views:

94

answers:

6

I have a script that works fine in all browsers that I have tested so far (FF, Safari, camino, Chrome) but not in IE and I can't figure out why. The IE 8 (windows 7) debug utility highlights this section of the script:

if(list[lineNum].getElementsByClassName("check")[0].getElementsByTagName("a")[0].getAttribute("title").search("Delete")==0)

and says:

Object doesn't support this property or method

I thought perhaps that it might be that IE doesn't like the list array so I added an explicit declaration at the beginning of the script

var list=new Array();

but i still get the same error.

I would really like to get this working on IE and would appreciate any help in doing so.

thanks

A: 

Without testing it, I believe the offending one is probably getElementsByClassName.

The obvious way to debug this would have been to break it into several substatements.

Kinopiko
+3  A: 

Internet Explorer doesn't have native getElementsByClassName support. There's a project that a lot of people use as an alternative, it's available on Google Code here under the MIT license.

Your code would become something like (not tested, just an example):

if(getElementsByClassName("check", null, list[lineNum])[0].getElementsByTagName("a")[0].getAttribute("title").search("Delete")==0)

I would really recommend using jQuery, though. It's built to make these things easy.

Brian McKenna
+1 for jQuery/a JS framework
scunliffe
A: 

I'm sure you're probably already aware, but this scenario is one of the major reasons why frameworks like jQuery, etc are so popular. Depending on your project a javascript framework may not be a realistic solution to this issue, but if you're free to use something like jQuery it'll abstract you away from issues like this so that for the most part, you never have to worry about them again.

Brian Hasden
+1  A: 

There are a lot of IE user's out there- enough so that unless yours is a hobby site, you need to support it. You can speed up IE8 a little by giving it its own methods, but for the other IEs and older browsers you need to change your code so you don't call a nonexistant method.

I define a branching method that uses an getElementsByClassName when available, or loops through an element's descendents, looking at attributes, when not. Remember there can be more than one class of an object.

/* @classes: space separated string of class names

   @pa:parent element reference
*/   
        document.getbyClass= function(classes, pa){
            pa= pa && pa.nodeType== 1? pa: document;
            if(pa.getElementsByClassName){
                return pa.getElementsByClassName(classes);
            }
            var elems= [], c= classes.split(/ +/), L= c.length, tem, temc, 
            tags= pa.getElementsByTagName('*'), max= tags.length;
            for(var i= 0, L= c.length; i< L; i++){
                c[i]= RegExp('\\b'+c[i]+'\\b');
            }
            getbyClassloop: 
            while(max){
                i= L;
                tem= tags[--max];
                temc= tem.className;
                if(temc){
                    while(i){
                        if(!c[--i].test(temc)) continue getbyClassloop;
                    }
                    elems[elems.length]= tem;
                }
            }
            return elems;
        }

// A quicker method for IE8

(function(){
    if(!document.getElementsByClassName){
        try{
            if(document.querySelectorAll && document.attachEvent){
                var IE8class= function(classes){
                    var C= classes.split(' '), tem,
                    els= Array.from(this.querySelectorAll('.'+ C.shift()));
                    while(C.length && els.length){
                        tem= C.shift();
                        els= els.testEach(function(itm){
                            return itm.className.indexOf(tem)!= -1;
                        });
                    }
                    return els;
                }
                HTMLDocument.prototype.getElementsByClassName= IE8class;
                Element.prototype.getElementsByClassName= IE8class;
                return true;
            }
        }
        catch(er){return false};
    }
})()

/* these 2 methods are used with the above... maybe you should let IE struggle along with its relatives in the tag sifting group.. */

  Array.prototype.testEach= function(fun){
        var A= [], tem, L= this.length;
        for(var i= 0; i< L; i++){
            tem= this[i];
            if((!fun && !!tem) || !!fun(tem)) A[A.length]= tem;
        }
        return A;
    }

    Array.from= function(what){
        var L, A= [];
        if(what){
            L= what.length;
            if(L){
                while(L) A[--L]= what[L];
                return A;
            }
            if(what.hasOwnProperty){
                for(var p in what){
                    if(what.hasOwnProperty(p)) A[A.length]= what[p];
                }
            }
        }
        return A;
    }
kennebec
A: 

As Brian McKenna said, native getElementsByClassName() isn't available on IE6/7/8.
On IE8 you could rewrite your line as:

if(list[lineNum].querySelector(".check").querySelector("a").getAttribute("title").search("Delete")==0)

This would also work on recent versions of FF/Safari/Chrome/Opera. But not IE6/7.
There are standardization libraries that would give you querySelector on IE6/7. See
http://stackoverflow.com/questions/408978/any-javascript-frameworks-with-the-aim-of-standard-based-cross-platform-js-and-do/

Sean Hogan
+1  A: 

getElementsByClassName doesn't exist in IE.

This is exactly the reason why it is advisable to use a standard, cross-browser compatible framework like Prototype, Dojo, jQuery, YUI, Mootools or any other the others.

I believe (that statement you have is huge and is hard to be certain without test HTML) that this is the equivalent in ...

jQuery:

if ( $(".check a[title^=Delete]", list[lineNum]) == 0 ) {}

Protoype:

if ( $(list[lineNum]).select(".check a[title^=Delete]") == 0 ) {}

Dojo

if ( dojo.query(".check a[title^=Delete]", list[lineNum]) == 0 ) {}

Simple and clean. You get the idea.

If a library isn't an option for you, then the functions that kennebec provided are likely a good solution.

Justin Johnson