• 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

    • Ah .. lockout for suspicious activity. I bet they uploaded the SanDisk utility detected as malware
    • Microsoft 365 will soon disable outdated authentication protocols for file access by Usama Jawad On a fairly regular basis, Microsoft disables outdated protocols that are used to access its services. In the past few years, the company has deprecated Basic Auth in Exchange Online and cut access to Outlook for third-party apps relying on this protocol. Now, it has decided to get rid of old authentication protocols for file access across Microsoft 365 services. As reported by Bleeping Computer, Microsoft has posted a message on its Microsoft 365 Admin Center. Starting from mid-July 2025, the company will begin disabling legacy authentication protocols used to access files across Microsoft 365 and Office apps, SharePoint, and OneDrive. Essentially, applications or services which use the Relying Party Suite (RPS) or FrontPage Remote Procedure Call (FPRPC) will to perform browser-based authentication to perform open operations on Office files will no longer be able to do so. As expected, this is primarily being done to improve the cybersecurity posture of various services. Microsoft states that RPS can be brute-forced and phished with relative ease as it is fairly outdated. Similarly, FPRPC is typically used for remote web page authoring and it is susceptible to exploitation through various vulnerabilities too. As such, both of these protocols will be disabled by default starting from mid-July 2025, with the rollout of this change targeting completion by August 2025. The Redmond tech giant will update the protocol baseline by default without mandating any licensing changes for customers. In addition, once these modifications are rolled out, Microsoft 365 will require admin consent to get third-party access to files and sites. IT admins can view the guidance available here to configure admin consent workflows. Microsoft says that these changes align with the principles of its Secure Future Initiative (SFI). Earlier today, it announced the rollout of improved security defaults for Windows 365 citing the same reasons too.
    • It does and it can... I took an i3 board and upgraded it to my FX8350... no issues, just put in new drivers over the top that Windows didn't. Not the issue for me, (though I eventually did do a new install from 23H2 to 24H2)... I was on 22H2 at the time. The issue is activation. You may get hit with having to activate again.
  • Recent Achievements

    • First Post
      Fuzz_c earned a badge
      First Post
    • First Post
      TIGOSS earned a badge
      First Post
    • Week One Done
      slackerzz earned a badge
      Week One Done
    • Week One Done
      vivetool earned a badge
      Week One Done
    • Reacting Well
      pnajbar earned a badge
      Reacting Well
  • Popular Contributors

    1. 1
      +primortal
      708
    2. 2
      ATLien_0
      284
    3. 3
      Michael Scrip
      218
    4. 4
      +FloatingFatMan
      197
    5. 5
      Steven P.
      130
  • Tell a friend

    Love Neowin? Tell a friend!