0

I am trying to determine if an image source contains a string when I click on the image. The images have the class .swap-color. I have the variable $current_swatch set to the image src attribute, and it tests successfully. My code is below. No matter what image I click on, I get the alert "Contains TB", even if TB isn't in the image src. What am I doing wrong?

<img src="/images/Swatch-TB.jpg" class="swap-color"/>

$("document").ready(function () {
    $('.swap-color').click(function () {
        //get the image src
        var $current_swatch = $(this).attr('src');
        //check if TB is in the src
        if ($('$current_swatch:contains("TB")').length > 0 ) {
            alert ('Contains TB');
        } else {
            alert ('Does not contain TB');
        }
    });
});
jshock
  • 1,373
  • 2
  • 11
  • 17
  • Variables aren't expanded inside strings in Javascript, you should use concatenation. – Barmar Feb 11 '16 at 02:45
  • And `:contains` isn't for searching strings, it's for searching DOM elements. – Barmar Feb 11 '16 at 02:46
  • Why the downvotes? This is a perfectly reasonable, well-constructed question? – random_user_name Feb 11 '16 at 02:48
  • Some people downvote any question that indicates the poster is clueless and hasn't done any debugging on their own. Like use the JS console to see what `$('$current_swatch:contains("TB")')` returns. – Barmar Feb 11 '16 at 02:50
  • @Barmar - Well, it's nice to bump into you again here on SO, and thank you for all your hard work! Good comments, good editing. Thanks for the insight! – random_user_name Feb 11 '16 at 02:52

2 Answers2

4

There's enough feedback that I'm going to go out on a limb and post an answer, even though the key to your question could be done in a comment.

The way to check for the contents is to use the JS native indexOf(), rather than the jQuery selector method in your code.

Here's some commented revisions to your code:

// Streamlined, conflict-safe document ready
jQuery(function ($) {
    $('.swap-color').click(function() {
        //get the image src
        var $current_swatch = $(this).attr('src');
        //check if TB is in the src
        // Use JS native "indexOf" rather than jQuery 
        if ($current_swatch.indexOf('TB') > -1 ) {
            alert ('Contains TB');
        } else {
            alert ('Does not contain TB');
        }
    });
});

For more information on different ways to check for a substring, check out this answer: Fastest way to check a string contain another substring in Javascript?

Community
  • 1
  • 1
random_user_name
  • 25,694
  • 7
  • 76
  • 115
1

So, you're using the jQuery's contains method which checks if a selector contains a value. The problem is, $current_swatch is actually a string, since $(this).attr('src') will give "/images/Swatch-TB.jpg".

Instead what you want is the vanilla JS includes.

if ($current_swatch.includes('TB')) {
  ...
Barmar
  • 741,623
  • 53
  • 500
  • 612
Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128
  • Isn't includes for arrays? Not strings per-se? – random_user_name Feb 11 '16 at 02:48
  • @cale_b not at all. Array and String both have `includes` and `indexOf` as part of their prototypes. Look at the doc I linked to - it's for String. I would argue in OP's case `includes` is more clear since OP isn't looking for the index, just if the value exists. – Matthew Herbst Feb 11 '16 at 02:50
  • @cale_b to go further, if you really think about it, strings are implemented as arrays, so it makes sense that they would have many of the same methods. – Matthew Herbst Feb 11 '16 at 02:51
  • 1
    Yes, agreed on strings == arrays. And nice to learn about includes - always learning on SO. Thanks! – random_user_name Feb 11 '16 at 02:51
  • @MatthewHerbst Not really, since the array methods look for individual elements, while the string methods look for substrings. – Barmar Feb 11 '16 at 02:51
  • @MatthewHerbst And there are many other differences, like you can modify an array, you can't modify a string. – Barmar Feb 11 '16 at 02:52
  • @Barmar I didn't say all of the same - just some. But yeah, very big differences of course. Interestingly, on Chrome at least, [`indexOf` performs significantly better on large haystacks, while both methods seem equivalent on small haystacks](http://jsperf.com/string-indexof-includes) – Matthew Herbst Feb 11 '16 at 03:02
  • @MatthewHerbst Other `.length` and `[index]`, I can't think of many similarities. – Barmar Feb 11 '16 at 03:09
  • @MatthewHerbst They have some other methods with the same names, but they behave differently. – Barmar Feb 11 '16 at 03:10
  • @Barmar yeah, I'm looking at the (V8) source now. Interestingly enough, [`includes` actually just calls `indexOf`](https://chromium.googlesource.com/v8/v8/+/master/src/js/string.js#780), which makes sense. – Matthew Herbst Feb 11 '16 at 03:23
  • Of course, it's just a convenience function to handle a common idiom. No need to repeat code. – Barmar Feb 11 '16 at 03:27