I have list of input area in the form with id like "contact1_title", "contact2_title", "contact3_title" ....
And I also have a list of selection in this form with id like "contact1_name", "contact2_name", "contact2_name" ....
I want to write a loop to dynamic bind the onchange function for the selections.
Here is my code:
for(var j=1;j<6;j++){
$('#contact'+j+'_name').change(function() {
alert(j);
//json.engineer is a json object
$('#contact'+j+'_title').val( json.engineer[this.selectedIndex-1].title );
});
}
When I change the selection, it always alert 6.
and title input area cannot be changed by select.
Does it mean the variable in javascript always change?
How can I bind an action dynamically?
I can hack it by using "this.name.split("_")[0]" but the code seems ugly.
Thanks in advanced.
Wrap your change functionality by closure:
for(var j=1;j<6;j++){
(function(j){
$('#contact'+j+'_name').change(function() {
alert(j);
//json.engineer is a json object
$('#contact'+j+'_title').val( json.engineer[this.selectedIndex-1].title );
});
})(j);
}
The problem was, when you click, your loop is already ended, so j is equal to 6.
Another solution would be to pass the counter as event data:
for(var j=1;j<6;j++){
$('#contact'+j+'_name').change({index: j}, function(event) {
$('#contact' + event.data.index + '_title')
.val(json.engineer[this.selectedIndex-1].title );
});
}
Even better would be if you could avoid using a for loop, but that depends on your markup and whether you have control over the created elements since you probably have to adjust them to do so.
There is a closure already, use it efficiently.
for(var j=1;j<6;j++){
$('#contact'+j+'_name').change(function() {
var k=j;
alert(k);
//json.engineer is a json object
$('#contact'+k+'_title').val( json.engineer[this.selectedIndex-1].title );
});
}
Related
[First time on stackoverflow.] I am trying to dynamically add html buttons to my page and then give them a javascript function to run when they are clicked, using jQuery's click. I want to have one button for each element in an array, so I used a for loop. My code looks like this (simplified)
for (var i = 0; i < results.length; i++) {
$("#" + place[i].place_id).click(function(){console.log("Test");})
$("#" + place[i].place_id).click();
}
(I inject buttons with the right id's in the same loop.) This code, when run, console logs "Test" the right number of times, but afterwards, only the last button responds "Test" when clicked. (This situation is a little absurd.) So, I think the event handler ends up using only the final value of i to assign the event handler. I think the problem has to do with closures, but I am not sure how to make a closure out of a jQuery Selector (and in general am not familiar with them).
In contrast, as a hack solution, I "manually" wrote code like the below right below and outside the for loop, and it works as expected, in that clicking causes the console log.
$("#" + place[0].place_id).click(function(){console.log("Test"););
$("#" + place[1].place_id).click(function(){console.log("Test");});
etc.
(Of course, this all occurs within a larger context - specifically a Google Maps Places API call's callback.)
First, am I understanding the problem correctly? Second, what would work? Should I take a different approach altogether, like use a .each()?
(I later would want to display a property of place[i] when clicked, which I would think would need another callback
My final hack code looks like this:
$("#" + place[0].place_id).click(function(){google.maps.event.trigger(placeMarkers[0], "click"); repeated 20 times
To do this, you can simply create a self executing function inside the for loop, like this:
for (var i = 0; i < results.length; i++) {
(function(index) {
$("#" + place[index].place_id).click(function() {
//Do something with place[index] here
});
})(i);
}
In my research and attempts to use JavaScript to add rows to a HTML Table dynamically, it was important that each id tag be incremented according to the row number. I found various suggested ways of doing this. Finally, I thought I'd give a try at writing a recursive function to do the trick. The following works. But I do not know if it could be optimized. Kindly let me know what I can do to improve it.
function incrementElementID(element, incrementVal) {
if(element.hasAttribute("id")) {
idVal = element.getAttribute("id");
element.setAttribute("id",idVal+incrementVal);
}
var numChildren = element.childElementCount;
for (var i=0; i<numChildren; i++)
incrementElementID(element.children[i],incrementVal);
return;
}
Best done with a closure variable if you're not intentionally trying to use recursion.
Set a variable outside the function scope and increment it within the function.
You're better off with some simple jQuery:
var incrementVal = ...
$("[id]").each(function(index, value) {
elem = $(value);
elem.attr("id", +elem.attr("id") + incrementVal);
});
$("[id]") selects any element that has an id attribute: http://api.jquery.com/has-attribute-selector/
.each iterates through all the items in the collection: https://api.jquery.com/jQuery.each/
The + at the front of +elem.attr("id") converts the attribute value from a string to an int.
What am I missing here?
As part of an answer to How can i change options in dropdowns if it is generated dynamically?
I have an issue inside an onchange. I want to set all the siblings values to the value of the changed select
$("select").on("change",function() {
var idx=$(this).val();
console.log($(this).attr("id"),$(this).val())
$(this).siblings("select").each(function() {
$(this).val(idx);
});
});
Here is the generated code in a JSFIDDLE
I have seen
How do i get the value of all other dropdowns when one of them is changed
but I prefer to find the reason for my error
You are using the val method as a property.
var idx=$(this).val;
// ----^
http://jsfiddle.net/Vr5Je/
You can also use the val method instead of each:
$("select").on("change", function() {
$(this).siblings("select").val(this.value);
});
http://jsfiddle.net/Pq2vq/
Got a question for you javascript gurus out there. I'm creating a sidebar tool that is comprised of a few different text input fields. The purpose of this tool is to edit copy on a template. I've tried to pass the data entered into the field onchange, but I'm running into problems dumping the data into my js object. This is somewhat what I have in mind:
$('myInputField').(function(){
$(this).onChange(){
// write to variable X
}
});
Essentially I want to have what I'm typing in the input be mimicked live and then I can parse the changes to my database.
$('#myInputField').(function(){
$(this).onkeyup(){
x = this.value;
}
});
or more succinctly:
$('#myInputField').onkeyup(){
x = this.value;
});
You're just looking for the value that's in myInputField within that event handler? Something like this?:
$('myInputField').(function(){
$(this).onChange(){
x = $(this).val();
}
});
I don't remember off the top of my head if this is already a jQuery object. If it is, then this should work and perhaps skip a little bit of overhead:
x = this.val();
Additionally, you can explicitly reference the field with a normal jQuery selector if this is ever overridden with a different context, or if you want to reference other fields as well, etc.:
x = $('myInputField').val();
The problem is, on IE, the onchange event doesn't work on INPUT elements. Thus, you have to use the onkeypress or the onblur event depending on what you want to do.
JS way:
document.getElementById('myInputField').onblur = function() {
var x = this.value
}
jQuery way:
$('#myInputField').blur(function() {
var x = this.value
})
Wouldn't a simply keyup event on the input fields be sufficient?
jQuery:
$('textarea').keyup(function() {
$('#foo').html($(this).val());
});
HTML:
<textarea></textarea>
<div id="foo"></div>
jsFiddle example.
i plan to show some images on the page and when the user press up button some related new images will be shown. I have been achieving that by changing the "src" attribute already existing image html tag.
i have json data like [["a","b"],["c","d"]] which gives the name of images like a.jpg, b.jpeg etc.
Here is the problem i can not pass the array value to jquery click object. my javascript functions as below:
var a; // a global variable holding the json array [["a","b"],["c","d"]]
function rileri(){ //img next
var ix=parseInt($("#up").attr('rel'));
ix=(ix+1)%a.length;
for(var i=0;i<2;i+=1){
$("#k"+i).attr("src","img/m/t/"+a[ix][i]+".jpg");
$("#k"+i).click(function() { rgetir(a[ix][i]);}); //problem is here!!
}
$("#up").attr('rel',ix); // i keep index data of appearing img on "rel"
}
function rgetir(n){ //img down ajax
$("#brc").load("data/rgetir.php", {'name':n});
}
I wonder how can i bind click event and if there is any better solutions ?
html is like that (no "src" at start, is it ok ?):
<img id="k0"/><img id="k1"/>
<input id="up" rel="0" type="button" onclick="rileri()" value="Next">
Yeap the main problem is passing the multidimensional array value to a function :(
The problem has nothing to do with "multidimensional arrays." It is that you are using i inside the assigned click value, and i changes with every iteration of the loop. Each assigned click value holds a reference to i, so when rileri is finished each points to the same value. You need to break the reference, usually done by passing i to a function and binding the click in there.
There are many flavors of using a function to break a reference, but since you're using jQuery and iterating an array, we'll use $.each:
(what follows is untested but should serve as an example)
function rileri(){
var ix=parseInt($("#up").attr('rel'),10);
ix=(ix+1)%a.length;
$.each(a[ix], function (i) {
var img_name = this;
$("#k"+i)
.attr("src","img/m/t/"+img_name+".jpg")
.click(function () {
rgetir(img_name);
});
if (i >= 2)
{
return false;
}
});
$("#up").attr('rel',ix);
}
Here is a simple fiddle that shows your problem
http://jsfiddle.net/MHJx6/
The problem is your ix and i variables are closures, so at the time the event runs they have the wrong values as you can see in this example.
I tried to write some code that will do what I think you are trying to do below. It would be easier if I knew what you were trying to do (use case). Maybe this is what you want?
var a; // a global variable holding the json array [["a","b"],["c","d"]]
function rileri(){ //img next
$("#k0").click(function() { handleClick(0); });
$("#k1").click(function() { handleClick(1); });
}
function handleClick(index) {
var ix=parseInt($("#up").attr('rel'));
ix=(ix+1)%a.length;
$("#k"+index).attr("src","img/m/t/"+a[ix][index]+".jpg");
$("#up").attr('rel',ix);
}