TJnTN
TJnTN

Reputation: 57

Getting Value from Nested Anonymous Function

I've got a list of items that have different data values that I'm trying to return on a click event. I can't seem to pass the value from the click event to the parent function. I may just be doing this all wrong. I just need the data value from each click event to replace the value of my systemName variable. Can someone help me out here?

function getSystemName(){
var systemName = '';
$('.pulldown li').bind('click', function(){
    var systemName = '';
    var systemName = $(this).find('a').data('value');
    console.log(systemName);
});
return systemName;
}

// Edit: I should probably explain that I'm trying to get that value from the click event to update content on the page via jquery .load so perhaps like mentioned below....I'm not doing this properly because I can log the systemName properly on click but it doesn't seem to update the page content. Here is the entire code block.

$.ajaxSetup ({  
    cache: false  
});  
var ajax_load = "<img src='.../images/130.gif' alt='loading...' align='middle' />";
var loadUrl = ".../content.php";  

var getSystemName = (function(){
var systemName = '';
$('.pulldown li').bind('click', function(){
   systemName = $(this).find('a').data('value');
   console.log(systemName);
});
return function() { return systemName };
})();

$("#results")  
    .html(ajax_load)  
    .load(loadUrl, "ki_systems=" +getSystemName());

Upvotes: 0

Views: 1017

Answers (6)

nnnnnn
nnnnnn

Reputation: 150010

In the code in the question, each time you call getSystemName() it will bind a click handler again (resulting in multiple click handlers) and then just return the local systemName variable that will always be blank.

If you are saying that each time you call getSystemName() you want it to return the system name associated with whichever li element was most recently clicked then you can declare the systemName variable as a global variable and bind the event handler (once) outside getSystemName():

var systemName = '';

$('.pulldown li').bind('click', function(){
   systemName = $(this).find('a').data('value');
   console.log(systemName);
});

function getSystemName() {
   return systemName;
}

But that makes the function rather redundant: you could just refence the global variable directly.

On the other hand you could declare just the function and use a closure to avoid the need for global variables, something like this:

var getSystemName = (function(){
    var systemName = '';
    $('.pulldown li').bind('click', function(){
       systemName = $(this).find('a').data('value');
       console.log(systemName);
    });
    return function() { return systemName };
})();

// if no items have been clicked yet it will return an empty string by default
console.log( getSystemName() ); // ""
// click on an item with name "red"
console.log( getSystemName() ); // "red"
// click on an item with name "green"
console.log( getSystemName() ); // "green"

That last block could be a little confusing to the uninitiated. It is setting getSystemName to whatever is returned from an anonymous function expression that is executed immediately (note the extra empty parentheses at the end). And what is returned is a simple function that when called itself will return systemName, which is declared in the outer scope. The click handler also updates this same systemName. So when you actually call getSystemName() you are calling the little one-liner function from the return statement.

Upvotes: 2

Quentin
Quentin

Reputation: 943157

You can't.

Look at the code.

  1. Set systemName to an empty string
  2. When a list item is clicked set systemName to something else
  3. Return systemName

You can't make 3 wait for 2. You need to do something with the data in the click handler and not try to return it.

Upvotes: 0

Greg Banister
Greg Banister

Reputation: 186

Consider this, on the second line you're only binding a callback function to the click event, not executing the code inside that function.

Upvotes: 0

NeilC
NeilC

Reputation: 1390

Well, i suppose you are trying to set a value to see which node has been click, thus you need to change the scope of your systemName variable. Move it out so it will be global, like so:

var systemName = '';
$('.pulldown li').bind('click', function(){
    systemName = $(this).find('a').data('value');
    console.log(systemName);
});

Upvotes: -1

Dan Hardiker
Dan Hardiker

Reputation: 3053

I think the problem here is that you're missing synchronous and asynchronous programming - you probably want a callback on the getSystemName() function. I expect there's something more architecturally wrong with the approach you're taking.

However, this is what it'd look like if I wrote that using your style:

function getSystemName(callback) {
    $('.pulldown li').bind('click', function(){
        console.log(systemName);
        callback( $(this).find('a').data('value') );
    });
}

So instead of this sort of code:

console.log("System Name: ", getSystemName())

You would have:

getSystemName( function (name) { console.log("System Name: ", name); } );

Upvotes: 1

zozo
zozo

Reputation: 8582

Remove the var from the second and third definitions. If you use var before the variable name a new local instance will be created.

 systemName = '';
 systemName = $(this).find('a').data('value');
console.log(systemName);

Upvotes: 0

Related Questions