2

I done a console.log on a variable and in IE it came back with

<HtmlCollection length="8">
      <input name="Date_Visit" class="Visitor wmp-calendar hasDatepicker" id="rn_Date_Visit_Visitor_23" required="" type="text"></input>
      <input name="Time_Arrival" class="Visitor" id="rn_Time_Arrival_Visitor_23" required="" type="text" maxlength="50"></input>
      <textarea name="Visitor_Names" class="Visitor" id="rn_Visitor_Names_Visitor_23" rows="5"></textarea>
      <input name="Visitor_Organisation" class="Visitor" id="rn_Visitor_Organisation_Visitor_23" required="" type="text"></input>
      <input name="Host_Name" class="Visitor" id="rn_Host_Name_Visitor_23" required="" type="text" maxlength="50"></input>
      <input name="Host_Collar" class="Visitor" id="rn_Host_Collar_Visitor_23" required="" type="text" maxlength="50"></input>
      <input name="Host_Contact" class="Visitor" id="rn_Host_Contact_Visitor_23" required="" type="text" maxlength="50"></input>
      <input name="Floor_Meeting" class="Visitor" id="rn_Floor_Meeting_Visitor_23" type="text" maxlength="50"></input>
      </HtmlCollection>
</HtmlCollection>

This is what I used to put the above

var elements = mainDiv.children[i].getElementsByClassName('Visitor');
console.log(elements);

Similar in Chrome (with more detail however)

So this code below, works in Chrome but fails in IE. In IE all it shows is the names, and some random stuff like "length", "item" and "namedItem" on the second console.log. IE11 does not show all property names, just the very first.

for (var k in elements) {
    console.log("validateForm 5");
    console.log(" > k: " + k);
    console.log(" > k.search(rn): " + k.search("rn_"));
    if (k.search("rn_") > -1){
        console.log("validateForm 6");
        var temp = k.split("_");
        var key = temp[1]+"_"+temp[2];
        var value = elements[k].value;
        VisitorData[x] = key+"|"+elements[k].value;//.getAttribute("value");
        x++;        
    }
}

Any advice? So for example https://jsfiddle.net/6f0L9ye8/1/ works fine in Chrom, it brings back everything (including HERE, WE and GO) but IE11 does not

pee2pee
  • 3,619
  • 7
  • 52
  • 133
  • What is `elements`? – Lennholm May 18 '17 at 11:44
  • Sorry - should have said. That's my HTMLcollection - have edited question – pee2pee May 18 '17 at 11:45
  • Several answers to [*For-each over an array in JavaScript?*](http://stackoverflow.com/questions/9329446/for-each-over-an-array-in-javascript) address how to correctly loop through an *array-like* structure like this. Duplicate? – T.J. Crowder May 18 '17 at 11:47
  • I wouldn't say so - my problem is that IE11 only accesses the first item/property and not all of them whereas Chrome does – pee2pee May 18 '17 at 12:07

1 Answers1

3

for-in isn't for looping through elements in a collection, it's for looping through the names of properties in an object.

To loop through the collection, use a simple for:

for (var k = 0; k < elements.length; ++k) {
    var element = elements[k];
    // ...
}

...or use forEach from Array.prototype:

Array.prototype.forEach.call(elements, function(element) {
    // ...
});

...or any of several other looping techniques. There are several outlined in the answers to this question that handle not just arrays (the topic of the question) but also "array-like" structures such as DOM collections.

If you want to visit the elements and do something with their id and/or name, you'd use a loop such as the above and act on id and name if found. So using your jsFiddle's HTML but with input instead of div (name isn't a valid attribute for divs):

var elements = document.getElementsByClassName("Visitor");
Array.prototype.forEach.call(elements, function(element, index) {
    console.log("index = " + index);
    if (element.id) {
       console.log("id = " + element.id);
    }
    if (element.name) {
       console.log("name = " + element.name);
    }
});
<input class="Visitor" id="ONE" name="Here">
<input class="Visitor" id="TWO" name="We">
<input class="Visitor" id="THREE" name="Go">

If you want other attributes, you can use element.attributes to access them.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • How come in Chrome it goes through every property? IE just seems to pick out the first one and then some random ones – pee2pee May 18 '17 at 11:48
  • @pee2pee: Because you're into unspecified behavior, which different engines can implement differently. – T.J. Crowder May 18 '17 at 11:49
  • @pee2pee: The answer **is** the guidance: Loop correctly. :-) – T.J. Crowder May 18 '17 at 11:52
  • https://jsfiddle.net/6f0L9ye8/1/ doesn't work in IE11 but does in Chrome for example – pee2pee May 18 '17 at 11:58
  • @pee2pee: It's not clear to me what you want here. IE11 doesn't make the indexes or names enumerable properties on the object, so they don't show up in `for-in` loops. Chrome apparently does. [The spec](https://dom.spec.whatwg.org/#htmlcollection) doesn't say either way whether they should be enumerable, and in any case, it doesn't make much sense to loop through the property names defined on `elements`. What are you actually trying to achieve, and how does looping through the collection with the methods above not help you do that? – T.J. Crowder May 18 '17 at 12:07
  • I am trying to loop through every element of a certain class (visitor in this case). I then loop through every property of that element. I do a search on that to see if it matches a string. If it does, I get the value of that property and use it. – pee2pee May 18 '17 at 12:09
  • 1
    @pee2pee *"I am trying to loop through every element"* - And the way to do that is what's described in this answer, not the way you're doing it in your code – Lennholm May 18 '17 at 12:12
  • @pee2pee: You just need to loop through the element using something in-spec, and then act on those elements as you see fit. I've added an example detecting `id` and `name`; if you want other attributes, when you visit the element, use `element.attributes` to discover them. – T.J. Crowder May 18 '17 at 12:26