One javascript for mutliple divs? - javascript

I have this HTML and a script
/**
* Increment value with random intervals.
* #param {string} id - Id of DOM Element.
* #param {number} start - Start counter value. Applied immediately.
* #param {number} end - End counter value.
* #duration {number} duration - Max duration of one iteration in ms.
*/
function animateValue(id, start, end, duration) {
let current = start;
const obj = document.getElementById(id);
obj.innerHTML = current; // immediately apply start value
const setIncrOut = () => {
let time = Math.random() * 500;
setTimeout(function() {
if (current < end) {
current += 1;
obj.innerHTML = current;
setIncrOut(time)
}
}, time);
}
setIncrOut();
}
animateValue("value", 100, 1000000);
<div id="value">100</div>
Basically I want to use this 1 script for multiple divs:
<div id="value2">100</div>
<div id="value3">100</div>
<div id="value4">100</div>
I know that div id must match the script id, is there a workaround, so that I wouldn't need to duplicate the same script and simply use just one?
I'm planning to use over 200 of them, so I thought it's not feasible and using just one will save a lot resources.
EDIT: I figured I can use:
animateValue("value", 100, 1000000);
animateValue("value2", 100, 1000000);
animateValue("value3", 100, 1000000);
But maybe there's even simpler solution?

Try this
Use a class and since you are using let, you can just call with the object
/**
* Increment value with random intervals.
* #param {string} id - Id of DOM Element.
* #param {number} start - Start counter value. Applied immediately.
* #param {number} end - End counter value.
* #duration {number} duration - Max duration of one iteration in ms.
*/
function animateValue(obj, start, end, duration) {
let current = start;
obj.innerHTML = current; // immediately apply start value
const setIncrOut = () => {
let time = Math.random() * 500;
setTimeout(function() {
if (current < end) {
current += 1;
obj.innerHTML = current;
setIncrOut(time)
}
}, time);
}
setIncrOut();
}
document.querySelectorAll(".incr").forEach(obj => animateValue(obj, 100, 1000000));
<div class="incr">100</div>
<div class="incr">100</div>

Related

Read Coordinates from file in javascript

I have file in javascript i am opening using
fs.readFileSync(fileName)
after I return it to the client it is stored like so:
[G]Hey, where did [C]we go, da[G]ys when the ra[D]ins came
[G]Down in the holl[C]ow, [G]playin' a ne[D]w game
However, I need the x and y coordinates so that I can update my canvas.
Is there any way to do this?
If we assume the first character has the position {x: 0, y: 0} and that the next line increments the y position by one, then we can use something like this to calculate the positions of the characters:
/**
* Find the XY positions of this string
*
* #type {string}
*/
const given = `[G]Hey, where did [C]we go, da[G]ys when the ra[D]ins came
[G]Down in the holl[C]ow, [G]playing a ne[D]w game`;
/**
* Return the coordinates of the characters in a string
*
* #param {string} string
* #returns {Array}
*/
const calculateXY = (string) => {
const positions = [];
let yIndex = 0;
let xIndex = 0;
string.split('').forEach(character => {
if(/\n/g.test(character)) {
yIndex++;
xIndex = 0;
} else {
positions.push({ [character]: { x: xIndex, y: yIndex}});
}
xIndex++;
});
return positions;
};
const result = calculateXY(given);
console.log(result);
You can modify the above block an pass a multiplier so that x and y are incremented by the distance in pixels to the next character.

Issue with offset while reading code points

Resume: I'm currently writting an ActionScript 3 lexer that transforms a source code into tokens. I chosen to interpret the input, a String with optional surrogate pairs wrapped in a class UString, by code points. Under the hood I cache the last read position by using the UStringPos class.
I've tested how it scans the identifier "huehuehue" with...
'use strict';
import {Lexer} from 'core/Lexer';
import {UString} from 'utils/UString';
import ErrorHandler from 'core/ErrorHandler';
const errorHandler = new ErrorHandler(true);
// Tell the length to the `Lexer` manually.
const lexer = new Lexer(
new UString('huehuehue'), 9, errorHandler);
// Scan first token
lexer.next();
const id = lexer.lookahead.value;
console.log(
id,
id.length
);
It should have logged "huehuehue", 9, but was another story...
Why is it missing the last 'e'? The innermost method related on scanning this is Lexer#getCommonIdentifier. I've already tested my UString part and it works okay, by the way.
Lexer Related Definitions
/*
* Class that turns AS3 code into tokens.
*/
export class Lexer
{
/*
* #param {UString} source
* #param {Number} length
* #param {ErrorHandler} errorHandler
*/
constructor(source, length, errorHandler)
{
this.source = source;
this.length = length;
this.index = 0;
this.lineStart = 0;
this.lineNumber = 1;
this.comments = [];
this.errorHandler = errorHandler;
this.previousToken = null;
this.token = null;
this.lookahead = null;
this._special = [];
}
/*
* Verifies the end of file.
*/
eof()
{
return this.index >= this.length;
}
/*
* Advance the previous, current and lookahead tokens.
* The lexer however does not depend on these tokens.
*/
next()
{
this.previousToken = this.token;
this.token = this.lookahead;
this.lookahead = this.lex();
}
/*
* Consumes the next token and return it.
*/
lex()
{
this.consumeWhiteSpaces();
while (this.consumeComment())
this.consumeWhiteSpaces();
let cp = this.source.codePointAt(this.index);
let pureIdentifier =
Character.isIdentifierStart(cp);
if (pureIdentifier || (cp === 0x5C))
return this.scanIdentifierOrKeyword(!pureIdentifier);
if (this.eof())
{
let loc = [ this.index, this.lineNumber ];
return new Token(TokenType.EOF, loc, loc, '<end>');
}
}
/*
* Scan an identifier, keyword or boolean literal.
*/
scanIdentifierOrKeyword(usingEscape)
{
const start = this.index;
let id;
/* Like Esprima does: only identifiers containing
* escapes need some overheads. */
if (usingEscape)
{
id = this.getEscapedIdentifier(
String.fromCodePoint(this.scanUnicodeEscapeSequence()));
}
else
id = this.getCommonIdentifier();
return new Token(
TokenType.IDENTIFIER,
[ start , this.lineNumber ],
[ this.index, this.lineNumber ],
id
);
}
/*
* Interprets an identifier. If any escape appears, switches to
* getEscapedIdentifier().
*/
getCommonIdentifier()
{
const start = this.source.position.offset;
let cp = 0;
// Jump the starting symbol.
++this.index;
while (!this.eof())
{
cp = this.source.codePointAt(this.index);
if (Character.isIdentifierPart(cp))
++this.index;
// Switches to escape-minded task...
else if (cp === 0x5C)
return this.getUnicodeEscapedIdentifier(
this.source.string.slice(
start, this.source.position.offset
)
);
else break;
}
return this.source.string.slice(
start, this.source.position.offset
);
}
/* ... */
}
utils/UString.js
'use strict';
/*
* String wrapper with methods _based_ on code points.
*/
export class UString
{
/*
* Constructs the {UString}.
*
* #param {String} s String to be wrapped.
*/
constructor(s)
{
/*
* #type {String}
*/
this.string = s;
/*
* Tracks the last accessed position.
*
* #type {UStringPos}
*/
this.position = new UStringPos(0, 0);
}
/*
* Reads a code point at specific index.
*
* #param {Number} index
* #return {Number}
*/
codePointAt(index)
{
this.position.walk(this.string, index);
return this.string.codePointAt(this.position.offset);
}
/*
* Slices the internal string by code point indices.
*
* #param {Number} i
* #param {Number} j
* #return {String}
*/
slice(i, j)
{
this.position.walk(this.string, i);
i = this.position.offset;
this.position.walk(this.string, j);
j = this.position.offset;
return this.string.slice(i, j);
}
};
/*
* Class that tracks the position of a code point on a string.
*/
export class UStringPos
{
/*
* Constructs the {UStringPos}.
*
* #param {Number} index The initial index.
* #param {Number} offset The initial offset.
*/
constructor(index, offset)
{
/*
* #type {Number}
*/
this.index = index;
/*
* #type {Number}
*/
this.offset = offset;
}
/*
* Walks to the given index.
*
* #param {String} s
* #param {Number} index
* #note No backward. Track the previous position instead.
* #return {void}
*/
walk(s, index)
{
for (; this.index < index; ++this.index)
this.offset += (
this._usingSurrogates(
s.charCodeAt(this.offset)
) ? 2 : 1
);
}
/*
* #private
*/
_usingSurrogates(ch)
{
return (ch >= 0xD800) && (ch <= 0xDBFF);
}
};
Anything?
Okay. So it was a problem with this.source.position.offset: when I do ++this.index, the offset of my UStringPos doesn't update. The problem was with the slice thing.
this.source.string.slice(
start, this.source.position.offset
);
This slice was based on offsets, since I had to track the previous offset where the identifier started.
Solution
I can use the slice of my own UString class and use the first parameter as an offset and the last one as a normal index.
'use strict';
export class UString
{
// ...
/*
* Slices the internal string by using a pair of
* offset and code point indices.
*
* #param {Number} i Offset
* #param {Number} j
* #return {String}
*/
slice(i, j)
{
this.position.walk(this.string, j);
j = this.position.offset;
return this.string.slice(i, j);
}
};

Logic Pro X Midi FX Javascript - Using GetTimingInfo() causes 100% CPU

I'm using the Scripter MidiFX in MainStage 3 (same as LogicPro X) to create a custom arpeggiator with javascript since I needed more control, so it seemed logical to use GetTimingInfo() to get the current beat inside of the ProcessMIDI() function to trigger the MIDI notes, as I saw in their examples. Unfortunately this pegs the CPU even on my Core i7 MacBook Pro, and I'm using a MacMini with a Core 2 Duo processor at actual shows.
I was able to write my own code to calculate the current beat using new Date() and then only using GetTimingInfo() to get the current tempo when a new note is pressed, but even that wasn't keeping the CPU where I'd like it to be.
When I don't include "NeedsTimingInfo=true" and just hard code the tempo everything works great, but this is a lot of extra code and makes more sense to use the built in functions.
Here's a simple sequencer example that causes this problem... am I doing something wrong? This happen even if I use a counter only run ProcessMIDI() on every 16th call!
NeedsTimingInfo = true;
var startBeat = -1;
var startPitch = 0;
var lastBeat = -1;
var currentStep = 0;
// melody test
var steps = [
0, 0, 0, 0, 0, 0, 0, 2,
0, 0, 0, 0, 0, 0, 2, 5
];
function HandleMIDI(e) {
if (e instanceof NoteOn) {
if (startBeat > 0) return;
currentStep = 0;
startPitch = e.pitch;
var info = GetTimingInfo();
lastBeat = startBeat = info.blockStartBeat;
doNote(e.pitch);
}
else if (e instanceof NoteOff) {
if (e.pitch == startPitch) {
startBeat = -1;
}
}
else {
e.send();
}
}
function doNote(pitch) {
var adjustment = 0;
if (currentStep < steps.length) {
adjustment = steps[currentStep];
}
var p = pitch + adjustment;
var on = new NoteOn;
on.pitch = p;
on.send();
var off = new NoteOff;
off.pitch = p;
off.sendAfterBeats(0.9);
}
function ProcessMIDI() {
var info = GetTimingInfo();
if (!info.playing) return;
if (startBeat < 0) return;
var beat = info.blockStartBeat;
if (beat - lastBeat >= 1) {
currentStep++;
doNote(startPitch);
lastBeat = beat;
}
}
What is your I/O Buffer Size set to in Preferences>Audio>Advanced Settings ? The smaller the buffer size, the more CPU is required. I assume that since you are using MainStage for live use, you have a very low setting to minimize your latency.
I tried running your code with a buffer size of 16, and MS stuttered and maxed out the CPU. 64 handled it better (the CPU meter spiked, but played without any hiccups). Tested on a 2009 MacBook Pro 3.06 Core 2 Duo.
You may have to live with a little more latency in order for Scripter to run smoothly. Your code itself, is solid.
The issue went away with MainStage 3.0.3, which I was able to find using TimeMachine.
I did create a custom Javascript implementation of their timing for 3.0.4, which did help quite a bit, but is an extra 100 lines or so of code (below). If anyone else runs into this problem, I would suggest the downgrade instead.
/**---[lib/TimingInfo.js]---*/
/**
* Constructor accepts the tempo for beat syncing and starts the clock
* to the current time.
*
* #param tempo the tempo of the song (default: 120bpm)
*/
function TimingInfo(tempo) {
this.schedule = [];
this.setTempo(tempo);
this.reset();
}
/**
* Sets the tempo and computes all times associated, assuming a 4/4
* beat structure.
*
* #param tempo the current tempo in beats per minute.
*/
TimingInfo.prototype.setTempo = function(tempo) {
this.tempo = tempo || 120;
this.msecPerBeat = (60 / this.tempo) * 1000;
};
/**
* Resets the beatsync to be relative to the current time.
*/
TimingInfo.prototype.reset = function() {
this.startTime = new Date().getTime();
this.update();
// trigger all scheduled messages immediately. TODO: note off only?
this._sendScheduled(null);
};
/**
* Uses the current time to update what the current beat is and all
* related properties. Any scheduled actions are performed if their
* time has passed.
*/
TimingInfo.prototype.update = function() {
var now = new Date().getTime();
this.elapsedMsec = now - this.startTime;
this.beat = this.elapsedMsec / this.msecPerBeat;
this._sendScheduled(this.beat);
};
/**
* Schedules a midi message to be sent at a specific beat.
* #param e MIDI event to schedule
* #param beat the beat number to send it on
*/
TimingInfo.prototype.sendAtBeat = function(e, beat) {
if (e == null) return;
// insert in-order into schedule
var insertAt = 0;
for (var i = 0; i < this.schedule.length; i++) {
if (this.schedule[i].beat > beat) {
insertAt = i;
break;
}
}
this.schedule.splice(insertAt, 0, {e:e, beat:beat});
};
/**
* Schedules a midi message relative to current beat.
*/
TimingInfo.prototype.sendAfterBeats = function(e, deltaBeats) {
this.sendAtBeat(e, this.beat + deltaBeats);
};
/**
* Sends all messages scheduled on or before a given beat. If not
* supplied all scheduled items are sent.
*
* #param atBeat beat to compare all scheduled events against (default: all)
*/
TimingInfo.prototype._sendScheduled = function(atBeat) {
// send all items on or before the given beat
var sent = 0;
for (var i = 0; i < this.schedule.length; i++) {
if (!atBeat || this.schedule[i].beat <= atBeat) {
this.schedule[i].e.send();
sent++;
}
else {
break;
}
}
// remove sent items
this.schedule.splice(0, sent);
};
var _timing = null;
/**
* Replacement for GetTimingInfo() that calls update() to handling
* any scheduled actions.
*/
function GetNewTimingInfo() {
if (_timing == null) {
_timing = new TimingInfo();
}
_timing.update();
return _timing;
}

HTML5 Video with random speed - autorefresh

So, I want to play a video as a loop, while random values of playbackRate is created to randomly set speed up and down video during another random interval of time.
For that, I have this:
window.onload = function ()
{
var tempo = Math.floor(Math.random() * 3) + 0.5; // TIME TO SET VIDEO SPEED
var tempo2 = Math.floor(Math.random() * 2000) + 1000; // TIME TO SET INTERVAL TIME
setInterval(function ()
{
document.getElementById("my-video").playbackRate = tempo;
console.log(tempo , tempo2);
}, Math.floor(Math.random() * this.tempo2) + 600);
};
For some reason, the video is randomly speed up and down, as I expected, but I need to refresh page to change value.
JSFIDDLE
Thanks
You need to update the tempo variable in the setInterval function
setInterval(function ()
{
document.getElementById("my-video").playbackRate = tempo;
tempo = Math.floor(Math.random() * 3) + 0.5;
console.log(tempo , tempo2);
}, Math.floor(Math.random() * this.tempo2) + 600);
But I think that what you want is also an update of the tempo2 variable, by using a setTimeout call of a function that update the random values, use the tempo2 as new timeout.
var update = function () {
document.getElementById("my-video").playbackRate = tempo;
//update random values
tempo = Math.floor(Math.random() * 3) + 0.5;
tempo2 = Math.floor(Math.random() * 2000) + 1000;
console.log(tempo, tempo2);
//recall the method with new tempo2 value
setTimeout(update, tempo2);
}
See there:
JSFiddle

Jquery div strobe

I would like to have a div act like a strobe light with jquery. Basicly change the background color from black to white every 500 milliseconds.
How can I do that?
<div id="strobe"></div>
Thank you!
The setInterval() function is your friend here.
You don't need to use JQuery, you can do it inn pure javascript - this is how you'd do it:
var elem = document.getElementById("strobe");
var strobeBackground = function() {
(elem.style.backgroundColor == "white") ? elem.style.backgroundColor = "black" : elem.style.backgroundColor = "white";
}
setInterval(strobeBackground, 500);
However if you want to do it in jQuery, here it is: http://jsfiddle.net/Ru9xt/2/
The HTML would look like this:
<div id="strobe" class="white">Hello</div>
The CSS would look like this:
.white {
background-color: white;
}
.black {
background-color: black;
}
And the JS is here:
setInterval(function () {
$("#strobe").toggleClass('black');
}, 500);
You can use jQuery for both checking the background color of the element and for setting the interval at which it flickers with the $.css() method which gets or sets the style of an element and the setInterval() method which sets up a reoccurring method call.
function toggle(){
var strobe = $('#strobe');
if(strobe.css('background-color') == '#FFFFFF'){
strobe.css('background-color', '#000000');
}else{
strobe.css('background-color', '#FFFFFF');
}
}
setInterval(toggle, 500);
I used classes instead:
/**
* Initialise strobe using classes. By Emmanuel Mahuni - 2015
* #param {string} sel selector
* #param {int} i speed in milli-seconds
* #param {string} c1 class 1
* #param {string} c2 class 2
* #returns {int} the interval id so that you can clear it later
*/
function initStrobeClass(sel, i, c1, c2) {
return setInterval(strobeClass, i,sel,c1,c2);
}
/**
* Strobe using classes. By Emmanuel Mahuni - 2015
* #param {string} sel selector
* #param {string} c1 class 1
* #param {string} c2 class 2
*/
function strobeClass(sel, c1, c2) {
var s = $(sel);
s.toggleClass(c1 + " " + c2);
}
/**
* Clear the strobe to a particular class
* #param {int} t interval id
* #param {string} sel selector of the element
* #param {string} c the class to set after clearing the strobe
* #returns {null} returns null to make sure we don't come back here again, make sure the interval id is set by this and do the checking to eliminate errors.
*/
function clearStrobeToClass(t, sel, c) {
clearInterval(t);
$(sel).attr('class', c);
return null;
}
usage:
The code below will begin strobbing the logout button when the count down is below 181. It will restore it when it goes above 180.
if (autoLogoutCountdown <= 180 && (typeof strobeLogoutTimer !== typeof NaN)) {
strobeLogoutTimer = initStrobeClass('#logout', 1000, 'logoutflash', 'logout');
} else if (autoLogoutCountdown > 180 && (typeof strobeLogoutTimer === typeof NaN)) {
strobeLogoutTimer = clearStrobeToClass(strobeLogoutTimer, '#logout', 'logout');
}
I hope this helps someone

Categories

Resources