web-dev-qa-db-fra.com

Effacement de <input type = 'file' /> en utilisant jQuery

Est-il possible d'effacer une valeur de contrôle <input type='file' /> avec jQuery? J'ai essayé ce qui suit:

$('#control').attr({ value: '' }); 

Mais ça ne marche pas.

523
sagar

Facile: vous enroulez un <form> autour de l'élément, appelez reset sur le formulaire, puis supprimez le formulaire à l'aide de la commande wrapper (). Contrairement aux solutions clone () sinon dans ce fil, vous vous retrouvez avec le même élément à la fin (y compris les propriétés personnalisées qui y ont été définies).

Testé et fonctionnant sous Opera, Firefox, Safari, Chrome et IE6 +. Fonctionne également sur d'autres types d'éléments de formulaire, à l'exception de type="hidden".

http://jsfiddle.net/rPaZQ/

function resetFormElement(e) {
  e.wrap('<form>').closest('form').get(0).reset();
  e.unwrap();

  // Prevent form submission
  e.stopPropagation();
  e.preventDefault();
}

Comme Timo le notera ci-dessous, si vous disposez des boutons pour déclencher la réinitialisation du champ à l'intérieur du <form>, vous devez appeler preventDefault sur l'événement pour empêcher le <button> de déclencher une soumission.

Modifier

Ne fonctionne pas dans IE 11 en raison d'un bogue non corrigé. Le texte (nom du fichier) est effacé sur l'entrée, mais sa liste File reste remplie.

512
slipheed

Réponse rapide: remplacez-le.

Dans le code ci-dessous, j'utilise la méthode replaceWith jQuery pour remplacer le contrôle par un clone. Si des gestionnaires sont liés à des événements sur ce contrôle, nous souhaitons également les conserver. Pour ce faire, nous passons true comme premier paramètre de la méthode clone .

<input type="file" id="control"/>
<button id="clear">Clear</button>
var control = $("#control");

$("#clear").on("click", function () {
    control.replaceWith( control = control.clone( true ) );
});

Fiddle: http://jsfiddle.net/jonathansampson/dAQVM/

Si le clonage, tout en préservant les gestionnaires d'événements, présente les problèmes que vous pourriez envisager d'utiliser avec la délégation d'événements pour gérer les clics sur ce contrôle à partir d'un élément parent:

$("form").on("focus", "#control", doStuff);

Cela évite la nécessité de cloner des gestionnaires avec l'élément lorsque le contrôle est actualisé.

427
Sampson

Jquery est censé s'occuper pour vous des problèmes de navigateur croisé/ancien.

Cela fonctionne sur les navigateurs modernes que j'ai testés: Chromium v25, Firefox v20, Opera v12.14

Utiliser jquery 1.9.1

HTML

<input id="fileopen" type="file" value="" />
<button id="clear">Clear</button>

Jquery

$("#clear").click(function () {
    $("#fileopen").val("");
});

Sur jsfiddle

La solution javascript suivante a également fonctionné pour moi sur les navigateurs mentionnés ci-dessus.

document.getElementById("clear").addEventListener("click", function () {
    document.getElementById("fileopen").value = "";
}, false);

Sur jsfiddle

Je n'ai aucun moyen de tester avec IE, mais théoriquement, cela devrait fonctionner. Si IE est suffisamment différent pour que la version Javascript ne fonctionne pas car MS l’a fait de manière différente, la méthode jQuery devrait, à mon avis, s’en occuper pour vous, sinon il vaudrait la peine de la signaler à jQuery team avec la méthode requise par IE. (Je vois des gens dire "cela ne fonctionnera pas sur IE", mais pas de code JavaScript Vanilla pour montrer comment cela fonctionne sur IE (soi-disant un "dispositif de sécurité"?), Signalez-le également peut-être comme un bogue à MS (s'ils le comptent comme tel), afin que cela soit corrigé dans toute nouvelle version)

Comme mentionné dans une autre réponse, un post sur le forum jquery

 if ($.browser.msie) {
      $('#file').replaceWith($('#file').clone());
 } else {
      $('#file').val('');
 }

Mais jquery a maintenant supprimé le support pour les tests de navigateur, jquery.browser.

Cette solution javascript a également fonctionné pour moi, c’est l’équivalent Vanilla de la méthode jquery.replaceWith .

document.getElementById("clear").addEventListener("click", function () {
    var fileopen = document.getElementById("fileopen"),
        clone = fileopen.cloneNode(true);

    fileopen.parentNode.replaceChild(clone, fileopen);
}, false);

Sur jsfiddle

La chose importante à noter est que la méthode cloneNode ne conserve pas les gestionnaires d’événements associés.

Voir cet exemple.

document.getElementById("fileopen").addEventListener("change", function () {
    alert("change");
}, false);

document.getElementById("clear").addEventListener("click", function () {
    var fileopen = document.getElementById("fileopen"),
        clone = fileopen.cloneNode(true);

    fileopen.parentNode.replaceChild(clone, fileopen);
}, false);

Sur jsfiddle

Mais jquery.clone offre ceci [*1]

$("#fileopen").change(function () {
    alert("change");
});

$("#clear").click(function () {
    var fileopen = $("#fileopen"),
        clone = fileopen.clone(true);

    fileopen.replaceWith(clone);
});

Sur jsfiddle

[*1] jquery est capable de faire cela si les événements ont été ajoutés par les méthodes de jquery car il en garde une copie dans jquery.data , cela ne fonctionne pas autrement, donc c'est un peu une triche/solution de contournement et des choses qui ne sont pas compatible entre différentes méthodes ou bibliothèques.

document.getElementById("fileopen").addEventListener("change", function () {
    alert("change");
}, false);

$("#clear").click(function () {
    var fileopen = $("#fileopen"),
        clone = fileopen.clone(true);

    fileopen.replaceWith(clone);
});

Sur jsfiddle

Vous ne pouvez pas obtenir le gestionnaire d'événements attaché directement à partir de l'élément lui-même.

Voici le principe général de javascript dans Vanilla, voici comment jquery et toutes les autres bibliothèques le font (environ).

(function () {
    var listeners = [];

    function getListeners(node) {
        var length = listeners.length,
            i = 0,
            result = [],
            listener;

        while (i < length) {
            listener = listeners[i];
            if (listener.node === node) {
                result.Push(listener);
            }

            i += 1;
        }

        return result;
    }

    function addEventListener(node, type, handler) {
        listeners.Push({
            "node": node,
                "type": type,
                "handler": handler
        });

        node.addEventListener(type, handler, false);
    }

    function cloneNode(node, deep, withEvents) {
        var clone = node.cloneNode(deep),
            attached,
            length,
            evt,
            i = 0;

        if (withEvents) {
            attached = getListeners(node);
            if (attached) {
                length = attached.length;
                while (i < length) {
                    evt = attached[i];
                    addEventListener(clone, evt.type, evt.handler);

                    i += 1;
                }
            }
        }

        return clone;
    }

    addEventListener(document.getElementById("fileopen"), "change", function () {
        alert("change");
    });

    addEventListener(document.getElementById("clear"), "click", function () {
        var fileopen = document.getElementById("fileopen"),
            clone = cloneNode(fileopen, true, true);

        fileopen.parentNode.replaceChild(clone, fileopen);
    });
}());

Sur jsfiddle

Bien sûr, jquery et d'autres bibliothèques ont toutes les autres méthodes de support requises pour maintenir une telle liste, ceci n'est qu'une démonstration.

102
Xotic750

Pour des raisons évidentes de sécurité, vous ne pouvez pas définir la valeur d'une entrée de fichier, même sur une chaîne vide.

Tout ce que vous avez à faire est de réinitialiser le formulaire dans lequel se trouve le champ ou si vous souhaitez uniquement réinitialiser la saisie de fichier d'un formulaire contenant d'autres champs, utilisez ceci:

function reset_field (e) {
    e.wrap('<form>').parent('form').trigger('reset');
    e.unwrap();
}​

Voici un exemple: http://jsfiddle.net/v2SZJ/1/

48
Laurent

Cela fonctionne pour moi. 

$("#file").replaceWith($("#file").clone());

http://forum.jquery.com/topic/how-to-clear-a-file-input-in-ie

J'espère que ça aide.

43
SyntaxError

Dans IE8, le champ File Upload était en lecture seule pour des raisons de sécurité. Voir le IE billet de blog de l'équipe :

Historiquement, le contrôle de fichier HTML () a été à l’origine d’un nombre important de vulnérabilités en matière de divulgation d’informations. Pour résoudre ces problèmes, deux modifications ont été apportées au comportement du contrôle.

Pour bloquer les attaques qui reposent sur le «vol» de frappes au clavier et amener subtilement l'utilisateur à saisir un chemin de fichier local dans le contrôle, la zone d'édition Chemin de fichier est désormais en lecture seule. L'utilisateur doit explicitement sélectionner un fichier à télécharger à l'aide de la boîte de dialogue Parcourir les fichiers.

En outre, l'option "Inclure le chemin du répertoire local lors du téléchargement de fichiers" a été définie sur "Désactiver" pour la zone Internet. Cette modification empêche toute fuite d'informations sur le système de fichiers local potentiellement sensibles sur Internet. Par exemple, plutôt que de soumettre le chemin d'accès complet C:\utilisateurs\ericlaw\documents\secret\image.png, Internet Explorer 8 ne soumettra désormais que le nom de fichier image.png.

20
Jon Galloway

Je me suis retrouvé avec toutes les options ici. Voici un hack que j'ai fait qui a fonctionné:

<form>
 <input type="file">
 <button type="reset" id="file_reset" style="display:none">
</form>

et vous pouvez déclencher la réinitialisation à l'aide de jQuery avec un code similaire à celui-ci:

$('#file_reset').trigger('click');

(jsfiddle: http://jsfiddle.net/eCbd6/ )

12
Saneem

$("#control").val('') est tout ce dont vous avez besoin! Testé sur Chrome avec JQuery 1.11

D'autres utilisateurs ont également testé dans Firefox.

11
Bodi

J'ai fini avec ceci:

if($.browser.msie || $.browser.webkit){
  // doesn't work with opera and FF
  $(this).after($(this).clone(true)).remove();  
}else{
  this.setAttribute('type', 'text');
  this.setAttribute('type', 'file'); 
}

peut ne pas être la solution la plus élégante, mais cela fonctionne aussi loin que je peux dire.

8
skvalen

J'ai utilisé https://github.com/malsup/form/blob/master/jquery.form.js , qui possède une fonction appelée clearInputs(), qui est crossbrowser, bien testé, facile à utiliser et qui gère également IE problème et effacement des champs cachés si nécessaire. Peut-être une solution un peu longue pour effacer uniquement l'entrée de fichier, mais si vous traitez des téléchargements de fichiers entre navigateurs, cette solution est recommandée.

L'utilisation est facile:

 // Efface tous les champs du fichier: 
 $ ("Input: fichier"). ClearInputs (); 

 // Efface également les champs masqués: 
 $ ("Input: fichier") .clearInputs (true); 

 // Vide les champs spécifiques: 
 $ ("# myfilefield1, # ​​myfilefield2"). clearInputs (); 
/** 
 * Efface les éléments de formulaire sélectionnés .
 */
 $ .fn.clearFields = $ .fn.clearInputs = function (includeHidden) {
 var re =/^ (?: couleur | date | date/heure | email | mois | numéro | mot de passe | plage | recherche | tel | texte | heure | url | semaine) $/i; // 'caché' n'est pas dans cette liste 
 retourne this.each (function () {
 var t = this.type, tag = this.tagName.toLowerCase (); 
 if (re.test (t) || tag == 'textarea') { 
 this.value = ''; ;__.} 
 else if (t == 'case à cocher' || t == 'radio') {
 this.checked = false; 
}
 else if (tag == 'select') {
 this.selectedIndex = -1; 
} 
 else if (t == "fichier") {
 if (/ MSIE /. test (navigator.userAgent)) {
 $ (this) .replaceWith ($ (this) .clone (true)); 
} else {
 $ (this) .val ('') ;
} 
} 
 else if (includeHidden) {
 // includeHidden peut être la valeur true ou il peut s'agir d'une chaîne de sélecteur 
 // indiquant un test spécial, par exemple: 
 // $ ('# myForm'). clearForm ('. special: hidden') 
 //. Ce qui précède nettoiera les entrées cachées ayant la classe de 'special' 
 if ((includeHidden === true&& /hidden/.test(t)) || 
 (typeof includeHidden == 'chaîne' && $ (this) .is (includeHidden))) 
 this.value = ''; 
 } 
 }); 
}; 
8
Timo Kähkönen

La valeur des entrées de fichier est en lecture seule (pour des raisons de sécurité). Vous ne pouvez pas le supprimer par programme (autrement qu'en appelant la méthode reset () du formulaire, dont la portée est plus large que celle de ce champ).

5
Quentin

J'ai pu faire fonctionner le mien avec le code suivant:

var input = $("#control");    
input.replaceWith(input.val('').clone(true));
5
Purusartha

J'ai réussi à ce que cela fonctionne en utilisant ce qui suit ...

function resetFileElement(ele) 
{
    ele.val(''); 
    ele.wrap('<form>').parent('form').trigger('reset');   
    ele.unwrap();
    ele.prop('files')[0] = null;
    ele.replaceWith(ele.clone());    
}

Cela a été testé dans IE10, FF, Chrome & Opera.

Il y a deux mises en garde ...

  1. Ne fonctionne toujours pas correctement dans FF, si vous actualisez la page, l'élément de fichier est re-rempli avec le fichier sélectionné. Où il obtient cette information est au-delà de moi. Quels autres éléments liés à un élément d’entrée de fichier pourrais-je essayer d’effacer?

  2. N'oubliez pas d'utiliser la délégation pour tous les événements que vous avez associés à l'élément d'entrée du fichier, afin qu'ils continuent de fonctionner lors de la création du clone.

Ce que je ne comprends pas, c'est qui sur la terre a pensé que ne pas vous autoriser à effacer un champ de saisie d'une sélection de fichier non valide non valide était une bonne idée?

OK, ne me laissez pas le définir de manière dynamique avec une valeur afin que je ne puisse pas extraire les fichiers du système d'exploitation d'un utilisateur, mais laissez-moi effacer une sélection non valide sans réinitialiser l'intégralité d'un formulaire. 

De toute façon, ce n'est pas comme si 'accepter' faisait autre chose qu'un filtre et, dans IE10, il ne comprend même pas les types mime de MS Word, c'est une blague!

4
1DMF

La fonction .clone() ne fonctionne pas pas dans Opera (et éventuellement dans d’autres). Il garde le contenu.

La méthode la plus proche pour moi ici était celle de Jonathan plus tôt, mais il a fallu s'assurer que le champ préservait son nom, ses classes, etc.

Quelque chose comme ça pourrait bien marcher (merci à Quentin aussi):

function clearInput($source) {
    var $form = $('<form>')
    var $targ = $source.clone().appendTo($form)
    $form[0].reset()
    $source.replaceWith($targ)
}
4
SpoonNZ

Je cherchais un moyen simple et propre de supprimer les entrées HTML, les réponses ci-dessus sont excellentes, mais aucune d’entre elles ne répond vraiment à ce que je cherche, jusqu’à ce que je tombe sur le Web avec une méthode simple et élégante:

var $input = $("#control");

$input.replaceWith($input.val('').clone(true));

tout le mérite revient à Chris Coyier .

// Referneces
var control = $("#control"),
    clearBn = $("#clear");

// Setup the clear functionality
clearBn.on("click", function(){
    control.replaceWith( control.val('').clone( true ) );
});

// Some bound handlers to preserve when cloning
control.on({
    change: function(){ console.log( "Changed" ) },
     focus: function(){ console.log(  "Focus"  ) }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="file" id="control">
<br><br>
<a href="#" id="clear">Clear</a>

3
chebaby

cela fonctionne pour moi dans chaque navigateur.

        var input = $(this);
        var next = this.nextSibling;
        var parent = input.parent();
        var form = $("<form></form>");
        form.append(input);
        form[0].reset();
        if (next) {
            $(next).before(input);
        } else {
            parent.append(input);
        }
2
srsajid

Sur mon Firefox 40.0.3 ne fonctionne qu'avec cela

 $('input[type=file]').val('');
 $('input[type=file]').replaceWith($('input[type=file]').clone(true));
2
Roger Russel

J'ai essayé avec la plupart des techniques mentionnées par les utilisateurs, mais aucune d'entre elles n'a fonctionné dans tous les navigateurs. i.e: clone () ne fonctionne pas en FF pour les entrées de fichier . J'ai fini par copier manuellement l'entrée de fichier, puis remplacer l'original par celui copié. Cela fonctionne dans tous les navigateurs.

<input type="file" id="fileID" class="aClass" name="aName"/>

var $fileInput=$("#fileID");
var $fileCopy=$("<input type='file' class='"+$fileInput.attr("class")+" id='fileID' name='"+$fileInput.attr("name")+"'/>");
$fileInput.replaceWith($fileCopy);
1
Juan
function clear() {
    var input = document.createElement("input");
    input.setAttribute('type', 'file');
    input.setAttribute('value', '');
    input.setAttribute('id', 'email_attach');

    $('#email_attach').replaceWith( input.cloneNode() );
}
0
Claudio Guirunas

Faites-le asynchrone et réinitialisez-le une fois les actions souhaitées effectuées par le bouton.

    <!-- Html Markup --->
    <input id="btn" type="file" value="Button" onchange="function()" />

    <script>
    //Function
    function function(e) {

        //input your coding here           

        //Reset
        var controlInput = $("#btn");
        controlInput.replaceWith(controlInput = controlInput.val('').clone(true));
    } 
    </script>
0
JEPAAB

ça ne marche pas pour moi:

$('#Attachment').replaceWith($(this).clone());
or 
$('#Attachment').replaceWith($('#Attachment').clone());

ainsi, dans asp MVC, j’utilise les fonctions de rasoir pour remplacer l’entrée de fichier . crée d’abord une variable pour la chaîne de saisie avec Id et Nom, puis l’utilise pour afficher la page et remplacer en cliquant sur le bouton de réinitialisation:

@{
    var attachmentInput = Html.TextBoxFor(c => c.Attachment, new { type = "file" });
}

@attachmentInput

<button type="button" onclick="$('#@(Html.IdFor(p => p.Attachment))').replaceWith('@(attachmentInput)');">--</button>
0
Omid-RH

$("input[type=file]").wrap("<div id='fileWrapper'/>");
$("#fileWrapper").append("<div id='duplicateFile'   style='display:none'>"+$("#fileWrapper").html()+"</div>");
$("#fileWrapper").html($("#duplicateFile").html());
0
Niraj

Juste utiliser,

 $("#fileUploaderID").val(''); 
0
Thisara Subath