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());
}
Related
I have 16 divs with the class "box" and each "box" has a different name.
The first "box" has name="box1";
the second "box" has name="box2";
the third "box" has name="box3";
and so on.....
I want to select these individual names, so I attempted to use the following code:
for (var i = 0; i < $(".box").length; i++) {
console.log($(".box")[i].attr("name"));
}
But my console shows that "$(...)[i].attr is not a function".
When I tried this:
for (var i = 0; i < $(".box").length; i++) {
console.log($(".box").attr("name"));
}
I get back 16 lines of "box1", which is only the name for the first "box" div.
What I want instead is "box1, box2, box3, box4, box5..."
What can I do?
Using jQuery:
$( ".box" ).each(function( index ) {
console.log($(this).attr("name") );
});
Does it have to be jQuery? If not, this could work:
[...document.querySelectorAll('.box')]
.map(d => d.getAttribute('name'))
.forEach(name => console.log(name))
You can do it using jQuery eq
for (var i = 0; i < $(".box").length; i++) {
console.log($(".box").eq(i).attr("name"));
}
or using fully jQuery version
$('.box').each(function(){
console.log($(this).attr('name'));
})
Please note that name is not a supported attribute on div elements, hence making your HTML invalid. Use data-name instead. Once you changed that, that also makes the code easier:
$(".box")[i]
gives you the native DOM element in the jQuery collection, which does not have any jQuery methods like attr(). It does, tho, have the native DOMElement dataset API, so you can simply go with
$(".box")[i].getAttribute('data-name')
or, even simpler
$(".box")[i].dataset.name
If you insist on using jQuery and also on using an index-based for-loop (which I haven't used in years now), go with jQuery's eq(index) function:
$(".box").eq(i).data("name")
As with almost everything, jQuery is just unnecessary bloat you don't need any longer in 2020. Here's the modern way to achieve your goal:
document.querySelectorAll('.box')
.forEach(el => console.log(el.dataset.name);
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 = ...;
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 :)
I am using .map to get an array of element IDs (this is named 'ids') that have a 'default-highlight' class. After removing that class on mouseenter, I want to return that class to those specific id's (basically, leave it how I found it).
Two things are causing me trouble right now:
When I dynamically add data-ids to the td elements and then use those data-ids to create the array of 'ids' my mouseenter stops adding the 'HIGHLIGHT' class (NO idea why this is happening)
On mouseleave I can't loop through the 'ids' and return the 'default-highlight' class to the elements they originally were on
I figure I should be using something like this, but it obviously isn't working:
$.each(ids, function() {
$(this).addClass('default-highlight');
});
I have tried a number of things, but keep coming up short. I am attaching a link to a codepen.io where I use data-ids that are being dynamically added to the table (this one the mouseenter doesn't work) and a codepen one where I am using regular IDs for the default highlight and everything appears to work like it is supposed to be (It isn't, since I want to be using the dynamically generated data-ids and then the subsequently produced array to reapply those classes).
Both of these codepens have a gif at top showing how the interaction should work.
If anything is unclear, please let me know. Thanks for reading!
You need to add # before id selector
$.each(ids, function() {
$('#'+this).addClass('default-highlight');
});
or you can use common selector by the help of map() and join()
$(ids.map(function(i, v) {
return '#' + v;
}).join()).addClass('default-highlight');
or you can add # when getting the id's and then you just need to join them
var ids = $('.default-highlight').map(function(i) {
return '#'+$(this).data('id');
}).get();
...
...
...
$(ids.join()).addClass('default-highlight');
It seems like storing the IDs and using those is overkill when you can store a reference to the jQuery element directly:
$highlightCells = $('.default-highlight').removeClass('default-highlight')
And later give the class back:
$highlightCells.addClass('default-highlight')
Here's a codepen fork: http://codepen.io/anon/pen/ZbOvZR?editors=101
Use this way:
$.each(ids, function() {
$("#" + this).addClass('default-highlight');
});
Please consider the following code :
<!DOCTYPE html>
<html>
<style>
p{ width:200px; }
</style>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<p><span>Hello</span>, how are you?</p>
<p>Me? I'm <span>good</span>.</p>
<script>
$(document).ready(function(){$("p").find($("*")).andSelf().css("background- color","blue"); });
</script>
</body>
</html>
The output is the whole document turning into blue color while I only wanted the paragraph and span inside it to turn blue.
If I use $("p").find(" * ") instead of $("p").find($(" * ")) then everything shows according to my need. Can anyone work out the difference between the two approach?Thanks!
Note: Please everyone note that I know there are easier methods to do this stuff,but I just want to know why this didn't work..
Disclaimer: The other answers already suggest better selectors to
achieve your goal, but I understand you want to know why andSelf()
ends up matching all the elements in the document, so I'll try to
explain that.
First, as you know, andSelf() adds the previous set of elements on the stack to the current set. So, in your case, it seems it should add the <p> elements to the set containing their descendants:
$("p") // match the paragraphs
.find($("*")) // match all the elements that descend from a paragraph
.andSelf() // add the paragraphs to the elements above
However, the above assumes that find($("*")) is the previous set of elements, and that's simply not the case here. The first hint about this comes from the documentation for find():
As of jQuery 1.6, we can also filter the selection with a given jQuery
collection or element. With the same nested list as above, if we start
with:
var $allListElements = $('li');
And then pass this jQuery object to find:
$('li.item-ii').find( $allListElements );
This will return a jQuery collection which contains only the list
elements that are descendants of item II.
The last sentence is particularly interesting: it seems to imply that the jQuery object passed to find() is filtered in order to match the descendants of the elements in the original set. If that's indeed the case, the logic would be inverted, and the previous element set would end up being $allListElements instead of the set returned by find().
A look at the jQuery source code shows that's exactly what happens:
find: function(selector) {
var self = this, i, l;
if (typeof selector !== "string") {
return jQuery(selector).filter(function() {
for (i = 0, l = self.length; i < l; i++) {
if (jQuery.contains(self[i], this)) {
return true;
}
}
});
}
// [...]
}
So, when you write:
var elements = $("p").find($("*")).andSelf();
You're actually writing the equivalent of:
var self = $("p"), i, l;
var elements = $("*").filter(function() {
for (i = 0, l = self.length; i < l; i++) {
if ($.contains(self[i], this)) {
return true;
}
}
}).andSelf();
As you can see, the previous element set is actually $("*") instead of the set returned by find($("*")) because of the logic inversion. Therefore, all the elements in the document end up being legitimately added to the current set by andSelf().
You just need
$("p").css("background-color","blue");
To change the color or all the p tags in the document. Is there some specific reason for the way you have done it?
The $("*") has no context, so it selects every element in the document. You want to find all elements within the currently selected element, so you need to just pass the string to find.
However, it's completely unnecessary and you could just apply the style to the p (as the span is a child you don't to apply it to that too):
$("p").css("background-color","blue");
Note that in that line above I've used background-color with no spaces, unlike in your question. I'm guessing it was just a typo when you wrote the question, but it won't work if you put spaces in the property name.
You don't have to do any of that. Just do this.
$(function() { $("p").css('background-color', 'blue'); });
Note: $(function() {}); is the same as $(document).ready(function(){});
Edit: Since you have two, you may have to do this:
$(function() { $("p").each(item, function() { item.css('backround-color', 'blue'); })});
Edit2: Based on your comments, you want this:
$(function() { $("p").find('span').andSelf().css('background-color', 'blue'); });
The difference between $("p").find(" * ") and $("p").find($(" * ")) is that in the second one you're passing find() a jquery object instead of a regular selector string.
EDIT: I just tried it out. Looks like adding the andSelf() makes it select the entire document somehow. The logical process would be select p > find all elems inside that match everything in the document > select self(p) > color, but it seems to be going wrong at the select self bit.
I think it(the andSelf()) just selects the object passed to find(), which is $('*'), and so selects everything.
If you want to select all P's simply use
$(document).ready(function(){
$("p").css("background-color","blue");
});
No reason to complicate stuff
If you want to select the spans inside you can do something like
$(document).ready(function(){
$("p > span").css("background-color","blue");
});
** Update **
Your selector attribute in your find query is bad, you shouldn't have it like $("*") but only "*". However the $("p").find("*")... will only select any elements inside the <p> tag so trailing the find method with an andSelf will make the selection ambiguous.