jQuery appending multiple cloned DOM objects using a for loop - javascript

I'm attempting to make a simple shopping cart that pulls in cart objects from another page using a JSON file. However when I begin the process of appending a cloned DOM object to the product-list div it only appends the last object in the loop, essentially overwriting any objects before the final iteration.
$('document').ready(function(){
var cartArray = JSON.parse(localStorage.getItem("cart"));
console.log(cartArray);
parseData(cartArray);
})
function parseData(item){
// grab a clone of the aside
$copy = $('.cart-selection').clone();
//loop through and append a clone with modified JSON information for each item in the cart array
for(i=0; i<item.length; i++){
console.log(i);
$('h2', $copy).html(item[i].name);
$('img', $copy).attr("src", item[i].url);
$copy.appendTo($('product-list'));
}
}
I've tried several different variations using both .append and .appendTo with no luck. Any help would be greatly appreciated.

You should create another copy of the clone inside the loop.
The idea is to create a "prototype" of the element, and then create a copy of that prototype for each item in your loop:
// grab a clone of the aside
$clone= $('.cart-selection').clone();
//loop through and append a clone with modified JSON information for each item in the cart array
for(i=0; i<item.length; i++){
// create a copy of the clone
$copy = $clone.clone();
console.log(i);
$('h2', $copy).html(item[i].name);
$('img', $copy).attr("src", item[i].url);
$copy.appendTo($('product-list'));
}

I guess product-list is a class name or ID something?
$copy.appendTo($('product-list')); <--
if so, you may need to use .product-list or #product-list

You need to create the clone in the loop else you will be creating only one clone of the target element and you are just changing its content in the loop
$('document').ready(function () {
var cartArray = JSON.parse(localStorage.getItem("cart"));
console.log(cartArray);
parseData(cartArray);
})
function parseData(item) {
//loop through and append a clone with modified JSON information for each item in the cart array
for (i = 0; i < item.length; i++) {
// grab a clone of the aside, need to do in the loop because for each item in the loop we need a new element
//also should clone only the first instance of the cart-selection else in each iteration you will get multiple elements
var $copy = $('.cart-selection').eq(0).clone();
console.log(i);
$('h2', $copy).html(item[i].name);
$('img', $copy).attr("src", item[i].url);
//need to fix the selector here, may be you need a class selector if product-list is a class
$copy.appendTo($('.product-list'));
}
}
Demo: Fiddle

Related

Add data in Object Array

So, I have an input, I enter words for filter answers.
My answers are my panel.
I create an Array for register my answers.
var array = [];
But when I finish my loop, I want to innerHTML my datas who are in my Array.
But I have a [object HTMLDivElement] because i push Object in Array.
Ok my question is = How can I create an Array Object and push my panel in
var obj = {}
And How can I display them
This code search in answer if the words exist
if (searchIndex > -1) {
If the answer exist , push the panel in my array and count how many answer he founds
array.push(panel);
countFound++;
}
When the loop is finish, exploit this data and display them
array1.forEach(function(element) {
// I dont know how is the method to exploit all data one by one
});
Depending on what your HTML looks like, you should use innerHTML attribute to get the contents of an element.
array.push(panel.innerHTML);
You get the object HTMLDivElement because that's what panel is.
If you want to iterate over the elements in array you can do it with a foor loop, alternative with a foreach loop, and to display it again in the HTML you once again need to use the innerHTML attribute.
text = "";
for (i=0; i < array.length; i++) {
text += array[I];
}
document.getElementById("result").innerHTML = text;
And of you want to repeat the procedure you need to empty the array variable afterwards:
array = []; // Add this line after appending your data to the HTML.
// Realistically after the for loop
For more Details go to adding-elements-to-object
Here is how it works:
var element = {}, cart = [];
element.id = 1;
element.panel = document.getElementById("panel");
cart.push(element);
alert(cart[0].panel);
<div id="panel"></div>

[variable].AddEventListener in Javascript?

I am very new to coding. Below is a piece of JS code i am struggling to understand:
var btnContainer = document.getElementbyId(“linkcontainer”);
var btns = btnContainer.getElementsbyClassName(“btn”);
for (var i = 0; i < btns.length; i++){
btns.addEventListener(“click”, function(){
var current = document.getElementsbyClassName(“active”);
current[0].className = current[0].className.replace(‘active’, “”);
this.className += ‘active’;
});}
What difference does the [i] make in
btns[i].AddEventListener??
What is it exactly and what if there was no “i” in between the brackets? Also current[0]. It’s probably a stupid question, but please help me understand.
First of all there are no stupid question but only stupid answers.
In your code you get a list of DOM elements stored in an array called 'btns', then you iterate it with a loop.
So btns[i] allow you to retrieves the elements at the i position (It's important to note that array start at 0 in Javascript).
Example:
var fruits = ['Apple', 'Banana'];
console.log(fruits[0])
console.log(fruits[1])
So if you don't use the [i] you will iterate on the array itself and not on the element stored in it.
As the name of the method getElementsByClassName suggests, this queries the DOM and returns an array like object that contain multiple elements with the class name that was specified.
btns - will be an array that contains one or more elements.
To access a specific element from the array, you access it using the index of the current iteration.
btns[1] - Gives you access to the 2nd element in the list.
addEventListener - is used to bind a event handler to a single element. You cannot directly use this on array of objects.
// query the DOM for element with id - linkcontainer
var btnContainer = document.getElementbyId(“linkcontainer”);
// query the DOM for elements with className - btn
// This can return multiple elements, so btns will be
// as array like object of elements
var btns = btnContainer.getElementsByClassName(“btn”);
// iterate over the array that was just queried for
for (var i = 0; i < btns.length; i++) {
// bind a click event for each element in the array
btns[i].addEventListener(“click”, function() {
// query the dom for elements with className - active
var current = document.getElementsByClassName(“active”);
// access the first element and replace the active class
current[0].className = current[0].className.replace(‘active’, “”);
// add the active class to the element that was clicked
this.className += ‘active’;
});
}
The way I see it you will have to remove the active class for all the elements instead of just the first entity. A slightly better way to improve this code would be is
var btnContainer = document.getElementbyId(“linkcontainer”);
var btns = btnContainer.getElementsByClassName(“btn”);
btns.forEach(function(btn) {
btn.addEventListener(“click”, function() {
// query the dom for elements with className - active
var current = document.getElementsByClassName(“active”);
current.forEach(function(elem) {
elem.classList.remove('active');
});
this.classList.add('active');
});
});
As the other posters have mentioned, your code var btns = btnContainer.getElementsbyClassName(“btn”); should return an array of DOM elements so in your for loop, btns[i] will retrieve the specific element at index i of btns as i goes from 0 to btns.length. Removing the i will retrieve the entire array on each iteration.
To your second question: current is exactly the same thing as btns, an array of DOM elements so current[0] will retrieve the first element in this array.

While outputting an array with a for loop, how can i output all of the contents into a single, new div? javascript

I am outputting the values of an array with a for loop by using innerHTML +=, in order to add to the contents of a current div- let's call it div1 (known as currentQuestions in the code).
The function which outputs the array values is to be used multiple times, as the values stored within the array change from user input. This means that div1 will have a growing list of output.
However the problem is that for each group of data iterated by the array, i need them to be stored together in their own div (within div1), separate from other groups generated by a different call of the same function.
they dont need to have unique IDs, but they are needed to call a function onclick which will affect only the div that is clicked.
This is what i have so far:
arrayLength = answers.length
for (var j = 0; j < arrayLength; j++)
{
document.getElementById('currentQuestions').innerHTML += answers[j] + '<br />'
}
As you can see, all i have is the for loop so far. I cant add a div to the innerHTML because then it will create a div for each iteration rather than one div for the full iteration of the array.
I'm out of ideas. Thoughts?
Create the div and attach the event handler before the loop, something like this:
var subdiv = document.createElement('div'), // Creates a new element to the DOM
arrayLength = answers.length;
subdiv.addEventListener('click', function () {...}); // Attach a click listener
for (var j = 0; j < arrayLength; j++) {
subdiv.innerHTML += answers[j] + '<br />'; // Add some content to newly-created DIV
}
document.getElementById('currentQuestions').appendChild(subdiv); // Append the newly-created element to the document.
Make your life easier and try jQuery...
This example would take the html within a div they clicked on and append it to the #currentQuestions div...
$('body').on('click', '.class_of_div_they_click_on', function(event) {
var div_content = $(this).html();
$("#currentQuestions").append(div_content + '<br>');
});

What is the best way to create an array of all images found in a string?

I am looking to create an array of all the images in a string of HTML.
I've tried using the following but it generates errors if the complete URL path is not present in the src.
var found = $(html).find('img');
$("img").each(
function(index) {
theArray.push( $(this).attr("src") );
});
Quick run down of how to achieve this:
Open with jQuery's DOM Ready function ->
$(function(){
Create the variable found which holds a collection of the elements.
var found = $('p > img');
Create an empty Array to hold our results.
var results = new Array();
Iterate through each of the elements that we found
$.each(found, function(index,value){
For each 'value' (the item) that we find, we want to take the src, and push that src into the array.
results.push($(value).attr('src'));
Erroneous closure
});
Alert the total amount of items in the array;
alert('There is a total of '+results.length+' results in the Array.');
Alert just the src of the 3rd item we added to the array.
alert('The src of the 3rd item is: '+results[2]); //3nd item in array, indexes are 0 based
Erroneous closure
});
Hopefully this helps clear things up a bit.
You can do that with simple and plain JavaScript by creating an "instant" html element:
Create a element
Insert the string as innerHTML
Query the node
Example:
var html = "<html><body><img src='/img1.png' /><br /><img src='/img2.png' /></body></html>";
var node = document.createElement("div");
node.innerHTML = html;
for(var i=0; i < node.children.length; i += 1) {
if (node.children[i].tagName === 'IMG') {
alert(node.children[i].src)
};
}
Just try this:
var imgArray = $('img'),
srcArray = [];
console.log(imgArray); // array of imgs
$.each(imgArray, function() {
srcArray.push(this.src));
});

Remove multiple elements with same name using removeChild?

I have an element with multiple elements inside. All of the elements inside have the same name. Is there any way to remove them using one function?
(refer to this question for example Remove multiple children from parent?
Here's a solution that removes the first level children with the specified name for the parent with the specified id. If you want to go deeper, you can recursively call it on the child elements you get inside (you'll have to add a parent parameter as well).
function removeChildren (params){
var parentId = params.parentId;
var childName = params.childName;
var childNodes = document.getElementById(parentId).childNodes;
for(var i=childNodes.length-1;i >= 0;i--){
var childNode = childNodes[i];
if(childNode.name == 'foo'){
childNode.parentNode.removeChild(childNode);
}
}
}
And to call it:
removeChildren({parentId:'div1',childName:'foo'});
And a fiddle for testing:
Notes: You can only access the name element dependably in JavaScript when it supported on your element (e.g. NOT on DIVs!). See here for why.
UPDATE:
Here's a solution using className based on our conversation:
function removeChildren (params){
var parentId = params.parentId;
var childName = params.childName;
var childNodesToRemove = document.getElementById(parentId).getElementsByClassName('foo');
for(var i=childNodesToRemove.length-1;i >= 0;i--){
var childNode = childNodesToRemove[i];
childNode.parentNode.removeChild(childNode);
}
}
2021 Answer:
Perhaps there are lots of way to do it, such as Element.replaceChildren().
I would like to show you an effective solution with only one redraw & reflow supporting all ES6+ browsers.
function removeChildren(cssSelector, parentNode){
var elements = parentNode.querySelectorAll(cssSelector);
let fragment = document.createDocumentFragment();
fragment.textContent=' ';
fragment.firstChild.replaceWith(...elements);
}
Usage: removeChildren('.foo',document.body);: remove all elements with className foo in <body>
ok this should be easy. First get the parent element:
var theParent = document.getElementById("notSoHappyFather");
then get an array of the nodes that you want to remove:
var theChildren = theParent.getElementsByName("unluckyChild");
Lastly, remove them with a loop:
for (var i = 0; i < theChildren.length; i++)
{
theParent.removeChild(theChildren[i]);
}
A sample of your HTML would get you a more complete answer, but one can fairly easy call DOM functions to get the list of children and just remove them. In jQuery, remove all children would be something like this:
$("#target > *").remove();
or
$("#target").html("");
And, you can see a demo here: http://jsfiddle.net/jfriend00/ZBYCh/
Or, not using jQuery you could also do:
document.getElementById("target").innerHTML = "";
If you're trying to only remove a subset of the children (and leave others intact), then you need to be more specific how one would determine which children to leave and which to remove. In jQuery, you could use a .find() select or a filter() selector to narrow the list of children to just the children you wanted to target for removal.

Categories