Add event responders to elements in a loop with Jquery - javascript

Lets say I have a page with 5 images, and I get an array of them all by
var images = document.getElementsByTagName("img");
Then I want to add a mousemove event to each one, my first instinct would be to do this:
for (var i = 0; i < images.length; i++){
$(images[i]).mousemove(function(e){
//do stuff
});
}
but that doesn't work, so how would this be possible?

$('img').mousemove(function(){
//do stuff
});

Related

Is this noramal that on event in jquery does not work out when I send data to a function during on event, then how can I fix that?

Why on event in j-query does not work? It just work one time.
I want to move data to another block when on event in j-query work, so I made arrays and when 'click' event occur, I move data to another array and execute function that is named 'showList'
but it work just one time
I want to know why this click event work just one time
function(dataList){
var arrayNum=[];
var arrayNumDown =[];
//up
var length = Math.floor(Math.random()*5+1);
var list = "<div>";
for(var i=0; i<length; i++){
list+="<div class=number>";
list+="<span>5523-1134-112"+i+"</span>";
list+="<img class=imageA src=../image/x.png.png style=width:10px; height:10px;></div>";
arrayNum.push("5523-1134-112"+i);
}
list+="</div>";
$('#numbers').html(list);
//down
var Dlength = Math.floor(Math.random()*4+1);
var ul="<ul>";
for(var i=0; i<Dlength; i++){
ul+="<li><input type=checkbox name=listCheck class=checkArr> <span id=spa"+i+">"+"2311-223-111"+i+"</span></li>";
arrayNumDown.push("2311-223-111"+i);
}
ul+="</ul>";
document.querySelector("#contents").innerHTML = ul;
$('#numbers').on('click','.imageA',function(){
var val =$(this).prev().text();
for(var i=0; i<arrayNum.length; i++){
if(arrayNum[i]==val){
alert(i);
arrayNum.splice(i,1)
arrayNumDown.push(val);
console.log(arrayNumDown);
showList(arrayNum,arrayNumDown);
}
}
})
$('.checkArr').on('click',function(){
var val=$(this).next().text();
for(var i =0; i<arrayNumDown.length; i++){
if(arrayNumDown[i]==val){
arrayNumDown.splice(i,1);
arrayNum.push(val);
console.log(arrayNum);
showList(arrayNum,arrayNumDown);
}
}
})
}
}
function showList(arrayNum,arrayNumDown){
var list = "<div>";
for(var i=0; i<arrayNum.length; i++){
list+="<div class=number>";
list+=arrayNum[i];
list+="<img src=../image/x.png.png style=width:10px; height:10px; id=x"+i+"></div>";
}
list+="</div>";
$('#numbers').html(list);
var ul="<ul>";
for(var i=0; i<arrayNumDown.length; i++){
ul+="<li><input type=checkbox name=listCheck id=chk"+i+"> <span id=spa"+i+">"+arrayNumDown[i]+"</span></li>";
}
ul+="</ul>";
document.querySelector("#contents").innerHTML = ul;
}
When you add the listener with .on("click"), it will only add it to the elements already available. When you dynamically add new elements, you need to add the listeners to those element after that.
The other option is to add the listener to the parent element and limit it with the selector variable to the wanted elements. This way it will work also on dynamically created elements:
$('#contents').on('click','.checkArr',function(){

Dynamically bond handler on multiple elements will call only last bond function

http://jsfiddle.net/7CV88/8/
On this snippet, I try to bind change to #r(Nth)e <input> element to change the contents of #r(N+1th)s <input> element. But when I change any Nth <input> element, the message shown is always "#r(last N)e change handler"
for(var i = 1; i < numRanges; i++){
$('#r'+i+'e').change(function(){
$('#messages').html('#r'+i+'e change handler');
$('#r'+(i+1)+'s').val($('#r'+i+'e').val());
});
}
You should use the so-called event data to pass the value of i into the onchange event handler:
for(var i = 1; i < numRanges; i++){
$('#r'+i+'e').change(i, function(e){
$('#messages').html('#r'+e.data+'e change handler');
$('#r'+(e.data+1)+'s').val($('#r'+e.data+'e').val());
});
}
Updated Demo.
Note: This just answers directly to your asked problem, I know your code is messy, fixing it is not the main thing to do.
This is a typical "closure" issue.
I was trying the simplest way to get out of the closure issue so I suggested this incorrect way:
for(var i = 1; i < numRanges; i++){
$('#r'+i+'e').change(function(){
var tempVariable = i;
$('#messages').html('#r'+tempVariable +'e change handler');
$('#r'+(tempVariable +1)+'s').val($('#r'+tempVariable +'e').val());
});
}
Thanks to metadings, I realized my mistake so I created a demo to test according to their advice:
var list = $("div");
for(var i = 0; i < list.length; i++){
$(list[i]).click((function(x){
return function(){alert(x);};
})(i));
}
http://jsfiddle.net/9qBXn/
HTH

Jquery wrapping my content with divs using append

for(var i=0; i<num_cols; i++)
{
//Wrapper for column
$('#cupcake-list').append('<div>');
//end wrapper
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$('#cupcake-list').append('<p>'+cupcakeData[d].name+'</p>');
}
//Wrapper for column
$('#cupcake-list').append('</div>');
//end wrapper
}
I just want to encapsulate my p tags within div tags to act as rows, however all I get are <div></div><p>ssdfsdf</p><p>sdfsdfdsf</p><div></div>etc....
What's the best way of doing it?
Start with a fragment so that you don't access the DOM more than once, and append it all at the end. You can skip the wrap by starting with your empty fragment, like so:
var $fragment;
for(var i=0; i<num_cols; i++)
{
$fragment = $('<div />');
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$fragment.append('<p>'+cupcakeData[d].name+'</p>');
}
//Wrapper for column
$('#cupcake-list').append($fragment);
//end wrapper
}
This is a much faster way to do it! Append parts of a string to an array and then you only have to update the DOM once.
var a = [];
for(var i=0; i<num_cols; i++)
{
a.push('<div>');
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
a.push('<p>'+cupcakeData[d].name+'</p>');
}
a.push('</div>');
}
$('#cupcake-list').append(a.join(''));
EDIT:
I'll explain why yours wasn't working. When you were calling $('#cupcake-list').append('<div>'); you thought it would only add the opening div tag, but that is not the case. jQuery won't let you do this is because they want to make sure the html is valid after every function call. If you were to just add the opening div and then do some other stuff, the next closing div (</div>) in the document would close the div you just opened, changing the structure of the document entirely.
In summation:
$('#cupcake-list').append('<div>'); and $('#cupcake-list').append('</div>'); will both append <div></div> to the document. Also, access and update the DOM as if it costs you a million dollars because it is among the slowest things you can do in javascript.
jQuery has a method called .wrap, and some similar ones (.wrapAll).
If you are having the output that you showed, your code is not reaching the inner for, so you have a logic problem. I think your way of doing this is correct. When i need to build some structure on the fly i usually do the same thing.
JQuery append adds DOM nodes, not HTML. So you can accomplish your task like this:
for(var i=0; i<num_cols; i++)
{
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$('#cupcake-list').append($('<div></div>').append('<p>'+cupcakeData[d].name+'</p>'));
}
}
First, $('<div></div>') creates a new empty div element not yet attached to the page (you can also do $('<div>') as a shorthand if you want). Then .append('<p>...</p>') adds a p element inside the div. Finally, $('#cupcake-list').append(...) adds the whole div to the end of #cupcake-list.

Events will not fire that have been added to dynamically created divs

I'm working in JavaScript. For the most part I've been able to add event listeners fine, but for divs that I have generated dynamically whatever event I add to them nothing seems to happen. The code is:
for(var i=0; i<sceneNumber; i++){
var a=i;
if(i>2)
a=i%3;
sceneArray[i]=document.createElement('div');
sceneArray[i].className="border"+a;
if(i%2==1)
sceneArray[i].style.left=0;
else
sceneArray[i].style.left=(i+1)*100;
sceneArray[i].style.top = i*100+100;
sceneArray[i].onclick= function(){console.log("fire212");
if(extend1){
console.log("scenelistener");
currentArrow.rotate(degrees);
currentArrow.scale(desiredLength/arrowLength,1);
}
};
console.log(sceneArray[i].onclick);
document.getElementsByTagName('body')[0].appendChild(sceneArray[i]);
sceneArray[i].style.zIndex = -1;
console.log(sceneArray[i]);
}
As you can see I should at least get "fire212" in the console but even that doesn't happen. What could be going wrong?
You should implement something similer to JQuery's live() or on() methods. The below post may help you.
http://www.alfajango.com/blog/exploring-jquery-live-and-die/
for(var i=0; i<sceneNumber; i++){
var a=i;
if(i>2)
a=i%3;
sceneArray[i]=document.createElement('div');
sceneArray[i].className="border"+a;
if(i%2==1)
sceneArray[i].style.left=0;
else
sceneArray[i].style.left=(i+1)*100;
sceneArray[i].style.top = i*100+100;
sceneArray[i].onclick=onclickevent();
console.log(sceneArray[i].onclick);
document.getElementsByTagName('body')[0].appendChild(sceneArray[i]);
sceneArray[i].style.zIndex = -1;
console.log(sceneArray[i]);
}
function onclickevent(){
console.log("fire212");
if(extend1){
console.log("scenelistener");
currentArrow.rotate(degrees);
currentArrow.scale(desiredLength/arrowLength,1);
}
}

Detect clicks of images inside iframe

I cant figure out why this isn't working. It's probably something simple. The iframe is from the same domain as parent page.
I know I can use jQuery, but I want to learn to do it in pure JavaScript.
My code so far:
document.getElementById('my_iframe').onload = function() {
document.getElementById('my_iframe').contentWindow.document.getElementsByTagName('img').onclick = function() {
alert("image in iframe was clicked");
}
}
Forget the frame business for a second, and look at this code:
document.getElementsByTagName('img').onclick = function() {
Will that ever work? No. You are getting an object (a NodeList, to be precise) containing all the img elements in the document. You are adding an onclick property to that object. Not to the elements themselves: to an object that points to them. The function will never be fired because it is never applied to any elements.
You should do exactly the same as you normally would: loop though all the images you've found and apply the function to them individually.
var onclickFn = function() {
alert("image in iframe was clicked");
},
images = document.getElementById('my_iframe').contentWindow.document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
images[i].onclick = onclickFn;
}
document.getElementsByTagName is returning a collection of images. You can't just set a click handler on the entire collection. You need to loop through them one at a time.
var allimgs = document.getElementById('my_iframe').contentWindow.document.getElementsByTagName('img');
for (var i = 0; i < allimgs.length; i++) {
allimgs[i].onclick = function() {
alert("image in iframe was clicked");
};
}

Categories