SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    Founder of Primal Skill Ltd. feketegy's Avatar
    Join Date
    Aug 2006
    Posts
    482
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Exclamation Javscript event problem

    Hello, i would appreciate it if somebody could help me with the following problem:

    i have to assign events to images with addEventListener function and i have to pass additional arguments. How can i do that? Using addEventListener is the only way, i can't use any other type of event adding.

    ex.

    element.addEventListener('click',elm_event_func,false);

    i want that elm_event_func accepts arguments and to be able to pass argument s in the addEventListener.

    i tried
    element.addEventListener('click',function(e){elm_event_func(arg1);},false);

    this works, but the problem is that if i put this in a for loop only the last variable will be passed.
    ex:

    for (var i=0; i<5; i++)
    {
    //create the elements
    //adding events to the different element
    element.addEventListener('click',function(e){elm_event_func(i);},false);
    }

    here is only the i=5 will be passed as argument, don't know why.

    can somebody help me?

  2. #2
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I should know how to do this, but I don't

    Here's what I normally do:
    Code:
    for (var i=0; i<5; i++)
    {
    	//create the elements
    	
    	// assign a crazy id that contains the value of i
    	element.id = "therealid___" + i;
    	//adding events to the different element
    	element.addEventListener('click',function (e) {
    		// extract the value of i from the crazy id
    		elm_event_func(this.id.split("___").pop());
    	},false);
    }
    Someone help us both so I don't need to fill my code with weird faces
    ("___")

  3. #3
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Jim, you're on the right track...
    Code:
    for (var i = 0; i < 5; i++)
    {
      //create the elements
    
      // assign a crazy id that contains the value of i
      ele.id = "therealid___" + i;
    
      //adding events to the different element
      addListenerWithArg(ele, 'click', i);
    }
    
    function addListenerWithArg(ele, evType, arg)
    {
      ele.addEventListener(evType,
        function(ev) {
          alert(arg);
        }, false
      );  
    }
    but there are other ways - and most of the time this is like cracking a nut with a sledge hammer. It has become a quick answer to a variety of problems - but not always the best answer.

    Don't get me wrong, Jim, you are posting the answer to the question. But, feketegy, if we knew more about your application we could make much more appropriate suggestions.

  4. #4
    Founder of Primal Skill Ltd. feketegy's Avatar
    Join Date
    Aug 2006
    Posts
    482
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    okay. i'm developing a greasemonkey script. It's greasemonkey and firefox so there's no browser compatibilty issues.
    I dynamically create some images on the site with javascript and dom. And i want to assign to each image a different click event, based on a variable. But i cannot manage to do it.
    So there is a for loop to crawl an array and assign the arrays elements to the images click events. The problem is that each click event holds the last element of the array and i don't know why is that...

  5. #5
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Assign a different click event listener to each? or pass a different argument to each?

    Did you try the code I posted?

    Another way to do it is to add a property to each image element. The property can be the custom data, or it can be an index with which you access an array - it could be the same index used in the loop. But to use this technique you need to use DOM0 event properties.
    Code:
    function init()
    {
      var i, img;
      for (i = 0; i < 5; ++i) {
        img = new Image();
        img.myImgIndex = i;
        img.onclick = imgOnClick;
      }
    }
    function imgOnClick(ev)
    {
      alert(this.myImgIndex);
    }
    Concerning why your first loop doesn't work.
    Code:
    function init()
    {
      for (var i = 0; i < 5; ++i) {
        //create the elements
        //adding events to the different element
        ele.addEventListener('click',
          function(e) {
            /* We are accessing a variable in the outer function 'init'.
               but this listener function won't be called until later -
               after 'init' has finished executing. That creates a closure
               on 'init'. When this listener is called later, the value of
               variable 'i' will be what it was when 'init' finished executing. */
            elm_event_func(i);
          },false
        );
      }
    }
    In the code in my previous post, a closure is created each time addListenerWithArg is called. Each one of those closures preserves the value of the argument as it was when addListenerWithArg was called.

  6. #6
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The problem is that each click event holds the last element of the array and i don't know why is that...
    It's because of the way the "closure" rules work. See an explanation here:

    http://www.sitepoint.com/forums/show...1&postcount=13

    // assign a crazy id that contains the value of i
    element.id = "therealid___" + i;
    There's no reason to use the "id" property. You can just create a custom property:
    Code:
    element.indexVal = i;
    and then retrieve it directly inside the event handler function:
    Code:
    this.indexVal
    which avoids having to call split().
    Edit:


    Sorry Mike, I didn't see your previous post. It looks like you covered everything I posted.
    Last edited by 7stud; Mar 9, 2007 at 20:42.


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
  •