最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Pure Javascript target label - Stack Overflow

programmeradmin3浏览0评论

I have some checkboxes and I want the text of the label to change when the checkbox is selected:

JSFIDDLE

var listener = function() {
    document.addEventListener('change', function(e) {
            if (e.target.checked) {
                e.target.label.className = "option-selected";
            }
        }
    }
}

HTML if you are interested:

<input id="0A" class="individual-checkbox" type="checkbox" value="A">
<label for="0A">A</label>
<br>
<input id="0B" class="individual-checkbox" type="checkbox" value="B">
<label for="0B">B</label>

Obviously, target.label doesn't work. How do I access the label of the target and give it a CSS class (purely in JavaScript)?

I have some checkboxes and I want the text of the label to change when the checkbox is selected:

JSFIDDLE

var listener = function() {
    document.addEventListener('change', function(e) {
            if (e.target.checked) {
                e.target.label.className = "option-selected";
            }
        }
    }
}

HTML if you are interested:

<input id="0A" class="individual-checkbox" type="checkbox" value="A">
<label for="0A">A</label>
<br>
<input id="0B" class="individual-checkbox" type="checkbox" value="B">
<label for="0B">B</label>

Obviously, target.label doesn't work. How do I access the label of the target and give it a CSS class (purely in JavaScript)?

Share Improve this question asked Dec 20, 2013 at 2:21 stevenspielstevenspiel 6,01914 gold badges63 silver badges90 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

To make your jsFiddle work, you have to change the following:

  1. Fix the syntax error (missing a closing paren for the addListener() function call and you have an extra closing brace.
  2. Actually call the listener() function to make it run.
  3. Target the actual label, not the checkbox with your class

There are several different ways to target the label. The simplest would be to enclose the input inside the label and then just use .parentNode to get the label from the checkbox.

HTML:

<label for="0A">
    <input id="0A" class="individual-checkbox" type="checkbox" value="A">
A</label>
<br>
<label for="0B">
    <input id="0B" class="individual-checkbox" type="checkbox" value="B">
B</label>

code:

var listener = function() {
    document.addEventListener('change', function(e) {
        if (e.target.checked) {
            e.target.parentNode.className = "option-selected";
        }
    });
}
listener();

Working jsFiddle: http://jsfiddle/jfriend00/s2A7W/


If you don't want to change your HTML, then you just need to find the label element that is right after your input element.

You can do that like this:

var listener = function() {
    document.addEventListener('change', function(e) {
        var label;
        if (e.target.checked) {
            label = next(e.target, "label");
            if (label) {
                label.className = "option-selected";
            }
        }
    });
}
listener();

function next(src, tag) {
    tag = tag.toUpperCase();
    while (src && src.tagName !== tag) {
        src = src.nextSibling;
    }
    return src;    
}

Working jsFiddle: http://jsfiddle/jfriend00/3wQKa/


FYI, you should probably also restrict the action of your listener to only when a checkbox is actually the target or an element with a particular classname or some other distinguishing feature that makes sure it's a checkbox you want targeted by this code. You are probably safe with e.target.checked, but I don't like the fact that this event listener responds to all propagated change events in the entire page.

Assuming there is only one label element associated with the element:

e.target.labels[0].className = "option-selected";

This is an HTML5 property though, I don't know how well it is supported in older browsers. Source: MDN.

Alternatively, if IE8 support is enough for you, you can explicitly search for it with document.querySelector:

var label = document.querySelector('[for=' + e.target.name + ']');

This only works if you give the input elements name attributes (which you really want to do, otherwise the labels are not properly connected to the input elements).

And finally, if the label always es after the input, you can traverse the DOM:

var label = e.target.nextSibling;
while (label.nodeName !== 'LABEL') {
    label = label.nextSibling;
}

If you'd restructure your HTML so that the input element is a child of the label element:

<label for="0A">
    <input id="0A" class="individual-checkbox" type="checkbox" value="A">
    A
</label>

then you could simply use e.target.parentNode to get the label. Putting the input element inside the label also connects the label to the input.

this will do the trick:

function addListener(elem) {
    // remember: checkboxes never change trair value 
    elem.addEventListener('click', function () {
        var ls = document.getElementsByTagName('label');
        for (var l = 0, ll = ls.length, lbl; l < ll; ++l) {
            lbl = ls[l];
            if ( this.id == lbl.getAttribute("for") )
            {
                lbl.className = ( this.checked ? "option-selected" : "" );
            }
        }
    });
}

see http://jsfiddle/fGSCH/10/

be aware that addListener() might not work in every browser. but since you used it in the example i will use it too.

发布评论

评论列表(0)

  1. 暂无评论