Reputation: 205
I have a set of divs that looks like this:
<div id="con">
<div> 1 </div>
<div> 2 </div>
<div> 3 </div>
<div> 4 </div>
<div> 5 </div>
</div>
But I want them to flip so that it looks like this:
<div> 5 </div>
<div> 4 </div>
<div> 3 </div>
<div> 2 </div>
<div> 1 </div>
So that when a new <div>
is added it goes to the end of the list.
How can I do this (or is there a better way of doing this)?
Upvotes: 20
Views: 18439
Reputation: 550
A vanilla JS solution:
function reverseChildren(parent) {
for (var i = 1; i < parent.childNodes.length; i++){
parent.insertBefore(parent.childNodes[i], parent.firstChild);
}
}
Upvotes: 24
Reputation: 448
const container = document.getElementById("con");
const divs = Array.from(container.querySelectorAll("div"));
// Reverse the order of the div elements
divs.reverse();
// Append the reversed divs back to the container
divs.forEach((div) => {
container.appendChild(div);
});
<div id="con">
<div> 1 </div>
<div> 2 </div>
<div> 3 </div>
<div> 4 </div>
<div> 5 </div>
<div> 6 </div>
<div> 7 </div>
<div> 0 </div>
</div>
Upvotes: 0
Reputation: 23
I think the easiest is just to use display: flex
#con {
display: flex;
flex-direction: column-reverse;
}
<div id="con">
<div> 1 </div>
<div> 2 </div>
<div> 3 </div>
<div> 4 </div>
<div> 5 </div>
</div>
Upvotes: 1
Reputation: 1576
I found all the above somehow unsatisfying. Here is a vanilla JS one-liner:
parent.append(...Array.from(parent.childNodes).reverse());
Snippet with explanations:
// Get the parent element.
const parent = document.getElementById('con');
// Shallow copy to array: get a `reverse` method.
const arr = Array.from(parent.childNodes);
// `reverse` works in place but conveniently returns the array for chaining.
arr.reverse();
// The experimental (as of 2018) `append` appends all its arguments in the order they are given. An already existing parent-child relationship (as in this case) is "overwritten", i.e. the node to append is cut from and re-inserted into the DOM.
parent.append(...arr);
<div id="con">
<div> 1 </div>
<div> 2 </div>
<div> 3 </div>
<div> 4 </div>
<div> 5 </div>
</div>
Upvotes: 17
Reputation: 1287
without a library:
function reverseChildNodes(node) {
var parentNode = node.parentNode, nextSibling = node.nextSibling,
frag = node.ownerDocument.createDocumentFragment();
parentNode.removeChild(node);
while(node.lastChild)
frag.appendChild(node.lastChild);
node.appendChild(frag);
parentNode.insertBefore(node, nextSibling);
return node;
}
reverseChildNodes(document.getElementById('con'));
jQuery-style:
$.fn.reverseChildNodes = (function() {
function reverseChildNodes(node) {
var parentNode = node.parentNode, nextSibling = node.nextSibling,
frag = node.ownerDocument.createDocumentFragment();
parentNode.removeChild(node);
while(node.lastChild)
frag.appendChild(node.lastChild);
node.appendChild(frag);
parentNode.insertBefore(node, nextSibling);
return node;
};
return function() {
this.each(function() {
reverseChildNodes(this);
});
return this;
};
})();
$('#con').reverseChildNodes();
Upvotes: 6
Reputation: 7946
Another (simpler?) vanilla javascript response: http://jsfiddle.net/d9fNv/
var con = document.getElementById('con');
var els = Array.prototype.slice.call(con.childNodes);
for (var i = els.length -1; i>=0; i--) {
con.appendChild(els[i]);
}
Alternatively, a shorter but less efficient method: http://jsfiddle.net/d9fNv/1/
var con = document.getElementById('con');
Array.prototype.slice.call(con.childNodes).reverse().forEach(function(el) {
con.appendChild(el);
});
Upvotes: 0
Reputation: 303421
Wrapped up as a nice jQuery function available on any set of selections:
$.fn.reverseChildren = function() {
return this.each(function(){
var $this = $(this);
$this.children().each(function(){ $this.prepend(this) });
});
};
$('#con').reverseChildren();
Proof: http://jsfiddle.net/R4t4X/1/
Edit: fixed to support arbitrary jQuery selections
Upvotes: 20
Reputation: 15461
One way:
function flip(){
var l=$('#con > div').length,i=1;
while(i<l){
$('#con > div').filter(':eq(' + i + ')').prependTo($('#con'));
i++;
}
}
Upvotes: 3