Adding incrementTo(num, time, pace) to counter - javascript

I'm using this counter (http://cnanney.com/journal/code/apple-style-counter-revisited/#options) and I'm trying to make the counter stop at '150'.
The website above says that the function I need to use is called: myCounter.incrementTo(150, 10, 400); This will increment to 150 as well, but the increment process will take 10 seconds to complete. The counter will determine the optimal values to use. In the example I've set a desired pace of 400, which the counter will try and stay as close to as possible when finding the optimal values. This method is not chainable.
The counter does not seem to recognize this function, could someone tell me what I am missing here?
HTML
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8"/>
<title>CSS Flip-Counter Revisited</title>
<!-- Counter script -->
<script type="text/javascript" src="js/flipcounter.js"></script>
<script type="text/javascript" src="js/modernizr.custom.21954.js"></script>
<!-- Counter styles -->
<link rel="stylesheet" type="text/css" href="css/style.css"/>
</head>
<body>
<h1>COUNTER</h1>
<div class="counter-wrapper">
<ul class="flip-counter huge" id="myCounter"></ul>
</div>
<script>
var myCounter = new flipCounter("myCounter", {inc: 25, pace: 400});
myCounter.setAuto(true);
myCounter.incrementTo(150, 10, 400);
</script>
</body>
</html>
JS
/**
* CSS Flip Counter
*
* Copyright (c) 2013 Chris Nanney
*
* http://cnanney.com/journal/code/css-flip-counter-revisited/
*
* Licensed under MIT
* http://www.opensource.org/licenses/mit-license.php
*/
var flipCounter = function(d, options){
// Default values
var defaults = {
value: 0,
inc: 1,
pace: 1000,
auto: true
};
var counter = options || {};
var doc = window.document;
for (var opt in defaults){
counter[opt] = counter.hasOwnProperty(opt) ? counter[opt] : defaults[opt];
}
var digitsOld = [], digitsNew = [], digitsAnimate = [], x, y, nextCount = null;
var div = d;
if (typeof d === 'string'){
div = doc.getElementById(d);
}
/**
* Sets the value of the counter and animates the digits to new value.
*
* Example: myCounter.setValue(500); would set the value of the counter to 500,
* no matter what value it was previously.
*
* #param {int} n
* New counter value
*/
this.setValue = function(n){
if (_isNumber(n)){
x = counter.value;
y = counter.value = n;
_digitCheck(x, y);
}
return this;
};
/**
* Sets the increment for the counter. Does NOT animate digits.
*/
this.setIncrement = function(n){
counter.inc = _isNumber(n) ? n : defaults.inc;
return this;
};
/**
* Sets the pace of the counter. Only affects counter when auto == true.
*
* #param {int} n
* New pace for counter in milliseconds
*/
this.setPace = function(n){
counter.pace = _isNumber(n) ? n : defaults.pace;
return this;
};
/**
* Sets counter to auto-increment (true) or not (false).
*
* #param {boolean} a
* Should counter auto-increment, true or false
*/
this.setAuto = function(a){
var sa = typeof a !== "boolean" ? true : a;
if (counter.auto){
if (!sa){
if (nextCount) _clearNext();
counter.auto = false;
}
}
else{
if (sa){
if (nextCount) _clearNext();
counter.auto = true;
_doCount();
}
}
return this;
};
/**
* Increments counter by one animation based on set 'inc' value.
*/
this.step = function(){
if (!counter.auto) _doCount();
return this;
};
/**
* Adds a number to the counter value, not affecting the 'inc' or 'pace' of the counter.
*
* #param {int} n
* Number to add to counter value
*/
this.add = function(n){
if (_isNumber(n)){
x = counter.value;
counter.value += n;
y = counter.value;
_digitCheck(x, y);
}
return this;
};
/**
* Subtracts a number from the counter value, not affecting the 'inc' or 'pace' of the counter.
*
* #param {int} n
* Number to subtract from counter value
*/
this.subtract = function(n){
if (_isNumber(n)){
x = counter.value;
counter.value -= n;
if (counter.value >= 0){
y = counter.value;
}
else{
y = "0";
counter.value = 0;
}
_digitCheck(x, y);
}
return this;
};
/**
* Gets current value of counter.
*/
this.getValue = function(){
return counter.value;
}
/**
* Stops all running increments.
*/
this.stop = function(){
if (nextCount) _clearNext();
return this;
}
//---------------------------------------------------------------------------//
function _doCount(first){
var first_run = typeof first === "undefined" ? false : first;
x = counter.value;
if (!first_run) counter.value += counter.inc;
y = counter.value;
_digitCheck(x, y);
// Do first animation
if (counter.auto === true) nextCount = setTimeout(_doCount, counter.pace);
}
function _digitCheck(x, y){
digitsOld = _toArray(x);
digitsNew = _toArray(y);
var ylen = digitsNew.length;
for (var i = 0; i < ylen; i++){
digitsAnimate[i] = digitsNew[i] != digitsOld[i];
}
_drawCounter();
}
// Creates array of digits for easier manipulation
function _toArray(input){
return input.toString().split('').reverse();
}
// Sets the correct digits on load
function _drawCounter(){
var bit = 1, html = '', dNew, dOld;
for (var i = 0, count = digitsNew.length; i < count; i++){
dNew = _isNumber(digitsNew[i]) ? digitsNew[i] : '';
dOld = _isNumber(digitsOld[i]) ? digitsOld[i] : '';
html += '<li class="digit" id="'+d+'-digit-a'+i+'">'+
'<div class="line"></div>'+
'<span class="front">'+dNew+'</span>'+
'<span class="back">'+dOld+'</span>'+
'<div class="hinge">'+
'<span class="front">'+dOld+'</span>'+
'<span class="back">'+dNew+'</span>'+
'</div>'+
'</li>';
if (bit !== count && bit % 3 === 0){
html += '<li class="digit-delimiter">,</li>';
}
bit++;
}
div.innerHTML = html;
var alen = digitsAnimate.length;
// Need a slight delay before adding the 'animate' class or else animation won't fire on FF
setTimeout(function(){
for (var i = 0; i < alen; i++){
if (digitsAnimate[i]){
var a = doc.getElementById(d+'-digit-a'+i);
a.className = a.className+' animate';
}
}
}, 20)
}
// http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric/1830844
function _isNumber(n){
return !isNaN(parseFloat(n)) && isFinite(n);
}
function _clearNext(){
clearTimeout(nextCount);
nextCount = null;
}
// Start it up
_doCount(true);
};

try to run this script on dom ready
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', runCounter, false);
} else {
window.attachEvent('onload', runCounter);
}
do like this :
<script>
var runCounter = function(){
var myCounter = new flipCounter("myCounter", {inc: 25, pace: 400});
myCounter.setAuto(true);
myCounter.incrementTo(150, 10, 400);
};
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', runCounter, false);
} else {
window.attachEvent('onload', runCounter);
}
</script>

Related

Insert two scripts in the same <script> tag without conflicts

I have to put these two scripts in a single tag without them coming into conflict but I can not make it. Please, how can I do it?
Also is it better to insert multiple scripts in the same tag?
Script 1
var sec = 04;
var hour = 00;
var time0, time1;
var delay=0;
var duringtime = 1000;
time1 = (hour *10000 + min * 100 + parseInt(sec)).toString();
console.log("time1", time1);
function refresh() {
........
}
}
refresh();
Script 2
var min = 80;
var max = 85;
var random = Math.floor(Math.random() * (max - min)) + min;
if (localStorage.getItem("stockcount_99")) {
if (localStorage.getItem("stockcount_99") >= duration) {
var value = random;
} else {
var value = localStorage.getItem("stockcount_99");
}
} else {
var value = random;
}
document.getElementById('divCounter').innerHTML = value;
var stockcount_99 = function() {
if (value <= stopValue) { // end count down. <= or >=
clearInterval(interval);
value = stopValue;
} else {
value = parseInt(value) - 1; // + 1 or - 1
localStorage.setItem("stockcount_99", value);
}
document.getElementById('divCounter').innerHTML = value;
};
var interval = setInterval(function() {
stockcount_99();
}, speedcontrol);
With the following method can I isolate the two scripts and thus prevent any conflicts?
(function() {
...script 1...
})()
(function() {
...script 2...
})()

Repeat an audioContext oscillator every 5 seconds

I am trying to write a morse code trainer that produces a random two letter pattern every 5 seconds with the audiocontext recreated each loop, but I cannot figure out how to add code which will call for a repeated loop. I've tried setTimeout() setInterval(), but they both eliminate the audio.
Also, after pressing the button five times on the following code.
I get the error
" TypeError: null is not an object (evaluating 'ctx.currentTime')"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button onclick = "startIt()">Play</button>
<button onclick = "stopIt()">Stop</button>
<h2>Morse Code</h2>
<h1 id="demo"></h1>
<h1 id="demo2"></h1>
<script>
var codeStream = '';
var dot = 1.2 / 15;
var text = "";
var display = "";
var k = 0;
var alphabet = [["A",".-"],["B","-..."],["C","-.-."],["D","-.."],["E","."],["F","..-."],["G","--."],["H","...."],["I",".."],["J",".---"],
["K","-.-"],["L",".-.."],["M","--"],["N","-."],["O","---"],["P",".--."],["Q","--.-"],["R",".-."],["S","..."],["T","-"],["U","..-"],
["V","...-"],["W",".--"],["X","-..-"],["Y","-.--"],["Z","--.."],["1",".----"],["2","..---"],["3","...--"],["4","....-"],["5","....."],
["6","-...."],["7","--..."],["8","---.."],["9","----."],["0","-----"],[".",".-.-.-"],[",","--..--"],["?","..--.."],["'",".----."],["!","-.-.--"],
["/","-..-."],[":","---..."],[";","-.-.-."],["=","-...-"],["-","-....-"],["_","..--.-"],["\"",".-..-."],["#",".--.-."],["(","-.--.-"],[" ",""]];
stopIt = function(){
ctx.close();
location.reload();
}
function nextGroup() {
for (i = 0; i < 2; i++){
var randomLetter = Math.floor(Math.random() * 26);
var code = alphabet[randomLetter][1] + " ";
var character = alphabet[randomLetter][0];
display += code;
text += character;
}
codeStream = display;
}
function startIt(){
var AudioContext = window.AudioContext || window.webkitAudioContext;
var ctx = new AudioContext();
var t = ctx.currentTime;
var oscillator = ctx.createOscillator();
oscillator.type = "sine";
oscillator.frequency.value = 600;
oscillator.start();
var gainNode = ctx.createGain();
nextGroup();
console.log(codeStream);
document.getElementById("demo").innerHTML = text;
document.getElementById("demo2").innerHTML = codeStream;
display = "";
text = "";
gainNode.gain.setValueAtTime(0, t);
for (var i = 0; i < codeStream.length; i++) {
switch(codeStream.charAt(i)) {
case ".":
gainNode.gain.setValueAtTime(1, t);
t += dot;
gainNode.gain.setValueAtTime(0, t);
t += dot;
break;
case "-":
gainNode.gain.setValueAtTime(1, t);
t += 3 * dot;
gainNode.gain.setValueAtTime(0, t);
t += dot;
break;
case " ":
t += 7 * dot;
break;
}
}
gainNode.gain.setValueAtTime(0, t);
t += 50 * dot;
oscillator.connect(gainNode);
gainNode.connect(ctx.destination);
codeStream = '';
oscillator.stop(t);
}
</script>
</body>
</html>
It looks like some of the issues are to do with scoping and state management of the oscillator. I wasn't able to reproduce the error you were seeing but the stopIt function certainly doesn't have access to ctx created in startIt.
An alternative might be to, rather than recreate the context, oscillator and gain node on each run, create them once and reuse them instead. Demo here: http://jsfiddle.net/kts74g0x/
The code:
const ALPHABET = [
["A", ".-"],
...
[" ",""]
];
const DOT = 1;
const DASH = 3;
const NEXT = DOT;
const SPACE = 7;
const SPEED = 1.2 / 15;
const AudioContext = window.AudioContext || window.webkitAudioContext;
/**
* Create a single audio context, oscillator and gain node and repeatedly
* use them instead of creating a new one each time. The gain is just
* silent most of the time.
*/
const ctx = new AudioContext();
const oscillator = ctx.createOscillator();
const gainNode = ctx.createGain();
oscillator.type = "sine";
oscillator.frequency.value = 600;
oscillator.connect(gainNode);
oscillator.start();
gainNode.connect(ctx.destination);
gainNode.gain.value = 0;
function playCodeStream(stream) {
let t = ctx.currentTime;
gainNode.gain.setValueAtTime(0, t);
for (var i = 0; i < stream.length; i++) {
switch(stream.charAt(i)) {
case ".":
gainNode.gain.setValueAtTime(1, t);
t += DOT * SPEED;
gainNode.gain.setValueAtTime(0, t);
t += NEXT * SPEED;
break;
case "-":
gainNode.gain.setValueAtTime(1, t);
t += DASH * SPEED;
gainNode.gain.setValueAtTime(0, t);
t += NEXT * SPEED;
break;
case " ":
t += SPACE * SPEED;
break;
}
}
}
/**
* Set interval will wait initially for the period of
* time before first triggering the function.
*/
setInterval(() => { playCodeStream([
ALPHABET.filter(v => v[0] === "H"),
ALPHABET.filter(v => v[0] === "E"),
ALPHABET.filter(v => v[0] === "L"),
ALPHABET.filter(v => v[0] === "L"),
ALPHABET.filter(v => v[0] === "O")
].join(" ")); }, 10000);
Set interval returns an ID that can be passed to clearInterval to prevent future runs, the play button might start the interval and the stop button could clear it, for example.
For iOS there are restrictions so that an AudioContext cannot play sound unless it is in response to a user interaction (https://hackernoon.com/unlocking-web-audio-the-smarter-way-8858218c0e09). We can get around the problem by adding a button.
<button id="go">Go</button>
And checking the state of the audio context / starting the interval in response to clicking this button (demo: http://jsfiddle.net/7gfnrubc/). The updated code:
function next() {
playCodeStream([
ALPHABET.filter(v => v[0] === "H"),
ALPHABET.filter(v => v[0] === "E"),
ALPHABET.filter(v => v[0] === "L"),
ALPHABET.filter(v => v[0] === "L"),
ALPHABET.filter(v => v[0] === "O")
].join(" "));
}
function go() {
if (ctx.state === 'suspended') {
ctx.resume();
}
/**
* Set interval will wait initially for the period of
* time before first triggering the function. Can call
* the function initially to start off.
*/
next();
setInterval(next, 10000);
}
const button = document.getElementById("go");
button.addEventListener("click", go);

Tracking time and display it at next game

I have an assignment and I am a bit stuck. The assignment states:
Modify the game so that the time is tracked and a best time (or time to beat) is stored and displayed at the end of the game and at the beginning of the next game that is played. This functionality assumes the browser is not closed and that each successive game is begun through the "Play Again?" link. The display of the time to beat is shown below.
I have all files necessary, but I am stuck in this part. Here is the code:
<!DOCTYPE html>
<html>
<head>
<title>Recipe: Drawing a square</title>
<script src="easel.js"></script>
<script type="text/javascript">
var canvas;
var stage;
var placementArray = [];
var tileClicked;
var timeAllowable;
var totalMatchesPossible;
var matchesFound;
var txt;
var matchesFoundText;
var tileHeight = 30;
var tileWidth = 45;
var border = 1;
var globalPadding = 10;
var margin = 10;
var padding = 5;
var textTiles;
var flashcards = [
["a", "\u3042"],
["i", "\u3044"],
["u", "\u3046"],
["e", "\u3048"],
["o", "\u304A"],
["ka", "\u304B"],
["ki", "\u304D"],
["ku", "\u304F"],
["ke", "\u3051"],
["ko", "\u3053"],
["sa", "\u3055"],
["shi", "\u3057"],
["su", "\u3059"],
["se", "\u305B"],
["so", "\u305D"],
["ta", "\u305F"],
["chi", "\u3061"],
["tsu", "\u3064"],
["te", "\u3066"],
["to", "\u3068"],
["na", "\u306A"],
["ni", "\u306B"],
["nu", "\u306C"],
["ne", "\u306D"],
["no", "\u306E"],
["ha", "\u306F"],
["hi", "\u3072"],
["fu", "\u3075"],
["he", "\u3078"],
["ho", "\u307B"],
["ma", "\u307E"],
["mi", "\u307F"],
["mu", "\u3080"],
["me", "\u3081"],
["mo", "\u3082"],
["ya", "\u3084"],
["yu", "\u3086"],
["yo", "\u3088"],
["ra", "\u3089"],
["ri", "\u308A"],
["ru", "\u308B"],
["re", "\u308C"],
["ro", "\u308D"],
["wa", "\u308F"],
["wo", "\u3092"],
["n", "\u3093"]
];
function init() {
canvas = document.getElementById('myCanvas');
stage = new Stage(canvas);
totalMatchesPossible = flashcards.length;
var numberOfTiles = totalMatchesPossible * 2;
matchesFound = 0;
var columns = 12;
timeAllowable = 500;
txt = new Text(timeAllowable, "30px Monospace", "#000");
txt.textBaseline = "top";
txt.x = 700;
txt.y = 0;
stage.addChild(txt);
textTiles = [];
matchesFoundText = new Text(matchesFound + "/" + totalMatchesPossible, "30px Monospace", "#000");
matchesFoundText.textBaseline = "top";
matchesFoundText.x = 700;
matchesFoundText.y = 40;
stage.addChild(matchesFoundText);
Ticker.init();
Ticker.addListener(window);
Ticker.setPaused(false);
setPlacementArray(numberOfTiles);
for (var i = 0; i < numberOfTiles; i++) {
var placement = getRandomPlacement(placementArray);
var pairIndex = Math.floor(i / 2);
text = flashcards[pairIndex][i % 2];
var textTile = drawTextTile(text, pairIndex);
textTile.x = (tileWidth + margin) * (placement % columns) + globalPadding;
textTile.y = (tileHeight + margin) * Math.floor(placement / columns) + globalPadding;
stage.addChild(textTile);
background = new Shape();
background.x = textTile.x - padding;
background.y = textTile.y - padding;
background.graphics.setStrokeStyle(border).beginStroke("#000").beginFill('#eee').drawRect(0, 0, tileWidth, tileHeight);
textTiles.push(background);
stage.addChildAt(background);
background.text = textTile;
background.onPress = handleOnPress;
stage.update();
};
}
function drawTextTile(text, pairIndex) {
textTile = new Text(text, "20px Monospace", "#000");
textTile.pairIndex = pairIndex;
textTile.textBaseline = "top";
return textTile;
}
function randomColor() {
var color = Math.floor(Math.random() * 255);
var color2 = Math.floor(Math.random() * 255);
var color3 = Math.floor(Math.random() * 255);
return Graphics.getRGB(color, color2, color3)
}
function setPlacementArray(numberOfTiles) {
for (var i = 0; i < numberOfTiles; i++) {
placementArray.push(i);
}
}
function getRandomPlacement(placementArray) {
randomNumber = Math.floor(Math.random() * placementArray.length);
return placementArray.splice(randomNumber, 1)[0];
}
function handleOnPress(event) {
var tile = event.target;
if (!!tileClicked === false || tileClicked === tile) {
tileClicked = tile;
} else {
tileClicked.graphics.beginFill('#eee').drawRect(0, 0, tileWidth, tileHeight);
tile.graphics.beginFill('#aae').drawRect(0, 0, tileWidth, tileHeight);
if (tileClicked.text.pairIndex === tile.text.pairIndex && tileClicked.id != tile.id) {
tileClicked.visible = false;
tile.visible = false;
matchesFound++;
matchesFoundText.text = matchesFound + "/" + totalMatchesPossible;
if (matchesFound === totalMatchesPossible) {
gameOver(true);
}
}
tileClicked = tile;
}
stage.update();
}
function tick() {
secondsLeft = Math.floor((timeAllowable - Ticker.getTime() / 1000));
txt.text = secondsLeft;
if (secondsLeft <= 0) {
gameOver(false);
}
stage.update();
}
function gameOver(win) {
Ticker.setPaused(true);
var replayParagraph = document.getElementById("replay");
replayParagraph.innerHTML = "<a href='#' onClick='history.go(0);'>Play Again?</a>";
for (var i = 0; i < textTiles.length; i++) {
textTiles[i].onPress = null;
}
if (win === true) {
matchesFoundText.text = "You win!"
} else {
txt.text = secondsLeft + "... Game Over";
}
}
function replay() {
init();
}
</script>
</head>
<body onload="init()">
<header id="header">
<p id="replay"></p>
</header>
<canvas id="myCanvas" width="960" height="400"></canvas>
</body>
</html>
I give you 1 option for this, though you can do it also in other ways,
we declare global variables which are
var prev_time;
var best_time;
add that to your global variable declarations, then give it a value when you compute the time i guess we had that here:
function tick() {
secondsLeft = Math.floor((timeAllowable - Ticker.getTime() / 1000));
txt.text = secondsLeft;
if (secondsLeft <= 0) {
gameOver(false);
}
//compute here the total time player had and give it to prev_time
//var totalTimePlayerplayed = some computation here which should be allowed time per player - secondsLeft
prev_time = totalTimePlayerplayed;
stage.update();
}
function gameOver(win) {
Ticker.setPaused(true);
var replayParagraph = document.getElementById("replay");
replayParagraph.innerHTML = "<a href='#' onClick='history.go(0);'>Play A
gain?</a>";
for (var i = 0; i < textTiles.length; i++) {
textTiles[i].onPress = null;
}
if (win === true) {
matchesFoundText.text = "You win!"
if(best_time !== NULL){
best_time = prev_time;
//WE assume that the last player is the best scorer
}
} else {
//if there is already existing top scorer
if(best_time < prev_time){
best_time = prev_time
}
txt.text = secondsLeft + "... Game Over";
}
}
then give that time of the first player to the prev_time. Upon Game over or Game ended we validate here if the best_time has a value if not, then we give it a value of the value of prev_time, else we validate if the score is higher that the previous best_time and here's a tip, now when the player would trigger the "Play again" which I can't seem find right now, you get the variable best_time's value and display it as the score to beat. Hope you get the concept and somehow it helped you accomplished what you're intended to do, but like i said before you also have some other options to do this.

Javascripts code stops working

the problem it's about a roulette that spins every 1 min,
Problem : When I switch from one tab to another on google chrome or any other navigators, the script stops running and the roulette stops (and I need to go back to the tab again in order to make the script work)
image roulette = animation of game
//<![CDATA[
var myRoll = {
nbr : [14, 1, 13, 2, 12, 3, 11, 0, 4, 10, 5, 9, 6, 8 ,7],
initRoll : function(){
var Ccolor;
var nbrCtn = $(".nbr-ctn");
for(j = 0; j < 6 ; j++){
for(i = 0; i < this.nbr.length; i++){
Ccolor = "";
if(this.nbr[i] === 0 ){
Ccolor = "nbr-green";
}else if(this.nbr[i] > 7){
Ccolor = "nbr-black";
}else{
Ccolor = "nbr-red";
}
var elem = '<div class="nbr '+ Ccolor +'" >'+ this.nbr[i] +'</div>';
nbrCtn.append(elem);
}
}
},
lastResult : function(n){
Ccolor = "";
if(n === 0 ){
Ccolor = "nbr nbr-green";
}else if(n > 7){
Ccolor = "nbr nbr-black";
}else{
Ccolor = "nbr nbr-red";
}
var nbrResult = $(".lastResult > div").length;
if(nbrResult === 5 ){
$(".lastResult div:first-child").remove();
}
var elem = '<div class="circle '+ Ccolor +'" >'+ n +'</div>';
$(".lastResult").append(elem);
},
rollAnimation : function(offset, n){
var prog = $(".progress-line");
if(offset){
prog.width("100%");
var nbrCtn = $(".nbr-ctn");
nbrCtn.css("left" , "0px");
nbrCtn.animate({left: "-"+ offset +".5px"}, 6000, 'easeInOutQuint', function(){
myRoll.lastResult(n);
myRoll.countDown();
});
}
},
getRandomInt : function(min, max){
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
},
startRoll : function(n){
var nbrCtn = $(".nbr-ctn");
var gAnim = $("#game-animation");
var idx = this.nbr.indexOf(n) + this.nbr.length * 4;
var elmWidth = nbrCtn.find(".nbr").width();
var offset = idx * elmWidth - (gAnim.width() / 2);
offset = this.getRandomInt(offset + 5, offset + elmWidth - 5);
this.rollAnimation(offset, n);
},
countDown : function(){
var prog = $(".progress-line");
var gameStatus = $(".rolling > span");
prog.animate({width : "0px"}, {
duration: 30000,
step: function(now){
var rt = (now*3) / 100;
gameStatus.html("Closing in " + rt.toFixed(2));
},
complete: function(){
// when the progress bar be end
gameStatus.html("Rolling ...");
myRoll.startRoll(myRoll.getRandomInt(0, 14));
},
easing: "linear"
});
}
};
window.onload = function(){
myRoll.initRoll();
myRoll.countDown();
};
//]]>
For this you need to implement things in following way (this is just way out).
Basic concept behind bellow code is calculate lag between tab switch and set current state accordingly.
var prevTime,curTime;
var rate = 500; //(miliseconds) you can set it.
function update()
{
var diffTime = curTime - prevTime;
if (diffTime >= rate)
{
//check if difference is more than step value then calculate
//current state accordingly. so you will always be updated as you calculating lags.
// e.g. diffTime = 1500;
// you will need to jump Math.floor(diffTime/rate) which is 3.
// calculate current state.
//your code....
prevTime = curTime;
}
requestAnimationFrame(update);
}

Is there any way of adapting this name-generating loop to run for a minimum number of seconds?

I'm using the following code (which has some Frog VLE API code in it; hopefully that's not too relevant) to pick a random student from a list.
This works well, but sometimes - given its random nature - it only runs for a very brief period of time. Would it be possible to loop this a number of times first, to ensure that it runs for X period of time as a minimum?
var Count = 0;
/* construct the array of people */
for (var i in data.users) {
for (var n = 0; n < data.users[i].Quantity; n++) {
var TempObj = { 'Count' : Count, 'Student_ID' : i, 'Student_Name' : data.users[i].Student_Name };
RewardPurchases.PurchasesArray[Count] = TempObj;
Count++;
}
}
... more code here, nothing relevant to the way the script works ...
$('button#random').click( function() {
/* first things first, play a drum-roll when the button is clicked! */
$('embed').remove();
$('body').append('<embed src="/user/74/177499.wav" autostart="true" hidden="true" loop="true">');
/* take the RewardPurchases.PurchasesArray and sort it so that there's no particular order */
RewardPurchases.PurchasesArray.sort(function() {return 0.5 - Math.random()})
/* remove the winner class for consecutive re-rolls */
$display.removeClass( "winner" );
$display.addClass( "spinner" );
/* determine the number of people in the array and calculate a random winner */
var total = RewardPurchases.PurchasesArray.length,
selected = Math.floor( Math.random() * total ),
i = 0;
/* work out how long each name should appear for, dependent upon how many people are in the array */
var timeout = ( 15000 / total );
/* run through the array of people ... */
for (i=0; i<total; i++) {
setTimeout((function(i){
return function(){
console.log( "timeout", i );
/* ... if the person in the array is a valid person! then display their name */
if (typeof RewardPurchases.PurchasesArray[i] === 'object' && typeof RewardPurchases.PurchasesArray[i] !== null) {
$display.text( "[" + RewardPurchases.PurchasesArray[i].Count + "] " + RewardPurchases.PurchasesArray[i].Student_Name.toUpperCase() );
/* if we encounter the winner, play a cheering wav and change the class of the display so that they appear in big, bold, red text */
if( i === selected ) {
$('embed').remove();
$('body').append('<embed src="/user/74/177086.wav" autostart="true" hidden="true" loop="false">');
$display.addClass( "winner" );
}
}
};
}(i)), i*timeout);
/* if the winner has been found, break the loop */
if( i === selected ) {
break;
}
}
} );
Thanks in advance,
You could do something like this :
function doforsec(msec, func) {
var curDate = new Date().getTime();
while ((new Date().getTime() - curDate) < msec) {
func();
}
}
doforsec(200, function() {
console.log(new Date().getSeconds())
});​
This executes the function given to doforsec again and again until the timeperiod specified (in milliseconds) is over. (first i had seconds, but i think milliseconds will be better)
JSfiddle
Because my deadline for this is.. well, around 8 hours from posting this.. I've decided to re-write the script and use a jQuery plugin:
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
$(document).ready(function(){
var staff = [ 'hardcoded', 'list', 'of', 'staff', 'members' ];
$('button#start').click( function() {
var $display = $('#display'),
$results = $('#results table');
$display.removeClass( "winner" );
$display.addClass( "spinner" );
var counter = 0,
rand = 0,
run_time = 10,
delay = ( run_time * 100 ) / staff.length,
loop_number = 5,
max_count = staff.length * loop_number;
$display.doTimeout( 'loop', delay, function() {
counter++;
var newRand = Math.floor( Math.random() * staff.length );
if ( rand === newRand ) {
rand = Math.floor( Math.random() * staff.length );
} else {
rand = newRand;
}
$(this).text( staff[rand] );
if ( counter < max_count ) { return true; }
else {
$('#results tr:last').after('<tr><td class="number">' + staff.length + '</td><td>' + staff[rand] + '</td></tr>');
staff.remove( rand );
}
});
$display.doTimeout( 'class', max_count * delay, function() {
$display.removeClass( "spinner" );
$display.addClass( "winner" );
});
});
});
After var timeout = ( 15000 / total ); insert the following, and remove the line for (i=0; i
var totalTime = 2000;
var timeOut= Math.Ceiling(totalTime/timeout);
var timesToDisplay = totalTime / timeOut;
var currentDisplay = 0;
for (currentDisplay = 0; currentDisplay < timesToDisplay; currentDisplay++) {
i = currentDisplay % total;

Categories