Generate random number every x seconds and display it - javascript

Inside my App I have a sort of bottom bar Always shown, where I have a div with an h1, and a button. Everytime I click the button I coded and animation that do change the text of the h1 with a random number. Till here everything works fine.
My goal is to make this thing WITHOUT pressing a button, but just every x seconds during all the App execution. I tried to use "setInterval(func, ms);" I didn't get any error, but it just did it one time.
I think that my error is "where to put" the code. I don't understand this. So, I tried to put the code on the event handler of my button just to see if it works, but it did it one time anyway. I need that this function continues to be executed while the users do something else... It's like a clock inside an app: it should work continuosly while you do something else.
My function code:
function fraseCasuale(sel) {
var i = 1 + Math.floor(Math.random() * (groupedItems.length-1));
var oggetto = groupedItems.getAt(i);
if (sel === 1) {
document.getElementById("frasecasuale").textContent = oggetto.frase;
document.getElementById("autore").textContent = oggetto.nome;
document.getElementById("genere").textContent = oggetto.genere;
} else {
document.getElementById("frasecasuale2").textContent = oggetto.frase;
document.getElementById("autore2").textContent = oggetto.nome;
document.getElementById("genere2").textContent = oggetto.genere;
}
}
And then how I call it, for example:
setInterval(fraseCasuale(1), 5000);
My application is based on the grid template of Visual Studio 2012 for Windows Store aps. I added the bar I was talking above into "default.html", which is the container of the other pages.

Are you sure something like this doesn't work?
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var ms = 2000;
var func = function () {
var randNum = getRandomInt(1, 253); // Gets random number between 1 and 253
document.getElementById("element_id").innerHTML = randNum;
};
setInterval(func, ms);
http://jsfiddle.net/FQSAH/1/

The problem in your code is that you aren't passing a function to setInterval, you are passing the ONE TIME result of the function call fraseCasuale(1), so the result of that function is what is being passed to setInterval.
Since you want to pass a parameter to it, setTimeout lets you specify arguments after the function pointer and timeout interval, such as:
setInterval(fraseCasuale,5000,1);
If you are doing this in a defined 'Page' you'd do something like this in home.js
WinJS.UI.Pages.define("/pages/home/home.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
setInterval(this.fraseCasuale, 1000, 656);
},
fraseCasuale: function (sel) {
console.log(sel);
var i = 1 + Math.floor(Math.random() * (4 - 1));
var element = document.getElementById("updateMe");
element.textContent = i;
}
});
or if just using a default.js then you can throw your code there in app.ready, right above for ex. app.oncheckpoint (order doesn't actually matter above or below any function, just providing a place to show you an example)
So in default.js:
app.onready = function (args) {
//1 is a placeholder for your parameter
setInterval(fraseCasuale,5000,1);
};

This should work...
var id = window.setInterval(function(){randomNumber()},1000);
function randomNumber()
{
var rand = Math.floor(Math.random()*6)
//Do whatever you want with that number
}
Quick JSBin : http://jsbin.com/egajog/1/

Related

How do I have an onclick function change the properties of another onclick function?

To help visualize what I'm after. I have a button with an onclick() that increments the value of an input by 1
\\ HTML looks like this
<button class="clickme" onclick="pluspotato()">Potato</button>
<script>
var potatocount = 0;
function pluspotato() {
potatocount = potatocount + 1;
document.getElementById("potatonum").value = potatocount;
document.title = potatocount + " Potatoes";
}
</script>
Now I want to add a button that will change the property of the pluspotato() function to multiply by 2.
Any help would be greatly appreciated.
If youd like to solve this properly (so that it scales for further enhancements / development) id suggest you read up on Observables. Im am going to write a simple implementation of one and explain it here.
Since you want to change a value at multiple points in your code and read it potentially at multiple points youd have to come up with some sort of interface that allows participants (eg gui elements) to listen to changes made to it (and uptdate the gui accordingly).
Since this is a quite often needed functionality it is best to write an generally applieable solution for this. Like this Class:
class Observable {
constructor(initalValue) {
// here come the subscriptions / perticepants that want to listen to changes
this.listeners = []
// this is the actual wrapped value. Which can basically be anything. The only
// important thing is that nothing changes this property outside of this class.
// A convention is to mark those properties / functions with an underscore.
this._value = initalValue
}
setValue(value) {
// first check if the current value is not already the same as the new one.
// if so: just do nothing
if (this._value === value) return
// then set the stored value (so that it can be getted)
this._value = value
// loop through all listeners and call them with the now value
for (let i = 0; i < this.listeners.length; i++) {
this.listeners[i](value)
}
}
getValue() {
return this._value
}
subscribe(func) {
// add new listeners to array so that it gets called on setValue
this.listeners.push(func)
// Optional:
// call added function immediately with current value
func(this._value)
}
unsubscribe(func) {
//should also exist
}
}
This class now allows you to add such behaviour.
let observableCounter = new Observable(0)
function incrementClick() {
observableCounter.setValue(observableCounter.getValue() + 1)
}
function doubleClick() {
observableCounter.setValue(observableCounter.getValue() * 2)
}
// then simply listen to changes everywhere you want the gui to update
function update1(value) {
console.log("Updateing GUI to " + value)
// document.getElementById()...
// Side note: dont document.getElementById here. If the element doesnt change,
// getElement once outside update1 and then simply take the reference here.
// This way on every change the element needs to be found from scartch.
}
observableCounter.subscribe(update1)
You can change the element's onclick function to a function that multiplies.
function multpotato() {
potatocount *= 2;
document.getElementById("potatonum").value = potatocount;
document.title = potatocount + " Potatoes";
}
document.getElementById("change").addEventListener("click", function() {
document.querySelector(".clickme").onclick = multpotato;
});
You may do conditional operation in pluspotato() depending on activation of the second button:
var potatocount = 0;
var operation = 'add1';
function pluspotato() {
let potatocount;
if(operation === 'multiply2') {
potatocount = Number(document.getElementById("potatonum").value) * 2;
}
else{
potatocount = Number(document.getElementById("potatonum").value) + 1;
}
document.getElementById("potatonum").value = potatocount;
document.title = potatocount + " Potatoes";
}
function changePluspotato() {
operation = 'multiply2';
}
<button class="clickme" onclick="pluspotato()">Potato</button>
<input id="potatonum"></input><br>
<button id="change" onclick="changePluspotato()">changePluspotato</button>
Once you click the second button, the potato button starts to multiply by 2

How can I change this into a loop instead of a recursive function?

So I have a piece of code like
var barlen = $('#SSWEprogressbar').width(),
$elems = $('[data-srcurl]'),
k = 0,
n = $elems.length;
LoadImage();
function LoadImage()
{
var $elem = $($elems[k]);
var img = new Image(),
url = $elem.attr('data-srcurl');
$(img).load(function(){
$('#SSWEloaderfront').attr('src',url);
$('#SSWEloadprogress').width((k+1)/n*barlen + "px");
var srctgt = $elem.attr('data-srctgt');
// change url to src attribute or background image of element
if ( srctgt == "srcattr" ){ $elem.attr('src',url); }
else if ( srctgt == "bgimg" ) { $elem.css('background-image',"url("+url+")"); }
// decide whether to exit the
if ( ++k == n ) { AllyticsSSWEPlayerShow(); }
else { LoadImage(); }
});
img.src = url;
}
and the reason I have it written that way is because load callback needs to be called before the stuff in the function can be executed again. If possible, I'd like to change this from a recursive function to a loop, but I don't know how to do that because there's no way to make a for or while loop "wait" before going on to the next iteration. Or is there?
As I mentioned in the comment you can easily resolve your problem, by using setTimeout(LoadImage, 100); in the else instead of calling the function directly. The 2nd parameter is the delay in ms.
If you understand why setTimeout(LoadImage, 0); is not stupid and not the same as calling the function directly then you understood setTimeout. It puts the function call in the queue, this means other events like clicks or keys that were pressed can be processed before the function is called again and the screen doesn't freeze. It's also impossible to reach max recursion like this, the depth is 1.

Variable in setInterval only increments the first time

I have a simple script:
var bannerNum = 2;
window.setInterval(function () {
bannerSwap(bannerNum);
}, 5000);
function bannerSwap(bannerNum) {
if (bannerNum == 5) {
bannerNum = 1;
document.getElementById('b1').style.display = "block";
document.getElementById('b4').style.display = "none";
return;
}
document.getElementById('b' + (bannerNum - 1)).style.display = "none";
document.getElementById('b' + bannerNum).style.display = "block";
bannerNum++;
return;
}
It just loops through the function every 5 seconds and swaps the banner image (4 divs, all display:none except the first, named b1 through b4). Pulling the page up, it switches the first time (bannerNum = 3), but it never switches after that. I alerted bannerNum at the end and saw that it switched from 2 to 3 and then it popped up every 5 seconds saying it was 3 over and over. So why isn't it incrementing?
Try
window.setInterval(function () {
bannerSwap(bannerNum++);
}, 5000);
Remove the bannerNum++ inside the bannerSwap function
EDIT
Your code doesn't work because you are not modifying the actual bannerNum variable, but rather a parameter you recieve with the same name.
For your code to work entirely, you should do one of the following,
Make all the modifications to bannerNum inside the setInterval function
Remove the parameter from the bannerSwap signature, so you gain scope of the global variable
As said in the comments, remove bannerNum from bannerSwap's parameter list like this:
<script>
var bannerNum = 2;
window.setInterval(function() {
bannerSwap();
},5000);
function bannerSwap() {
// Your code here (it will work)
}
</script>

Calling random function without duplicates

I am creating a random photo365 challenge list generator using javascript. I have a list of 365 different function which come up with a different assignment name/page link (this probably isn't the best way to do it, but it works)
It works as it's supposed to, it does call 365 functions and puts them in a list...
But what I'd like to do is prevent repeats. (Please note, the code below doesn't have all the 365 functions listed)
I have searched on stack overflow, and I have come across a variety of methods of preventing repeats. But any time I try to add the new code it, I can't get it to work.
I'm really not that skilled in javascript, so any guidance you could provide would be extremely appreciated...
Noel
//Create a new To-Do
function randomFrom(array) {return array[Math.floor(Math.random() * array.length)];}
function randomCreate() {
var func = randomFrom([createNew365ToDo,
createNew365ToDoBulb,
createNew365ToDo2,
createNew365ToDoShallow,
createNew365ToDoWide,
createNew365ToDoLenses,
createNew365ToDoMacro,
createNew365ToDoAToZ]);
(func)();
}
function createNew365ToDoList()
{
deleteAll365Rows();
for (var p = 0; p < 365; p++) {
{
randomCreate();
}
}}
I would do something like this:
//are arrays passed by reference? I don't remember, so let's just make it available to everything to demonstrate
var fnArray = [createNew365ToDo, createNew365ToDoBulb, createNew365ToDo2, createNew365ToDoShallow, createNew365ToDoWide, createNew365ToDoLenses, createNew365ToDoMacro,createNew365ToDoAToZ];
function randomFunction() {
//get a random index from the list
var index = Math.floor(Math.random() * fnArray.length);
//save that function to fn, and REMOVE it from the list
var fn = fnArray.splice(index, 1);
//return that function - now, when randomFunction() gets called again, you won't ever
//return the same function since it's no longer in the list
return fn;
}
function callRandomFunction() {
var func = randomFunction();
(func)();
}

stopping dynamically generated setInterval

I am generating multiple charts each with their own setInterval to refresh the data. I have it set to clearInterval when the dynamically generated container is removed - but if I reload and it has the same id the old setInterval continues to run. Is there a way to set a dynamically named setInterval that can be stopped when the replacement is generated?
Right now I'm using:
function generateChart(data, location){
var chart = new Highcharts.Chart({
// blah blah blah
}, function(chart){
setInterval(function(){
if($('#'+location).length){
// I'm doing stuff every minute
}else{
clearInterval();
}
},60000);
});
}
What happens is, the location is a randomly generated string that becomes the element ID for the container for the Highchart and if they user saves the chart it becomes the unique identifier. If the user updates the chart that's saved and reloads the chart, the old one gets .removed() and the new one generated in its place. Now the new one has the same element ID as the old one and since the old interval finds the container it wants it attempts to continue updating - which is can't since its chart went poof.
is there a way to set a dynamic variable I can use for setInterval so that I can clearInterval on it?
var blob+location = setInterval(function(){ ...
and then
clearInterval(blob+location);
You can just use an object:
var myObj = {};
var location = "somevalue";
myObj[location] = setInterval(...
clearInterval(myObj[location]);
ok - since I couldn't seem to wrap my head around some of your answers I decided to go low tech.
function genToken(){
var num = Math.floor(Math.random() * 10000);
var token = 't-' + num;
return token;
}
function genLocation(){
var chartToken = genToken();
var newChart = '<div id="'+location+'" data-token="'+chartToken+'"></div>';
$('#chartHome').append(newChart);
}
// inside my chart function
var token = $('#'+location).data('token');
setInterval(function(){
if( $('[data-token="'+token+'"]').length ){
// still there - keep going
}else{
// all gone - time to stop
clearInterval();
}
},60000);
now when I do:
$('#'+location).remove();
the token also vanishes and won't be the same if I generate a new chart with the same location id.
Stop using setInterval, use setTimeout instead (How do I execute a piece of code no more than every X minutes?):
function generateChart(data, location) {
var element = $('#'+location);
var chart = new Highcharts.Chart({
// blah blah blah
}, foo);
var foo = function() {
if(element){
// I'm doing stuff every minute
setTimeout(foo, 6000);
}
};
}
To stop it, just avoid the setTimeout or make element = null.
Maybe my code is a little bit wrong (I'm getting sleep right now), but the thing is to use setTimeout and closures.
If inside foo, something longs more than 6 seconds you will be in troubles since setTimeinterval will call it again, please watch http://www.youtube.com/watch?feature=player_detailpage&v=i_qE1iAmjFg#t=462s , so, this way you ensure that this will run 6 seconds after the last completed stuff.
I'll let this example here to posterity:
http://jsfiddle.net/coma/vECyv/2/
var closure = function(id) {
var n = 0;
var go = true;
$('#' + id).one('click', function(event) {
go = false;
});
var foo = function() {
if(go) {
console.log(id, n++);
setTimeout(foo, 1000);
}
};
foo();
};
closure('a');
closure('b');
Not sure if anyone is still looking for this solution but I ran into this problem and chose the following approach.
For anyone dynamically creating private/anonymous intervals that need to be stopped based on some event. You can simply save the interval in a variable, then transfer that variable into a data property in your html element.
// Outer scope
let pos = 1
let interval = setInterval(() => {
if (pos < 700) {
pos++;
}
htmlEl.style.top = pos + "px";
});
htmlEl.setAttribute("data-interval", interval)
This will save the numeric identifier of your interval, providing that html element is somewhere in your DOM.
Then, later you can simply extract this data attribute and use it to cancel an interval.
let intervalId = document.querySelector("#someElement").dataset.interval;
clearInterval(intervalId);

Categories

Resources