How can I sort divs with javascript - javascript

I would like to sort a few divs in ascending order based on their data-id. How can I do that?
<div class="container" data-id="1000">
<div id="H1"></div>
<div id="sub">sub 1</div>
<div id="sub">sub 2</div>
</div>
<div class="container" data-id="3000">
<div id="H1"></div>
<div id="sub"></div>
<div id="sub"></div>
</div>
<div class="container" data-id="2000">
<div id="H1"></div>
<div id="sub"></div>
<div id="sub"></div>
</div>

I've found the solution to my problem a while ago:
function sortOut() {
// get the classname chapcontainer
var classname = document.getElementsByClassName('container');
// create a variable and put the classes it into an array.
var divs = [];
for (var i = 0; i < classname.length; ++i) {
divs.push(classname[i]);
}
// Sort the divs based on data-id.
divs.sort(function(a, b) {
return +a.getAttribute("data-id") - +b.getAttribute("data-id");
});
};
divs.sort does the trick. More info about this function can be found here:
https://www.w3schools.com/jsref/jsref_sort.asp

Related

Cannot get value of div

I have problem with getting value of a div with class="idC". I need this value to remove object from my array. I know I probably gonna need to use parseInt but all I'm getting with this code is rowid: undefined when I use console.log("rowid: " + bikeId.value). bikeRow.remove(); works fine. It removes the row I want to.
const buttonDel = document.querySelectorAll(".deleteC");
buttonDel.forEach(button => {
console.log("jazda");
button.addEventListener('click', () => {
const bikeRow = button.parentNode;
const bikeId = bikeRow.firstChild;
if (!window.confirm())
return;
console.log("rowid: " + bikeId.value);
bikeRow.remove();
//bikeStorage.removeBike(bikeId.value);
})
})
<div class="bikeRows">
<div class="bikeRow">
<div class="idC"></div>${bike.id}</div>
<div class="frameC">${bike.frame}</div>
<div class="suspC">${bike.susp}</div>
<div class="wheelC">${bike.wheel}</div>
<div class="typeC">${bike.constructor.name}</div>
<div class="deleteC"><button class="delButton" id="${bike.id}">Delete</button></div>
</div>
</div>
You have invalid HTML and you really should delegate
I added the ID as a data-attribute to the row like this
<div class="bikeRow" data-id="${bike.id}">
Makes the code much simpler to debug and extend
document.querySelector(".bikeRows").addEventListener("click", e => {
const tgt = e.target.closest("button");
if (!tgt.matches(".delButton")) return; // not a delete button
if (!window.confirm("Sure?")) return; // they cancelled
const bikeRow = tgt.closest("div.bikeRow"),
id = bikeRow.dataset.id; // the ID to remove from the storage
bikeRow.remove();
//bikeStorage.removeBike(id);
})
<div class="bikeRows">
<div class="bikeRow" data-id="ID1">
<div class="idC">ID1</div>
<div class="frameC">Frame 1</div>
<div class="suspC">Susp 1</div>
<div class="wheelC">Wheel 1</div>
<div class="typeC">Constructor name 1</div>
<div class="deleteC"><button class="delButton">Delete</button></div>
</div>
<div class="bikeRow" data-id="ID2">
<div class="idC">ID 2</div>
<div class="frameC">Frame 2</div>
<div class="suspC">Susp 2</div>
<div class="wheelC">Wheel 2</div>
<div class="typeC">Constructor name 2</div>
<div class="deleteC"><button class="delButton">Delete</button></div>
</div>
<div class="bikeRow" data-id="ID3">
<div class="idC">ID 3</div>
<div class="frameC">Frame 3</div>
<div class="suspC">Susp 3</div>
<div class="wheelC">Wheel 3</div>
<div class="typeC">Constructor name 3</div>
<div class="deleteC"><button class="delButton">Delete</button></div>
</div>
</div>

How to remove duplicate childNode elements within a parent in Javascript?

How do you remove any duplicate childNodes from a parent element so that there is never more than 1 element with the same innerText within the parent? HTML example below of what the before and the intended after is.
HTML
<div id="parent">
<div class="child">hello</div>
<div class="child">hello</div>
<div class="child">world</div>
<div class="child">world</div>
</div>
Goal
<div id="parent">
<div class="child">hello</div>
<div class="child">world</div>
</div>
Try this.
var children = document.querySelectorAll(".child")
var tmpTexts = []
for (const c of children) {
if (tmpTexts.includes(c.innerText)) continue
tmpTexts.push(c.innerText)
c.parentNode.removeChild(c)
}
<div id="parent">
<div class="child">hello</div>
<div class="child">hello</div>
<div class="child">world</div>
<div class="child">world</div>
</div>
Here’s another way of doing it:
const children = document.querySelectorAll('.child');
function filterChildren(text, i, textArray) {
if ( textArray.indexOf(text) <= textArray.lastIndexOf(text) && textArray.indexOf(text) !== i ) {
children[i].parentNode.removeChild( children[i] )
}
}
Array
.from(children)
.map( child => child.innerHTML )
.forEach(filterChildren);
<div id="parent">
<div class="child">hello</div>
<div class="child">hello</div>
<div class="child">world</div>
<div class="child">world</div>
</div>

How can I toggle a class to various items?

I just want to toggle a class from various items. I mean, I have 5 divs with .item class inside a div with .container class. Can I toggle a new class to those 5 .items? Maybe with a loop?
I was trying to do it but it seems that the loop goes infinite.
This is what I tried:
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<button onclick="myFunction()"></button>
</div>
<script>
function myFunction () {
var x = document.getElementsByClassName("item");
for (i=0; i<x.length; i+1) {
x[i].classList.toggle('new-class');
}
}
</script>
I expect something like this at the end (maybe with some loop in JS):
<div class="container">
<div class="item new-class"></div>
<div class="item new-class"></div>
<div class="item new-class"></div>
<div class="item new-class"></div>
<div class="item new-class"></div>
</div>
You can do it by using the for loop and the classList.add() method.
function myFunction() {
var items = document.querySelectorAll('.item');
for(var i = 0; i < items.length; i++) {
items[i].classList.add('new-class');
}
}

grouping nodeList elements into separate Groups

I have following nodeList
['<div class="item">1</div>', '<div class="item">2</div>', '<div class="item">3</div>', '<div class="item">4</div>']
and following function which accepts the number of element for a group and generates group of elements wrapped by divs
function groupElms (nOfElms) {
var count = 0;
[].forEach.call(nL, function (item) {
count++;
});
}
lets say noOfElms is 2 then the function should generate Elements like this
<div>
<div class="item">1</div>
<div class="item">2</div>
</div>
<div>
<div class="item">3</div>
<div class="item">4</div>
</div>
if noOfElms is 3 it should be like
<div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<div>
<div class="item">4</div>
</div>
I dont understand how to achieve this. Please Could someone help me with this.
You can simply loop through your items and place every N of them into a created wrapper like this:
function groupNodes(list, groupBy)
{
var list = [].slice.call(list);
var parent = list[0].parentElement;
for (var i = 0; i < list.length; i += groupBy)
{
var lastWrapper = document.createElement('div');
lastWrapper.className = 'wrapper';
parent.appendChild(lastWrapper);
[].forEach.call(list.slice(i, i + groupBy), function(x) {
lastWrapper.appendChild(x);
});
}
}
groupNodes(document.getElementsByClassName('item'), 3);
.wrapper {
border: 2px solid black;
}
<div id="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>
Note that it is supposed that all of these items are siblings. Otherwise, they all will be moved to the parent of the first item.
It can be done even easier using jQuery .wrap() function:
function groupNodes(selector, groupBy)
{
var $list = $(selector);
for (var i = 0; i < $list.length; i += groupBy)
$list.slice(i, i + groupBy).wrapAll('<div class="wrapper"></div>');
}
groupNodes('.item', 3);
.wrapper {
border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>
use the following
lets say
var a = ['<div class="item">1</div>', '<div class="item">2</div>', '<div class="item">3</div>', '<div class="item">4</div>'];
then function should be written like the following
function groupElms (nOfElms) {
var count = 1;
a.forEach(function (item) {
if(count == 1) {
var tempDiv = document.createElement("div");
}
tempDiv.appendChild(item);
if(count == nOfElms) {
document.body.appendChild(tempDiv);
delete tempDiv;
count=1;
}
count++;
});
}

JQuery Sort Divs by child divs

I have the following list of divs and I'd like to be able to sort them using Javascript / JQuery.
<div class="item">
<div class="genre">Classical</div>
<div class="name">Alpha</div>
<div class="location">London</div>
</div>
<div class="item">
<div class="genre">Blues</div>
<div class="name">Bravo</div>
<div class="location">New York</div>
</div>
<div class="item">
<div class="genre">Pop</div>
<div class="name">Charlie</div>
<div class="location">Paris</div>
</div>
<div class="buttons">
Sort by Genre
Sort by Name
Sort by Location
</div>
I'd like to be able to sort the items by their Genre/Name/Location alphabetically.
Example: If Sort by Genre was clicked, it would sort the items in 0-9 A-Z by Genre.
If any of you have any tips it would greatly be appreciated.
Cheers :)
You have to make a little change to html like following:
<div id="container">
<div class="item">
<div class="genre">Classical</div>
<div class="name">Alpha</div>
<div class="location">London</div>
</div>
<div class="item">
<div class="genre">Blues</div>
<div class="name">Bravo</div>
<div class="location">New York</div>
</div>
<div class="item">
<div class="genre">Pop</div>
<div class="name">Charlie</div>
<div class="location">Paris</div>
</div>
</div>
<div class="buttons">
Sort by Genre
Sort by Name
Sort by Location
</div>
jQuery
function sorting(tag) {
var items = $('div.item').sort(function(a, b) {
var txt1 = $.trim($('div.' + tag, a).text()),
txt2 = $.trim($('div.' + tag, b).text());
if (txt1 > txt2) return 1;
else return -1;
});
return items;
}
$('.buttons a').on('click', function(e) {
e.preventDefault();
$('div#container').html(sorting(this.id));
});
Working Sample
Ok, this would be my pure JS solution.
First, we should wrap your <div>s into a larger container.
<div id = "wrapper">
<div id = "item">...</div>
<div id = "item">...</div>
<div id = "item">...</div>
</div>
Now, let's define a constant - which property do you want to sort it by? (this will probably be a function parameter later in your code).
var propName = "genre";
Let's get all the <div>s and put them in an array.
var items = document.getElementsByClassName("item");
var itemsArray = new Array();
Let us sort them lexicographically according to the text of the selected property.
for (var i = 0; i < items.length; i++)
itemsArray.push(items[i]);
itemsArray.sort(function(a, b) {
var aProp = a.getElementsByClassName(propName)[0].firstChild.nodeValue;
var bProp = b.getElementsByClassName(propName)[0] .firstChild.nodeValue;
if (aProp < bProp)
return -1;
else if (aProp > bProp)
return 1;
else
return 0;
});
Let us construct a document fragment consisting of the sorted <div>s.
var fragment = document.createDocumentFragment();
for (var i = 0; i < itemsArray.length; i++)
fragment.appendChild(itemsArray[i].clone());
Finally, let us clear the contents of the <div id = "wrapper"> and replace it with the document fragment.
document.getElementById('wrapper').innerHTML = '';
document.getElementById('wrapper').appendChild(fragment);
Also, note that document.getElementsByClassName does not work in IE<9, but I was now really lazy to cope with that issue.
A fiddle: http://jsfiddle.net/nNXr4/
Check this beast:
function sortByCreatedOnAsc(a,b){
return $(a).find('.created_on').text() > $(b).find('.created_on').text();
}
function sortByCreatedOnDesc(a,b){
return $(a).find('.created_on').text() < $(b).find('.created_on').text();
}
function reorderEl(el){
var container = $('#tasks');
container.html('');
el.each(function(){
$(this).appendTo(container);
});
}
$('#created_on').click(function(){
if($(this).hasClass("asc")){
reorderEl($('.task').sort(sortByCreatedOnDesc));
$(this).removeClass("asc");
$(this).addClass("desc");
} else {
reorderEl($('.task').sort(sortByCreatedOnAsc));
$(this).removeClass("desc");
$(this).addClass("asc");
}
return false;
});
jsfiddle: http://jsfiddle.net/jKJc3/116/

Categories