• 0

Passing a variable to a jQuery selector


Question

I have some JavaScript code that loops through a record set using a for loop. The ID of each record is assigned dynamically using this script. For example:

id="header1", id="header2", id="header3"

The numeral at the end of the id is assigned via script.

I also need to select these IDs via jQuery but I do not understand how to insert a variable into my jQuery selector.

I have tried the following (simplified for clarity):

$("#header[i]")...;
$("#header"+[i])...;
$("#header+[i]")...;
$("#header"+i)...;

None of these things seem to work as jQuery doesn't select the objects I'm trying to get.

Any ideas on how to dynamically create jQuery objects using a counter variable?

Link to comment
Share on other sites

10 answers to this question

Recommended Posts

  • 0

I can't get this technique to work.

My code:

var currentIMHeader = "IM-header"+[i];
			var currentIMData = "IMData"+[i];
			alert("binding a function to "+currentIMData);
			$(currentIMHeader).toggle( function() {
				alert("showing "+currentIMData);
				$(currentIMData).show();
				}, function() {
				alert("hiding "+currentIMData);
				$(currentIMData).hide();
				});

The alerts are there for testing purposes. I have also tried passing a "#" to the selector as I am trying to select based on ID.

Link to comment
Share on other sites

  • 0

This is a basic thing on JavaScript syntax, not on jQuery really.

var i = 5;

$("#header"+i).fadeOut();

I see no reason why this would not work - fading out the element with an ID of header5.

Edited by Rob
Link to comment
Share on other sites

  • 0
This is a basic thing on JavaScript syntax, not on jQuery really.

var i = 5;

$("#header"+i).fadeOut();

I see no reason why this would not work - fading out the element with an ID of header5.

It might work outside of a for loop but it doesn't seem to work in one.

The following code with hardcoded jQuery selectors should bind a function to the "defName0" object but it doesn't bind when used within a for loop.

$("#defName0").bind("click", function() {
			 $("#defValue0").fadeIn("normal");
			 });

I'm completely stuck.

Is there some basic incompatibility betwen standard JS For loops and jQuery? jQuery has an "Each()" function that I have not used yet - is this the path to salvation?

Link to comment
Share on other sites

  • 0

Quick usage note:

$(".headers").fadeOut();

This would fade out all elements with a class of 'headers'.

$(".headers").each(function() { 
  alert("Fading out element: "+$(this).attr("id"));
  $(this).fadeOut(); 
} );

That would find all elements with a class of 'headers', alert to the screen their ID, and fade them out.

Link to comment
Share on other sites

  • 0

To append on what Rob posted, you can put a variable in function() to have an iterated value for the loop

$(".headers").each(function(i) {
  alert("Fading out element "+i+": "+$(this).attr("id"));
  $(this).fadeOut();
} );

Do note that it works like an indexed array, so i will start at 0, not at 1.

Link to comment
Share on other sites

  • 0

When passing the counter variable "i" to my jQuery function is there a need to reference the variable using brackets ""?

$(".headers").each(function([i]) {

Link to comment
Share on other sites

  • 0
When passing the counter variable "i" to my jQuery function is there a need to reference the variable using brackets ""?

$(".headers").each(function([i]) {

No, the only time (that I know of) that it is necessary is for arrays or lists:

var locations = Array();
locations[0] = 'Neowin.net';

var sites = ["Neowin.net", "Microsoft.com"];

Link to comment
Share on other sites

  • 0

Long explanation incoming.

jQuery is JavaScript. All JavaScript rules apply to everything jQuery. jQuery doesn't change how the language (and interpreters) function and behave. Case in point:

var i = 5
$("#myElement" + i).bind(...);

In the above code, "#myElement" + i always returns the string #myElement5. Therefore, the jQuery function $() receives the string #myElement5 as a parameter.

The code your provided has some issues with it. I won't say that what you did is wrong, because you wrote it the way you thought it would work. It's wrong in the sense that the interpreter interprets the code differently than what you thought it would. Your code follows; I added the for loop because I assumed that's what you're doing:

for (var i = 0; i < 5; i++) {
	var currentIMHeader = "IM-header"+[i];
	var currentIMData = "IMData"+[i];
	alert("binding a function to "+currentIMData);

	$(currentIMHeader).toggle(
		function() {
			alert("showing "+currentIMData);
			$(currentIMData).show();
		}, 
		function() {
			alert("hiding "+currentIMData);
			$(currentIMData).hide();
		}
	);
}

First, is used incorrectly. The [] operators are for arrays (and objects, but we won't go there) to pick an item in the array at a specific index. For instance, say I have an array with ten items. You use the [] operators to pick which item you want from the array:

alert(myArray[5]); // alerts the sixth item in the array

You don't receive an error from the usages above, but it is incorrect.

The issues in your code are scope and closures. Variables defined in a function are function scoped... meaning any variable you define in the function can be used anywhere in that function as long as the variable is defined. Take the following code samples as an example:

alert(i); // alerts undefined

for (var i = 0; i < 5; i++) {
	alert(i); // alerts 0, 1, 2, 3, or 4
}

alert(i); // alerts 5 (because the loop iterated i to 5, then exited because 5 isn't less than 5)

...

alert(foo); // undefined

if (true) {
	var foo = "bar";
}

alert(foo); // alerts bar

Even though the i and foo variables are defined within a block (designated by {}) of code, they can be used outside that block and still retain their value. That in itself doesn't cause the problem you see, but throw in a closure and things can start to behave differently than you'd think.

Looking back at your code, the function declarations for the toggle() method are closures. The problem comes from using the currentIMData variable within the enclosed functions. Each function passed to the toggle() method contains a reference to the same currentIMData variable, and currentIMData's value changes with each iteration of the loop. So in actuality, after the loop exists, this is what the the interpreter sees for every heading when toggle() is called:

function() {
	alert("showing IMData5");
	$("IMData5").show();
}, 
function() {
	alert("hiding IMData5");
	$("IMData5").hide();
}

The way to get around this issue is, ironically, another closure; a function to return a function. The code below works:

for (var i = 0; i < 5; i++) {
	var currentIMHeader = "IM-header"+ i;
	var currentIMData = "IMData"+ i;
	alert("binding a function to "+currentIMData);

	$(currentIMHeader).toggle(
		function(elementId) { // function that accepts a parameter
			return function() { // the function to return
				alert("showing "+ elementId);
				$(elementId).show(); // use the variable from the parameter
			};
		}(currentIMData), // call the function and pass currentIMData as the parameter
		function(elementId) { // function that accepts a parameter
			return function() { // the function to return
				alert("hiding "+ elementId);
				$(elementId).hide(); // use the variable from the parameter
			};
		}(currentIMData) // call the function and pass currentIMData as the parameter
	);
}

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.