How to add additional class name to an element? - javascript

I can't believe I can't find this in google - I need to add an additional class name to a div with the classname checkField:
<div id="wth" class="checkField"><label>Ok whatever</label></div>
document.getElementById("wth").className="error"; // This works
document.getElementsByClassName("field").className="error"; // Doesn't work
I tried this:
document.getElementsByClassName("field").getElementsByTagName("label").className="error";
^ Also doesn't work.
Can someone please give me some advice? I'm too use to JQuery.

The getElementsByClassName method returns a nodeList, which is an array-like object, not a single element. To do what you want you need to iterate the list:
var divs = document.getElementsByClassName("checkField");
if (divs) {
// Run in reverse because we're
// modifying the result as we go:
for (var i=divs.length; i-- >= 0;) {
divs[i].className = 'error';
}
}
Also, just setting className actually replaces the class instead of adding to it. If you want to add another class you need to do it like this:
divs[i].className += ' error'; // notice the space bar
As for the second thing you're trying to do, that is setting the class of the label instead of the div, you need to loop through the divs and call getElementsByTagName on them:
var divs = document.getElementsByClassName("checkField");
if (divs) {
// Run in reverse because we're
// modifying the result as we go:
for (var i=divs.length; i-- >= 0;) {
var labels = divs[i].getElementsByTagName('label');
if (labels) {
for (var j=0; j<labels.length; j++) {
labels[j].className = 'error';
}
}
}
}

You need to add the class onto the current value:
document.body.className += " foo"; // adds foo class to body
Some browsers support classList which provides methods for adding, removing, and toggling classes on elements. For instance, you could add a new class like this:
document.body.classList.add("newClass");
Imagine the work involved in toggling a class; you'd have to perform some string operation to first determine whether a class is already on the element or not, and then respond accordingly. With classList you can just use the toggle method:
document.body.classList.toggle("toggleMe");
Some browsers don't currently support classList, but this won't prevent you from taking advantage of it. You can download a polyfill to add this feature where it's not natively supported.

try something like
you want to do this by document.body
so try
var demo =document.body;
// also do this by class like var demo = document.getElementsByClassName("div1one");
// or id var demo = document.getElementsId("div1one");
demo .className = demo .className + " otherclass";
or simpler solution if you have jquery as an option
$("body").addClass("yourClass");

Here's are simple utility functions for adding and removing a class:
function addClass(elem, cls) {
var oldCls = elem.className;
if (oldCls) {
oldCls += " ";
}
elem.className = oldCls + cls;
}
function removeClass(elem, cls) {
var str = " " + elem.className + " ";
elem.className = str.replace(" " + cls + " ", " ").replace(/^\s+|\s+$/g, "");
}

Related

querySelectorAll only selecting second element when using this.element

I've recently started learning about JavaScript objects, and how frameworks such as jQuery, and Modernizr work.
I have tried to create my own little "framework", to further learn how JavaScript objects work, and how to utilize them to their full potential.
It's all gone pretty smoothly so far, until I tried to set a global variable using the querySelectorAll() method (and a for loop), to grab multiple elements with the specified selector.
With this, I intended to add or remove a class from each of those elements with that specific selector. However, it only ever worked on the very last element of the bunch.
Here is my (relevant) JavaScript:
var aj = function(sr){
this.selector = sr || null; // set global selector variable
this.element = null;
}
aj.prototype.init = function(){
switch(this.selector[0]){
// first, second, third case e.t.c...
default:
var els = document.querySelectorAll(this.selector); // select all elements with specified selector (set above)
for(var i = 0; i < els.length; i++){
this.element = els[i];
}
}
};
aj.prototype.class = function(type, classes){
if(type === "add"){ // if the user wants to add a class
if((" " + this.element.className + " ").indexOf(" " + classes + " ") < 0){
this.element.className += " " + classes;
}
} else if(type === "remove") { // if the want to remove a class
var regex = new RegExp("(^| )" + classes + "($| )", "g");
this.element.className = this.element.className.replace(regex, " ");
}
};
Example:
<div class="example-class">Example</div>
<div class="example-class">Example 2</div> <!-- only this one will be altered !-->
<script>
$(".example-class").class("add", "classname");
</script>
Why would this be occurring? My for loop appears to be correct, so I am unsure what is wrong. Apologies if it appears pretty obvious, however, I'm still new to vanilla JavaScript.
All help (and suggestions) is appreciated,
Thanks.
for(var i = 0; i < els.length; i++){
this.element = els[i];
}
You have a loop. Each time it goes around the loop it assigns a value to this.element.
The first time it goes around the loop it assigns the value of els[0]. The second time it assigns the value of els[1].
Since you only have two elements that match, it reaches the end of the loop and stops.
At this point, this.element is still equal to els[1].
If you want to do something (like add membership of a class) to each item in els then you have to loop over els at the time you modify className.

How to check class of multiple class elements in javascript, without jquery

I have the following javascript code to put the uploader name before the upload date and view count in youtube search results.
function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
var elems = document.getElementsByClassName('yt-lockup-meta-info');
var elemss = document.getElementsByClassName('yt-uix-sessionlink g-hovercard spf-link');
var elemsss = 1;
var elemssss = 0;
var myElem = document.getElementById('sb-button-notify');
if (myElem == null) elemsss = 0; // these two lines are here to skip the additional element
// that is only there if you are logged in
for (var i = 0; i < elems.length; ++i) {
if (hasClass(elemss[i+elemsss],'yt-uix-tile-link'))
{elemssss=elemssss+1;elemsss=elemsss+3;alert('damn');}
elems[i+elemssss].insertBefore(elemss[i+elemsss],elems[i+elemssss].firstChild);}
Instead of the hasClass function, how can I check the whole class attribute of a multiple class element? This didn't work:
element.className=='yt-uix-sessionlink yt-uix-tile-link
yt-ui-ellipsis yt-ui-ellipsis-2 g-hovercard spf-link'
I just need to check the class, so the code can skip elements with a specific class. An even better solution would be an alternative to document.getElementsByClassName, which would only get elements with exactly the given classes, and ignore ones that have MORE classes.
element.classList
It would return you the array of all the classes present on the element
like ["site-icon", "favicon", "favicon-stackoverflow"] , so then by using normal javascript you can implement hasClass functionality of your own.
So your hasClass function becomes
function hasClass(element, cls){
return element.classList.contains(cls);
}
You can use classList but this is not supported in all browsers.
I think the best solution is something like that:
function hasClass (element, cls) {
var classes = element.className.split(' ');
return classes.indexOf(cls) != -1;
}

What is the best way to check if element has a class?

The problem
If the element has multiple classes then it will not match with the regular property value checking, so I'm looking for the best way to check if the object has a particular class in the element's className property.
Example
// element's classname is 'hello world helloworld'
var element = document.getElementById('element');
// this obviously fails
if(element.className == 'hello'){ ... }
// this is not good if the className is just 'helloworld' because it will match
if(element.className.indexOf('hello') != -1){ ... }
So what would be the best way to do this?
just pure javascript please
function hasClass( elem, klass ) {
return (" " + elem.className + " " ).indexOf( " "+klass+" " ) > -1;
}
In modern browsers, you can use classList:
if (element.classList.contains("hello")) {
// do something
}
In the browser that doesn't implement classList but exposes the DOM's prototype, you can use the shim showed in the link.
Otherwise, you can use the same shim's code to have a generic function without manipulate the prototype.
this 2018 use ES6
const hasClass = (el, className) => el.classList.contains(className);
How to use
hasClass(document.querySelector('div.active'), 'active'); // true
You ask for pure javascript, so this is how jQuery implement it:
hasClass: function( selector ) {
var className = " " + selector + " ",
i = 0,
l = this.length;
for ( ; i < l; i++ ) {
if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
return true;
}
}
return false;
},
rclass is a regular expression of [\n\t\r], to ensure that alternative methods of delimiting class names are not an issue. this would be jQuery's reference to the object(s) and in a sense it makes the code more complicated than required, but it should make sense without knowing the details of it.
This should work for you:
var a = [];
function getElementsByClassName(classname, node) {
if(!node) node = document.getElementsByTagName("body")[0];
var re = new RegExp('\\b' + classname + '\\b');
var els = node.getElementsByTagName("*");
for(var i=0, j=els.length; i<j; i++)
if(re.test(els[i].className)) a.push(els[i]);
return a;
}
getElementsByClassName('wrapper');
for (var i=0; i< a.length; i++) {
console.log(a[i].className);
}
This code will traverse the DOM and search for classes defined as parameter in the main function.Then it will test each founded class elements with a regexp pattern. If it founds will push to an array, and will output the results.
First, split the className by using the " " character, then check the index of the class you want to find.
function hasClass(element, clazz) {
return element.className.split(" ").indexOf(clazz) > -1;
}

jQuery Incorporating a variable within a selector

I've tried adding a variable within the selector, but no dice. I've tried a couple of different ways.
Ex1:
function makeDerp() {
var num = 1;
$("myDiv" + num).append("<h1>derp</h1>");
}
Ex2:
function makeDerp() {
var num = 1;
var thing = $("myDiv" + num);
thing.append("<h1>derp</h1>");
}
Ex3:
function makeDerp() {
var num = 1;
var thing = "$('myDiv" + num + "')";
thing.append("<h1>derp</h1>");
}
On all 3, I get nada. Any ideas? Something with my syntax or am I missing a step?
Your first and second examples will work fine. The problem is your selector, which is currently looking for an element of type myDiv. I'm guessing you meant it to be an id selector (perhaps a class selector, or something else entirely, but the idea is the same):
$("#myDiv" + num).append("<h1>derp</h1>");
Your third example will not work. thing contains a string literal, and that won't have an append method so you'll get a TypeError.
I'm assuming you're using either a class or id selector, in which case you're missing said symbol. Try:
$('#myDiv' + num);

Javascript find child class

I have a table. When the item is dropped I need to apply padding to a single table cell. I have flagged that cell with a class. How do I select it?
droppedRow contains the table row that is has just been dropped.
If it was an id I would do droppedRow.getElementById('..'); Is there something similar for class names. Needs to support >= IE7
Thanks
Using vanilla JavaScript, you'll probably need to load up all of the element's by tag name and then locate it by evaluating each element's classname.
For example (the styles are just for example)...
var tableCells = document.getElementsByTagName('td');
for(var i = 0, l = tableCells.length; i < l; i++) {
if(tableCells[i].className === 'droppedRow') {
tableCells[i].style.padding = '1em';
}
}
If, on the other hand, you're using jQuery, then you should be able to use:
$('.droppedRow').css('padding', '1em');
Note however that in both of these examples, all cells that have the droppedRow class name will receive this styling (rather than just a single element).
If you're not using a library, I'd say stick with the vanilla variant of this functionality - libraries would be too much overhead just to condense this to a single line.
Maxym's answer also provides a solid implementation of getElementsByClassName for older browsers.
There exists getElementsByClassName but it is not supported in IE. Here is what you can do:
var element;
// for modern browsers
if(document.querySelector) {
element = droppedRow.querySelector('.yourClass');
}
else if(document.getElementsByClassName) { // for all others
element = droppedRow.getElementsByClassName('yourClass')[0];
}
else { // for IE7 and below
var tds = droppedRow.getElementsByTagName('td');
for(var i = tds.length; i--; ) {
if((" " + tds[i].className + " ").indexOf(" yourClass ") > -1) {
element = tds[i];
break;
}
}
}
Reference: querySelector, getElementsByClassName, getElementsByTagName
Clientside getElementsByClassName cross-browser implementation:
var getElementsByClassName = function(className, root, tagName) {
root = root || document.body;
if (Swell.Core.isString(root)) {
root = this.get(root);
}
// for native implementations
if (document.getElementsByClassName) {
return root.getElementsByClassName(className);
}
// at least try with querySelector (IE8 standards mode)
// about 5x quicker than below
if (root.querySelectorAll) {
tagName = tagName || '';
return root.querySelectorAll(tagName + '.' + className);
}
// and for others... IE7-, IE8 (quirks mode), Firefox 2-, Safari 3.1-, Opera 9-
var tagName = tagName || '*', _tags = root.getElementsByTagName(tagName), _nodeList = [];
for (var i = 0, _tag; _tag = _tags[i++];) {
if (hasClass(_tag, className)) {
_nodeList.push(_tag);
}
}
return _nodeList;
}
Some browsers support it natively (like FireFox), for other you need provide your own implementation to use; that function could help you; its performance should be good enough cause it relies on native functions, and only if there is no native implementation it will take all tags, iterate and select needed...
UPDATE: script relies on hasClass function, which can be implemented this way:
function hasClass(_tag,_clsName) {
return _tag.className.match(new RegExp('(\\s|^)'+ _clsName +'(\\s|$)'));
}
It sounds like your project is in need of some JQuery goodness or some Dojo if you need a more robust and full-fledged javascript framework. JQuery will easily allow you to run the scenario you have described using its selector engine.
If you are using a library, why not use:
JQuery - $("#droppedRow > .paddedCell")
Thats the dropped row by ID and the cell by class
Prototype - $$("#droppedRow > .paddedCell")

Categories