How to get closest value of span on click by class - javascript

When a user clicks on a link. I am trying to find the closest span value by class and then get that classes text. Currently it is just returning empty text:
Here is the HTML:
<div class="plan recommended">
<div class="recommended-badge"><span>DOUBLE DATA</span></div>
<div data-equalizer-listener="plan-heading" class="plan-header">
<div class="prices">
<div class="col total">
<div class="price"><sup>$</sup> <span class="amount">85</span> <span class="caption">per month</span></div>
</div>
<p class="min-payment">Min. Total Cost is $2,040 over 24 months.</p>
</div>
</div>
<div class="features">
<div class="feature included_data PO_Included_Data standard first" data-equalizer-selector="PO_Included_Data" style="height: 247px;">
<div class="description"><span class="highlight-text">28GB TOTAL DATA</span><br>
<span class="legal">Includes 14GB + 14GB bonus data for 24 mths<br>
New and recontracting services only<br>
Offer ends 15/04/18<br>
$10 per extra 1GB</span></div>
<div class="more-data-info hide" data-information="included-data"><strong>Data Pool -</strong> Combine any of our latest My Plan Plus (including SIM Only) and My Mobile Broadband Plus plans on the one bill to pool and share the data.</div>
<div>more</div>
</div>
</div>
</div>
and my javascript
So when someone clicks on the a href with the class="more-data-link" I want to find the span with the class="amount" and get its text
$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).closest('plan-header').find('.price').find('.amount').text();
console.log(x);
});

Please use this fiddle
$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).closest('.plan.recommended').find('.plan-header .price .amount').text();
console.log(x);
});
<div class="plan recommended">
<div class="recommended-badge"><span>DOUBLE DATA</span></div>
<div data-equalizer-listener="plan-heading" class="plan-header">
<div class="prices">
<div class="col total">
<div class="price"><sup>$</sup>
<span class="amount">85</span>
<span class="caption">per month</span></div>
</div>
<p class="min-payment">Min. Total Cost is $2,040 over 24 months.</p>
</div>
</div>
<div class="features">
<div class="feature included_data PO_Included_Data standard first" data-equalizer-selector="PO_Included_Data" style="height: 247px;">
<div class="description"><span class="highlight-text">28GB TOTAL DATA</span><br>
<span class="legal">Includes 14GB + 14GB bonus data for 24 mths<br>New and recontracting services only<br>Offer ends 15/04/18<br>$10 per extra 1GB</span>
</div>
<div class="more-data-info hide" data-information="included-data">
<strong>Data Pool -</strong> Combine any of our latest My Plan Plus (including SIM Only) and My Mobile Broadband Plus plans on the one bill to pool and share the data.
</div>
<div>
more
</div>
</div>
</div>
</div>
You need to select parent (plan recommended) class and then find its child...

For those seeking a solution without jquery (the logic inside the click event is the same as described by Sarvan Kumar):
window.onload = function(){
for(var tL=document.querySelectorAll('.more-data-link'), i=0, j=tL.length; i<j; i++){
tL[i].onclick = function(){
var tE = function fA(e){return !e || (e.className && e.className.indexOf('plan') !== -1 && e.className.indexOf('recommended') !== -1) ? e && e.querySelector('.amount') : fA(e.parentNode)}(this);
console.log(tE ? tE.textContent : '404')
}
}
}

I check your script and find some error in it, use innerHtml in place of text() and closest('plan-header') should be closest('.plan-header'). but may be you not get the proper result because it will search in parents div not subling check link https://www.w3schools.com/jquery/traversing_closest.asp
you can use the simplest and best way to do same by creating the attribute of the more-data-link and save value of amount in it and use the following code.
$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).attr('amount');
console.log(x);
});

$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).closest('.plan-header').find('.amount').text();
console.log(x);
});
Fixed it. You don't need to use the second find and you missed a dot

Related

How to differ changing text of child class based on parent class in javascript code?

I try to set value and text of my child classes after clicking on one of two buttons in my html code
$(".fce-pool-for > .fce-pool-bar").val($('.fce-pool-bar').val(Math.round(resultFor)));
$(".fce-pool-for > .fce-pool-percentage").text($('.fce-pool-percentage').text((Math.round(resultFor).toString()) + "%"));
$(".fce-pool-against > .fce-pool-bar").val($('.fce-pool-bar').val(Math.round(resultAgainst)));
$(".fce-pool-against > .fce-pool-percentage").text($('.fce-pool-percentage').text((Math.round(resultAgainst).toString()) + "%"));
<div class="fce-pool-against">
<div class="row">
<div class="col-1">
<p class="fce-pool-title">
<?php the_sub_field('vote_against_title')?>
</p>
</div>
<div class="col-8">
<progress class="fce-pool-bar" max="100" value="0"></progress>
</div>
<div class="col-1">
<p class="fce-pool-percentage">0 %</p>
</div>
<div class="col-1 offset-1">
Less
</div>
</div>
<p>
<?php the_sub_field('vote_against_note')?>
</p>
</div>
<div class="fce-pool-for">
<div class="row">
<div class="col-1">
<span class="fce-pool-title"><?php the_sub_field('vote_for_title')?></span>
</div>
<div class="col-8">
<progress class="fce-pool-bar" max="100" value="0"></progress>
</div>
<div class="col-1">
<p class="fce-pool-percentage">0 %</p>
</div>
<div class="col-1 offset-1">
More
</div>
</div>
<p>
<?php the_sub_field('vote_for_note')?>
</p>
</div>
But do not know how to set values when parent class is different... please someone has an advice how to do that ???
I don't know where you get the resultFor and resultAgainst value from so I put an example of that in there, using the commented out functions.
Note the key to your question is "what was clicked, from where". To do that, I attached an event handler to the pools '.fce-pool-against, .fce-pool-for', targeting the buttons within that> '.fce-pool-button' as in:
$('.fce-pool-against, .fce-pool-for').on('click', '.fce-pool-button',
Then, inside the function I use the attached pool (the delegateTarget) and find stuff inside that during the click event handler function execution.
let pool = $(event.delegateTarget);
Documentation: https://api.jquery.com/event.delegateTarget/
Perhaps a better solution is to use a data attribute in each pool, so I put an example of that in there, this makes the code much more generic, and we can attach a button click handler to each pool and then use that, finding the elements we need in each pool when clicked.
Separate thing snippet
let resultFor = 20;
let resultAgainst = 13;
$('.fce-pool-for').on('click', '.fce-pool-button', function(event) {
event.preventDefault();
let pool = $(event.delegateTarget);
let resultValue = Math.round(resultFor);
pool.find('.fce-pool-percentage').text( resultValue + " %");
pool.find('.fce-pool-bar').val(resultValue);
});
$('.fce-pool-against').on('click', '.fce-pool-button', function(event) {
event.preventDefault();
let pool = $(event.delegateTarget);
let resultValue = Math.round(resultAgainst);
pool.find('.fce-pool-percentage').text( resultValue + " %");
pool.find('.fce-pool-bar').val(resultValue);
});
Use the data property/attribute to do something more generic:
$('.fce-pool-against, .fce-pool-for').on('click', '.fce-pool-button', function(event) {
event.preventDefault(); // keep link from executing
let pool = $(event.delegateTarget); // the pool
let votes = pool.data('votes'); // data from the pool
votes = votes + 1;
// store new value
pool.data('votes', votes);
// update the percent and display
$('.fce-pool-button').trigger('showvalues');
});
$('.fce-pool-against, .fce-pool-for')
.on('showvalues', '.fce-pool-button', function(event) {
event.preventDefault(); // keep link from executing
let pool = $(event.delegateTarget); // the pool
let votes = pool.data('votes'); // data from the pool
let totalVotes = 0;
$('.fce-pool-button').each(function(e) {
totalVotes = totalVotes + $(this).closest('.fce-pool').data('votes');
});
let percent = (votes / totalVotes) * 100;
//console.log(totalVotes, votes, percent);
let resultValue = Math.round(percent);
// find the elements in our pool, set them
pool.find('.fce-pool-percentage').text(resultValue + " %");
pool.find('.fce-pool-bar').val(resultValue);
pool.find('.votes-display').text(votes);
})
.find('.fce-pool-button')
.trigger('showvalues'); // trigger initial display
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<div class="fce-pool fce-pool-against" data-votes="25">
<div class="row">
<div class="col-1">
<span class="fce-pool-title">
Against
</span>
</div>
<div class="col-8">
<progress class="fce-pool-bar" max="100" value="0"></progress>
</div>
<div class="col-1">
<p class="fce-pool-percentage">0 %</p>
</div>
<div class="col-1 offset-1">
Less
</div>
</div>
<p>
Against Votes: <span class="votes-display"></span>
</p>
</div>
<div class="fce-pool fce-pool-for" data-votes="43">
<div class="row">
<div class="col-1">
<span class="fce-pool-title">For</span>
</div>
<div class="col-8">
<progress class="fce-pool-bar" max="100" value="0"></progress>
</div>
<div class="col-1">
<p class="fce-pool-percentage">0 %</p>
</div>
<div class="col-1 offset-1">
More
</div>
</div>
<p>
For Votes: <span class="votes-display"></span>
</p>
</div>
I think what you want is to be able to isolate the parent class of whichever fce-pool-button is clicked.
Give the fce-pool-against and fce-pool-for parents a common class like fce-pool along with the classes they already have.
Then you can isolate the parent fce-pool class by traversing to closest('.fce-pool') and use find() within that parent to look for instance specific elements like the <progress>.
You can also use is() to determine whether it is for or against pool so you know how to manage the data for that instance
$('.fce-pool-button').click(function(event){
// "this" is the button that was clicked
var $pool = $(this).closest('.fce-pool'),
// find the progess element in current instance
$progress = $pool.find('progress.fce-pool-bar'),
// set boolean to know which type it is
isForPool = $pool.is('.fce-pool-for');// true/false
// now use logic similar to
$progress.val( isForPool ? resultFor : resultAgainst)
})

JavaScript Do/While Loop Infinitely Looping

I know this is potentially a common question however I believe the logic and the code appear correct, yet it still seems to loop until the browser crashes.
$("#orderview").click(function(){
do {
$(".row1").clone().appendTo(".cardbox");
var i = $( "listrow" ).length;
}
while (i < 10);
});
My function is creating Listrow class DIV's until there are 10 of them. My HTML starts with 1 DIV.
<div class="listrow news" id="row-a">
<div class="l-padding floatleft">
<div id="redditThumbnail"></div>
<div class="articleheader news">
<p class="mediatitle alignleft" id="redditTitle">
</p>
<p class="mediumtext floatleft alignleft">
Submitted by
</p>
<div id="redditUsername"></div>
<div class="half floatright">
<p class="mediatext floatright s-color bold h-s-margin">
TEST
</p>
<p class="mediatext floatright p-color bold">
ACTION
</p>
</div>
</div>
</div>
</div>
The logic behind my attempted JS was:
Clone the first DIV
Check how many "Listrow" class DIVs are present
If there are < 10 Listrow DIV's then restart the loop and clone
another
Am I missing something? Thanks in advance for the assistance.
change :
var i = $( "listrow" ).length;
to :
var i = $( ".listrow" ).length;

Changing Div content based on Geo IP

I currently have a website that is showing a price for a product within a <div>. I would like this number to change if the user is from outside the UK, for example changing the price to Euros rather than GBP.
Is this possible? I can't find an example I understand.
You should give more example info but Im not going to be so critical.
You could capture the location using google maps if they agree to it, or ip address and then set a class to all the price divs and price symbol divs.
try something like this
<div id="parent_id">
<div class="item">
<span class="symbol">£</span> <div class="price_divs" id="div1">5.00</div>
</div>
<div class="item">
<span class="symbol">£</span> <div class="price_divs" id="div2">5.00</div>
</div>
<div class="item">
<span class="symbol">£</span> <div class="price_divs" id="div3">5.00</div>
</div>
</div>
<script>
jQuery(function(){ ///requires jquery
if(location == "US"){ //location must be a global variable given a value from google maps
var all_pricing = $('#parent_id').find('.price_divs');
$('.symbol').html('$');
$.each(all_pricing,function(x,y){
var c = convertToDollars($('#'+y.id).html());
$('#'+y.id).html(c);
});
}
function convertToDollars(cost)
{
///some conversion here
return cost;
}
});
</script>

Get specific data from page and write it to div

I'm building an online store with javascript shopping cart. However, the script doesn't allow printing only one or two values when displaying cart, but I need to do this.
Here's what the cart looks like:
<div class="simpleCart_items">
<div>
<div class="headerRow">
<div class="item-name">Tuote</div>
<div class="item-price">Hinta</div>
<div class="item-decrement">-</div>
<div class="item-quantity">Määrä</div>
<div class="item-increment">+</div>
<div class="item-total">Yhteensä</div>
<div class="item-remove">Poista</div>
</div>
<div class="itemRow row-0 odd" id="cartItem_SCI-1">
<div class="item-name">Teipit</div>
<div class="item-price">€0.00</div>
<div class="item-decrement"><img src="css/minus.png" alt="minus">
</div>
<div class="item-quantity">3</div>
<div class="item-increment"><img src="css/plus.png" alt="plus">
</div>
<div class="item-total">€0.00</div>
<div class="item-remove"><img src="css/remove.png" alt="Remove">
</div>
</div>
<div class="itemRow row-1 even" id="cartItem_SCI-3">
<div class="item-name">Car Speaker -hajuste</div>
<div class="item-price">€4.00</div>
<div class="item-decrement"><img src="css/minus.png" alt="minus">
</div>
<div class="item-quantity">1</div>
<div class="item-increment"><img src="css/plus.png" alt="plus">
</div>
<div class="item-total">€4.00</div>
<div class="item-remove"><img src="css/remove.png" alt="Remove">
</div>
</div>
<div class="itemRow row-2 odd" id="cartItem_SCI-5">
<div class="item-name">Teipit (Musta hiilikuitu)</div>
<div class="item-price">€0.00</div>
<div class="item-decrement"><img src="css/minus.png" alt="minus">
</div>
<div class="item-quantity">1</div>
<div class="item-increment"><img src="css/plus.png" alt="plus">
</div>
<div class="item-total">€0.00</div>
<div class="item-remove"><img src="css/remove.png" alt="Remove">
</div>
</div>
</div>
</div>
NOTE: The cart is written via javascript so it isn't visible in page source, only in inspect mode of the browser.
So how would I gather the item-name, item-priceand item-quantity?
I've tried this:
var name = $('.item-name');
var price = $('.item-price');
var quantity = $('.item-quantity');
var data = name + price + quantity;
$('#items').html(data);
But this won't actually do anything.
When doing this -> $('.item-name');
You are just capturing the element as object but not the value.
Now that you got your element as object, you need to extract the value and, in this case, your element object is a div so you can try .text() or .html() (to get the text or html inside the div).
(For this situation I will use text() cause you are working just with values and there is nothing related to html)
Try this:
var name = $('.item-name');
var price = $('.item-price');
var quantity = $('.item-quantity');
var data = name.text() + price.text() + quantity.text();
$('#items').html(data);
Better solution:
This will make clickable the div in which you have the product and match the cartItem_SCI pattern.
So, when user clicks any of the elements of your cart, you will get the name, price and quantity values that will be attached to the $('#items') div using append() method instead of html() (because using this will replace the product information each time the user clicks a div)
$(document).ready(function() {
$('div[id^="cartItem_SCI-"]').css({ cursor:'pointer' });
$('div[id^="cartItem_SCI-"]').click(function() {
var name = $(this).find('.item-name');
var price = $(this).find('.item-price');
var quantity = $(this).find('.item-quantity');
var data = name.text() + ' - ' + price.text() + ' - ' + quantity.text();
$('#items').append(data + '<br/>');
});
});​
You are just getting a reference to the class, add .html() to get the inner html of the element that the class applied to.
var name = $('.item-name').html();
For one item you can get like this.But since you have multiple items make one object like this .
var item={};
$('.item-name').each(function(){item.name=$(this).html()});
$('.item-price').each(function(){item.price=$(this).html()});
$('.item-quantity').each(function(){item.quantity=$(this).html()});
var data='';
for(var i=0;i<item.length;i++)
{
data+=item[i].name+item[i].price+item[i].quantity;
}
$('#items').html(data);

If I can only use javascript, how can I filter list by date?

I have this list structure:
<ul class="pol list">
<li>
<div class="tekst">
<h2><span class="name"></span></h2>
<p class="description"></p>
<div class="commentsBar1">
<div class="commentsBarL1">
<h5>
<strong class="category">
<span style="display:none;"></span>
<span class="d">27.12.2011</span>
</strong>
</h5>
<h5><strong></strong></h5>
</div>
</div>
</div>
</li>
<li>
<div class="tekst">
<h2><span class="name"></span></h2>
<p class="description"></p>
<div class="commentsBar1">
<div class="commentsBarL1">
<h5>
<strong class="category">
<span style="display:none;"></span>
<span class="d">03.03.2012</span>
</strong>
</h5>
<h5><strong></strong></h5>
</div>
</div>
</div>
</li>
</ul>
I need js that will hide all list tags which contain a date outside of a certain range. The date range is given by user and both start and end dates are given in same way as dates in the list (dd.mm.yyyy).
<input id="Date1" name="Date1">
<input id="Date2" name="Date2">
I have this date comparison code:
var dControl = document.getElementsByClassName("d");
var d1Control = document.getElementById("Date1");
var d2Control = document.getElementById("Date2");
var arrD = dControl.value.split(".");
var dd0 = new Date(arrStartDate[2], arrStartDate[1], arrStartDate[0]);
var arrD1 = d1Control.value.split(".");
var dd1 = new Date(arrStartDate[2], arrStartDate[1], arrStartDate[0]);
var arrD2 = d2Control.value.split(".");
var dd2 = new Date(arrStartDate[2], arrStartDate[1], arrStartDate[0]);
if((dd0 <= dd2 && dd0 >= dd1)) {
return true;
}
return false;
And one more thing... The number of list elements varies from page to page so I also need to get some idea about the list size, but that I assume is easy to do with "length".
Any ideas how can I achieve this?
You will need to write javascript to build the dom based on the dates you have. I suggest using a templating framework such as mustache or handlebars to keep your code tidy.
just run through the elements with class "d" and check if they meet your date criteria if not then set that li to display "none". you will have to find the li in the DOM node tree which appears to be 8 levels higher that your date.

Categories