隐藏文件输入时为什么选择错误?

sko*_*jic 4 jquery

我100%肯定这段代码有效,但在一个特例中它失败了 - 花了一个小时来找到bug(无法在JSFiddle上重现它).最后我找到了原因,但我不知道为什么会这样.它只在我隐藏文件输入时才会发生,结果是:无论选择和更改我更改第一个标签的文件,请看一下:

var activateFileSelection = function( container ) {
    var container = container || $('body');
    container.find(':file').each(function(i) {
        var thisInput = $(this);
        var thisLabel = thisInput.siblings('label');
        if (thisLabel.length > 0 && !thisLabel.hasClass('file-input-label')) {
            var thisLabelDefaultText = thisLabel.html();
            thisLabel.addClass('file-input-label');
            thisInput.on('change', function(e) {
                if (thisInput.val()) {
                    thisLabel.html(thisInput.val());
                } else {
                    thisLabel.html(thisLabelDefaultText);
                };
            });
        };
    });
};
activateFileSelection();
Run Code Online (Sandbox Code Playgroud)
input {
    display: none;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
    <label for="myfile">select 1</label>
    <input id="myfile" type="file" />
</div>
<div>
    <label for="myfile">select 2</label>
    <input id="myfile" type="file" />
</div>
<div>
    <label for="myfile">select 3</label>
    <input id="myfile" type="file" />
</div>
Run Code Online (Sandbox Code Playgroud)

还在JSFiddle上.

如果没有隐藏输入,一切正常:小提琴.

正如没关系下面指出的,重复输入ID可能有脚本的东西这个问题,我仍然没有解决和ID.此外,每个文件输入的更改会触发标签文本的更改,但错误的更改.

Con*_*Fan 6

HTML代码的布局可能表明每个标签都链接到它旁边的输入字段,但事实并非如此.由于for三个标签的属性是"myfile",所有三个标签实际上都链接到第一个输入字段,即找到的字段document.getElementById("myfile").

因此,单击任何标签时,将使用第一个输入字段.thisInput.siblings('label')然后在文件选择后更新在代码中获得的相邻标签.即使3个输入字段可见,也是如此.

另一方面,如果直接单击输入字段,则使用该输入字段并更新相应的标签.

以下代码段向控制台发送一条消息,指示使用了哪个文件输入.

var activateFileSelection = function (container) {
    var container = container || $('body');
    container.find(':file').each(function (i) {
        var thisInput = $(this);
        var thisLabel = thisInput.siblings('label');
        if (thisLabel.length > 0 && !thisLabel.hasClass('file-input-label')) {
            var thisLabelDefaultText = thisLabel.html();
            thisLabel.addClass('file-input-label');
            thisInput.on('change', function (e) {
                console.log("Input used: " + thisInput.data("field"));
                if (thisInput.val()) {
                    thisLabel.html(thisInput.val());
                } else {
                    thisLabel.html(thisLabelDefaultText);
                };
            });
        };
    });
};
activateFileSelection();
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Test by clicking on label 3 vs clicking on input field 3:</p>
<div>
    <label for="myfile">select 1</label>
    <input id="myfile" type="file" data-field="input1" />
</div>
<div>
    <label for="myfile">select 2</label>
    <input id="myfile" type="file" data-field="input2" />
</div>
<div>
    <label for="myfile">select 3</label>
    <input id="myfile" type="file" data-field="input3" />
</div>
Run Code Online (Sandbox Code Playgroud)