В JavaScript можно ли программно запустить событие «щелчка» для элемента ввода файла?


261

Я бы хотел, чтобы событие щелчка вызывало <input type="file">метку программно.

Просто вызов click () ничего не делает или, по крайней мере, не вызывает диалог выбора файла.

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


1
Событие click, которое вы запускаете, должно вызываться в событии click, запущенном пользователем, иначе оно не будет работать.
Умагон

Ответы:


79

Вы не можете делать , что во всех браузерах, предположительно IE это позволить, но Mozilla и Opera нет.

Когда вы создаете сообщение в GMail, функция «прикрепить файлы» реализуется одним способом для IE и любого браузера, который поддерживает это, а затем реализует другой способ для Firefox и тех браузеров, которые этого не делают.

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


1
Убирайся. Ну, я, конечно, понимаю, что это эксплуатируется. Это где-нибудь задокументировано? Я думаю, это будет реализовано каждым браузером?
user28655

Обновлен мой ответ, чтобы он был более правильным, чем предыдущий ответ - суть та же, но уточнение должно немного помочь. Этот парень столкнулся с той же проблемой: bytes.com/forum/thread542877.html
Джейсон Бантинг

Слава Богу, FF5 позволяет этот клик
rshimoda

2
Чтобы уточнить выше комментарий: Chrome недавно изменен, чтобы проверить, inputвидим ли элемент файла . Запуск clickметода работает, в том числе и в консоли, если элемент виден.
jwadsack

2
@ Отважный - чувак, этому ответу (тот, который ты говоришь неправильно) 10 лет - не удивительно, что он не правильный! (Я не знаю точно, я верю вашему слову за это). : P
Джейсон Бантинг

257

Я искал решение для всего этого дня. И вот выводы, которые я сделал:

  1. По соображениям безопасности Opera и Firefox не позволяют запускать ввод файла.
  2. Единственная удобная альтернатива - создать «скрытый» ввод файла (используя непрозрачность, а не «скрытый» или «показ: нет»!) И затем создать кнопку «под» ним. Таким образом, кнопка видна, но при щелчке пользователя она фактически активирует ввод файла.

Надеюсь это поможет! :)

<div style="display: block; width: 100px; height: 20px; overflow: hidden;">
<button style="width: 110px; height: 30px; position: relative; top: -5px; left: -5px;"><a href="javascript: void(0)">Upload File</a></button>
<input type="file" id="upload_input" name="upload" style="font-size: 50px; width: 120px; opacity: 0; filter:alpha(opacity=0);  position: relative; top: -40px;; left: -20px" />
</div>

6
это решение прекрасно работает. Не уверен, почему это упустили из виду и не повысили. Это не совсем то, о чем спрашивает вопрос, но это отличная работа. Вы обнаружили, что он несовместим с любыми браузерами? У меня нет времени, чтобы пройтись по всем 10+ вкусам соответствующих тестов.
Евгений Симкин

1
Спасибо за этот ответ, это
круто

Хорошее решение. Работает на мобильном телефоне Android тоже.
Gstroup

1
Это не правда, см. Ответ Дидье ниже. Программный щелчок должен происходить из контекста действия пользователя - как в обработчике щелчка другой кнопки. Тогда он работает нормально, нет необходимости иметь элемент переполнения.
Smok

1
Единственная проблема в том, что если вы хотите изменить стиль кнопки при наведении, вы не сможете. Это означает, что если вы хотите, чтобы он выглядел как все остальные кнопки в вашем приложении, вы не можете.
Винсент

68

Вы можете запустить click () в любом браузере, но в некоторых браузерах этот элемент должен быть видимым и сфокусированным. Вот пример jQuery:

$('#input_element').show();
$('#input_element').focus();
$('#input_element').click();
$('#input_element').hide();

Он работает с Hide раньше, click()но я не знаю, работает ли он без вызова метода show. Никогда не пробовал это на Opera, я тестировал на IE / FF / Safari / Chrome, и это работает. Я надеюсь, это поможет.


51
Спасибо, что поделился. На всякий случай, если вы не знали - вы можете использовать цепочку в jQuery: $(...).show().focus().click().hide();:)
pimvdb

1
@pimvdb: насколько я тестирую, ваше решение работает только в Chrome.
Hoàng Long

1
@ Hoàng Long: Вы имеете в виду решение о цепочках или Florin Mogos? Я не верю, что создание цепочек приведет к каким-либо различиям между браузерами
pimvdb

1
@ HoàngLong Это работает для меня в IE 8 и 9, последних версиях Chrome, Safari и Firefox.
Сами Самхури

2
Странный. Как я тестировал, он не работает под Chrome в Ubuntu.
sandrew

29

ЭТО ВОЗМОЖНО: под FF4 +, Opera ?, Chrome: но:

  1. inputElement.click()должен вызываться из контекста действий пользователя! (не контекст выполнения скрипта)

  2. <input type="file" />должно быть видно ( inputElement.style.display !== 'none') (вы можете скрыть это с помощью видимости или чего-то другого, но не с помощью свойства "display")


Это решило это для меня. Мне пришлось добавить javascript к onclickатрибуту вместо привязки к событию.
jasonlfunk

1
Upvoting единственное разумное решение. Метод переполнения ужасен.
Smok

Ха! Я знал, что это должно быть что-то в контексте! Я заметил, что вызов inputElement.click()из события keydown (ярлык для прикрепления файла) работает, но вызов из-за тайм-аута или обратного вызова ajax не сработал. Upvoted.
brettjonesdev

9
Кстати, у кого-нибудь есть дополнительные ресурсы по «контексту действий пользователя» по сравнению с «контекстом выполнения скрипта»? Все, что я вижу при поиске, связано с контекстом выполнения и this. : /
brettjonesdev

@bretjonesdev Я думаю, это означает, что его нужно выполнять внутри обработчика событий, инициированного пользователем, например, обработчик события click, вместо обещания, тайм-аута или любого другого события, не инициированного пользователем.
Алекс Герра

10

Для тех, кто понимает, что вам нужно наложить невидимую форму на ссылку, но лень писать, я написал ее для вас. Ну, для меня, но может также поделиться. Комментарии приветствуются.

HTML (где-то):

<a id="fileLink" href="javascript:fileBrowse();" onmouseover="fileMove();">File Browse</a>

HTML (где вам все равно):

<div id="uploadForm" style="filter:alpha(opacity=0); opacity: 0.0; width: 300px; cursor: pointer;">
    <form method="POST" enctype="multipart/form-data">
        <input type="file" name="file" />
    </form>
</div>

JavaScript:

function pageY(el) {
    var ot = 0;
    while (el && el.offsetParent != el) {
        ot += el.offsetTop ? el.offsetTop : 0;
        el = el.offsetParent;
    }
    return ot;
}

function pageX(el) {
    var ol = 0;
    while (el && el.offsetParent != el) {
        ol += el.offsetLeft ? el.offsetLeft : 0;
        el = el.offsetParent;
    }
    return ol;
}

function fileMove() {
    if (navigator.appName == "Microsoft Internet Explorer") {
        return; // Don't need to do this in IE. 
    }
    var link = document.getElementById("fileLink");
    var form = document.getElementById("uploadForm");
    var x = pageX(link);
    var y = pageY(link);
    form.style.position = 'absolute';
    form.style.left = x + 'px';
    form.style.top = y + 'px';
}

function fileBrowse() {
    // This works in IE only. Doesn't do jack in FF. :( 
    var browseField = document.getElementById("uploadForm").file;
    browseField.click();
}



7

Если вы хотите, чтобы clickметод работал в Chrome, Firefox и т. Д., Примените следующий стиль к своему входному файлу. Это будет совершенно скрыто, как будто вы делаетеdisplay: none;

#fileInput {
    visibility: hidden;
    position: absolute;
    top: 0;
    left: -5000px;
}

Это так просто, я проверил это работает!


Мне больше нравится этот способ, так как некоторые старые браузеры ничего не будут делать с inputElement.click (), если он скрыт.
Ник

Почему бы просто не установить heightи widthдо 0?
Соломон Уцко

5
$(document).one('mousemove', function() { $(element).trigger('click') } );

Работал на меня, когда столкнулся с подобной проблемой, это обычный eRube Goldberg.


4

РАБОЧЕЕ РЕШЕНИЕ

Позвольте мне добавить к этому старому посту рабочее решение, которое я использовал, которое работает, вероятно, в 80% и более браузеров, как новых, так и старых.

Решение сложное, но простое. Первый шаг - использовать CSS и скрыть тип входного файла с «недоэлементами», которые видны сквозь, поскольку у него непрозрачность 0. Следующий шаг - использовать JavaScript для обновления своей метки по мере необходимости.

HTML Идентификаторы просто вставляются, если вам нужен быстрый способ доступа к конкретному элементу, однако классы необходимы, поскольку они связаны с CSS, который устанавливает весь этот процесс

<div class="file-input wrapper">
    <input id="inpFile0" type="file" class="file-input control" />
    <div class="file-input content">
        <label id="inpFileOutput0" for="inpFileButton" class="file-input output">Click Here</label>
        <input id="inpFileButton0" type="button" class="file-input button" value="Select File" />
    </div>
</div>

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

.file-test-area {
    border: 1px solid;
    margin: .5em;
    padding: 1em;
}
.file-input {
    cursor: pointer !important;
}
.file-input * {
    cursor: pointer !important;
    display: inline-block;
}
.file-input.wrapper {
    display: inline-block;
    font-size: 14px;
    height: auto;
    overflow: hidden;
    position: relative;
    width: auto;
}
.file-input.control {
    -moz-opacity:0 ;
    filter:alpha(opacity: 0);
    opacity: 0;

    height: 100%;
    position: absolute;
    text-align: right;
    width: 100%;
    z-index: 2;
}
.file-input.content {
    position: relative;
    top: 0px;
    left: 0px;
    z-index: 1;
}
.file-input.output {
    background-color: #FFC;
    font-size: .8em;
    padding: .2em .2em .2em .4em;
    text-align: center;
    width: 10em;
}
.file-input.button {
    border: none;
    font-weight: bold;
    margin-left: .25em;
    padding: 0 .25em;
}

JavaScript Чистый и верный, однако, некоторые старые (вышедшие из употребления) браузеры могут все еще иметь проблемы с ним (например, Netscrape 2!)

var inp = document.getElementsByTagName('input');
for (var i=0;i<inp.length;i++) {
    if (inp[i].type != 'file') continue;
    inp[i].relatedElement = inp[i].parentNode.getElementsByTagName('label')[0];
    inp[i].onchange /*= inp[i].onmouseout*/ = function () {
        this.relatedElement.innerHTML = this.value;
    };
};

Рабочий пример jsFiddle


4

Оно работает :

По соображениям безопасности в Firefox и Opera вы не можете выполнить щелчок при вводе файла, но вы можете смоделировать с помощью MouseEvents:

<script>
click=function(element){
    if(element!=null){
        try {element.click();}
        catch(e) {
            var evt = document.createEvent("MouseEvents");
            evt.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,0,null);
            element.dispatchEvent(evt);
            }
        }
    };
</script>

<input type="button" value="upload" onclick="click(document.getElementById('inputFile'));"><input type="file" id="inputFile" style="display:none">

1
Обратите внимание, что createEvent()и initMouseEvent()теперь устарели.
Алексис Уилке

4

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

Тем не менее, на сегодняшний день fileInput.click () работает в текущем Chrome (36.0.1985.125 м) и текущем Firefox ESR (24.7.0), но не в текущем IE (11.0.9600.17207). Наложение поля файла с непрозрачностью 0 поверх кнопки работает, но я хотел, чтобы элемент ссылки был видимым триггером, а подчеркивание при наведении курсора не вполне работает ни в одном браузере. Он мигает, а затем исчезает, вероятно, браузер выясняет, действительно ли применяется стиль наведения мыши или нет.

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

Все просто: поместите поле ввода файла за пределы экрана (позиция: абсолютная; верх: -5000px), поместите элемент метки вокруг него и запустите щелчок на метке вместо самого поля файла.

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

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


Хорошо, на теге кнопки onclick = "filetag.click ()" не работает с IE 9 и 10 (но работает с IE 11, Firefox 4/10/26/27/28, Chrome / Chromium 31/32/33 / 36, Сафари 7, Опера 23). Но если вы используете метку для = "id-of-file-input" (без onlick), она работает для IE 9/10/11.
luigifab

4

JS Fiddle: http://jsfiddle.net/eyedean/1bw357kw/

popFileSelector = function() {
    var el = document.getElementById("fileElem");
    if (el) {
        el.click();  
    }
};

window.popRightAway = function() {
    document.getElementById('log').innerHTML += 'I am right away!<br />';
    popFileSelector();
};

window.popWithDelay = function() {
    document.getElementById('log').innerHTML += 'I am gonna delay!<br />';
    window.setTimeout(function() {
        document.getElementById('log').innerHTML += 'I was delayed!<br />';
        popFileSelector();
    }, 1000);
};
<body>
  <form>
      <input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)" />
  </form>
  <a onclick="popRightAway()" href="#">Pop Now</a>
    <br />
  <a onclick="popWithDelay()" href="#">Pop With 1 Second Delay</a>
    <div id="log">Log: <br /></div>
</body>


3

Этот код работает для меня. Это то, что вы пытаетесь сделать?

<input type="file" style="position:absolute;left:-999px;" id="fileinput" />
<button  id="addfiles" >Add files</button>

<script language="javascript" type="text/javascript">
   $("#addfiles").click(function(){
      $("#fileinput").click();
   });
</script>

3

Мое решение для Safari с jQuery и jQuery-ui:

$("<input type='file' class='ui-helper-hidden-accessible' />").appendTo("body").focus().trigger('click');

Heads: не работает для Firefox 33, Chrome 38. Триггер («щелчок») может работать только в контексте события взаимодействия с пользователем - обработчики событий.
Амит Г

3

Вот чистое решение этой проблемы на JavaScript. Хорошо работает во всех браузерах

<script>
    function upload_image_init(){
        var elem = document.getElementById('file');
        if(elem && document.createEvent) {
           var evt = document.createEvent("MouseEvents");
           evt.initEvent("click", true, false);
           elem.dispatchEvent(evt);
        }
    }
</script>

2

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

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

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

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


2

Я исследовал это некоторое время назад, потому что я хотел создать пользовательскую кнопку, которая открывала бы диалог файла и немедленно начинала загрузку. Я только что заметил кое-что, что могло бы сделать это возможным - Firefox, кажется, открывает диалоговое окно, когда вы щелкаете в любом месте загрузки. Таким образом, следующее может сделать это:

  1. Создайте файл загрузки и отдельный элемент, содержащий изображение, которое вы хотите использовать в качестве кнопки
  2. Расположите их так, чтобы они перекрывали друг друга, и сделайте фон файла и границы прозрачными, чтобы кнопка была единственной видимой
  3. Добавьте JavaScript, чтобы IE открывал диалоговое окно при нажатии кнопки / файла.
  4. Используйте событие onchange для отправки формы при выборе файла

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


2

У меня был <input type="button">тег, скрытый от глаз. Я прикрепил "onClick"событие к любому видимому компоненту любого типа, например к метке. Это было сделано с помощью инструментов разработчика Google Chrome или Firebug Mozilla Firefox с помощью правой кнопки мыши «изменить HTML». В этом случае укажите следующий скрипт или что-то подобное:

Если у вас есть JQuery:

$('#id_of_component').click();

если не:

document.getElementById('id_of_component').click();

Спасибо.


2

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

$scope.getSingleInvoicePDF = function(invoiceNumberEntity) {
   var fileName = invoiceNumberEntity + ".pdf";
   var pdfDownload = document.createElement("a");
   document.body.appendChild(pdfDownload);

   AngularWebService.getFileWithSuffix("ezbillpdfget",invoiceNumberEntity,"pdf" ).then(function(returnedJSON) {
       var fileBlob = new Blob([returnedJSON.data], {type: 'application/pdf'});
       if (navigator.appVersion.toString().indexOf('.NET') > 0) { // for IE browser
           window.navigator.msSaveBlob(fileBlob, fileName);
       } else { // for other browsers
           var fileURL = window.URL.createObjectURL(fileBlob);
           pdfDownload.href = fileURL;
           pdfDownload.download = fileName;
           pdfDownload.click();      
       }
   });
};

Для AngularJS или даже для обычного JavaScript.


1

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


2
На самом деле Firefox4 значительно улучшает состояние загрузки файлов. Моя проблема в том, как сделать то же самое в браузере Google Chrome.
erick2red

1

Вот решение, которое работает для меня: CSS:

#uploadtruefield {
    left: 225px;
    opacity: 0;
    position: absolute;
    right: 0;
    top: 266px;
    opacity:0;
    -moz-opacity:0;
    filter:alpha(opacity:0);
    width: 270px;
    z-index: 2;
}

.uploadmask {
    background:url(../img/browse.gif) no-repeat 100% 50%;
}
#uploadmaskfield{
    width:132px;
}

HTML с «маленькой» справкой JQuery:

<div class="uploadmask">
    <input id="uploadmaskfield" type="text" name="uploadmaskfield">
</div>
<input id="uploadtruefield"  type="file" onchange="$('#uploadmaskfield').val(this.value)" >

Просто убедитесь, что maskfied полностью покрыт полем загрузки.



1

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


1

Надеюсь, это кому-то поможет - я провел 2 часа, стуча головой об это:

В IE8 или IE9, если вы вообще инициируете открытие ввода файла с помощью javascript (поверьте мне, я пробовал их все), это не позволит вам отправить форму с использованием javascript, просто произойдет сбой в молчании.

Отправка формы с помощью обычной кнопки отправки может работать, но вызов form.submit (); молча провалится.

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


Кроме того, вы можете обернуть файл ввода в метку, чтобы в IE вы могли получить кликабельную область метки, чтобы покрыть всю область кнопки, тогда как с помощью всего лишь тега ввода файла, только половина из них активна в IE.
Галатам

1

Это сработало для меня:

<script>
    function sel_file() {
        $("input[name=userfile]").trigger('click');
    }  
</script>

<input type="file" name="userfile" id="userfile" />

<a href="javascript:sel_file();">Click</a>

1

это не невозможно

var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);  
setTimeout(function(){ document.getElementById('input_field_id').dispatchEvent(evObj); },100);

Но так или иначе это работает, только если это находится в функции, которая была вызвана через событие click.

Таким образом, вы можете иметь следующую настройку:

HTML:

<div onclick="openFileChooser()" class="some_fancy_stuff">Click here to open image chooser</div>
<input type="file" id="input_img">

JavaScript:

    function openFileChooser() {
      var evObj = document.createEvent('MouseEvents');
      evObj.initMouseEvent('click', true, true, window);  
      setTimeout(function()
      { 
        document.getElementById('input_img').dispatchEvent(evObj);      
      },100);      
    }

createEvent()И initMouseEvent()были устаревшими. Вы должны использовать CustomEvent()сейчас ...
Алексис Уилк

0

Ты можешь использовать

<button id="file">select file</button>
<input type="file" name="file" id="file_input" style="display:none;">
<script>
$('#file').click(function() {
        $('#file_input').focus().trigger('click');
    });
</script>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.