SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Wizard Stomme poes's Avatar
    Join Date
    Aug 2007
    Location
    Netherlands
    Posts
    10,280
    Mentioned
    51 Post(s)
    Tagged
    2 Thread(s)

    className and IE

    Hallo,
    I've got a set of code ( of which I only understand half of it as I was only able to write half of it... someone else wrote the rest as I am hitting deadlines) which does almost nothing in IE (also not in IE8) while working pretty well in all other browsers (safari, konq, ff, opera, chrome). I'm still in the process of fully understanding this code while also trying to fix it, which isn't necessarily a good combination... but it's how it is for now.

    Here is a temp link to the page, the JS is inside right after the part it's affecting.

    IE gives the error:
    Object Required
    Line 290, char 9

    That's all it says. I know IE isn't known for reporting the right line but I think it's probably right here. This is the JS in its entirety and I marked line 290:
    Code:
        <script type="text/javascript">
        function hasClass(target, classValue) {
            var pattern = new RegExp('(^| )' + classValue + '( |$)');
    /*this is line 290*/        if (pattern.test(target.className)) {
                return true;
            }
            return false;
        }
        
        function addClass(target, classValue) {
            if(!hasClass(target, classValue)) {
                if (!target.className == '') {
                    classValue = ' ' + classValue;
                }
                target.setAttribute('class', target.className + classValue);
            }
        }
    
        function removeClass(target, classValue) {
            if(!hasClass(target,classValue)) {
              return;
            }
            var removedClass = target.className;
            var pattern = new RegExp('(^| )' + classValue  + '( |$)');
            removedClass = removedClass.replace(pattern, '$1');
            removedClass = removedClass.replace(/ $/, '');
            target.setAttribute('class',removedClass);
        }
    
        function createAnchor(text, href) {
            var anchor = document.createElement('a');
            anchor.appendChild(document.createTextNode(text));
            anchor.href = '#' + href;
            return anchor;
        }
    
        function toggle(target,classValue) {
            if (hasClass(target,classValue)) { 
                removeClass(target, classValue);
            } else {
    	        addClass(target, classValue);
    	    }
        }
    
    var toggleFunc = function() {
        var prN = this.parentNode;
        toggle(prN.nextSibling.nextSibling,'verberg');
    
        var signNode = this.firstChild;
        signNode.nodeValue = signNode.nodeValue == '+' ? '-' : '+';
    
        if(prN.firstChild.nodeValue === 'Algemeen') {
            var kids = prN.parentNode.getElementsByTagName('ul');
            for(var i = 0, j = kids.length; i<j; i++) {
                var prevSib = kids.item(i).previousSibling.previousSibling;
    
                anchorNode = prevSib.firstChild.nextSibling.firstChild;            
                anchorNode.nodeValue = signNode.nodeValue == '-' ? '-' : '+';
                
                if(signNode.nodeValue == '-') {
                    removeClass(kids.item(i),'verberg');    
                } else {
                    addClass(kids.item(i),'verberg');
                } 
            }
        } 
        return false;
    };
    
    var bLinks = document.getElementById('beschrijflinks');
    var divs = bLinks.getElementsByTagName('div'), 
        h2s  = bLinks.getElementsByTagName('h2');
        
    for( var i = 0, j = h2s.length; i < j; i++) {
    
        var div = divs.item(i);
    
        var h3s = div.getElementsByTagName('h3');
        for( var k = 0, l = h3s.length; k < l; k++) {
            var anchor = createAnchor('+', 'a_'+k);
            h3s.item(k).appendChild(anchor);
            anchor.onclick = toggleFunc;
            toggle(h3s.item(k).nextSibling.nextSibling,'verberg');
        }
    
        var anchor = createAnchor('+', 'a_'+i);
        h2s.item(i).appendChild(anchor);
        anchor.onclick = toggleFunc;
                
        toggle(div,'verberg');    
    }
        
        </script>
    With this line
    if (pattern.test(target.className)) {
    left unchanged, IE tries to implement the adding of anchors to the first set of anchors, but doesn't do anything else (though looking in the IE dev toolbar it claims the class of "verberg" (hidden) is added to the elements on page load... but if they really were, the CSS would have kicked in and hidden those elements).
    If I change (just to check) className to target.class then I have no error messages in IE and nothing works at all.

    I think every place where className is used, IE is not getting it at all. I suspect this line:
    target.setAttribute('class', target.className + classValue);
    (line 301 in the addClass function) and I wonder if I have to use something like
    target.setAttribute(
    ('class' ? 'class' : className),
    target.className + classValue);
    or something? I'm not sure how to write an IE-version of every line who needs it. I'm not sure how to deal with it. Should I try instead writing two separate lines, one target.setAttribute for modern browsers and another separate line for IE?

    Ideally also if there's a site somewhere someone knows of who specifically deals with writing JS for everyone and specifically dealing with IE and different methods of object detection (with syntax examples) that would be very nice.

  2. #2
    SitePoint Evangelist
    Join Date
    Jun 2007
    Location
    North Yorkshire, UK
    Posts
    483
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Debugging on IE the problem is that target is null. The call stack shows

    toggle(h3s.item(k).nextSibling.nextSibling,'verberg');

    as being the place where target gets supplied. That is h3s.item(k).nextSibling.nextSibling is null

    Haven't got to grips with the logic yet but hope this might help.

  3. #3
    SitePoint Wizard Stomme poes's Avatar
    Join Date
    Aug 2007
    Location
    Netherlands
    Posts
    10,280
    Mentioned
    51 Post(s)
    Tagged
    2 Thread(s)
    I had found a couple of forums where people running into similar trouble found that parentNodes of things were different in IE.

    I wonder if it's not counting whitespace as nodes?
    Maybe I will try adding the
    while (blah.nodeType == 3) {
    //move on to the nextSibling;
    }
    and remove one of the nextSibling's in there.

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,718
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Stomme poes View Post
    I had found a couple of forums where people running into similar trouble found that parentNodes of things were different in IE.

    I wonder if it's not counting whitespace as nodes?
    Yes, that will definately be the problem.

    Internet Explorer is unique (hah!) in that it doesn't incluse whitespace elements when using moving from one sibling to the next.

    It may help if you use a separate function to move to the next sibling, where you can perform the appropriate checks:

    Code javascript:
    function nextSibling(el) {
        el = el.nextSibling;
        while (el && el.nodeType !== 3) {
            el = el.nextSibling;
        }
        return el;
    }
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  5. #5
    SitePoint Wizard Stomme poes's Avatar
    Join Date
    Aug 2007
    Location
    Netherlands
    Posts
    10,280
    Mentioned
    51 Post(s)
    Tagged
    2 Thread(s)
    Hm, neat. Better than adding a while statement in every chunk that looks for the nextSibling.

    I've got to try out one thing at a time though. I've got the setAttribute "class"/className problem and the nextSibling problem. I'm going to try the next sibling one first.

  6. #6
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,718
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    All the best with it.

    Regarding the class names, we haven't gone wrong by using the functions from this snippet
    http://snipplr.com/view/3561/addclas...lass-hasclass/

    Code javascript:
    function hasClass(ele,cls) {
    	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
    }
     
    function addClass(ele,cls) {
    	if (!this.hasClass(ele,cls)) ele.className += " "+cls;
    }
     
    function removeClass(ele,cls) {
    	if (hasClass(ele,cls)) {
        	var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
    		ele.className=ele.className.replace(reg,' ');
    	}
    }

    They're so good that they're close to being best-practice material.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  7. #7
    SitePoint Wizard Stomme poes's Avatar
    Join Date
    Aug 2007
    Location
    Netherlands
    Posts
    10,280
    Mentioned
    51 Post(s)
    Tagged
    2 Thread(s)
    My husband had initially something very similar to that addClass posted above, whereas my original code had the addClass function from Javascript Anthology, as I read that Opera was not happy with
    class=" classname" with the leading space.
    I had him keep the check for other classes first, if none add the classname, otherwise add the space = classname...
    if this was only a very old Opera bug then I'd be happy to have leaner code!

    Is is safer to use \\s in the regex than a regular space? I understand that \s can also take care of tabs, but is that ever an issue? Just curious.

  8. #8
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,718
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Stomme poes View Post
    My husband had initially something very similar to that addClass posted above, whereas my original code had the addClass function from Javascript Anthology, as I read that Opera was not happy with
    class=" classname" with the leading space.
    I had him keep the check for other classes first, if none add the classname, otherwise add the space = classname...
    if this was only a very old Opera bug then I'd be happy to have leaner code!
    If you believe that it will cause a problem, you can very easily resolve that with this update that applies the space only if there is already something there:

    [highlight="javascript"]
    if (!this.hasClass(ele,cls)) {
    if (ele.className > '') {
    ele.className += ' ';
    }
    ele.className += cls;
    }

    Quote Originally Posted by Stomme poes View Post
    Is is safer to use \\s in the regex than a regular space? I understand that \s can also take care of tabs, but is that ever an issue? Just curious.
    \\s is the best one to use as it neatly resolves edge-case issues without introducing further difficulties.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  9. #9
    padawan silver trophybronze trophy markbrown4's Avatar
    Join Date
    Jul 2006
    Location
    Victoria, Australia
    Posts
    4,109
    Mentioned
    28 Post(s)
    Tagged
    2 Thread(s)
    lijst[l].setAttribute("class", "verberg");
    lijst[l].className = "verberg";
    If I could just do that then why am I not just using the second line in the first place?
    Precisely I wasn't suggesting you use both. Avoid setAttribute getAttribute for 'class' and 'for' attributes.

  10. #10
    SitePoint Wizard Stomme poes's Avatar
    Join Date
    Aug 2007
    Location
    Netherlands
    Posts
    10,280
    Mentioned
    51 Post(s)
    Tagged
    2 Thread(s)
    Precisely I wasn't suggesting you use both. Avoid setAttribute getAttribute for 'class' and 'for' attributes.
    Ah, ok, but I couldn't get the addClass/removeClass functions (as they came out of the box from the Anthology book) to work at all (back with original code) until at least once the setAttribute was used... so I figured it was necessary to use setAttribute.

    A problem for me with code snippets is they don't have much context I can look at and copy.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •