each() function returning Null or Objects - javascript

Hi I am newbie in programming and I am trying to learn and make it work with each(). Bear with me. I try my best to learn from here and you.
I am trying to go through the item per product in a catalog for the specific prices: either original and sale from the page.
then calculate the % for discount
print discount %
check to compare the percent to color the background: brown, yellow and red.
Now, I test each line to see if it works or not.
salecost = $(this).find('#sale').html(); returns a few nulls before displays amount with dollar signs. Weird couldn't figure that one out. Replace() isn't working right - couldn't get it working. It is supposed to remove dollar sign.
Also, I am not sure how it goes with compare -- do i write statement correctly?
Thank you in advance for the help
var salecost;
var originalcost;
var percentDiscount;
var percent;
function calculate(sale, original)
{
percentDiscount = eval((sale/original)*100);
document.getElementById("percentoff").innerHTML=parseInt(percentDiscount) + '%';
}
$(document).ready(function(index){
$('.item').each(function(){
salecost = $(this).find('#sale').html();
salecost = salecost.replace(/[^\d\.]/g,"");
alert (salecost);
originalcost = $('#sale').html();
originalcost = originalcost.replace(/[^\d\.]/g,"");
alert (originalcost);
percent = calculate(salecost,originalcost);
alert(percent);
if(percent<30)
{
$("div#percentoff").css({"background-color":"brown", "padding":"5px 0"});
}
if(percent<50){
$("div#percentoff").css({"background-color":"yellow", "padding":"5px 0"});
}
if(percent<70){
$("div#percentoff").css({"background-color":"red", "padding":"5px 0"});
}
});
});

This is not required
$(this).find('#sale').html();
You can replace this using
$("#sale").html();
since id will be unique in a document. If you have more than one element with the same id then your HTML is invalid.
Edit
Remove the id from the span tag.
<span class="price">S$319</span>
This will find all the spans[here only 1] with class name price inside the parent div. No need to use .html() here, you can use .text()
$(this).find('span.price').text();

You should move your var statements to within the each function so they're not global.
You don't need to you the eval, (sale/original)*100 will work by it self.
It's better to use consistent style, your calculate function could be written using jquery.
$("#percentoff").html(percentDiscount) + '%');
casting is unnecessary for most cases in javascript, concatenating a number with a string will produce a string.
your calculate function should return percentDiscount;
Instead of using .css() it would be better to use .addClass that way it's easy to undo with .removeClass, the style is all the the style sheet and you can use jquery to select the elements with the class.

Related

Javascript - passing percentage of variable to charts.js

I am a total newbie to javascript and bascially i need to know how to make the following work
The original working code is
var initial_deposit = document.querySelector('#initial_deposit'),
But i want it to be the value + 25% of it (obviously not like the below but just to show the thought process)
var initial_deposit = document.querySelector('#initial_deposit' / 4 + '#initial_deposit'),
could anybody point me in the right direction or help me with the string syntax i need to make this happen?
When using document.querySelector
The querySelector() method returns the first element that matches a
specified CSS selector(s) in the document.
i will sugest to use document.getElementById().value and then do you calculation and change the value.
if you get the value as a string use parseInt()
You haven't told us what type of element #initial_deposit is, but assuming it's an input field:
Parse the value of #initial_deposit
Multiply it by 1.25 to increase it by 25%.
var value = parseFloat(document.querySelector('#initial_deposit').value);
var initial_deposit = value * 1.25;

How to count through a tags and apply +1rem padding to each one?

I'm trying to style some breadcrumbs programmatically, because I don't know how many breadcrumbs there will be (due to child categories being set up by the client, etc). I've tried a few ways to count through the a tags and do this, without much success. Basically I just want each a tag to have one more 1rem of left padding than the previous one. Here is my code:
for(var i = 0; i < jQuery('.woocommerce-breadcrumb a').length; i++){
jQuery('.woocommerce-breadcrumb a:nth-child(' + i + ')').css('padding', i + 'rem');
}
Please excuse my bad coding as I'm just a novice with JavaScript/jQuery. And thank you in advance for any help.
If you want to use jQuery inside of pure CSS, you don't have to use the nth-child selector to get each a tag, you could just loop through each a tag by using the jQuery .each() function.
Something like this should work:
$('.woocommerce-breadcrumb a').each(function(i, ele) {
$(ele).css('padding-left', i + 'rem');
});
This will loop through every tag that matches .woocommerce-breadcrumb a, and then apply the relevant css. the .each() function let's you declare an index i in the function, so that lets us use incrementing padding-left for each element.
See this following code pen - http://codepen.io/anon/pen/vLyOMj - for an example as well.
jQuery.each automatically passed an index so there is no reason to do the for loop.
$('.woocommerce-breadcrumb a').each(function(i) {
$(this).css('padding', i + 'rem');
});
https://jsfiddle.net/SeanWessell/79Lnpze8/
I'd suggest, based on your stated requirements:
// selects the <a> elements contained within an element with a
// class-name of 'woocommerce-breadcrumb',
// uses the css() method to update the 'padding-left' property
// with an anonymous function, in which the first argument
// here 'i' (the index of the current element in the set returned
// by the selector):
jQuery('.woocommerce-breadcrumb a').css('padding-left', function (i) {
// returns a concatenated string, formed by the number of 1
// added to the current index and finally with the units
// added:
return 1 + i + 'rem';
});
References:
css().

jquery offset method doesn't always work / exist

Good morning and happy new year everyone!
I've run into a snag on something and need to figure out a solution or an alternative, and I don't know how to approach this. I actually hope it's something easy; meaning one of you all have dealt with this already.
The problem is that I'm doing rollovers that contain information. They're divs that get moved to the absolute location. Now I've tried this with jquery 1.6 - 1.9.1. Of course this has to work in multiple browsers.
What needs to happen is on rollover show a div, and when you rollout of that div, make it hide.
...
// .columnItem is class level and works
$(".columnItem").mouseleave(function() {
$(this).css("display", "none");
});
...
$(".column").mouseenter(function() {
var currentItem = $(this)[0]; // this is where the problem is
// hide all .columnItems
$(".columnItem").css("display", "none");
// i get this error: Object #<HTMLDivElement> has no method 'offset' (viewing in chrome console)
var offsetTop = currentItem.offset().top;
var columnInfoPanel = $("#column" + currentItem.innerText);
});
So the immediate thought of some would be don't use $(this)[0]. Instead, I should use $(this), and you are correct! Where the other problem comes into play is by removing the array index, currentItem.innerText is now undefined.
The only thing I can think of is I'll have to mix both, but it seems like there should be a way to use the selector and get both options.
What have you all done?
Thanks,
Kelly
Replace:
var currentItem = $(this)[0];
With:
var currentItem = $(this).eq(0);
This creates a new jQuery object containing only the first element, so offset will work.
Then you can use either currentItem[0].innerText or currentItem.text(), whichever you prefer.
Skip the [0] at the beginning as you are saying.
But then change the last line to:
var columnInfoPanel = $("#column" + currentItem[0].innerText);
De-referencing the jQuery selector gives you the DOM-object.
If you want to stick to pure jQuery, the .text() / .html() methods will give you the same functionality.

Cloned row requesting same function [duplicate]

This question already exists:
Closed 10 years ago.
Possible Duplicate:
Call same function by a cloned list row
I am trying to make a simple calculation to work.
I have the following running:
http://jsfiddle.net/vSyK6/41/
Basically, the way it works now is this:
When you select an option on the drop down list it will display the content based on the option selected. Then when you select the same option again it will add, basically clone the same row.
Now, when the second option is selected "Option2" it will display an empty textbox. When you enter a number it will or should call the a function where we make a basic calculation. The function is already in the script.
However, when we have two empty textboxes it should call the same calculation function but calculate seperately and puts it in a different div. The div# where we display the amount is a called "amount"
Basically, it should work like this:
First Empty textbox -> 100 -> 100 * 22.38 = display result in div#1
Second Empty textbox -> 230 -> 230 * 22.38 = display in div#2
any idea on how to accomplish that ?
When cloning elements the id is cloned as well. It is best practice to create a new ID for the cloned elements, which will also help in accomplishing what you want. The same goes for the name attribute as well.
With a few modification to your code, http://jsfiddle.net/dNQVQ/3/, I was able to get what you were after. Let me first say that this might not be the ideal way to go, but it is a start. Like I said earlier the key is going to be setting unique ids for the cloned elements. What I did in this example was use a index as part of the list element id that is cloned with a matching index in an 'amount' div. This way when an input is updated the index is retrieved and then used to update the appropriate div. Additionally, I moved the function that did the calculation and updates to an anonymous function in the settimeout call. This makes it easy to use a reference to the updated input in the function call.
Joining the party quite late here :) Here is one vernon: http://jsfiddle.net/KVPwm/
ALso if its assignment bruv, put an assignment homework tag!
People around SO community are awesome folks so be truthful, guys will help man!
Use .on instead of live - recommendation. i.e. upgrade your JQ source if keen read this - What's wrong with the jQuery live method?
you have 2 document.ready functions also I chained few things for you.
Also think of using isNan check as well.
Rest you can read the code and play around a bit to make it more concise.
I have added 2 divs and using the id number to populate the stuff accordingly.
This should fit the cause :)
code
$("document").ready(function() {
/////////////////////////////////CALUCATIONS/////////////////////////////////
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 0; //time in ms, 5 second for example
$('input[name=Input2], input[name=Input1]').live('keyup', function() {
var str = $(this).prop("id");
var pattern = /[0-9]+/g;
var matches = str.match(pattern);
amount = parseFloat($(this).val()) * 22.38;
typingTimer = setTimeout(doneTyping(matches), doneTypingInterval);
});
$('#Input2').keydown(function() {
clearTimeout(typingTimer);
});
function doneTyping(matches) {
$('#amount'+matches).text(amount.toFixed(2) + " lbs");
}
$("#List-Option1,#List-Option2").hide();
$('#category').change(function() {
var str = $('#category').val();
if (str == 'Option1') {
var option1 = $("#List-Option1:first").clone().show();
$('#box li:last').after(option1);
}
if (str == 'Option2') {
var option2 = $("#List-Option2:first").clone().show();
$('#box li:last').after(option2);
}
});
});​

Better performance for selecting options by value with jQuery?

I am trying to work out some performance problems with some JavaScript I've been working on for a few days. One of the pieces of the functions is below:
var removeAddress = function(pk) {
var startTime = new Date();
jQuery('.add_driver select.primary_address:has(option[value=' + pk + ']:selected)').each(function(c, o) {
console.log("Shouldn't get here yet...");
showInputs(o);
});
console.log('removeAddress1: ', (new Date() - startTime) / 1000);
jQuery('.add_driver select.primary_address option[value=' + pk + ']').remove();
console.log('removeAddress2: ', (new Date() - startTime) / 1000);
};
This code is quite peppy in Firefox:
removeAddress1: 0.004
removeAddress2: 0.023
But in IE8 it is another story:
LOG: removeAddress1: 0.203
LOG: removeAddress2: 0.547
The form in question is a 20-person in put form with first name, last name, and 5 address fields. I've also put in a drop down for selecting other addresses already existing in the form (.primary_address). This code is removing an address from the primary address select boxes.
I'm trying to nail down why this is taking so long, and the only thing which stands out is the option[value=????] section. This was the most practical way to find the elements in question, so I ran with it. Is there something about these two selectors which is causing IE to lose its lunch?
The option element is always temperamental. Perhaps it's simpler to just get all the SELECT elements and then simply query their values. The selected OPTION always will give its value property to the SELECT as well. So:
jQuery('.add_driver select.primary_address').filter(function() {
return $(this).value === pk;
});
jQuery('.add_driver select.primary_address[value='+pk+']');
Maybe one of those will be faster - not sure if the second will work.
You can likely speed this up a lot by breaking down your uber-selector string.
To start, begin with an id, or even better a cached element. Then get your select elements using .children(). Instead of using the :has selector use .has(). Methods are generally faster than complex selector syntax because jQ doesn't have to parts a string to figure out what you mean. Then, as Rafael said, you can skip the :selected and just look at the value of the matched select's.
formElem = document.getElementById('formId');
jQuery('.add_driver', formElem)
.children('select.primary_address')
.has('[value=' + pk + ']')
.each(...);
Passing formElem as the second arg uses it as the context for the search so jQ doesn't have to start at the root.
To .remove() the elements either cache the jQuery object from above or chain it on after the .each() so you don't have to reselect everything again.
Maybe precompute $('formId .add_driver select') outside of the removeAddress function, then reuse that so the removeAddress() doesn't have to enumerate so many elements.

Categories

Resources