onclick assignment in loop not behaving as expected.

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MKayHavoc
    New Member
    • Dec 2007
    • 4

    onclick assignment in loop not behaving as expected.

    I have the following onload function:

    [HTML]function slidebarPrep(){
    if(!document.ge tElementById) return false;
    var slidebar = document.getEle mentsByTagName( "div");
    for(var i = 0; i < slidebar.length ; i++){
    if(slidebar[i].className == "sub_slidebar") {
    var parentId = slidebar[i].offsetParent.i d;
    var parentHeight = slidebar[i].offsetParent.c lientHeight;

    var subBox = document.getEle mentById(parent Id);
    subBox.style.he ight = "115px";

    slidebar[i].onclick = function(){
    sub_expand(50, parentId, parentHeight);
    }
    }
    }
    }[/HTML]

    I have three div's with parent Id's of submitNews, podcastTopic and VideoSubmission s. So when slidebar[i].onclick I would expect it to output like this:

    onclick="sub_ex pand(50, submitNews, 531);"
    onclick="sub_ex pand(50, podcastTopic, 600);"
    onclick="sub_ex pand(50, videoSubmission s, 425);"

    However for some reason each onclick is set to:

    onclick="sub_ex pand(50, videoSubmission s, 425);"

    The last div in the loop.

    However everything else is set correctly prior to the onclick portion, i.e. each div's hight is set to 115px.

    Does anybody have any suggestions?
  • acoder
    Recognized Expert MVP
    • Nov 2006
    • 16032

    #2
    Welcome to TSDN!

    Can you post the corresponding HTML?

    offsetParent is not consistent across the browsers - see this link.

    Comment

    • MKayHavoc
      New Member
      • Dec 2007
      • 4

      #3
      The HTML is as follows, it's the same for each segment:
      [HTML]<div id="submitNews" >
      <p class="submissi onInfo">Proin sed mi in enim consectetuer ullamcorper. Duis suscipit cursus turpis. Phasellus diam leo, dictum dapibus, semper ac, pharetra condimentum, leo.</p>
      <fieldset class="newsForm ">
      <ul>
      <li><label for="contact_na me">Your Name:</label>
      <input id="contact_nam e" type="text" value="<?=$cont act_name;?>" size="20" maxlength="50" tabindex="1" /></li>
      <li><label for="contact_em ail">Your E-Mail:</label>
      <input id="contact_ema il" type="text" value="<?=$cont act_email;?>" size="40" maxlength="100" tabindex="2" /></li>
      <li><label for="contact_ci ty">Your Website:</label>
      <input id="contact_cit y" type="text" value="<?=$cont act_city;?>" size="50" maxlength="100" tabindex="3" /></li>
      <li><label for="contact_ty pe">News Type:</label>
      <select id="contact_typ e" name="contact_t ype" tabindex="4">
      <option value="false">--- Select One ---</option>
      <option value="companyG ossip">Company Gossip</option>
      <option value="event">E vent</option>
      <option value="productL aunch">Product Launch</option>
      <option value="other">O ther</option>
      </select>
      </li>
      <li><label for="contact_me ssage">What's New?:</label>
      <textarea id="contact_mes sage" rows="8" cols="40" tabindex="5"><? =$contact_messa ge;?></textarea></li>
      </ul>
      </fieldset>
      <fieldset class="submit">
      <input class="submit" type="submit" name="contact_s ubmit" value="Submit" tabindex="6" />
      </fieldset>
      <div><div class="sub_slid ebar"></div></div> <!--Wrapper to fix crap IE bug-->
      </div>[/HTML]
      You'll notice that the sub_slider div it wrapped in another div. This is why i've had to use offsetParent, the additional div is needed to correct an IE processing issue when an absolute element is proceeds a floated element.

      OffsetParent seems to be retreived correctly, at least in FF. But in FF the onclick portion still doesn't work.

      Comment

      • Logician
        New Member
        • Feb 2007
        • 210

        #4
        Originally posted by MKayHavoc
        Code:
         			slidebar[i].onclick = function(){
        				sub_expand(50, parentId, parentHeight);
        			}
        Try this:
        Code:
        slidebar[i].onclick = new Function("sub_expand(50,'"+parentId+"', '"+parentHeight+"')");

        Comment

        • gits
          Recognized Expert Moderator Expert
          • May 2007
          • 5390

          #5
          the real problem is, that we have to use a closure when assigning functions with a loop since 'i' would always be the last value of the loop ... so we have to build it the following way (besides the eval which is suggested in the previous post)

          the following is what you did and i will always be the last value ... so we get the value 3 alerted:

          [CODE=javascript]var obj = {};

          for (var i = 0; i < 3; i++) {
          obj[i] = function() {
          alert(i);
          };
          }

          obj[0]();
          [/CODE]
          to fix that issue we may use a 'explicit' closure here:

          [CODE=javascript]var obj = {};

          for (var i = 0; i < 3; i++) {
          obj[i] = function(val) {
          return function() { alert(val) };
          }(i);
          }

          obj[0]();
          [/CODE]
          that will alert '0' as we want it ...

          kind regards

          Comment

          • MKayHavoc
            New Member
            • Dec 2007
            • 4

            #6
            @Logician = You method works perfectly for me, across all browsers I've tested so thanks you.

            @gits = When I was reading your example I understood what you were saying especially seen as that's the behaviour my script was performing, but I could seem to translate your example into my script. :-( I new to javaScript so it's likely just me doing something wrong.

            Thanks to both of you though. My issue is now resolved. :-)

            Comment

            • gits
              Recognized Expert Moderator Expert
              • May 2007
              • 5390

              #7
              hi ...

              glad to hear that you got it working ... a small hint for your closure-adaption:

              [CODE=javascript]slidebar[i].onclick = function(p_id, p_height) {
              return function() { sub_expand(50, p_id, p_height); };
              }(parentId, parentHeight);[/CODE]
              that should do the trick. and should work like the eval-like version ...

              kind regards

              Comment

              • MKayHavoc
                New Member
                • Dec 2007
                • 4

                #8
                I understand. Thanks.

                So what are the benefits of using your method compared to the eval way?

                Comment

                • gits
                  Recognized Expert Moderator Expert
                  • May 2007
                  • 5390

                  #9
                  hi ...

                  typically we never have to use the Function-constructor or the eval function in our javascript code ... but sometimes we cannot avoid it ... for example to eval a json-string that came as response of an ajax request. the main issue with that are performance issues ... have a look here ... and since we don't need to use it it seems to be 'inelegant' to do so :)

                  kind regards

                  Comment

                  Working...