Как я могу определить, когда пользователь отменяет ввод файла, используя ввод файла html?
onChange позволяет мне определять, когда они выбирают файл, но я также хотел бы знать, когда они отменяют (закройте диалоговое окно выбора файла, ничего не выбирая).
e.target.files
Ответы:
Хотя это не прямое решение, а также плохо в том, что оно работает только (насколько я тестировал) с onfocus (требуя довольно ограничивающую блокировку событий), вы можете добиться этого с помощью следующего:
Что в этом хорошего, так это то, что вы можете присоединять / отсоединять его вовремя с файловым событием, и он также, кажется, отлично работает со скрытыми входами (определенная привилегия, если вы используете визуальный обходной путь для дерьмового типа ввода по умолчанию = ' файл'). После этого вам просто нужно выяснить, изменилось ли входное значение.
Пример:
Посмотреть в действии: 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
отправляется событие.Так что я брошу свою шляпу в этот вопрос, так как я придумал новое решение. У меня есть прогрессивное веб-приложение, которое позволяет пользователям снимать фотографии и видео и загружать их. Мы используем WebRTC, когда это возможно, но возвращаемся к средствам выбора файлов HTML5 для устройств с меньшей поддержкой * cough Safari cough *. Если вы работаете специально над мобильным веб-приложением Android / iOS, которое использует встроенную камеру для прямой съемки фотографий / видео, то это лучшее решение, с которым я столкнулся.
Суть этой проблемы в том, что когда страница загружается, то
file
естьnull
, но затем, когда пользователь открывает диалоговое окно и нажимает «Отмена»,file
остается неподвижнымnull
, следовательно, он не «изменился», поэтому событие «изменение» не запускается. Для настольных компьютеров это не так уж плохо, потому что большинство пользовательских интерфейсов рабочего стола не зависят от знания, когда вызывается отмена, но мобильные пользовательские интерфейсы, которые вызывают камеру для захвата фото / видео, очень зависят от знания, когда нажата отмена.Первоначально я использовал
document.body.onfocus
событие, чтобы определить, когда пользователь вернулся из средства выбора файлов, и это сработало для большинства устройств, но iOS 11.3 сломала его, так как это событие не запускается.Концепция
Мое решение - * содрогаться *, чтобы измерить синхронизацию процессора, чтобы определить, находится ли страница в данный момент на переднем плане или в фоновом режиме. На мобильных устройствах время обработки передается приложению, которое в данный момент находится на переднем плане. Когда камера видна, она крадет процессорное время и снижает приоритет браузера. Все, что нам нужно сделать, это измерить, сколько времени на обработку отводится нашей странице, когда при запуске камеры наше доступное время резко упадет. Когда камера закрывается (либо отменяется, либо иным образом), наше доступное время резко увеличивается.
Реализация
Мы можем измерить время ЦП, используя
setTimeout()
для вызова обратного вызова в X миллисекундах, а затем измерить, сколько времени потребовалось для его фактического вызова. Браузер никогда не вызовет его ровно через X миллисекунд, но если он достаточно близок, то мы должны быть на переднем плане. Если браузер находится очень далеко (более чем в 10 раз медленнее, чем запрошено), значит, мы должны работать в фоновом режиме. Базовая реализация этого выглядит так:Я протестировал это на последних версиях iOS и Android, вызвав встроенную камеру, установив атрибуты
<input />
элемента.На самом деле это сработало намного лучше, чем я ожидал. Он запускает 10 попыток, запрашивая запуск таймера через 25 миллисекунд. Затем он измеряет, сколько времени на самом деле потребовалось для вызова, и если среднее значение 10 попыток составляет менее 50 миллисекунд, мы предполагаем, что мы должны быть на переднем плане, а камера исчезла. Если он превышает 50 миллисекунд, значит, мы все еще должны находиться в фоновом режиме и должны продолжать ждать.
Некоторые дополнительные детали
Я использовал,
setTimeout()
а неsetInterval()
потому, что последний может ставить в очередь несколько вызовов, которые выполняются сразу после друг друга. Это могло резко увеличить шум в наших данных, поэтому я придерживалсяsetTimeout()
этого правила, хотя это немного сложнее.Эти конкретные числа хорошо работали для меня, хотя я видел хотя бы один случай, когда отключение камеры было обнаружено преждевременно. Я считаю, что это связано с тем, что камера может медленно открываться, и устройство может пройти 10 испытаний, прежде чем оно фактически станет заземленным. Добавление дополнительных испытаний или ожидание 25-50 миллисекунд перед запуском этой функции может быть обходным решением.
Рабочий стол
К сожалению, это не работает для настольных браузеров. Теоретически возможен тот же трюк, поскольку они отдают приоритет текущей странице над фоновыми страницами. Однако у многих настольных компьютеров достаточно ресурсов, чтобы страница работала на полной скорости даже в фоновом режиме, поэтому на практике эта стратегия не работает.
Альтернативные решения
Одно из альтернативных решений, которые я изучал, было издевательством над файлом
FileList
. Мы начинаем сnull
in,<input />
а затем, если пользователь открывает камеру и отменяет, он возвращается к немуnull
, что не является изменением, и никакое событие не запускается. Одним из решений было бы назначить фиктивный файл для начала<input />
страницы, поэтому установкаnull
будет изменением, которое вызовет соответствующее событие.К сожалению, официального способа создать a не существует
FileList
, а<input />
элемент требует,FileList
в частности, и не принимает никаких других значений, кромеnull
. Естественно,FileList
объекты не могут быть сконструированы напрямую, это связано с некоторыми старыми проблемами безопасности, которые, по-видимому, даже больше не актуальны. Единственный способ получить один за пределами<input />
элемента - использовать хак, который копирует и вставляет данные, чтобы подделать событие буфера обмена, которое может содержатьFileList
объект (вы в основном имитируете перетаскивание файла на -ваше-сайт событие). Это возможно в Firefox, но не в iOS Safari, поэтому для моего конкретного случая использования это было нецелесообразно.Браузеры, пожалуйста ...
Излишне говорить, что это явно смешно. Тот факт, что веб-страницы не получают никаких уведомлений об изменении критического элемента пользовательского интерфейса, просто смехотворен. Это действительно ошибка в спецификации, так как она никогда не предназначалась для пользовательского интерфейса полноэкранного захвата мультимедиа, и отсутствие запуска события «изменения» технически соответствует спецификации.
Однако могут ли производители браузеров признать реальность этого? Эту проблему можно решить либо с помощью нового события «Готово», которое запускается, даже если никаких изменений не происходит, либо вы можете просто запустить «изменение» в любом случае. Да, это было бы против спецификации, но для меня тривиально вывести событие изменения на стороне JavaScript, но принципиально невозможно изобрести собственное событие «done». Даже мое решение на самом деле просто эвристика, если не дает никаких гарантий относительно состояния браузера.
В его нынешнем виде этот API принципиально непригоден для мобильных устройств, и я думаю, что относительно простое изменение браузера могло бы значительно упростить это для веб-разработчиков * сходит с ума *.
источник
Когда вы выбираете файл и нажимаете кнопку «Открыть / отменить»,
input
элемент должен потерять фокусblur
. Предполагая, что начальноеvalue
значениеinput
пусто, любое непустое значение в вашемblur
обработчике будет означать ОК, а пустое значение будет означать Отмена.ОБНОВЛЕНИЕ:
blur
не запускается, когдаinput
скрыт. Поэтому нельзя использовать этот трюк с загрузкой на основе IFRAME, если вы не хотите временно отображать файлыinput
.источник
blur
не запускается при выборе файла. В других браузерах не пробовал.источник
else
оценивается ли когда-нибудь ваше утверждение?Большинство из этих решений мне не подходят.
Проблема в том, что никогда не знаешь, какое событие сработает кулаком, это
click
или нетchange
? Вы не можете предполагать какой-либо порядок, потому что он, вероятно, зависит от реализации браузера.По крайней мере, в Opera и Chrome (конец 2015 года)
click
срабатывает непосредственно перед «заполнением» ввода файлами, поэтому вы никогда не узнаете, сколько времени пройдетfiles.length != 0
до тех пор, пока выclick
не сработаетеchange
.Вот код:
источник
Просто послушайте также событие щелчка.
Следуя примеру Shiboe, вот пример jQuery:
Вы можете увидеть это в действии здесь: http://jsfiddle.net/T3Vwz
источник
Вы можете поймать отмену, если выберете тот же файл, что и раньше, и нажмете кнопку «Отмена»: в этом случае.
Сделать это можно так:
источник
Самый простой способ - проверить, есть ли файлы во временной памяти. Если вы хотите получать событие изменения каждый раз, когда пользователь нажимает на ввод файла, вы можете запустить его.
источник
Решение Shiboe было бы хорошим, если бы оно работало на мобильном webkit, но это не так. Что я могу придумать, так это добавить прослушиватель событий mousemove к некоторому объекту dom в то время, когда открывается окно ввода файла, например:
Событие mousemove блокируется на странице, пока открыто диалоговое окно с файлом, а когда он закрывается, одно проверяет, есть ли какие-либо файлы во входном файле. В моем случае я хочу, чтобы индикатор активности блокировал вещи до тех пор, пока файл не будет загружен, поэтому я хочу удалить свой индикатор только при отмене.
Однако для мобильных устройств это не решает, поскольку нет мыши, которую можно было бы перемещать. Мое решение там далеко не идеально, но я считаю его достаточно хорошим.
Теперь мы прислушиваемся к касанию экрана, чтобы выполнить ту же проверку файлов. Я почти уверен, что после отмены и отключения этого индикатора активности палец пользователя будет довольно быстро помещен на экран.
Можно также просто добавить индикатор активности в событие изменения ввода файла, но на мобильных устройствах часто возникает задержка в несколько секунд между выбором изображения и срабатыванием события изменения, так что это просто намного лучший UX для индикатора активности, который будет отображаться в начало процесса.
источник
Я нашел этот атрибут, пока он самый простой.
Вот
selectedFile
файлinput type=file
.источник
Я знаю, что это очень старый вопрос, но на случай, если он кому-то поможет, я обнаружил, что при использовании события onmousemove для обнаружения отмены необходимо было проверить два или более таких события за короткий промежуток времени. Это произошло потому, что отдельные события onmousemove генерируются браузером (Chrome 65) каждый раз, когда курсор перемещается из диалогового окна выбора файла и каждый раз, когда он перемещается из главного окна и обратно. Простой счетчик событий движения мыши в сочетании с коротким таймаутом для сброса счетчика до нуля сработало.
источник
В моем случае мне пришлось скрыть кнопку отправки, пока пользователи выбирали изображения.
Вот что я придумываю:
#image-field
это мой селектор файлов. Когда кто-то нажимает на нее, я отключаю кнопку отправки формы. Дело в том, что при закрытии диалогового окна файла - неважно, выбирают ли они файл или отменяют -#image-field
фокус возвращается, поэтому я слушаю это событие.ОБНОВИТЬ
Я обнаружил, что это не работает в safari и poltergeist / phantomjs. Примите во внимание эту информацию, если хотите ее реализовать.
источник
Объединив решения Shiboe и alx, я получил самый надежный код:
Как правило, событие mousemove помогает, но если пользователь сделал щелчок и затем:
... мы не получим событие mousemove, следовательно, обратного вызова отмены не будет. Более того, если пользователь отменяет второй диалог и перемещает мышь, мы получим 2 обратных вызова отмены. К счастью, специальное событие jQuery focusIn всплывает в документе в обоих случаях, помогая нам избежать таких ситуаций. Единственное ограничение - блокировка события focusIn.
источник
mousemove
событиеdocument
во время выбора файлов в диалоге ОС в Chrome 56.0.2924.87 на Ubuntu 16.10. Нет проблем, если вы не перемещаете мышь или используете только клавиатуру для выбора файла. Мне пришлось заменитьmousemove
на,keydown
чтобы обнаружить отмену как можно раньше, но не «слишком рано», когда диалог еще был открыт.Я вижу, что мой ответ был бы довольно устаревшим, но тем не менее. Я столкнулся с той же проблемой. Итак, вот мое решение. Самый полезный фрагмент кода - это код KGA. Но это не совсем работает и немного сложно. Но я упростил.
Кроме того, основной причиной проблем был тот факт, что событие «изменение» не происходит сразу после фокусировки, поэтому нам нужно подождать некоторое время.
«#appendfile» - на который пользователь нажимает, чтобы добавить новый файл. Hrefs получают события фокуса.
источник
Вы можете обнаружить это только в ограниченных обстоятельствах. В частности, в Chrome, если файл был выбран ранее, а затем щелкнули диалоговое окно с файлом и нажали кнопку отмены, Chrome очищает файл и запускает событие onChange.
https://code.google.com/p/chromium/issues/detail?id=2508
В этом сценарии вы можете обнаружить это, обработав событие onChange и проверив свойство files .
источник
Для меня работает следующее (на рабочем столе, в Windows):
Это действительно использует angularjs $ q, но вы можете заменить его любой другой структурой обещаний, если это необходимо.
Протестировано в IE11, Edge, Chrome, Firefox, но похоже, что он не работает в Chrome на планшете Android, поскольку не запускает событие Focus.
источник
Поле
file
-type, к сожалению, не реагирует на множество событий (размытие было бы прекрасно). Я вижу много людей, предлагающихchange
ориентированные на решения решения, и за них голосуют против.change
действительно работает, но у него есть серьезный недостаток (по сравнению с тем, что мы хотим ).Когда вы только что загружаете страницу, содержащую поле файла, откройте окно и нажмите «Отмена». К сожалению, ничего не меняется .
Я выбрал загрузку в закрытом состоянии.
section#after-image
в моем случае скрыта от просмотра. Когда моиfile field
изменения, отображается кнопка загрузки. После успешной загрузкиsection#after-image
отображается.change
событие запускается этой отменой, и там я могу (и действительно) повторно скрыть свою кнопку загрузки, пока не будет выбран правильный файл.Мне повезло, что это закрытое состояние уже было дизайном моей формы. Вам не нужно использовать один и тот же стиль, просто сначала скрывая кнопку загрузки, а после изменения устанавливайте скрытое поле или переменную javascript на то, что вы можете отслеживать при отправке.
Я попытался изменить значение files [0] до взаимодействия с полем. Это не повлияло на изменение.
Так что да,
change
работает, по крайней мере, так хорошо, как мы собираемся получить. Файловое поле защищено по очевидным причинам, но к разочарованию разработчиков с благими намерениями.Это не соответствует моей цели, но вы могли бы
onclick
загрузить предупреждение (неalert()
, потому что это останавливает обработку страницы) и скрыть его, если срабатывает изменение и files [0] имеет значение null. Если изменение не запускается, div остается в своем состоянии.источник
Есть хакерский способ сделать это (добавить обратные вызовы или разрешить некоторую отложенную / обещающую реализацию вместо
alert()
вызовов):Как это работает: пока открыто диалоговое окно выбора файла, документ не получает событий указателя мыши. Задержка составляет 1000 мс, чтобы диалоговое окно действительно появилось и заблокировало окно браузера. Проверено в Chrome и Firefox (только для Windows).
Но, конечно, это ненадежный способ обнаружить отмененный диалог. Хотя это может улучшить поведение пользовательского интерфейса для вас.
источник
Вот мое решение, использующее фокус ввода файла (без использования таймеров)
источник
Error: { "message": "Uncaught SyntaxError: missing ) after argument list", "filename": "https://stacksnippets.net/js", "lineno": 51, "colno": 1 }
В лучшем случае это хакерство, но вот рабочий пример моего решения, чтобы определить, загрузил ли пользователь файл или нет, и разрешить им продолжить, только если они загрузили файл.
В основном скрыть
Continue
,Save
,Proceed
или что - то ваша кнопка. Затем в JavaScript вы берете имя файла. Если имя файла не имеет значения, не показыватьContinue
кнопку. Если у него есть значение, покажите кнопку. Это также работает, если они сначала загружают файл, а затем пытаются загрузить другой файл и нажимают «Отмена».Вот код.
HTML:
JavaScript:
CSS:
Для CSS во многом это делается для того, чтобы сделать сайт и кнопку доступными для всех. Настройте свою кнопку так, как вам нравится.
источник
Что ж, это не совсем ответ на ваш вопрос. Я предполагаю, что у вас есть сценарий, когда вы добавляете ввод файла и вызываете выбор файла, и если пользователь нажимает кнопку отмены, вы просто удаляете ввод.
Если это так, то: Зачем вводить пустой файл?
Создавайте один на лету, но добавляйте его в DOM только после того, как он заполнен. Примерно так:
Итак, здесь я создаю <input type = "file" /> на лету, привязываюсь к его событию изменения и сразу же вызываю щелчок. При изменении сработает только тогда, когда пользователь выберет файл и нажмет «ОК», в противном случае ввод не будет добавлен в DOM и, следовательно, не будет отправлен.
Рабочий пример здесь: https://jsfiddle.net/69g0Lxno/3/
источник
// Используем наведение вместо размытия
источник
Если вам уже требуется JQuery, это решение может сработать (это тот самый код, который мне действительно нужен в моем случае, хотя использование обещания просто заставляет код ждать, пока выбор файла не будет решен):
});
источник
В этом потоке есть несколько предлагаемых решений, и эта трудность определения момента, когда пользователь нажимает кнопку «Отмена» в поле выбора файла, является проблемой, которая затрагивает многих людей.
Дело в том, что не существует 100% надежного способа определить, нажал ли пользователь кнопку «Отмена» в поле выбора файла. Но есть способы надежно определить, добавил ли пользователь файл во входной файл. Итак, это основная стратегия этого ответа!
Я решил добавить этот ответ, потому что, по-видимому, другие ответы не работают в большинстве браузеров и не гарантируются на мобильных устройствах.
Вкратце код основан на 3 пунктах:
Для лучшего понимания посмотрите на приведенный ниже код и примечания.
Спасибо! = D
источник
Мы достигли углового, как показано ниже.
HTML
TS
источник
Просто добавьте в свой ввод слушателя изменений, тип которого - файл. т.е.
Я использовал jQuery, и, очевидно, любой может использовать valina JS (в соответствии с требованиями).
источник
.change()
вызывается ненадежно, если пользователь нажимает кнопку «Отмена» в средстве выбора файлов.источник
Решение для выбора файла со скрытым вводом
Примечание: этот код не обнаруживает отмену, он предлагает способ обойти необходимость ее обнаружения в общем случае, когда люди пытаются ее обнаружить.
Я пришел сюда, когда искал решение для загрузки файлов с использованием скрытого ввода, я считаю, что это наиболее распространенная причина искать способ обнаружения отмены ввода файла (диалоговое окно открытия файла -> если файл был выбран, запустите несколько код, иначе ничего не делать), вот мое решение:
Пример использования:
Обратите внимание, что если файл не был выбран, первая строка вернется только один раз,
selectFile()
вызывается снова (или если вы вызывалисьfileSelectorResolve()
из другого места).Другой пример:
источник
Вы можете создать прослушиватель изменений jquery в поле ввода и определить, что пользователь отменяет или закрывает окно загрузки по значению поля.
вот пример:
источник