joe92 Posted February 7, 2012 Share Posted February 7, 2012 Hi, I am writing a function which will apply an active class to a div that has been clicked. I am running into a problem in that the function that is called on all the elements involved doesn't know how to differentiate between the elements, and will therefore jump to the highest element with the call. If that's clear enough? The function is written to first remove the active class from whichever element it used to be on, and then apply it to our current element. Here is the javascript function: function setActiveThis(el){ var container = document.getElementById('activeContainer'); var containerEls = container.getElementsByTagName('*'); var theClass = ''; var newClass = ''; for(var i=0;i<containerEls.length;i++) { /*get the class of the current element*/ theClass = containerEls[i].className; /*check the class is not blank*/ if(theClass != '') { /*check if this element is the active one*/ if(theClass.match(/active/)) { /*remove the active class from it*/ newClass = theClass.replace(/\s?active/, ''); containerEls[i].className = newClass; /*since there is only ever one active class break out of the loop*/ i = containerEls.length; } } } var elClass = el.className; elClass += ' active'; el.className = elClass; } And here is the HTML that I am testing it with: <div id="activeContainer"> <div onclick="setActiveThis(this);"> Content1 <div onclick="setActiveThis(this);"> Content2 <div onclick="setActiveThis(this);"> Content3 <div onclick="setActiveThis(this);"> Testing </div> </div> </div> </div> <div onclick="setActiveThis(this);"> I work because there are no higher elements with the setActiveThis function around me </div> </div> What I need is for when I click on a div, for example the word testing, the active class be applied to ONLY the div which directly contains it. Currently, it is applying it to the highest element that wraps around it with the setActiveThis function, in this example applying it to the div with content1. How can I get it to apply the active class to the 'testing' div only? If this isn't clear enough, please say so and I will try to reword my problem. Any and all help is appreciated! Cheers, Joe Quote Link to comment Share on other sites More sharing options...
Psycho Posted February 8, 2012 Share Posted February 8, 2012 You have two problems: 1. The child elements are INSIDE the parent elements. So, when you click on the child you are also clicking on the parent. If you put an alert in the function you will see it popup multiple times based upon which child element you select. 2. The child elements will inherit the styles of the parent elements. The easy fix is to not have nested divs. Quote Link to comment Share on other sites More sharing options...
nogray Posted February 8, 2012 Share Posted February 8, 2012 You can just stop the event propagation. Quote Link to comment Share on other sites More sharing options...
joe92 Posted February 8, 2012 Author Share Posted February 8, 2012 You have two problems: 1. The child elements are INSIDE the parent elements. So, when you click on the child you are also clicking on the parent. If you put an alert in the function you will see it popup multiple times based upon which child element you select. 2. The child elements will inherit the styles of the parent elements. The easy fix is to not have nested divs. Problem 2 is actually a desired result - when they click the parent it highlights them all by carrying the style through and when they click the child it only highlights the child. It's problem 1 that I'm trying to get around. I just don't know how yet. You can just stop the event propagation. Thank you for pointing me in the right direction. Google's given me this tutorial, which describes my exact problem in the first sentence, from a quick search so I'll see what I can do. I wasn't even aware of event propagation so I might be back soon with another question Looks interesting though, thanks again! Quote Link to comment Share on other sites More sharing options...
joe92 Posted February 8, 2012 Author Share Posted February 8, 2012 OK, after a morning of reading and learning new JavaScript functions and tricks I have come up with the following to try and fix it. function cancelBubble(e) { var evt = e || window.event; /*ff/chrome etc. route*/ if (evt.stopPropagation) { evt.stopPropagation(); } /*ie route*/ else{ evt.cancelBubble = true; } } function setActiveThis(tg){ /*add custom event listener to the element to prevent event propagation*/ if(tg && tg.addEventListener) { tg.addEventListener('click', cancelBubble, false); } else if(tg && tg.attachEvent) { tg.attachEvent('onclick', cancelBubble); } /*start event*/ var container = document.getElementById('activeContainer'); var containerEls = container.getElementsByTagName('*'); var theClass = ''; var newClass = ''; for(var i=0;i<containerEls.length;i++) { /*get the class of the current element*/ theClass = containerEls[i].className; /*check the class is not blank*/ if(theClass != '') { /*check if this element is the active one*/ if(theClass.match(/active/)) { /*remove the active class from it*/ newClass = theClass.replace(/\s?active/, ''); containerEls[i].className = newClass; /*since there is only ever one active class break out of the loop*/ i = containerEls.length; } } } var tgClass = tg.className; tgClass += ' active'; tg.className = tgClass; } This works perfectly, absolutely what I needed. However, it only works after the first click. I.e. the first click still applies the active class to the highest element with the event attached to it, but all subsequent clicks go in their intended positions. Any idea why that's happening and how I can fix it? I'm guessing that it may be to do with the timing of when I add the event listeners? Thanks for all you help. I've nearly got this one sorted, Joe Quote Link to comment Share on other sites More sharing options...
joe92 Posted February 8, 2012 Author Share Posted February 8, 2012 And it was entirely to do with the timing. To get round it, I've attached a class of stopPropagation to all the elements that have the setActiveThis function attached to them. Then on window.load I run a function that loop's through all elements with this class and attaches the needed event listener to stop event propagation. Problem solved and I've learnt a lot! Thank you, Joe Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.