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

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

Related

onclick triggered automatically - how to create button on the fly

I tried to search through similar questions but I can't get a solution.
I have a snippet of code which is creating some HTML to append to a div:
var list="<ul>";
for(i=0; i<data.length; i++) {
sid=data[i].sid;
list += "blablabla <a onclick=delete(sid)>delete</a></li>";
}
list +="</ul>";
document.getElementById("my_container").innerHTML = list;
The function delete(sid):
function delete(Sid){
doSomething(taskSid,
function(error) {
if(error) {
console.log(error.code);
console.log(error.message);
return;
}
console.log("deleted");
}
);
The problem is that the function delete(sid) is called automatically.
I have read that it's because I am calling directly the function, and I have tried different proposed solutions, but cannot really make them work.
My code will create a several rows which have this button or link which need to call the function delete.
Probably it is completely wrong also the approach of having one container and define the list in javascript?
Any help appreciated.
Thanks
You should try binding the function
<a onclick=delete.bind(null,sid)>delete</a>
Something like this bind prepares your listener to be executed here you are calling the function so because of that it get executed right away. You can also try arrow function here and calling delete function from inside it, like this
<a onclick=()=>delete(sid)>delete</a>
Better approach is to use createElement method. Something like this:
let list = document.createElement('ul');
for(i = 0; i<data.length; i++) {
let sid=data[i].sid;
let link = document.createElement('li');
link.innerHTML = 'delete';
link.onclick = function(){
deleteTask(sid);
};
list.appendChild(link);
}
document.getElementById("my_container").appendChild(list);

button OnClick event not firing

There is a page and I am trying to attach an onclick event to the button ("SEARCH CRUISES") on the page but the onclick event is not firing correctly. Here is my code:
<script>
debugger;
var x = document.getElementsByClassName("cdc-filters-search-cta")
for (i=0; i< x.length; i++){
if(x[i].text.trim().indexOf("SEARCH") >= 0 && x[i].text.trim().indexOf("CRUISES") >= 0){
x[i].onclick = function(){
console.log("Search button clicked");
};
break;
}
}
Here is the complete html: https://jsfiddle.net/g0tkqrx6/
I have tried attaching the onclick event to the object in many different ways but I am not able to get the click event to fire. I would appreciate if anybody can provide some insight as to what I could be doing wrong here.
Thanks in advance
Seeing your html would be helpful. Make sure you are interacting with the correct names for your js events.
You must use textContent for element text and make it uppercase.
Here is an example:
var x = document.getElementsByClassName("cdc-filters-search-cta")
for (var i=0; i< x.length; i++){
var element = x[i] ;
if((element.textContent ).toUpperCase().indexOf("SEARCH") >= 0 && element.textContent.toUpperCase().indexOf("CARS") >= 0){
element.onclick = function(){
console.log("Search button clicked");
};
break;
}
}
<button class="cdc-filters-search-cta"> SEARCH</button>
<button class="cdc-filters-search-cta"> CARS</button>
<button class="cdc-filters-search-cta">SEARCH CARS</button>
Well to start with I think you should really take a look at this article on why you shouldn't add inline functions or css.
https://www.tomdalling.com/blog/coding-styleconventions/why-inline-comments-are-generally-a-bad-idea/
Secondly I think your issue is that you are trying to add a click event to an angular front end which is controlled by the ngModel and also the site is probably compiled AOT. However you can try this,
let x = document.querySelectorAll('.cdc-filters-search-cta');
let term = /[(SEARCH)(CRUISES)]/
x = Array.from(x);
x.forEach(span => {
if (term.test(span.textContent)) {
return span.addEventListener('click', (e) => {
console.log('span clicked')
});
}
})
I changed your code to querySelectorAll which returns an array and I used a forEach loop to add an eventListener. Not sure how well that will go down with your angular, but maybe.

javascript collapsible table without jquery

This is a simple question I can't seem to figure out and every google search returns a million ways to do this via jquery, but I'd prefer to use vanilla javascript because I am new to it and want to learn it well before using any libraries. What I am trying to do is have a button collapse part of a table when clicked and then show those hidden parts again when clicked again. Basically just toggling the display of a class of elements.
I have a button that calls the test() function
when clicked nothing on my table changes. Here is my javascript code. I am using collapse[0] because if I understand it correctly collapse is a nodeList and I always close and open all of these together so I only need to check the first element.
function test() {
var collapse = document.getElementsByClassName("catOne");
var i = 0;//Counter for loops
if(collapse[0].style.display === "table-row"){
for(i = 0; i < collapse.length; i += 1){
collapse[i].style.display = "none";
}
}
if(collapse[0].style.display === "none"){
for(i = 0; i < collapse.length; i += 1){
collapse[i].style.display = "table-row";
}
}
}
I've tested the function with this code:
function test() {
var collapse = document.getElementsByClassName("catOne");
var i = 0;//Counter for loops
for (i = 0; i < collapse.length; i += 1) {
collapse[i].style.display = "none";
}
which works fine on collapsing the elements so evidentally the issue is with my if statement, but my IDE, Netbeans, doesn't throw any errors and as far as I can tell it should be working.
Thanks for the help.
Link to html and javascript: https://jsfiddle.net/ozjbekjy/
I suspect there are a few problems working against you.
First, you need to make sure the test() function is defined earlier in the page than it's being used. With jQuery, that means using the $(function(){}) wrapper to apply event handlers on DOM ready. You can approximate the same thing yourself with something like this answer.
Otherwise, simply place the <script> tag somewhere before the table (probably in the <head>), and the onclick will work.
You also are using i += 1 where you could be using i++ - they accomplish the same behavior.
Secondly, instead of manipulating the style attribute, use the classList.toggle() function to simply add and remove a class that has the rule display: none, like so:
CSS
.hide-me {
display: none;
}
JavaScript
function test() {
var collapse = document.getElementsByClassName("catOne");
for (var i = 0; i < collapse.length; i++) {
collapse[i].classList.toggle("hide-me");
}
}
Your JSFiddle, with the suggested updates: https://jsfiddle.net/ozjbekjy/4/

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

Add event responders to elements in a loop with Jquery

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

Categories