1

I am working on a simple example, if a user clicks on element then all the elements above it should have a class and all elements below it should not have any class applied to them.

Here is my code:

<script>
function test(object) {
    var pid = object.id;
    var id = parseInt(pid.split("")[1]);
    console.log(id);
    for (var i = 1; i <= id; i++) {
        var element = document.getElementById("p"+i);
        console.log(element);
        element.className = "active";
    }
    console.log(id+1);
    for(var i = id+1; i <= 4; i++) {
        var element = document.getElementById("p"+i);
        element.className.replace(new RegExp('(?:^|\\s)'+ 'active' + '(?:\\s|$)'), ' ');
        console.log(element);
    }
}   
</script>

<div id="divid">
    <p id="p1" onclick="test(this)">one</p>
    <p id="p2" onclick="test(this)">two</p>
    <p id="p3" onclick="test(this)">three</p>
    <p id="p4" onclick="test(this)">four</p>
</div>

So here if I click on three then the elements for one, two, three should have the class active and element four should not have any class. This is working fine.

Now if I click on one, I am expecting that two, three, four should have any css class but it is not working like that.

Can you please help me where is the issue. I want to use plain Javascript.

3
  • what if,,p2 comes after p3? Commented Jul 14, 2017 at 20:00
  • @KoushikChatterjee, good question. currently my id's are incrementing only. Need to check this scenario alos. Commented Jul 14, 2017 at 20:01
  • hmmm, given a simple solution for that case too, please check the new answer by me. Commented Jul 14, 2017 at 20:11

4 Answers 4

4

It might be wise to consider an alternative to using the onclick attribute due to separation of concerns. The following allows you to alter the HTML without having to consider JavaScript while you work.

https://jsfiddle.net/gseh0wxc/2/

var getList = (selector) => [].slice.call(document.querySelectorAll(selector));

var paragraphs = getList("#divid p[id ^= 'p']");
paragraphs.forEach((paragraph, index) => {
  paragraph.addEventListener('click', (e) => {
    for (let i = 0; i < index; i++) {
      paragraphs[i].classList.remove('active');
    }
    for (let i = index; i < paragraphs.length; i++) {
      paragraphs[i].classList.add('active');
    }
  });
})
Sign up to request clarification or add additional context in comments.

6 Comments

This is really good, can you please explain what this code indicates? var getList = (selector) => [].slice.call(document.querySelectorAll(selector));
It creates a function called getList that returns an array of elements that match whatever CSS selector you pass into it. The big thing is that it returns an Array of elements that you can actually manipulate.
interesting, I want to know more, can you please point me to some documentation of javascript that explains this feature, never saw this earlier.
It's something you learn while you progress and it becomes incredibly useful. For more of an explanation of why it's used and useful take a look at this post: stackoverflow.com/questions/19099170/…
This should be the accepted answer because it solves the problem and also improves the code quality, which is always good for SO.
|
1

Please try this code

function test(object) {
    var pid = object.id;
    var id = parseInt(pid.split("")[1]);
    console.log(id);
    for (var i = 1; i <= id; i++) {
        var element = document.getElementById("p"+i);
        element.classList.add("active");
    }
    console.log(id+1);
    for(var i = id+1; i <= 4; i++) {
        var element = document.getElementById("p"+i);
        element.classList.remove("active");
    }
}

Hope this helps.

3 Comments

I see like this <p id="p3" onclick="test(this)" class="">three</p> is it possible to remove the class attribute itself so it looks like <p id="p3" onclick="test(this)">three</p>
Sure. You can use removeAttribute class. For example element.removeAttribute("class"); Then you'll get what you want.
Code only answers are less useful than those with explanations of exactly what code was added/removed. It would be even better if you'd add references where users could learn about the classList interface.
1

try this simple approach instead, don't need to extract id number and all, and with a single simple loop.

function test(option) {
//this will select all p tags id starts with "p" inside div having id "divid" and return a array
var targetPTags = document.querySelectorAll("div#divid p[id^=p]")
var idx, flag=false;
    //we are iterating over that array and taking each dom element in el
    for(idx=0;idx<targetPTags.length;idx++) {
        var el = targetPTags[idx];
        if(flag) {
            //do operation you want for after elements in el
        } else if(option===el) {
            flag=true; // we are making flag true when its the element that clicked and doing no operation
            //do the operation you want for the element, may be the same as below operation in else
        } else {
            //do operation you want for before element in el
        }
    }
}

2 Comments

Can you please explain this code, what the if, else if and else doing here. Not able to co-relate with my program.
@user3181365 i have edited my answers with comments, that may help. otherwise tell me I will explain further.
0

Kind of similar to "Chatterjee"'s solution, but here you go:

function test(object)
{
    var parentElem = null;
    var childElems = null;
    var currElemSet = false;
    var i=-1;

    try
    {
        parentElem = object.parentElement;

        if(parentElem!=null)
        {
            childElems=parentElem.getElementsByTagName(object.nodeName); // could refine to accommodate sibling nodes only
            if(childElems!=null)
            {
                for(i=0;i<childElems.length; i++)
                {
                    if(currElemSet) childElems[i].className = "";
                    else childElems[i].className = "active";

                    if(childElems[i]==object) currElemSet = true;
                }
            }

        }
    }
    catch(e)
    {
        alert("Error:  " + e.Message);
    }
    finally
    {

    }

}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.