How can I replace a class with another using jQuery? - javascript

What jquery can I use to change the class that's used in the following from indent_1 to indent_2 or indent_4 to indent_2? I know about remove class but how can I do that when the classes are names that vary?
<div class="rep_td0 indent_1" id="title_1">Menu two</div>
or
<div class="rep_td0 indent_4" id="title_1">Menu two</div>

Since you haven't been very specific about exactly what class you want to change to another and you've said you want to deal with the case where you don't know exactly what the class is, here are some ideas:
You can find all objects that have a class that starts with "indent_" with this selector:
$('[className^="indent_"]')
If you wanted to examine the class on each one of those objects, you could iterate over that jQuery object with .each() and decide what to do with each object or you could use removeClass() with a custom function and examine the class name and decide what to do with it.
If you just wanted to change all indent class names to indent_2, then you could use this:
$('[className^="indent_"]').removeClass("indent_1 indent_3 indent_4").addClass("indent_2");
or, using a custom function that can examine the class name with a regex:
$('[className^="indent_"]').removeClass(function(index, name) {
var match = name.match(/\bindent_\d+\b/);
if (match) {
return(match[0]);
} else {
return("");
}
}).addClass("indent_2");
Or, if all you want to do is find the object with id="title_1" and fix it's classname, you can do so like this:
var o = document.getElementById("title_1");
o.className = o.className.replace(/\bindent_\d+\b/, "indent_2");
You can see this last one work here: http://jsfiddle.net/jfriend00/tF8Lw/
If you're trying to make this into a function that could take different numbers, you could use this:
function changeIndentClass(id, indentNum) {
var item = document.getElementById(id);
item.className = item.className(/\bindent_\d+\b/, "indent_" + indentNum);
}

try this code,
$("#title_1").removeClass("indent_1").addClass("indent_2");
if you not sure which is available, try this
$("#title_1").removeClass("indent_1").removeClass("indent_4").addClass("indent_2");
Updated:
$("#title_1").removeClass(function() {
var match = $(this).attr('class').match(/\bindent_\d+\b/);
if (match) {
return (match[0]);
} else {
return ("");
}
}).addClass("indent_2");

Try below :
$('#title_1').removeClass('indent_1').addClass('indent_2');
Here, the indent_1 classes will be replaced with indent_2.

Maybe this?: Remove all classes that begin with a certain string
That answers how to replace a classname on a jQuery element that has a specific prefix, such as 'indent_'.
While that answer doesn't specifically address replacement, you can achieve that by altering one of their answers slightly:
$("selector").className = $("selector").className.replace(/\bindent.*?\b/g, 'indent_2');
Or similar...

First things first...If you have multiple elements on your page with the exact same ID you're going to have problems selecting them by ID. Some browsers won't work at all while others may return just the first element that matches.
So you'll have to clean up the ID thing first.
You can use the starts with selector to find all the classes that match your class name patter and then decide if you want to switch them or not:
$('[class^="indent_"]').each(function() {
var me = $(this);
if(me.hasClass("indent_1").removeClass("indent_1").addClass("indent_2");
});

Related

How to apply range of values to a partial attribute selector? [duplicate]

I am after documentation on using wildcard or regular expressions (not sure on the exact terminology) with a jQuery selector.
I have looked for this myself but have been unable to find information on the syntax and how to use it. Does anyone know where the documentation for the syntax is?
EDIT: The attribute filters allow you to select based on patterns of an attribute value.
You can use the filter function to apply more complicated regex matching.
Here's an example which would just match the first three divs:
$('div')
.filter(function() {
return this.id.match(/abc+d/);
})
.html("Matched!");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="abcd">Not matched</div>
<div id="abccd">Not matched</div>
<div id="abcccd">Not matched</div>
<div id="abd">Not matched</div>
James Padolsey created a wonderful filter that allows regex to be used for selection.
Say you have the following div:
<div class="asdf">
Padolsey's :regex filter can select it like so:
$("div:regex(class, .*sd.*)")
Also, check the official documentation on selectors.
UPDATE: : syntax Deprecation JQuery 3.0
Since jQuery.expr[':'] used in Padolsey's implementation is already deprecated and will render a syntax error in the latest version of jQuery, here is his code adapted to jQuery 3+ syntax:
jQuery.expr.pseudos.regex = jQuery.expr.createPseudo(function (expression) {
return function (elem) {
var matchParams = expression.split(','),
validLabels = /^(data|css):/,
attr = {
method: matchParams[0].match(validLabels) ?
matchParams[0].split(':')[0] : 'attr',
property: matchParams.shift().replace(validLabels, '')
},
regexFlags = 'ig',
regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g, ''), regexFlags);
return regex.test(jQuery(elem)[attr.method](attr.property));
}
});
These can be helpful.
If you're finding by Contains then it'll be like this
$("input[id*='DiscountType']").each(function (i, el) {
//It'll be an array of elements
});
If you're finding by Starts With then it'll be like this
$("input[id^='DiscountType']").each(function (i, el) {
//It'll be an array of elements
});
If you're finding by Ends With then it'll be like this
$("input[id$='DiscountType']").each(function (i, el) {
//It'll be an array of elements
});
If you want to select elements which id is not a given string
$("input[id!='DiscountType']").each(function (i, el) {
//It'll be an array of elements
});
If you want to select elements which name contains a given word, delimited by spaces
$("input[name~='DiscountType']").each(function (i, el) {
//It'll be an array of elements
});
If you want to select elements which id is equal to a given string or starting with that string followed by a hyphen
$("input[id|='DiscountType']").each(function (i, el) {
//It'll be an array of elements
});
If your use of regular expression is limited to test if an attribut start with a certain string, you can use the ^ JQuery selector.
For example if your want to only select div with id starting with "abc", you can use:
$("div[id^='abc']")
A lot of very useful selectors to avoid use of regex can be find here: http://api.jquery.com/category/selectors/attribute-selectors/
var test = $('#id').attr('value').match(/[^a-z0-9 ]+/);
Here you go!
Add a jQuery function,
(function($){
$.fn.regex = function(pattern, fn, fn_a){
var fn = fn || $.fn.text;
return this.filter(function() {
return pattern.test(fn.apply($(this), fn_a));
});
};
})(jQuery);
Then,
$('span').regex(/Sent/)
will select all span elements with text matches /Sent/.
$('span').regex(/tooltip.year/, $.fn.attr, ['class'])
will select all span elements with their classes match /tooltip.year/.
ids and classes are still attributes, so you can apply a regexp attribute filter to them if you select accordingly. Read more here:
http://rosshawkins.net/archive/2011/10/14/jquery-wildcard-selectors-some-simple-examples.aspx
$("input[name='option[colour]'] :checked ")
I'm just giving my real time example:
In native javascript I used following snippet to find the elements with ids starts with "select2-qownerName_select-result".
document.querySelectorAll("[id^='select2-qownerName_select-result']");
When we shifted from javascript to jQuery we've replaced above snippet with the following which involves less code changes without disturbing the logic.
$("[id^='select2-qownerName_select-result']")
If you just want to select elements that contain given string then you can use following selector:
$(':contains("search string")')

Extract last part of ID using regex or javascript

I have a component with an ID that is composed of a first static part and a second dynamic value, like this:
<div id="smallPlacardone">
Where: smallPlacard is static and one is passed using a variable.
Later in my code I want to use the dynamic part of the ID, namely one, but not the first static part smallPlacard, like this:
var clicked = $(this).parent().attr("id");
$("#right"+clicked+"").show();
What's the best way of doing it?
If "smallPlacard" is static, then you can just remove it using the replace method:
var clicked = $(this).parent().attr("id").replace(/smallPlacard/, '');
$("#right" + clicked).show();
I recommend working with delimiter chars and split(). It's easier to read and avoids the regex entirely:
<div id="smallPlacard_one">
and
var clicked = $(this).parent().attr("id").split("_")[1];
$("#right_" + clicked).show();
Alternatively something like this, which is more flexible because it does not rely on hidden conventions:
<div id="smallPlacard_one" data-show="#right_one">
and
var selector = $(this).data("show")
$(selector).show();

Select tags that starts with "x-" in jQuery

How can I select nodes that begin with a "x-" tag name, here is an hierarchy DOM tree example:
<div>
<x-tab>
<div></div>
<div>
<x-map></x-map>
</div>
</x-tab>
</div>
<x-footer></x-footer>
jQuery does not allow me to query $('x-*'), is there any way that I could achieve this?
The below is just working fine. Though I am not sure about performance as I am using regex.
$('body *').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
Working fiddle
PS: In above sample, I am considering body tag as parent element.
UPDATE :
After checking Mohamed Meligy's post, It seems regex is faster than string manipulation in this condition. and It could become more faster (or same) if we use find. Something like this:
$('body').find('*').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
UPDATE 2:
If you want to search in document then you can do the below which is fastest:
$(Array.prototype.slice.call(document.all)).filter(function () {
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
There is no native way to do this, it has worst performance, so, just do it yourself.
Example:
var results = $("div").find("*").filter(function(){
return /^x\-/i.test(this.nodeName);
});
Full example:
http://jsfiddle.net/6b8YY/3/
Notes: (Updated, see comments)
If you are wondering why I use this way for checking tag name, see:
JavaScript: case-insensitive search
and see comments as well.
Also, if you are wondering about the find method instead of adding to selector, since selectors are matched from right not from left, it may be better to separate the selector. I could also do this:
$("*", $("div")). Preferably though instead of just div add an ID or something to it so that parent match is quick.
In the comments you'll find a proof that it's not faster. This applies to very simple documents though I believe, where the cost of creating a jQuery object is higher than the cost of searching all DOM elements. In realistic page sizes though this will not be the case.
Update:
I also really like Teifi's answer. You can do it in one place and then reuse it everywhere. For example, let me mix my way with his:
// In some shared libraries location:
$.extend($.expr[':'], {
x : function(e) {
return /^x\-/i.test(this.nodeName);
}
});
// Then you can use it like:
$(function(){
// One way
var results = $("div").find(":x");
// But even nicer, you can mix with other selectors
// Say you want to get <a> tags directly inside x-* tags inside <section>
var anchors = $("section :x > a");
// Another example to show the power, say using a class name with it:
var highlightedResults = $(":x.highlight");
// Note I made the CSS class right most to be matched first for speed
});
It's the same performance hit, but more convenient API.
It might not be efficient, but consider it as a last option if you do not get any answer.
Try adding a custom attribute to these tags. What i mean is when you add a tag for eg. <x-tag>, add a custom attribute with it and assign it the same value as the tag, so the html looks like <x-tag CustAttr="x-tag">.
Now to get tags starting with x-, you can use the following jQuery code:
$("[CustAttr^=x-]")
and you will get all the tags that start with x-
custom jquery selector
jQuery(function($) {
$.extend($.expr[':'], {
X : function(e) {
return /^x-/i.test(e.tagName);
}
});
});
than, use $(":X") or $("*:X") to select your nodes.
Although this does not answer the question directly it could provide a solution, by "defining" the tags in the selector you can get all of that type?
$('x-tab, x-map, x-footer')
Workaround: if you want this thing more than once, it might be a lot more efficient to add a class based on the tag - which you only do once at the beginning, and then you filter for the tag the trivial way.
What I mean is,
function addTagMarks() {
// call when the document is ready, or when you have new tags
var prefix = "tag--"; // choose a prefix that avoids collision
var newbies = $("*").not("[class^='"+prefix+"']"); // skip what's done already
newbies.each(function() {
var tagName = $(this).prop("tagName").toLowerCase();
$(this).addClass(prefix + tagName);
});
}
After this, you can do a $("[class^='tag--x-']") or the same thing with querySelectorAll and it will be reasonably fast.
See if this works!
function getXNodes() {
var regex = /x-/, i = 0, totalnodes = [];
while (i !== document.all.length) {
if (regex.test(document.all[i].nodeName)) {
totalnodes.push(document.all[i]);
}
i++;
}
return totalnodes;
}
Demo Fiddle
var i=0;
for(i=0; i< document.all.length; i++){
if(document.all[i].nodeName.toLowerCase().indexOf('x-') !== -1){
$(document.all[i].nodeName.toLowerCase()).addClass('test');
}
}
Try this
var test = $('[x-]');
if(test)
alert('eureka!');
Basically jQuery selector works like CSS selector.
Read jQuery selector API here.

How to use jquery to get one of the class name attribute of an html element which has multiple class names assigned [duplicate]

This question already has answers here:
jQuery - get the first class only from a element
(3 answers)
Closed 9 years ago.
For example:
<div class="home current">home</div>
When I use $(this).attr("class"), it simply returns "home current".
I want to get the "home" attribute only. How can I achieve this?
If you know the class name and want to check if an element has it, you can use .hasClass()
// will return true if the element has that class applied to it
$(elem).hasClass('home');
On the other hand, if you want each class applied to an element separately, you can split by space and iterate:
var classes = $(elem).attr('class').split(' ');
for(var i=0; i<classes.length; i++) {
classes[i]; // each class name
}
The class attribute returns the space delimitered list of css classes assigned to the element, to convert this into an array use the split method on the string, and to retrieve the first one, use the [0] indexer, as in:
var firstClass = $(this).attr('class').split(' ')[0]
var allClass= $(this).attr("class");
var class = allClass.replace("current", "");
this will work if you only have "current" as an additional class
Is there a specific reason that you need to pull the class list. If you know the class you are looking for and just need to check if the object has the class home, you could do this:
$(this).hasClass("home");
Otherwise, you could just split the result and check for whatever class you need.
var classAttr = $(this).attr("class");
var classes = classAttr.split(" ");
It seems you need the primary class of the element.
var primaryClass= $(this).attr('class').split(' ')[0].
Remember this line may cause exception if no class applied,while the time you using it.

How can I remove all CSS classes using jQuery/JavaScript?

Instead of individually calling $("#item").removeClass() for every single class an element might have, is there a single function which can be called which removes all CSS classes from the given element?
Both jQuery and raw JavaScript will work.
$("#item").removeClass();
Calling removeClass with no parameters will remove all of the item's classes.
You can also use (but it is not necessarily recommended. The correct way is the one above):
$("#item").removeAttr('class');
$("#item").attr('class', '');
$('#item')[0].className = '';
If you didn't have jQuery, then this would be pretty much your only option:
document.getElementById('item').className = '';
Hang on, doesn't removeClass() default to removing all classes if nothing specific is specified? So
$("#item").removeClass();
will do it on its own...
Just set the className attribute of the real DOM element to '' (nothing).
$('#item')[0].className = ''; // the real DOM element is at [0]
Other people have said that just calling removeClass works - I tested this with the Google jQuery Playground: http://savedbythegoog.appspot.com/?id=ag5zYXZlZGJ5dGhlZ29vZ3ISCxIJU2F2ZWRDb2RlGIS61gEM ... and it works. So you can also do it this way:
$("#item").removeClass();
Of course.
$('#item')[0].className = '';
// or
document.getElementById('item').className = '';
Remove specific classes:
$('.class').removeClass('class');
Say if element has class="class another-class".
The shortest method
$('#item').removeAttr('class').attr('class', '');
You can just try:
$(document).ready(function() {
$('body').find('#item').removeClass();
});
If you have to access that element without a class name, for example you have to add a new class name, you can do this:
$(document).ready(function() {
$('body').find('#item').removeClass().addClass('class-name');
});
I use that function in my project to remove and add classes in an HTML builder.
I like using native JavaScript to do this, believe it or not!
solution 1: className
Remove all class of all items
const items = document.querySelectorAll('item');
for (let i = 0; i < items.length; i++) {
items[i].className = '';
}
Only remove all class of the first item
const item1 = document.querySelector('item');
item1.className = '';
solution 2: classList
// remove all class of all items
const items = [...document.querySelectorAll('.item')];
for (const item of items) {
item.classList.value = '';
}
// remove all class of the first item
const items = [...document.querySelectorAll('.item')];
for (const [i, item] of items.entries()) {
if(i === 0) {
item.classList.value = '';
}
}
// or
const item = document.querySelector('.item');
item.classList.value = '';
jQuery ways (not recommended)
$("#item").removeClass();
$("#item").removeClass("class1 ... classn");
refs
https://developer.mozilla.org/en-US/docs/Web/API/Element/className
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
$('#elm').removeAttr('class');
Attribute "class" will no longer be present in "elm".
Since not all versions of jQuery are created equal, you may run into the same issue I did, which means calling $("#item").removeClass(); does not actually remove the class (probably a bug).
A more reliable method is to simply use raw JavaScript and remove the class attribute altogether.
document.getElementById("item").removeAttribute("class");
Let's use this example. Maybe you want the user of your website to know a field is valid or it needs attention by changing the background color of the field. If the user hits reset then your code should only reset the fields that have data and not bother to loop through every other field on your page.
This jQuery filter will remove the class "highlightCriteria" only for
the input or select fields that have this class.
$form.find('input,select').filter(function () {
if((!!this.value) && (!!this.name)) {
$("#"+this.id).removeClass("highlightCriteria");
}
});
Try with removeClass.
For instance:
var nameClass=document.getElementsByClassName("clase1");
console.log("after", nameClass[0]);
$(".clase1").removeClass();
var nameClass=document.getElementsByClassName("clase1");
console.log("before", nameClass[0]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clase1">I am a Div with class="clase1"</div>
I had a similar issue. In my case, on disabled elements was applied that aspNetDisabled class and all disabled controls had wrong colors. So, I used jQuery to remove this class on every element/control I want and everything works and looks great now.
This is my code for removing aspNetDisabled class:
$(document).ready(function () {
$("span").removeClass("aspNetDisabled");
$("select").removeClass("aspNetDisabled");
$("input").removeClass("aspNetDisabled");
});

Categories