简体   繁体   中英

Setting href via jquery click event only fires once

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.

$(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 eg using only $(this).parent().find('a').attr('href', link);

ps 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--> 

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 href s 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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM