• 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

    • Yeah!!!! I was damn well shocked to see the tab with previous file open when I clicked on the new file. It had private info and I was opening another file to show another person. That was weird
    • The article says the whole setup is about the size of a pencil case which sounds pretty portable to me.
    • I thought router has to have 6 Ghz band to be called wifi-7, guess I was wrong...
    • I have the Pixel 9 Pro XL...Unless this thing is "leaps and bounds" faster than the 9, I'll pass. And by leaps and bounds, I don't mean on benchmarks. "Real world" faster. Most people don't even come close to topping out the performance of their phones. Tensor G5 is Google's most powerful chip to date, boasting a staggering 36 percent performance leap over G4.
    • MIT's stunning 'bubble wrap' device squeezes water out from thin air even in deserts by Sayan Sen Image by Matteo Roman via Pexels Massachusetts Institute of Technology (MIT) engineers have built a new kind of device that can pull clean drinking water straight out of the air—no electricity needed. It’s designed for areas where water is scarce and traditional sources like rivers or lakes aren’t reliable. Right now, more than 2.2 billion people globally don’t have access to safe drinking water. In the United States alone, 46 million face water insecurity, with either no running water or water that’s not safe to drink. This new device, called an Atmospheric Water Harvesting Window (AWHW), uses a unique hydrogel panel that looks like black bubble wrap. These dome-shaped bubbles soak up water vapor from the air, especially at night when humidity is higher. During the day, sunlight makes the vapor inside evaporate. That vapor then condenses on a glass surface and drips down through a tube, turning into drinkable water. The AWHW doesn’t rely on power sources like batteries or solar panels. It’s completely passive, meaning it works on its own. The team tested a meter-sized panel in Death Valley, California, one of the driest places in North America, and got between 57.0 and 161.5 milliliters of water per day even with humidity as low as 21 percent. That’s more than what other similar passive devices have managed. “We have built a meter-scale device that we hope to deploy in resource-limited regions, where even a solar cell is not very accessible,” said Xuanhe Zhao, a professor at MIT. “It’s a test of feasibility in scaling up this water harvesting technology. Now people can build it even larger, or make it into parallel panels, to supply drinking water to people and achieve real impact.” Another cool part of the design is how they kept the water safe to drink. Usually, these kinds of hydrogels use salts like lithium chloride to absorb more vapor but that can lead to salt leaking into the water, which isn’t ideal. To solve this, MIT’s team mixed in glycerol, a compound that helps keep salt locked inside the gel. In testing, the lithium ion concentration in the harvested water stayed below 0.06 ppm (parts per million), which is way below the safe limit. The hydrogel domes also give the material more surface area, letting it collect more vapor. The outer glass panel is coated with a special polymer film that helps cool the glass, making it easier for vapor to condense. “This is just a proof-of-concept design, and there are a lot of things we can optimize,” said lead author Chang Liu, now a professor at the National University of Singapore. “For instance, we could have a multipanel design. And we’re working on a next generation of the material to further improve its intrinsic properties.” Published in Nature Water, the study says the AWHW could last at least a year and shows promise for making safe, sustainable water in places with harsh climates. The researchers believe an array of vertical panels could one day supply water to individual households, especially in remote or off-grid locations. Source: MIT News, Nature This article was generated with some help from AI and reviewed by an editor. Under Section 107 of the Copyright Act 1976, this material is used for the purpose of news reporting. Fair use is a use permitted by copyright statute that might otherwise be infringing.
  • Recent Achievements

    • One Month Later
      Ricky Chan earned a badge
      One Month Later
    • First Post
      leoniDAM earned a badge
      First Post
    • Reacting Well
      Ian_ earned a badge
      Reacting Well
    • One Month Later
      Ian_ earned a badge
      One Month Later
    • Dedicated
      MacDaddyAz earned a badge
      Dedicated
  • Popular Contributors

    1. 1
      +primortal
      506
    2. 2
      ATLien_0
      209
    3. 3
      Michael Scrip
      204
    4. 4
      Xenon
      143
    5. 5
      +FloatingFatMan
      121
  • Tell a friend

    Love Neowin? Tell a friend!