Apply complicated li to descending order with jQuery - javascript

in the demo below, it orders li's according to text.
http://codepen.io/anon/pen/ByERqd
<abbr id="arti173" class="butarti">8</abbr>
I want to order li's according to the text in abbr.
I really appreciate your help.
I've been working on it lately and am stuck.
html
<body>
<input type="button" id="test" value="Sort List (click again to reverse)" />
<ul id="list">
<li>Peter<div class="yordivu">
<div>
<img>
</div>
<div> <button id="likefuncid173" class="likebutx mybutton" onclick="likefunc(173,1,'abbr#arti173')"><abbr id="arti173" class="butarti">6</abbr><span class="fa fa-thumbs-up"></span></button><button id="unlikefuncid173" class="mybutton" onclick="unlikefunc(173,1,'abbr#eksi173')"><abbr id="eksi173" class="buteksi">2</abbr><span class="fa fa-thumbs-down"></span></button>
</div>
</div>
<div style="word-wrap: break-word;">
<div><h3 class="yornameh"></h3><span class="text-muted"><strong></strong></span></div>
<div class="yortext">
</div>
</div></li>
<li>Mary<div class="yordivu">
<div>
<img>
</div>
<div> <button id="likefuncid173" class="likebutx mybutton" onclick="likefunc(173,1,'abbr#arti173')"><abbr id="arti173" class="butarti">8</abbr><span class="fa fa-thumbs-up"></span></button><button id="unlikefuncid173" class="mybutton" onclick="unlikefunc(173,1,'abbr#eksi173')"><abbr id="eksi173" class="buteksi">3</abbr><span class="fa fa-thumbs-down"></span></button>
</div>
</div>
<div style="word-wrap: break-word;">
<div><h3 class="yornameh"></h3><span class="text-muted"><strong></strong></span></div>
<div class="yortext">
</div>
</div></li>
<li>Paul<div class="yordivu">
<div>
<img>
</div>
<div> <button id="likefuncid173" class="likebutx mybutton" onclick="likefunc(173,1,'abbr#arti173')"><abbr id="arti173" class="butarti">5</abbr><span class="fa fa-thumbs-up"></span></button><button id="unlikefuncid173" class="mybutton" onclick="unlikefunc(173,1,'abbr#eksi173')"><abbr id="eksi173" class="buteksi">0</abbr><span class="fa fa-thumbs-down"></span></button>
</div>
</div>
<div style="word-wrap: break-word;">
<div><h3 class="yornameh"></h3><span class="text-muted"><strong></strong></span></div>
<div class="yortext">
</div>
</div></li>
<li>Allen<div class="yordivu">
<div>
<img>
</div>
<div> <button id="likefuncid173" class="likebutx mybutton" onclick="likefunc(173,1,'abbr#arti173')"><abbr id="arti173" class="butarti">1</abbr><span class="fa fa-thumbs-up"></span></button><button id="unlikefuncid173" class="mybutton" onclick="unlikefunc(173,1,'abbr#eksi173')"><abbr id="eksi173" class="buteksi">10</abbr><span class="fa fa-thumbs-down"></span></button>
</div>
</div>
<div style="word-wrap: break-word;">
<div><h3 class="yornameh"></h3><span class="text-muted"><strong></strong></span></div>
<div class="yortext">
</div>
</div></li>
</ul>
</body>
javascript
function sortUnorderedList(ul, sortDescending) {
if (typeof ul == "string") ul = document.getElementById(ul);
var lis = ul.getElementsByTagName("LI");
var vals = [];
for (var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i].innerHTML);
vals.sort();
if (sortDescending) vals.reverse();
for (var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i];
}
window.onload = function() {
var desc = false;
document.getElementById("test").onclick = function() {
sortUnorderedList("list", desc);
desc = !desc;
return false;
}
}

First of all, there should not be more than one id value in a document. Any kind of querying on that will fail then.
Coming to your issue, you can insert the text inside abbr in your array to be sorted along with li and then sort based on the text. Keeping that in mind, change your code to this -
for (var i = 0, l = lis.length; i < l; i++)
{
// pushing an array with text as second field
vals.push([lis[i].innerHTML, lis[i].getElementsByClassName("butarti")[0].innerHTML]);
}
// sorting the final based on text
vals.sort(function(a,b){return parseInt(a[1]) - parseInt(b[1])});
if (sortDescending) vals.reverse();
// replacing the existing li tags html
for (var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i][0];
Hope this works.

Related

Why does the addEventListener property does not work on a dynamic HTMLcollection object?

I am working on a chrome extension and trying to add an event listener to a getElementsByClassName variable, in which elements are added dynamically using template strings.
I have tried a lot of changes in the code, but the code doesn't work.
The code is supposed to delete the targeted element from the array "recipeList", storing the array in localStorage and then render the updated array "recipeList" using template string to the HTML code again.
DELETE BUTTON Function
let delBtn = document.getElementsByClassName("del-btn");
for(let i = 0; i < delBtn.length; i++) {
delBtn[i].addEventListener("click", function() {
recipeList.splice(i, 1);
localStorage.setItem("recipeList", JSON.stringify(recipeList));
recipeList = JSON.parse(localStorage.getItem("recipeList"));
render(recipeList);
if(!recipeList.length) {
tabBtn.style.width = "100%";
delAllBtn.style.display = "none";
}
});
}
RENDER CODE
function render(list) {
let recipeURL = "";
for(let i = 0; i < list.length; i++) {
recipeURL += `
<div class="mb-2 row">
<div class="col-1 num-btn">
${i+1}
</div>
<div class="col-10">
<div class="recipe-url">
<a target="_blank" href="${list[i]}">
${list[i]}
</a>
</div>
</div>
<div class="col-1 del-btn">
<a href="#">
<i class="bi bi-trash-fill"></i>
</a>
</div>
</div>
`
}
urlList.innerHTML = recipeURL;
console.log(delBtn);
}
When you render, you create new .del-btn which are not included in your first let delBtn = document.getElementsByClassName("del-btn");.
Each time you create new .del-btn, you should also add a new listener.
function render(list) {
let recipeURL = "";
for(let i = 0; i < list.length; i++) {
recipeURL += `
<div class="mb-2 row">
<div class="col-1 num-btn">
${i+1}
</div>
<div class="col-10">
<div class="recipe-url">
<a target="_blank" href="${list[i]}">
${list[i]}
</a>
</div>
</div>
<div class="col-1 del-btn">
<a href="#">
<i class="bi bi-trash-fill"></i>
</a>
</div>
</div>
`
}
urlList.innerHTML = recipeURL;
console.log(delBtn);
Array.from(urlList.querySelectorAll('.del-btn')).forEach((btn, i) => {
btn.addEventListener('click', () => console.log('.del-btn index: ' + i))
})
}
}

Cannot set property 'innerHTML' of undefined in loop

i want to change the color of button but i get this message with any method (style,innerHtml,...)
error: Uncaught TypeError: Cannot set property 'color' of undefined
html:
`
<div class="a-section backGround layer">
</div>
<div class="a-section layer">
<div class="a-row dealDetailContainer">
<div class="a-row a-spacing-mini">
<div class="a-row a-spacing-unspecified">
<span class="a-size-mini a-color-base hiddenCss"> </span>
<span class="a-size-mini a-color-base badgeSkew"></span>
</div>
</div>
<div class="a-row stackToBottom">
<div class="a-row a-spacing-medium">
<span class="a-declarative">
<span class="a-button a-button-normal a-button-span12 a-button-primary fixedWidth210">
<span class="a-button-inner">
<button class="a-button-text a-text-center" type="button">
Add to Cart
</button>
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
`
js:
var button = document.getElementsByClassName=(".a-button-primary .a-button-text");
var i;
for(i=0 ; i <= button.length ; i++){
button[i].style.color = "blue";
}
As noted in #Heretic's comment, your syntax is incorrect. Another issue I found is that you are looping beyond the length of the returned elements. In your for loop, you are using <= instead of <. Because we're starting at 0, <= will go too far and return undefined when the loop exceeds the actual element length.
Here is a basic example of what you're trying to do.
var button = document.getElementsByClassName("my-button");
for (var i = 0; i < button.length; i++) {
button[i].style.color = "blue";
}
<button class="my-button">hello</button>
<button class="my-button">hello</button>
<button class="my-button">hello</button>

document.getElementsByClassName not working

Does anyone know why it isn't working?
I want it to show div odpoved when I click on div dotaz.
function ukaz(a) {
var elements = document.getElementsByClassName(a);
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = "block";
}
}
<div class="dotaz" onClick="ukaz(odpoved)">
<p>YOSODJDN</p>
<span class="qanick">jirka</span>
<span class="fafadown"><i class="arrow fa fa-angle-down" style="font-size:24px"></i></span>
</div>
<div class="odpoved" style="display:none">
<p>ODPOVED</p>
<span class="qanick">anetka</span>
</div>
Use it like this, pass odpoved as a string
<div class="dotaz" onClick="ukaz('odpoved')">
<div class="dotaz" onClick="ukaz('odpoved')">
<p>YOSODJDN</p>
<span class="qanick">jirka</span>
<span class="fafadown"><i class="arrow fa fa-angle-down" style="font-
size:24px"></i></span>
</div>
<div class="odpoved" style="display:none">
<p>ODPOVED</p>
<span class="qanick">anetka</span>
</div>
<script>
function ukaz(a) {
var elements = document.getElementsByClassName(a);
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = "block";
}
}
</script>
onClick="ukaz(odpoved)" is attempting to call a function, using a variable - instead of a string - as an argument.
function ukaz(a) {
var elements = document.getElementsByClassName(a);
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = "block";
}
}
<div class="dotaz" onClick="ukaz('odpoved')"> <!-- odpoved is a string, not a variable -->
<p>YOSODJDN</p>
<span class="qanick">jirka</span>
<span class="fafadown">
<i class="arrow fa fa-angle-down" style="font-size:24px"></i>
</span>
</div>
<div class="odpoved" style="display:none">
<p>ODPOVED</p>
<span class="qanick">anetka</span>
</div>

how to dynamically set text to an element in jquery

i have an onclick function that that calls a changeName function anytime a click event on that element happens.
function changeName() {
var frag = $('<span class="Name">change me</span>');
$( ".list" ).prepend(frag);
var x =[];
$('.ch-gname').each(function(index, obj)
{
x.push($(this).text());
for(i=0; i<x.length; i++) {
$('.Name').text(x[i]);}}});
$('#action').on('click', changeName);
HTML
<div>
<a href="#0" class="cb-pgcar"</a>
<span class="ch-gname">Greenhouse</span>
</div>
<div>
<a href="#0" class="cb-pgcar"</a>
<span class="ch-gname">tree house</span>
</div>
<div>
<a href="#0" class="cb-pgcar"</a>
<span class="ch-gname">light house</span>
</div>
<div class="list">
</div>
<div class="list">
</div>
<div class="list">
</div>
i want to able to change the text of the class Name to the text of class ch-gname. My function gives me only the last text text(lighthouse) for the three links.Any help please
The function changeName() has $('#action').on('click', changeName); but i do not see any element with id 'action'. Anyhow i've made necessary changes in order to make it work.
Added Action id to the elements
Changed the $('.Name').text(x[i]); to $('.Name')[i].innerHTML = x[i];
Look at the below example
function changeName() {
var frag = $('<span class="Name">change me</span>');
$(".list").prepend(frag);
var x = [];
$('.ch-gname').each(function(index, obj) {
x.push($(this).text());
});
for (i = 0; i < x.length; i++) {
$('.Name')[i].innerHTML = x[i];
}
}
$('#action').on('click', changeName);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<a href="#0" class="cb-pgcar" </a>
<span id="action" class="ch-gname">Greenhouse</span>
</div>
<div>
<a href="#0" class="cb-pgcar" </a>
<span id="action" class="ch-gname">tree house</span>
</div>
<div>
<a href="#0" class="cb-pgcar" </a>
<span id="action" class="ch-gname">light house</span>
</div>
<div class="list">
</div>
<div class="list">
</div>
<div class="list">
</div>

JavaScript. Sorting ements by value of children

Need a bit of help with JS. I'm trying to figure out how to sort a pile of div's, using values of their children elements. I'v found a solution here on stack and tried to modify it a bit but with no luck so far.
Please, give me some advise. Thank you
The idea is to sort div.person according to their "age" element.
<!DOCTYPE html>
<html>
<head>
<title>Sort list items alphabetically with Javascript</title>
<script type="text/javascript">
function sortUnorderedList(div, sortDescending) {
if(typeof div == "number")
div = document.getElementById(div);
var lis = div.getElementsByClassName("person");
var vals = [];
for(var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i].innerHTML);
vals.sort();
if(sortDescending)
vals.reverse();
for(var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i];
}
window.onload = function() {
var desc = false;
document.getElementById("test").onclick = function() {
sortUnorderedList("list", desc);
desc = !desc;
return false;
}
}
</script>
</head>
<body>
<input type="button" id="test" value="Sort List"/>
<div id="list">
<div class="person">
<div>Jack</div>
<div>Plumber</div>
<div class="info">
<span class="age">24</span>
<span class="hair-color">Blonde</span>
</div>
</div>
<div class="person">
<div>Jill</div>
<div>Actress</div>
<div class="info">
<span class="age">18</span>
<span class="hair-color">Gray</span>
</div>
</div>
<div class="person">
<div>John</div>
<div>Driver</div>
<div class="info">
<span class="age">37</span>
<span class="hair-color">Brown</span>
</div>
</div>
</ul>
</body>
</html>
I changed the code a bit to make it more readable for myself.
First I get all the htmlNode by class name "person", though this will return a htmlCollection which is array-ish but not an array.
Therefore I convert it to an array on the next line so I can perform array-methods on it like 'sort'.
You can swap out the different compareFunctions I wrote for different kind of sorting.
After sorting I empty the existing content of the list-element, and fill it up again with for-loop.
function sortUnorderedList(list, sortDescending) {
var htmlCollection = list.getElementsByClassName("person"),
elements = [].slice.call(htmlCollection); //convert htmlCollection to array
//sort by ...
//elements.sort(compareNames);
//elements.sort(compareJobs);
elements.sort(compareAges);
if (sortDescending) elements.reverse();
list.innerHtml = ''; //remove current contents
for (var i = 0; i < elements.length; i++) {
list.appendChild(elements[i]); //add them again in different order
}
function compareNames(el1, el2) {
//innerText of the first child of each element is the name
if (el1.children[0].innerText < el2.children[0].innerText) return -1;
if (el1.children[0].innerText > el2.children[0].innerText) return 1;
return 0;
}
function compareJobs(el1, el2) {
//innerText of the second child of each element is the job
if (el1.children[1].innerText < el2.children[1].innerText) return -1;
if (el1.children[1].innerText > el2.children[1].innerText) return 1;
return 0;
}
function compareAges(el1, el2) {
var age1 = parseInt(el1.children[2].children[0].innerText),
age2 = parseInt(el2.children[2].children[0].innerText);
if(isNaN(age1))age1=-1;
if(isNaN(age2))age2=-1;
return age1 - age2;
}
}
window.onload = function() {
var desc = false;
document.getElementById("test").onclick = function() {
sortUnorderedList(document.getElementById('list'), desc);
desc = !desc;
return false;
};
};
<!DOCTYPE html>
<html>
<head>
<title>Sort list items alphabetically with Javascript</title>
</head>
<body>
<input type="button" id="test" value="Sort List" />
<div id="list">
<div class="person">
<div>Jack</div>
<div>Plumber</div>
<div class="info">
<span class="age">24</span>
<span class="hair-color">Blonde</span>
</div>
</div>
<div class="person">
<div>Jill</div>
<div>Actress</div>
<div class="info">
<span class="age">0</span>
<span class="hair-color">Gray</span>
</div>
</div>
<div class="person">
<div>John</div>
<div>Driver</div>
<div class="info">
<span class="age"></span>
<span class="hair-color">Brown</span>
</div>
</div>
</ul>
</body>
</html>

Categories