Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Question Explorer not supporting passing of object arrays or "this" keyword in JavaScript?

    Hi all,

    I've tried gluing together some JS pieces I've found, and the end result works in Firefox, with no warnings or errors. Of course, IE 6.0 on Windows XP SP2 pukes on the first non-trivial instruction in my custom code:
    Code:
    Line: 7
    Char: 5
    Error: Object doesn't support this property or method
    Code: 0
    For some context, here's the HTML:
    Code:
    <SCRIPT type="text/javascript" src="http://www.l0b0.net/include/dhtml/getElementsByClassName.js"></SCRIPT>
    <SCRIPT type="text/javascript" src="http://www.l0b0.net/include/dhtml/addEvent.js"></SCRIPT>
    <SCRIPT type="text/javascript" src="http://www.l0b0.net/include/dhtml/toggle.js"></SCRIPT>
    <script type="text/javascript">
    //<![CDATA[
    window.onload=function(){
     var helpElements = getElementsByClassName(document, "*", "hidden_help");
     for (var i = 0; i < helpElements.length; i++) {
      addEvent(helpElements[i], 'click', function(){toggle(this)});
     }
    }
    //]]>
    </script>
    and
    Code:
    <td class="editable">This element will be repaired between the 17th
      <span class="hidden_help" title=" and the 19th August. Take it in exchange with another element from the tunnel. Wait to bring it to the dcum in SX6 until I sent an e-mail confirming the supports">[...]</span>
    </td>
    The only of the JS files I've modified myself is toggle.js:
    Code:
    function toggle() {
      var initText = '[...]'; //Original element contents
    
      for ( var i=0; i < arguments.length; i++ ) {
        //var title = document.getElementById('merTextHeader').getAttribute('title');
        var title = arguments[i].getAttribute("title"); //Current title (should always be preserved)
        var matchTitle = /^ + title + /m; //Matches the @title at the end of a multi-line string
        var curText = arguments[i].firstChild.nodeValue; //Element contents
    
        var newText = (matchTitle.test(curText) ? initText : title);
    
        if (document.all) {
          arguments[i].innerHTML = newText;
        } else if (document.getElementById) {
          var rng = document.createRange(); //Necessary for text insertion in DOM
          rng.setStartBefore(arguments[i]); //Where to input the text
          var htmlFrag = rng.createContextualFragment(newText);
          arguments[i].removeChild(arguments[i].lastChild);
          arguments[i].appendChild(htmlFrag);
        }
        //addEvent(arguments[i], 'click', function(){toggle(this)});
      }
      return true;
    }
    IE barfs on the "var title =" line, but not if I replace it with the line above. How come? The "arguments" object is supposed to be supported, and "this" should reference the element just like getElementById.

    PS: The page is in a frame, and I can't do anything about it.

  2. #2
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    have you tried:

    arguments[i].title

    ?

    Also, try alerting arguments[i] and see what it is.

  3. #3
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    IE says arguments[i].title is undefined, and arguments[i] is reported as [object].

  4. #4
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    Well, you're using the keyword this in the context of the window, not of the element. If you want the element to be passed in:

    Code:
    window.onload=function(){
     var helpElements = getElementsByClassName(document, "*", "hidden_help");
     for (var i = 0; i < helpElements.length; i++) {
      addEvent(helpElements[i], 'click', function(){toggle(helpElements[i])});
     }
    }

  5. #5
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks, I've tried taking a different course for handling this. The onload contains only this:
    Code:
    var helpElements = getElementsByClassName(document, "*", "help");
    toggle(helpElements);
    toggle() is defined this way:
    Code:
    function toggle() {
      var moreText = 'more &rarr;'; //Link text
      var moreClass = 'help_link';
      var lessText = ' &larr; less'; //Link text
      var lessClass = 'help_text';
    
      for ( var i=0; i < arguments.length; i++ ) {
        alert(arguments[i]);
        var newText = '';
    
        if (arguments[i].getAttribute('class') != moreClass) { //Text is shown, or there are no span children
          arguments[i].setAttribute('class', moreClass);
          newText = moreText;
        } else { //Text is hidden
          arguments[i].setAttribute('class', lessClass);
          newText = arguments[i].getAttribute('title') + lessText;
        }
    
        if (document.all) {
          arguments[i].innerHTML = newText;
        } else if (document.getElementById) {
          var range = document.createRange(); //Necessary for text insertion in DOM
          range.setStartBefore(arguments[i]); //Where to input the text
          var markup = range.createContextualFragment(newText); //Create markup from string
          arguments[i].replaceChild(markup, arguments[i].lastChild); //Element contents
        }
    
        addEvent(arguments[i].lastChild, 'click', function(){toggle(arguments[i].lastChild)});
      }
      return true;
    }
    But now both IE and Firefox are complaining that I cannot run getAttribute on an object (line 11 of toggle()). What gives? Is there anywhere I can get a post-2000 explanation on the way the JavaScript object model works?

  6. #6
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by l0b0
    Code:
        if (arguments[i].getAttribute('class') != moreClass)
    But now both IE and Firefox are complaining that I cannot run getAttribute on an object (line 11 of toggle()). What gives?
    Alerting typeof(arguments[i]) gives me "object", the same as for typeof(document.getElementById('someID')). So I'm even more puzzled than ever.

  7. #7
    Master Coder Kor's Avatar
    Join Date
    Apr 2003
    Location
    Bucharest, ROMANIA
    Posts
    8,478
    Thanks
    58
    Thanked 379 Times in 375 Posts
    forget about getAttribute() and setAttribute() when dealing with classes. IE and Moz have different visions (class and className)

    There are differences also regarding the nature of the returned value (IE takes it as object, while Moz take it as a simple variable)

    Anyway, you may use the good old DOM 0 Level crosbrowser syntax in this particular case of classes. Use

    element.className instead of element.getAttribute('class')
    and
    element.className='myclass' instead of element.setAttribute('class','myclass')
    KOR
    Offshore programming
    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  8. #8
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks Kor. Now my problem has moved on a bit, and I get a security error when trying to setStartBefore(): Error: uncaught exception: [Exception... "Security error" code: "1000" nsresult: "0x805303e8 (NS_ERROR_DOM_SECURITY_ERR)" location: "http://www.l0b0.net/include/dhtml/toggle.js Line: 25"]. The current code (check out the alerts for some more information):
    Code:
    function toggle() {
      for ( var i=0; i < arguments.length; i++ ) {
        var newText = '';
    
        if (arguments[i].className != 'help_link') { //Text is shown, or there are no span children
          arguments[i].className = 'help_link';
          newText = 'more &rarr;';
        } else { //Text is hidden
          arguments[i].className = 'help_text';
          newText = arguments[i].title + ' &larr; less';
        }
    
        if (typeof(document.getElementById) != 'undefined') { //DOM compliant browser
          var range = document.createRange(); //Necessary for text insertion in DOM
          if (self == top) {
            range.setStartBefore(arguments[i]); //Where to input the text
          } else { // Handle frames
            //alert('ID: ' + arguments[i].id); //undefined
            //alert('Title: ' + arguments[i].title); //undefined
            //alert('Node type: ' + arguments[i].nodeType); //undefined
            //alert('Type: ' + typeof(arguments[i])); //object
            //alert('Value: ' + arguments[i].nodeValue); //undefined
            //alert('# children: ' + arguments[i].childNodes.length); //crashes
            //alert('siblings: ' + arguments[i].parent.childNodes.length); //crashes, "arguments[i].parent has no properties"
            range.setStartBefore(arguments[i]); //Where to input the text
          }
          var markup = range.createContextualFragment(newText); //Create markup from string
          arguments[i].replaceChild(markup, arguments[i].lastChild); //Element contents
    
        } else if (document.all) { //IE and older browsers
          arguments[i].innerHTML = newText;
        }
    
        addEvent(arguments[i], 'click', function(){toggle(arguments[i])});
      }
      return true;
    }

  9. #9
    Master Coder Kor's Avatar
    Join Date
    Apr 2003
    Location
    Bucharest, ROMANIA
    Posts
    8,478
    Thanks
    58
    Thanked 379 Times in 375 Posts
    I guess that the condition is not sufficient. text range is different in IE from Mozilla (DOM standard), but

    if (typeof(document.getElementById) != 'undefined')
    ...

    else if(document.all)

    will allow IE to pass, as IE uses getElementById as well

    try this condition

    if (document.getElementById && !document.all)
    {
    ...
    }
    else
    {
    }
    ...
    KOR
    Offshore programming
    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  10. #10
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks! I've now moved on in this labyrinth, and got something which works in Firefox, but not IE. Markup:
    Code:
    <SCRIPT type="text/javascript" src="http://www.l0b0.net/include/dhtml/getElementsByClassName.js"></SCRIPT>
    <SCRIPT type="text/javascript" src="http://www.l0b0.net/include/dhtml/addEvent.js"></SCRIPT>
    
    <SCRIPT type="text/javascript" src="http://www.l0b0.net/include/dhtml/toggle.js"></SCRIPT>
    <script type="text/javascript">
    //<![CDATA[
    window.onload=function(){
     var helpElements = getElementsByClassName(document, "*", "help");
     for (var i=0; i < helpElements.length; i++ ) {
      toggle(helpElements[i].id);
      addEvent(helpElements[i], 'click', function(){toggle(this.id)});
     }
    }
    //]]>
    </script>
    and
    Code:
    <TD class="editable">
    This element will be repaired between the 17th 
     <span id="help_4" class="help" title=" and the 19th August. Take it in exchange with another element from the tunnel. Wait to bring it to the dcum in SX6 until I sent an e-mail confirming the supports">[...]</span></TD>
    The JavaScript:
    Code:
    function toggle(id) {
      if (typeof(document.getElementById) == 'undefined') { //DOM compliant browser
        return false;
      }
      var el = document.getElementById(id);
      var newText = '';
    
      if (el.className != 'help_link') { //Text is shown, or there are no span children
        el.className = 'help_link';
        newText = 'more &rarr;';
      } else { //Text is hidden
        el.className = 'help_text';
        newText = el.title + ' &larr; less';
      }
    
      if (document.getElementById && !document.all) { //DOM compliant browsers
        var range = document.createRange(); //Necessary for text insertion in DOM
        range.setStartBefore(el);
        var markup = range.createContextualFragment(newText); //Create markup from string
        el.replaceChild(markup, el.lastChild); //Element contents
      } else { //IE and older browsers
        el.innerHTML = newText;
      }
    
      return true;
    }
    IE now complains that something needs an object on line 9 (which, of course, should be line 8) of toggle.js. Exactly why is beyond me. According to MSDN, IE is supposed to support this.

  11. #11
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Forgot to mention it: I believe the error is in the way IE handles the "this" keyword.

  12. #12
    Master Coder Kor's Avatar
    Join Date
    Apr 2003
    Location
    Bucharest, ROMANIA
    Posts
    8,478
    Thanks
    58
    Thanked 379 Times in 375 Posts
    Try replacing

    addEvent(helpElements[i], 'click', function(){toggle(this.id)});

    with the old trusty DOM 0 crossbrowser

    helpElements[i].onclick=function(){toggle(this.id)}

    again IE and Moz capture events in different ways.
    KOR
    Offshore programming
    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  13. #13
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    again, the "this" keyword can be problematic. IE and Moz handle the "this" keyword exactly the same. The difference is how they handle events. Check http://www.quirksmode.org/ for more info.

    If you want to pass the object being clicked to your toggle function, the safest way is to reference it directly and avoid "this":

    helpElements[i].onclick=function(){toggle(helpElements[i].id)}

  14. #14
    New to the CF scene
    Join Date
    Mar 2006
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thank you, Kor!

    Finally a version which works in IE and Firefox, with no warnings or errors.

    Beagle: That method doesn't work, both IE and Firefox get the helpElements[i].id reference wrong.

  15. #15
    Master Coder Kor's Avatar
    Join Date
    Apr 2003
    Location
    Bucharest, ROMANIA
    Posts
    8,478
    Thanks
    58
    Thanked 379 Times in 375 Posts
    Quote Originally Posted by Beagle
    again, the "this" keyword can be problematic. IE and Moz handle the "this" keyword exactly the same. The difference is how they handle events. Check http://www.quirksmode.org/ for more info.

    If you want to pass the object being clicked to your toggle function, the safest way is to reference it directly and avoid "this":

    helpElements[i].onclick=function(){toggle(helpElements[i].id)}
    take care, Beagle... Remember that the momemnt the event will be activated, the loop is already done, so that i will have a single value, the last index run.

    To avoid that you may use this. Additionally you may use a "faux" attribute attached to the object.

    PHP Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
    <
    html>
    <
    head>
    <
    title>Untitled Document</title>
    <
    meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <
    meta http-equiv="Content-Style-Type" content="text/css">
    <
    meta http-equiv="Content-Script-Type" content="text/javascript">
    <
    script type="text/javascript">
    onload = function (){
    var 
    s=document.getElementsByTagName('span');
    for(var 
    i=0;i<s.length;i++){
    s[i].ind=i;
    s[i].onclick=function(){alert(this.ind)}
    }
    }
    </script>
    </head>
    <body>
    <span>adfasf</span>
    <br>
    <span>adfasf</span>
    <br>
    <span>adfasf</span>
    <br>
    <span>adfasf</span>
    <br>
    <span>adfasf</span>
    <br>
    </body>
    </html> 
    Now try using
    PHP Code:
    for(var i=0;i<s.length;i++){
    s[i].onclick=function(){alert(i)}

    instead, and you'll see what I mean.
    KOR
    Offshore programming
    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*


 
Page 1 of 2 12 LastLast

Posting Permissions

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