How to get data value of a div that has no ID? - javascript

Below is part of some code on an html page that lists shopping cart products. Using JavaScript/jQuery, I need to be able to loop through the li items and get the div "data-" values for each. The issue that I am having is that there are no IDs for the div that has the data- value (). I only see the div for "CategoryContent".
<div class="Block CategoryContent Moveable Panel" id="CategoryContent">
<ul class="ProductList ">
<li class="Odd">
<div class="ProductImage QuickView" data-product="577">
<img src="http://cdn3.example.com/products/577/images/1731/2311-.jpg?c=2" alt="Sweater Vest V-Neck Cotton" />
</div>
<div class="ProductDetails">
Sweater Vest V-Neck Cotton
</div>
<em class="p-price">$45.04</em>
<div class="ProductPriceRating">
<span class="Rating Rating0">
<img src="http://cdn3.example.com/templates/custom/images/IcoRating0.png?t=" alt="" style="" />
</span>
</div>
<div class="ProductActionAdd" style="display:;">
Choose Options
</div>
</li>
</ul>
</form>
</div>
So, there is only one li item here, on a typical page, there are up to 9. My goal is to use JavaScript to get the data-product values and then use that to look up a better image thumbnail and have it replaced. So, how do I get the value set for data-product?

Quite easy:
// Loop through all list items of ul.ProductList:
$("ul.ProductList li").each(function (index, element) {
// Find the element with attribute data-product:
$dp = $(element).find("[data-product]");
// Get the value of attribute data-product:
var product = $dp.attr("data-product");
// Now set the high quality thumbnail url:
var url = "/images/hq/" + product + ".png"; // Note that this is just an example
// Here you can use $(element) to access to current li (and the img):
$(element).find('.ProductImage img').attr('src', url);
});

You can use this:
$("#CategoryContent div[data-product]").each(function(){
alert($(this).attr('data-product'));
});

Pure JS:
var divs = document.querySelectorAll('#CategoryContent div[data-product]');
var index = 0, length = divs.length, prodIds = [];
for ( ; index < length; index++) {
prodIds.push(divs[index].getAttribute('data-product'));
}
Fiddle: http://jsfiddle.net/we5q7omg/

You could use the class name to get the data-product
var products = document.getElementsByClassName("ProductImage");
for(var i=0; i<products.length;i++)
{
console.log(products[i].getAttribute("data-product"));
}

Using JQuery, you can get the elements with the data-product attribute by simply calling
$('[data-product]')
// Or if you only want the data-product elements within the UL.
$('ul').find('[data-product]')
From there you can simply do pull the products from the elements. For Example:
var products = $('[data-product]').map(function() {
return $(this).data('product');
});

Related

Simple jQuery filter to accept "AND" for multiple buttons clicked and filter cards accordingly [duplicate]

I have a page that includes a section that's generated from a csv file (in Jekyll, using liquid). In this section, I have individual divs with an image and description. I need to find each div that fits a specific description.
<div class="row">
{% for item in site.data.items %}
<div class="col-md-3 item {{ item.test }} {{ item.industry }} {{ item.shape }}">
<img src="source here">
<br/>
<p>{{ item.name }}</p>
<p>{{ item.description }}</p>
</div>
{% endfor %}
</div>
I assigned classes to each div, and pulled the classes from the csv. This generates a class name of something like "item sticky food pasta".
Now I want to filter the displayed items when a user selects options on the page. I created an array, selectedOptions:
var selectedOptions = [];
Hide the other items:
$(".item").hide();
Push the selected options to the array:
$('input[name="filter-input"]:checked').each(function(i){
selectedOptions.push($(this).val());
});
And loop through the options to display only the items that have the classes selected:
for (var i = 0; i < selectedOptions.length; i++) {
$('.item').each(function() {
if ($(this).hasClass(selectedOptions[i])){
$(this).show();;
}
});
}
This works great, if I wanted every item that has any of the classes. However, what I want is a cumulative effect: I want only the items that have BOTH food AND pasta as a class.
How can I show every item that has all the classes? I know I can use something like $('.classa.classb'), but I'm not sure how to use that with the array I have here.
Thank you!
You can use querySelectorAll to do the dirty work for you in finding all the elmeents that match. Just build up a selector string.
const wrapper = document.querySelector(".wrapper");
document.querySelector("fieldset").addEventListener("change", function () {
const cbs = Array.from(document.querySelectorAll('input[type="checkbox"]:checked'));
const selectedClasses = cbs.map(cb => cb.value).join("");
const matchedElems = wrapper.querySelectorAll(selectedClasses);
console.log(matchedElems);
});
<div class="wrapper">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="one two">1 2</div>
<div class="one three">2 3</div>
<div class="two three">1 3</div>
<div class="one two three">1 2 3</div>
</div>
<form>
<fieldset>
<legend>Filters</legend>
<input type="checkbox" value=".one" id="cb1" /><label for="cb1">1</label>
<input type="checkbox" value=".two" id="cb2" /><label for="cb2">2</label>
<input type="checkbox" value=".three" id="cb3" /><label for="cb3">3</label>
</fieldset>
</form>
Consider the following.
$(".item").hide();
$('input[name="filter-input"]:checked').each(function(i){
$(".row > .item." + $(this).val()).show();
});
This will hide all items and then iterate each of the selected. It will show each of the elements that has the Class selected. The Selector does all the work.
E.G. If the user selects food and pasta, all the row that have food and pasta as a child will be shown.
$(".row > .item.pasta").show();
This will be done for each checked item.
You can also bank them up in an Array as you suggested. E.G.:
selectedOptions = ["food", "pasta"];
You can simply use .join(), yet you may want to add . to each so it can be a Class selector.
$(".item").hide();
var selectedOptions = [];
$('input[name="filter-input"]:checked').each(function(i){
selectedOptions.push($(this).val());
});
$.each(selectedOptions, function(k, v){
selectedOptions[k] = "." + v;
});
$(selectedOptions.join(", ")).show();
This will result in something like:
$(".food, .pasta").show();
You might notice how this is a lot of extra code to accomplish the same thing.

JQuery: iterate and dynamically change attr for each link based on the current item id

My JQuery code returns the same value to the link disregarding the current product id
The shopping cart page consist of [i] number of products, each product has its own productId. because the page iterates and it outputs the [i] number of products, I am not able to include the productId inside the wishlist iteration which is also [i] number of wishlists.
So I decided to go with JQuery and select the attributes to change the link for each product so users will be able to click and insert the product to their wishlists.
The final link for each product should be http://example.com/customer.do?addThisProductToWishList&productID=[i]&wishlistID=[i]
I have tried the code below but it keeps iterating and outputs a very long link and only keeps one productID stored to be populated to each product.
JQuery Code
$(".details").each(function() {
var _href = $(".addThisProductToWishList").attr("href");
$(".ProductID").each(function(){
var _theProductID = $(".ProductID").attr("data-id");
$(".addThisProductToWishList").attr("href", _href + '&productId=' + _theProductID + '&wishListID=');
});
});
EDIT
HTML CODE
<input type="hidden" name="wishListID"/>
<span class="wishListID" data-id="<js:text name="ProductID" />"></span>
<ul class="dropdown-list">
<js:iterate id="wishlists" collection="<%=wishListsCollection.getLists(new Integer(1))%>" >
<li class="dropdown-element">
<span data-id="<js:text name="wishList.wishListID"/>">
<js:text name="wishList.wishListName"/>
<js:a actionpath="/customer.do?action=addThisProductToWishList" name="product.productId" class="addThisProductToWishList">
<app:msg key="product.add_to_wishlist" /> </js:a>
</span>
</js:iterate>
</li>
</ul>
I think you aren't referring to current context that's why you are getting same value. Use this for current context. I hope below example will help you.
$(document).ready(function() {
$('.details').each(function() {
var pID = $(this).attr('data-product-id');
var wID = $(this).attr('data-wish-id');
$(this).find('a').attr('href', 'http://example.com/customer.do?addThisProductToWishList&productID=' + pID + '&wishlistID=' + wID);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="details" data-product-id="1" data-wish-id="a">
Product1
</div>
<div class="details" data-product-id="2" data-wish-id="b">
Product2
</div>
<div class="details" data-product-id="3" data-wish-id="c">
Product3
</div>

How iterate a jQuery function for each slide in a slider?

Summary: The purpose of this is to display a 3-part slider that users can click through, and they can use the index on each slide to filter the cards on that slide to a specific topic. The filters are working fine, but there's a problem in the JavaScript when it populates the indices: it's populating an index for all 3 cards, and showing that large index on each slide. Instead, the index for each slide needs to be unique, and only contain the hashtags from the cards in that same slide. I really want to avoid duplicating code for the different slides.
HTML
The following HTML has 3 (li) slides. Each slide contains a visible index (.hashtag-list), and one or more article cards (.item). Each (.item) besides the first one contains a hidden input with one or more hashtag values.
<li class="trend-cards">
<div class="card-items">
<div class="item trendingtopiccardblock">
<div class="hashtag-list"></div>
</div>
<div class="item">
<input class="tags" type="hidden" value="TopicA,TopicB"/>
</div>
<div class="item">
<input class="tags" type="hidden" value="TopicC"/>
</div>
</div>
</li>
<li class="trend-cards">
<div class="card-items">
<div class="item trendingtopiccardblock">
<div class="hashtag-list"></div>
</div>
<div class="item">
<input class="tags" type="hidden" value="TopicC, TopicD"/>
</div>
<div class="item">
<input class="tags" type="hidden" value="TopicA,TopicC,TopicD"/>
</div>
</div>
</li>
<li class="trend-cards">
<div class="card-items">
<div class="item trendingtopiccardblock">
<div class="hashtag-list"></div>
</div>
<div class="item">
<input class="tags" type="hidden" value="TopicA, TopicD"/>
</div>
<div class="item">
<input class="tags" type="hidden" value="TopicB,TopicC,TopicD"/>
</div>
</div>
</li>
JavaScript
The following jQuery pulls the values from the .tags classes, stores them in an array, removes duplicates, sorts them, and then populates the HTML in a callback. (Ignore the countryButtons and countries array, as that's not relevant.)
populateHashtagList: function() {
var $cards = $(".card-items .tags");
var list = [];
var $countryButtons = $('.card-filtering li .country-filtering');
var countries = [];
$countryButtons.each(function() {
countries.push(this.firstChild.data.replace("#", "").toLowerCase());
});
//Get tag values, set to lowercase and store in List array
$cards.each(function() {
var tags = getTags($(this).val());
$(tags).each(function (index, value) {
var tagValue = value.toLowerCase();
if($.inArray(tagValue, countries) === -1) list.push(value);
});
});
//Remove duplicates from the array
var uniqueTags = [];
$.each(list, function(i, el){
if($.inArray(el, uniqueTags) === -1) uniqueTags.push(el);
});
uniqueTags.sort();
function getTags(parameter) {
var arr = parameter.split(',');
return arr;
}
//Populate hash-tag List
var hashtagList = $('.hashtag-list');
populateHashtagList();
function populateHashtagList(callback) {
$.each(uniqueTags, function(i, el){
var htmlToInsert = '<span class="active">' + el + '</span>';
hashtagList.append(htmlToInsert);
});
if(typeof callback == "function")
callback();
}
}
What I've tried
Isolating the function using a $(".trend-cards").each function. This resulted in the same large list, but it was tripled on each slide.
Adding more specific paths to the .tags selectors, which changed nothing.
Using a parent selector once the .tags variable is set, and calling the remainder of the function from there. No hashtags populate in this case.
I appreciate any feedback and input on this. I want to learn how to do this better in the future. Thank you very much!
Wrapping this code in .each() function is the best solution here. You said you tried that and you probably forgot to specify parent element for cards and hashtag-list selectors.
Here is a working example: https://jsfiddle.net/k3oajavs/
$(".trend-cards").each(function(){
var $cards = $(".card-items .tags", this);
// ...
var hashtagList = $('.hashtag-list', this);
});

Set the HTML by calling using its ID or Class

I have a list of menus like
<ul id="toc">
<li>Description</li>
<li>Messages</li>
<li><a class="job_content">Applicants</a></li>
</ul>
Then i have a div like
<div id="job_item35116" class="items">
</div>
Then i have some more divs like
<div id="#description35116">
</div>
<div id="#msg_body35116">
</div>
So i am trying to do is when i will click the list item then these div (#description35116) will be appended inside id="job_item35116". (One item at a time)
So can i append a div with its ID inside another div ??
I tried like
JS (But its not working)
$('.job_content').unbind('click').click(function(){
var href = $(this).attr('href');
var id = $(this).attr('id');
var job_item = '#job_item'+ id;
if($(job_item).children().length > 0 ){
$(".items").empty();
$(href).toggle();
}else{
$(href).toggle();
}
return false;
});
Try this:
$('#toc li').on('click','a',function(e){
e.preventDefault();
var id = $(this).attr('href');
var div = $('<div id="' + id + '"></div>');
$(div).text(id);
$('.items').append($(div));
});
FIDDLE DEMO
Working solution: http://jsfiddle.net/aT7pF/1/
Remove the "#" from you ID-names in the div. It makes you live more easy.
From a coder perspective: Just place blank text within the </li>-tags. you don't need a <a href/>. Instead add a custom attribute to your tags, eg divId which you use to store the value of the </div>. it makes more sense this way. With JQuery you can fetch the value which you stored in your custom attribute easily with .attr()
(Refactored) HTML:
<ul id="toc">
<li divId="description35116">Description</li>
<li divId="msg_body35116">Messages</li>
<li>Applicants
</li>
</ul>
<div id="job_item35116" class="items"></div>
<div id="description35116">description35116</div>
<div id="msg_body35116">msg_body35116</div>
Javascript:
$("#description35116").hide();
$("#msg_body35116").hide();
var divId = $(this).attr("divId");
/*
you can make this line shorter:
$("#job_item35116").empty().append("<div>" +$("#"+divId).html() + "<div>");
*/
// by doing this:
$("#job_item35116").html("<div>" +$("#"+divId).html() + "<div>");

Am using Push() array was used am trying to use for select a list from drop down menu and post that list into a span?

HTML section
div to show the values
<div class="lef rightCol n">
<span class="para"> add-on Services(Optional)</span>
<div class="new">
<ul>
</ul>
</div>
</div
div that contain drop down
<div class="rightCol n mar ">
<span id="at1" class="spn">Click here to add add-on Services</span>
<ul id="ad1" class="drpdwn">
<li><input type="checkbox" id="ck1" value="1"><a id="a1">Drop Shadows</a></
li>
<li><input type="checkbox" id="ck2" value="2"><a id="a2">Reflections</a> <
li>
<li><input type="checkbox" id="ck3" value="6">General Spotting</a></li>
</ul>
I have tried this slide down while click
jQuery
slide down while click at1(Span)
this is the try for show on span on new div
here where should i use Push() most of them force me to use i don't know how and for what
var ots = [];
$('#at1,#at2,#at3,#at4,#at5,#at6').click(function(){
$(this).next('.drpdwn').stop().slideToggle();
}),
$('#ck1').click(function()
{
option=$('#a1').text();
$('.new ul').append('<li><span id="span1" alt="1" ></span></li>');
$('#span1').html(option).addClass('surr');
ots.push({id: 1});
}),
$('#ck2').click(function()
{
option=$('#a2').text();
$('.new ul').append('<li><span id="span2" alt="1" ></span></li>');
$('#span1').html(option).addClass('surr');
ots.push({id: 2});
}),
now i moved some value to array ots while append now the question is how to retrieve the newly created span's alt atrribute using array..?am using like these its not working clearly
some function
var f = $('.new span').length;
ad=o;
cs=o;
for(i=1;i<=f;i++)
{
$.each(this.opt, function() {
$.each(this, function(name, value) {
cs=eval($( "#span"+value).attr("alt"));
console.log(name + '=' + value);
ad+=cs;
console.log("ad: "+ad);
})
})
}
it shows ad as Nan and every time i click those id's it created like 1 then 1,2 then 1,2,3 like this help me out every time select check box it plays like this.!
push method is used to add new item in an array...so in your code push() was obivously used to push items to array(though i cannot find push methods in your question...so wouldn't be able to explain in your case)
docs
ex:
var sports = ["soccer", "baseball"];
sports.push("football", "swimming");

Categories