I current have a class in Javascript to handle a cart (only with static data as it stands). However, when I try to add two integers together:
var Cart = {
handler: {
totalCost: 0,
addCost: function() {
$('#cart li').each(function() {
var cost = +$(this).attr('cost');
console.log('single cost: ' + cost);
var total = this.totalCost + cost;
console.log('after add: ' + total);
});
console.log(this.totalCost);
}
}
};
I get this output:
after add: NaN
I have tried ensuring both values are numerical adding a + delimiter to the variable, I receive the same output? A sample of working code is at JsFiddle.
You have a scoping issue - within the each function this no longer refers to handler, but to the currently iterated element. You can fix this by referring directly to Cart.handler:
$(document).ready(function() {
var Cart = {
handler: {
productId: 'pid-',
totalCost: 0,
yesNoAlert: $('.display'),
addCost: function() {
$('#cart li').each(function() {
cost = +$(this).attr('cost');
console.log('single cost: ' + cost);
total = Cart.handler.totalCost + cost;
console.log('after add: ' + total);
});
console.log(Cart.handler.totalCost);
},
removeProduct: function(pid) {
this.productId = pid;
this.displayYesNo('remove');
},
displayYesNo: function(callback) {
this.yesNoAlert.attr('callback', callback);
this.yesNoAlert.slideToggle('slow');
},
callback: function(callback) {
if (callback === 'remove') {
$('#' + this.productId).hide();
}
this.yesNoAlert.hide();
},
throw: function(e) {
$('#error').html(e);
$('#error').slideToggle('slow');
}
}
};
https://jsfiddle.net/d6kccr88/3/
you can save the value of this in another variable that and use that variable in your method to save the this value
because in jquery each method the value of this will be your currect element which are currently iterating
Related
Creating Stars rating system and I want to access the rating number and perform an action based on that. How can I access the number variable outside my click function?
$(document).ready(function () {
$(".li").mouseover(function () {
var current = $(this);
$(".li").each(function (index) {
$(this).addClass("hovered-stars");
if (index == current.index()) {
return false;
}
})
})
$(".li").mouseleave(function () {
$(this).removeClass("hovered-stars");
})
$(".li").click(function () {
$(".li").removeClass("clicked");
$(".hovered-stars").addClass("clicked");
var number = $(".clicked").length;
$("#message").html("You rated " + number + " Stars");
})
console.log(number);
})
Currently cannot print number variable outside click event listener
you need to declare the number variable outside the click function and then re-assign the value inside click function
$(document).ready(function () {
var number=0;
$(".li").mouseover(function () {
var current = $(this);
$(".li").each(function (index) {
$(this).addClass("hovered-stars");
if (index == current.index()) {
return false;
}
})
})
$(".li").mouseleave(function () {
$(this).removeClass("hovered-stars");
})
$(".li").click(function () {
$(".li").removeClass("clicked");
$(".hovered-stars").addClass("clicked");
number = $(".clicked").length;
$("#message").html("You rated " + number + " Stars");
})
console.log(number);
})
var newSalary = function(){
var salary = 30000;
function update (amount){
salary += amount;
}
return {
hike: function(){
update (5000);
},
lower: function(){
update (-5000);
},
current: function(){
return salary;
}
}
}
console.log('current salary::'+newSalary.current());
Getting:
newSalary.current is not a function.
What's wrong in the code?
You need to call newSalary as a function, with parantheses ():
console.log('current salary::' + newSalary().current());
▲
Here's a working snippet:
var newSalary = function(){
var salary = 30000;
function update (amount){
salary += amount;
}
return {
hike: function(){
update (5000);
},
lower: function(){
update (-5000);
},
current: function(){
return salary;
}
}
}
console.log('current salary::' + newSalary().current());
You need to call the newSalary function to get object having definition of current function:
console.log('current salary::' + newSalary().current());
You need:
console.log('current salary::'+newSalary().current());
Since newSalary is a function you have to add the () to call it.
You need create instance of object
var salary = new newSalary();
salary.current();
Add a "return salary" to both the hike and lower functions :
var newSalary = function(){
var salary = 30000;
function update (amount){
salary += amount;
}
return {
hike: function(){
update (5000);
return salary;
},
lower: function(){
update (-5000);
return salary;
},
current: function(){
return salary;
}
}
}
You can then call them by using either newSalary().hike(); or newSalary().lower();
basically I have a number stored within my javascript structure, something like the following:
MyProgram.data.main.padding;
console.log(MyProgram.data.main.padding); // will output the number, something like 34.
However, I need to store that number in a struct I have set up in
MyProgram.data.tests.main.padding; // this is a struct " {'width':0, 'padding':0, 'acceptable' //etc...}
The problem is when I do this:
MyProgram.data.tests.main.padding = MyProgram.data.main.padding;
console.log(MyProgram.data.tests.main.padding); // shows undefined
any ideas why I can't store the number?
I really appreciate any help...
Can someone load this example on jsfiddle please? I don't know how:
http://jsfiddle.net/hdnj52Lp/2/
RESULT OUTPUT ON MY LOCAL TEST: 0) acceptable: true fontSize undefined padding: undefined
function MyProgram() {
var mp = this;
this.main = {
'data' : {
'padding': 50,
'fontSize': 10,
'tests' : {
'padding':null,
'fontSize':null,
'results':new Array()
}
},
'test' : function () {
console.log('running');
var testResult = {'acceptable':false,
'fontSize':0,
'padding':0}
//after some testing:
var newComputedPadding = 100;
var newComputedFontSize = 32;
var acceptable = true;
testResult.acceptable = acceptable;
testResult.fontSize = newComputedFontSize;
testResult.padding = newComputedPadding;
mp.main.data.tests.results.push(testResult);
mp.main.outputResults();
},
'outputResults' : function () {
for(var i = 0; i < mp.main.data.tests.results.length; i++) {
console.log( i + ') acceptable: ' + mp.main.data.tests.results[i].acceptable + ' fontSize ' + mp.main.data.tests.results.fontSize + ' paddingSides: ' + mp.main.data.tests.results.padding);
}
}
}
}
var Load;
if (window.attachEvent) {
Load =function ( elem, event, handler ) {
elem.attachEvent( 'on'+event, function load() {
handler();
elem.detachEvent( 'on'+event, load );
});
};
} else {
Load =function ( elem, event, handler ) {
elem.addEventListener( event, function load() {
handler();
elem.removeEventListener( event, load, false );
}, false);
};
}
Load(window, 'load', function() {
var MP = new MyProgram();
MP.main.test();
});
You are simply printing
mp.main.data.tests.results.fontSize
instead of
mp.main.data.tests.results[i].fontSize
The code is correct for acceptable but you forgot the [i] part for fontSize and padding.
I have a slight problem that I do not know how to approach due to my lack of Javascript experience. Basically I have two or more counters that each count upwards or downwards separately. I want to run a function when all of the counters total value equals to 0
But I do not know how to extract that value from the functions that someone wrote for me.
Here is a jsFiddle for the counters
http://jsfiddle.net/RoryMcCrossan/puJ6G/1015/
jQuery(document).ready(function () {
$('.qtyplus').click(function (e) {
e.preventDefault();
var $container = $(this).closest('.count-container');
var $field = $container.find('input[name=' + $(this).data('field') + ']');
var currentVal = parseInt($field.val(), 10);
if (!isNaN(currentVal)) {
$field.val(currentVal + 1);
} else {
$field.val(0);
}
});
$(".qtyminus").click(function (e) {
e.preventDefault();
var $container = $(this).closest('.count-container');
var $field = $container.find('input[name=' + $(this).data('field') + ']');
var currentVal = parseInt($field.val(), 10);
if (!isNaN(currentVal) && !currentVal == 0) {
$field.val(currentVal - 1);
} else {
$field.val(0);
}
});
});
Many thanks! :)
Firstly we can write a new function which checks all our counters and adds their values together:
function checkCounters() {
var result = 0;
// Loop through each "qty" input element
$('.qty').each(function() {
// Add the value of the input to our result
result += +this.value;
});
if (result === 0)
// Your function should be triggered here
console.log("Result is 0");
else
console.log("Result isn't 0, result is " + result);
}
We can then call this function whenever we update the value of a counter:
...
if (!isNaN(currentVal)) {
$field.val(currentVal + 1);
} else {
$field.val(0);
}
checkCounters();
JSFiddle demo.
I need to be able to call a function getProgress every second. This function does an ajax request and updates a progress bar. I need to be able to stop the call to this function when a call returned from ajax is "true".
Html:
<td class="checkbox">
<input type="checkbox" value="6" class="checkbox download" id="chk-6">
<div class="hide" id="prgbar-6"><span class="progresslabel"></span></div>
</td>
My function:
function getProgress(operationId) { // receives operationId
$.post("#Url.Action("Status","Packages")", { operationId: operationId }, function (data) {
if (data) {
for (var key in data) {
if ($("#prgbar-" + key + "").size() != 0) {
var objPrg = $("#prgbar-" + key + "");
var objchk = $("#chk-" + key + "");
if (data[key]) {
objPrg.find("span").text("downloading...").css("color:#000000");
objchk.hide();
objPrg.removeClass("hide").show().progressbar({
value: 0
});
var value = Math.floor(parseInt(data[key]) * 100);
objPrg.progressbar("option", "value", value);
objPrg.find("span").text(value + "%");
} else {
}
}
}
}
});
}
var interval = setInterval(function(){getProgress(operationId,interval)},1000);
In your $.POST complete callback function, clear this interval: {i use complete here but if you want to do only for successful request, use .success()}
$.post("#Url.Action("Status","Packages")", { operationId: operationId }, function (data) {
if (data) {
for (var key in data) {
if ($("#prgbar-" + key + "").size() != 0) {
var objPrg = $("#prgbar-" + key + "");
var objchk = $("#chk-" + key + "");
if (data[key]) {
objPrg.find("span").text("downloading...").css("color:#000000");
objchk.hide();
objPrg.removeClass("hide").show().progressbar({
value: 0
});
var value = Math.floor(parseInt(data[key]) * 100);
objPrg.progressbar("option", "value", value);
objPrg.find("span").text(value + "%");
} else {
}
}
}
}
}).complete(function() { clearInterval(interval); });
I like this method. It requires no clearing of intervals. It just runs on its own and sets a timeout if necessary.
var operationId = ...;
var processFunction = function () {
$.post("#Url.Action("Status","Packages")", { operationId: operationId }, function (data) {
if (data !== true) {
// your normal function stuff
setTimeout(processFunction, 1000);
}
});
};
setTimeout(processFunction, 1000);
Method #1:
You could just make a variable outside of the function called requestRunning and on calling getProgress it checks if requestRunning is true.
// Pseudo-code
var requestRunning = false;
if requestRunning === true => continue with getProgress
if requestRunning === false => stop firing getProgress
Method #2:
Use setInterval and on success of the request and clear the interval.
var progressHandle = setInterval(function(){getProgress(id)}, 1000);
$.ajax({
success: function() {
clearInterval(progressHandle);
}
});
I'd probably prefer the first option although progress checking through subsequent AJAX calls isn't really good.