jQueryを使用して<input type = 'file' />をクリアする


回答:


529

簡単:<form>要素をラップし、フォームでresetを呼び出してから、を使用してフォームを削除し.unwrap()ます。.clone()このスレッドの他のソリューションとは異なり、最後に同じ要素が設定されます(それに設定されたカスタムプロパティを含む)。

テスト済みで、Opera、Firefox、Safari、Chrome、IE6 +で動作します。を除いて、他のタイプのフォーム要素でも機能しtype="hidden"ます。

window.reset = function(e) {
  e.wrap('<form>').closest('form').get(0).reset();
  e.unwrap();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form>
  <input id="file" type="file">
  <br>
  <input id="text" type="text" value="Original">
</form>

<button onclick="reset($('#file'))">Reset file</button>
<button onclick="reset($('#text'))">Reset text</button>

JSFiddle

Timoが以下に述べるように、内のフィールドのリセットをトリガーするボタンがある場合は、イベントを<form>呼び出し.preventDefault()て、<button>が送信をトリガーしないようにする必要があります。


編集

未修正のバグのため、IE 11では機能しません。テキスト(ファイル名)は入力でクリアされますが、そのFileリストは入力されたままです。


14
勝者!すべてのブラウザーで機能し、入力フィールドの複製を回避します。ただし、クリアボタンがフォーム内にある場合は、名前reset()をegなどに変更してください。reset2()、少なくともChromeでは、すべてのフィールドがクリアされているためですreset()。送信を防ぐために、呼び出しをクリアした後にevent.preventDefault()を追加します。このように:<button onclick="reset2($('#file'));event.preventDefault()">Reset file</button>。作業例:jsfiddle.net/rPaZQ/23
TimoKähkönen2013年

28
問題は、これにより少なくとも一時的にドキュメントが無効になることです。(フォームに他のフォームを含めることはできません。)現在機能しているかどうかに関係なく、いつでも自由に中断できます。
cHao 2013年

6
@cHao、もちろんこれは、入力要素が実際にフォーム内にある場合にのみ当てはまります。
Ninjakannon 2013

7
フォーム内にフォームを配置することに関しては、常にDOMの外部に新しいフォーム要素を作成するか、必要に応じて本文に追加してから、入力要素をそのフォーム内に移動できます。次に、その新しいフォームをリセットし、入力要素を元の場所に戻し、追加のフォーム要素を削除します。
Kevin Heidt、2014

4
これはIE 11では機能しないことがわかりました。このアプローチを使用するPixelFileInputを使用しています。そして、テキストとサムネイルがクリアされている間、オブジェクトのファイルリストは同じままです:(
Ian Grainger

434

簡単な答え:それを交換してください。

以下のコードでは、replaceWithjQueryメソッドを使用して、コントロールをそれ自体のクローンに置き換えています。このコントロールのイベントにバインドされたハンドラーがある場合は、それらも保持する必要があります。これを行うにtrueは、cloneメソッドの最初のパラメーターとして渡します。

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

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

フィドル:http : //jsfiddle.net/jonathansampson/dAQVM/

イベントハンドラーを保持しながら複製を行うと、イベントの委任を使用して親要素からのこのコントロールのクリックを処理することを検討できる問題が発生します。

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

これにより、コントロールが更新されているときに、ハンドラーを要素と共に複製する必要がなくなります。


50
フィールド$( '#clone')。replaceWith($(this).clone());で.clone()メソッドを使用することもできます。
metric152

4
それはまったく何もしません-ファイアバグのエラーはありません。control.val( '')を追加する必要がありました。ファイル入力ボックスをクリアします。あなたのコードはクロムとIE9でそのまま機能しました。
mnsr

10
それでも動作しません。交換する前にクリアする必要があります。したがって、.replaceWith()の前に.val()が必要です。したがって、control.val( '')。replaceWith(...);
mnsr

6
私は以下のソリューションはこれよりはるかにきれいです持っている:stackoverflow.com/a/13351234/909944
slipheed

2
この答えは歴史的な理由からここにあります。最近のブラウザのサポートinput.value = null;
アンドレWerlang

113

jqueryは、クロスブラウザー/古いブラウザーの問題を処理します。

これは私がテストした最新のブラウザーで動作します:Chromium v​​25、Firefox v20、Opera v12.14

jquery 1.9.1の使用

HTML

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

jquery

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

オンjsfiddle

次のjavascriptソリューションは、上記のブラウザでも機能しました。

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

オンjsfiddle

IEでテストする方法はありませんが、理論的にはこれでうまくいくはずです。IEが十分に異なっていて、MSが別の方法でそれを行ったためにJavaScriptバージョンが機能しない場合、jqueryメソッドはあなたのためにそれを処理するべきです、そうでない場合は、jqueryチームにそれを指摘する価値がありますIEが必要とするメソッド。(「これはIEでは機能しません」と言う人がいますが、IEでどのように機能するかを示すバニラJavaScript(「セキュリティ機能」と思われる)はありません。おそらく、バグとしてMSにも報告します(そのようにそれを数える)、それで新しいリリースで修正されるようにする)

別の回答で述べたように、jqueryフォーラムの投稿

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

しかし、jqueryはブラウザーテストのサポートjquery.browserを削除しました。

このjavascriptソリューションも私にとってはうまくいきました。これは、jquery.replaceWithメソッドの基本的な同等物です。

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

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

オンjsfiddle

注意すべき重要な点は、cloneNodeメソッドは関連するイベントハンドラーを保持しないことです。

この例を参照してください。

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

オンjsfiddle

しかし、jquery.cloneはこれを提供します[* 1]

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

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

    fileopen.replaceWith(clone);
});

オンjsfiddle

[* 1] jquery.dataにコピーを保持しているため、jqueryのメソッドによってイベントが追加された場合、jqueryはこれを行うことができます。それ以外の場合は機能しません。そのため、チート/ 回避策のビットであり、物事ができない異なるメソッドまたはライブラリ間で互換性があります。

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

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

    fileopen.replaceWith(clone);
});

オンjsfiddle

要素自体から直接、アタッチされたイベントハンドラーを取得することはできません。

これがバニラJavaScriptの一般原則です。これが、jqueryと他のすべてのライブラリが(おおまかに)行う方法です。

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

オンjsfiddle

もちろん、jqueryと他のライブラリには、そのようなリストを維持するために必要な他のすべてのサポートメソッドがあります。これは単なるデモンストレーションです。


これでうまくいきます!(まあ、少なくともこの答えの最初のバニラJSビット)。私はこれを最新のChrome、Firefox、IE(11)でテストしました。
PhilT 2015

4
私はあなたの同じ答えのいくつかを追加しようとしていましたが、主にそれ.val('')です。アップロード要素のクローンを作成したり、ネストされたフォームを追加したりするよりも簡単ではありませんか?+1。
Erenor Paz 2015

3
.val("")おかげで、最初のJQueryソリューション(を使用)は完全に機能しました。入力を複製して置き換えるよりもはるかに簡単です。
Hugo Zink 2015年

51

明らかなセキュリティ上の理由から、ファイル入力の値を空の文字列に設定することはできません。

あなたがしなければならないのは、フィールドでフォームをリセットすること、または他のフィールドを含むフォームのファイル入力のみをリセットしたい場合は、これを使用してください:

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

ここexempleは次のとおりです。http://jsfiddle.net/v2SZJ/1/


6
IEでは正しく機能しません。視覚的に値はリセットされますが、el.valueは以前のバージョンを報告します。el.valueのリセットに役立ちますが、IE10 +のみです。jsfiddle.net/9uPh5/2
グレゴール

2
上記と同じソリューション
PhilT 2015

2
これは誤りです。フィールドを特定の値に設定することはできませんが、うまくいけば、フィールドをクリアできます。
fralbo 2015


20

IE8では、セキュリティのために[ファイルのアップロード]フィールドを読み取り専用にしました。IEチームのブログ投稿を参照してください。

歴史的に、HTMLファイルアップロードコントロール()は、多数の情報漏えいの脆弱性の原因でした。これらの問題を解決するために、コントロールの動作に2つの変更が加えられました。

キーストロークを「盗む」ことに依存する攻撃をブロックして、ユーザーをだましてコントロールにローカルファイルパスを入力させるように、ファイルパス編集ボックスは読み取り専用になりました。ユーザーは、[ファイルの参照]ダイアログを使用して、アップロードするファイルを明示的に選択する必要があります。

さらに、「ファイルのアップロード時にローカルディレクトリパスを含める」URLActionがインターネットゾーンに対して「無効」に設定されています。この変更により、機密性の高いローカルファイルシステム情報のインターネットへの漏洩が防止されます。たとえば、完全パスC:\ users \ ericlaw \ documents \ secret \ image.pngを送信するのではなく、Internet Explorer 8はファイル名image.pngのみを送信するようになりました。


16

$("#control").val('')は、あなたが必要とすることすべてです!JQuery 1.11を使用してChromeでテスト済み

他のユーザーもFirefoxでテストしました。


2
ここの他の多くの投稿で説明されているように、これはクロスブラウザーフレンドリーではありません。
Tisch、2015年

これが失敗するブラウザを理解するには?
TheHamstring

1
IEで入力タイプファイルが読み取り専用であるため、Internet Explorerで失敗します>
Lucky

4
ChromeとFirefoxで動作します。十二分に。
naimul64 2017

12

ここですべてのオプションに行き詰まりました。これが私が作ったハックです:

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

そして、次のようなコードでjQueryを使用してリセットをトリガーできます。

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

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


3
わかりましたが、フォーム全体がクリアされます。特定のファイル入力ではありません
Ashish Ratan

8

私はこれで終わりました:

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

最もエレガントな解決策ではないかもしれませんが、私が知る限り、それは機能します。



Chrome 34(Linux)では機能しません。replaceWith()メソッドは両方のブラウザ(chrome、firefox)で機能します
Gaurav Sharma

最初は「$ .browserがjquery 1.9から削除されました」に気づかなければなりませんが、最後の2行(type属性をテキストに変更してからファイルに戻す)は機能しました。さらに、私は$( '#control')。val( '');を設定しようとしました。またはjavascript document.getElementById(control).value = ''; そして、あまりにも働いて、なぜ私たちがこのアプローチを使うべきではないのか分かりません!?最後に、両方を使用することにしました。
QMaster

8

私はhttps://github.com/malsup/form/blob/master/jquery.form.jsを使用しました関数が呼び出されました、clearInputs()があり、クロスブラウザーであり、十分にテストされ、使いやすく、IEの問題と非表示フィールドのクリアも処理します必要に応じて。ファイル入力をクリアするだけの少し長い解決策かもしれませんが、クロスブラウザファイルのアップロードを処理している場合は、この解決策をお勧めします。

使い方は簡単です:

//すべてのファイルフィールドをクリアします。
$( "input:file")。clearInputs();

//非表示フィールドもクリアします:
$( "input:file")。clearInputs(true);

//特定のフィールドをクリアします:
$( "#myfilefield1、#myfilefield2")。clearInputs();
/ **
 *選択したフォーム要素をクリアします。
 * /
$ .fn.clearFields = $ .fn.clearInputs = function(includeHidden){
    var re = / ^(?: color | date | datetime | email | month | number | password | range | search | tel | text | time | url | week)$ / i; // 'hidden'はこのリストにありません
    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));
            } そうしないと {
                $(this).val( '');
            }
        }
        else if(includeHidden){
            // includeHiddenは値trueにするか、セレクター文字列にすることができます
            //特別なテストを示します。例えば:
            // $( '#myForm')。clearForm( '。special:hidden')
            //上記は、「特別」のクラスを持つ非表示の入力をクリーンアップします
            if((includeHidden === true && /hidden/.test(t))||
                 (typeof includeHidden == 'string' && $(this).is(includeHidden)))
                this.value = '';
        }
    });
};

なぜこの回答の方が賛成されないのか理解できません!?
AlexB 2014

1
@AlexB:Timoが説明したように、1つのファイル入力フィールドをクリアするのはやり過ぎです。
TheCarver 2015

それがうまくいったかどうかはわかりませんが、FF 45.0.2ではそれ以上機能しません:(
fralbo

5

ファイル入力の値は読み取り専用です(セキュリティ上の理由から)。プログラムで空白にすることはできません(フォームのreset()メソッドを呼び出す以外は、そのフィールドよりも広いスコープを持ちます)。


16
混乱しています-$( "#inputControl")。val( "")を試しましたが、実際にはフィールドが空白になりました。何か不足していますか?
サンプソン

1
@Jonathanも私にとっては機能しますが、他の値に設定するとセキュリティエラーになります。FF4でテスト済み。
ブレンデン

reset()はJSネイティブメソッドであるため、jQueryを介してフォームを選択する場合は、jQueryスコープから要素を取り出す必要があります。$( "form#myForm")[0] .reset();
クリススティーブンス

4
@ジョナサンそれはあなたがIEでそれをしなかったのであなたのために働きます。このセキュリティ問題は、IEのみが停止する問題です。値をクリアするとChromeとFirefoxの両方で定期的に機能しますが、IEでは機能しません
VoidKing

5

私は私の次のコードで動作させることができました:

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

5

私はHTMLファイル入力をクリアするシンプルでクリーンな方法を探していましたが、上記の答えは素晴らしいですが、私が探しているものに実際に答える方法はありません。

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

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

クレジットはすべて、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>


4

この.clone()ことはOpera(そしておそらく他のもの)では機能しませ。コンテンツを保持します。

ここで私に最も近い方法はJonathanの以前の方法でしたが、私の場合、フィールドがその名前やクラスなどを乱雑なコード用に作成したままになっていることを確認しました。

このようなものはうまくいくかもしれません(クエンティンにも感謝します):

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

これはすべての主要なブラウザでテストされていますか?
Shawn

Chrome / FF / Operaの最新バージョンとIE8では問題なく動作するようです。何も機能しない理由はわかりません。フォームのリセットオプションは長い間使用されていました。
SpoonNZ

4

私はこれを使ってこれをうまく動かすことができました...

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

これはIE10、FF、Chrome、Operaでテストされています。

2つの警告があります...

  1. それでもFFでは正しく機能しません。ページを更新すると、選択したファイルがファイル要素に再入力されます。どこからこの情報を取得するかは私を超えています。ファイル入力要素に関連する他に何をクリアしようとすることができますか?

  2. ファイルのinput要素にアタッチしたすべてのイベントで委任を使用することを忘れないでください。そうすることで、クローンが作成されたときにも機能します。

私が理解していないのは、無効な許容できないファイルの選択から入力フィールドをクリアできないようにするのは良い考えだと誰が思ったのですか?

OK、動的に値を設定してユーザーのOSからファイルをリーチできないようにしないでください。フォーム全体をリセットせずに、無効な選択をクリアしてみましょう。

とにかく 'accept'がフィルター以外のことをするのではなく、IE10ではMS WordのMIMEタイプも理解できません。それは冗談です。


これはほとんど機能します。Firefoxでこれを機能させるために必要なことの1つは.pop()、ファイルの配列をnullに設定する代わりに使用することです。これはファイルを適切に消去するようです。
kmacdonald 2015

2

私のFirefox 40.0.3では、これでのみ動作します

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

1
$( 'input [type = file]')。replaceWith($( 'input [type = file]')。clone(true).val( ''));
Andrei

2

すべてのブラウザで動作します。

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

1

ユーザーが言及したテクニックのほとんどを試してみましたが、どのブラウザーでも機能するものはありませんでした。すなわち:clone()はFFではファイル入力に対して機能しません。最終的にファイル入力を手動でコピーし、元のファイルをコピーしたファイルで置き換えました。すべてのブラウザで動作します。

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

0

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

1
こんにちはNiraj。ようこそ。この答えは正しいかもしれませんが、いくつかの説明を使用できます。
tomfanning

0

これはChrome、FF、Safariで動作します

$("#control").val("")

IEまたはOperaでは動作しない場合があります


1
OPの問題
そのもの

1
はecmascript標準ではありません。入力タイプfileの値は、セキュリティ上の理由から保護プロパティです。
e-info128 2013

0

非同期にし、ボタンの必要なアクションが完了した後でリセットします。

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

私にはうまくいきません:

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

したがって、asp mvcでは、かみそり機能を使用してファイル入力を置き換えます。最初にIdとNameを使用して入力文字列の変数を作成し、それを使用してページに表示し、リセットボタンのクリック時に置換します。

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

@attachmentInput

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

0

簡単な方法は、入力タイプを変更して、もう一度元に戻すことです。

このようなもの:

var input = $('#attachments');
input.prop('type', 'text');
input.prop('type', 'file')

-1

あなたはそれをそのようなクローンで置き換えることができます

var clone = $('#control').clone();

$('#control').replacewith(clone);

しかし、これもその価値でクローンするので、あなたはそうする方が良いです

var emtyValue = $('#control').val('');
var clone = emptyValue.clone();

$('#control').replacewith(clone);

-4

簡単ですlol(すべてのブラウザで動作します(オペラを除く)):

$('input[type=file]').each(function(){
    $(this).after($(this).clone(true)).remove();
});

JSフィドル:http : //jsfiddle.net/cw84x/1/


私はオペラについてあまり気にしませんでした。気になる場合は、フォームにラップしてください。私は個人的には気にせず、自分の方法を使用します。
匿名

2
これは良い答えではありませんが、主な問題は本当に悪い態度でした
Sam P

-5

何?検証関数に、単に

document.onlyform.upload.value="";

アップロードが名前であると仮定します:

<input type="file" name="upload" id="csv_doc"/>

私はJSPを使用していますが、それが違いを生むかどうかはわかりません...

私にとってはうまくいき、それはずっと簡単だと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.