In JavaScript posso fare in modo che un evento "clic" venga attivato a livello di codice per un elemento di input file?


261

Vorrei che un evento clic si attivi su un <input type="file">tag a livello di codice.

Basta chiamare click () non sembra fare nulla o almeno non appare una finestra di dialogo per la selezione dei file.

Ho sperimentato l'acquisizione di eventi utilizzando gli ascoltatori e il reindirizzamento dell'evento, ma non sono stato in grado di farlo per eseguire effettivamente l'evento come qualcuno ha cliccato su di esso.


1
L'evento click che attivi deve essere chiamato all'interno di un evento click avviato dall'utente, altrimenti non funzionerà.
Umagon,

Risposte:


79

Non puoi farlo in tutti i browser, presumibilmente IE lo consente, ma Mozilla e Opera non lo fanno.

Quando componi un messaggio in GMail, la funzione 'allega file' viene implementata in un modo per IE e per qualsiasi browser che lo supporta, e quindi implementata in un altro modo per Firefox e quei browser che non lo fanno.

Non so perché non puoi farlo, ma una cosa che rappresenta un rischio per la sicurezza e che non ti è permesso fare in nessun browser è impostare programmaticamente il nome del file sull'elemento File HTML.


1
Drat. Beh, certamente capisco che è sfruttabile. Questo è documentato ovunque? Immagino che sarebbe implementato da ciascun browser?
user28655,

La mia risposta è stata aggiornata per essere più corretta della risposta precedente: l'essenza è la stessa, ma il chiarimento dovrebbe aiutare un po '. Questo ragazzo ha riscontrato
Jason Bunting,

Grazie a Dio FF5 consente questo clic
rshimoda

2
Per chiarire il commento sopra: Chrome è stato recentemente modificato per verificare se l' inputelemento del file è visibile. L'attivazione del clickmetodo funziona, anche nella console, se l'elemento è visibile.
jwadsack,

2
@Otvazhnii - amico, questa risposta (quella che stai dicendo è sbagliata) ha 10 anni - nessuna sorpresa non è corretta! (Non lo so per certo, sto prendendo in considerazione la tua parola). : P
Jason Bunting,

257

Ho cercato una soluzione per tutto il giorno. E queste sono le conclusioni che ho fatto:

  1. Per motivi di sicurezza, Opera e Firefox non consentono di attivare l'input di file.
  2. L'unica alternativa conveniente è quella di creare un input di file "nascosto" (usando l'opacità, non "nascosto" o "display: none"!) E successivamente creare il pulsante "sotto". In questo modo il pulsante viene visualizzato ma al clic dell'utente attiva effettivamente l'input del file.

Spero che questo ti aiuti! :)

<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
questa soluzione funziona alla grande. Non sono sicuro del motivo per cui è stato trascurato e non aggiornato. Non è * esattamente quello che la domanda chiede, ma è un ottimo modo per aggirare. Hai trovato incompatibile con qualsiasi browser? Non ho il tempo di sfogliare tutti i 10+ gusti di quelli rilevanti su cui testare.
Evgenij Simkin,

1
Grazie per questa risposta, è fantastico: D
mario.tco,

Bella soluzione. Funziona anche su browser mobile Android.
gstroup,

1
Questo non è vero, vedi la risposta di Didier di seguito. Il clic programmatico deve provenire dal contesto dell'azione dell'utente, come nel gestore di clic di un altro pulsante. Quindi funziona benissimo, non è necessario avere l'elemento di overflow.
Fumò il

1
L'unico problema è che se si desidera modificare lo stile del pulsante al passaggio del mouse, non è possibile. Ciò significa che se vuoi che assomigli a tutti gli altri pulsanti della tua app, non puoi.
Vincent,

68

Puoi attivare click () su qualsiasi browser ma alcuni browser richiedono che l'elemento sia visibile e focalizzato. Ecco un esempio di jQuery:

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

Funziona con hide prima del click()ma non so se funziona senza chiamare il metodo show. Non l'ho mai provato su Opera, ho provato su IE / FF / Safari / Chrome e funziona. Spero che questo possa aiutare.


51
Grazie per la condivisione. Nel caso in cui non lo sapessi, puoi usare il concatenamento in jQuery: $(...).show().focus().click().hide();:)
pimvdb

1
@pimvdb: per quanto ho testato, la tua soluzione funziona solo su Chrome.
Hoàng Long,

1
@ Hoàng Long: Intendi la soluzione concatenata o Florin Mogos? Non credo che il concatenamento farebbe differenze tra i browser.
pimvdb,

1
@ HoàngLong Funziona per me in IE 8 e 9, Chrome, Safari e Firefox più recenti.
Sami Samhuri,

2
Strano. Come ho testato, non funziona con Chrome in Ubuntu.
Sandrew

29

QUESTO È POSSIBILE: Sotto FF4 +, Opera?, Chrome: ma:

  1. inputElement.click()dovrebbe essere chiamato dal contesto di azione dell'utente! (non contesto di esecuzione dello script)

  2. <input type="file" />dovrebbe essere visibile ( inputElement.style.display !== 'none') (puoi nasconderlo con visibilità o qualcos'altro, ma non "visualizzare" la proprietà)


Questo mi ha risolto. Ho dovuto aggiungere il javascript onclickall'attributo invece di associarlo all'evento.
Jasonlfunk,

1
Valorizzare l'unica soluzione ragionevole. Il metodo di overflow è brutto.
Fumò il

Ha! Sapevo che doveva essere qualcosa con il contesto! Avevo osservato che la chiamata inputElement.click()dall'interno di un evento keydown (scorciatoia per allegare un file) funzionava, ma chiamarla in timeout o ajax callback NON funzionava. Upvoted.
Brettjonesdev,

9
A proposito qualcuno ha ulteriori risorse sul "contesto di azione dell'utente" rispetto al "contesto di esecuzione dello script"? Tutto ciò che vedo durante la ricerca ha a che fare con il contesto di esecuzione e this. : /
brettjonesdev

@bretjonesdev Penso che ciò significhi che deve essere eseguito all'interno di un gestore eventi avviato dall'utente, come un gestore eventi click, rispetto a una promessa, un timeout o qualsiasi altro evento non avviato dall'utente.
Alex Guerra,

10

Per coloro che capiscono che devi sovrapporre una forma invisibile al link, ma sei troppo pigro per scrivere, l'ho scritto per te. Bene, per me, ma potrebbe anche condividere. I commenti sono ben accetti

HTML (da qualche parte):

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

HTML (da qualche parte che non ti interessa):

<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

Se vuoi che il clickmetodo funzioni su Chrome, Firefox, ecc., Applica il seguente stile al tuo file di input. Sarà perfettamente nascosto, è come se lo facessidisplay: none;

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

È così semplice, ho provato che funziona!


Mi piace in questo modo il migliore dato che alcuni browser meno recenti non faranno nulla su inputElement.click () se è nascosto.
Nick,

Perché non è sufficiente impostare la heighte widthper 0?
Solomon Ucko,

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

Ha funzionato per me quando mi sono imbattuto in un problema simile, è un eRube Goldberg normale.


4

SOLUZIONE DI LAVORO

Permettetemi di aggiungere a questo vecchio post, una soluzione funzionante che ho usato che funziona probabilmente nell'80% o più di tutti i browser sia nuovi che vecchi.

La soluzione è complessa ma semplice. Il primo passo è usare CSS e indovinare il tipo di file di input con "under-elements" che mostrano come ha un'opacità di 0. Il passo successivo è usare JavaScript per aggiornare la sua etichetta secondo necessità.

HTML Gli ID vengono semplicemente inseriti se si desidera un modo rapido per accedere a un elemento specifico, tuttavia le classi sono un must in quanto si riferiscono al CSS che imposta l'intero processo

<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 Tieni presente che la colorazione e gli stili di carattere e simili sono totalmente le tue preferenze, se usi questo CSS di base, puoi sempre usare il mark-up after-end per lo stile come preferisci, questo è mostrato nel jsFiddle elencato alla fine.

.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 Puro e vero, tuttavia, alcuni browser OLDER (ritirati) potrebbero ancora avere problemi con esso (come 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;
    };
};

Esempio di jsFiddle funzionante


4

Funziona :

Per motivi di sicurezza su Firefox e Opera, non è possibile attivare il clic sull'input del file, ma è possibile simulare con 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
Si noti che createEvent()e initMouseEvent()sono ora obsoleti.
Alexis Wilke,

4

So che questo è vecchio e tutte queste soluzioni sono trucchi per le precauzioni di sicurezza del browser con un valore reale.

Detto questo, ad oggi, fileInput.click () funziona nell'attuale Chrome (36.0.1985.125 m) e nell'ESR Firefox attuale (24.7.0), ma non nell'IE I corrente (11.0.9600.17207). La sovrapposizione di un campo file con l'opacità 0 sopra un pulsante funziona, ma volevo un elemento di collegamento come trigger visibile e il passaggio del mouse sopra non funziona in nessun browser. Si accende e poi scompare, probabilmente il browser pensa se lo stile hover si applica o meno.

Ma ho trovato una soluzione che funziona in tutti quei browser. Non pretenderò di aver testato ogni versione di ogni browser o di sapere che continuerà a funzionare per sempre, ma sembra soddisfare le mie esigenze ora.

È semplice: posiziona il campo di input del file fuori dallo schermo (posizione: assoluto; in alto: -5000px), metti un elemento etichetta attorno ad esso e attiva il clic sull'etichetta, invece del campo file stesso.

Nota che per chiamare il metodo click dell'etichetta è necessario che il link sia scritto, non lo fa automaticamente, come quando fai clic sul testo all'interno di un elemento label. Apparentemente l'elemento link cattura il clic e non riesce a raggiungere l'etichetta.

Si noti inoltre che ciò non fornisce un modo per mostrare il file attualmente selezionato, poiché il campo è fuori schermo. Volevo inviare immediatamente quando è stato selezionato un file, quindi non è un problema per me, ma avrai bisogno di un approccio un po 'diverso se la tua situazione è diversa.


Ok, sul tag del pulsante, onclick = "filetag.click ()" non funziona con IE 9 e 10 (ma funziona con IE 11, Firefox 4/10/26/27/28, Chrome / Chromium 31/32/33 / 36, Safari 7, Opera 23). Ma, se usi un'etichetta per = "id-of-file-input" (senza onlick), funziona per 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

Questo codice funziona per me. È questo che stai cercando di fare?

<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

La mia soluzione per Safari con jQuery e jQuery-ui:

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

heads up: non funziona con firefox 33, chrome 38. trigger ('click') può funzionare solo all'interno del contesto dell'evento di interazione dell'utente - gestori di eventi.
Amit G

3

Ecco la pura soluzione JavaScript a questo problema. Funziona bene su tutti i browser

<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

Esistono modi per reindirizzare gli eventi al controllo ma non aspettarti di essere in grado di eseguire facilmente gli eventi sul controllo incendio poiché i browser tenteranno di bloccarlo per (buone) ragioni di sicurezza.

Se hai solo bisogno che la finestra di dialogo del file appaia quando un utente fa clic su qualcosa, diciamo perché vuoi dei pulsanti di caricamento dei file più belli, allora potresti dare un'occhiata a ciò che Shaun Inman ha inventato .

Sono stato in grado di ottenere il trigger della tastiera con spostamento creativo della messa a fuoco dentro e fuori il controllo tra eventi keydown, keypress ed keyup. YMMV.

Il mio sincero consiglio è di lasciarlo solo, perché questo è un mondo di incompatibilità con il browser. Gli aggiornamenti minori del browser possono anche bloccare trucchi senza preavviso e potrebbe essere necessario reinventare gli hack per farlo funzionare.


2

Lo stavo cercando da tempo perché volevo creare un pulsante personalizzato che aprisse la finestra di dialogo del file e avviasse immediatamente il caricamento. Ho appena notato qualcosa che potrebbe renderlo possibile: Firefox sembra aprire la finestra di dialogo quando fai clic in qualsiasi punto del caricamento. Quindi potrebbe farlo il seguente:

  1. Crea un caricamento di file e un elemento separato contenente un'immagine che desideri utilizzare come pulsante
  2. Disporli in modo che si sovrappongano e rendano l'elemento del file backgroud e il bordo trasparenti in modo che il pulsante sia l'unica cosa visibile
  3. Aggiungi JavaScript per fare in modo che IE apra la finestra di dialogo quando si fa clic sul pulsante / input di file
  4. Utilizzare un evento onchange per inviare il modulo quando viene selezionato un file

Questo è solo teorico poiché ho già usato un altro metodo per risolvere il problema, ma potrebbe funzionare.


2

Avevo un <input type="button">tag nascosto alla vista. Quello che ho fatto è stato allegare l' "onClick"evento a qualsiasi componente visibile di qualsiasi tipo come un'etichetta. Ciò è stato fatto utilizzando gli Strumenti per sviluppatori di Google Chrome o Firebug di Mozilla Firefox utilizzando il comando "modifica HTML" del tasto destro. In questo caso, specifica il seguente script o qualcosa di simile:

Se hai JQuery:

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

altrimenti:

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

Grazie.


2

Ehi, questa soluzione funziona. per il download dovremmo usare 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();      
       }
   });
};

Per AngularJS o anche per javascript normale.


1

Ciò sarà ora possibile in Firefox 4, con l'avvertenza che conta come una finestra pop-up e sarà quindi bloccato ogni volta che una finestra pop-up sarebbe stata.


2
In realtà firefox4 migliora molto lo stato del caricamento dei file. Il mio problema è come fare lo stesso nel browser Google Chrome.
erick2red

1

Ecco la soluzione che funziona per me: 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 con "piccolo" aiuto di JQuery:

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

Basta essere sicuri che la maschera sia coperta in modo completo dal vero campo di upload.



1

Ho scoperto che se l'input (file) è fuori forma, quindi l'attivazione dell'evento click richiama la finestra di dialogo del file.


1

Spero che questo aiuti qualcuno - ho passato 2 ore a sbattere la testa contro di esso:

In IE8 o IE9, se si attiva l'apertura di un input di file con javascript in alcun modo (credetemi, li ho provati tutti), non ti permetterà di inviare il modulo utilizzando javascript, ma fallirà silenziosamente.

L'invio del modulo tramite un normale pulsante di invio potrebbe funzionare ma chiamare form.submit (); fallirà silenziosamente.

Ho dovuto ricorrere alla sovrapposizione del pulsante di selezione del file con un input di file trasparente che funziona.


Inoltre, puoi avvolgere l'input del file in un'etichetta in modo che in IE sia possibile ottenere l'area cliccabile dell'etichetta per coprire l'intera area del pulsante, mentre con solo un tag di input del file, solo metà di essa è selezionabile in IE.
Galati

1

Questo ha funzionato per me:

<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

non è impossibile:

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

Ma in qualche modo funziona solo se questo è in una funzione che è stata chiamata tramite un evento click.

Quindi potresti avere la seguente configurazione:

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

L' createEvent()e initMouseEvent()sono stati deprecati. Devi usare un CustomEvent()ora ...
Alexis Wilke,

0

Puoi usare

<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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.