тип ввода = код файла:

могу определить, когда пользователь отменяет ввод файла, используя ввод файла html?

onChange позволяет мне определять, когда они выбирают файл, но я также хотел бы знать, когда они отменяют (закройте диалог выбора файла, ничего не выбирая).

Ответы на вопрос(27)

ности, в Chrome, если файл был выбран ранее, а затем щелкнуло диалоговое окно файла и нажали кнопку отмены, Chrome очищает файл и запускает событие onChange.

https://code.google.com/p/chromium/issues/detail?id=2508

В этом сценарии вы можете обнаружить это, обработав событие onChange и проверивфайлы свойство.

тип ввода = код файла:

onchange="if(this.files[0]!=undefined){ UploadImg(); }else{ alert('cancel'); }"

Проблема в том, что вы никогда не знаете, какое событие будет вызвано первым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);
    };
});

я брошу свою шляпу в этот вопрос, так как я придумал новое решение. У меня есть Прогрессивное веб-приложение, которое позволяет пользователям снимать фотографии и видео и загружать их. Мы используем WebRTC, когда это возможно, но используем устройства выбора файлов HTML5 для устройств с меньшей поддержкой * кашель Safari * кашель.Если вы работаете специально над мобильным веб-приложением на базе Android / iOS, которое использует встроенную камеру для непосредственного захвата фотографий / видео, то это лучшее решение, которое мне встречалось.

Суть этой проблемы в том, что при загрузке страницыfile являетсяnull, но затем, когда пользователь открывает диалоговое окно и нажимает «Отмена»,file все ещеnullследовательно, оно не «изменилось», поэтому событие «изменение» не вызывается. Для настольных компьютеров это не так уж плохо, потому что большинство пользовательских интерфейсов не зависят от того, когда вызывается отмена, но мобильные интерфейсы, которые поднимают камеру для захвата фото / видео,очень зависит от того, когда знать, когда нажата отмена.

Я изначально использовалdocument.body.onfocus событие, чтобы определить, когда пользователь вернулся из средства выбора файлов, и это работало для большинства устройств, но iOS 11.3 прервала его, поскольку это событие не вызывается.

концепция

Мое решение - это * вздрогнуть *, чтобы измерить тактовую частоту процессора, чтобы определить, находится ли страница в данный момент на переднем плане или на заднем плане. На мобильных устройствах время обработки отводится приложению, находящемуся на переднем плане. Когда камера видна, она крадет процессорное время и депортирует браузер. Все, что нам нужно сделать, это измерить, сколько времени отводится нашей странице, когда камера запускается, наше доступное время резко сократится. Когда камера закрывается (отменяется или иным образом), наше доступное время резко возрастает.

Реализация

Мы можем измерить время процессора, используя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 будет изменение, которое вызовет соответствующее событие.

К сожалению, нет никакого официального способа создатьFileListи<input /> элемент требуетFileList в частности, и не будет принимать никаких других значений, кромеnull, Естественно,FileList объекты не могут быть построены напрямую, это связано с какой-то старой проблемой безопасности, которая, по-видимому, уже не актуальна. Единственный способ завладеть одним вне<input /> Элемент должен использовать хак, который копирует и вставляет данные, чтобы имитировать событие буфера обмена, которое может содержатьFileList объект (вы в основном фальсифицируете событие drag-and-drop-a-file-on-your-website). Это возможно в Firefox, но не для iOS Safari, поэтому он не подходит для моего конкретного случая использования.

Браузеры, пожалуйста ...

Излишне говорить, что это явно смешно. Тот факт, что веб-страницы получают нулевое уведомление об изменении критического элемента пользовательского интерфейса, просто смешен. Это действительно ошибка в спецификации, так как она никогда не предназначалась для полноэкранного пользовательского интерфейса захвата мультимедиа, и не вызывать событие "change"технически по спец.

тем не мение, пожалуйста, производители браузеров могут признать реальность этого? Это можно решить с помощью нового события «done», которое запускается, даже если никаких изменений не происходит, или вы можете просто вызвать «change» в любом случае. Да, это было бы против спецификации, но для меня тривиально дедуплировать событие изменения на стороне JavaScript, но принципиально невозможно изобрести мое собственное событие "done". Даже мое решение на самом деле просто эвристика, если не предлагают никаких гарантий о состоянии браузера.

В настоящее время этот API принципиально непригоден для мобильных устройств, и я думаю, что относительно простая смена браузера может сделать это бесконечно проще для веб-разработчиков * отходит от мыла *.

это не совсем отвечает на ваш вопрос. Я предполагаю, что у вас есть сценарий, когда вы добавляете ввод файла и запускаете выбор файла, и если пользователь нажимает кнопку отмены, вы просто удаляете ввод.

Если это так, то: Зачем добавлять пустой файл ввода?

Создайте его на лету, но добавляйте его в 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" /> на лету, привязываю его к событию изменения и затем немедленно вызываю click. Изменения будут срабатывать только тогда, когда пользователь выберет файл и нажмет Ok, в противном случае ввод не будет добавлен в DOM, поэтому не будет отправлен.

Рабочий пример здесь:https://jsfiddle.net/69g0Lxno/3/

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) {
    // ...
}

 connexo06 июн. 2018 г., 15:24
Запуск вашего фрагмента дает мнеError: { "message": "Uncaught SyntaxError: missing ) after argument list", "filename": "https://stacksnippets.net/js", "lineno": 51, "colno": 1 }

если бы оно работало на мобильном webkit, но это не так. Что я могу придумать, так это добавить слушатель события mousemove к некоторому объекту dom во время открытия окна ввода файла, например:

 $('.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 для отображения индикатора активности на начало процесса.

а также плохое в том смысле, что оно только (насколько я тестировал) работает с onfocus (требующим довольно ограниченной блокировки событий), вы можете добиться этого с помощью следующего:

document.body.onfocus = function(){ /*rock it*/ }

Что хорошо в этом, так это то, что вы можете подключить / отсоединить его вовремя с помощью события file, и это также, кажется, прекрасно работает со скрытыми вводами (определенным преимуществом, если вы используете визуальный обходной путь для дрянного ввода по умолчанию type type = ' файл'). После этого вам просто нужно выяснить, изменилось ли входное значение.

Пример:

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

 aagjalpankaj19 апр. 2017 г., 07:24
Не работает каждый раз. Пробовал на Chrome / Windows.
 John Weisz03 сент. 2017 г., 12:48
Это не работает в Firefox и Edge для меня. Тем не менее, прислушиваясь кmousemove событие наwindow.document к тому же слушатьfocus наwindow кажется, работает везде (по крайней мере, в современных браузерах, меня не волнуют крушения прошлого десятилетия). По сути, для этой задачи можно использовать любое событие взаимодействия, которое блокируется диалоговым окном открытия открытого файла.
 gabriele.genta03 февр. 2014 г., 16:57
к сожалению, это не работает в мобильном сафари
 WoodenKitty13 авг. 2016 г., 04:21
Я не хотел, чтобы событие фокусировки срабатывало каждый раз, поэтому я хотел использоватьaddEventListener("focus",fn,{once: true}), Однако я не мог заставить это стрелять вообще, используяdocument.body.addEventListener.. я не знаю почему. Вместо этого я получил тот же результат сwindow.addEventListener.
 Piotr Kowalski15 окт. 2016 г., 00:30
Он работает в FF на Ubuntu, но не на Windows. Странный...

есть ли какие-либо файлы во временной памяти. Если вы хотите получать событие изменения каждый раз, когда пользователь нажимает на ввод файла, вы можете запустить его.

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
    }
});

что это очень старый вопрос, но на случай, если он кому-то поможет, я обнаружил, что при использовании события onmousemove для обнаружения отмены необходимо было проверить два или более таких событий за короткий промежуток времени. Это произошло потому, что браузер генерирует отдельные события onmousemove (Chrome 65) каждый раз, когда курсор перемещается из диалогового окна выбора файла и каждый раз, когда он перемещается из основного окна и обратно. Простой счетчик событий перемещения мыши в сочетании с коротким тайм-аутом для сброса счетчика обратно в ноль работали.

 Filnor18 апр. 2018 г., 14:14
Первый абзац - хороший ответ, хотя его можно разбить на несколько для лучшей читаемости. Но эти две строки «SOAPBOX» делают его граничащим с неотвеченным, поскольку вопросы не входят в ответы. Можете ли вы перефразировать / перефразировать ваш ответ немного? Спасибо.

некоторые отложенные / обещающие реализации вместо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).

Но это, конечно, не надежный способ обнаружения отмененного диалога. Тем не менее, может улучшить некоторое поведение пользовательского интерфейса для вас.

 Peter14 сент. 2017 г., 10:15
Один из основных недостатков - телефоны и планшеты, они не используют мышей нормально!

и в итоге я создал очень простое решение. Можно увидеть здесь:http://jsfiddle.net/elizeubh2006/1w711q0y/5/

(Но будет работать только после первого выбора файла. Для меня это было полезно, потому что событие onchange вызывалось, даже когда пользователь нажимал кнопку отмены. Пользователь выбирал файл, затем нажимал, чтобы выбрать другой файл, но отменил и обмен назывался.)

   $("#inputFileId").on("change", function() {
 var x = document.getElementById('inputFileId');
    if(x.files.length == 0)
    {
    alert('cancel was pressed');
    }
    else
    {
        alert(x.files[0].name);
    }

});
 Trevor03 дек. 2016 г., 00:03
«будет работать только после первого выбора» << Это не совсем точно. Это не работает, например, если вы 1) Выберите, 2) Отмена, 3) Отмена. Он «обнаружит» первую отмену, но не вторую.
 Patrick Rudolph07 апр. 2015 г., 15:32
К сожалению, это не работает на iOS Safari.
 user381270303 авг. 2015 г., 14:35
«будет работать только после первого выбора файла» ->jsfiddle.net/elizeubh2006/1w711q0y/5
 Oussama Elgoumri30 июл. 2015 г., 01:01
Это не будет работать, потому что изменение вступает в силу только тогда, когда выбран файл, также выбранный файл должен отличаться от ранее выбранного файла.
function file_click() {
    document.body.onfocus = () => {
        setTimeout(_=>{
            let file_input = document.getElementById('file_input');
            if (!file_input.value) alert('please choose file ')
            else alert(file_input.value)
            document.body.onfocus = null
        },100)
    }
}

что мой ответ будет довольно устаревшим, но тем не менее. Я столкнулся с той же проблемой. Итак, вот мое решение. Самый полезный код был взломан 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);
});

если выберете тот же файл, что и ранее, и нажмете «Отмена»: в этом случае.

Вы можете сделать это так:

<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>
 VPK20 мар. 2013 г., 12:03
Thnkx @loveJs этот пост действительно помог мне.
 Tiago Peres França08 нояб. 2013 г., 14:27
Не совсем, если пользователь выбирает тот же файл, это не отмена = (
 Chris06 дек. 2017 г., 15:07
@CodeGems разрешено программно устанавливать input.value в пустую строку. Но вы правы, что установка любого другого значения недопустима.
 Chris06 дек. 2017 г., 02:53
Вы можете очистить выбор ввода (input.value = '') после того, как обнаружите первое изменение, чтобы сработал второй раз, даже если пользователь снова выбирает тот же файл.
 Shane13 февр. 2014 г., 01:04
onchange срабатывает только в том случае, если произошли изменения. Поэтому, если файл совпадает с предыдущим, прослушиватель onchange не будет запускаться.

но вот рабочий пример моего решения, чтобы определить, загрузил ли пользователь файл, и разрешить ему продолжить, только если он загрузил файл.

В основном скрыть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 многое из этого - сделать сайт и кнопку доступными для всех. Стилизуйте свою кнопку на то, что вам нравится.

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 focusIn всплывает до документа в обоих случаях, помогая нам избежать таких ситуаций. Единственное ограничение - блокирование события focusIn.

 Ferdinand Prantl18 февр. 2017 г., 00:09
Я поймалmousemove событие наdocument во время выбора файлов в диалоге ОС в Chrome 56.0.2924.87 на Ubuntu 16.10. Нет проблем, когда вы не двигаете мышь или используете только клавиатуру для выбора файла. Я должен был заменитьmousemove поkeydown обнаруживать отмену как можно раньше, но не «слишком рано», когда диалог все еще был открыт.

ть значение отмены или закрытия окна загрузки пользователем по значению поля.

вот пример:

//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
    }
});

Результат диалогового окна файла не отображается в браузере.

 Ppp13 янв. 2011 г., 15:34
Можно ли проверить, открыт ли переключатель файлов?
 Trevor01 дек. 2016 г., 23:24
Msgstr "Результат диалогового окна файла не отображается браузеру." Это не так, если диалог закрывается путем выбора файла.
 Patrick Roberts13 июл. 2018 г., 20:41
Кроме того, если файл уже выбран, и вы снова выбираете тот же файл, нетchange событие отправлено для этого либо.
 Oded13 янв. 2011 г., 15:35
@Ppp - Нет. Браузер не говорит вам этого.
 John Weisz18 авг. 2017 г., 12:52
менять Вызванный с помощью файла диалог открывается браузером. Смотрите, если файл не выбран, и файл не выбран впоследствии, то ничего не изменилось, поэтому нетchange событие отправлено.

// Используем hover вместо blur

var fileInput = $("#fileInput");

if (fileInput.

Я нашел этот атрибут, его самый простой из всех.

if ($('#selectedFile')[0].files.length > 1)
{
   // Clicked on 'open' with file
} else {
   // Clicked on 'cancel'
}

Вот,selectedFile являетсяinput type=file.

 Bron Thulke03 нояб. 2017 г., 02:06
Это хорошее решение для меня, за исключением того, что оно должно быть> = 1

Следуя примеру Шибое, вот пример 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

 barrypicker15 мар. 2018 г., 03:38
Ваша скрипка у меня не сработала - с помощью Firefox 58.0.2
 Benoit Blanchon21 июн. 2016 г., 16:33
Я тестировал на Chrome 51, он не работает при первом выборе файлов. Решение состоит в том, чтобы добавить задержку:jsfiddle.net/7jfbmunh
/* 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 */
    }
});
 mix3d19 июн. 2017 г., 21:16
Я могу сказать, после некоторого кросс-браузерного тестирования, что Firefox не запускает событие изменения при отмене, а также не очищает существующие файлы, выбранные при повторном открытии и повторном нажатии на кнопку отмены. Странно, а?
 Rizky K.24 янв. 2017 г., 13:23
Насколько я помню, когда я писал этот ответ, если пользователь выбирает файл, а затем повторно выбирает файл (но затем отменяет его), он будет рассматриваться как не выбранный файл, я использую только оповещение для переменной selected_file_name, чтобы проверить его. во всяком случае, с тех пор больше не проверял.
 jayarjo11 дек. 2016 г., 10:43
Вы проверили, если вашelse заявление когда-либо оценивается?

fileполе типа, к сожалению, не реагирует на множество событий (размытие было бы прекрасно). Я вижу много людей, предлагающихchange-ориентированные решения и их снижение.

change работает, но у него есть большой недостаток (против того, что мыхотеть случаться).

Когда вы заново загрузите страницу, содержащую поле файла, откройте окно и нажмите «Отмена». Ничего, к сожалению,изменения.

То, что я решил сделать, это загрузить в закрытом состоянии.

Следующая часть формыsection#after-image в моем случае это скрыто от глаз. Когда мойfile field изменения, кнопка загрузки отображается. После успешной загрузки,section#after-image Показано.Если пользователь загружает, открывает файл-диалог, а затем отменяет, они никогда не видят кнопку загрузки.Если пользователь выбирает файл, отображается кнопка загрузки. Если они затем откроют диалоговое окно и отменить,change событие отменяется этой отменой, и там я могу (и могу) повторно скрыть свою кнопку загрузки, пока не будет выбран правильный файл.

Мне повезло, что это закрытое состояние уже было дизайном моей формы. Вам не нужно использовать один и тот же стиль, просто сначала скрыв кнопку загрузки и после изменения, установив скрытое поле или переменную javascript в то, что вы можете отслеживать при отправке.

Я попытался изменить значение файла [0] до того, как поле было взаимодействовать с. Это ничего не сделало в отношении обмена.

Так да,change работает, по крайней мере, так хорошо, как мы собираемся получить. Поле файла защищено по понятным причинам, но к разочарованию благонамеренных разработчиков.

Это не соответствует моей цели, но вы можетеonclickзагрузить предупреждение (неalert(), потому что это останавливает обработку страницы), и скрыть его, если изменение вызвано, и файлы [0] равны нулю. Если изменение не вызвано, div остается в своем состоянии.

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, так как не запускает событие Focus.

когда пользователи выбирали изображения.

Это то, что я придумаю:

$(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. Примите эту информацию во внимание, если вы хотите ее реализовать.

input элемент должен потерять фокус акаblur, Предполагая начальныйvalue изinput пусто, любое непустое значение в вашемblur Обработчик будет указывать ОК, а пустое значение будет означать Отмена.

ОБНОВЛЕНИЕ:blur не срабатывает, когдаinput скрыт. Поэтому нельзя использовать этот трюк с загрузками на основе IFRAME, если вы не хотите временно отображатьinput.

 Qwertiy27 дек. 2017 г., 18:55
Это не работает - размытие на входе срабатывает сразу после щелчка. Chrome 63.0.3239.84 x64 на Win7.
 Blaise03 янв. 2012 г., 13:21
В бета-версии Firefox 10 и Chrome 16blur не срабатывает при выборе файла. Не пробовал в других браузерах.

Ваш ответ на вопрос