0

I have jQuery that changes the href attribute of an <a> tag, but it only runs once

This is what I have:

JS:

$('.swatch span').click(function(e) {
      e.preventDefault();
      var link = $(this).parents().attr("href");
      if($(this).data("image").indexOf("no-image") == -1) {
        $(this).parents('.thumbnail').find('img').attr('src', $(this).data("image"));
        $(this).parents('.thumbnail').find('img').attr('srcset', $(this).data("image"));
      }
      $(this).parents('.thumbnail').find('a').attr('href', link);
    });

I found this answer and tried below:

$('.swatch span').on('click', function(e) {
      e.preventDefault();
      var link = $(this).parents().attr("href");
      if($(this).data("image").indexOf("no-image") == -1) {
        $(this).parents('.thumbnail').find('img').attr('src', $(this).data("image"));
        $(this).parents('.thumbnail').find('img').attr('srcset', $(this).data("image"));
      }
      $(this).parents('.thumbnail').find('a').attr('href', link);
    });

HTML/Markup:

<div class="one-third column alpha thumbnail even" itemprop="itemListElement" itemscope="" itemtype="http://schema.org/Product">
<!-- the link below needs to change -->
  <a href="/collections/polarized/products/product" itemprop="url">
    <div class="relative product--product collection--443303820 product_image">
      <img src="//cdn.shopify.com/s/files/1/2321/4605/products/013_a-_g__72_380x@2x.jpg?v=1504208271" class="transition-in lazyloaded">

 <div class="collection_swatches">         
    <a href="/collections/polarized/products/product?variant=44459262348" class="swatch">
      <span data-image="//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_g__72_480x.jpg?v=1504208271" style="background-color: ; background-image: url(//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_g__72_480x.jpg?v=1504208271); background-position: center; background-size: contain"></span>
    </a>

    <a href="/collections/polarized/products/product?variant=44459262476" class="swatch">
      <span data-image="//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_b__72_480x.jpg?v=1504208271" style="background-color: ; background-image: url(//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_b__72_480x.jpg?v=1504208271); background-position: center; background-size: contain"></span>
    </a>

    <a href="/collections/polarized/products/product?variant=44459262668" class="swatch">
      <span data-image="//cdn.shopify.com/s/files/7/2221/2305/products/_a-_g__72_480x.jpg?v=1504208271" style="background-color: ; background-image: url(//cdn.shopify.com/s/files/7/2221/2305/products/store_003_a-_g__72_480x.jpg?v=1504208271); background-position: center; background-size: contain"></span>
    </a>
</div>

Doesn't work.

putting in console.log('clicked') returns clicked on every click.

  1. why is my click event firing only once in both instances?
  2. Does it have to do with the .attr() behavior? I checked documentation but don't see anything that suggests that it only fires once.
kawnah
  • 3,204
  • 8
  • 53
  • 103
  • Can you show your html? I don't think it only run once but rather everytime it runs it execute the exact same thing so you dont "feel" it's running. Have you tried `console.log('clicked')` to check? – yqlim Nov 07 '17 at 01:16
  • Updated anaswer. – kawnah Nov 07 '17 at 01:20
  • Also it's not an issue with the click event `console.log('clicked')` returns `clicked` in my console every click. – kawnah Nov 07 '17 at 01:22
  • This code is wack. What are you trying to achieve? – StackSlave Nov 07 '17 at 01:47
  • @PHPglue I'm trying to change an attribute of a href with the link in the swatches using `.attr()` but it only fires once and I don't why. Also calling this "wack" isn't really productive for anyone involved I'm trying to work with an exisiting codebase and this is a part of it. – kawnah Nov 07 '17 at 01:52
  • @kawnah, since you have updated the HTML code in your answer, it is becoming more clear about what you want exactly to achieve, however, since you have not provided the location of closure tags of new HTML elements it is still ambiguous where to look for the elements, however try to inspect UPDATED answer – Roman Habibi Nov 07 '17 at 10:01

2 Answers2

1

$(this).parents('.thumbnail').find('a').attr('href', link);

will not lead to the link in html, since you do not have any thumbnail class in your html parents which are related to this, since this is a span you have clicked on, or you need to add some elements with class thumbnail,

or try

$(this).parents().find('a').attr('href', link);

to get link you have clicked on use parent() instead of parents():

var link = $(this).parent().attr("href");

when you add link to parents() that means that you changing all hrefs of all a elements, so when you click next time on any link, it will be always the one you have clicked first, so you need to specify where to apply clicked link exactly e.g. using only $(this).parent().find('a').attr('href', link);

p.s. in style setting background: ; is not the best thing to do, if you do not use one, just delete the rule ore use background: none;

UPDATE: now once you have updated the html, it is possible to see where .thumbnail element is located, however your new html elements in the answer are not closed, so I have guessed in order to make proper html code: see snipped below:

$('.swatch span').on('click', function(e) {
          e.preventDefault();
          var link = $(this).parent().attr("href");
          if($(this).data("image").indexOf("no-image") == -1) {
            $(this).parents('.thumbnail').first().find('img').first().attr('src', $(this).data("image"));
            $(this).parents('.thumbnail').first().find('img').first().attr('srcset', $(this).data("image"));
          }
console.log(link);
        // update all a hrefs of all .thumbnail parents:
        //  $(this).parents().find('.thumbnail').find('a')[0]).attr('href', link);
          // update only the first a href of all .thumbnail parents
          $(this).parents('.thumbnail').first().find('a').first().attr('href', link);
        });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="one-third column alpha thumbnail even" itemprop="itemListElement" itemscope="" itemtype="http://schema.org/Product">
<!-- the link below needs to change -->
  <a href="/collections/polarized/products/product" itemprop="url">
    <div class="relative product--product collection--443303820 product_image">
      <img src="//cdn.shopify.com/s/files/1/2321/4605/products/013_a-_g__72_380x@2x.jpg?v=1504208271" class="transition-in lazyloaded">
    </div>
  </a>

 <div class="collection_swatches">         
    <a href="/collections/polarized/products/product?variant=44459262348" class="swatch">
      <span data-image="//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_g__72_480x.jpg?v=1504208271" style="background-color: ; background-image: url(//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_g__72_480x.jpg?v=1504208271); background-position: center; background-size: contain">link1</span>
    </a>

    <a href="/collections/polarized/products/product?variant=44459262476" class="swatch">
      <span data-image="//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_b__72_480x.jpg?v=1504208271" style="background-color: ; background-image: url(//cdn.shopify.com/s/files/7/2221/2305/products/store_013_a-_b__72_480x.jpg?v=1504208271); background-position: center; background-size: contain">link2</span>
    </a>

    <a href="/collections/polarized/products/product?variant=44459262668" class="swatch">
      <span data-image="//cdn.shopify.com/s/files/7/2221/2305/products/_a-_g__72_480x.jpg?v=1504208271" style="background-color: ; background-image: url(//cdn.shopify.com/s/files/7/2221/2305/products/store_003_a-_g__72_480x.jpg?v=1504208271); background-position: center; background-size: contain">link3</span>
    </a>
 </div>

</div> <!-- .thumnail div closed here-->
Roman Habibi
  • 604
  • 5
  • 8
  • It still has same behavior - it works *once* but then if I click on another swatch, it doesn't update. – kawnah Nov 07 '17 at 01:28
  • @kawnah, since you have updated the code in your html, it is becoming more clear about what you want exactly to achieve, however, since you have not provided the location of closure tags of new html elements it is still ambiguous where to look for the elements, I have tryied to guess: play the snipped and inspect it to see if it is what you want to achieve, or provide the correct location of closure tags – Roman Habibi Nov 07 '17 at 10:00
0

although you did not include where parents('.thumbnail') is located in the HTML markup, I still can guess what happen in your code.

what really happen is like this:

<div class="collection_swatches">         
    <a href="some-link-1" class="swatch">
        <span data-image="some-img-1" style="some-bg-img-css-1"></span>
    </a>

    <a href="some-link-2" class="swatch">
        <span data-image="some-img-2" style="some-bg-img-css-2"></span>
    </a>

    <a href="some-link-3" class="swatch">
        <span data-image="some-img-3" style="some-bg-img-css-3"></span>
    </a>
</div>

when I click on the first span, var link = $(this).parent().attr("href"); will result as var link = 'some-link-1'

next you check if the span has image on it, if it has, change the image on some .thumbnail container somewhere in the markup:

if($(this).data("image").indexOf("no-image") == -1) {
    $(this).parents('.thumbnail').find('img').attr('src', $(this).data("image"));
    $(this).parents('.thumbnail').find('img').attr('srcset', $(this).data("image"));
}

and then you change the link of an <a> in that container, which is does not mean the same <a> with the var link one

$(this).parents('.thumbnail').find('a').attr('href', link);

and you repeat that every click, therefore the call of var link = $(this).parent().attr("href"); will result in the same link over and over, in this case it will result 'some-link-1' all the time.

so what happen is that the click is triggered correctly, that is replacing a href of a link somewhere in your markup with the href of your parent <a>, and the replacement value is always the same.

TLDR: the logic of your code does not match with what you want it to be

EDIT:

okay, after your update, this confirms some points in Roman Habibi's answer, that is you changed the entire <a>'s hrefs below the .thumbnail container, as shown in your markup, the collection spans's parents are located under .thumbnail container.

you can fix it by using .first() -- as the link you want to change is only the first one -- like this:

$(this).parents('.thumbnail').find('a').first().attr('href', link);

or using css selector:

$(this).parents('.thumbnail').find('a:first-of-type').attr('href', link);
am05mhz
  • 2,727
  • 2
  • 23
  • 37
  • I updated my question with markup, but this is a good step in the right direction I think. Although I thought using `this` on every click would replace the `href` attribute everytime, so I'm still a little confused there – kawnah Nov 07 '17 at 02:21
  • I don't understand...why would it be the same everytime? when I console log `link` on every click it logs the correct link everytime? – kawnah Nov 07 '17 at 02:26
  • what I meant is that when you click on the 1st `span` it will result `some-link-1` all the time, and the 2nd `span` would result `some-link-2` all the time, after your update I think I am getting of what you want to do, I'll try to re-analyze it. – am05mhz Nov 07 '17 at 02:30
  • Sort of...link updates nicely now, but image doesn't update – kawnah Nov 08 '17 at 01:00
  • I COMPLETELY changed how I was going about this and it works now. I'm using `data-link` in the `` tag and grabbing that which is working well. – kawnah Nov 08 '17 at 01:46