I think I can explain this properly. I have a function that I want to call with an onclick event on several divs.
$scope.dataArray = []; //array for holding values from another function
$scope.myFunction = function(id) {
var val1 = id[0];
var val2 = id[1];
}
And I want to assign this function to an onclick on divs that I append to a parent inside this function.
$scope.appendDivs = function (someData) {
var result = someData; // an array
var parentContainer = document.getElementById('parent-container');
for( var i = 0; i < result.length; i++)
{
var div = document.createElement('div');
div.className = "child-element";
parentContainer.appendChild(div);
div.onclick = function() {
$scope.myFunction(result.id); //pass an array of data to myFunction
};
div.innerHTML = result[i].data1 + "<br>" + result[i].data2;
}
The problem lies in when I click the div to activate the onclick call and I debug to see what's going on, $scope.myFunction always gets passed the length of "result" where nothing is defined at. i.e. a length of 3 has elements 0, 1 and 2. myFunction tries to look at results[3]. Is there a way I can have each div know which element to pass to myFunction?
I was able to get around my problem by piggybacking my value onto div.id. I don't need the id of the div for anything, and I was able to get rid of the dataArray as well. So now I can just pass the value I need into myFunction and it's the corresponding value to the div that is clicked. Thanks for your time though guys!
Related
I am working on a project where the user decides how many buttons are there, and then each button triggers a different function.
What I have done is: I have an input that asks "Enter the number of buttons" and a "Submit" button. When the "Submit" button is clicked, the value of variable n is set to the user-defined value.
I then have the following code (assuming the user has set n to 10):
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
x.onclick = function() {alert(i)};
document.body.appendChild(x);
}
What I want is, that when div with id i is clicked, the pop-up message says i. But what has ended up happening is, that no matter which div I click, the pop-up message always says 10.
Why is this happening? How to fix this?
The only thing you need to change is the assignment of i inside the for-loop. Use let to define a locally-scoped variable. Also, use textContent instead of innerHTML for simple text. It is recommended to used const/let rather than var.
for (let i = 0; i < 10; i++) {
const x = document.createElement('div');
x.id = i;
x.textContent = i;
x.onclick = function() { alert(i) };
document.body.appendChild(x);
}
By iterating over your NodeList elements, you can take this next approach.
First of all, append all your created divs in your HTML and continue by looping through the elements list by document.querySelectorAll("div")
That way you select all elements and then assign an addEventListener to each one of the items. On your alert function, print this.id and it will return you the number of the id of the element which corresponds to your i index.
It would be the same also if you just put the whole addEventListener function inside the other loop.
I just separated both so you can understand it better.
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
document.body.appendChild(x);
}
let divs = document.querySelectorAll("div");
for(var a= 0; a < divs.length; a++){
divs[a].addEventListener("click", function(){
alert(this.id);
});
}
You can use getAttribute to read the id of the elements. I show you an example:
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
x.onclick = function(e) {
let dataId= e.currentTarget.getAttribute("id")
alert(dataId)
};
document.body.appendChild(x);
}
Explanation:
getAtrribute() returns the value of an html attribute as a string, just enter the name of the attribute in braces to get the value. In this case I entered "id" which is the value we want to retrieve.
Also to get the value of the element where you click I use currentTarget, to accurately retrieve the value of the div that the iteration creates. If you use target, and inside the div you have more elements, this code will generate an error. Therefore, it is important to use currentTarget for this application.
This happen because after the initialisationn the function will look for the value of i which is always 10 (once it has been initialized)
EDIT
As explained by #Mr. Polywhirl in his better answer, you can use let in your for loop to declare your variable locally instead of globally.
To solve your problem you can pass an event to the function (the click event) and the getting your value.
It can be done with either :
The value of the content (as you did with x.innerHTML)
Adding an id to the div and getting this id
Example :
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
x.onclick = function(event) {
alert(event.target.innerHTML) // with the content
alert(event.target.id) // with the id
};
document.body.appendChild(x);
}
I know that the title sounds weird but I don´t know how to exactly describe my problem. I have an array with all the divs id I created before. Now I want to take the first div´s id and remove the div by parentNode.removeChild(); The console prints:
'The "removeChild" property of an undefined or null reference can not be retrieved.'
I hope you can help me with that :)
var animation_time = 1500;
var div_id_selection = [];//it contains 'div0', div1, div2 ... divn
var array_counter = -1;
// Before that is a function that creates a div by document.createElement("div); with the id div0, div1, div2 ...than it writes the id into the array:
div_id_selection.push('div' + id);
var delete_divs = function(){
setTimeout(function(){
array_counter += 1;
var div_to_delete = div_id_selection[array_counter];
//var div_to_delete_str = div_to_delete.toString(); I already tried it with the string-didn´t work
console.log(div_to_delete);
console.log(array_counter);
div_to_delete.parentNode.removeChild(div_to_delete); // here is the problem
}, animation_time);
}
div_to_delete is a string ( id that is stored in the array ).
parentNode method is only available on a DOM object.
You will have to first select the element using the id.
// get the correct DOM object using the array
var elem = document.getElementById(div_to_delete);
elem.parentNode.removeChild(elem);
Firstly, I'm trying to create multiple DOM nodes and cache them as a variable for use in a function. What I want to do is create a function that sets-up the elements by classname. Then call that function as variable for use later.
Secondly, I'm not sure what the correct syntax is when manipulating inserted nodes via classname, when you want to select all classes with that name.
i.e for (var i = 0; i < insertedNodes.length; i++) {
To clarify what exactly I'm asking, my questions are this:
How to insert nodes as variables for use later on in function.
How to call those each of those variables.
How to call both of those variables together.
Hopefully my code will help explain what I'm trying to understand a little further:
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
var node1 = {};
var node2 = {};
var bothNodes = {};
function nodes() {
function insertNodes() {
node1 = div1.appendChild(nodeBase);
node2 = div2.appendChild(nodeBase);
bothNodes = [node1, node2];
}
function nodeBase() {
var node = document.createElement('div');
node.className = 'newNode';
}
function dosomething(node1, node2) {
//
}
function dosomethingElse(bothNodes) {
//
}
}
new nodes();
You don't return node here..
function nodeBase() {
var node = document.createElement('div');
node.className = 'newNode';
// ADD THIS LINE
return node;
}
And, as pointed out by Felix in the comment:
function insertNodes() {
node1 = div1.appendChild(nodeBase()); // Fixed
node2 = div2.appendChild(nodeBase()); // Fixed
bothNodes = [node1, node2];
}
This might get drowned with down votes, but pointing you to another direction.
How to insert nodes as variables for use later on in function.
you don't actually have to store those elements. You can always query them later.
How to call each of those variables.
You can select the first matching element with a particular class as follows:
var div1 = document.getElementsByClassName('.div1')[0];
OR
var div1 = document.querySelector('.div1');
How to call both of those variables together.
You can select all elements with a particular class, iterate over the collection and apply your logic as follows:
var nodes = document.getElementsByClassName('.div1');
OR
var nodes = document.querySelectorAll('.div1');
for(var i=0;i<nodes.length;i++){
// your loic
}
I know the question sounds strange, but it's really very simple. I have the following function which isn't working:
function start40Counter(counter40_set){console.log(counter40_set);
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
cont += "<a class='suitpick' onClick='pickSuit(counter40_set);'><img src='"+base+"images/someimg.png' title='Odaberi' /></a>";
});
$('#game40_picks').html(cont);
}
counter40_set is [10, 3, ["H", "S"]]. The part of the function that fails is the part this:
onClick='pickSuit(counter40_set);'
It says that counter40_set is not defined. I understand that. This wouldn't even work if counter40_set was a simple string instead of an array. If I try onClick='pickSuit("+counter40_set+");' I get a different error, saying H is not defined. I get this too, the array is rendered and JS doesn't know what H and S are.
I also tried passing the array elements (counter40_set[0] etc) individually but it still fails with the last element (["H", "S"]).
So, how do I pass this data to the onClick function in this case? There must be a more elegant way than concatenating the whole thing into a string and passing that to the function?
Btw, this is a simplified version. What I should really be passing in every iteration is [suit, counter40_set] so that each link chooses a different suit. I'm asking the simplified question because that will be enough to send me down the right path.
It cannot work,because the context is lost and thus "counter40_set" is not set.
To fix it simply use jquery for the onlick as well:
$('#game40_picks').empty(); // get rid of everything
$.each(suits, function (num, suit) {
var line = $("<a class='suitpick'><img src='"+base+"images/"+cardsuits[suit].img+"' title='Odaberi "+cardsuits[suit].name+"' /></a>");
line.click(function(ev){
ev.preventDefault(); // prevent default click handler on "a"
pickSuit(counter40_set);
});
$('#game40_picks').append(line);
});
this way the "counter40_set" is available for the click function.
You shouldn't use the onClick HTML attribute. Also, using DOM functions to build nodes saves the time it takes jQuery to parse strings, but basically the method below is to create the element and attach a click event listener and then append it to the specified element.
function start40Counter(event){console.log(event.data.counter40_set);
var counter40_set = event.data.counter40_set;
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
var link = document.createElement('a');
link.className = 'suitpick';
$(link).on('click', {counter40_set: counter40_set}, start40Counter);
var img = document.createElement('img');
img.src= base + "images/" + cardsuits[suit].img;
img.title = 'Odaberi ' + cardsuits[suit].name;
link.appendChild(img);
$('#game40_picks').append(link);
});
}
Not tested but it might work out of the box.
I've read a billion questions like this, but never found an answer yet.
Anyway, when I type
var variableContainingID = "header";
var div = $("#"+variableContainingID);
It returns 'undefined'
But when I type
var variableContainingID = "header";
var div = $('[id^="'+variableContainingID+'"]');
It works fine.
Any ideas why?
UPDATE
var json = '{"divs":['
var children = $(".parent_container > div");
var idArray = [];
var numArray = [];
for (var x=0; x<children.length; x++) {
var eleid = $(children[x]).attr("id");
idArray.push('"'+eleid+'"');
numArray.push(x+1);
}
var idString = idArray.join(",");
var numString = numArray.join(",");
json += idString;
json += '],"number":['+numString+']}';
var obj = JSON.parse(json);
for (x in obj["divs"]) {
var div = $('[id^="'+obj["divs"][x]+'"]');
}
Do you think the double quotes could be throwing it off?
As you wrote in your question:
var div = $("#"+variableContainingID);
var div = $('[id^="'+variableContainingID+'"]');
These two lines are not identical. The first one, will select an element with id of header. The second one,
selects elements that have the specified id with a value beginning exactly with a given string (header).
So if you have an element like this:
<div id="headerHere"></div>
The first one ($("#"+variableContainingID)) can't select it, but the second one ($('[id^="'+variableContainingID+'"]')) can select that element.
This is because you used ^= in your selector. See jQuery API: Attribute Starts With Selector (name^="value").
It's worth to see all attribute selectors in jQuery.
Attribute Selectors in jQuery