Reputation: 4151
I have this html:
<table>
<tr>
<td>
Set right order
</td>
<td>
<span style = "display: block;">asd | <a href = '#' onclick = "moveChoiceTo(this, -1);">↑</a><a href = '#' onclick = "moveChoiceTo(this, 1);">↓</a></span>
<span style = "display: block;">dsa | <a href = '#' onclick = "moveChoiceTo(this, -1);">↑</a><a href = '#' onclick = "moveChoiceTo(this, 1);">↓</a></span>
<span style = "display: block;">qwe | <a href = '#' onclick = "moveChoiceTo(this, -1);">↑</a><a href = '#' onclick = "moveChoiceTo(this, 1);">↓</a></span>
<span style = "display: block;">ewq | <a href = '#' onclick = "moveChoiceTo(this, -1);">↑</a><a href = '#' onclick = "moveChoiceTo(this, 1);">↓</a></span>
</td>
</tr>
</table>
And this JS:
function moveChoiceTo(elem_choice, direction)
{
var curr_index = -1; //index of elem that we should move
var td = elem_choice.parentElement.parentElement; //link to TD
for (var i = 0; i < td.children.length; i++) //determine index of elem that called this function
if (td.children[i].children[0] == elem_choice)
{
curr_index = i;
break;
}
if (curr_index == -1)
return;
if (curr_index == 0 && direction < 0) //if nowhere to move
return;
if (curr_index == td.children.length - 1 && direction > 0) //if nowhere to move
return;
var curr_child = td.children[curr_index]; //save current elem into temp var
td.children.splice(curr_index, 1); //here I getting exception that splice isn't supported by object, but arent this is array?
td.children.splice(curr_index + direction, 0, curr_child); //attempt to insert it
}
I getting exception that splice
isn't supported, but this supposed to be an array and support this method?
What other ways I have to change children order?
Upvotes: 13
Views: 25843
Reputation: 1
Same as dfsq's answer but with some modifications.
var selected_element;
function moveElementTo(selected_element, direction) {
var element_to_move = selected_element,
td = element_to_move.parentNode;
if (direction === -1 && element_to_move.previousElementSibling) {
td.insertBefore(element_to_move, element_to_move.previousElementSibling);
} else if (direction === 1 && element_to_move.nextElementSibling) {
td.insertBefore(element_to_move, element_to_move.nextElementSibling.nextElementSibling)
}
}
function move(dir){
if (selected_element != undefined){
moveElementTo(selected_element,dir);
}else{
console.error("No element Selected to move!");
}
}
<div >
<div onclick='selected_element = this;'><button onclick='selected_element = this.parentNode;'> Select element </button>Element One <button onclick='move(-1);'>Move_up</button></div>
<div onclick='selected_element = this;'><button onclick='selected_element = this.parentNode;'> Select element </button>Element Two <button onclick='move(-1);'>Move_up</button></div>
<div onclick='selected_element = this;'><button onclick='selected_element = this.parentNode;'> Select element </button>Element Three <button onclick='move(-1);'>Move_up</button></div>
</div>
My scenario for this was An element needs to be selected first, because I use it for a popup dialogue for which the operations show up upon long click, the Select Element button is just for demo.
Upvotes: 0
Reputation: 193291
I will add the answer with simpler (and better) approach:
function moveChoiceTo(elem_choice, direction) {
var span = elem_choice.parentNode,
td = span.parentNode;
if (direction === -1 && span.previousElementSibling) {
td.insertBefore(span, span.previousElementSibling);
} else if (direction === 1 && span.nextElementSibling) {
td.insertBefore(span, span.nextElementSibling.nextElementSibling)
}
}
The key idea is using insertBefore method properly. You also don't need to remove anything from DOM.
Upvotes: 23
Reputation: 1359
Splice is not supproted in HTMLCollection, you need to use .removeChild and .insertBefore something like this:
var before = td.children[curr_index + direction];
var child = td.children[curr_index];
td.removeChild(child);
td.insertBefore(child, before); //attempt to insert it
Upvotes: 5