【问题标题】:document.getElementsByClassName('')[i].addEventListener('click', function() {};) EventListener only executes on the last element of the array? [duplicate]document.getElementsByClassName('')[i].addEventListener('click', function() {};) EventListener 只在数组的最后一个元素上执行? [复制]
【发布时间】:2017-09-27 20:12:39
【问题描述】:

我正在使用js以启用表单字段,否则检查复选框时是否禁用。我正在使用document.getElementsByClassName,它返回一个复选框数组,然后我通过for循环为每个复选框添加一个addEventListener。然后我检查是否选中了该框,以及我从复选框的href 获得的目标表单字段的removeAttribute('diabled')setAttribute。一切都很好,只是它只适用于 getElementsByClassName 数组的元素。

html代码:

<div class="form-group">
    <form method="POST" action="/admin_accounts/editaccount.php">
        <div class="input-group">
            <div class="input-group-addon input-group-addon-reponsive">
                <label for="memType">Member Type</label>
            </div>
            <select class="form-control" id="memTypeEdit" name="memTypeEdit" disabled>
                <option value="Regular">Regular</option>
                <option value="Ordinary">Ordinary</option>
                <option value="Associate">Associate</option>
                <option value="Executive">Executive</option>
                <option value="Honorary">Honorary</option>
                <option value="Dependant">Dependant</option>
                <option value="Instructor">Instructor</option>
                <option value="Volunteer">Volunteer</option>
            </select>
            <div class="input-group-addon"> 
                <input type="checkbox" class="edit-toggle" href="memTypeEdit"> 
                <label>Edit</label>
            </div>
        </div> 
        <div class="input-group">
            <div class="input-group-addon input-group-addon-reponsive">
                <label for="employ">Employment</label>
            </div>
            <select class="form-control" id="employEdit" name="employEdit" disabled>
                <option value="None"              >None</option>
                <option value="President"         >President</option>
                <option value="Vice President"    >Vice President</option>
                <option value="Treasurer"         >Treasurer</option>
                <option value="Clerk"             >Clerk</option>
                <option value="Instructor"        >Instructor</option>
                <option value="Web Administrator" >Web Administrator</option>
                <option value=""                  >Volunteer</option>
            </select>
            <div class="input-group-addon"> 
                <input type="checkbox" class="edit-toggle" href="employEdit"> 
                <label>Edit</label>  
            </div>
        </div>
        <div class="input-group date" data-provide="datepicker">
            <div class="input-group-addon input-group-addon-reponsive">
                <label for="regDate">Registration Date</label>
            </div>
            <input type="text" id="regDateEdit" name="regDateEdit" class="form-control" disabled>
            <div class="input-group-addon">
                <input type="checkbox" class="edit-toggle" href="regDateEdit"> 
                <label>Edit</label>
            </div>
        </div>
        <div class="input-group date" data-provide="datepicker">
            <div class="input-group-addon input-group-addon-reponsive">
                <label for="expDate">Expiry Date</label>
            </div>
            <input type="text" class="form-control" id="expDateEdit" name="expDateEdit" disabled>
            <div class="input-group-addon">
                <input type="checkbox" class="edit-toggle" href="expDateEdit"> 
                <label>Edit</label>
            </div>
        </div>
        <div class="input-group">
            <div class="input-group-addon input-group-addon-reponsive">
                <label for="admin">Administrator</label>
            </div>
            <select class="form-control" id="adminEdit" name="adminEdit" disabled>
                <option value="0">Is Not Administrator</option>
                <option value="1">Is Administrator</option>                                        
            </select>
            <div class="input-group-addon"> 
                <input type="checkbox" class="edit-toggle" href="adminEdit"> 
                <label>Edit</label>
            </div>                                                        
        </div>
        <div class="text-right">
            <div class="btn-group btn-group-sm" role="group">
                <button type="submit" name="create" class="btn btn-success">Save</button>
                <button type="reset" class="btn btn-info" value="Reset">Reset</button>
            </div> 
        </div>
    </form>
</div>

还有 Js:

<script>
    var anchors = document.getElementsByClassName('edit-toggle');
    for (var i = 0, length = anchors.length; i < length; i++) {
        var anchor = anchors[i];
        anchor.addEventListener('click', function() {
            var target = document.getElementById(anchor.getAttribute('href'));
            if (anchor.checked){
                target.removeAttribute('disabled');
            }else{
                target.setAttribute('disabled', 'disabled');
            }
        }, true);
    };
</script>

就像现在一样,name="adminEdit" 按预期工作,但不是其他的,但是当我从 adminEdit 复选框中删除 class="edit-toggle" 时,expDateEdit 开始工作。所以它看起来像在最后一个元素上工作。有任何想法吗?谢谢。

【问题讨论】:

    标签: javascript html arrays checkbox


    【解决方案1】:

    您的问题是,在循环中,anchor 的值最终将是上次运行循环时的值,并且所有事件侦听器都将引用同一个锚对象。为了解决这个问题,您创建一个立即执行的函数,并将anchor[i] 传递给它以修复其值。这样的事情应该可以工作。

    <script>
        var anchors = document.getElementsByClassName('edit-toggle');
        for (var i = 0, length = anchors.length; i < length; i++) {            
            !function (anchor){
                anchor.addEventListener('click', function() {
                    var target = document.getElementById(anchor.getAttribute('href'));
                    if (anchor.checked){
                        target.removeAttribute('disabled');
                    }else{
                        target.setAttribute('disabled', 'disabled');
                    }
                }, true);
            }(anchors[i]);
        };
    </script>
    

    正如 Squint 指出的,在这种情况下,更简单的解决方案是使用 this 而不是 anchor

    <script>
        var anchors = document.getElementsByClassName('edit-toggle');
        for (var i = 0, length = anchors.length; i < length; i++) {
            var anchor = anchors[i];
            anchor.addEventListener('click', function() {
                var target = document.getElementById(this.getAttribute('href'));
                if (this.checked){
                    target.removeAttribute('disabled');
                }else{
                    target.setAttribute('disabled', 'disabled');
                }
            }, true);
        };
    </script>
    

    【讨论】:

    • 工作得很好,我唯一要做的就是为函数命名为 FireFox 需要的名称
    • 是的。除了命名函数之外,另外两个解决方案是 1) 在函数前加上感叹号:!function(){}();或 2) 将函数括在括号中: (function(){})();我相应地编辑了我的答案。
    • @bradlystrachan:这不是解决您的问题的解决方案。您需要做的就是将事件处理程序中的anchor 替换为this。虽然解决方案是正确的,但这种方法在这里是非常不必要的。
    • @squint - 确实如此。我将编辑答案以反映这一点(没有双关语)..
    • ...另外,作为旁注,不要使用set/removeAttribute 来设置禁用/启用。请改用.disabled 属性。整个事件处理程序可以简化为 document.getElementById(this.getAttribute('href')).disabled = !this.checked。尽管您应该将data- 属性用于非标准属性,例如input 上的href
    猜你喜欢
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    相关资源
    最近更新 更多