Javascript change class of an element - javascript

I have ul list and I need to change the class of one of <li> tags with javascript:
<ul>
<li>...</li>
<li class="something"> <- need to change this class to "myclass" (javascript goes here)</li>
<li>..</li>
</ul>
Thank you.

using jQuery (naturally):
$(function(){
$("li.something").removeClass("something").addClass("myclass");
});

As there seems to be alot of jquery answers and it's not always possible to use jquery (for example if your customer/company won't let you use it arrgh!), here is a plain javascript example.
// Where 'e' is the element in question, I'd advise using document.getElementById
// Unless this isn't possible.
// to remove
if ( e.className.match(/something/) ) {
e.className = e.className.replace("something", "")
}
// to add back in
if ( !e.className.match(/something/) ) {
e.className += " something"
}
This will work with multiple classes, for example:
<li class="something another">...</li>

Using regular javascript:
var listitems = document.getElementsByTagName("li");
for (int i = 0; i < listitems.length; i++)
{
if (listitems[i].className == "something")
{
listitems[i].className = "new class name";
break;
}
}
If your <li> tag had an id attribute, it would be easier, you could just do
document.getElementById("liID").className = "newclassname";

Using JQuery:
$('ul li:nth-child(2)').attr('class', 'myclass');

Related

Can I use a For loop with a Nodelist?

Basically I have some HTML code that is a tree, I was traverse the Nodelist for it and and assign certain classes to nodes if they have children, here's a snippet:
<li id='test' class="parentNode">
<button class="customer-btn button"><a href='#'>Customer 6</a></button>
<ul>
<li>
<a href='#'>Customer A</a>
</li>
</ul>
</li>
<li class="parentNode">
<button class="customer-btn button"><a href='#'>Customer 7</a></button>
<ul>
<li>
<a href='#'> Customer A</a>
</li>
</ul>
</li>
This is my Javascript:
parent_list = document.getElementsByTagName("LI");
var i;
$(document).ready(function() {
for (i=0; i < parent_list.length; i++){
children = $(i).find('LI');
document.getElementById('check').innerHTML = children;
}
});
The for loop I have return [object Object], what's the best what to do this?
You don't need jQuery.
window.addEventListener('DOMContentLoaded', run );
function run() {
var allLIElements = document.getElementsByTagName('LI');
for( var i = 0; i < allLIElements.length; i++ ) {
var li = allLIElements[i];
if( li.firstElementChild != null ) {
li.classList.add('hasChildren');
}
}
}
Note that this will soon be unnecessary as CSS has the proposed :has() pseudo-class which you can use to select elements that meet some criteria.
https://developer.mozilla.org/en-US/docs/Web/CSS/:has
The :has() CSS pseudo-class represents an element if any of the selectors, relative to the:scope of the given element, passed as parameters, matches at least one element. The :has() pseudo-class takes a selector list as an argument.
Consider this style rule instead, it will match any li element that contains another element. No JavaScript required.
li:has(> *) { /* As of early 2017 no browser supports this selector yet! */
}
Since you're using jQuery you don't need a for loop
$('li').each(function(index, element){
if($(element).children().length > 0){
$(element).addClass('myClass')
}
})
You can use a for loop for anything, but your code isn't correct...assigning children to innerHTML isn't a compatible assignment, and doing it in a loop will just result in the element 'check' being assigned multiple times, not with an addition.
If you are using jQuery then use:
$('#check').append(children);

one function to fire on same class elements click

I'm trying to make controls for category list with sub-category and sub-sub-category lists.
Here's HTML:
<ul class="selectbox-ul">
<li>
<div>Category</div>
<ul class="selectbox-ul-child">
<li>
<div>Subcategory</div>
<ul class="selectbox-ul-child">
<li>
<div>Sub-subcategory</div>
</li>
</ul>
<span id="trigger">icon</span>
</li>
</ul>
<span id="trigger">icon</span>
</li>
....
</ul>
So my shot was to add class for ul.selectbox-ul-child :
var trigger = document.getElementById("trigger");
function subCatStatus() {
if(this.parentElement.children[1].className != "... expanded") {
this.parentElement.children[1].className += " expanded"
} else {
this.parentElement.children[1].className == "..."
};
};
trigger.addEventListener("click", subCatStatus);
And it works only for first span#trigger(that shows subcategories), next one (for sub-subcategories) does nothing (I've also tried to use .getElementsByClassName it didn't work for any of triggers) . So i'd like to get some explanation why doesn't this one work. And some advice how to make it work.
As others have already mentioned, you can't stack multiple elements with the same ID since document.getElementById() is not supposed to return more than one value.
You may try instead to assign the "trigger" class to each of those spans instead of IDs and then try the following code
var triggers = document.getElementsByClassName("trigger");
function subCatStatus() {
if(this.parentElement.children[1].className != "... expanded") {
this.parentElement.children[1].className += " expanded"
} else {
this.parentElement.children[1].className == "..."
};
};
for(var i = 0; i < triggers.length; i++) {
triggers[i].addEventListener("click", subCatStatus);
}
javascript getElementById returns only single element so it will only work with your first found element with the ID.
getElementsByClassName returns an array of found elements with the same class, so when adding listener to the event on element you would require to loop through this array and add individually to it.

Build list when select option change

I'm trying to display the full list that have the same id that matches with the select option. But I can't figure out how to get the id from the attribute by using the name to be able to filter it.
The html example:
<select id='groopy' onchange='see();'>
<option>default</option>
<option>lista1</option>
<option>list1</option>
</select>
<ul id='grupo'>
<li id='list1' name="lista">Playground (Rangbhoomi)</li>
<li id='default' name="lista">Empire Made Me</li>
<li id='default' name="lista">Transmission</li>
<li id='lista1' name="lista">Hostel Room 131</li>
<li id='default' name="lista">A Disobedient Girl</li>
<li id='default' name="lista">Travels in the Land of Kubilai Khan</li>
<li id='list1' name="lista">The Indian Mutiny</li>
<li id='lista1' name="lista">Beauty and Sadness</li>
<li id='default' name="lista">The Collaborator</li>
<li id='list1' name="lista">I, Lalla</li>
<li id='default' name="lista">No Full Stops in India</li>
<li id='lista1' name="lista">For Lust of Knowing</li>
<li id='default' name="lista">On the Road to Kandahar</li>
</ul>
And the script I'm trying:
<script>
function see(){
var listita = document.getElementById('groopy').options[document.getElementById('groopy').selectedIndex].value;
var items = document.getElementsByName("lista");
var items_id = document.getElementsByName("lista").getAttribute('id');
if(listita==items_id){
for(var i = 0; i < items.length; i++)
{
document.getElementById("description").innerHTML = items[i].outerHTML;
}
}
}
onload= see();
</script>
By the way, the select and the ul are generated dynamically so I don't actually now the id's that could be provided. I'm trying a little different approach here .
When I manage to make the select filter work, the for stop working. WHY? I'm going crazy with this. Please help!!
Firstly you are having multiple elements with same id's which is wrong.. Cause getElementbyId will only fetch the first element encountered by it.
Replace then with class instead
Next you are overwriting the HTML for every iteration, so you will always have the last item appended to it.
Instead store that in a variable and append it after the for loop.
you need to bind your element with a change event, otherwise your call only works once when the page loads for the first time.
Try this
// Cache the selector as you are using it multiple times
var dropdown = document.getElementById('groopy');
function see() {
// set the selected option
var listita = dropdown.options[dropdown.selectedIndex].value
items = document.getElementsByClassName(listita);
html = '';
// For each item with class name, iterate over it and store in a string
for (var i = 0; i < items.length; i++) {
if (items[i].className == listita) {
console.log((items[i].outerHTML));
html += items[i].outerHTML
}
}
// set the html after the for loop
document.getElementById("description").innerHTML = html;
}
onload = see();
// attach the change event handler
dropdown.addEventListener('change', see);
Check Fiddle
try changing the id's to class in the li tags and use this function...
function see(){
var selectedVal = document.getElementById('groopy').options[document.getElementById('groopy').selectedIndex]. value;
var items = document.getElementsByClassName(selectedVal);
var html = '';
for(var i = 0; i < elements.length; i++)
{
html += items[i].outerHTML;
}
document.getElementById("description").innerHTML = html;
}
onload= see();
Step1 - Change id to class
Step2 - Traverse DOM elements with jQuery class selector. In this way replace document.getElementId('id) with $('.className')

jquery get certain class name of element which has several classes assigned

I need to read elements class name. I have elements like this:
<article class="active clrone moreclass">Article x</article>
<article class="active clrtwo moreclass">Article y</article>
<article class="active clrthree moreclass moreclass">Article z</article>
<article class="active clrone moreclass">Article xyza</article>
I need to parse out class name that starts with clr. So if second element was clicked then I would need to get clrtwo className.
You can use a regular expression match on the class name of the clicked item to find the class that begins with "clr" like this:
$("article").click(function() {
var matches = this.className.match(/\bclr[^\s]+\b/);
if (matches) {
// matches[0] is clrone or clrtwo, etc...
}
});
Here is solution for you:
$('article').click(function () {
var className = this.className.split(' ');
for (var i = 0; i < className.length; i+=1) {
if (className[i].indexOf('clr') >= 0) {
alert(className[i]);
}
}
});
http://jsfiddle.net/vJfT7/
There's no matter how you're going to order the different classes. The code will alert you a class name only of there's 'clr' as a substring in it.
Best regards.
If you don't need to find elements based on these classes (e.g. doing $('.clrtwo')) it would be nicer to store the data as a data-clr attribute. This is standards-compliant from HTML5, and is supported by jQuery using the .data() function.
In this instance, I would modify your HTML in this way:
<article class="active moreclass" data-clr="one">Article x</article>
<article class="active moreclass" data-clr="two">Article y</article>
<article class="active moreclass moreclass" data-clr="three">Article z</article>
<article class="active moreclass" data-clr="one">Article xyza</article>
I would then use Javascript like this:
$('article.active').click(function() {
console.log($(this).data('clr'));
});
jsFiddle example
If it is always the second class name which is of interest you can do this:
$("article").click(function () {
// split on the space and output the second element
// in the resulting array
console.log($(this)[0].className.split(" ")[1]);
});
http://jsfiddle.net/karim79/Z3qhW/
<script type="text/javascript">
jQuery(document).ready(function(){
$("article").click(function(){
alert($(this).attr('class').match(/\bclr[^\s]+\b/)[0]);
});
});
</script>
This should jquery script should do what you asked (tested on jsfiddle):
$(document).ready(function () {
function getClrClass(elem) {
var classes = elem.getAttribute('class').split(' ');
var i = 0;
var cssClass = '';
for (i = 0; i < classes.length; i += 1) {
if (classes[i].indexOf('clr') === 0) {
cssClass = classes[i];
i = classes.length; //exit for loop
}
}
return cssClass;
};
$('article').click(function (e) {
var cssClass = getClrClass($(this)[0]);
alert(cssClass);
e.preventDefault();
return false;
});
});
Hope this helps.
Pete
Use an attribute selector to get those that have class names that contain clr.
From there:
extract the class name (string functions)
analyze the position
determine the next element
The latter two might be best served by a translation array if you only had a few classes.
UPDATE
I agree with lonesomeday, you'd be far better off using data-* attribute to handle such logic. Using CSS as JavaScript hooks is a thing of the past.
http://jsfiddle.net/4KwWn/
$('article[class*=clr]').click(function() {
var token = $(this).attr('class'),
position = token.indexOf('clr');
token = token.substring(position, token.indexOf(' ', position));
alert(token);
});

Count how many UL Elements there are in a Div with Javascript?

I am dynamically adding UL elements to a DIV element. I would like to be able to count how many UL elements there are inside the DIV so that once all the ULs are removed dynamically I can delete the DIV that they are contained in.
<div id="000">
<ul id="000-1">
<li>Stuff</li>
<li>Stuff</li>
</ul>
<ul id="000-2">
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
Is there a simple Javascript solution that counts the amount of ULs so that I can do something like this.. ?
if(ulcount == 0){
var remove = document.getElementById("000");
remove.innerHTML = '';
results.parentNode.removeChild("000");
}
Thanks.
#Cheeso's answer is a good pure-JS solution. But, if you're using jQuery, the process can be made simpler.
jQuery('div#000').children('ul').length;
The above code will return the number of child ul elements of the div#000.
To update the count when you add elements dynamically, you will have to create a function and call it to update the number whenever a change occurs:
function countUls() {jQuery('div#000').children('ul').length;}
Bind that to an event so that it will be called when you want to update the number.
Code:
function getDirectChildrenByTagName(elt,tagname) {
var allChildren = elt.children, wantedChildren=[], i, L;
tagname = tagname.toUpperCase();
for(i=0, L=allChildren.length; i<L; i++) {
if (allChildren[i].tagName.toUpperCase() == tagname) {
wantedChildren.push(allChildren[i]);
}
}
return wantedChildren;
}
use it like this:
var zero = document.getElementById("000");
var uls = getDirectChildrenByTagName(zero, 'UL');
var ulCount = uls.length;
....
Try this:
var x = document.getElementById("000-1").querySelectorAll("li").length
console.log(">>>>", x);

Categories