更好的方法来实现这个vanilla javascript DOM遍历?

时间:2017-09-01 18:56:23

标签: javascript html dom css-selectors dom-traversal

我有一些来自Marketo的自动生成的表单,这意味着我被迫解决所提供的问题。当只有一个值的复选框时,我需要在父标签上添加一个类(有一个注释指示哪一个)。

有问题的复选框可以是任何字段,而不仅仅是" explicitOptin",因此我无法根据该字段进行选择(至少不是最初的)。我还必须确保不会意外选择包含两个或更多值的复选框。

以下是我提出的javascript:

var ckBox = document.querySelector('.mktoCheckboxList .mktoField:only-of-type').parentNode.previousSibling.previousSibling;
if (ckBox.className.indexOf('mktoSingleCheckbox') == -1) {
    ckBox.className += ' mktoSingleCheckbox';
}
<form id="mktoForm_1690" novalidate="novalidate" class="mktoForm mkt*emphasized text*oHasWidth mktoLayoutLeft" data-styles-ready="true">
<div class="mktoFormRow">
    <div class="mktoFormRow">
        <div class="mktoFieldDescriptor mktoFormCol">
            <div class="mktoOffset"></div>
            <div class="mktoFieldWrap">
                <label for="hazmatchooseallthatapply" class="mktoLabel mktoHasWidth">
                    <div class="mktoAsterix">*</div>Hazmat (choose all that apply):</label>
                <div class="mktoGutter mktoHasWidth"></div>
                <div class="mktoLogicalField mktoCheckboxList mktoHasWidth">
                    <input name="hazmatchooseallthatapply" id="mktoCheckbox_9480_0" type="checkbox" value="Hazardous Materials" class="mktoField">
                    <label for="mktoCheckbox_9480_0">Hazardous Materials</label>
                    <input name="hazmatchooseallthatapply" id="mktoCheckbox_9480_1" type="checkbox" value="Hazardous Waste" class="mktoField">
                    <label for="mktoCheckbox_9480_1">Hazardous Waste</label>
                    <input name="hazmatchooseallthatapply" id="mktoCheckbox_9480_2" type="checkbox" value="Fuel Tanker" class="mktoField">
                    <label for="mktoCheckbox_9480_2">Fuel Tanker</label>
                </div>
                <div class="mktoClear"></div>
            </div>
            <div class="mktoClear"></div>
        </div>
        <div class="mktoClear"></div>
    </div>
    <div class="mktoClear"></div>
</div>
<div class="mktoFormRow">
    <div class="mktoFieldDescriptor mktoFormCol">
        <div class="mktoOffset"></div>
        <div class="mktoFieldWrap">
            <!--This label directly below is the element that needs the new class-->
            <label for="explicitOptin" class="mktoLabel mktoHasWidth mktoSingleCheckbox">
                <div class="mktoAsterix">*</div>Yes, please sign me up to receive information from PrePass by email.</label>
            <div class="mktoGutter mktoHasWidth"></div>
            <div class="mktoLogicalField mktoCheckboxList mktoHasWidth mktoValid">
                <!-- This is the single checkbox input that I am selecting with my javascript -->
                <input name="explicitOptin" id="explicitOptin" type="checkbox" value="yes" class="mktoField">
                <label for="explicitOptin"></label>
            </div>
            <div class="mktoClear"></div>
        </div>
        <div class="mktoClear"></div>
    </div>
    <div class="mktoClear"></div>
</div>

我觉得必须有一种更好的方法,而不仅仅是将parentNode和previousSibling方法串在一起。

有什么建议吗?我想可能的替代方法是使用我使用的CSS选择器,但随后获取ID值并搜索具有该ID的for值的元素。也许只需将parentNode和previousSiblings串在一起就可以了......?

1 个答案:

答案 0 :(得分:2)

在撰写本文时,您的解决方案似乎是最佳选择,但使用element.classList代替element.className除外。

可选的重新格式导致这个(长)单行:

document.querySelector('.mktoCheckboxList .mktoField:only-of-type')
  .parentNode.previousSibling.previousSibling
  .classList.add('mktoSingleCheckbox');

展望未来,浏览器会让我们使用HTMLInputElement.labels API收集与<input>相关联的标签。

#                                                                   WOW!
document.querySelector('.mktoCheckboxList .mktoField:only-of-type').labels[0]
  .classList.add('mktoSingleCheckbox');

不幸的是,此API的浏览器支持目前非常有限,并且尝试手动获取关联标签可能比当前方法更麻烦

希望这有帮助!