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();
Related
Please check this on :
http://jsfiddle.net/wmaokqh3/
<div id="message">
</div>
<audio id="bgm" src="http://www.freesfx.co.uk/rx2/mp3s/9/10780_1381246351.mp3">
</audio>
<div id="count">
</div>
function Typer() {
var dfd = $.Deferred();
var srcText = 'EXAMPLE';
var i = -(1);
var result = '';
setInterval(function() {
if (i == srcText.length) {
clearInterval(this);
dfd.resolve();
};
$("#count").append('<br>i =' + i + ' , ');
i++;
result += srcText[i].replace("\n", "<br />");
$("#message").html(result + '---' + i + ' , ');
},
1000);
return dfd.promise();
}
function playBGM() {
var playsound = $.Deferred();
$('#bgm')[0].play();
$("#bgm").on("ended", function() {
playsound.resolve();
});
return playsound.promise();
}
function thirdFunction() {
alert('third function');
}
Typer().then(playBGM).then(thirdFunction);
Not sure where you learned to do clearInterval(this) but that is not correct. The this has nothing to do with the current interval. You need to use the generated id for the interval to cancel it.
var myInterval = window.setInterval( )
and in your code you need to use that id
clearInterval(myInterval)
You have to assign the setInterval to a variable in order to clear it later:
var result = '';
const myInterval = setInterval(function() {
if (i == srcText.length) {
clearInterval(myInterval);
So there is nothing in coding clearInterval(this)
clearInterval function needs a variable in the paranthesis in order to give it a variable you should set the interval function into a variable which should be like this var inter = window.setInterval(function() {}, 1000);
I've built a series of timers that are designed to be started, paused and resumed on cue. Numbers update dynamically on my page when the timer ticks up. The issue I'm having is figuring out how to get the timer to start from where it left off before I paused it. I can get it to restart from scratch, but I unsure how to take the paused Date.now() value, and work it into the formula to display the correct value. It will be something stupid that I just cant figure out.
function ticking2(num) {
//IF TIMER IS PAUSED CANCEL THE ANIMATION FRAME
if (timerObjArray[num].paused == true) {
timerObjArray[num].restartTime = Date.now();
cancelAnimationFrame(id);
} else if (timerObjArray[num].paused == false) {
timerObjArray[num].initialTime = Date.now()
if (timerObjArray[num].restartTime != 0) {
//THIS IS THE LINE WHERE I AM HAVING TROUBLE
timerObjArray[num].milli = ((timerObjArray[num].initialTime - timerObjArray[num].initialDate) - (timerObjArray[num].initialTime - timerObjArray[num].restartTime)) / 1000;
} else {
timerObjArray[num].milli = ((timerObjArray[num].initialTime - timerObjArray[num].initialDate ) / 1000);
}
//THIS FUNCTION TAKES THE MS VALUE AND CONVERTS IT TO HH:MM:SS
convert(num, timerObjArray[num].milli * 1000);
id = requestAnimationFrame(function() {
ticking2(num);
});
}
}
Thanks for the help.
I don't have enough information so, I made a simple implementation. You can look at this to help determine what you're missing. You're welcome to use it.
Timer fiddle
Utility:
var timer = (function() {
let _timers = {};
let pub = {
start : function(id) {
if(!_timers[id]) _timers[id] = {on:true, intervals:[{start:new Date()}] };
else if(_timers[id].on) throw 'timer is already started: ' + id;
else {
_timers[id].on = true;
_timers[id].intervals.push({start:new Date()});
}
},
stop : function(id) {
if(!_timers[id]) throw 'timer does not exist, cannot be stopped: ' + id;
else if(!_timers[id].on) throw 'timer is already stopped: ' + id;
else {
_timers[id].on = false;
let interval = _timers[id].intervals[_timers[id].intervals.length -1];
interval.stop = new Date();
interval.total = interval.stop - interval.start;
}
},
read : function(id) {
if(!_timers[id]) throw 'timer does not exist, cannot be read: ' + id;
let total = 0;
for(let i=0; i<_timers[id].intervals.length; i++) {
if(_timers[id].intervals[i].total) total += _timers[id].intervals[i].total;
else total += (new Date()) - _timers[id].intervals[i].start;
}
return { intervals:_timers[id].intervals, total: total };
},
delete: function(id) {
if(!_timers[id]) throw 'timer does not exist, cannot be deleted: ' + id;
delete _timers[id];
}
};
return pub;
})();
Example usage:
$('.start').on('click', function(){
timer.start(123);
});
$('.stop').on('click', function(){
timer.stop(123);
});
$('.clear').on('click', function(){
timer.delete(123);
$('input').val('');
});
setInterval(function(){
let result = null;
try//obviously not a great pattern
{
result = timer.read(123);
} catch(ex){}
if(result) {
$('input').val(result.total);
}
}, 35);
I am making my own version of simon Game, but the callback function inside click is not existing after user press wrong input. As a result function handler.patternRepeatPlayer() is getting called recursively for each element of array pattern.I want a solution to break from the else after callinghandler.patternRepeatPlayer just once. The program is working fine in strict mode, but only in non-strict mode inside else , I am not able to break from else.
-- can access the project on Git.
https://github.com/santosh1357/simonGame.git
The flow is like from html -> Function simonnGame.PatternGen from PatternGen -> handler.PatternRepeatPlayer -> PatternRepPlayer -> PatternMatcher -> userInput(here if wrong user input in non-strict mode) -> patternRepeatPlayer
This case is failing as in this case else is not existing after calling the function only once.
//Problematic Function.
userInput: function(){
var userPattern = new Array();var id;
$('img').click(function(){
id = parseInt(this.id,10); userPattern.push(id);handler.effect(id);
if(userPattern.indexOf(id) !== simonGame.PATTERN.indexOf(id)){
if($('.chkStrict:checked').val() === "on"){
var audio = new Audio('sounds/wrong.mp3');
audio.play();
setTimeout(function(){window.location.reload(true)},1000);
} else {
var audio = new Audio('sounds/wrong.mp3');
audio.play();
userPattern.length = 0;
handler.repeatFlag = true;
handler.patternRepeatPlayer(); ****//this is getting called recursivelly rather than quiting after calling once****
return ;
}
}
//End Problematic Functiom
I think there is some misunderstanding on how click callback functions work.
//Fullcode
var simonGame = {
COUNT: 0,
PATTERN: [],
SOUND:[{file:'sounds/sa.mp3'},{file:'sounds/re.mp3'},{file:'sounds/ga.mp3'},{file:'sounds/ma.mp3'},{file:'sounds/pa.mp3'},{file:'sounds/dha.mp3'},{file:'sounds/nee.mp3'}],
patternGen: function(){
var randomId;
randomId = Math.floor(Math.random() * 7);
simonGame.PATTERN.push(randomId);
if(simonGame.COUNT > 20){
alert("You have won the game!!");
window.location.reload(true);
}
simonGame.COUNT += 1;
//debugger;
//console.log("increase count true calling count display " + simonGame.COUNT);
handler.countDisplay();
//console.log("count gen true calling patternPlayer with PATTERN " + simonGame.PATTERN );
handler.patternRepeatPlayer();
}, //close patternGen
patternMatcher: function(genPattern){
//console.log("inside patternMatch");
var genPattern = simonGame.patternGen;
//setTimeout(function(){
//console.log("PATEERN: " + simonGame.PATTERN + "COUNT " + simonGame.COUNT );
//calling user input
console.log("calling user Input");
handler.userInput();
setTimeout(function(){
if(handler.repeatFlag === false){ //execute count gen only if repeat flag is false inside user INPUT
genPattern();
}
},simonGame.COUNT*2000);
//console.log("pattern check true, calling pattern gen");
//},simonGame.COUNT*5000); //c`enter code here`lose setTimeout
}, //close patternMatcher
} //close simonGame
var handler = {
countRepPlayer: 0,
repeatFlag: false,
patternRepeatPlayer: function(){
var repeater = setInterval(function(){
handler.effect(simonGame.PATTERN[handler.countRepPlayer]);
handler.countRepPlayer += 1;
if(handler.countRepPlayer > simonGame.COUNT){
clearInterval(repeater);
//setTimeout(function(){
simonGame.patternMatcher();
//},1000);
handler.countRepPlayer = 0;
}
},1000);//close sestInterval
}, //close patternRepeatPlayer
effect: function(id){
var img = document.getElementById(id);
if(img !== null && id !== undefined){
$( img ).fadeIn(100).fadeOut(100).fadeIn(100);//fadeOut(200).fadeIn(200);
//debugger;
var audio = new Audio(simonGame.SOUND[id].file);
audio.play();
//console.log("id inside effect " + id)
}
},//close effect
countDisplay: function(){
document.getElementById("count").innerHTML = "Count: " + simonGame.COUNT;
}, //close countIncrease
userInput: function(){
var userPattern = new Array();var id;
$('img').click(function(){
id = parseInt(this.id,10);
userPattern.push(id);
handler.effect(id);
console.log(" user " + userPattern);
console.log(" pattern " + simonGame.PATTERN);
if(userPattern.indexOf(id) !== simonGame.PATTERN.indexOf(id)){
console.log(" WRONG USER INPUT ");
if($('.chkStrict:checked').val() === "on"){
var audio = new Audio('sounds/wrong.mp3');
audio.play();
setTimeout(function(){window.location.reload(true)},1000);
} else {
console.log("inside else " );
var audio = new Audio('sounds/wrong.mp3');
audio.play();
userPattern.length = 0;
handler.repeatFlag = true;
handler.patternRepeatPlayer(); ****//this is getting called recursivelly rather than quiting after calling once**.**
return ;
}
}
//reset the userPattern Array
if(userPattern.length === simonGame.PATTERN.length){
userPattern.length = 0;
}
}); //close click.
}
} //close handler
Yes, It will be called recursively, because you set interval for it.
Here you can modify your code:
patternRepeatPlayer: function(){
var repeater = setInterval(function(){
handler.effect(simonGame.PATTERN[handler.countRepPlayer]);
handler.countRepPlayer += 1;
if(handler.countRepPlayer > simonGame.COUNT){
clearInterval(repeater);
//setTimeout(function(){
simonGame.patternMatcher();
//},1000);
handler.countRepPlayer = 0;
}
},1000);//close sestInterval
}
To: (EDITED)
function myCallbackFunction(repeater){
handler.effect(simonGame.PATTERN[handler.countRepPlayer]);
handler.countRepPlayer += 1;
if(handler.countRepPlayer > simonGame.COUNT){
clearInterval(repeater);
simonGame.patternMatcher();
handler.countRepPlayer = 0;
}
}
patternRepeatPlayer: function(){
var repeater = setInterval(function() {myCallbackFunction(repeater);}, 1000);
}
And where you need to call it once, just call myCallbackFunction(repeater)
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
jQuery is giving me this error
Uncaught TypeError: Cannot call method 'toLowerCase' of undefined
and I it began to appear when I added this keypress event handler on my input.
The input is being switched from a div to a text field, but whenever I do so, I call my bindHandlers function.
Here is the whole code:
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
}
function leadingZero(num) {
return num < 10 ? '0'+num:num;
}
function bindHandlers() {
$('div.city').click(function() {
$(this).replaceWith('<input type="text" class="city input" value="'+$(this).text()+'" />');
bindHandlers();
});
$('.city.input').blur(function() { changeCity(); });
$('.city.input').keypress(function(e) { if(e.keyCode == 13) changeCity(); });
}
function changeCity() {
clearTimeout(weatherTimeout);
window.city = $(this).val();
$(this).replaceWith('<div class="city">'+window.city+'</div>');
bindHandlers();
}
function loadWeatherData(city) {
$.getScript('http://api.openweathermap.org/data/2.5/weather?q='+city+'&callback=updateWeather&units=metric');
console.log('Getting weather for city "'+city+'"');
}
function updateTime() {
var d = new Date(),
hours = leadingZero(d.getHours()),
minutes = leadingZero(d.getMinutes()),
seconds = leadingZero(d.getSeconds()),
week = leadingZero(d.getWeek()),
date = leadingZero(d.getDate()),
month = leadingZero(d.getMonth()+1),
year = d.getFullYear().toString().substring(2),
dateString = '<div>'+hours+':'+minutes+':'+seconds+'<br />w'+week+' '+date+'-'+month+'-'+year+'</div>';
$('.date').html(dateString);
setTimeout(updateTime, 1000);
}
function updateWeather(data) {
console.log(data);
$('.weather').fadeOut(function() {
$('.temp').html(data.main.temp+'°');
$('.humid').html(data.main.humidity+'%');
for(var i = 0; i < data.weather.length; i++) {
function wIcon(data) {
switch(data) {
case 'Clear':
return 'ò';
break;
case 'Drizzle':
case 'Rain':
return 'õ';
break;
case 'Thunderstorm':
return 'ú';
break;
case 'Snow':
return 'û';
break;
case 'Clouds':
return 'ö';
break;
}
};
var icon = wIcon(data.weather[i].main);
console.log(icon);
$('.weather-icon').html('');
$('.weather-icon').append('<i data-icon="'+icon+'" title="'+data.weather[i].description+'"></i>')
$('.wind-speed').html(data.wind.speed+' m/s');
}
weatherTimeout = setTimeout(function() {
loadWeatherData();
}, 30 * 1000);
$(this).fadeIn(function() { $('.wind-deg').rotate(data.wind.deg); });
});
}
$(function() {
var city = 'Roskilde', weatherTimeout;
loadWeatherData(city);
updateTime();
bindHandlers();
});
Aah.. found the issue, since I both had blur and keypress, I made a function for them so my code didn't get repetitive, when I made the function, I forgot to parse the $(this) to the function, so it had no idea what I meant by $(this). Code is now as follows:
function bindHandlers() {
$('div.city').click(function() {
$(this).replaceWith('<input type="text" class="city input" value="'+$(this).text()+'" />');
bindHandlers();
});
$('.city.input').blur(function() { changeCity(this); });
$('.city.input').keypress(function(e) { if(e.keyCode == 13) changeCity(this); });
}
function changeCity(el) {
window.city = $(el).val();
$(el).replaceWith('<div class="city">'+window.city+'</div>');
clearTimeout(weatherTimeout);
loadWeatherData(window.city);
localStorage.setItem('city', window.city);
bindHandlers();
}
Conclusion: When moving code into a function, make sure that the function still get the dependent variables from the previous location.