Results 1 to 3 of 3

Thread: Why is only the last select element is being affected???

  1. #1
    Join Date
    Nov 2006
    Posts
    20
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Why is only the last select element is being affected???

    I have several <select> on my html page but the below function seems to work the only the LAST select element. The rest seems to have no effect at all. Isn't my code adding the new functions to every <select> within the loop.
    My last try asking here

    HTML Code:
    function normalizeDDWidth(){
    var a = document.getElementsByTagName("select");
    	for(var i=0; i<a.length; i++){
    		var selectObj = a[i];
    //		alert(selectObj.id);
    
    		selectObj.onmouseover = function() { selectObj.style.width = 'auto'; }
    		
    		selectObj.onblur = function(){
    		var selectedVal = selectObj.options[selectObj.selectedIndex].value;
    			if(selectedVal != ''){ 
    				selectObj.style.width = "auto"; 
    			}
    			else{ 
    				selectObj.style.width = "9em"; 
    			}
    		}
    
    
    	}//end for
    }//end normalizeDDWidth()

  2. #2
    Join Date
    Jun 2005
    Location
    英国
    Posts
    11,876
    Thanks
    1
    Thanked 180 Times in 172 Posts
    Blog Entries
    2

    Default

    Read the Jibbering.com Closures FAQ for more information on your problem. The functions do get added to every <select>, but the selectObj modified within those functions is the one that exists after the loop has run all the way through. One way to cure this problem is to create a separate scope to hold the current element:
    Code:
    function normalizeDDWidth() {
      for(var i = 0, a = document.getElementsByTagName("select"); i < a.length; ++i) {
        a[i].onmouseover = (function() {
          var selectObj = a[i];
          return function() {
            selectObj.style.width = "auto";
          };
        })();
        a[i].onblur = (function() {
          var selectObj = a[i];
          return function() {
            if(selectObj.options[selectObj.selectedIndex].value !== '')
              selectObj.style.width = "auto";
            else
              selectObj.style.width = "9em";
          };
        })();
      }
    }
    ... but a far better method (although one that may be unsuitable for your code, if it does things other than the snippet you've shown here) is to just use this to refer to the current element, and avoid creating all those unnecessary scopes:
    Code:
    function normalizeDDWidth() {
      var overfunc = function() {
        this.style.width = "auto";
      };
      var outfunc = function() {
        if(this.options[this.selectedIndex].value !== '')
          this.style.width = "auto";
        else
          this.style.width = "9em";
      };
      for(var i = 0, a = document.getElementsByTagName("select"); i < a.length; ++i) {
        a[i].onmouseover = overfunc;
        a[i].onblur = outfunc;
      }
    }
    Twey | I understand English | 日本語が分かります | mi jimpe fi le jbobau | mi esperanton komprenas | je comprends français | entiendo español | tôi ít hiểu tiếng Việt | ich verstehe ein bisschen Deutsch | beware XHTML | common coding mistakes | tutorials | various stuff | argh PHP!

  3. #3
    Join Date
    Dec 2004
    Location
    UK
    Posts
    2,358
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Quote Originally Posted by Twey View Post
    Read the Jibbering.com Closures FAQ for more information on your problem.
    That's actually the FAQ notes for the comp.lang.javascript newsgroup. The notes provide more in-depth discussion than is suitable to be included in the FAQ itself.

    The functions do get added to every <select>, but the selectObj modified within those functions is the one that exists after the loop has run all the way through.
    That is to say that the function objects created within the for loop all share the local variables declared within the normalizeDDWidth function. When one of those variables is changed - in this case, the selectObj variable - all of the function objects created by the function expressions "see" that change.

    Code:
    function normalizeDDWidth() {
      for(var i = 0, a = document.getElementsByTagName("select"); i < a.length; ++i) {
        a[i].onmouseover = (function() {
          var selectObj = a[i];
          return function() {
            selectObj.style.width = "auto";
          };
        })();
        a[i].onblur = (function() {
          var selectObj = a[i];
          return function() {
            if(selectObj.options[selectObj.selectedIndex].value !== '')
              selectObj.style.width = "auto";
            else
              selectObj.style.width = "9em";
          };
        })();
      }
    }
    Another reason to try and stay clear of that is that it will cause a memory leak in MSIE: [select element].onmouseover -> [function object].[[Scope]] -> [Variable object].selectObj -> [select element]. A similar circular reference exists with the blur event listener.

    Mike

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
  •