Remove and add href from anchor - Jquery

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

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?

Thanks! This helped a lot!

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

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.

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.

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.

Thank you, that would be great!

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.

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

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

https://codepen.io/gunhoo93/pen/djoxdB?editors=1010
Note that this is just a proof of concept.
But, If you have questions let me know.

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.

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.

1 Like

You are probably right. Frankly, I barely know anything about Jquery. Also, I haven’t given too much thought or haven’t done any refactoring. So, whatever you can do to make it better will work.

Yep, it is always good to represent data as valid type. I was just relying on coercing because I didn’t see any point of it outside of being used as an index. But, yeah I should’ve done that.

Hey guys, sorry for the late reply, I wanna thank you both for all your help, I can’t thank you enough for that. Now in my free time I am going to break down the code to have a fully understanding of it. If I have any more questions (and 'Im sure I will) I’ll come back here, I hope that’s not an issue. I say this because I will have questions about other functionalities but it’s all part of the same project.

I’m a beginner but I want to build this project because it represents a big challenge, so far I am learning a lot with the help of this great community.

I think I should probably change the title to “building a shopping cart” because at the end this is what this app is all about.

Hey guys, going back to what we started I’ve been modifying and adding some more functionalities to the code you provided but now I have an issue. I created the array of objects storing the data for the html structure:

var data = [
  {
    product: "Haori Jacket",
    url: "haorijacket.html",
    image: "img/haori-jacket.jpg",
    altDesc: "Jacket",
    price: "$210.00",
    outwear: ""
  },
  {
    product: "Swing Dress",
    url: "swingdress.html",
    image: "img/swing-dress.jpg",
    altDesc: "Dress",
    price: "$218.00",
    dress: ""
  },
{
    product: "Jane Skirt",
    url: "",
    image: "img/jane-skirt.jpg",
    altDesc: "Shirt",
    price: "$150.00",
    sale: "$263.00",
    bottom: ""
  },
  {
    product: "Romy Top",
    url: "",
    image: "img/romy-top.jpg",
    altDesc: "Blouse",
    price: "$199.00",
    sale: "$300.00",
    top: ""
  }
];
....

Then following @gunhoo93 code I have the template:

function clothingView(item, index) {
  return (`
    <a href="${item.url}" class="shop-item">
    ${item.sale ? `<span class="shop-item__sale">Sale</span>`: ''}
      <img data-src=${item.image} alt="${item.altDesc}" class="shop-item__img">
      <div class="quickview">
        <span class="quickview__icon">Quick View</span>
        <span class="quickview__info">${item.product}
          <br>
          <span class="quickview__price">${item.price}
            ${item.sale ? `<span class="quickview__price--sale">${item.sale}</span>`: ''}
          </span>
        </span>
        <span class="clothing-index">${index}</span>
      </div>
    </a>
    `);
};

// Append template literal to html structure
for (var i = 0; i < data.length; ++i) {
  $('.all-items').append(clothingView(data[i], i))
}

Then I am filtering the array based on attributes:

saleData = data.filter(obj => 'sale' in obj);
  for (var i = 0; i < saleData.length; ++i) {
    $('.sale').append(clothingView(saleData[i], i))
  }

Then the popup:

function swapPopup(clothing) {
  $('#clothingImg').prop('src', clothing.image)
  $('#clothingName').text(clothing.product)
  $('#clothingPrice').text(clothing.price)
  $('#clothingSale').text(clothing.sale) // This is supposed to be only for items on sale
}

var currentPopup = 0;
$('.quickview__icon').click(function(e) {
  event.preventDefault();
  $('.overlay').css({'opacity': '1', 'visibility': 'visible'});

  currentPopup = $(e.target).parent().children('.clothing-index').text();
  swapPopup(data[currentPopup]);
});

And this is what is happening:

This item does not have the “sale” attribute, but after I click on a item that has this attribute, suddenly (on the popup window) all items have this attribute. I only want this to show on the popup when I click an item with the sale attribute.

This piece of code here is not very clear to me

function swapPopup(clothing) {
  $('#clothingImg').prop('src', clothing.image)
  $('#clothingName').text(clothing.product)
  $('#clothingPrice').text(clothing.price)
  $('#clothingSale').text(clothing.sale)
};

var currentPopup = 0;
$('.quickview__icon').click(function(e) {
  event.preventDefault();
  $('.overlay').css({'opacity': '1', 'visibility': 'visible'});

// This piece of code
  currentPopup = $(e.target).parent().children('.clothing-index').text();
  swapPopup(data[currentPopup]);
});

If can wrap my head around this that could help me solve my current problem.

currentPopup = $(e.target).parent().children('.clothing-index').text();

This is just a way to get to the clothing index. The receiver of the event is quickview__icon I just inserted the index of cloth at the end of quickview. So, to get to the index, we go from the receiver’s parent and then query for one of its children. If you put the index directly under quickview__icon, you don’t really need extra traversal.

I’ll look into the problem you mentioned but honestly,
I don’t really recommend keep putting more stuff to my dirty implementation. This will likely make matters worse whenever you try to add something. If I knew JQuery any better, I might have suggested better ways, but JQuery is not something I’m interested in. Personally, I’d build this in React and the resulting code will be much simpler to understand. But it’s up to you whether you want to learn things like React or not.

If you want to stick to JQuery, then I’d suggest you to dig more into how people generally use that technology.

The problem is likely happening because you’ve introduced branching, but swapPopup() doesn’t know about that branch.
For example, swapPopup() must choose to display or not display the sale info based on the existence of it. Clicking an item with sale will inject sale info. Next, If you click an item without sale data, the sale data simply remains because not having sale info results .text(undefined), which seems to have no effect. Try introducing a branch that states if sales info exists use it, if not override with empty text or something.

Adding that bit of code will solve the problem temporarily but, like I said earlier, it is not a good idea to push forward with the current design of the code.

Here https://codepen.io/CodingGilbert/pen/xJGvQB

The issue that I have is that after you open the popup of one of the items with the “sale” attribute (which have a discount), you will see (in the popup window) next to the price the discount of this sale attribute in other items that don’t have the attribute at all.

I’d like to include this sale attribute in the popup only when an item that has the sale attribute is clicked, I did something similar with the template literal by adding it to the template only if the object has the attribute.

edit: If I click an item without the sale attribute first, then it won’t appear in the popup and everything works as intended.