Dmitry Chernyshov Dmitry Chernyshov - 1 month ago 12
HTML Question

How to change next(previous)Sibling color in list using Javascript?

I just need onclick function, which will change the color of each next (previous) element of the list. But I don't understand how to do it. Please, help.

HTML (need two last buttons).

<ul id="myUL"><li>First element</li><li>Second element</li></ul>
<form>
<input type="button" id="add" value="Add" onclick="append(this.form)">
<input type="button" id="delete" value="Delete" onclick="remove()">
<input type="button" id="addStart" value="Add in beginning" onclick="addBeg(this.form)">
<input type="text" id="myinput" name="input" size="30" /><br />
<input type="button" id="selectFirst" value="Select first element" onclick="selectFirstEl()">
<input type="button" id="selectLast" value="Select last element" onclick="selectLastEl()">
<input type="button" id="selectNext" value="Select next element" onclick="selectNextEl(this.form)">
<input type="button" id="selectPrevious" value="Select previos element" onclick="selectPrevEl(this.form)">
</form>


JavaScript (functions for every button)

function append(form) {
if (form.input.value) {
var newItem = document.createElement("li");
newItem.innerHTML = form.input.value;
document.getElementById("myUL").appendChild(newItem);
}
};

function remove() {
var list = document.getElementById("myUL");
var item = list.lastChild;
list.removeChild(item);
}
function addBeg(form) {
if (form.input.value) {
var newItem1 = document.createElement("li");
newItem1.innerHTML = form.input.value;
document.getElementById("myUL").appendChild(newItem1);
var list1 = document.getElementById("myUL");
list1.insertBefore(newItem1,list1.childNodes[0]);
}
};

function selectLastEl() {
var ul = document.getElementById("myUL");
var liLast = ul.lastChild;
var liFirst = ul.firstChild;
liLast.style.color = "green";

if (liFirst.style.color == "green") {
liFirst.style.color = "black";
};

return false;
};
function selectFirstEl() {
var ul = document.getElementById("myUL");
var liLast = ul.lastChild,
liFirst = ul.firstChild;

liFirst.style.color = "green";

if (liLast.style.color == "green") {
liLast.style.color = "black";
};

return false;
};

Answer

First thing to do is finding a way to tell the selectNextEl function, which element is the currently selected one. One could do that through searching for an element with element.style.color == "green", but this would just cost us time and code. We should instead always store a reference to the currently selected element in a variable. If no element is selected, the vairable will be null.

var selectedElement = null;     //Initialization of selectedElement

The selectNextEl() will then first check, if an element is selected as we can't determine the next element, if no is selected. Then we will reset it's color and select the next sibling of it, just to apply the green color to it:

function selectNextEl() {
    //if selectedElement is not equal null
    if(selectedElement) { 
        //reset it's color
        selectedElement.style.color = "black";
        //set it's next sibling as the new selectedElement
        selectedElement = selectedElement.nextElementSibling;
        //apply green to new selectedElement
        selectedElement.style.color = "green";
    }
}

I believe, you can do selectPrevEl() on your own now ;). Remove the this.form from their function calls in onlick if you want.
We now have do modify the existing functions to update selectedElement correctly.
I will post the correct code here and point out some mistakes in your old code below.
Corrected Functions:

function append(form) {
    if (form.input.value) {
        var newItem = document.createElement("li");
        newItem.innerHTML = form.input.value;
        document.getElementById("myUL").appendChild(newItem);
    }
};

function remove() {
    var list = document.getElementById("myUL");
    var item = list.lastChild;
    list.removeChild(item);
}

function addBeg(form) {
    if (form.input.value) {
        var newItem1 = document.createElement("li");
        newItem1.innerHTML = form.input.value;
        var list1 = document.getElementById("myUL");
        list1.insertBefore(newItem1, list1.firstElementChild); 
    }
};

function selectLastEl() {
    //if selectedElement is not equal to null
    if(selectedElement)         
        //reset it's color
        selectedElement.style.color = "black";

    //set new selectedElement
    selectedElement = document.getElementById("myUL").lastElementChild;  
    //apply green color to it
    selectedElement.style.color = "green";                        
};

function selectFirstEl() {
    //if selectedElement is not equal to null
    if(selectedElement)         
        //reset it's color
        selectedElement.style.color = "black";

    //set new selectedElement
    selectedElement = document.getElementById("myUL").firstElementChild;  
    //apply green color to it
    selectedElement.style.color = "green";  
};


Mistakes and Things you should be aware of:

First off, you were using firstChild, lastChild and childNodes. Those functions can also return a textNode. It's safer to use firstElementChild, lastElementChild and children, as they always return tags. In your scenario it won't be an issue, until you change

<ul id="myUL"><li>First element</li><li>Second element</li></ul>

to

<ul id="myUL">
    <li>First element</li>
    <li>Second element</li>
</ul>

in which case, you would get text instead, if you use those commands mentioned first.

Second, you were inside selectLastEl and selectFirstEl originally only checking if the opposite element was selected by e.g.

    if (liFirst.style.color == "green") {
        liFirst.style.color = "black";
    };

However, after appending more elements, it could be any of those, not necessarily the first or last one. So you either would need to check all other elements or reference the selected one through a variable.

Third, in your original addBeg() function, you were first appending the child and later inserting it again. The appendChild(newItem1) had no effect at all.

Fourth, care about indentation! There are handy tools like Beautify in modern IDEs, which do it for you.