I'm trying to loop through different divs. I've got product arrays, but they are displayed in different div's. Is there a way to loop through them? I would like to put the available products (array.length) in an Array. The code is as followed:
<div id=Googletagsholderdiv data-gtm-ecommerce.purchase.actionField.id="x"
data-gtm-ecommerce.purchase.actionField.affiliation="x"
data-gtm-ecommerce.purchase.actionField.revenue="x"
data-gtm-ecommerce.purchase.actionField.tax="x"
data-gtm-ecommerce.purchase.actionField.shipping="x"
data-gtm-ecommerce.purchase.actionField.coupon="x">
<div data-gtm-ecommerce.purchase.products[0].name="x"
data-gtm-ecommerce.purchase.products[0].id="x"
data-gtm-ecommerce.purchase.products[0].price="x"
data-gtm-ecommerce.purchase.products[0].brand="x"
data-gtm-ecommerce.purchase.products[0].category="x"
data-gtm-ecommerce.purchase.products[0].variant="x"
data-gtm-ecommerce.purchase.products[0].quantity="x"
data-gtm-ecommerce.purchase.products[0].coupon="x"
data-gtm-ecommerce.purchase.products[0].dimensionX="x">
</div>
<div data-gtm-ecommerce.purchase.products[1].name="x"
data-gtm-ecommerce.purchase.products[1].id="x"
data-gtm-ecommerce.purchase.products[1].price="x"
data-gtm-ecommerce.purchase.products[1].brand="x"
data-gtm-ecommerce.purchase.products[1].category="x"
data-gtm-ecommerce.purchase.products[1].variant="x"
data-gtm-ecommerce.purchase.products[1].quantity="x"
data-gtm-ecommerce.purchase.products[1].coupon="x"
data-gtm-ecommerce.purchase.products[1].dimensionX="x">
</div>
<div data-gtm-ecommerce.purchase.products[2].name=""
data-gtm-ecommerce.purchase.products[2].id="x"
data-gtm-ecommerce.purchase.products[2].price="x"
data-gtm-ecommerce.purchase.products[2].brand="x"
data-gtm-ecommerce.purchase.products[2].category=""
data-gtm-ecommerce.purchase.products[2].variant="x"
data-gtm-ecommerce.purchase.products[2].quantity="x"
data-gtm-ecommerce.purchase.products[2].coupon="x"
data-gtm-ecommerce.purchase.products[2].dimensionX="x">
</div>
</div>
I think you should had a class to all your div with your desired data, and after, get all of them with jQuery.
You can select the parent element with any selector you like and get it's children with the children array.
Yoi can loop through this array using the for..of loop:
var Googletagsholderdiv = document.getElementById("Googletagsholderdiv");
for (var div of Googletagsholderdiv.children) {
console.log(div);
}
<div id=Googletagsholderdiv data-gtm-ecommerce.purchase.actionField.id="x" data-gtm-ecommerce.purchase.actionField.affiliation="x" data-gtm-ecommerce.purchase.actionField.revenue="x" data-gtm-ecommerce.purchase.actionField.tax="x" data-gtm-ecommerce.purchase.actionField.shipping="x"
data-gtm-ecommerce.purchase.actionField.coupon="x">
<div data-gtm-ecommerce.purchase.products[0].name="x" data-gtm-ecommerce.purchase.products[0].id="x" data-gtm-ecommerce.purchase.products[0].price="x" data-gtm-ecommerce.purchase.products[0].brand="x" data-gtm-ecommerce.purchase.products[0].category="x"
data-gtm-ecommerce.purchase.products[0].variant="x" data-gtm-ecommerce.purchase.products[0].quantity="x" data-gtm-ecommerce.purchase.products[0].coupon="x" data-gtm-ecommerce.purchase.products[0].dimensionX="x"></div>
<div data-gtm-ecommerce.purchase.products[1].name="x" data-gtm-ecommerce.purchase.products[1].id="x" data-gtm-ecommerce.purchase.products[1].price="x" data-gtm-ecommerce.purchase.products[1].brand="x" data-gtm-ecommerce.purchase.products[1].category="x"
data-gtm-ecommerce.purchase.products[1].variant="x" data-gtm-ecommerce.purchase.products[1].quantity="x" data-gtm-ecommerce.purchase.products[1].coupon="x" data-gtm-ecommerce.purchase.products[1].dimensionX="x"></div>
<div data-gtm-ecommerce.purchase.products[2].name="" data-gtm-ecommerce.purchase.products[2].id="x" data-gtm-ecommerce.purchase.products[2].price="x" data-gtm-ecommerce.purchase.products[2].brand="x" data-gtm-ecommerce.purchase.products[2].category=""
data-gtm-ecommerce.purchase.products[2].variant="x" data-gtm-ecommerce.purchase.products[2].quantity="x" data-gtm-ecommerce.purchase.products[2].coupon="x" data-gtm-ecommerce.purchase.products[2].dimensionX="x"></div>
Related
This question already has answers here:
Easiest way to sort DOM nodes?
(9 answers)
Closed last month.
I have list and this list must be sort to a => b throught like btn (example click SORT and we have list to a -> b)
<div class = "list">
<div id = "products"> Sugar </div>
<div id = "products"> Banana </div>
<div id = "products"> Apple </div>
</div>
sorted to for button =>
<div class = "list">
<div id = "products"> Apple </div>
<div id = "products"> Banana </div>
<div id = "products"> Sugar </div>
</div>
Idk how did that with like btn :(
I tried something like that =>
// For the HTML //
<button class = 'sortBtn' onclick = 'sort()'>Sort</button>
<script>
const sort = document.quertSelector('.sortBtn');
sort.addEventListenet('click', function sort(a, b){
$parent.sort();
})
</script>
I would be grateful for help :) <3
There's a few issues in your code.
Typo: quertSelector -> querySelector
Typo: addEventListenet -> addEventListener
The repeated id in your HTML are invalid, convert them to class instead.
The function you provide to addEventListener should be anonymous in this case. Giving it a name here serves no purpose other than to waste bytes.
Avoid using inline event handlers, such as onclick, in your HTML code. It's outdated and no longer good practice. Use unobtrusive event handlers instead, such as addEventListener(), which you already use elsewhere in your code.
sort() should compare the a and b arguments and return an integer depending on which way to sort them. In this case, as you're comparing strings you can use localeCompare() on the textContent property of the elements.
After the sort() has completed you need to update the DOM to respect the new order of the elements. To do this you can call append() on the parent element, supplying the children as the argument.
Here's a working example with these issues addressed:
const sortButton = document.querySelector('.sortBtn');
const list = document.querySelector('.list');
const products = list.querySelectorAll('.products');
sortButton.addEventListener('click', () => {
const sortedElements = Array.from(products).sort((a, b) => a.textContent.localeCompare(b.textContent));
list.append(...sortedElements);
})
<div class="list">
<div class="products">Sugar</div>
<div class="products">Banana</div>
<div class="products">Apple</div>
</div>
<button type="button" class="sortBtn">Sort</button>
Convert the children of the parent element to an array. Then you can use the array sort() method to sort it, then append the children back to the parent in that order.
document.querySelector(".sortBtn").addEventListener("click", () => sortDiv(document.querySelector(".list")));
function sortDiv(parent) {
let children = [...parent.children];
children.sort((a, b) => a.innerText.localeCompare(b.innerText));
parent.innerHTML = '';
children.forEach(child => parent.appendChild(child));
}
<div class="list">
<div class="products"> Sugar </div>
<div class="products"> Banana </div>
<div class="products"> Apple </div>
</div>
<button class='sortBtn'>Sort</button>
I'm trying to load an carousel with angularjs using owl-carousel. I want my carousel to scroll endless, loading items every time the list is fully scrolled and adding queried elements to the actual list. My issue is:
When I get data from the controller of the next page, I want to merge and contact the received items to be merged the the current array and be rendered at the end of the carousel, here is what I've done:
<data-owl-carousel class="owl-carousel" data-options="{navigation: true, pagination: false, rewindNav : false}">
<div owl-carousel-item="" ng-repeat="item in hmc.ProductData.Products track by $index" class="item">
<a ng-href="/#!//{{Page.Culture+'/product/'+item.id}}">
<div class="telewebion-show-box one-row">
<div class="telewebion-show-box-cover">
<ul>
<li>{{::item.title}}</li>
<li>{{::item.price}}</li>
</ul>
</div>
<img ng-src="{{::item.picture_path}}" width="220" height="148" alt="" class="img-responsive"/>
</div>
</a>
</div>
</data-owl-carousel>
And here is my controller:
hmc.getProducts=function(){
ProductFactory.getProducts(hmc.ProductData.Offset,hmc.ProductData.Limit).then(function(Products){
if(hmc.ProductData.Page==0)
{
hmc.ProductData.Products[0]='';
}
hmc.ProductData.Page++;
var tempArray=[];
tempArray.push(Products);
console.log(tempArray);
hmc.ProductData.Products [0]=hmc.ProductData.Products [0].concat(tempArray[0]);
console.log(hmc.ProductData.Products );
hmc.ProductData.UpdateInProgress=false;
});
}
but it doesn't contact and merge the array and wouldn't work.
With tempArray.push(Products); you push a single array, considered as the whole variable, in a single cell of the array tempArray without obtaining the expected result. You should call:
tempArray = tempArray.concat(Products);
This way you push every element of Products in tempArray. Please note that concat does not modify the calling array directly, this behavior force you to reassign its return value to the original tempArray.
I Just did it like this:
hmc.ProductData.Page++;
var tempArray=[];
var tempArray2=[];
tempArray.push(AjaxProducts);
tempArray2.push(hmc.ProductData.Products);
hmc.ProductData.Products= tempArray2[0].concat(tempArray[0]);
tempArray.length = 0;
tempArray2.length = 0;
Now angular ng-repeat just repeat in a single array structure and ajax appends to the end of that array
I tried it with getElementById and it worked. But now I want the same with multiple div's so I have to use classes. So I changed the method to getElementsByClassName and now it says undefined.
(The function is called when a option in a select changes. This works correctly)
HTML:
<div class="item_content">
<h3 class="filmnaam">22 jump street</h3>
</div>
<div class="item_content">
<h3 class="filmnaam">rio 2</h3>
</div>
Javascript:
function sorting(sortingway) {
alert(sortingway.value);
var titelfilms = document.getElementsByClassName("filmnaam");
var titels = titelfilms.innerHTML;
console.log(titels[0]);
}
Is there a way to do this without jQuery?
getElementsByClassName returns a collection, so loop that!
var titelfilms = document.getElementsByClassName("filmnaam");
for (var i = 0; i < titelfilms.length; i++) {
var titels = titelfilms[i].innerHTML;
console.log(titels);
}
titelfilms is a node list, you can't get the innerHTML of a node list as a whole, it contains multiple references to elements which each have their own individual property.
You could loop through and concatenate each innerHTML onto a variable, or you could map() the innerHTML of your returned elements to an array and then join() them up:
function sorting(sortingway) {
var titelfilms = document.getElementsByClassName("filmnaam");
var titels = Array.prototype.map.call(titelfilms, function (el) {
return el.innerHTML;
}).join(' ');
console.log(titels);
}
sorting();
<div class="item_content">
<h3 class="filmnaam">22 jump street</h3>
</div>
<div class="item_content">
<h3 class="filmnaam">rio 2</h3>
</div>
I have a page with a very large table (several thousand rows).
The table shows a subset of data specified by certain filters. I need the table to update whenever one of the filters changes.
Basically, there are a few check boxes and a text box, whenever one of these changes I reload the table to display only those rows which fit the criteria specified by the user.
I'm doing this by clearing the table and reloading the rows that match the filters. This works but has proven to be very slow.
Here is my javascript code:
function reloadTable() {
var tablebody = document.getElementById("tablebody");
while(tablebody.hasChildNodes()) tablebody.removeChild(tablebody.firstChild);
filter = new FilterChecker();
for (var i=0;i<rows.length;i++) {
if (filter.isVisible(rows[i]))
addRowToTable(rows[i]);
}
}
Is there a way to make it faster?
Alright, sorry for the delay, but I got wrapped up in work. I came up with a nice set of logic that illustrates what you need.
FIDDLE
I created some simple html to illustrate the point. It contains two drop downs to mimic the filters and 8 data rows to mimic your data grid.
<div id="body">
<select id="filterA" class="filter" name="states">
<option value="filterACT">Connecticut</option>
<option value = "filterAMA">Mass</option>
</select>
<select id="filterB" class="filter" name="towns">
<option value="filterBBT">Big Town</option>
<option value = "filterBST">Small Town</option>
</select>
<div id="grid">
<div class="row filterACT filterBBT">BigTown CT 1</div>
<div class="row filterACT filterBBT">BigTown CT 2</div>
<div class="row filterACT filterBST">SmallTown CT 1</div>
<div class="row filterACT filterBST">SmallTown CT 2</div>
<div class="row filterAMA filterBBT">BigTown MA 1</div>
<div class="row filterAMA filterBBT">BigTown MA 2</div>
<div class="row filterAMA filterBST">SmallTown MA 1</div>
<div class="row filterAMA filterBST">SmallTown MA 2</div>
</div>
</div>
</br>
<hr/>
<div>LOG</div>
<hr/>
<div id="log"></div>
The log div is simply to show an output, which I think would be helpful. Each row is identified by class 'row' followed by another series of classes. These classes help determine what their filter data is. You would need to set this programmatically when building the grid. Additionally, these class names must match the filter option values. You can see that the first row has classes from the first option in filterA and from the first option in filterB.
Now, the javascript is a bit verbose, but you can refactor to your hearts content. Sometimes I find it easier when things are explicit when you are trying to understand them. Also, admittedly, I would do this with jQuery, so my pure Javascript isn't as sharp.
var elements = document.getElementsByClassName('filter');
writeToLog("Filter elements found: " + elements.length);
for(var e = 0;e < elements.length;e++)
{
elements[e].onchange =function() {
writeToLog('Filter event fired for id:'+this.id);
filterChange();
};
}
First I get all the elements with the filter class, this would be your filters. I then iterate over them and set their onchange event to call the filterChange() method. The writeToLog() method calls are just for output purposes.
function filterChange() {
var filterClasses = [];
for(var i = 0;i<elements.length;i++) {
writeToLog('Pushing ('+elements[i].value+') into filter class variable.');
filterClasses.push(elements[i].value);
}
In the first part of the function I get all the select filter option values and put them into an array.
writeToLog('Filter classes: ' + filterClasses);
var rows = document.getElementsByClassName('row')
writeToLog('Row count: ' + rows.length);
I then get all of the rows, in my grid and start to iterate over them:
for(var j = 0;j<rows.length;j++)
{
writeToLog('Checking row: ' + rows[j].className);
var rowIsHidden = false;
Once I have a row, in the loop, I iterate the filter classes in the array and see if this row's classes have it. If not, I set rowIsHidden to true, otherwise it stays false.
for(var k = 0;k<filterClasses.length;k++)
{
writeToLog('Checking for class: ' + filterClasses[k]);
if(rows[j].className.indexOf(filterClasses[k]) < 0)
{
writeToLog('Class not found, hide this row.');
rowIsHidden = true;
break;
}
}
Before the loop moves to the next row, I set the display style based on the rowIsHidden value.
writeToLog('Row is hidden: ' + rowIsHidden);
rows[j].style.display = rowIsHidden ? 'none' : 'block';
}
}
By all means, this can be cleaned up and certainly optimized, but I think the intent and logic is fairly clear. Hope this helps and feel free to question any of it :)
<div class="contain_questions">
<div class="question">
<div class="question_text">First question</div>
<div class="question_mandatory">1</div>
<div class="options">
<div class="option"><div class="option_name">a</div><div class="option_value">1</div></div>
<div class="option"><div class="option_name">b</div><div class="option_value">2</div></div>
<div class="option"><div class="option_name">c</div><div class="option_value">3</div></div>
</div>
add_another_option
</div>
.
. // many more div.question ...
.
<input type="button" value="submit_questions" />
</div>
How do you use .each() for each div.option within an outer .each() for each question?
I have the outer .each() working fine, which iterates over all div.question and pushes the question_text etc into an array, however I cant seem to target the options container within each question in order to also push all of the options for each question into the array.
Also, is it possible to target a subset of the DOM with the .each() function, or is there some other way to iterate over all classes within a given class?
Thanks guys..
Just as simple as that:
$(".question").each(function() {
...
$(this).find(".option").each(function() {
...
});
});
So your code might look like the following:
var questions = [];
$(".question").each(function() {
var obj = {
name : $(this).find(".question_text").text(),
options : []
};
$(this).find(".option").each(function() {
obj.options.push({
name : $(this).find(".option_name").text(),
value : $(this).find(".option_value").text()
});
});
questions.push(obj);
});
console.log(questions);