Remove and add href from anchor - Jquery

Remove and add href from anchor - Jquery
0.0 0

#1

I have a gallery made of anchor elements and inside these elements I have a “quickview” button, When I click this button a popup window shows up. If I dont click the button and click the item instead, then each item is supposed to take me to a different section of the website based on the href link. The problem that I am facing is that when I set a path to the href of these anchors and I click the quickview button the popup window quickly disappears and Im taken to whatever path I set in the href of the anchor element.

I would like to remove the href attribute from the anchors when I click the “quickview” button and then add it back when I close the popup window. I know I can use $("a").removeAttr("href"); to remove the href when I click the quickview button, but if I do that then when I close the popup, the anchors no longer has the href attr.

I need to add the href back with the path they originally had before removing the href, I have like 40 of these items, how can I solve this?

Note: the first 2 items have href with links to other places, if you wish to see the popup window click on one of the last 2.

Please help!

Codepen: https://codepen.io/CodingGilbert/pen/KBpbLo


Popup window prev and next button functionality
#2

You need to prevent the default action of the anchor tag from opening the href if just the quick view icon is clicked. You can modify your quickview icon click event as:

  $('.quickview__icon').click(function(event) {
    event.preventDefault();
    $('.overlay').css({'opacity': '1', 'visibility': 'visible'});
    .
    .
    .
    document.getElementById("clothingPrice").innerHTML = price;
  });

Next, remove the quickview hover pseudo class from your CSS and let jQuery take care of the hovering effects. You will need to add the following hover event for anchors:

$("a").hover(
  function() {
    $(this).find(".quickview").css({ opacity: "1" });
  },
  function() {
    $(this).find(".quickview").css({ opacity: "0" });
  }
);

I think this will fix your issues and you can now add the url back into the href attribute for each anchor element. The reason the hover pseudo class had to be removed from the CSS, is the other details such as product name and price were still showing when the icon was clicked.

Let me know if this does not resolve your issue or if I misunderstood what your ultimate goal was.


#3

Dude you are a SAVIOR! this piece of code here solved my problem event.preventDefault();

I’ve been asking on stackoverflow and nobody could give me a simple answer like this one, some even suggested to change the html structure by placing the “quickview” button out of the anchor, which was out of question to me given that I have like 40 of these items already in my html.

As for the hover effect, everything works perfectly as it is, all I wanted was to prevent the anchor from taking me to the href link path when I click the “quickview” button and event.preventDefault(); has solved the issue for me.

Thanks a lot man, I really appreciate it. One more question if you dont mind, what does event.preventDefault(); do exactly?


#4

It prevents the default action of the event from occurring. In this case, the default action of an anchor is to open a link.


#6

Thanks! This helped a lot!


#7

If I had 40 products to add/manage, then I would want to separate the products’ data from the html structure. I would do that by having a js file with just the products stored in an array of objects, with each object containing all the relevant data of a specific product. Then I would have a loop to iterate through the array and display each product on the page with a specific “template” structure for each product. The template would be used to dynamically generate the html for the 40 products, instead of you having to manually create the html for the 40 products. I took your four products and created the array like:

const products = [
  { 
    product: "Haori Jacket",
    url: "https://www.pinterest.com/pin/ASQyu4IhVADMC-1ZPfodm2IgJJD-Q2dKvL8t-bQZv-H5rfuxCX52s94/",
    image: "https://static1.squarespace.com/static/560c458be4b0af26f729d191/560c5de0e4b083d9c365515f/560d4f67e4b00b2c2a29ab00/1443712877696/lauren-winter-haori-jacket_0250.jpg?format=750w",
    altDesc: "Clothing item",
    price: 210
  },
  { 
    product: "Swing Dress",
    url: "https://www.pinterest.com/pin/449304500297815470/",
    image: "https://static1.squarespace.com/static/560c458be4b0af26f729d191/560c5de0e4b083d9c365515f/560d5226e4b0e3eb29871ecf/1443713579307/lauren-winter-swing-dress_0183.jpg?format=2500w",
    altDesc: "Clothing item",
    price: 218
  },
  { 
    product: "Haori Jacket",
    url: "https://www.pinterest.com/pin/ASQyu4IhVADMC-1ZPfodm2IgJJD-Q2dKvL8t-bQZv-H5rfuxCX52s94/",
    image: "https://static1.squarespace.com/static/560c458be4b0af26f729d191/560c5de0e4b083d9c365515f/560d4fd9e4b03b1013fd1f56/1443712996946/lauren-winter-lounge-jumpsuit-black_0284.jpg?format=750w",
    altDesc: "Clothing item",
    price: 298
  },
  { 
    product: "Swing Dress",
    url: "https://www.pinterest.com/pin/449304500297815470/",
    image: "https://static1.squarespace.com/static/560c458be4b0af26f729d191/560c5de0e4b083d9c365515f/560d542ae4b088b5adb66691/1443714094740/ulihu-blue-linen-crop-top_0320.jpg?format=750w",
    altDesc: "Clothing item",
    price: 125
  }    
]; 

The above data could be stored in a separate file and linked in to the html file before the main part of the script (the part you have already written plus the code that generates the actual product html - seen below):

// dynamically generate a string using a Template Literal via the reduce method
const productsHTML = products.reduce((html, {product, url, image, altDesc, price}) => {
  const productID = product.replace(/\s/g,'_');
  price = price.toFixed(2);
  return html += `<a href="${url}" class="shop-item">
    <img src="${image}" alt="${altDesc}" class="lazy shop-item__img" id="${productID}Img">
    <div class="quickview">
      <span class="quickview__icon" id="${productID}">Quick View</span>
      <span class="quickview__info">${product}<br><span class="quickview__info--price" id="${productID}Price">$${price}</span></span>
    </div>
  </a>`
},'');

// appends the above html to the products section
$('.products-container').append(productsHTML); 

Using the above code, the section where you manually had the products would now only contain the following:

<section class="products-container container"></section>

Everything after the above section would remain the same in your html file.


#8

I have a gallery of items for an e-commerce website, when I hover on one of these items a “quickview” button appears on it, if I click on this button a popup window shows up with a “prev” and “next” button. I’m wondering how can I make these prev and next buttons work, because the content that the popup shows is based on the item that is clicked, and every item has different content (img, price, etc). If possible I would like to make the “prev” button disappears if the popup is showing the first item and the opposite for the “next” button. Any help is greatly appreciated.

here’s a codepan example of what I currently have so far: https://codepen.io/CodingGilbert/pen/KBpbLo


#9

A simple implementation of slideshow is this.

Slideshow
    [cloth1, cloth2, cloth3, ....]
               ^current

    cloth2 -> clothView(cloth2) -> some html -> attach to appropriate place

You have a list of cloth data and a tracker for currently viewed cloth. The slideshow always display cloth where current points at. Clicking next and prev button simply moves current +1 and -1 respectively.

Given your current implementation this is very hard because all of your cloth data is hard coded in html. You can try traversing over next or previous <a> when prev and next is clicked; however, this is better than nothing as your code must rely on a fragile DOM structure.

You should refactor your current implementation so that your Javascript code renders html just like how you did with the quickview_icon. For example, you can treat your cloth view as a fixed template, and pass along cloth data so you can easily render different cloth view. From there, implementing slideshow won’t be so difficult.

You will need a list of cloth data made available in your JS code.


#10

Yes… I believe that’s why it would be difficult to implement this functionality because I hard coded the data in the html structure. I’m sure there are better ways to do this but I have no idea of how to do that. Is there any ways that you can help me with that or direct me to some example? I’m very new at this so for me to understand a concept I need to see an example.


#11

Unfortunately, that will be somewhat long journey. I can maybe simplify your current code to demonstrate the minimal idea. I’ll let you know when it happens on this thread. I’m very rusty at this as well, so it might be a good practice for me too.


#12

Thank you, that would be great!


#13

Look back at my latest response after I merged your two topics. I have shown you a way to dynamically create your products html.


#14

It definitely looks so much cleaner and way more manageable , I tested it and it works perfectly. However, now there’s one functionality that is missing, when I click the “quickview” button I should be to see in the popup window the item “product” (name), “image” and “price” based on the item that is clicked.

I have to get this information from the object that you created somehow, but as my JS knowledge is very limited, I don’t know how to do that. Maybe when you have some time you can help me with that. I’ll keep doing some research.

Thank you so much, it’s good to know that I can do this kind of thing creating objects in JS.


#15

I will leave the rest up to you or someone else who wants to continue what I started. It is very doable.


#16

Alright! Thank you very much for all your help, this will be a great practice for me.


#17

Well is this what you wanted? I’ve tried to make as few changes as possible.


Note that this is just a proof of concept.
But, If you have questions let me know.


#18

It seems that it’s working great! Thank you very much, my other question would be if you mind explaining the logic behind this code, I really want to be able to understand the whole code.


#19

Which part(s) do you not understand from the code @gunhoo93 created for you?


#20

@gunhoo93’s solution is great. I was wondering if the next and prev click events could be combined and came up with the following which could be used in place of the two separate click event handlers. At first, I did not realize the currentOverlay was a string, but once I realized that, I just used the Number function to convert it for my 3rd line calculation.

$('#overlay-prev, #overlay-next').click(function() {
  var end = data.length - 1;
  var direction = $(this).attr('id') === 'overlay-prev' ? -1 : 1;
  currentOverlay = Number(currentOverlay) + direction;
  currentOverlay = currentOverlay < 0 ? end : currentOverlay > end ? 0 : currentOverlay;
  swapOverlay( data[currentOverlay] )
});

#21

The big picture is this

  • Cloth data varies and cloth views are identical. So, extract varying cloth data to objects and make a single cloth view template.
  • Overlay view also follows the same strategy except you don’t need more than one view. So, instead of making template for it, I inject new cloth data into existing html structure whenever it varies. This is done by swapOverlay()
  • When user clicks a quick view, there must be a way to identify which cloth view to use. There are many ways to do this, but in this case, I simply inject index of each cloth data within the quickview in overlay-index node.
  • When user clicks prev, I simply subtract one from the index of currently viewed item. And, reset it if the index underflows to negative value. The behavior for next is exactly the opposite.

These are definitely not an examplary way of doing this. The clothView() is a pretty dirty way of making html template. Marking overlay-index inside html still requires unnecessary DOM traversal for picking which cloth to display. And, the whole code is still heavily coupled with html structure. But it’s probably enough for what it is meant to be.