UPDATE: the before-title is wrong, the foor loop is ok (probably). The problem is that I can't make a reference to the product itself. At the last if (if(notItsPlace)) it's not the productArr[i].parentNode I have to use but the product-name, but I need to sort the products themselves. So the new question is:
How to make a reference to an element that's two levels up?
Hi everyone, I'm new in JavaScript and have a quick question: In my code below the foor loop does not increment the var i but stucks in an infinite loop. I'm sure something is out of order but can't figure it out what.
The task is to place the product items in alphabetical order (and many other), and the products in this case are not coming from a database but it's written in the HTML (I know). Can't edit the HTML and would not like to use JQuery.
Thank you in advance!
var sortingSel = document.querySelector(".order");
var product = document.querySelectorAll("div[class='product']");
var productArr = Array.from(product);
sortingSel.onchange = function(){
var sortingOpt = parseInt(sortingSel.options[sortingSel.selectedIndex].value);
var notItsPlace;
var switchPlace = true;
switch(sortingOpt){
case 2:
while (switchPlace){
switchPlace = false;
for (var i = 0; i < (productArr.length -1); i ){
console.log("i = " i);
notItsPlace = false;
if (productArr[i].querySelector(".product-name").innerText.toLowerCase() > productArr[i 1].querySelector(".product-name").innerText.toLowerCase()){
notItsPlace = true;
break;
}
}
if (notItsPlace){
productArr[i].parentNode.insertBefore(productArr[i 1], productArr[i]);
switchPlace = true;
}
}
break;
default:
console.log("def");
}
}
<select style="padding: 10px;" class="order">
<option value="0">case 0</option>
<option value="1">case 1</option>
<option value="2">case 2</option>
<option value="3">case 3</option>
</select>
<div class="products">
<div class="product">
<span class="image-container">
<img src="">
</span>
<div class="product-data" data-identifier="6">
<div class="product-name">CNAME</div>
<div class="product-price">PRICE</div>
</div>
</div>
<div class="product">
<span class="image-container">
<img src="">
</span>
<div class="product-data" data-identifier="6">
<div class="product-name">ANAME</div>
<div class="product-price">PRICE</div>
</div>
</div>
<div class="product">
<span class="image-container">
<img src="">
</span>
<div class="product-data" data-identifier="6">
<div class="product-name">BNAME</div>
<div class="product-price">PRICE</div>
</div>
</div>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
I propose to use another sorting method, in which all the products are first collected, then sorted and then inserted into the layout.
There used method js for right sorting 'String' localeCompare and a reduce for the layout assembly.
var sortingSel = document.querySelector(".order");
var product = document.querySelectorAll("div[class='product']");
var productList = document.querySelector('.products');
var productArr = Array.from(product);
sortingSel.onchange = function(){
var sortingOpt = parseInt(sortingSel.options[sortingSel.selectedIndex].value);
newProductArr = productArr.sort(function(a, b) {
const elemA = a.querySelector(".product-name").innerText;
const elemB = b.querySelector(".product-name").innerText;
if (sortingOpt === 2) {
return elemA.localeCompare(elemB);
} else {
return elemB.localeCompare(elemA)
}
});
newProductListArr = newProductArr.reduce(function(acc, elem) {
return acc elem.innerHTML;
}, '');
productList.innerHTML = newProductListArr;
}
<select style="padding: 10px;" class="order">
<option value="0">case 0</option>
<option value="1">case 1</option>
<option value="2">case 2</option>
<option value="3">case 3</option>
</select>
<div class="products">
<div class="product">
<span class="image-container">
<img src="">
</span>
<div class="product-data" data-identifier="6">
<div class="product-name">CNAME</div>
<div class="product-price">PRICE</div>
</div>
</div>
<div class="product">
<span class="image-container">
<img src="">
</span>
<div class="product-data" data-identifier="6">
<div class="product-name">ANAME</div>
<div class="product-price">PRICE</div>
</div>
</div>
<div class="product">
<span class="image-container">
<img src="">
</span>
<div class="product-data" data-identifier="6">
<div class="product-name">BNAME</div>
<div class="product-price">PRICE</div>
</div>
</div>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>