SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    Not yet perfect mattalexx's Avatar
    Join Date
    Oct 2005
    Location
    Taos, NM, US
    Posts
    441
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Passing variables through functions (not inline)

    I have a function like this:
    Code:
    function calc(id) {
       // Do something with string id
    }
    I need to attach this function to the onchange and onkeyup of a bunch of form elements, but I don't want to add "onkeyup='calc(1)' onchange='calc(1)'" to every one of them. Instead, I want to loop through them all and do something like this:
    Code:
    element[ids[i]].onchange = calc(ids[i]);
    element[ids[i]].onkeyup = calc(ids[i]);
    ...but this isn't working because I don't think you can pass variables through a function when you store it in the event like this. So My next step was to use anonymous functions like this:
    Code:
    element[ids[i]].onchange = function () { calc(ids[i]) };
    element[ids[i]].onkeyup = function () { calc(ids[i]) };
    It still isn't working. Can one of you JavaScript gurus help me with this?
    Matt Alexander
    Alexander Site Design

  2. #2
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    As was taught to me recently in these forums, the trick is to use 'this':
    Code:
    element[ids[i]].onchange = function () { calc(this) };
    element[ids[i]].onkeyup = function () { calc(this) };

  3. #3
    Awesome Addict
    Join Date
    Mar 2004
    Location
    Toronto, Canada
    Posts
    326
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question

    Quote Originally Posted by Raffles View Post
    As was taught to me recently in these forums, the trick is to use 'this':
    Code:
    element[ids[i]].onchange = function () { calc(this) };
    element[ids[i]].onkeyup = function () { calc(this) };
    Just to clarify a little further, the "this" keyword in the code above references the element that is firing the onchange/onkeyup event. You can use either one of your previous code examples -- just substitute "ids[i]" with the "this" keyword. Remember though, that "this" references all of the properties and methods of an object: so, if your function requires an id as a parameter you'll have to either pass the id of the object directly into the function:
    Code:
    element[ids[i]].onkeyup = function() { 
      calc(this.id);
      return false;
    };
    // or
    element[ids[i]].onkeyup = calc(this.id);
    ...or modify the function to take an element object and then get the id:
    Code:
    function calc(elm) {
      var id = elm.id;
      // use object id in proceeding code...
    }
    HTH!

  4. #4
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    but this isn't working because I don't think you can pass variables through a function when you store it in the event like this.
    When you make an assignment like this:
    Code:
    someElement.onchange = someFunc;
    you are assigning a function reference to the onchange property of someElement. Two ways a function reference can be specified are:

    a) by assinging the name of a function defined elsewhere, or
    b) by assigning the definition of an anonymous function

    Note that you are not making a call to the function with any js you wrote. To make a function call in js, you use the function execution operator "()", which executes the function and returns the results, e.g.:

    var result = someFunc(a);

    Instead, you want js to take note of a function you defined and then execute it sometime in the future when a certain event occurs. js then calls the function you specified at the appropriate time, e.g. onclick, but in js only the caller can pass parameters to a js function. Since you aren't calling the function when you write:
    Code:
    someElement.onchange = someFunc;
    you can't pass any parameters.

    You can easily get around that problem by wrapping your function call in an anonymous function:

    Code:
    someElement.onchange = function(){someFunc(a)};
    However, you can run into some thorny problems if you try to use a loop to make multiple assignments like that inside another function--in other words when each of those anonymous functions is being defined inside a surrounding function.

    So My next step was to use anonymous functions like this:
    Code:
    element[ids[i]].onchange = function () { calc(ids[i]) };
    element[ids[i]].onkeyup = function () { calc(ids[i]) };
    It still isn't working. Can one of you JavaScript gurus help me with this?
    Post a complete but brief example demonstrating your problem. If I had to guess, the new problem you are seeing is due to the fact that the calc() function that is eventually called for each element uses a value for i that is 1 greater than the ending constraint for your loop.
    Last edited by 7stud; Jan 5, 2007 at 01:05.

  5. #5
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mattalexx View Post
    Code:
    element[ids[i]].onchange = function () { calc(ids[i]) };
    element[ids[i]].onkeyup = function () { calc(ids[i]) };
    It still isn't working.
    The reason why this doesn't work has been explained several times here, see e.g. http://www.sitepoint.com/forums/showthread.php?t=439253

    What you need is probably something like this

    Code:
    for(var i = 0; i < ids.length; i++)
    	element[ids[i]].onchange = 
    		function(id) {
    			return function() {
    				calc(id)
    			}
    		}(ids[i])

  6. #6
    Not yet perfect mattalexx's Avatar
    Join Date
    Oct 2005
    Location
    Taos, NM, US
    Posts
    441
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Red face

    Quote Originally Posted by stereofrog View Post
    What you need is probably something like this

    Code:
    for(var i = 0; i < ids.length; i++)
    	element[ids[i]].onchange = 
    		function(id) {
    			return function() {
    				calc(id)
    			}
    		}(ids[i])
    That's an interesting way of going about it. I didn't delve further into debugging this because of a time crunch. Sadly, I just added inline onchanges to the HTML (I know; yuck.)

    Thanks all for your help.
    Matt Alexander
    Alexander Site Design


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
  •