• 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?

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.

  • 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
  • 0
  Rob said:
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?

  • 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.

  • 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.

  • 0
  raskren said:
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"];

  • 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
	);
}

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

    • No registered users viewing this page.
  • Posts

    • "New" Outlook is not even a mobile app (mobile app has Unified Inbox at least), this is just their web app with an added ability to use email account other than Microsoft's.
    • Sounds like a good time to do a fresh install of Windows. WTF people...
    • It only includes Russia. All other territories come at an additional cost of $20/pm/per territory you want to use it in.
    • From cars to cosmos: Honda's experimental rocket aces first landing test by Paul Hill Image via Honda Watch your back SpaceX, the Japanese company Honda has just performed a successful first launch of its experimental reusable rocket. The 6.3 meter rocket, which weighs 900kg, reached a modest altitude of 271.4 meters, but managed to land within 37cm of its target (1.2 feet), which is certainly pretty close. The rocket took off from a Honda facility in Taiki Town, Hokkaido, a growing space town in Japan. The flight time was also modest, coming in at just 56.6 seconds, but in that time, Honda was able to demonstrate key reusability technologies such as flight stability and landing capability. This marks a significant milestone for Honda’s space R&D department, which began work just four years ago. If you remember the tests SpaceX was performing around 2012 with Grasshopper, well Honda is at about the same stage with its reusable rocket. Why Honda is building rockets: Beyond cars and motorcycles Honda said that it wants to leverage core technologies it already works on for offering space services. It said that reusable rockets are a key part of sustainable space transportation. By 2029, the company wants to be able to perform suborbital launches, and while commercialization hasn’t been decided yet, it sees itself launching remote-sensing and wide-area communication satellites in the future. The Japanese car maker sees growing demand for satellite launches and wants to be involved by developing reusable rockets which could help it perform such launches economically. If it does end up finding customers, it will add more competition to the rocket launch sector. While the company hasn’t confirmed this, by developing its own launch system, it could eventually be in a position to launch its own satellites that could provide services to its cars to add value for customers. The competitive landscape and Japan's space ambitions Honda is just the latest company to join the growing list of companies trying to develop reusable rocket technology. The most famous companies doing this are SpaceX and Blue Origin, but there are also lots of other companies around the world also developing this technology. Honda is still taking baby steps compared to SpaceX, but it shows that the company is taking a focused, step-by-step approach, and achieving successes as noted by this launch. Hopefully, the company ends up providing tough competition against SpaceX, Blue Origin, and other companies so that it can help to drive down prices and spur on innovation.
    • Does that subscription include international data roaming, inclusive of Russia?
  • Recent Achievements

    • Week One Done
      vivetool earned a badge
      Week One Done
    • Reacting Well
      pnajbar earned a badge
      Reacting Well
    • Week One Done
      TBithoney earned a badge
      Week One Done
    • First Post
      xuxlix earned a badge
      First Post
    • First Post
      Tomek Święcicki earned a badge
      First Post
  • Popular Contributors

    1. 1
      +primortal
      680
    2. 2
      ATLien_0
      288
    3. 3
      Michael Scrip
      223
    4. 4
      +FloatingFatMan
      194
    5. 5
      Steven P.
      145
  • Tell a friend

    Love Neowin? Tell a friend!