Jquery If element has class which begins with x, then don't addClass
Asked Answered
W

4

22

I'm a definite newbie, so apologies for rubbish coding! I've written the following Jquery for a practice project I set myself:

When you click on the div, it has the class "in_answerbox1" added and a cloned div is created in the answerbox with the class "answerbox_letter1" added.

Eventually there will be many divs in a grid (or cells in a table) that when you click on a particular one, it will fade out and seem to appear in the answerbox. Then when you click on the thing in the answerbox,the relevant div in the grid will reappear and the clone will be removed from the answerbox.

However, I now want the class to be added ONLY if the thing I'm clicking on is not already in the answerbox: i.e. if either the original or the clone has a class which contains "answerbox".

I wrote the following knowing it wouldn't work but that it might explain what I want better.

var n = 0;

$('#box').click(function(){

    if(!$(this).hasClass('*[class^="answerbox"]')) {

    $(this).addClass('in_answerbox' + (n+ 1) );

    $(this).clone().appendTo('#answerbox').addClass('answerbox_letter' + (n + 1));
    n = (n + 1);

}


});

Any suggestions?

Weakwilled answered 23/4, 2013 at 8:58 Comment(0)
T
43

I think the matter is in the if condition :

if(!$(this).hasClass('[class^="answerbox"]')) {

Try this :

if(!$(this).is('[class*="answerbox"]')) {
    //Finds element with no answerbox class
} else {
    //The element has already an answerbox class
}

You should take a look at toggleClass and is jquery docs.

See this live fiddle example.

Little tip : instead of n = (n + 1) you can do n++ :).

Edit :

After reading again the question, I did a full working script :

Assuming the Html is :

<div id="box">
    <p>Answer1</p>
    <p>Answer2</p>
    <p>Answer3</p>
</div>

<div id="answerbox">

</div>

jQuery :

var n = 0;

$('#box p').on('click',function(e) {
    e.preventDefault();
    if(!$(this).is('[class*="answerbox"]')) {
        n++;
        $(this).addClass('in_answerbox' + n );
        $(this).clone().appendTo('#answerbox').addClass('answerbox_letter' + n); 
    }
});

See this example here.

You should consider using data-attributes, they'll be more reliable then classes for what you're trying to do.


Note that if you want the selector to match only if the class attribute begins with a word, you'll want [class^="word"]. * however searches through the whole class attribute. Be careful though, [class^="word"] will not match <div class="test word"> see here.

Tarra answered 23/4, 2013 at 9:3 Comment(10)
This will try to find elements with the given selector below the current element in the DOM tree, not including the current element. But the OP wanted to check the current element for a given classDistinctly
Thanks for the tip! Yep, I did want it to check the current element for a given class.Weakwilled
Added a full working example after reading your question again ;).Tarra
Just had a look and this looks pretty much exactly what I was looking for: saw the working example and it does what is needed. I'll also have a look at data-attributes. Thanks for this!Weakwilled
small thing: any idea why it might be that it only works the second time you click on the div box?Weakwilled
On the example it's working on the first click to me, try to reproduce the bug in a jsfiddle I might help you more.Tarra
my bad! hadn't deleted original $('#box').click(function(){ });Weakwilled
checking existence of a class that STARTS with a "word" should be tested using: $el.is('[class^="word"], [class*=" word"]') as you might have a class named "any-word" and will test positively as it contains the keyword, but it's not starting with ...Inwrap
Clarified this with an example, just know that it's the class attribute not the class list (there could be a confusion).Tarra
if(!$(this).is('[class*="answerbox"]')) works like a charm !!! thank youCarmellacarmelle
D
5

Use .is() instead of .hasClass(). The former can be used with CSS selectors whereas the latter can only use class name as a "fixed" string.

if(!$(this).is('[class^="answerbox"]'))

NOTE: This will only work consistently if the element has exactly one class

Distinctly answered 23/4, 2013 at 9:7 Comment(4)
What did you meen by This will only work consistently if the element has exactly one class. I did a little test here, but can't understand.Tarra
If you have more than one class, the mentioned selector for .is() will work if and only if the very first class name in the list starts with answerbox. If the class name you are looking for is not the first one, the selector won't work as expectedDistinctly
Ok now I understand it, but it seems to work with the *= selector.Tarra
I think I'll need multiple classes, but in theory would this work if I changed its idea with instead of the class?Weakwilled
G
3

The other answers do not work if your element has multiple classes on the same element. You need to select it as such:

if ( $(this).is('[class^="bleh_"], [class*=" bleh_"]') ) {

    // Return true if element has class that starts with "bleh_"

    // Note: The second argument has a space before 'bleh_'

}
Gastronome answered 4/1, 2019 at 17:49 Comment(1)
Thanks for this, best answer for selection.Doane
D
2

If you need something that works for multiple class names, check this

var theClasses = $(this).attr('class').split(" ");
var i=0;
var found = false;
while(i<theClasses.length && !found) {
   if(theClasses[i].indexOf('answerbox') == 0) {   // starts with answerbox
      found = true;
   }
   i++;
}
if(!found) {
   // the current element does not have a class starting with answerbox
}
Distinctly answered 23/4, 2013 at 11:6 Comment(1)
Thanks for this, I'll have a look to see if I can get it to work!Weakwilled

© 2022 - 2024 — McMap. All rights reserved.