質問

I'm trying to change the class of a div using the onclick notifier of an object. The code looks like it should work, but when I'm troubleshooting with Firebug, it appears that my for loop (that even Firebug shows having only 1 element in it) executes more than once and throws an error the second time around. Here's the Javascript:

function handleElements(elementid,containerid) {
// Get array of all 'visible' elements in the container
var elements = document.getElementById(containerid).getElementsByClassName('visible');

// Iterate over that array and make them all 'hidden'
for (var i in elements) {
    var object = elements[i].id;
    document.getElementById(object).className='hidden';
}

// Get the 'clicked' tab and set it to 'visible'
var clicked = document.getElementById(elementid);
clicked.className='visible';
}

And here is the HTML:

<div id="wrapper">
<div id="leftpanel">
    <div id="navcontainer">
        <ul id="navlist">
            <li><a href="javascript:;" onClick="handleElements('Modules','rightpanel')">Modules</a></li>
            <li><a href="javascript:;" onClick="handleElements('DataViewer','rightpanel')">Data Viewer</a><li>
            <li><a href="javascript:;" onClick="handleElements('Alarms','rightpanel')">Alarms</a><li>
            <li><a href="javascript:;" onClick="handleElements('Logging','rightpanel')">Logging</a><li>
            <li><a href="javascript:;" onClick="handleElements('Outputs','rightpanel')">Output Control</a><li>
        </ul>
    </div>
</div>

<div id="rightpanel">
    <div id="Modules" class="visible">
        <h2>Module Information Here</h2>
    </div>
    <div id="DataViewer" class="hidden">
        <h2>Data Viewer Here</h2>
    </div>
    <div id="Alarms" class="hidden">
        <h2>Alarm Page Here</h2>
    </div>
    <div id="Logging" class="hidden">
        <h2>Logging Setup Here</h2>
    </div>
    <div id="Outputs" class="hidden">
        <h2>Output Control Here</h2>
    </div>
</div>

役に立ちましたか?

解決

There are two problems with your loop:

  1. You're looping through a list of elements, there's no need to then go try to get them by id. so change these two lines:

    var object = elements[i].id;
    document.getElementById(object).className='hidden';
    

    to:

    elements[i].className='hidden';
    

    Changing that fixes the problem: Compare this working version (source) to your original (source), but I haven't figured out yet why. :-) getElementById is returning null even though you've clearly assigned the ids (and in fact, we're getting them correctly from the elements).

  2. But while the above is something you need to fix, it's not why you're having the error. The error is coming from your using for-in to loop through the NodeList. Use a normal for loop:

    for (var i = 0; i < elements.length; ++i) {
    

    Remember that for-in is not about looping through array elements (and the return value from getElementsByClassName is not an array), it's about looping through the enumerable property names of an object. In your case, you see it loop twice: Once for the property "0", and once for the property "length". Since you don't have an element with the id "length", your next line blows up, since getElementById returns null for that id.

    More about the myths and realities of for-in on my blog, and more about various "correct" ways to loop through arrays (although again, that's not what elements is in your code) here on Stack Overflow.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top