Как определить, когда нажатие на файл нажата на ввод файла?

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

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

Ответ 1

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

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

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

Пример:

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

Ответ 2

Вы не можете.

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

Вы можете сделать это следующим образом:

<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>

Ответ 6

Просто прослушайте событие click.

Следуя примеру 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

Ответ 7

Решение Shiboe было бы хорошим, если бы оно работало на мобильном 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 для индикатора активности отображается в начале процесса.

Ответ 8

Большинство из этих решений не работают для меня.

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

Ответ 9

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

Вот что я поднимаю:

$(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 получил фокус назад, поэтому я слушаю это событие.

UPDATE

Я обнаружил, что это не работает в safari и poltergeist/phantomjs. Учитывайте эту информацию, если вы хотите ее реализовать.

Ответ 10

Объединяя решения 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 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 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.

Ответ 11

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

Кроме того, основным создателем проблем был тот факт, что событие "change" не происходит сразу после фокуса, поэтому нам нужно подождать некоторое время.

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

Ответ 12

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

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

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

Ответ 13

Существует хакерский способ сделать это (добавьте обратные вызовы или разрешите выполнение отложенных/обещаний вместо вызовов 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).

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

Ответ 14

Вот мое решение, используя фокус ввода файла (не используя таймеры)

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

Ответ 15

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

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

Ответ 16

Кажется, что для меня работает (на рабочем столе, в окнах):

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.

Ответ 17

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

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

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

То, что я выбрал, - это загрузка в закрытом состоянии.

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

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

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

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

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

Ответ 18

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

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

Здесь selectedFile является input type=file.

Ответ 19

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

вот пример:

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

Ответ 20

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

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

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

});

Ответ 21

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

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