www.webdeveloper.com
Results 1 to 7 of 7

Thread: [RESOLVED] Question about 'addEvent()' function

  1. #1
    Join Date
    Dec 2005
    Location
    FL
    Posts
    7,259

    resolved [RESOLVED] Question about 'addEvent()' function

    In the following script I'm trying to set-up an 'addEvent()' for the tabs
    but I'm getting an error about an 'uncaught exception: ...' in FF error console.

    I'm pretty sure it is in the initialization during the onload function, specifically at:
    Code:
    	addEvent(document.getElementById('sm'+i),'click',toggle(i));
    But I don't know how to specify the function correctly so that it creates a 'toggle("#")' for each tab. [toggle("0") ... toggle("4")]
    There are commented 'alert(info)' messages scattered about while I was trying to debug this problem.

    Can someone show me how to correctly specify the function for the 'addEvent()'.
    There is a reference to the original addEvent() code in the script.

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta content="text/html; charset=windows-1252" http-equiv="Content-Type" />
    <title>Preview Menu</title>
    
    <style type="text/css">
    #tabbedTable {
    	width: 300px;
    	height: 250px;
    	position: fixed; 
    	border: 1px solid blue;
    	top:50px;	left:100px;
    }
    #displayContent {
    	border-bottom: 0;
    }
    .tab {
    	text-align: center;
    	vertical-align: middle;
    	height: 32px;
    	border: 1px outset; 
    	cursor: pointer;
    	color: #6699CC;
    	background-color: #EEEEEE;
    }
    .activeTab {
    	text-align: center;
    	vertical-align: middle;
    	height: 32px;
    	border: 1px outset; 
    	cursor: pointer;
    	color: #006699;
    	background-color: #FFFFFF;
    }
    .contentBlock {
    	display: none;
    	height: 195px;
    	overflow: hidden;
    	text-align: left; 
    }
    .heading { /* text-align: center;  */
               font-size:1.5em;
               background-color:yellow;
               border-bottom:1px solid blue;
    }
    
    </style>
    <script type="text/javascript">
    
    var tabCount = 5;
    
    function toggle(info) {		
      var tabIDS = 'sm'+info;				// alert(tabIDS);  // for testing purposes
      var contentIDS = 'Content'+info;
      var tmenu = document.getElementById('tabMenu');	// alert(tmenu.id);
      var divInfo = tmenu.getElementsByTagName('div');  // alert(divInfo.length);
      for (var i=0; i<divInfo.length; i++) { 			// alert(divInfo[i].className);
    	divInfo[i].className = 'tab'; }
      document.getElementById(tabIDS).className = 'activeTab';
      for (var i=0; i<tabCount; i++) {
    	document.getElementById('Content'+i).style.display = 'none'; }
      sel = document.getElementById(contentIDS);
      if (sel.style.display != 'block') { sel.style.display = 'block'; }
                                   else { sel.style.display = 'none'; }	
    }
    
    // Following from: http://ejohn.org/blog/flexible-javascript-events/#postcomment
    //   should work in all browsers for:
    // type = click, keyup, mousedown, mousemove, mouseout, mouseover, mouseup, reset, resize, select, submit
    // obj  = document.getElementById(IDS);
    // fn   = doSomething or function() { alert('hello!'); }
    function addEvent( obj, type, fn ) {
      if ( obj.attachEvent ) {
        obj['e'+type+fn] = fn;
        obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
        obj.attachEvent( 'on'+type, obj[type+fn] );
      } else
        obj.addEventListener( type, fn, false );
    }
    /* Following is not currently used
    function removeEvent( obj, type, fn ) {
      if ( obj.detachEvent ) {
        obj.detachEvent( 'on'+type, obj[type+fn] );
        obj[type+fn] = null;
      } else
        obj.removeEventListener( type, fn, false );
    }
    */
    
    onload = function() {
      var divInfo = document.getElementById('tabMenu').getElementsByTagName('div');
      for (var i=0; i<divInfo.length; i++) {
    	addEvent(document.getElementById('sm'+i),'click',toggle(i));
      }
    
      toggle('0');	
    }
    
    </script>
    </head>
    
    <body>
    <table border="0" cellpadding="0" cellspacing="0" id="tabbedTable">
    <tr><td colspan="2" class="heading">Header</td></tr>
    <tr><td valign="top" width="25%" id="tabMenu">
        <div id='sm0' class="tab">Category 1</div>
        <div id='sm1' class="tab">Category 2</div>
        <div id='sm2' class="tab">Category 3</div>
        <div id='sm3' class="tab">Category 4</div>
        <div id='sm4' class="tab">Category 5</div>
        </td>
        
    	<td id="displayContent" valign="top">
    		<div class="contentBlock" id="Content0"> 
    		Information concerning category 1
    		</div>
    		
    		<div class="contentBlock" id="Content1"> 
    		Information concerning category 2
    		</div>
    		
    		<div class="contentBlock" id="Content2">
    		Information concerning category 3
    		</div>
    		
    		<div class="contentBlock" id="Content3">
    		Information concerning category 4
    		</div>
    		
    		<div class="contentBlock" id="Content4">
    		Information concerning category 5
    		</div>
    		
    	</td>
    </tr>
    </table>
    </body>
    </html>

  2. #2
    Join Date
    Jul 2005
    Location
    USA
    Posts
    909
    toggle(i) will not work

    try

    Code:
    addEvent(document.getElementById('sm'+i),'click', function(){toggle(i)});
    Bitter web veteran

  3. #3
    Join Date
    Dec 2005
    Location
    FL
    Posts
    7,259

    Question Corrected, but still a problem ...

    Quote Originally Posted by Webnerd View Post
    toggle(i) will not work

    try

    Code:
    addEvent(document.getElementById('sm'+i),'click', function(){toggle(i)});
    Thank you 'Webnerd', that got rid of the 'uncaught exception ...' error
    but now I have another problem with the same initialization section.

    I corrected the area as you suggested:
    Code:
    onload = function() {
      var divInfo = document.getElementById('tabMenu').getElementsByTagName('div');
      for (var i=0; i<divInfo.length; i++) {
        addEvent(document.getElementById('sm'+i),'click', function(){toggle(i)});
      }
    
      toggle('0');	
    }
    Then if you allow the alert display here:
    Code:
    function toggle(info) {		
      var tabIDS = 'sm'+info;		 alert(tabIDS);  // for testing purposes
    ...
    After the initial display of the 'sm0' tab (which works correctly),
    it tries to fire an event on 'sm5' for all the tabs.

    Any idea why it does not set the addEvent toggle function correctly to '0' ... '4'?

    Appreciate the help regardless.
    I feel I'm getting closer to a solution.

  4. #4
    Join Date
    Jul 2005
    Location
    USA
    Posts
    909
    Try:

    Code:
    onload = function() {
      var divInfo = document.getElementById('tabMenu').getElementsByTagName('div');
      for (var i=0; i<divInfo.length; i++) {
    	(function(i){
    		addEvent(document.getElementById('sm'+i),'click', function(){toggle(i)});
    	})(i);
      }
    
      toggle('0');	
    }
    Problem is that your scope needed to change. We do this by wrapping your addEvent into an anonymous function.
    Bitter web veteran

  5. #5
    Join Date
    Dec 2005
    Location
    FL
    Posts
    7,259

    Thumbs up Perfect for my needs ...

    Quote Originally Posted by Webnerd View Post
    Try:

    Code:
    onload = function() {
      var divInfo = document.getElementById('tabMenu').getElementsByTagName('div');
      for (var i=0; i<divInfo.length; i++) {
    	(function(i){
    		addEvent(document.getElementById('sm'+i),'click', function(){toggle(i)});
    	})(i);
      }
    
      toggle('0');	
    }
    Problem is that your scope needed to change. We do this by wrapping your addEvent into an anonymous function.
    Thank you very much. That change did the trick. Works like a champ nowl

    One last question(s): I would have NEVER thought of that solution.
    Can you explain what is happening with the (function(i){ ... statement
    that you put inside the onload loop?
    Are you creating a function that is part of the body or the window?
    Is that the scope that you are referring to?

    I see that it works, but I would like to understand why!

    Again, appreciate the help!

  6. #6
    Join Date
    Jul 2005
    Location
    USA
    Posts
    909
    The issue is that variable "i" is part of onload function scope. So when you tried to execute it before, the value of "i" was set to the last known value which would be the highest index reached.

    In order to address that issue, you need to define a "new scope". You do this by wrapping your code within an anonymous function and pass the variable into it.

    It took me a long time to understand this concept as well.

    Here is a minimal breakdown:

    Code:
    	(function(i){ // creating new scope -make sure to specify params being passed
    		addEvent(document.getElementById('sm'+i),'click', function(){toggle(i)});
    	})(i); // the last parenthetical collection contains the variable to pass
    It is just like calling a function:

    dosomething(i)

    except the function has no name (anonymous), so we represent that with

    (function(i){})(i)

    So in place of the function name (dosomething), we have (function(i){}) and all the processing goodies inside.
    Last edited by Webnerd; 01-24-2010 at 03:53 PM.
    Bitter web veteran

  7. #7
    Join Date
    Dec 2005
    Location
    FL
    Posts
    7,259
    Thanks again for the help and the explanation.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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



Recent Articles