Unable to change the class of a div using JavaScript - javascript

So I got into JavaScript and tried setting up the following scenario:
I have 2 Buttons on my Site (IDs are buttonWebdev and buttonUXUI), which should trigger an Action when they are hovered upon. If buttonWebdev is hovered upon, it should hide all p', h3's and imgs with the class "classWeb". I wrote this code to do it, but it doesn't work:
HTML:
<h3 class="classWeb">Editierbare Inhalte</h3>
<p class="classWeb">Test</p>
<button class="buttonImg" id="buttonWebdev"><img src="./img/buttonWebdev.png" /></button>
<script type="text/javascript">
var button = document.getElementById('buttonWebdev');
var classWeb = document.getElementsByClassName('classWeb');
button.onmouseover = function() {
classWeb.className = 'webdev';
}
CSS:
.classWeb.webdev {
display: none;
}

First, since there can be more than one element with a given class on a page, getElementsByClassName returns a list of elements instead of a single element. You’ll need to perform your action on every element of that list, with a for…of loop, for example:
for (let element of classWeb) {
element.className = 'webdev';
}
(for…of is relatively new, though, so you might have to use a regular for loop depending on your target browsers.)
After fixing this, you’ll run into another problem. When you assign to className like that, you’re setting the entire list of classes on an object. If the list of classes is 'webdev', it no longer includes 'classWeb'. Modern browsers support an API to add a class without affecting the rest:
for (let element of classWeb) {
element.classList.add('webdev');
}
The way to diagnose these sorts of problems is by opening up your browser’s developer tools, looking for JavaScript errors in the console, and looking at the state of the elements you’re trying to affect in the document tree.

document.getElementsByClassName('classWeb'); this gives collection & to add classes you need to iterate over them & then apply classes.
classWeb[0].className = 'webdev'; would reset class
either use classWeb[i].className += ' webdev'; or classWeb[i].classList.add('webdev');
See below working example
var button = document.getElementById('buttonWebdev');
var classWeb = document.getElementsByClassName('classWeb');
button.onmouseover = function() {
for (var i = 0; i < classWeb.length; i++)
classWeb[i].className += ' webdev';
}
.classWeb.webdev {
display: none;
}
<h3 class="classWeb">Editierbare Inhalte</h3>
<p class="classWeb">Test</p>
<button class="buttonImg" id="buttonWebdev">hover over me</button>

Firstly, the
document.getElementsByClassName('classWeb');
will give you a LIVE list of all the matched elements. That means that when you reassign the class like so:
classWeb[0].className = 'webdev';
the element will be removed from the list, as it no longer corresponds to the original command which was to find all elements with a specific class (which you overrode with 'webdev').
An easier and more friendly api is querySelectorAll which mimics the jQuery selector (which uses css selectors to find elements, thats why there is a # for an id and a . for a class name). The example below shows, how to use it.
var button = document.querySelector('#buttonWebdev');
var classWeb = document.querySelectorAll('.classWeb');
button.onmouseenter = function() {
for (var i = 0; i < classWeb.length; i++) {
classWeb[i].className = 'webdev';
}
}
ps. The querySelectorAll is not a live list, so items will not disappear after you change their class.
ps2. Use onmousenter instead of onmouseover as the onmouseenter is only called when the mouse starts hovering over an element, while onmouseover will be called on every mouse move over the element (even if already hovering).
Good luck!

Related

getElementsByClassName but manipulate only the one that i want

i have multiple div with same classname but i want to change only one of their opacity, the one that i interact with a mouse or touch. How can i do it? The below code changing all of theirs properties, apparently. Full .js code is here if anyone would like to take a look at: https://jsfiddle.net/b7y6mfv4/
var target1 = document.getElementsByClassName('beforeLabel');
var target2 = document.getElementsByClassName('afterLabel');
for (var i=0; i<target1.length; i++) {
target1[i].style.opacity = beforeAfter;
target2[i].style.opacity = beforeAfter2;
}
Based on your fiddle, change document.getElementsByClassName to evt.target.getElementsByClassName and get rid of the loop.
Target lets you reference only the element that is the target of the event.
Your JS is looping through all elements with either of those two class names and applying opacity. What you can do is make use of the mouse events target property, which will give you the specific element which has been interacted with, and apply the opacity to that.
document.addEventListener('mouseover', (event) => {
if (event.target.className.includes("beforeLabel")) {
event.target.style.opacity = 0.5;
}
});
You can see a full working example here.

Changing a Background-image CSS with Javascript

I have a Wordpress site with a background in the header inside of a class.
I'm tring to write a bit of JS to change this background image depending on a hashtag. The Hashtag script is working but the change BG bit isn't - please help... :-(
The script I've writen is:
document.getElementsByClassName("eut-bg-image").style.backgroundImage = "url(https://boutiqueballer.com/wp/wp-content/uploads/2017/10/chanel.jpg)";
})();
getElementsByClassName yields a collection of elements. The individual elements in the collection have the style property, not the collection itself. If you are targeting just one element, you can access it by index:
document.getElementsByClassName('eut-bg-image')[0].style.backgroundImage = ...;
If you are targeting several elements, you may iterate over them:
var elements = document.getElementsByClassName('eut-bg-image');
for(var i = 0; i < elements.length; i++)
elements[i].style.backgroundImage = ...;
Alternatively, you may use document.querySelector, depending on which level of browser compatibility you need. You can then distinguish between document.querySelectorAll if you want a collection, or docment.querySelector if you want only the first match. Accepts a CSS selector:
document.querySelector('.eut-bg-image').style.backgroundImage = ...;

Most efficient way to change class of the anchor element based on query string

Criteria - I prefer not to use any additional library, want to perform this with just pure javascript, but happy to use one if needed.
I want to add an additional class to anchor elements which have a query string of 'xyz=negate'. My page typically has more than 200 anchor elements. I am looking for the most efficient way to achieve this.
The user base for my website still has a decent number of IE 8 (intranet site) and hence looking for the most efficient code. My page has anchor elements which look like the following
Visit W3Schools.com!
Visit W3Schools.com!
Visit W3Schools.com!
Visit W3Schools.com!
Visit W3Schools.com!
I want to add class to the first, fourth and fifth anchor element in the above example.
Use * in selector to match, example:
var links=document.querySelectorAll("a[href*='xyz=negate']");
It will find all links with href containing xyz=negate in any part of attribute.
In pure js it is not possible to set class to collection like in Jquery, so we must go through every element and set class.
for ( var i in links ){
links[i].classList.add("someClass");
}
For IE8 ( classList not exists ):
for ( var i in links ){
links[i].className+="someClass";
}
Do you need to actually add the class so can you do it with just CSS?
a[href*="xyz=negate"]:first-child {
background-color: yellow;
}
If you do need the class it should just be
var elem = document.querySelector('a[href*="xyz=negate"]');
if(elem) {
elem.className = elem.className + " active";
}
If it is all, it is just
a[href*="xyz=negate"] {
background-color: yellow;
}
or
var elems = document.querySelectorAll('a[href*="xyz=negate"]');
for (var i=0;i<elems.length;i++) {
elems[i].className = elems[i].className + " active";
}
You can do this in either pure vanilla JS, or also using jQuery, if you like.
The logic and principle is still the same:
find all a anchor elements
where the href attribute contains your preferred query string ("xyz=negate") in the href
loop through the matching elements and add the class (in the examples, .someclass) to that element
Here is a JSFiddle: https://jsfiddle.net/ana4upbh/4/
I have included both the jQuery and Vanilla JS solutions for comparison; just comment/uncomment to use either
Here is a pure JS solution (IE8+ compatible):
// select all "a" (anchor) elements with the query string
var anchors = document.querySelectorAll("a[href*='xyz=negate']");
// loop through each of the matching elements
for (var i = 0; i < anchors.length; i++) {
var el = anchors[i];
// add the 'someclass' class to the element (or whatever meaningful name you use)
if (el.classList)
el.classList.add('someclass');
else
el.someclass += ' someclass';
}
or, here is a jQuery version:
$("a[href*='xyz=negate']").each(function(i) {
$(this).addClass('someclass');
});
or simply
$("a[href*='xyz=negate']").addClass('someclass');
EDIT:
Updated the selector to get desired elements, rather than doing the check within the loop, for performance; as suggested in comments. I'll update the JSFiddle when I get back on the PC JSFiddle is now up to date
EDIT 2:
Removed encapsulation of forEach loop into direct for loop, for clarity.
Added alternative jQuery solution and updated JSFiddle.
Hope this helps!
Any questions, just ask :)

jQuery: Toggle class on one element, remove same from all other

new here and deeply hoping I'm not missing a stupid syntax flaw. I was thinking that my problem is a fairly common one, but somehow nothing has helped so far in my specific case.
There is a simple inline-block list of Image Galleries which are zoomable to fill the parent width. As soon as one is zoomed through click on a child, the others should unzoom by stripping of the class which maximizes them. Nothing more to it.
I achieved the first part via the following jQuery (where the problem is hidden in the for-loop, I think):
$(".zoom").click(function() {
var target = $(this);
target.closest('div.product-item').toggleClass('maximized');
var ot = document.getElementsByClassName('product-item');
for (var i = 0; i < ot.length; i++) {
if (ot[i] !== target) {
ot[i].removeClass('maximized');
}
}
});
So: Some .zoom classed element is clicked, its parent is toggled to maximize and a for loop checks all other elements of the same class as the parent and removes the .maximized class.
The reason the script is constructed with a for-loop and a removeClass is so that the same .zoom elements are able to minimize their parent elements, not only to maximize them.
Im not a javascript professional, but to my knowledge this should work in principle. Am I missing anything here?
This post from a year ago addressed a similar problem but didn't help in my case: jQuery onClick: How to add class to element and remove from all others
You can find a pen to see the script in action here.
$(".zoom").on('click',function() {
var target = $(this);
$('div.product-item').removeClass('maximized');
target.closest('div.product-item').toggleClass('maximized');
});
you can use
if(target.closest('div.product-item').hasClass('maximized')){
$('div.product-item').removeClass('maximized');
}else{
$('div.product-item').removeClass('maximized');
target.closest('div.product-item').addClass('maximized');
}
JSFIDDLE

adding classes (serially numbered) to each DIV on page automatically via javascript?

i'm running a contact-form-plugin on my wordpress installation. everything works fine but i want to style my form a little bit more. to do it like this i have to style some DIVs (which the plugin is processing) in a different way. the problem is: all DIV-containers have no IDs or classes! everything is processed by the plugin and my PHP-skills are like zero so i have to deal with this "naked" DIVs ;-)
the question is: is it possible to add serially numbered classes to each DIV on the current site via javascript?
thanks so far and i hope you get waht i mean (sorry for that shitty english)!
Yet another way, passing a callback to .attr [docs]:
$('div').attr('class', function(i) {
return 'someClass' + i;
});
Though you could also use this for IDs instead, since each class will be unique.
Note that you don't have to use IDs or classes to select elements, there are a number of selectors and traversal methods with which you can get a reference to the elements you want.
To prevent overriding existing classes, either select only the elements with no class or somehow narrow down the selection of divs to only those you want:
$('div:not([class])')
or use .addClass [docs] instead of .attr:
$('div').addClass(function(i) {
return 'someClass' + i;
});
You need something like this,
Live Demo
$('div').each(function(i, item){
$(this).attr('class', "YourClass" + i); //You can replace i with some other variable if required and increment it.
});
You could do this:
var divs = document.getElementsByTagName("div");
var className = "myClass";
for( var i = 0, max = divs.length; i< max; i++ ){
divs[i].setAttribute("class",className + i.toString());
}

Categories

Resources