17

I have some code doing this :

 var changes = document.getElementsByName(from);
 for (var c=0; c<changes.length; c++) {
   var ch = changes[c];
   var current = new String(ch.innerHTML);
   etc.
 }

This works fine in FF and Chrome but not in IE7. Presumably because getElementsByName isn't working in IE. What's the best workaround?

Jason Bunting
  • 58,249
  • 14
  • 102
  • 93
sa386
  • 303
  • 1
  • 2
  • 6

7 Answers7

17

In case you don't know why this isn't working in IE, here is the MSDN documentation on that function:

When you use the getElementsByName method, all elements in the document that have the specified NAME attribute or ID attribute value are returned.

Elements that support both the NAME attribute and the ID attribute are included in the collection returned by the getElementsByName method, but elements with a NAME expando are not included in the collection; therefore, this method cannot be used to retrieve custom tags by name.

Firefox allows getElementsByName() to retrieve elements that use a NAME expando, which is why it works. Whether or not that is a Good Thing™ may be up for debate, but that is the reality of it.

So, one option is to use the getAttribute() DOM method to ask for the NAME attribute and then test the value to see if it is what you want, and if so, add it to an array. This would require, however, that you iterate over all of the nodes in the page or at least within a subsection, which wouldn't be the most efficient. You could constrain that list beforehand by using something like getElementsByTagName() perhaps.

Another way to do this, if you are in control of the HTML of the page, is to give all of the elements of interest an Id that varies only by number, e.g.:

<div id="Change0">...</div>
<div id="Change1">...</div>
<div id="Change2">...</div>
<div id="Change3">...</div>

And then have JavaScript like this:

// assumes consecutive numbering, starting at 0
function getElementsByModifiedId(baseIdentifier) {
    var allWantedElements = [];
    var idMod = 0;
    while(document.getElementById(baseIdentifier + idMod)) { // will stop when it can't find any more
        allWantedElements.push(document.getElementById(baseIdentifier + idMod++));
    }
    return allWantedElements;
}

// call it like so:
var changes = getElementsByModifiedId("Change");

That is a hack, of course, but it would do the job you need and not be too inefficient compare to some other hacks.

If you are using a JavaScript framework/toolkit of some kind, you options are much better, but I don't have time to get into those specifics unless you indicate you are using one. Personally, I don't know how people live without one, they save so much time, effort and frustration that you can't afford not to use one.

Community
  • 1
  • 1
Jason Bunting
  • 58,249
  • 14
  • 102
  • 93
  • Taking the MSDN documentation as the "correct implementation" seems like an odd stance. Name is not ID. MSFT got it wrong, way wrong. One can argue which elements should have names, but returning an element that doesn't have a name is just plain silly. (rumor has it this is fixed in IE8 std mode) – scunliffe Nov 10 '08 at 23:04
  • MSDN documentation *is* the correct implementation for IE 7 - the original poster said IE7 broke his code, in case you didn't read his post. The OP was applying the name attribute as an expando attribute on a tag for which name isn't allowed, so IE didn't return it, per the documentation. – Jason Bunting Nov 10 '08 at 23:08
  • 3
    I'm sorry, but **where** in the OP question is there *any mention* of *setting* the name? I only see code stating that the OP was attempting to iterate over the items retrieved by using `document.getElementsByName(name)`. I still stand by my statement, that the implementation of `.getElementsByName(name)` is incorrect in IE (in all legacy versions). – scunliffe Apr 27 '11 at 17:38
4

There are a couple of problems:

  1. IE is indeed confusing id="" with name=""
  2. name="" isn't allowed on <span>

To fix, I suggest:

  1. Change all the name="" to class=""
  2. Change your code like this:

-

var changes = document.getElementById('text').getElementsByTagName('span');
for (var c=0; c<changes.length; c++) {
 var ch = changes[c];

 if (ch.className != from)
continue;

 var current = new String(ch.innerHTML);
Greg
  • 316,276
  • 54
  • 369
  • 333
  • Well, thanks. The page is here ( http://lwww.dege.ukfsn.org/encrypt/decode.php ) it's a simple illustration of code-breaking through frequency analysis of letters. You may need to hit tab when you enter a letter in IE. In FF a return does just as well. – sa386 Nov 10 '08 at 18:39
  • At first i didn't think this worked in my IE 11 nor IE 8, but my capitalization was incorrect on the 'Id' in .getElementById(). I've made that mistake so many times! But after fixing *my own* errors, this worked great in both IE 8 and IE 11. Thanks for the great solution! if only IE wud work as well as other browsers! I hope Edge isn't as bad. Time will tell. – Shawn Kovac Jan 19 '16 at 22:27
2

It's not very common to find elements using the NAME property. I would recommend switching to the ID property.

You can however find elements with a specific name using jQuery:

 $("*[name='whatevernameYouWant']");

this will return all elements with the given name.

Pim Jager
  • 31,965
  • 17
  • 72
  • 98
1

I've had success using a wrapper to return an array of the elements. Works in IE 6, and 7 too. Keep in mind it's not 100% the exact same thing as document.getElementsByName, since it's not a NodeList. But for what I need it for, which is to just run a for loop on an array of elements to do simple things like setting .disabled = true, it works well enough.

Even though this function still uses getElementsByName, it works if used this way. See for yourself.

function getElementsByNameWrapper(name) {
  a = new Array();

  for (var i = 0; i < document.getElementsByName(name).length; ++i) {
    a.push(document.getElementsByName(name)[i]);
  }

  return a;
}
1

Workaround

                var listOfElements = document.getElementsByName('aName'); // Replace aName with the name you're looking for
            // IE hack, because it doesn't properly support getElementsByName
            if (listOfElements.length == 0) { // If IE, which hasn't returned any elements
                var listOfElements = [];
                var spanList = document.getElementsByTagName('*'); // If all the elements are the same type of tag, enter it here (e.g.: SPAN)
                for(var i = 0; i < spanList.length; i++) {
                    if(spanList[i].getAttribute('name') == 'aName') {
                        listOfElements.push(spanList[i]);
                    }
                }
            }
Davide Andrea
  • 1,357
  • 2
  • 15
  • 39
1

getElementsByName is supported in IE, but there are bugs. In particular it returns elements whose ‘id’ match the given value, as well as ‘name’. Can't tell if that's the problem you're having without a bit more context, code and actual error messages though.

In general, getElementsByName is probably best avoided, because the ‘name’ attribute in HTML has several overlapping purposes which can confuse. Using getElementById is much more reliable. When specifically working with form fields, you can more reliably use form.elements[name] to retrieve the fields you're looking for.

bobince
  • 528,062
  • 107
  • 651
  • 834
  • getElementsByName is actually useful if you are *only* looking for form fields for which a NAME attribute is actually part of the W3C spec. That said, it would be a rare thing to ever actually use it. – Jason Bunting Nov 10 '08 at 19:06
1

Just another DOM bug in IE:

Bug 1: Click here

Bug 2: Click here

Kondal
  • 2,870
  • 5
  • 26
  • 40
scunliffe
  • 62,582
  • 25
  • 126
  • 161