212 votes

Effacer <input type='file' /> en utilisant jQuery

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

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

Mais ça ne marche pas.

6voto

Quentin Points 325526

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

5voto

Timo Points 2732

J'ai utilisé https://github.com/malsup/form/blob/master/jquery.form.js qui a une fonction appelée clearInputs() qui est multi-navigateurs, bien testé, facile à utiliser et qui gère également les problèmes d'IE et la suppression des champs cachés si nécessaire. C'est peut-être une solution un peu longue pour n'effacer que les entrées de fichiers, mais si vous avez affaire à des téléchargements de fichiers multi-navigateurs, cette solution est recommandée.

L'utilisation est simple :

// Clear all file fields:
$("input:file").clearInputs();

// Clear also hidden fields:
$("input:file").clearInputs(true);

// Clear specific fields:
$("#myfilefield1,#myfilefield2").clearInputs();
    /\*\*
 \* Clears the selected form elements.
 \*/
$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
    return this.each(function() {
        var t = this.type, tag = this.tagName.toLowerCase();
        if (re.test(t) || tag == 'textarea') {
            this.value = '';
        }
        else if (t == 'checkbox' || t == 'radio') {
            this.checked = false;
        }
        else if (tag == 'select') {
            this.selectedIndex = -1;
        }
        else if (t == "file") {
            if (/MSIE/.test(navigator.userAgent)) {
                $(this).replaceWith($(this).clone(true));
            } else {
                $(this).val('');
            }
        }
        else if (includeHidden) {
            // includeHidden can be the value true, or it can be a selector string
            // indicating a special test; for example:
            //  $('#myForm').clearForm('.special:hidden')
            // the above would clean hidden inputs that have the class of 'special'
            if ( (includeHidden === true && /hidden/.test(t)) ||
                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
                this.value = '';
        }
    });
};

5voto

Xotic750 Points 6649

Jquery est censé s'occuper des problèmes liés aux navigateurs anciens et multiples.

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

Utilisation de 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 parce que MS l'a fait d'une manière différente, la méthode jquery devrait, à mon avis, s'en occuper pour vous, sinon cela vaudrait la peine de le signaler à l'équipe jquery avec la méthode que IE exige. (Je vois des gens dire "ça ne marchera pas sur IE", mais pas de vanilla javascript pour montrer comment ça marche sur IE (soi-disant une "fonctionnalité de sécurité" ?), peut-être le signaler comme un bug à MS aussi (s'ils le comptent comme tel), afin qu'il soit corrigé dans toute nouvelle version).

Comme mentionné dans une autre réponse, un poste sur le site de l 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 vanille de la fonction jquery.replaceWith méthode.

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

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

Sur jsfiddle

Il est important de noter que le cloneNode ne préserve 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 ce [*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 le faire si les événements ont été ajoutés par les méthodes de jquery, car il en conserve une copie dans le fichier jquery.data il ne fonctionne pas autrement, il s'agit donc d'une sorte de tricherie ou de contournement qui signifie que les choses ne sont pas compatibles entre les 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énement joint directement à partir de l'élément lui-même.

Voici le principe général de vanilla javascript, c'est ainsi que jquery et toutes les autres bibliothèques le font (en gros).

(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 nécessaires pour maintenir une telle liste, ceci est juste une démonstration.

4voto

skvalen Points 155

Je me suis retrouvé avec ça :

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

n'est peut-être pas la solution la plus élégante, mais elle fonctionne pour autant que je puisse dire.

4voto

SpoonNZ Points 2181

Le site .clone() chose fait pas travailler dans Opera (et peut-être d'autres). Il conserve le contenu.

La méthode la plus proche pour moi était celle de Jonathan, mais s'assurer que le champ conserve son nom, ses classes, etc. a rendu le code désordonné dans mon cas.

Quelque chose comme ceci pourrait bien fonctionner (merci aussi à Quentin) :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X