ฉันจะตรวจจับได้อย่างไรเมื่อผู้ใช้ยกเลิกอินพุตไฟล์โดยใช้อินพุตไฟล์ html
onChange ช่วยให้ฉันตรวจพบเมื่อพวกเขาเลือกไฟล์ แต่ฉันก็อยากทราบด้วยว่าพวกเขายกเลิกเมื่อใด (ปิดกล่องโต้ตอบเลือกไฟล์โดยไม่ต้องเลือกอะไรเลย)
ฉันจะตรวจจับได้อย่างไรเมื่อผู้ใช้ยกเลิกอินพุตไฟล์โดยใช้อินพุตไฟล์ html
onChange ช่วยให้ฉันตรวจพบเมื่อพวกเขาเลือกไฟล์ แต่ฉันก็อยากทราบด้วยว่าพวกเขายกเลิกเมื่อใด (ปิดกล่องโต้ตอบเลือกไฟล์โดยไม่ต้องเลือกอะไรเลย)
คำตอบ:
แม้ว่าจะไม่ใช่วิธีแก้ปัญหาโดยตรง แต่ก็แย่ตรงที่มันใช้งานได้กับออนโฟกัสเท่านั้น (ต้องมีการบล็อกเหตุการณ์ที่ค่อนข้าง จำกัด ) คุณสามารถทำได้ดังต่อไปนี้:
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/
น่าเศร้าที่ดูเหมือนว่าจะใช้ได้กับเบราว์เซอร์ webkit เท่านั้น อาจมีคนอื่นคิดหาวิธีแก้ปัญหา firefox / IE
addEventListener("focus",fn,{once: true})
ฉันไม่อยากให้เหตุการณ์ที่มุ่งเน้นที่จะยิงทุกครั้งดังนั้นผมจึงอยากจะใช้ อย่างไรก็ตามฉันไม่สามารถยิงมันได้เลยโดยใช้document.body.addEventListener
.. ฉันไม่รู้ว่าทำไม แต่ฉันได้ผลลัพธ์เดียวกันกับwindow.addEventListener
.
mousemove
เหตุการณ์window.document
นอกเหนือจากการฟังfocus
บนwindow
ดูเหมือนจะใช้งานได้ทุกที่ (อย่างน้อยในเบราว์เซอร์สมัยใหม่ฉันไม่สนใจเกี่ยวกับความพินาศในทศวรรษที่ผ่านมา) โดยทั่วไปสามารถใช้เหตุการณ์การโต้ตอบใด ๆ สำหรับงานนี้ที่ถูกบล็อกโดยกล่องโต้ตอบเปิดไฟล์ที่เปิดอยู่
คุณทำไม่ได้
ผลลัพธ์ของกล่องโต้ตอบไฟล์จะไม่เปิดเผยต่อเบราว์เซอร์
change
จัดส่งเหตุการณ์
change
ส่งเหตุการณ์สำหรับสิ่งนั้น
ดังนั้นฉันจะโยนหมวกของฉันเป็นคำถามนี้ตั้งแต่ฉันคิดวิธีแก้ปัญหาใหม่ ฉันมี Progressive Web App ที่ช่วยให้ผู้ใช้สามารถจับภาพและวิดีโอและอัปโหลดได้ เราใช้ WebRTC เมื่อเป็นไปได้ แต่กลับไปใช้เครื่องมือเลือกไฟล์ HTML5 สำหรับอุปกรณ์ที่มีการรองรับน้อยกว่า * ไอ Safari *หากคุณกำลังทำงานโดยเฉพาะกับแอปพลิเคชันเว็บบนมือถือ Android / iOS ซึ่งใช้กล้องเนทีฟเพื่อถ่ายภาพ / วิดีโอโดยตรงนี่เป็นวิธีแก้ปัญหาที่ดีที่สุด
ปมของปัญหานี้คือเมื่อหน้าเว็บโหลดขึ้นมาfile
คือnull
แต่เมื่อผู้ใช้เปิดกล่องโต้ตอบและกด "ยกเลิก" สิ่งfile
นั้นก็ยังคงอยู่null
จึงไม่ "เปลี่ยนแปลง" จึงไม่มีการทริกเกอร์เหตุการณ์ "เปลี่ยนแปลง" สำหรับเดสก์ท็อปสิ่งนี้ก็ไม่เลวร้ายนักเพราะ UI ของเดสก์ท็อปส่วนใหญ่ไม่ได้ขึ้นอยู่กับการรู้ว่าเมื่อใดมีการเรียกใช้การยกเลิก แต่ UI ของอุปกรณ์เคลื่อนที่ที่นำกล้องขึ้นมาเพื่อถ่ายภาพ / วิดีโอนั้นขึ้นอยู่กับการทราบเมื่อกดยกเลิก
เดิมทีฉันใช้document.body.onfocus
เหตุการณ์เพื่อตรวจจับเมื่อผู้ใช้กลับมาจากเครื่องมือเลือกไฟล์และสิ่งนี้ใช้ได้กับอุปกรณ์ส่วนใหญ่ แต่ iOS 11.3 พังเพราะเหตุการณ์นั้นไม่ถูกทริกเกอร์
วิธีแก้ปัญหาของฉันคือ * shudder * เพื่อวัดเวลาของ CPU เพื่อตรวจสอบว่าขณะนี้เพจอยู่ในพื้นหน้าหรือพื้นหลัง บนอุปกรณ์เคลื่อนที่เวลาในการประมวลผลจะถูกกำหนดให้กับแอปที่อยู่เบื้องหน้า เมื่อกล้องมองเห็นได้มันจะขโมยเวลาของ CPU และจัดลำดับความสำคัญของเบราว์เซอร์ สิ่งที่เราต้องทำคือวัดว่าหน้าเว็บของเราได้รับเวลาในการประมวลผลเท่าใดเมื่อกล้องเปิดตัวเวลาที่มีอยู่ของเราจะลดลงอย่างมาก เมื่อกล้องถูกปิด (ไม่ว่าจะยกเลิกหรืออย่างอื่น) เวลาที่มีอยู่ของเราก็เพิ่มขึ้นอย่างรวดเร็ว
เราสามารถวัดระยะเวลาของ CPU โดยใช้setTimeout()
เพื่อเรียกใช้การเรียกกลับเป็น X มิลลิวินาทีจากนั้นวัดระยะเวลาที่เรียกใช้จริง เบราว์เซอร์จะไม่เรียกใช้งานอย่างแน่นอนหลังจาก X มิลลิวินาที แต่ถ้ามันอยู่ใกล้พอสมควรเราจะต้องอยู่เบื้องหน้า หากเบราว์เซอร์อยู่ไกลมาก (ช้ากว่าที่ร้องขอมากกว่า 10 เท่า) เราจะต้องอยู่เบื้องหลัง การใช้งานขั้นพื้นฐานเป็นดังนี้:
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);
});
}
ฉันทดสอบสิ่งนี้ใน iOS และ Android เวอร์ชันล่าสุดโดยเปิดใช้งานกล้องเนทีฟโดยตั้งค่าแอตทริบิวต์ใน<input />
องค์ประกอบ
<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />
สิ่งนี้ได้ผลดีกว่าที่ฉันคาดไว้มาก ดำเนินการทดลอง 10 ครั้งโดยขอให้เรียกใช้ตัวจับเวลาใน 25 มิลลิวินาที จากนั้นจะวัดระยะเวลาที่ใช้ในการเรียกใช้จริงและหากค่าเฉลี่ยของการทดลอง 10 ครั้งน้อยกว่า 50 มิลลิวินาทีเราจะถือว่าเราต้องอยู่เบื้องหน้าและกล้องก็หายไป หากมากกว่า 50 มิลลิวินาทีเราจะต้องอยู่เบื้องหลังและควรรอต่อไป
ฉันใช้setTimeout()
มากกว่าsetInterval()
เพราะหลังสามารถจัดคิวการเรียกใช้หลายครั้งซึ่งดำเนินการทันทีหลังจากกัน สิ่งนี้สามารถเพิ่มสัญญาณรบกวนในข้อมูลของเราได้อย่างมากดังนั้นฉันจึงติดอยู่setTimeout()
แม้ว่าจะซับซ้อนกว่าเล็กน้อยในการทำเช่นนั้น
ตัวเลขเฉพาะเหล่านี้ใช้ได้ดีสำหรับฉันแม้ว่าฉันจะเคยเห็นอย่างน้อยหนึ่งครั้งที่ตรวจพบการเลิกใช้กล้องก่อนเวลาอันควร ฉันเชื่อว่าเป็นเพราะกล้องอาจเปิดได้ช้าและอุปกรณ์อาจทำการทดลอง 10 ครั้งก่อนที่จะกลายเป็นพื้นหลังจริง การเพิ่มการทดลองเพิ่มเติมหรือรอสัก 25-50 มิลลิวินาทีก่อนที่จะเริ่มฟังก์ชันนี้อาจเป็นวิธีแก้ปัญหาชั่วคราว
น่าเสียดายที่สิ่งนี้ใช้ไม่ได้กับเบราว์เซอร์เดสก์ท็อปจริงๆ ในทางทฤษฎีเคล็ดลับเดียวกันนี้เป็นไปได้เนื่องจากจัดลำดับความสำคัญของหน้าปัจจุบันเหนือหน้าที่มีพื้นหลัง อย่างไรก็ตามเดสก์ท็อปจำนวนมากมีทรัพยากรเพียงพอที่จะทำให้หน้าทำงานด้วยความเร็วเต็มที่แม้ว่าจะอยู่เบื้องหลังดังนั้นกลยุทธ์นี้จึงไม่ได้ผลในทางปฏิบัติ
ทางเลือกหนึ่งที่ไม่ค่อยมีใครพูดถึงว่าฉันสำรวจคือการล้อเลียนกFileList
. เราเริ่มต้นด้วยnull
ใน<input />
และจากนั้นถ้าผู้ใช้เปิดกล้องและยกเลิกพวกเขากลับไปมาnull
ซึ่งไม่ได้มีการเปลี่ยนแปลงและไม่มีเหตุการณ์จะเรียก วิธีแก้ปัญหาหนึ่งคือการกำหนดไฟล์ดัมมี่ให้กับการ<input />
เริ่มต้นหน้าดังนั้นการตั้งค่าเป็นnull
เป็นการเปลี่ยนแปลงซึ่งจะทำให้เกิดเหตุการณ์ที่เหมาะสม
น่าเสียดายที่ไม่มีวิธีอย่างเป็นทางการในการสร้าง a FileList
และ<input />
องค์ประกอบนั้นต้องใช้FileList
โดยเฉพาะและจะไม่ยอมรับค่าอื่นใดนอกจากnull
นี้ โดยปกติแล้วFileList
วัตถุไม่สามารถสร้างได้โดยตรง แต่จะเกี่ยวข้องกับปัญหาด้านความปลอดภัยเก่า ๆ ซึ่งดูเหมือนจะไม่เกี่ยวข้องอีกต่อไป วิธีเดียวที่จะได้รับข้อมูลจาก<input />
องค์ประกอบภายนอกคือการใช้แฮ็กที่คัดลอกวางข้อมูลเพื่อปลอมเหตุการณ์คลิปบอร์ดซึ่งอาจมีFileList
วัตถุ (โดยทั่วไปแล้วคุณจะแกล้งทำเป็นลากแล้วปล่อยไฟล์ - เหตุการณ์เว็บไซต์ของคุณ) สิ่งนี้เป็นไปได้ใน Firefox แต่ไม่ใช่สำหรับ iOS Safari ดังนั้นจึงไม่สามารถใช้ได้กับกรณีการใช้งานเฉพาะของฉัน
ไม่จำเป็นต้องพูดว่านี่เป็นเรื่องน่าขัน ความจริงที่ว่าหน้าเว็บได้รับการแจ้งเตือนเป็นศูนย์ว่ามีการเปลี่ยนแปลงองค์ประกอบ UI ที่สำคัญนั้นเป็นเรื่องน่าหัวเราะ นี่เป็นข้อบกพร่องในข้อมูลจำเพาะเนื่องจากไม่เคยมีไว้สำหรับ UI การจับภาพสื่อแบบเต็มหน้าจอและในทางเทคนิคจะไม่เรียกเหตุการณ์ "เปลี่ยนแปลง"ไปตามข้อกำหนด
อย่างไรก็ตามผู้จำหน่ายเบราว์เซอร์โปรดรับรู้ถึงความเป็นจริงของสิ่งนี้ได้หรือไม่? สิ่งนี้สามารถแก้ไขได้ด้วยเหตุการณ์ "เสร็จสิ้น" ใหม่ซึ่งถูกเรียกใช้แม้ว่าจะไม่มีการเปลี่ยนแปลงใด ๆ เกิดขึ้นหรือคุณสามารถเรียก "เปลี่ยน" ได้เลย ใช่ว่าจะขัดกับข้อมูลจำเพาะ แต่เป็นเรื่องเล็กน้อยสำหรับฉันที่จะสรุปเหตุการณ์การเปลี่ยนแปลงในฝั่ง JavaScript แต่โดยพื้นฐานแล้วเป็นไปไม่ได้ที่จะสร้างเหตุการณ์ "เสร็จสิ้น" ของฉันเอง แม้แต่วิธีแก้ปัญหาของฉันก็เป็นเพียงการวิเคราะห์พฤติกรรมหากไม่มีการรับประกันสถานะของเบราว์เซอร์
ตามที่กล่าวมาแล้ว API นี้ไม่สามารถใช้งานได้โดยพื้นฐานสำหรับอุปกรณ์พกพาและฉันคิดว่าการเปลี่ยนแปลงเบราว์เซอร์ที่ค่อนข้างเรียบง่ายอาจทำให้สิ่งนี้ง่ายขึ้นอย่างไม่มีที่สิ้นสุดสำหรับนักพัฒนาเว็บ * ขั้นตอนจากกล่องสบู่ *
เมื่อคุณเลือกไฟล์และคลิกเปิด / ยกเลิก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
? คุณไม่สามารถสรุปคำสั่งใด ๆ ได้เนื่องจากอาจขึ้นอยู่กับการใช้งานของเบราว์เซอร์
อย่างน้อยก็ใน Opera และ Chrome (ปลาย 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);
};
});
เพียงฟังเหตุการณ์คลิกเช่นกัน
ตามตัวอย่างของ Shiboe นี่คือตัวอย่าง 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
}
});
วิธีแก้ปัญหาของ Shiboe จะเป็นวิธีที่ดีหากใช้งานได้กับ webkit บนอุปกรณ์เคลื่อนที่ แต่ก็ไม่เป็นเช่นนั้น สิ่งที่ฉันสามารถทำได้คือการเพิ่มตัวรับฟังเหตุการณ์ mousemove ให้กับวัตถุบางตัวในเวลาที่เปิดหน้าต่างป้อนไฟล์ดังนี้:
$('.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
};
เหตุการณ์ mousemove ถูกบล็อกจากเพจในขณะที่กล่องโต้ตอบไฟล์เปิดอยู่และเมื่อปิดแล้วจะตรวจสอบว่ามีไฟล์ใดในอินพุตไฟล์หรือไม่ ในกรณีของฉันฉันต้องการให้ตัวบ่งชี้กิจกรรมปิดกั้นสิ่งต่าง ๆ จนกว่าไฟล์จะถูกอัปโหลดดังนั้นฉันต้องการลบตัวบ่งชี้ของฉันเมื่อยกเลิกเท่านั้น
อย่างไรก็ตามสิ่งนี้ไม่สามารถแก้ได้สำหรับมือถือเนื่องจากไม่มีเมาส์ให้ขยับ วิธีแก้ปัญหาของฉันมีน้อยกว่าที่สมบูรณ์แบบ แต่ฉันคิดว่ามันดีพอ
$('.upload-progress').bind('touchstart', function() {
checkForFiles(this);
});
ตอนนี้เรากำลังฟังการสัมผัสบนหน้าจอเพื่อทำการตรวจสอบไฟล์เดียวกัน ฉันค่อนข้างมั่นใจว่านิ้วของผู้ใช้จะวางบนหน้าจออย่างรวดเร็วหลังจากยกเลิกและปิดตัวบ่งชี้กิจกรรมนี้
นอกจากนี้คุณยังสามารถเพิ่มตัวบ่งชี้กิจกรรมในเหตุการณ์การเปลี่ยนแปลงอินพุตไฟล์ได้ แต่บนมือถือมักจะมีความล่าช้าสองสามวินาทีระหว่างการเลือกรูปภาพและการเริ่มทำงานของเหตุการณ์การเปลี่ยนแปลงดังนั้น UX จึงดีกว่ามากสำหรับตัวบ่งชี้กิจกรรมที่จะแสดงที่ เริ่มต้นกระบวนการ
ฉันพบว่า atribute นี้เรียบง่ายที่สุด
if ($('#selectedFile')[0].files.length > 1)
{
// Clicked on 'open' with file
} else {
// Clicked on 'cancel'
}
นี่selectedFile
คือinput type=file
ไฟล์.
ฉันรู้ว่านี่เป็นคำถามที่เก่ามาก แต่ในกรณีที่ช่วยใครบางคนฉันพบเมื่อใช้เหตุการณ์ onmousemove เพื่อตรวจจับการยกเลิกว่าจำเป็นต้องทดสอบเหตุการณ์ดังกล่าวตั้งแต่สองเหตุการณ์ขึ้นไปในช่วงเวลาสั้น ๆ เนื่องจากเบราว์เซอร์สร้างเหตุการณ์ onmousemove รายการเดียว (Chrome 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
ได้รับโฟกัสกลับมาดังนั้นฉันจึงฟังเหตุการณ์นั้น
อัปเดต
ฉันพบว่าสิ่งนี้ใช้ไม่ได้ในซาฟารีและ poltergeist / phantomjs นำข้อมูลนี้มาพิจารณาหากคุณต้องการนำไปใช้
การรวมโซลูชันของ Shiboe และ alx ฉันมีรหัสที่น่าเชื่อถือที่สุด:
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 */
โดยทั่วไปแล้วเหตุการณ์ mousemove จะหลอกลวง แต่ในกรณีที่ผู้ใช้คลิกและมากกว่า:
... เราจะไม่ได้รับเหตุการณ์ mousemove ดังนั้นจึงไม่มีการยกเลิกการโทรกลับ ยิ่งไปกว่านั้นหากผู้ใช้ยกเลิกกล่องโต้ตอบที่สองและเลื่อนเมาส์เราจะได้รับการยกเลิกการโทรกลับ 2 ครั้ง โชคดีที่ jQuery focus เป็นพิเศษในเหตุการณ์ที่เกิดขึ้นในเอกสารทั้งสองกรณีช่วยให้เราหลีกเลี่ยงสถานการณ์ดังกล่าว ข้อ จำกัด เพียงอย่างเดียวคือถ้าหนึ่งบล็อก focusIn เหตุการณ์อย่างใดอย่างหนึ่ง
mousemove
เหตุการณ์document
ระหว่างเลือกไฟล์ในกล่องโต้ตอบ OS ใน Chrome 56.0.2924.87 บน Ubuntu 16.10 ไม่มีปัญหาเมื่อไม่ได้เลื่อนเมาส์หรือใช้เพียงแป้นพิมพ์เพื่อเลือกไฟล์ ฉันต้องแทนที่mousemove
ด้วยkeydown
เพื่อตรวจจับการยกเลิกให้เร็วที่สุด แต่ไม่ "เร็วเกินไป" เมื่อกล่องโต้ตอบยังเปิดอยู่
ฉันเห็นว่าคำตอบของฉันค่อนข้างล้าสมัย แต่ก็ไม่น้อยไปกว่ากัน ฉันประสบกับปัญหาเดียวกัน นี่คือทางออกของฉัน โค้ดที่มีประโยชน์ที่สุดคือรหัสของ KGA แต่มันใช้งานไม่ได้ทั้งหมดและค่อนข้างซับซ้อน แต่ฉันทำให้มันง่ายขึ้น
นอกจากนี้ตัวสร้างปัญหาหลักคือข้อเท็จจริงที่ว่าเหตุการณ์ 'การเปลี่ยนแปลง' ไม่ได้เกิดขึ้นทันทีหลังจากโฟกัสดังนั้นเราต้องรอสักครู่
"#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);
});
คุณสามารถตรวจจับสิ่งนี้ได้ในบางสถานการณ์เท่านั้น โดยเฉพาะใน chrome หากไฟล์ถูกเลือกไว้ก่อนหน้านี้แล้วกล่องโต้ตอบไฟล์ถูกคลิกและยกเลิกการคลิก Chrome จะล้างไฟล์และเริ่มการทำงานของเหตุการณ์ onChange
https://code.google.com/p/chromium/issues/detail?id=2508
ในสถานการณ์สมมตินี้คุณสามารถตรวจพบได้โดยจัดการกับเหตุการณ์ onChange และตรวจสอบคุณสมบัติไฟล์
สิ่งต่อไปนี้ดูเหมือนจะใช้ได้สำหรับฉัน (บนเดสก์ท็อป, windows):
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, Edge, Chrome, Firefox แต่ดูเหมือนว่าจะไม่ทำงานบน Chrome บนแท็บเล็ต Android เนื่องจากไม่ทำให้เหตุการณ์โฟกัสเกิดขึ้น
ช่องfile
-type น่าหงุดหงิดไม่ตอบสนองต่อเหตุการณ์มากนัก (ภาพเบลอจะน่ารัก) ฉันเห็นผู้คนจำนวนมากแนะนำchange
วิธีแก้ปัญหาที่มีความเชี่ยวชาญและพวกเขาก็ถูกลดคะแนนลง
change
ใช้งานได้ แต่มีข้อบกพร่องที่สำคัญ (เทียบกับสิ่งที่เราต้องการให้เกิดขึ้น)
เมื่อคุณโหลดหน้าที่มีฟิลด์ไฟล์ใหม่ให้เปิดกล่องแล้วกดยกเลิก ไม่มีอะไรเปลี่ยนแปลงอย่างน่าหงุดหงิด
สิ่งที่ฉันเลือกทำคือโหลดในสภาพที่มีรั้วรอบขอบชิด
section#after-image
ในกรณีของฉันถูกซ่อนจากมุมมอง เมื่อมีfile field
การเปลี่ยนแปลงปุ่มอัปโหลดจะปรากฏขึ้น เมื่ออัปโหลดสำเร็จsection#after-image
จะปรากฏขึ้นchange
เหตุการณ์จะถูกเรียกโดยการยกเลิกนี้และที่นั่นฉันสามารถ (และทำ) ซ่อนปุ่มอัปโหลดของฉันอีกครั้งจนกว่าจะเลือกไฟล์ที่เหมาะสมฉันโชคดีที่รัฐที่มีรั้วรอบขอบชิดนี้เป็นผู้ออกแบบฟอร์มของฉันอยู่แล้ว คุณไม่จำเป็นต้องใช้สไตล์เดียวกันเพียงแค่ซ่อนปุ่มอัปโหลดไว้ในตอนแรกและเมื่อมีการเปลี่ยนแปลงการตั้งค่าฟิลด์ที่ซ่อนอยู่หรือตัวแปรจาวาสคริปต์เป็นสิ่งที่คุณสามารถตรวจสอบได้เมื่อส่ง
ฉันพยายามเปลี่ยนค่าของไฟล์ [0] ก่อนที่จะโต้ตอบกับฟิลด์ สิ่งนี้ไม่ได้ทำอะไรเกี่ยวกับการเปลี่ยนแปลง
ใช่ได้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);
วิธีการทำงาน: ในขณะที่กล่องโต้ตอบการเลือกไฟล์เปิดอยู่เอกสารจะไม่ได้รับเหตุการณ์ตัวชี้เมาส์ มีความล่าช้า 1000 มิลลิวินาทีเพื่อให้กล่องโต้ตอบปรากฏขึ้นจริงและปิดกั้นหน้าต่างเบราว์เซอร์ ตรวจสอบใน Chrome และ Firefox (Windows เท่านั้น)
แต่นี่ไม่ใช่วิธีที่เชื่อถือได้ในการตรวจจับกล่องโต้ตอบที่ถูกยกเลิกแน่นอน แม้ว่าอาจปรับปรุงพฤติกรรม 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
หรืออะไรก็ตามที่ปุ่มของคุณ จากนั้นใน JavaScript ให้คุณคว้าชื่อไฟล์ หากชื่อไฟล์ไม่มีค่าก็ไม่ต้องแสดง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>
JavaScript:
$('#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');
}
});
CSS:
.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 จำนวนมากนี้คือการทำให้เว็บไซต์และปุ่มสามารถเข้าถึงได้สำหรับทุกคน จัดแต่งปุ่มของคุณตามที่คุณต้องการ
นี่ไม่ได้ตอบคำถามของคุณอย่างแน่นอน สมมติฐานของฉันคือคุณมีสถานการณ์เมื่อคุณเพิ่มอินพุตไฟล์และเรียกใช้การเลือกไฟล์และหากผู้ใช้ยกเลิกคุณเพียงแค่ลบอินพุต
หากเป็นกรณีนี้: ทำไมต้องเพิ่มอินพุตไฟล์เปล่า?
สร้างได้ทันที แต่เพิ่มลงใน DOM เมื่อกรอกข้อมูลแล้วเท่านั้นเช่น:
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/
// ใช้โฮเวอร์แทนการเบลอ
var fileInput = $("#fileInput");
if (fileInput.is(":hover") {
//open
} else {
}
หากคุณต้องการ JQuery อยู่แล้วโซลูชันนี้อาจใช้งานได้ (นี่เป็นรหัสเดียวกับที่ฉันต้องการจริงๆในกรณีของฉันแม้ว่าการใช้ Promise จะเป็นเพียงการบังคับให้รหัสรอจนกว่าการเลือกไฟล์จะได้รับการแก้ไข):
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);
}
ขอบคุณ! = ง
เราทำได้ในเชิงมุมเหมือนด้านล่าง
<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 เสร็จแล้วและเห็นได้ชัดว่าทุกคนสามารถใช้ valina JS ได้ (ตามข้อกำหนด)
$("#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 change listener ในช่องป้อนข้อมูลและตรวจพบว่าผู้ใช้ยกเลิกหรือปิดหน้าต่างอัปโหลดโดยใช้ค่าของฟิลด์
นี่คือตัวอย่าง:
//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