jQuery: Remove and Re-Add Classes - javascript

I've searched quite a bit before asking this question, but I may be searching / asking the wrong question:
I want to select the last two classes of an element (that has multiple classes and an unknown amount of classes) and store that in a variable. I then want to remove those two classes and add them back at a later point (like toggleClass). The first class is known, while the second class is unknown.
For instance:
<div class="c1 c2 c3 c-unknown"></div>
I would like to select c3 and c-unknown
I've tried split() and it seems like the solution, but I couldn't quite get it to work.
I appreciate any help / guidance you can offer.

You could store them on the element itself allowing to isolate multiple instances
Following solution doesn't need classes to be in any specific order or matter how many classes are on element.
$('.c1').each(function () {
/* array of classes on elemnt*/
var classes = $(this).attr('class').split(' ');
/* remove the targeted selector from array */
classes.splice(classes.indexOf('c1'), 1);
/* remove the extra classes from element and store */
$(this).removeClass(classes.join(' ')).data('classes', classes);
});
For a specific element could also use attr(function)
$('.c1.Specific').attr('class', function(_, existingClasses){
var classes = existingClasses.split(' ');
classes.splice(classes.indexOf('c1', 1));
$(this).data('classes', classes);
return 'c1';
});
Then to re-use the stored classes
var $el = $('.c1:first');
$el.addClass( $el.data('classes').join(' '))
DEMO

Probably the easiest way to get the last two classes:
var lastTwoClasses = $('.c1').attr('class').split(/\s+/).slice(-2).join(' ');
Toggle (for example with button id="btn"):
$('#btn').click(function(){
$('.c1').toggleClass(lastTwoClasses);
});
JSFiddle
EDIT.
And yet another way:
$('.c1').each(function(){
var classes = $(this).attr('class').split(/\s+/).slice(-2).join(' ');
$(this).click(function(){
$(this).toggleClass(classes);
});
});
JSFiddle

I believe this is what you're trying to do.
var ele = document.getElementsByClassName('c1'),
classes = ele[0].className,
classArr = classes.split(' '),
spliceIndex = classArr.length - 2,
last2Classes = classArr.splice(spliceIndex, 2);
Here's a working fiddle
If you're trying to remove the classes you can use jquery or you could just use the dom element's className property and set it to whichever array has the classes you want to use. You would use the array method .toString() on either array and it will give you a string representation of the classes.

The answer here could help you to get part of the functionality you need:
Get first and last class with jQuery
Starting with that, you could use split, and removeClass like this
(sample text and css added for demo purposes):
function removeTheClasses(el) {
var classes = el.attr("class").split(/\s/);
var second_to_last = classes[classes.length - 2]; //second to last class
var last = classes[classes.length -1]; //last class
el.removeClass(second_to_last, last);
}
$('button').click(function() {
removeTheClasses($('.c1'));
});
.c-unknown {font-weight:bold}
.c3 {color:pink}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="c1 c2 c3 c-unknown">
ABC
</div>
<br/>
<button>Remove the last two classes</button>
In order to add these same classes back in (toggling), you'd have to keep a record of the recently removed classes. This would require:
pushing the values of the first & last variables to a cookie or web storage (if handling multiple elements at a time), OR
a single javascript variable above the scope of the 'removeTheClasses' function (if you're just handling one element at a time).

Related

i need to find one element over class search, and only add a class to the first element that shows up

I know it sounds stupid, but I'm just learning HTML and CSS and my boss hit me with a JS problem and I have no clue.
I already tried googling a ton, but all I found, I also don't understand bc lack of JS knowledge.
I need to find a Picture Element with the class .small floatfigure, the element i need would be the first one of multiple with this class to show up, and the first and only one needs the class .mgn added.
I tried stuff like this, but like i mentioned i have no f***ing clue what I'm even doing
var small floatfigure = { first: '.small floatfigure' };
small floatfigure.forEach((e)=>{
e.classList.add(".mgn");
};
______________________________________________________
var floatfigure = document.getElementsByClassName('.small floatfigure');
var floatfigure = small floatfigure.firstChild;
small floatfigure.className += 'mgn';
______________________________________________________
let aa = document.getElementsByClassName("small floatfigure");
aa.className = "small floatfigure";
aa.classList.add("mgn");
______________________________________________________
var floatfigure = document.querySelectorAll(".small floatfigure");
console.log(floatfigure);
if(!floatfigure.length==0){
floatfigure.forFirst((f)=>{
f.classList.add(".mgn");
});
};
pls pls pls help me
Use document.querySelector() to find the first occurrence of an element in the DOM. The function accepts CSS selectors to search for the element you're looking for.
Edit: Just in case that there are multiple elements with both the classes small and floatfigure, add the picture element selector to make your query more specific
const floatfigure = document.querySelector('picture.small.floatfigure');
floatfigure.classList.add('mgn');
Note that document.querySelectorAll() searches for all elements that match the query and returns an array-like object which can be iterated over.
You can stay away from document.getElementsByClassName. That function was how we used to be able to find multiple elements, but have been replaced by, the more modern, querySelector and querySelectorAll.

List of checkboxes checked for specific classes

I would like to get a list of names of which checkboxes are checked in a specific DIV (page-wrap). I am creating a filter of sorts and have a treeview of different types like color, quality, grain, etc... Each has its own class assigned to them. Color has a class of color_cb, Quality is product_cb, Grain is grain_cb. The following code works great for any one of them but I'd like to test for all 3. Is there a way to modify this for all 3.
var selected = [];
$('#page-wrap input:checkbox.color_cb:checked').each(function() {
selected.push($(this).attr('name'));
});
alert(selected.join(","));
I've tried this but it doesn't work.
var selected = [];
$('#page-wrap input:checkbox.color_cb:checked input:checkbox.product_cb:checked').each(function() {
selected.push($(this).attr('name'));
});
alert(selected.join(","));
use comma separator b/w selected element
$('#page-wrap input:checkbox.color_cb:checked ,#page-wrap input:checkbox.product_cb:checked')
^^^^-- add , seperator
or use map()
var selected = $('#page-wrap input:checkbox.color_cb:checked ,#page-wrap input:checkbox.product_cb:checked').map(function () {
return $(this).attr('name');
}).get();
'#page-wrap input:checkbox.color_cb:checked input:checkbox.product_cb:checked'
this query selector means that input:checkbox.product_cb:checked is child of input:checkbox.color_cb:checked
But, i think you are looking for elements that accomplish one OR the other query, for that you have to use a comma separator, like this:
'#page-wrap input:checkbox.color_cb:checked, #page-wrap input:checkbox.product_cb:checked'
Simply removing the class should work fine.
var selected = [];
$('#page-wrap input:checkbox:checked').each(function() {
selected.push($(this).attr('name'));
});
alert(selected.join(","));
http://jsfiddle.net/60hnvnh9/1/
If there are checkboxes that you want to avoid targeting, simply give the checkboxes another, common class, and target that.

How to get jquery selector seeing updated dom in change handler

I'm fairly new to javascript and jQuery. I've searched for answers to this question, but have had no luck, though I bet there are some in here. So advance apologies if this is a dup.
Markup has 3 checkboxes with different classes, and one class in common. I want to notice when the number of boxes checked in either of two classes changes, or rather when there is a transition between at least one box in two of the classes being checked or unchecked. The two interesting classes are named "professional" and "vendor", and the class in common is "account_type_checkbox".
When the page is ready, I count the number of checked "professional" and "vendor" boxes with:
jQuery("input.professional[checked='checked'], input.vendor[checked='checked']").length
This appears to work correctly. I have a "change" event handler on checkboxes in the common class that does the same count when it triggers. But when the event triggers, it gets the same count as it did on page load - i.e. it doesn't see the updated DOM with the modified checked attribute.
I've put a jsfiddle for this at http://jsfiddle.net/cm280s9z/1
Could someone please help me fix this, and/or explain why my code doesn't work the way I expected it to?
http://jsfiddle.net/cm280s9z/3/
Use alert($(":checkbox:checked").length); to get the sum of all marked checkboxes.
There are several other ways of doing this too, as pointed out in this thread, such as doing it by classes on a checkbox:
calculate the number of html checkbox checked using jquery
Maybe you will find this useful: http://jsfiddle.net/cm280s9z/6/
Here's a cleaned up version (not saying it's the best ever) of what you had, showing the :checked.
Reasons why this code is good:
storing the jQuery object checkboxes means it won't have to re-jquery-objectify it every time.
grabbing objects by certain [vague or lengthy] selectors can be more strenuous on jQuery. Grabbing by this class means it'll be more specific as well. We can further filter out checked using .filter. Extra Tip: If traversing the DOM, I like to grab a container that's fairly unique and use .find() to help me get at the descendants.
functions can bring some order and organization to what you're doing.
comments are your friend.
Hope this helps!
var GLOB = GLOB || {};
jQuery(document).ready(function () {
// Define
var checkboxes = jQuery('.account_type_checkbox');
var get_checkbox_count = function(checkboxes){
return checkboxes.filter(':checked').length;
};
var do_business = function(){
alert('transitioned to business');
};
var do_personal = function(){
alert('transitioned to personal');
};
// Initialize
GLOB.business_count = get_checkbox_count(checkboxes);
alert('GLOB.business_count = ' + GLOB.business_count);
// Events
checkboxes.change(function(){
var cur_count = get_checkbox_count(checkboxes);
var add_business = (cur_count > 0);
var no_business = (GLOB.business_count < 1);
// If any are selected it's business, where previously none were checked.
var transition_business = (add_business && no_business);
// If none are selected it's personal, if previously any were checked.
var transition_personal = (!add_business && !no_business)
if (transition_business)
do_business();
if (transition_personal)
do_personal();
});
});

Performing the same operation on multiple selectors, elegantly?

On the project I'm working on, I've been writing a little JavaScript object. One of its behaviors involve removing any children in a series of classes, as such:
function Foo () {
var $a = $('.a'),
$b = $('.b'),
// ...etc...
$n = $('.n');
$a.remove();
$b.remove();
// ...etc again...
$n.remove();
}
While there are some ways to revise this to be more easily maintainable (putting the selectors into a single array springs instantly to mind), I'm wondering if there's any elegant way to perform the .remove() operation on a series of selectors, as such:
function FooPrime() {
var selectors = [
'.a',
'.b',
// ...
'.n'
];
// Perform remove on all given selectors?
$(selectors).remove();
}
Thus, Question: What are some ways I could perform a single jQuery operation on a number of selectors?
EDIT: here is a JSFiddle to show a cut-down version of the problem context.
You can separate the selectors with commas:
$(selectors.join(',')).remove();
The comma has that purpose in straight ordinary CSS selector syntax.
Thanks for showing your DOM, you should avoid making big lists of classes to select when you can add multiple classes to elements and create a specific class for the elements you want to target... or target via association to other elements. This would be a more clean and efficient way to do it.
By association
Basically for the selector I just have this:
$("#test-callout").find("div").not(".callout-main").remove();
Fiddle
This assumes that you do not have any other div's besides .callout-main and the target div in test-callout. If you do you can modify the selector chain a bit to compensate.
By adding another class
Your arrow creation code was like this:
function calculateArrow() {
var arrowClass;
if(pub.isLeft) {
arrowClass = 'callout-arrow-left';
} else {
arrowClass = 'callout-arrow-right';
}
pub.$callout.append('<div class="' + arrowClass + '"></div>');
}
Modify it to be like this:
function calculateArrow() {
$arrow = $("<div>")
.addClass("callout-arrow")
.addClass(pub.isLeft ? "callout-arrow-left" : "callout-arrow-right");
pub.$callout.append($arrow);
}
Then your selector can be simply:
$("#test-callout").find(".callout-arrow").remove();
Fiddle
If you are interested in a complete refactor - I reduced your CalloutObject from 53 to 17 lines and it still works the same.
Fiddle

How to find a specific class name of element when there are multiple classes?

I have some DIVs on a page. Each has 3 classes: grid_#, push_# and pull_# where # is an actual number.
I need to replace each class separately, i.e. remove class='grid_1' and replace it with class='grid_14'.
I'm using a select list to choose the new class. I need the name of the old class so I can remove it.
Through trial and error, I've found that as long as an element has only one class, I can get it using
var old = document.getElementById('elementId');
var old_class = old.className;
When I try to get the class name from a DIV with multiple classes, I get nothing. Not undefined, not object, just blank. I've tried var old_class = old.className[0]; among other things, but that gives me undefined.
The current plan is to use regex to match the old class name to a list of possible classes, giving me a var with the class name to be removed. Being new to javascript I'm sure there is a better way to do it. Any suggestions are more than welcome.
I've just begun this project, but you can find it here if it would help.
Thanks,
Mark
EDIT: Changed title of question
If element has multiple classes, you need to use split:
var old = document.getElementById('elementId');
var old_class = old.className.split(' ')[0]; // first class
What split does is that it creates an array by splitting string (class in this case) which you can later access by its index eg [0] for first class.
If element has just one class, you simply use className:
var cls = old.className;

Categories

Resources