Closing 4 functions with different parameters in to array? - javascript

I could like to simplify my current code and close all four functions in array with passing equivalent parameters in to them .
function firstFunction() {
if (sound) {
var audio = document.getElementById("sound1");
audio.play();
}
sound = true;
$('#topleft').addClass('litTopLeft');
}
function secondFunction() {
if (sound) {
var audio = document.getElementById("sound2");
audio.play();
}
sound = true;
$('#topright').addClass('litTopRight');
}
function thirdFunction() {
if (sound) {
var audio = document.getElementById("sound3");
audio.play();
}
sound = true;
$('#bottomleft').addClass('litBottomLeft');
}
function fourthFunction() {
if (sound) {
var audio = document.getElementById("sound4");
audio.play();
};
sound = true;
$('#bottomright').addClass('litBottomRight');
}
All functions have similar parameters that need to be passed by like :
if (sound)
sound = true;
audio.play();
Rest of the parameters need to be equivalent to each function like:
var audio = document.getElementById("sound1");
$('#topleft').addClass('litTopLeft');

Make all the values that vary between the functions parameters.
function playFunction(soundid, targetid, classname) {
if (sound) {
var audio = document.getElementById(soundid);
audio.play();
}
sound = true;
$('#' + targetid).addClass(classname);
}
Then you call it like:
playFunction('sound1', 'topleft', 'litTopLeft');
You can remove one of the parameters if the target ID is always the same as the class with lit prefix removed.
function playFunction(soundid, classname) {
if (sound) {
var audio = document.getElementById(soundid);
audio.play();
}
sound = true;
var targetid = classname.replace('lit', '').toLowerCase();
$('#' + targetid).addClass(classname);
}
Then it's just
playFunction('sound1', 'litTopLeft');

Related

P5 JS - Saving an edited soundfile

let play_button = document.querySelector('#play_button');
let reverb_button = document.querySelector('#reverb_button');
let save_button = document.querySelector("#save_button");
let song, reverb, speed_slider, recorder;
let reverb_on = false;
function preload() {
song = loadSound('music/Mood.mp3');
}
function setup() {
speed_slider = createSlider(0.6, 1.5, 1, 0.1); // min, max, start, step
reverb = new p5.Reverb();
reverb.process(song, 10, 10); // 10 seconds duration, 10% decay
}
function draw() {
let val = 0;
if (reverb_on) val = 1;
reverb.drywet(val); // 1 is all reverb
song.rate(speed_slider.value());
}
function togglePlay() {
if (!song.isPlaying()) {
song.play();
play_button.innerText = "Stop"
} else {
song.pause();
play_button.innerText = "Play"
}
}
function toggleReverb() {
if (!reverb_on) {
reverb_button.innerText = 'off';
reverb_on = true;
} else {
reverb_button.innerText = 'on';
reverb_on = false
}
}
function saveSong() {
saveSound(song, 'mood')
}
Above is my code, trying to give the user an option to save the soundfile after they added different effects to it, such as reverb and speed control.
No matter what method I tried that was on the p5 documentation, including:
saveSound() -> https://p5js.org/reference/#/p5/saveSound
save() -> https://p5js.org/reference/#/p5.SoundFile/save
p5.SoundRecorder passing in the sound file itself.
None of them work and only save the original sound; doesn't save any of the 'changes' you make.

Toggling between Boolean variable

I'm wondering how you would toggle between two boolean variables. This works correctly the first time running the code but then after running it a second time the output isn't correct.
Output first time running switchPlayer():
player1.isActive = false,
player2.isActive = true
Output second time running switchPlayer():
player1.isActive = true,
player2.isActive = true
Below is the code I wrote:
var Player = function(score, isActive){
this.score = score;
this.isActive = isActive;
}
Player.prototype.toggleIsActive = function(){
if(this.isActive === false){
this.isActive = true;
} else{
this.isActive = false;
}
}
function switchPlayer(){
if(player1.isActive === true){
player1.toggleIsActive();
player2.toggleIsActive();
} else{
player1.isActive = true;
}
}
var player1 = new Player("0", true);
var player2 = new Player("0", false);
switchPlayer();
switchPlayer();
You can simplify it like this:
Player.prototype.toggleIsActive = function(){
this.isActive = !this.isActive;
}
function switchPlayer(){
player1.toggleIsActive();
player2.toggleIsActive();
}
ToggleIsActive should just be the opposite of what it once was. Also note that switchPlayer only calls toggle with no specific logic.
You can achieve this by removing the if/else from the switchPlayer() implementation:
function switchPlayer(){
player1.toggleIsActive();
player2.toggleIsActive();
}
Also, consider simplifying your toggleIsActive() method on the Player prototype like so:
Player.prototype.toggleIsActive = function(){
this.isActive = !this.isActive;
}
Here's a full example:
var Player = function(score, isActive){
this.score = score;
this.isActive = isActive;
}
Player.prototype.toggleIsActive = function(){
this.isActive = !this.isActive;
}
function switchPlayer(){
player1.toggleIsActive();
player2.toggleIsActive();
}
var player1 = new Player("0", true);
var player2 = new Player("0", false);
console.log('player1.isActive', player1.isActive)
console.log('player2.isActive', player2.isActive)
console.log('----------------')
switchPlayer();
console.log('player1.isActive', player1.isActive)
console.log('player2.isActive', player2.isActive)
console.log('----------------')
switchPlayer();
console.log('player1.isActive', player1.isActive)
console.log('player2.isActive', player2.isActive)
console.log('----------------')
let player1 = {};
let player2 = {};
player1.isActive = false;
player2.isActive = true;
function toggle () {
player1.isActive = !player1.isActive;
player2.isActive = !player2.isActive;
console.log('player1', player1.isActive, 'player2', player2.isActive);
}
<button onclick="toggle()">Toggle</button>

Audio player only plays, doesn't stop

I'm trying to make a simple audio player but it's just not working fine!
Here's the JavaScript:
var audio = document.getElementById("audio");
var isPlaying = false;
function togglePlay(element) {
element.classList.toggle("playing");
if (isPlaying) {
document.getElementById("audio").pause();
document.getElementById("audio").currentTime = 0;
} else {
document.getElementById("audio").play();
}
}
document.getElementById("audio").onplaying = function() {
var isPlaying = true;
};
document.getElementById("audio").onpause = function() {
var isPlaying = false;
};
Please help me!
var audio = document.getElementById("audio");
// use .paused instead
// var isPlaying = false;
function togglePlay(element) {
var promise;
if (!audio.paused) { /* isPlaying */
audio.pause();
audio.currentTime = 0;
element.classList.remove("playing");
} else {
// play is not instant, it returns a promise
promise = audio.play();
if (promise.then !== undefined) {
promise.then(function () {
element.classList.add("playing");
});
} else { /* old API */
element.classList.add("playing");
}
}
}
audio.onplaying = function() {
;
};
audio.onpause = function() {
;
};
Make sure to put the <script> at the end of the <body>
<script>/* put script at the end of body */</script>
</body>
</html>
Make sure the audio source for <audio> is an actual audio file. (not an html file containing audio) Open console and look at network requests.

Jquery Mobile stopwatch

Im trying to make a stopwatch in a JqueryMobile app. I've been following the guide from a previous post How to create a stopwatch using JavaScript?
This works but the function to create the button, essential just makes 3 links, where as I want them as buttons. So at present it will generate the html of:
start
where as I need it to be
start
I've played around with the function to try to get it to work, and even just added my own buttons into the HTML with hrefs of #start, #stop, #reset but cant get them to work
The function is:
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
Add the classes ui-btn ui-btn-inline to the links in createButton. As you are using jQuery anyway, I hvae also updated the stopwatch to use jQuery for DOM manipulation:
(function($) {
var Stopwatch = function (elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
var $elem = $(elem);
// append elements
$elem.empty()
.append(timer)
.append(startButton)
.append(stopButton)
.append(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return $('<span class="swTime"></span>');
}
function createButton(action, handler) {
var a = $('<a class="' + action + ' ui-btn ui-btn-inline">' + action + '</a>');
a.on("click",function (event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render();
}
function update() {
clock += delta();
render();
}
function render() {
timer.text(clock / 1000);
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
};
$.fn.stopwatch = function(options) {
return this.each(function(idx, elem) {
new Stopwatch(elem, options);
});
};
})(jQuery);
$(document).on("pagecreate","#page1", function(){
$(".stopwatch").stopwatch();
});
DEMO

How do I call a Javascript function outside of another Javascript function?

I have a javascript function that's supposed to toggle an animation when clicked by calling another function outside of it.
function MyFunction(id) {
var target = document.getElementById(id);
var on = true;
this.startMe = function() {
//animation code
on = true;
}
this.stopMe = function() {
//animation code
on = false;
}
this.toggleMe = function() {
if (on) this.stopMe();
else this.startMe();
}
target.addEventListener('click', function() {
this.toggleMe();
}, false);
}
The problem lies in the toggleMe and addEventListener functions. "this" refers to the function itself and not the one containing it, which is what I need it to reference. How can I work around this?
The easy fix is to use a closure variable as given below
function MyFunction(id) {
var self = this;
var target = document.getElementById(id);
var on = true;
this.startMe = function () {
//animation code
on = true;
}
this.stopMe = function () {
/animation code
on = false;
}
this.toggleMe = function() {
if (on) this.stopMe();
else this.startMe();
}
target.addEventListener('click', function() {
//this refers to the element here not the instance of MyFunction
//use a closure variable
self.toggleMe();
}, false);
}
Another solution is to pass a custom execution context to the callback using $.proxy() - you can use Function.bind() also but not supported in IE < 9
function MyFunction(id) {
var target = document.getElementById(id);
var on = true;
this.startMe = function () {
//animation code
on = true;
}
this.stopMe = function () {
//animation code
on = false;
}
this.toggleMe = function () {
if (on) this.stopMe();
else this.startMe();
}
//use Function.bind() to pass a custom execution context to
target.addEventListener('click', jQuery.proxy(function () {
// this refers to the element here not the instance of MyFunction
//use a closure variable
this.toggleMe();
}, this), false);
}
Also use .click()/on('click') to register the click handler instead of addEventListener
$(target).on('click', jQuery.proxy(function () {
// this refers to the element here not the instance of MyFunction
//use a closure variable
this.toggleMe();
}, this), false);
Simply add another variable with a reference to this but with a different name; then you can use that in your functions.
function MyFunction(id) {
var self = this;
var target = document.getElementById(id);
var on = true;
this.startMe = function() {
on = true;
}
this.stopMe = function() {
on = false;
}
this.toggleMe = function() {
if (on) self.stopMe();
else self.startMe();
}
target.addEventListener('click', function() {
self.toggleMe();
}, false);
}
My personal preference is to take it even one step further and continue to use self everywhere that makes sense:
function MyFunction(id) {
var self = this;
var target = document.getElementById(id);
var on = true;
self.startMe = function() {
on = true;
}
self.stopMe = function() {
on = false;
}
self.toggleMe = function() {
if (on) self.stopMe();
else self.startMe();
}
target.addEventListener('click', function() {
self.toggleMe();
}, false);
}

Categories

Resources