I seem to be having quite a simple error that I cannot seem to figure out. I have two functions. One that allows for a timed iteration through an array (slow iteration) and another that just combines the items in the array into a sentence (testfunction). I want these two functions to be called in a while loop so that the while loop will continually run between times in the day (this is the Now_time variable).
If i run the code without the while loop it runs correctly. As soon as I introduce the while loop it only iterates the first element and not continuously through the array using the functions.
Any suggestions?
//Sample array
var data = [
{Name:"Cape Town",City_Type:"Seaside"}
,
{Name:"Johannesburg",City_Type:"Inland"}
,
{Name:"Durban",City_Type:"Seaside"}
,
{Name:"Bloemfontein",City_Type:"Inland"}
];
// Slowly iterates through a given array
function slowArrayIterate(array, iterateFunc, start, speed) {
iterateFunc(array[start], start, array);
if (typeof array[start + 1] !== 'undefined') {
setTimeout(function() {
slowArrayIterate(array, iterateFunc, start + 1, speed, done);
}, speed);
} else {
done();
}
}
// Forms the sentence from the elements in the array
function testfunction(a,b){
var complete = a +" is a " + b +" city.";
console.log(complete);
}
// Gets the time of the day
var myDate = new Date(Date.now());
var time_now = myDate.toString().substring(16,24);
var here = time_now;
var there = time_now;
var everywhere = time_now;
var now = here.substring(0,2)+ there.substring(3,5) + here.substring(6,8);
var Now_time = parseFloat(now);
while (Now_time >= 73000 || Now_time <=170000) {
console.log("working");
// Calls the fucntion to slowly iterate
slowArrayIterate(data, function(arrayItem) {
console.log(arrayItem.Name);
console.log(arrayItem.City_Type);
// Calls the fucntion to form a sentence on the console log
testfunction(arrayItem.Name , arrayItem.City_Type);
}, 0, 1000);
// refreshes the time to see if it should still be running
myDate = new Date(Date.now());
var time_now = myDate.toString().substring(16,24);
var here = time_now;
var there = time_now;
var everywhere = time_now;
var now = here.substring(0,2)+ there.substring(3,5) + here.substring(6,8);
var Now_time = parseFloat(now);
console.log(Now_time);
}
There is error in the "done" function you are passing - include it inside the function call as :-
var data = [
{Name:"Cape Town",City_Type:"Seaside"}
,
{Name:"Johannesburg",City_Type:"Inland"}
,
{Name:"Durban",City_Type:"Seaside"}
,
{Name:"Bloemfontein",City_Type:"Inland"}
];
// Slowly iterates through a given array
function slowArrayIterate(array, iterateFunc, start, speed, done) {
iterateFunc(array[start], start, array);
if (typeof array[start + 1] !== 'undefined') {
setTimeout(function() {
slowArrayIterate(array, iterateFunc, start + 1, speed, done);
}, speed);
} else {
done();
}
}
// Forms the sentence from the elements in the array
function testfunction(a,b){
var complete = a +" is a " + b +" city.";
console.log(complete);
}
// Gets the time of the day
var myDate = new Date(Date.now());
var time_now = myDate.toString().substring(16,24);
var here = time_now;
var there = time_now;
var everywhere = time_now;
var now = here.substring(0,2)+ there.substring(3,5) + here.substring(6,8);
var Now_time = parseFloat(now);
while (Now_time >= 73000 || Now_time <=170000) {
console.log("working");
// Calls the fucntion to slowly iterate
slowArrayIterate(data, function(arrayItem) {
console.log(arrayItem.Name);
console.log(arrayItem.City_Type);
// Calls the fucntion to form a sentence on the console log
testfunction(arrayItem.Name , arrayItem.City_Type);
}, 0, 1000, function() { //problem was here
// stuff to do when finished (not important for now)
console.log("Done");
});
// refreshes the time to see if it should still be running
myDate = new Date(Date.now());
var time_now = myDate.toString().substring(16,24);
var here = time_now;
var there = time_now;
var everywhere = time_now;
var now = here.substring(0,2)+ there.substring(3,5) + here.substring(6,8);
var Now_time = parseFloat(now);
console.log(Now_time);
}
Related
so, i have a for loop that I want to run multiple set timeouts at once so it can continually check if it is a certain time for multiple times. i can't just check for all multiple times all at once, the check needs to repeat after different amounts of time. it only continues to repeat the last iteration of the loop, the last dict in lat.
my approach simplified a bit:
lat = list of dictionaries with some values that differentiate them + times
for(i = 0; i< lat.length; i++){
if(lat[i][differentiate value]) = {
function checktime(){
if(currenttime != lat[i]){
setTimeout(checktime,30000)
}
else{
console.log("yay the time is right!")
}
}
else if(lat[i][differentiate value]) = {
function checktime(){
if(currenttime != lat[i]){
setTimeout(checktime,50000)
}
else{
console.log("yay the time is right!")
}
}
}
How would I go about making this (its for a notification app)
original code:
(each value in later looks like [[75,null,[7,28,2021]], null,[[9,52,"p"]],"e&r"] with the amount of notifications, a preset date, the date for these reminders to be on, by time, which would be the first if, and the array of at times. for testing I had 2 laters with 2 different at times):
chrome.storage.sync.get('later', function(data){
if (data.later !== null){
var lat = data.later;
for(i = 0; i< lat.length; i++){
var currentDict = lat[i];
if(currentDict['notis'][1] !== null){
console.log("cheese")
var by = currentDict['notis'][1];
console.log(by)
const d = new Date();
var hr = d.getHours();
var min = d.getMinutes();
var sec = d.getSeconds();
var da = currentDict['notis'][0][2][1];
var mo = currentDict['notis'][0][2][0];
var ye = currentDict['notis'][0][2][2]
var h = by[0];
var m = by[1];
var ampm = by[2];
if(ampm == "p"){
h = h + 12;
}
var byMS = h*3600000 + m*60000;
var currentMS = hr*3600000 + min*60000 + sec*1000;
//check if right date then check if time is lesss than
function checkdate(){
var day = d.getDate();
var month = d.getMonth() + 1;
var year = d.getFullYear();
if(da == day && mo == month && ye == year){
var amt = 0;
function checktime(){
if(byMS >= currentMS){
//noti and delete
var int = setInterval(function(){
chrome.notifications.create({
title: currentDict['name'],
message: "do da " + currentDict['name'],
iconUrl: "logo.png",
type: "basic"
})
amt++
console.log(amt)
const dddd = new Date();
console.log(dddd.getMinutes() + " / " + dddd.getSeconds())
if(amt >= currentDict['notis'][0][0]){
clearInterval(int)
console.log("done")
//ju finish taht
console.log(lat)
lat.splice(lat.indexOf(currentDict),1)
console.log(lat)
chrome.storage.sync.set({'later': lat})
}
}, (byMS-currentMS)/currentDict['notis'][0][0])
}
else{
setTimeout(checktime,30000)
}
}
checktime();
}
else{
setTimeout(checkdate,66400000)
}
}
checkdate();
}
else if(currentDict['notis'][2] !== null){
console.log("cheese")
var at = currentDict['notis'][2];
console.log(at)
var arrayat = [];
for(j = 0; j<= at.length-1; j++){
var atcycle = at[j];
console.log(atcycle)
const ddd = new Date();
var hr = ddd.getHours();
var min = ddd.getMinutes();
var da = currentDict['notis'][0][2][1];
var mo = currentDict['notis'][0][2][0];
var ye = currentDict['notis'][0][2][2]
var hrat = atcycle[0];
var minat = atcycle[1];
var ampm = atcycle[2];
if(ampm == "p"){
hrat = hrat + 12;
}
console.log(hrat + "/" + minat + "/" + ampm)
if(hr <= hrat){
var temparray = [];
temparray.push(hrat)
temparray.push(minat)
arrayat.push(temparray);
console.log(arrayat)
}
else if(hr == hrat){
if(min<minat){
var temparray = [];
temparray.push(hrat)
temparray.push(minat)
arrayat.push(temparray);
console.log(arrayat)}
}
}
console.log(arrayat.length)
function checkdate(){
console.log(arrayat.length)
console.log("date")
const d = new Date();
var day = d.getDate();
var month = d.getMonth() + 1;
var year = d.getFullYear();
if(da == day && mo == month && ye == year){
function check(){
console.log(arrayat.length)
console.log("check")
for(l=0; l<arrayat.length; l++){
console.log(arrayat.length)
const dd = new Date();
var hr = dd.getHours();
var min = dd.getMinutes();
console.log(arrayat[l][1])
console.log(min)
if(arrayat[l][0] == hr && arrayat[l][1] == min ){ //at one of the times
console.log(arrayat)
arrayat.splice(l,1)
console.log(arrayat)
if(arrayat.length == 0){
lat.splice(lat.indexOf(currentDict),1)
chrome.storage.sync.set({'later': lat})
console.log(lat)
}
chrome.notifications.create({
title: currentDict['name'],
message: "do da " + currentDict['name'],
iconUrl: "logo.png",
type: "basic"
})
//add noti with name and delete it
console.log(arrayat)
check();
}
}
console.log(arrayat.length)
if(arrayat.length !== 0){
console.log("and repeat")
setTimeout(check,15000);//SETINTERVAL INSTEAD? ANDCLEAR
}
}
check();
}
else{
setTimeout(checkdate,66400000)
}
}
checkdate();
}
}
}
})
}
This is the wrong approach. You know the times, so you know how far off they are in time. You don't need to check over and over again if the time has arrived. Instead work out how many milliseconds until the time in question, then set a timeout for that time.
You basically need to pass different functions to each setTimeout():
function checktime1(){
if(currenttime != lat[i]){
setTimeout(checktime1,30000)
}
else{
console.log("yay the time is right!")
}
}
function checktime2(){
if(currenttime != lat[i]){
setTimeout(checktime2,50000)
}
else{
console.log("yay the time is right!")
}
}
However, this is obviously not scalable. If you have lots of timeouts you will be writing lots of duplicate functions. Worse, if you have a dynamic number of timeouts this won't solve your problem.
Fortunately, javascript lets us declare functions inside another function:
function checktime(timeout){
function loop () {
if(currenttime != lat[i]){
setTimeout(loop,timeout)
}
else{
console.log("yay the time is right!")
}
}
loop();
}
This allows you to dynamically create functions as needed:
checktime(30000);
checktime(50000);
If you need to pass arguments to each timeouts (eg. if you need to display custom alerts) you can just pass it to your outer function and it will be captured in a closure:
function checktime(timeout, message){
function loop () {
if(currenttime != lat[i]){
setTimeout(loop,timeout)
}
else{
console.log(message)
}
}
loop();
}
Then you can do:
checktime(30000, "Yay, the time is right for timer 1");
checktime(50000, "Yay, the time is right for timer 2");
Similarly, if you need to execute custom logic for each timer you can also pass it as an argument (callback):
function checktime(timeout, callback){
function loop () {
if(currenttime != lat[i]){
setTimeout(loop,timeout);
}
else{
console.log("yay the time is right!");
callback(); // <----------------- execute custom logic
}
}
loop();
}
Which you can use like:
checktime(30000, () -> console.log("TIMER 1"));
checktime(50000, () -> alert("TIMER 2"));
Am trying to achieve a dynamic count of certain node if defined:
This works but its not dynamic, you have to call sum().
app.factory("ArrayWithSum", function($firebaseArray) {
return $firebaseArray.$extend({
sum: function() {
var total = 0;
var todayDate = new Date();
var start = todayDate.setHours(0,0,0,0);
var end = todayDate.setHours(23,59,59,999);
// the array data is located in this.$list
angular.forEach(this.$list, function(rec) {
if (angular.isDefined(rec.qa)){
if (angular.isDefined(rec.qa.completed)) {
if (rec.qa.completed >= start && rec.qa.completed <= end){
total++;
}
}
}
});
return total;
}
});
});
I tried $$update but can't access this_counter in array:
app.factory("counter", function($firebaseArray) {
return $firebaseArray.$extend({
sum: function() {
return this._counter;
},
$$updated: function(){
var changed = $firebaseArray.prototype.$$updated.apply(this, arguments);
var todayDate = new Date();
var start = todayDate.setHours(0,0,0,0);
var end = todayDate.setHours(23,59,59,999);
if( !this._counter ) {
this._counter = 0;
}
// the array data is located in this.$list
angular.forEach(this.$list, function(rec) {
if (angular.isDefined(rec.qa)){
if (angular.isDefined(rec.qa.completed)) {
if (rec.qa.completed >= start && rec.qa.completed <= end){
this._counter++;
}
}
}
});
return changed;
}
});
});
Does anyone know how to make a dynamic variable that I can update and access?
Thanks
Got it working with $firebaseObject. Obviously you can add a property _counter to an object not an array. Any way this works and a good way to get a dynamic count.
app.factory("counter", function($firebaseObject) {
return $firebaseObject.$extend({
$$updated: function(){
var changed = $firebaseObject.prototype.$$updated.apply(this, arguments);
if( !this._counter ) { this._counter = 0; }
var total = 0;
var todayDate = new Date();
var start = todayDate.setHours(0,0,0,0);
var end = todayDate.setHours(23,59,59,999);
// the array data is located in this.$list
angular.forEach(this, function(rec) {
if (angular.isDefined(rec.qa)){
if (angular.isDefined(rec.qa.completed)) {
if (rec.qa.completed >= start && rec.qa.completed <= end){
total++;
}
}
}
});
this._counter = total;
return changed;
}
});
});
vm.panels = new counter(panelsRef);
{{vm.panels._counter}}
Am having issues with watches not firing after a long duration on IE11. So thought I'd try this approach.
I am a beginner at js and have a project due by the end of day. I have to display an array with temps added and have set up an object to hold this array. My problem is that the message won't display and the for statement doesn't increment. When passed through both the var i and count come back undefined. I know there is a lot missing from this code but at this point I have tried to stream line it so that I can debug this issue. The date I will deal with later.
Here is my code:
var temps = [];
function process() {
'use strict';
var lowTemp = document.getElementById('lowTemp').value;
var highTemp = document.getElementById('highTemp').value;
var output = document.getElementById('output');
var inputDate = (new Date()).getTime();
var temp = {
inputDate : inputDate,
lowTemp : lowTemp,
highTemp : highTemp
};
var message = '';
if (lowTemp == null) {
alert ('Please enter a Low Temperature!');
window.location.href = "temps.html";
} else if (highTemp == null) {
alert ('Please enter a High Temperature!');
window.location.href = "temps.html";
} else {
lowTemp = parseFloat(lowTemp, 10);
highTemp = parseFloat(highTemp, 10);
}
if (temp.value) {
temps.push(temp.inputDate, temp.lowTemp, temp.highTemp)
var message = '<h2>Temperature</h2><ol>';
for (var i = 0, count = temps.length; i < count; i++) {
message += '<li>' + temps[i] + '</li>'
}
message += '</ol>';
output.innnerHTML = message;
}
return false;
}
function init() {
'use strict';
document.getElementById('theForm').onsubmit = process;
}
window.onload = init;
Here is my new code:
var temps = [];
function process() {
'use strict';
var lowTemp = document.getElementById('lowTemp').value;
var highTemp = document.getElementById('highTemp').value;
var output = document.getElementById('output');
var inputDate = (new Date()).getTime();
var temp = {
inputDate : inputDate,
lowTemp : lowTemp,
highTemp : highTemp
};
var message = '';
if (lowTemp == null) {
alert ('Please enter a Low Temperature!');
window.location.href = "temps.html";
} else if (highTemp == null) {
alert ('Please enter a High Temperature!');
window.location.href = "temps.html";
} else {
lowTemp = parseFloat(lowTemp, 10);
highTemp = parseFloat(highTemp, 10);
}
if (temp.value) {
temps.push(temp.inputDate, temp.lowTemp, temp.highTemp)
var message = '<h2>Temperature</h2><ol>';
for (var i = 0, count = temps.length; i < count; i++) {
message += '<li>' + temps[i] + '</li>'
}
message += '</ol>';
output.innnerHTML = message;
}
return false;
}
function init() {
'use strict';
document.getElementById('theForm').onsubmit = process;
}
window.onload = init;
There are some big issues with your code:
You should never compare anything to NaN directly. The correct comparison should be:
if (isNaN(lowTemp)) {
You're using curly braces when not needed. You should remove both curly braces:
{window.location.href = "temps.html";}
The function parseFloat expects only one parameter: the string to be converted. You're probably confusing it to parseInt which expects both the string and the radix of the conversion.
You're using the temp's property value, but you have never setted it, so, the condition where you check if it exists will always return false, and the push method that you want to debug will never be called, since it's inside that if statement.
Finally, you're closing a li tag at the end, but you have never opened it. You should probably be closing the ol tag you have opened in the begining.
The rest of your code seems pretty OK for me.
Talking about debugging, you should read the Google Chrome's Debugging Javascript Tutorial.
I am attempting to create a ticker that fades in and out the objects in an array using the jQuery fadeIn/fadeOut function. I referenced someone else's code and was able to get it working for the most part. What I would like to do now is get the list property of listTicker to update every X number of seconds and move to the next array. I assume I must use a for loop somehow but I just cant seem to figure out how to implement it.
Below is what I was able to get working:
var listTicker = function(options) {
var defaults = {
list: [],
startIndex:0,
interval: 3 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function(index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value= options.list[index];
options.trickerPanel.fadeOut(function() {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function() {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
};
var textlist = new Array("Saab", "Volvo", "BMW");
var textlist2 = new Array("Dell", "HP", "Toshiba");
var textlist3 = new Array("John", "Dave", "Greg");
var currentlist = new Array(textlist, textlist2, textlist3);
$(function() {
listTicker({
list: currentlist[0] ,
startIndex:0,
trickerPanel: $('#expression'),
interval: 3 * 1000,
});
});
Not 100% happy with the organization/separation of this code, but it achieves the objective:
http://jsfiddle.net/49Y8s/
options.trickerPanel.fadeOut(function() {
$(this).html(value).fadeIn();
var nextItemIndex = (index+1) < currentList.length ? (index+1) : 0;
var nextListIndex = (function(){
var val = listIndex;
if(nextItemIndex==0){
val = listIndex+1;
}
if(val >= options.lists.length){
val = 0;
}
return val;
})();
setTimeout(function() {
listTickerInner(nextListIndex,nextItemIndex);
}, options.interval);
});
I am working on a simple blackjack program. I am completely new to javascript and am having trouble debugging my program. I keep getting the TypeError: cannot call getNumber method of undefined..... and i'm totally lost. I am trying to get the numerical value stored for each card but it appears thats the error is happening in my printHand() method inside the Hand class. When printing out the hand of two or more cards, I loop through each card in the hand calling cards[i].getNumber() where cards[] is the array of cards in each hand. Am i not referencing cards[] properly? I double checked to make sure my methods and variables were set to public but I still cannot figure out why getNumber() is being called on an undefined object. Is there something wrong with the way I am referencing this object?
Here is my code:
// Card Constructor
function Card (suit, number){
var the_suit = suit;
var the_number = number;
this.getNumber = function(){
return the_number;
};
this.getSuit = function(){
return the_suit;
};
this.getValue = function (){
// face cards
if(the_number > 10){
return 10;
// aces
} else if (the_number < 2){
return 11;
// other cards
} else {
return the_number;
}
};
}
function deal (){
// get card suit
var rand1 = Math.floor(Math.random ( ) * 4 + 1);
// get car number
var rand2 = Math.floor(Math.random ( ) * 13 + 1);
var newCard = new Card(rand1, rand2);
}
function Hand (){
// create two cards for initial hand
var card1 = deal();
var card2 = deal();
// store cards in array
var cards = [card1,card2];
// getter
this.getHand = function (){
return cards;
};
// get the score
this.score = function(){
var length = cards.length;
var score = 0;
var numAces = 0;
for(i = 0; i < length; i++){
if (cards[i].getValue() === 11 ){
numAces++;
}
score += cards[i].getValue();
}
while(score > 21 && numAces !== 0){
sum -= 10;
numAces--;
}
};
this.printHand = function(){
var length = cards.length;
for(i=0; i< length; i++){
var string = string + cards[i].getNumber() + " of suit " + cards[i].getSuit() + ", ";
}
return string;
};
this.hitMe = function(){
var newCard = deal();
cards.push(newCard);
}
}
function playAsDealer(){
var newHand = new Hand();
while(newHand.score < 17){
newHand.hitMe();
}
return newHand;
}
function playAsUser(){
var newHand = new Hand();
var choice = confirm("Current hand: "+ newHand.printHand() + ": Hold (Ok) or Stand(Cancel)");
while(choice){
newHand.hitMe();
choice = confirm("Current hand: "+ newHand.printHand() + ": Hold (Ok) or Stand(Cancel)");
}
}
function declareWinner(user, dealer){
//user wins case
if (user.score > dealer.score){
console.log("You are the Champion!");
}
// tie game
else if(user.score===dealer.score){
console.log("Tied!");
}
else{
console.log("Loser!!");
}
}
function playGame (){
var user = playAsUser();
var dealer = playAsDealer();
console.log("User's Hand: " + user.printHand());
console.log("Dealer's Hand: " + dealer.printHand());
declareWinner();
}
playGame();
You don't return the card object in the function "deal":
should be:
function deal (){
// get card suit
var rand1 = Math.floor(Math.random ( ) * 4 + 1);
// get car number
var rand2 = Math.floor(Math.random ( ) * 13 + 1);
var newCard = new Card(rand1, rand2);
return newCard;
}
There are a few probs, but to get you started:
The error i got was "TypeError: cards[i] is undefined". Since you are calling your deal() function like this:
var card1 = deal();
You'll need to return the card in the deal func, so change
var newCard = new Card(rand1, rand2);
to
return new Card(rand1, rand2);
You'll also need to convert : cards[i].getNumber() to a string when you print the hand