जवाबों:
हालांकि एक सीधा समाधान नहीं है, और इसमें भी बुरा है कि यह केवल (जहां तक मैंने परीक्षण किया है) ऑनफोकस के साथ काम करता है (एक बहुत सीमित घटना अवरुद्ध की आवश्यकता होती है) आप इसे निम्न के साथ प्राप्त कर सकते हैं:
document.body.onfocus = function(){ /*rock it*/ }
इसके बारे में क्या अच्छा है, यह है कि आप इसे फ़ाइल ईवेंट के साथ समय पर संलग्न / अलग कर सकते हैं, और यह छिपे हुए इनपुट के साथ भी ठीक काम करने लगता है (यदि आप भद्दा डिफ़ॉल्ट इनपुट प्रकार = के लिए एक दृश्य वर्कअराउंड का उपयोग कर रहे हैं, तो यह निश्चित है) फ़ाइल ')। उसके बाद, आपको बस यह पता लगाने की ज़रूरत है कि इनपुट मूल्य बदल गया है या नहीं।
एक उदाहरण:
var godzilla = document.getElementById('godzilla')
godzilla.onclick = charge
function charge()
{
document.body.onfocus = roar
console.log('chargin')
}
function roar()
{
if(godzilla.value.length) alert('ROAR! FILES!')
else alert('*empty wheeze*')
document.body.onfocus = null
console.log('depleted')
}
इसे क्रिया में देखें: http://jsfiddle.net/Shiboe/yuK3r/6/
अफसोस की बात है, यह केवल वेबकिट ब्राउज़र पर काम करने के लिए लगता है। हो सकता है कि कोई दूसरा व्यक्ति फ़ायरफ़ॉक्स / IE समाधान का पता लगा सके
addEventListener("focus",fn,{once: true})
। हालाँकि, मैं इसका उपयोग करने के लिए आग में नहीं जा सका document.body.addEventListener
.. मुझे पता नहीं क्यों। इसके बजाय मुझे वही परिणाम मिला window.addEventListener
।
mousemove
पर घटना window.document
अलावा सुनने की focus
पर window
हर जगह (आधुनिक ब्राउज़रों में कम से कम, मैं पिछले दशक जहाजों के बारे में परवाह नहीं है) काम करने के लिए लगता है। मूल रूप से, इस कार्य के लिए किसी भी इंटरैक्शन इवेंट का उपयोग किया जा सकता है जो कि एक खुली फ़ाइल खुले संवाद द्वारा अवरुद्ध है।
आप नहीं कर सकते।
फ़ाइल संवाद का परिणाम ब्राउज़र के संपर्क में नहीं है।
change
घटना नहीं भेजी जाती है।
change
तो उसके लिए कोई भी घटना नहीं भेजी जाती है।
इसलिए मैं इस सवाल पर अपनी टोपी फेंक दूंगा क्योंकि मैं एक उपन्यास समाधान के साथ आया था। मेरे पास एक प्रगतिशील वेब ऐप है जो उपयोगकर्ताओं को फ़ोटो और वीडियो कैप्चर करने और उन्हें अपलोड करने की अनुमति देता है। जब संभव हो तो हम WebRTC का उपयोग करते हैं, लेकिन कम समर्थन * खांसी सफारी खांसी * वाले उपकरणों के लिए HTML5 फ़ाइल पिकर पर वापस आते हैं। यदि आप विशेष रूप से एक एंड्रॉइड / आईओएस मोबाइल वेब एप्लिकेशन पर काम कर रहे हैं, जो सीधे फोटो / वीडियो कैप्चर करने के लिए देशी कैमरे का उपयोग करता है, तो यह सबसे अच्छा समाधान है जो मैं भर में आया हूं।
इस समस्या की जड़ यह है कि जब पृष्ठ लोड होता file
है null
, तो होता है , लेकिन तब जब उपयोगकर्ता संवाद खोलता है और "रद्द" करता है, तब file
भी होता है null
, इसलिए यह "परिवर्तन" नहीं हुआ, इसलिए कोई "परिवर्तन" घटना ट्रिगर नहीं होती है। डेस्कटॉप के लिए, यह बहुत बुरा नहीं है क्योंकि अधिकांश डेस्कटॉप यूआई रद्द किए जाने पर जानने पर निर्भर नहीं होते हैं, लेकिन मोबाइल यूआई के जो एक तस्वीर / वीडियो को कैप्चर करने के लिए कैमरा लाते हैं, यह जानने पर बहुत निर्भर करते हैं कि कैंसल कब दबाया जाता है।
मैंने मूल रूप से document.body.onfocus
घटना का पता लगाने के लिए उपयोग किया जब उपयोगकर्ता फ़ाइल पिकर से लौटा, और इसने अधिकांश उपकरणों के लिए काम किया, लेकिन iOS 11.3 ने इसे तोड़ दिया क्योंकि यह घटना ट्रिगर नहीं है।
इसका समाधान सीपीयू टाइमिंग को मापने के लिए * कंपकंपी * है यह निर्धारित करने के लिए कि पृष्ठ वर्तमान में अग्रभूमि या पृष्ठभूमि में है। मोबाइल उपकरणों पर, अग्रभूमि में वर्तमान में एप्लिकेशन को प्रसंस्करण समय दिया जाता है। जब एक कैमरा दिखाई देता है तो यह सीपीयू समय चुराएगा और ब्राउज़र को चित्रित करेगा। हमें केवल यह मापने की आवश्यकता है कि हमारे पेज को कितना प्रसंस्करण समय दिया जाता है, जब कैमरा लॉन्च करता है तो हमारा उपलब्ध समय काफी कम हो जाएगा। जब कैमरा खारिज कर दिया जाता है (या तो रद्द कर दिया जाता है या अन्यथा), हमारा उपलब्ध समय स्पाइक बैक अप होता है।
हम setTimeout()
एक्स मिलीसेकंड में एक कॉलबैक आह्वान करके CPU समय को माप सकते हैं , और फिर माप सकते हैं कि वास्तव में इसे लागू करने में कितना समय लगा। ब्राउज़र यह आह्वान कभी नहीं होगा वास्तव में एक्स मिलीसेकेंड के बाद, लेकिन अगर यह उचित करीब है तो हम अग्रभूमि में होना चाहिए। यदि ब्राउज़र बहुत दूर है (अनुरोध के मुकाबले 10x से अधिक धीमा) तो हमें पृष्ठभूमि में होना चाहिए। इसका एक बुनियादी कार्यान्वयन ऐसा है:
function waitForCameraDismiss() {
const REQUESTED_DELAY_MS = 25;
const ALLOWED_MARGIN_OF_ERROR_MS = 25;
const MAX_REASONABLE_DELAY_MS =
REQUESTED_DELAY_MS + ALLOWED_MARGIN_OF_ERROR_MS;
const MAX_TRIALS_TO_RECORD = 10;
const triggerDelays = [];
let lastTriggerTime = Date.now();
return new Promise((resolve) => {
const evtTimer = () => {
// Add the time since the last run
const now = Date.now();
triggerDelays.push(now - lastTriggerTime);
lastTriggerTime = now;
// Wait until we have enough trials before interpreting them.
if (triggerDelays.length < MAX_TRIALS_TO_RECORD) {
window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
return;
}
// Only maintain the last few event delays as trials so as not
// to penalize a long time in the camera and to avoid exploding
// memory.
if (triggerDelays.length > MAX_TRIALS_TO_RECORD) {
triggerDelays.shift();
}
// Compute the average of all trials. If it is outside the
// acceptable margin of error, then the user must have the
// camera open. If it is within the margin of error, then the
// user must have dismissed the camera and returned to the page.
const averageDelay =
triggerDelays.reduce((l, r) => l + r) / triggerDelays.length
if (averageDelay < MAX_REASONABLE_DELAY_MS) {
// Beyond any reasonable doubt, the user has returned from the
// camera
resolve();
} else {
// Probably not returned from camera, run another trial.
window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
}
};
window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
});
}
मैंने आईओएस और एंड्रॉइड के हाल के संस्करण पर इसका परीक्षण किया, <input />
तत्व पर विशेषताओं को सेट करके देशी कैमरा को ऊपर लाया ।
<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />
यह वास्तव में मेरी उम्मीद से बेहतर काम करता है। 25 मिलीसेकंड में एक टाइमर लगाने का अनुरोध करके यह 10 परीक्षण करता है। यह तब मापता है कि वास्तव में इसे लागू करने में कितना समय लगा, और यदि 10 परीक्षणों का औसत 50 मिलीसेकंड से कम है, तो हम मानते हैं कि हमें अग्रभूमि में होना चाहिए और कैमरा चला गया है। यदि यह 50 मिलीसेकंड से अधिक है, तो हमें अभी भी पृष्ठभूमि में होना चाहिए और इंतजार करना जारी रखना चाहिए।
मैंने इसके setTimeout()
बजाय इसका उपयोग किया setInterval()
क्योंकि उत्तरार्द्ध कई आक्रमणों को पंक्तिबद्ध कर सकता है जो एक दूसरे के तुरंत बाद निष्पादित होते हैं। यह हमारे डेटा में शोर को काफी बढ़ा सकता है, इसलिए मैं setTimeout()
ऐसा करने के लिए थोड़ा और अधिक जटिल होने के बावजूद अटक गया ।
इन विशेष नंबरों ने मेरे लिए अच्छा काम किया, हालांकि मैंने कम से कम एक बार उदाहरण देखा है जहां समय से पहले कैमरे को खारिज कर दिया गया था। मेरा मानना है कि ऐसा इसलिए है क्योंकि कैमरा खोलने में धीमा हो सकता है, और डिवाइस वास्तव में पृष्ठभूमि बनने से पहले 10 परीक्षण चला सकता है। इस कार्य को शुरू करने से पहले अधिक से अधिक परीक्षणों को जोड़ना या कुछ 25-50 मिलीसेकंड की प्रतीक्षा करना इसके लिए एक समाधान हो सकता है।
दुर्भाग्य से, यह वास्तव में डेस्कटॉप ब्राउज़रों के लिए काम नहीं करता है। सिद्धांत रूप में एक ही चाल संभव है क्योंकि वे पृष्ठभूमि वाले पृष्ठों पर वर्तमान पृष्ठ को प्राथमिकता देते हैं। हालाँकि कई डेस्कटॉप के पास पर्याप्त संसाधन होते हैं जो पृष्ठ को पृष्ठभूमि में रखते हुए भी पूरी गति से चलते रहते हैं, इसलिए यह रणनीति वास्तव में काम नहीं करती है।
एक वैकल्पिक समाधान में कई लोगों का उल्लेख नहीं है कि मैंने जो खोज की थी वह मजाक उड़ा रहा था FileList
। हम इसके साथ शुरू null
करते हैं <input />
और फिर यदि उपयोगकर्ता कैमरा और रद्द करता है तो वे वापस आ जाते हैं null
, जो कि परिवर्तन नहीं है और कोई भी घटना ट्रिगर नहीं होगी। एक समाधान <input />
पृष्ठ प्रारंभ में एक डमी फ़ाइल को असाइन करना होगा , इसलिए सेटिंग में null
एक परिवर्तन होगा जो उचित घटना को ट्रिगर करेगा।
दुर्भाग्य से, कोई रास्ता नहीं है आधिकारिक तौर पर एक बनाने के लिए FileList
, और <input />
तत्व को FileList
विशेष रूप से आवश्यकता होती है और इसके अलावा किसी भी अन्य मूल्य को स्वीकार नहीं करेगा null
। स्वाभाविक रूप से, FileList
वस्तुओं का निर्माण सीधे नहीं किया जा सकता है, कुछ पुराने सुरक्षा मुद्दे पर करें जो अब तक स्पष्ट रूप से प्रासंगिक नहीं हैं। एक <input />
तत्व के बाहर एक का एक हिस्सा पाने का एकमात्र तरीका एक हैक का उपयोग करना है जो एक क्लिपबोर्ड घटना को कॉपी करने के लिए डेटा को कॉपी-पेस्ट करता है जिसमें FileList
ऑब्जेक्ट हो सकता है (आप मूल रूप से ड्रैग-एंड-ड्रॉप-ए-फाइल-ऑन को फेक कर रहे हैं -आपकी वेबसाइट घटना)। फ़ायरफ़ॉक्स में यह संभव है, लेकिन आईओएस सफारी के लिए नहीं, इसलिए यह मेरे विशेष उपयोग के मामले में व्यवहार्य नहीं था।
यह कहने की आवश्यकता नहीं है कि यह हास्यास्पद है। तथ्य यह है कि वेब पृष्ठों को शून्य सूचना दी जाती है कि एक महत्वपूर्ण यूआई तत्व बदल गया है, बस हँसने योग्य है। यह वास्तव में कल्पना में एक बग है, क्योंकि यह कभी भी पूर्ण-स्क्रीन मीडिया कैप्चर यूआई के लिए नहीं था, और "परिवर्तन" घटना को ट्रिगर करने के लिए तकनीकी रूप से कल्पना नहीं है।
हालांकि , क्या ब्राउज़र विक्रेता कृपया इसकी वास्तविकता को पहचान सकते हैं? इसे किसी नए "किए गए" ईवेंट के साथ हल किया जा सकता है जो तब भी ट्रिगर होता है जब कोई परिवर्तन नहीं होता है, या आप "परिवर्तन" को किसी भी तरह से ट्रिगर कर सकते हैं। हाँ, यह कल्पना के खिलाफ होगा, लेकिन मेरे लिए जावास्क्रिप्ट की ओर एक परिवर्तन घटना को कम करने के लिए यह तुच्छ है, फिर भी मौलिक रूप से अपने स्वयं के "किए गए" घटना का आविष्कार करना असंभव है। यहां तक कि मेरा समाधान वास्तव में सिर्फ आंकड़े हैं, अगर ब्राउज़र की स्थिति पर कोई गारंटी नहीं देता है।
जैसा कि यह खड़ा है, यह एपीआई मोबाइल उपकरणों के लिए मौलिक रूप से अनुपयोगी है, और मुझे लगता है कि अपेक्षाकृत सरल ब्राउज़र परिवर्तन वेब डेवलपर्स के लिए असीम रूप से आसान बना सकता है * साबुन बॉक्स * से कदम।
जब आप किसी फ़ाइल का चयन करते हैं और खुले / रद्द करते हैं, तो input
तत्व को फोकस उर्फ खोना चाहिए blur
। प्रारंभिक value
के मान लेने input
से खाली है, आपके blur
हैंडलर में कोई भी खाली मूल्य ठीक है, और रिक्त मान का अर्थ रद्द करना होगा।
अद्यतन: blur
जब input
छिपा हुआ है ट्रिगर नहीं है। इसलिए IFRAME- आधारित अपलोड के साथ इस ट्रिक का उपयोग नहीं कर सकते, जब तक कि आप अस्थायी रूप से प्रदर्शित नहीं करना चाहते input
।
blur
जब आप किसी फ़ाइल का चयन करते हैं तो ट्रिगर नहीं होता है। अन्य ब्राउज़र में आज़माया नहीं गया है।
/* Tested on Google Chrome */
$("input[type=file]").bind("change", function() {
var selected_file_name = $(this).val();
if ( selected_file_name.length > 0 ) {
/* Some file selected */
}
else {
/* No file selected or cancel/close
dialog button clicked */
/* If user has select a file before,
when they submit, it will treated as
no file selected */
}
});
else
कभी अपने कथन का मूल्यांकन किया है तो क्या आपने जाँच की है ?
इनमें से अधिकांश समाधान मेरे लिए काम नहीं करते हैं।
समस्या यह है कि आपको कभी नहीं पता होगा कि कौन सी घटना मुट्ठी में होगी, यह है click
या यह है change
? आप किसी भी आदेश को नहीं मान सकते, क्योंकि यह संभवतः ब्राउज़र के कार्यान्वयन पर निर्भर करता है।
कम से कम ओपेरा और क्रोम (2015 के अंत में) click
फाइलों के साथ 'भरने' के इनपुट से ठीक पहले चालू हो जाता है, इसलिए आपको कभी भी इसकी लंबाई का पता नहीं चलेगा कि files.length != 0
आप इसके click
बाद ट्रिगर होने में देरी करते हैं change
।
यहाँ कोड है:
var inputfile = $("#yourid");
inputfile.on("change click", function(ev){
if (ev.originalEvent != null){
console.log("OK clicked");
}
document.body.onfocus = function(){
document.body.onfocus = null;
setTimeout(function(){
if (inputfile.val().length === 0) console.log("Cancel clicked");
}, 1000);
};
});
बस क्लिक इवेंट को भी सुनें।
शिबो के उदाहरण से, यहाँ एक jQuery का उदाहरण दिया गया है:
var godzilla = $('#godzilla');
var godzillaBtn = $('#godzilla-btn');
godzillaBtn.on('click', function(){
godzilla.trigger('click');
});
godzilla.on('change click', function(){
if (godzilla.val() != '') {
$('#state').html('You have chosen a Mech!');
} else {
$('#state').html('Choose your Mech!');
}
});
आप इसे यहां एक्शन में देख सकते हैं: http://jsfiddle.net/T3Vwz
यदि आप पहले जैसी फ़ाइल चुनते हैं और आप रद्द करते हैं: तो आप इस मामले में रद्द कर सकते हैं।
आप इसे इस तरह से कर सकते हैं:
<input type="file" id="myinputfile"/>
<script>
document.getElementById('myinputfile').addEventListener('change', myMethod, false);
function myMethod(evt) {
var files = evt.target.files;
f= files[0];
if (f==undefined) {
// the user has clicked on cancel
}
else if (f.name.match(".*\.jpg")|| f.name.match(".*\.png")) {
//.... the user has choosen an image file
var reader = new FileReader();
reader.onload = function(evt) {
try {
myimage.src=evt.target.result;
...
} catch (err) {
...
}
};
}
reader.readAsDataURL(f);
</script>
सबसे आसान तरीका यह है कि अस्थायी मेमोरी में कोई फाइल है या नहीं इसकी जांच करें। यदि आप हर बार उपयोगकर्ता को उस परिवर्तन ईवेंट को प्राप्त करना चाहते हैं जो फ़ाइल इनपुट पर क्लिक करता है तो आप उसे ट्रिगर कर सकते हैं।
var yourFileInput = $("#yourFileInput");
yourFileInput.on('mouseup', function() {
$(this).trigger("change");
}).on('change', function() {
if (this.files.length) {
//User chose a picture
} else {
//User clicked cancel
}
});
अगर यह मोबाइल वेबकिट पर काम करता है, तो शिबो का समाधान एक अच्छा होगा, लेकिन यह नहीं है। मैं उस समय किसी डोम ऑब्जेक्ट में एक मूसमोव ईवेंट श्रोता को जोड़ने के लिए आ सकता हूं जो फ़ाइल इनपुट विंडो खोली जाती है, जैसे:
$('.upload-progress').mousemove(function() {
checkForFiles(this);
});
checkForFiles = function(me) {
var filefield = $('#myfileinput');
var files = filefield.get(0).files;
if (files == undefined || files[0] == undefined) $(me).remove(); // user cancelled the upload
};
फ़ाइल डायलॉग खुला रहने पर मूसमव ईवेंट को पृष्ठ से ब्लॉक कर दिया जाता है, और जब उसका बंद होना यह देखना होता है कि फ़ाइल इनपुट में कोई फाइल है या नहीं। मेरे मामले में मैं फ़ाइल को अपलोड किए जाने तक चीजों को अवरुद्ध करने वाला एक गतिविधि संकेतक चाहता हूं, इसलिए मैं केवल रद्द करने पर अपना संकेतक निकालना चाहता हूं।
हालाँकि, यह मोबाइल के लिए हल नहीं करता है, क्योंकि मूव करने के लिए कोई माउस नहीं है। मेरा समाधान सही से कम है, लेकिन मुझे लगता है कि यह काफी अच्छा है।
$('.upload-progress').bind('touchstart', function() {
checkForFiles(this);
});
अब हम स्क्रीन पर एक स्पर्श के लिए सुन रहे हैं कि वही फाइलें चेक करें। मुझे पूरा विश्वास है कि इस गतिविधि संकेतक को रद्द करने और खारिज करने के बाद उपयोगकर्ता की उंगली बहुत जल्दी स्क्रीन पर डाल दी जाएगी।
कोई व्यक्ति फ़ाइल इनपुट परिवर्तन घटना पर केवल गतिविधि संकेतक जोड़ सकता है, लेकिन मोबाइल पर अक्सर छवि और परिवर्तन घटना फायरिंग का चयन करने के बीच कुछ सेकंड का अंतराल होता है, इसलिए गतिविधि सूचक को प्रदर्शित करने के लिए इसका सिर्फ बेहतर UX है प्रक्रिया की शुरुआत।
मुझे यह सबसे अच्छा लगता है।
if ($('#selectedFile')[0].files.length > 1)
{
// Clicked on 'open' with file
} else {
// Clicked on 'cancel'
}
यहाँ, selectedFile
एक है input type=file
।
मुझे पता है कि यह एक बहुत पुराना सवाल है, लेकिन अगर किसी को रद्द करने का पता लगाने के लिए onmousemove घटना का उपयोग करते समय मैंने पाया है कि बस समय की थोड़ी सी जगह में दो या अधिक ऐसी घटनाओं के लिए परीक्षण करना आवश्यक था। ऐसा इसलिए था क्योंकि हर बार ब्राउज़र (क्रोम 65) द्वारा सिंगल ऑनसमूव इवेंट्स उत्पन्न किए जाते हैं, हर बार कर्सर को चुनिंदा फ़ाइल डायलॉग विंडो से बाहर ले जाया जाता है और हर बार इसे मुख्य विंडो से बाहर ले जाया जाता है और माउस मूवमेंट इवेंट का एक सरल काउंटर होता है। काउंटर को शून्य पर वापस सेट करने के लिए एक छोटी अवधि के समय के साथ युग्मित किया गया एक उपचार का काम करता है।
मेरे मामले में मुझे सबमिट बटन को छिपाना पड़ा जबकि उपयोगकर्ता छवियों का चयन कर रहे थे।
यह मैं आ रहा हूँ:
$(document).on('click', '#image-field', function(e) {
$('.submit-button').prop('disabled', true)
})
$(document).on('focus', '#image-field'), function(e) {
$('.submit-button').prop('disabled', false)
})
#image-field
मेरी फ़ाइल चयनकर्ता है जब somenone उस पर क्लिक करता है, तो मैं फ़ॉर्म सबमिट बटन अक्षम करता हूं। बिंदु यह है, जब फ़ाइल संवाद बंद हो जाता है - कोई फर्क नहीं पड़ता कि वे एक फ़ाइल का चयन करते हैं या रद्द करते हैं - #image-field
फोकस वापस मिल गया, इसलिए मैं उस घटना को सुनता हूं।
अपडेट करें
मैंने पाया कि, यह सफारी और पॉलीटेजिस्ट / फैंटमज में काम नहीं करता है। यदि आप इसे लागू करना चाहते हैं तो इस जानकारी को ध्यान में रखें।
शिबो और एल्क्स के समाधानों को मिलाकर, मुझे सबसे विश्वसनीय कोड मिला है:
var selector = $('<input/>')
.attr({ /* just for example, use your own attributes */
"id": "FilesSelector",
"name": "File",
"type": "file",
"contentEditable": "false" /* if you "click" on input via label, this prevents IE7-8 from just setting caret into file input's text filed*/
})
.on("click.filesSelector", function () {
/* do some magic here, e.g. invoke callback for selection begin */
var cancelled = false; /* need this because .one calls handler once for each event type */
setTimeout(function () {
$(document).one("mousemove.filesSelector focusin.filesSelector", function () {
/* namespace is optional */
if (selector.val().length === 0 && !cancelled) {
cancelled = true; /* prevent double cancel */
/* that's the point of cancel, */
}
});
}, 1); /* 1 is enough as we just need to delay until first available tick */
})
.on("change.filesSelector", function () {
/* do some magic here, e.g. invoke callback for successful selection */
})
.appendTo(yourHolder).end(); /* just for example */
आम तौर पर, मूसमोव ईवेंट चाल करता है, लेकिन मामले में उपयोगकर्ता ने एक क्लिक और किया:
... हमें मूसमव इवेंट नहीं मिलेगा इसलिए कोई कॉलबैक रद्द नहीं होगा। इसके अलावा, यदि उपयोगकर्ता दूसरा डायलॉग रद्द करता है और माउस ले जाता है, तो हमें 2 रद्द कॉलबैक मिलेंगे। सौभाग्य से, विशेष jQuery का ध्यान केंद्रित। घटना दोनों स्थितियों में दस्तावेज़ में बुलबुले बनती है, जिससे हमें ऐसी स्थितियों से बचने में मदद मिलती है। केवल एक ही सीमा है अगर एक भी ध्यान केंद्रित करता है।
mousemove
घटना को पकड़ा document
। कोई समस्या नहीं है, जब माउस नहीं बढ़ रहा है, या फ़ाइल का चयन करने के लिए सिर्फ कीबोर्ड का उपयोग कर रहा है। मैं बदलने के लिए था mousemove
द्वारा keydown
यथाशीघ्र रद्द पता लगाने के लिए, लेकिन "बहुत जल्दी", जब संवाद अभी भी खुला था।
मैं देखता हूं कि मेरी प्रतिक्रिया काफी पुरानी होगी, लेकिन कभी कम नहीं हुई। मैंने उसी समस्या का सामना किया। तो यहाँ मेरा समाधान है। सबसे उपयोगी कोड छीन लिया गया था केजीए का। लेकिन यह पूरी तरह से काम नहीं कर रहा है और थोड़ा जटिल है। लेकिन मैंने इसे सरल बनाया।
इसके अलावा, मुख्य परेशानी निर्माता तथ्य यह था, कि 'परिवर्तन' घटना फ़ोकस के तुरंत बाद नहीं आती है, इसलिए हमें कुछ समय तक इंतजार करना होगा।
"#appendfile" - जो उपयोगकर्ता एक नई फ़ाइल को जोड़ने के लिए क्लिक करता है। Hrefs को फोकस इवेंट मिलते हैं।
$("#appendfile").one("focusin", function () {
// no matter - user uploaded file or canceled,
// appendfile gets focus
// change doesn't come instantly after focus, so we have to wait for some time
// wrapper represents an element where a new file input is placed into
setTimeout(function(){
if (wrapper.find("input.fileinput").val() != "") {
// user has uploaded some file
// add your logic for new file here
}
else {
// user canceled file upload
// you have to remove a fileinput element from DOM
}
}, 900);
});
इसका पता आप सीमित परिस्थितियों में ही लगा सकते हैं। विशेष रूप से, क्रोम में यदि किसी फ़ाइल को पहले चुना गया था और फिर फ़ाइल संवाद पर क्लिक किया गया और रद्द किया गया क्लिक किया गया है, तो क्रोम फ़ाइल को साफ़ करता है और ऑनकॉन्ग इवेंट को फायर करता है।
https://code.google.com/p/chromium/issues/detail?id=2508
इस परिदृश्य में, आप onChange ईवेंट को हैंडल करके और फ़ाइलों की संपत्ति की जाँच करके इसका पता लगा सकते हैं।
निम्नलिखित मेरे लिए काम करने लगता है (डेस्कटॉप, विंडोज़ पर):
var openFile = function (mimeType, fileExtension) {
var defer = $q.defer();
var uploadInput = document.createElement("input");
uploadInput.type = 'file';
uploadInput.accept = '.' + fileExtension + ',' + mimeType;
var hasActivated = false;
var hasChangedBeenCalled = false;
var hasFocusBeenCalled = false;
var focusCallback = function () {
if (hasActivated) {
hasFocusBeenCalled = true;
document.removeEventListener('focus', focusCallback, true);
setTimeout(function () {
if (!hasChangedBeenCalled) {
uploadInput.removeEventListener('change', changedCallback, true);
defer.resolve(null);
}
}, 300);
}
};
var changedCallback = function () {
uploadInput.removeEventListener('change', changedCallback, true);
if (!hasFocusBeenCalled) {
document.removeEventListener('focus', focusCallback, true);
}
hasChangedBeenCalled = true;
if (uploadInput.files.length === 1) {
//File picked
var reader = new FileReader();
reader.onload = function (e) {
defer.resolve(e.target.result);
};
reader.readAsText(uploadInput.files[0]);
}
else {
defer.resolve(null);
}
};
document.addEventListener('focus', focusCallback, true); //Detect cancel
uploadInput.addEventListener('change', changedCallback, true); //Detect when a file is picked
uploadInput.click();
hasActivated = true;
return defer.promise;
}
यह angularjs $ q का उपयोग करता है, लेकिन आपको जरूरत पड़ने पर इसे किसी अन्य वादे के ढांचे के साथ बदलने में सक्षम होना चाहिए।
IE11, एज, क्रोम, फायरफॉक्स पर परीक्षण किया गया है, लेकिन यह एंड्रॉइड टैबलेट पर क्रोम पर काम नहीं करता है क्योंकि यह फोकस इवेंट को फायर नहीं करता है।
file
प्रकार क्षेत्र, frustratingly, (कलंक सुंदर होगा) की घटनाओं का एक बहुत का जवाब नहीं है। मैं बहुत से लोगों को सलाह देता हूं कि वे change
समाधानों का सुझाव दे रहे हैं और उन्हें कम किया जा रहा है।
change
काम करता है, लेकिन इसका एक बड़ा दोष है (बनाम हम जो होना चाहते हैं)।
जब आप किसी फ़ाइल फ़ील्ड में नए सिरे से लोड करते हैं, तो बॉक्स खोलें और रद्द करें दबाएं। कुछ भी नहीं, निराशा से, बदलता है ।
मैंने जो करने के लिए चुना है वह एक gated-state में लोड है।
section#after-image
मेरे मामले में प्रपत्र का अगला भाग दृश्य से छिपा हुआ है। जब मेरा file field
परिवर्तन होता है, तो एक अपलोड बटन दिखाया जाता है। सफल अपलोड पर, section#after-image
दिखाया गया है।change
इस रद्द करने से ईवेंट चालू हो जाता है, और वहां मैं अपने अपलोड बटन को फिर से छिपा सकता हूं जब तक कि एक उचित फ़ाइल का चयन नहीं किया जाता है।मैं भाग्यशाली था कि यह गेट-स्टेट पहले से ही मेरे फॉर्म का डिज़ाइन था। आपको एक ही शैली का उपयोग करने की आवश्यकता नहीं है, केवल अपलोड बटन शुरू में छिपा हुआ है और बदलने पर, एक छिपे हुए क्षेत्र या जावास्क्रिप्ट चर को कुछ पर सेट करना है जिसे आप सबमिट कर सकते हैं।
मैंने फ़ील्ड के साथ बातचीत करने से पहले फ़ाइलों का मान बदलने की कोशिश की [0]। इसने onchange के बारे में कुछ नहीं किया।
हां, change
काम करता है, कम से कम जितना हम प्राप्त करने जा रहे हैं उतना अच्छा है। फ़ाइलफ़ील्ड स्पष्ट कारणों से सुरक्षित है, लेकिन अच्छी तरह से इरादे वाले डेवलपर्स की निराशा के लिए।
यह मेरे उद्देश्य के लिए उपयुक्त नहीं है, लेकिन आप onclick
चेतावनी प्रॉम्प्ट को लोड करने में सक्षम हो सकते हैं (नहीं alert()
, क्योंकि पृष्ठ-प्रसंस्करण को रोकता है), और इसे छिपाएं यदि परिवर्तन ट्रिगर हो गया है और फाइलें [0] शून्य है। यदि परिवर्तन को ट्रिगर नहीं किया जाता है, तो div अपने राज्य में रहता है।
ऐसा करने के लिए एक हैक तरीका है ( alert()
कॉल के बजाय कॉलबैक जोड़ें या कुछ स्थगित / वादा कार्यान्वयन का समाधान करें ):
var result = null;
$('<input type="file" />')
.on('change', function () {
result = this.files[0];
alert('selected!');
})
.click();
setTimeout(function () {
$(document).one('mousemove', function () {
if (!result) {
alert('cancelled');
}
});
}, 1000);
यह कैसे काम करता है: फ़ाइल चयन संवाद खुला है, दस्तावेज़ माउस सूचक घटनाओं को प्राप्त नहीं करता है। डायलॉग को वास्तव में प्रकट करने और ब्राउज़र विंडो को ब्लॉक करने की अनुमति देने के लिए 1000ms देरी है। क्रोम और फ़ायरफ़ॉक्स (केवल विंडोज) में चेक किया गया।
लेकिन यह निश्चित रूप से रद्द किए गए संवाद का पता लगाने का एक विश्वसनीय तरीका नहीं है। हालाँकि, आपके लिए कुछ UI व्यवहार में सुधार हो सकता है।
यहाँ मेरा समाधान है, फ़ाइल इनपुट फ़ोकस का उपयोग करके (किसी टाइमर का उपयोग नहीं)
var fileInputSelectionInitiated = false;
function fileInputAnimationStart() {
fileInputSelectionInitiated = true;
if (!$("#image-selector-area-icon").hasClass("fa-spin"))
$("#image-selector-area-icon").addClass("fa-spin");
if (!$("#image-selector-button-icon").hasClass("fa-spin"))
$("#image-selector-button-icon").addClass("fa-spin");
}
function fileInputAnimationStop() {
fileInputSelectionInitiated = false;
if ($("#image-selector-area-icon").hasClass("fa-spin"))
$("#image-selector-area-icon").removeClass("fa-spin");
if ($("#image-selector-button-icon").hasClass("fa-spin"))
$("#image-selector-button-icon").removeClass("fa-spin");
}
$("#image-selector-area-wrapper").click(function (e) {
$("#fileinput").focus();
$("#fileinput").click();
});
$("#preview-image-wrapper").click(function (e) {
$("#fileinput").focus();
$("#fileinput").click();
});
$("#fileinput").click(function (e) {
fileInputAnimationStart();
});
$("#fileinput").focus(function (e) {
fileInputAnimationStop();
});
$("#fileinput").change(function(e) {
// ...
}
Error: { "message": "Uncaught SyntaxError: missing ) after argument list", "filename": "https://stacksnippets.net/js", "lineno": 51, "colno": 1 }
यह सबसे अच्छी तरह से हैक किया गया है, लेकिन यहां एक उपयोगकर्ता ने किसी फ़ाइल को अपलोड किया है या नहीं, यह पता लगाने के लिए मेरे समाधान का एक कार्यशील उदाहरण है, और केवल यह सुनिश्चित करने की अनुमति देता है कि क्या उन्होंने कोई फ़ाइल अपलोड की है।
मूल रूप से छिपाने Continue
, Save
, Proceed
या जो कुछ भी अपने बटन है। फिर जावास्क्रिप्ट में आप फ़ाइल का नाम लेते हैं। यदि फ़ाइल नाम का कोई मान नहीं है, तो Continue
बटन न दिखाएं । यदि इसका कोई मान है, तो बटन दिखाएं। यह तब भी काम करता है जब वे पहले एक फ़ाइल अपलोड करते हैं और फिर वे एक अलग फ़ाइल अपलोड करने का प्रयास करते हैं और रद्द करते हैं।
यहाँ कोड है।
HTML:
<div class="container">
<div class="row">
<input class="file-input" type="file" accept="image/*" name="fileUpload" id="fileUpload" capture="camera">
<label for="fileUpload" id="file-upload-btn">Capture or Upload Photo</label>
</div>
<div class="row padding-top-two-em">
<input class="btn btn-success hidden" id="accept-btn" type="submit" value="Accept & Continue"/>
<button class="btn btn-danger">Back</button>
</div></div>
जावास्क्रिप्ट:
$('#fileUpload').change(function () {
var fileName = $('#fileUpload').val();
if (fileName != "") {
$('#file-upload-btn').html(fileName);
$('#accept-btn').removeClass('hidden').addClass('show');
} else {
$('#file-upload-btn').html("Upload File");
$('#accept-btn').addClass('hidden');
}
});
सीएसएस:
.file-input {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.file-input + label {
font-size: 1.25em;
font-weight: normal;
color: white;
background-color: blue;
display: inline-block;
padding: 5px;
}
.file-input:focus + label,
.file-input + label:hover {
background-color: red;
}
.file-input + label {
cursor: pointer;
}
.file-input + label * {
pointer-events: none;
}
CSS के लिए इसमें से बहुत कुछ वेबसाइट और बटन को सभी के लिए सुलभ बनाना है। अपने बटन को स्टाइल करें जो भी आपको पसंद है।
खैर, यह आपके सवाल का सही जवाब नहीं देता है। मेरी धारणा यह है कि, आपके पास एक परिदृश्य है, जब आप एक फ़ाइल इनपुट जोड़ते हैं, और फ़ाइल चयन को लागू करते हैं, और यदि उपयोगकर्ता हिट रद्द करता है, तो आप बस इनपुट हटा देते हैं।
यदि यह मामला है, तो: खाली फ़ाइल इनपुट क्यों जोड़ा जा रहा है?
मक्खी पर एक बनाएँ, लेकिन इसे डोम में तभी भरें जब वह अंदर भर जाए।
var fileInput = $("<input type='file' name='files' style='display: none' />");
fileInput.bind("change", function() {
if (fileInput.val() !== null) {
// if has value add it to DOM
$("#files").append(fileInput);
}
}).click();
इसलिए यहाँ मैं मक्खी पर <input type = "file" /> बनाता हूँ, इसे बदलने की घटना से बाँधता हूँ और फिर तुरंत क्लिक पर आह्वान करता हूँ। परिवर्तन पर केवल तभी फायर होगा जब उपयोगकर्ता किसी फ़ाइल का चयन करता है और ओके को हिट करता है, अन्यथा DOM में इनपुट नहीं जोड़ा जाएगा, इसलिए सबमिट नहीं किया जाएगा।
यहाँ काम करने का उदाहरण: https://jsfiddle.net/69g0Lxno/3/
यदि आपको पहले से ही JQuery की आवश्यकता है, तो यह समाधान काम कर सकता है (यह वास्तव में मेरे मामले में आवश्यक वही कोड है, हालांकि एक वादा का उपयोग करना कोड को केवल तब तक इंतजार करने के लिए मजबूर करना है जब तक फ़ाइल चयन हल नहीं हो जाता है):
await new Promise(resolve => {
const input = $("<input type='file'/>");
input.on('change', function() {
resolve($(this).val());
});
$('body').one('focus', '*', e => {
resolve(null);
e.stopPropagation();
});
input.click();
});
इस थ्रेड में कई प्रस्तावित समाधान हैं और जब उपयोगकर्ता चयन फ़ाइल पर "रद्द करें" बटन पर क्लिक करता है, तो यह पता लगाने में कठिनाई होती है कि कई लोगों को प्रभावित करता है।
तथ्य यह है कि उपयोगकर्ता ने फ़ाइल चयन बॉक्स पर "रद्द करें" बटन पर क्लिक किया है या नहीं, इसका पता लगाने का कोई 100% विश्वसनीय तरीका नहीं है । लेकिन मज़बूती से यह पता लगाने के तरीके हैं कि क्या उपयोगकर्ता ने फ़ाइल को इनपुट फ़ाइल में जोड़ा है । तो यह इस उत्तर की मूल रणनीति है!
मैंने इस उत्तर को जोड़ने का फैसला किया क्योंकि स्पष्ट रूप से अन्य उत्तर अधिकांश ब्राउज़रों पर काम नहीं करते हैं या मोबाइल उपकरणों पर गारंटी नहीं देते हैं।
संक्षेप में कोड 3 बिंदुओं पर आधारित है:
बेहतर समझ के लिए नीचे दिए गए कोड और नोट्स को भी देखें।
[...]
<button type="button" onclick="addIptFl();">ADD INPUT FILE!</button>
<span id="ipt_fl_parent"></span>
[...]
function dynIptFl(jqElInst, funcsObj) {
if (typeof funcsObj === "undefined" || funcsObj === "") {
funcsObj = {};
}
if (funcsObj.hasOwnProperty("before")) {
if (!funcsObj["before"].hasOwnProperty("args")) {
funcsObj["before"]["args"] = [];
}
funcsObj["before"]["func"].apply(this, funcsObj["before"]["args"]);
}
var jqElInstFl = jqElInst.find("input[type=file]");
// NOTE: Open the file selection box via js. By Questor
jqElInstFl.trigger("click");
// NOTE: This event is triggered if the user selects a file. By Questor
jqElInstFl.on("change", {funcsObj: funcsObj}, function(e) {
// NOTE: With the strategy below we avoid problems with other unwanted events
// that may be associated with the DOM element. By Questor
e.preventDefault();
var funcsObj = e.data.funcsObj;
if (funcsObj.hasOwnProperty("after")) {
if (!funcsObj["after"].hasOwnProperty("args")) {
funcsObj["after"]["args"] = [];
}
funcsObj["after"]["func"].apply(this, funcsObj["after"]["args"]);
}
});
}
function remIptFl() {
// NOTE: Remove the input file. By Questor
$("#ipt_fl_parent").empty();
}
function addIptFl() {
function addBefore(someArgs0, someArgs1) {
// NOTE: All the logic here happens just before the file selection box opens.
// By Questor
// SOME CODE HERE!
}
function addAfter(someArgs0, someArgs1) {
// NOTE: All the logic here happens only if the user adds a file. By Questor
// SOME CODE HERE!
$("#ipt_fl_parent").prepend(jqElInst);
}
// NOTE: The input file is hidden as all manipulation must be done via js.
// By Questor
var jqElInst = $('\
<span>\
<button type="button" onclick="remIptFl();">REMOVE INPUT FILE!</button>\
<input type="file" name="input_fl_nm" style="display: block;">\
</span>\
');
var funcsObj = {
before: {
func: addBefore,
args: [someArgs0, someArgs1]
},
after: {
func: addAfter,
// NOTE: The instance with the input file ("jqElInst") could be passed
// here instead of using the context of the "addIptFl()" function. That
// way "addBefore()" and "addAfter()" will not need to be inside "addIptFl()",
// for example. By Questor
args: [someArgs0, someArgs1]
}
};
dynIptFl(jqElInst, funcsObj);
}
धन्यवाद! = D
हमने नीचे की तरह कोणीय में हासिल किया।
<input type="file" formControlName="FileUpload" click)="handleFileInput($event.target.files)" />
/>
this.uploadPanel = false;
handleFileInput(files: FileList) {
this.fileToUpload = files.item(0);
console.log("ggg" + files);
this.uploadPanel = true;
}
@HostListener("window:focus", ["$event"])
onFocus(event: FocusEvent): void {
if (this.uploadPanel == true) {
console.log("cancel clicked")
this.addSlot
.get("FileUpload")
.setValidators([
Validators.required,
FileValidator.validate,
requiredFileType("png")
]);
this.addSlot.get("FileUpload").updateValueAndValidity();
}
}
बस अपने इनपुट पर 'परिवर्तन' श्रोता जोड़ें जिसका प्रकार फ़ाइल है। अर्थात
<input type="file" id="file_to_upload" name="file_to_upload" />
मैंने jQuery का उपयोग किया है और जाहिर है कि कोई भी वैलीना जेएस (आवश्यकता के अनुसार) का उपयोग कर सकता है।
$("#file_to_upload").change(function() {
if (this.files.length) {
alert('file choosen');
} else {
alert('file NOT choosen');
}
});
.change()
अगर उपयोगकर्ता फाइल पिकर पर "रद्द" पर क्लिक करता है तो मज़बूती से नहीं कहा जाता है।
enter code here
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<h1>Hello</h1>
<div id="cancel01">
<button>Cancel</button>
</div>
<div id="cancel02">
<button>Cancel</button>
</div>
<div id="cancel03">
<button>Cancel</button>
</div>
<form>
<input type="file" name="name" placeholder="Name" />
</form>
<script>
const nameInput = document.querySelector('input[type="file"]');
/******
*The below code if for How to detect when cancel is clicked on file input
******/
nameInput.addEventListener('keydown', e => {
/******
*If the cancel button is clicked,then you should change the input file value to empty
******/
if (e.key == 'Backspace' || e.code == 'Backspace' || e.keyCode == 8) {
console.log(e);
/******
*The below code will delete the file path
******/
nameInput.value = '';
}
});
</script>
</body>
</html>
नोट: यह कोड रद्दीकरण का पता नहीं लगाता है, यह एक सामान्य मामले में इसका पता लगाने की आवश्यकता को दरकिनार करने का एक तरीका प्रदान करता है जिसमें लोग इसका पता लगाने की कोशिश करते हैं।
मैं एक छिपे हुए इनपुट का उपयोग करके फ़ाइल अपलोड के लिए एक समाधान की तलाश में यहां आया था, मेरा मानना है कि फ़ाइल इनपुट रद्द करने का पता लगाने का एक सबसे आम कारण है (खुले फ़ाइल संवाद -> यदि कोई फ़ाइल चयनित थी, तो कुछ चलाएं कोड, नहीं तो कुछ नहीं), यहाँ मेरा समाधान है:
var fileSelectorResolve;
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.addEventListener('input', function(){
fileSelectorResolve(this.files[0]);
fileSelectorResolve = null;
fileSelector.value = '';
});
function selectFile(){
if(fileSelectorResolve){
fileSelectorResolve();
fileSelectorResolve = null;
}
return new Promise(function(resolve){
fileSelectorResolve = resolve;
fileSelector.dispatchEvent(new MouseEvent('click'));
});
}
ध्यान दें कि यदि कोई फ़ाइल नहीं चुनी गई थी, तो पहली पंक्ति केवल एक बार वापस आ जाएगी selectFile()
(या यदि आप fileSelectorResolve()
कहीं और से कॉल की जाती हैं)।
async function logFileName(){
const file = await selectFile();
if(!file) return;
console.log(file.name);
}
एक और उदाहरण:
async function uploadFile(){
const file = await selectFile();
if(!file) return;
// ... make an ajax call here to upload the file ...
}
आप इनपुट फ़ील्ड पर एक jquery परिवर्तन श्रोता बना सकते हैं और पता लगा सकते हैं कि उपयोगकर्ता फ़ील्ड के मान से रद्द या बंद अपलोड विंडो है।
यहाँ एक उदाहरण है:
//when upload button change
$('#upload_btn').change(function(){
//get uploaded file
var file = this.files[0];
//if user choosed a file
if(file){
//upload file or perform your desired functiuonality
}else{
//user click cancel or close the upload window
}
});
e.target.files