How to remove class from siblings of an element without JQuery? - javascript

I'm adding a class to an element and want to remove it from siblings. In JQuery it is simple, but how to do it the best way in plain JS?
Here is an example of my code.
<div class="controllers">
<span id='one' class='active'></span>
<span id='two'></span>
<span id='three'></span>
</div>
firstBtn.onclick = function() {
slides[0].className = 'slide active';
this.className = 'active';
};

You can use loop inside click event to remove active class from all elements and then again set it on clicked element.
var el = document.querySelectorAll('.controllers span');
for (let i = 0; i < el.length; i++) {
el[i].onclick = function() {
var c = 0;
while (c < el.length) {
el[c++].className = 'slide';
}
el[i].className = 'slide active';
};
}
.active {
color: red;
}
<div class="controllers">
<span id='one' class='active'>Lorem</span>
<span id='two'>Lorem</span>
<span id='three'>Lorem</span>
</div>

A generic function to set only one active element would be:
const setActive = el => {
[...el.parentElement.children].forEach(sib => sib.classList.remove('active'));
el.classList.add('active')
}
In your example:
let spans = [...document.body.querySelectorAll('.controllers > span')];
spans.forEach(el => el.addEventListener('click', e => setActive(el)))
Fiddle: https://jsfiddle.net/9j1qguac/
Update: At one point, browsers expected Array.from(el.parentElement.children) instead of [...el.parentElement.children]. Both are now supported, but if you start a row with a bracket, the previous row needs a semicolon. (eg a = b \n [1].map... will be treated as a = (b[1]).map....

To remove a class from sibling
var el = document.getElementById( "two" );
var one = el.previousSibling();
one.classList.remove("active");
use previousSibling or nextSibling to traverse to it, and use classList.remove to remove a class.

Remove a class from an element siblings
let elem = document.getElementById('id');
let siblings = elem.parentElement.children;
for(let sib of siblings) {
sib.classList.remove('active')
}

Related

Binding an event listener to multiple elements with the same class

I'm trying to apply the onclick event with JavaScript to the following elements:
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
If I click on the first element (with index [0]) then this works, but I
need this event applicable for all classes:
document.getElementsByClassName('abc')[0].onclick="function(){fun1();}";
function fun1(){
document.getElementsByClassName('abc').style.color="red";
}
.onclick does not expect to receive a string, and in fact you don't need an extra function at all.
However, to assign it to each element, use a loop, like I'm sure you must have learned about in a beginner tutorial.
var els = document.getElementsByClassName('abc');
for (var i = 0; i < els.length; i++) {
els[i].onclick = fun1;
}
function fun1() {
this.style.color = "red";
}
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
To expand on the solution provided by #rock star I added two small additions to the function. First it is better to add / reemove a class (with an associated style rule) to an element than directly applying the stylerule to the element.
Secondly - on the click event - this will now remove the red class (and therefore style) from the previously selected element and add it to the new element. This will allow only one element to be red at a time (in the original solution any element that was clicked would become red).
var els = document.getElementsByClassName('abc');
for (var i = 0; i < els.length; i++) {
els[i].onclick = fun1;
}
function fun1() {
var oldLink = document.getElementsByClassName('red')[0];
if(oldLink) {oldLink.classList.remove('red')};
this.classList.add('red');
}
.red {
color:red;
}
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
This works:
<body>
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
<script>
var elements = document.getElementsByClassName('abc');
for(var i = 0, max = elements.length; i < max; i += 1) {
var clickedElement = elements[i];
clickedElement.onclick=function (){
fun1(this);
};
}
function fun1(element){
element.style.color="red";
}
</script>
</body>

Need to print Dom path when clicked anywhere in a page using only JS

Need to print the all parentnodes nodename in order when we clicked anywhere in a html page. for eg if i clicked somewhere (inside the html page) paragraph. i need output as HTML>Body>Div>p>(clicked)
I need to use only simple javascript for this. I tried the below code. but i can't get answer. help me to findout,
script.js
document.body.onclick = function(e){
var x= e.parentNode.nodeName;
console.log(x);
};
Once you have the event target, you just climb up the parentNode tree, prepending the tag names, e.g.
window.onload = function(){
document.body.addEventListener('click', climbNodes);
}
function climbNodes(e){
var node = e.target;
var ancestors = node.tagName;
while (node.parentNode && node.parentNode.tagName) {
node = node.parentNode;
ancestors = node.tagName + '>' + ancestors;
}
console.log(ancestors);
}
<div>Click here
<div>or here
<p>
<span>or here</span>
</p>
<ul>
<li>or here</li>
</ul>
</div>
</div>
let els = document.getElementsByTagName('*')
let nodes = []
for (let i = 0; i < els.length; i++) {
els[i].addEventListener('click', function() {
event.stopPropagation();
let element = this
nodes = []
while (element.nodeName !== 'HTML') {
// Add element to nodes
nodes.push(element)
// Set element equal to parent element
element = element.parentNode
}
})
}

How to remove wrapper of multiple elements without jquery?

I have a set of elements and want to remove its container wrapper in Javascript.
I've researched around (this, this, and this) but I need a solution that 1) doesn't involve jQuery. 2) and can work on multiple elements.
HTML:
<div class="global-container stacked">
<article class="global"></article>
<article class="global"></article>
</div>
I've tried:
var globalArticles = document.getElementsByClassName('global');
globalArticles.outerHTML = globalArticles.innerHTML;
But that doesn't work. How would one go about removing the wrapper from all article.global?
You could just create your own unwrap() method, something like this
function unwrap(elems) {
elems = 'length' in elems ? elems : [elems];
for (var i = 0; i < elems.length; i++) {
var elem = elems[i];
var parent = elem.parentNode;
var grandparent = parent.parentNode;
grandparent.insertBefore(elem, parent);
if (parent.children.length === 0)
grandparent.removeChild(parent);
}
}
var globalArticles = document.getElementsByClassName('global');
unwrap(globalArticles);
You can use .innerHTML, .removeChild(), .insertAdjacentHTML()
var container = document.querySelector(".global-container");
var html = container.innerHTML; // store `html` of `container`
container.parentElement.removeChild(container); // remove `container`
document.body.insertAdjacentHTML("beforeend", html); // append `html`
<div class="global-container stacked">
<article class="global">1</article>
<article class="global">2</article>
</div>
This should work:
var globalArticle = document.getElementsByClassName('global')[0];
if (globalArticle) {
globalArticle.parentElement.outerHTML = globalArticle.parentElement.innerHTML;
}

Link toggles when clicked twice

This is my javascript and it works great except that if you click the same link twice it toggles. How can I keep that from happening? Ultimately I just want to show a psection based on item clicked... but if you click it twice it toggles.
current = "intersitial"; // div with id="m0" is currently diplayed
function show_or_hide ( id )
{
if ( current ) //if something is displayed
{
document.getElementById ( current ).style.display = "none";
if ( current == id ) //if <div> is already diplayed
{
current = 0;
}
else
{
document.getElementById ( id ).style.display = "block";
current = id;
}
}
else //if nothing is displayed
{
document.getElementById ( id ).style.display = "block";
current = id;
}
}
My HTML is:
<ul>
<li onclick="show_or_hide('intersitial')"><span>intersitial</span></li>
<li onclick="show_or_hide('advancedDetail')"><span>advancedDetail</span></li>
<li onclick="show_or_hide('ultimateDetail')"><span>ultimateDetail</span></li>
</ul>
<div class="megamenu" id="intersitial">intersitial</div>
<div class="megamenu" id="advancedDetail" style="display: none">advancedDetail</div>
<div class="megamenu" id="ultimateDetail" style="display: none">ultimateDetail</div>
I'd suggest changing from the obtrusive JavaScript (using in-line event-handlers, onclick, onfocus, onblur and so on), and instead using JavaScript to bind the events:
// use a function-name that's descriptive of what it does:
function showOnly() {
// or you could use `document.getElementsByClassName('megamenu'):
var divs = document.querySelectorAll('div.megamenu'),
// gets the text from the 'span' of the clicked 'li' (the 'id' for later):
id = this.firstChild.textContent;
// iterates over each of the found '.megamenu' elements:
for (var i = 0, len = divs.length; i < len; i++){
/* if the id of the current 'div' is the same as the text in the 'span'
display = block, otherwise display = none:
*/
divs[i].style.display = divs[i].id === id ? 'block' : 'none';
}
}
// get the 'li' elements:
var lis = document.querySelectorAll('li');
// iterate over those elements and bind an event-handler to them:
for (var i = 0, len = lis.length; i < len; i++) {
lis[i].addEventListener('click', showOnly);
}
JS Fiddle demo.
This approach also avoids littering the global namespace with variables (which are easily over-written inside of other functions, particularly (but not exclusively) when multiple developers work on the same project).
References:
Element.addEventListener().
document.querySelectorAll().
Node.firstChild.
Node.textContent.
function show_or_hide(id)
{
if (current == id) return;
if (current) // if something is displayed
{
document.getElementById ( current ).style.display = "none";
}
document.getElementById ( id ).style.display = "block";
current = id;
}

How to remove the class in javascript?

<div id="tab1" class="nav left">
<ul>
<li>Home</li>
......
</ul>
</div>
Now, i want to remove the class="now" or set the class value empty. If the url not on mangento, I using the following code. But the I don't know how to write the last part.
window.onload = function removeNow() {
var div = document.getElementById("tab1").getElementsByTagName("a");
if (window.location.pathname != '/magento/') {
div.removeClass();
}
}
Thank you.
In modern browsers you can use the classList API:
div.classList.remove( 'now' );
But a problem specific to your code: You must loop in order to remove the class. So try this:
for ( var i = 0; i < div.length; i++ ) {
div[i].classList.remove( 'now' );
}
If your browser doesn't support classList, use this removeClass shim:
function removeClass( elem, name ) {
var classlist = elem.className.split( /\s/ ),
newlist = [],
idx = 0;
for ( ; idx < classlist.length; idx++ ) {
if ( classlist[ idx ] !== name ) {
newlist.push( classlist[ idx ] );
}
}
elem.className = newlist.join(" ");
return true;
}
or with jQuery (with which we are not required to use classList or className):
$('a').each(function() {
if (window.location.pathname != '/magento/')
$(this).removeClass();
});
Set the className property:
div.className = '';
Note that getElementsByTagName returns a (possibly empty) NodeList, so:
var div = document.getElementById("tab1").getElementsByTagName("a");
is a collection of all the A element descendents of the element with ID "tab1" (and so 'div' is probably not a good name).
If all you want to do is remove all class values of the first such A element, then:
div[0].className = '';
will do the job. But since the NodeList might be empty, the following would be more robust:
if (div[0]) {
div[0].className = '';
}
or perhaps
div[0] && div[0].className = '';
it depends on your coding style and maintainability requirements.

Categories

Resources