Is there a way to do this in javascript? - javascript

All I want to do is to make the code below more compressed, because i have hundreds of words to vocalize.
<audio id="aufgabe" preload="auto">
<source src="../../../audio/aufgabe.mp3" type="audio/mpeg">Your browser does not support the audio element.</audio>
<button id="idj-play-button" class="btn btn-xs"><i class="glyphicon glyphicon-play"></i></button>
<button id="idj-pause-button" class="btn btn-xs hide"><i class="glyphicon glyphicon-pause"></i></button>
<script>
$('#idj-play-button').click(function() {
document.getElementById('aufgabe').play();
$('#idj-play-button').addClass('hide');
$('#idj-pause-button').removeClass('hide');
});
$('#idj-pause-button').click(function() {
document.getElementById('aufgabe').pause();
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
});
$('#aufgabe').on('ended', function() {
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
$('#aufgabe').load();
});
</script>
I have almost zero knowledge in javascript so I was wondering is there any way to make some kind of function, for example:
function vocalizeFile(aufgabe);
that leads to the other functions
<script>
$('#idj-play-button').click(function() {
document.getElementById('aufgabe').play();
$('#idj-play-button').addClass('hide');
$('#idj-pause-button').removeClass('hide');
});
$('#idj-pause-button').click(function() {
document.getElementById('aufgabe').pause();
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
});
$('#aufgabe').on('ended', function() {
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
$('#aufgabe').load();
});
</script>
so I dont have to make copy of this code everytime.
Thanks in advance!

You can trigger the event creating a custom data attribute and attaching a click event to it:
HTML:
<audio id="aufgabe" preload="auto">
<source src="../../../audio/aufgabe.mp3" type="audio/mpeg">Your browser does not support the audio element.
</audio>
<button id="idj-play-button" class="btn btn-xs" data-action="play" data-target="#aufgabe">
Play
</button>
<button id="idj-pause-button" class="btn btn-xs hide" data-action="pause" data-target="#aufgabe">
Pause
</button>
jQuery:
$('body').on('click','[data-action]',function() {
var action = $(this).data('action');
var target = $(this).data('target');
switch(action) {
case 'play':
$(target)[0].play();
break;
case 'pause':
$(target)[0].pause();
break;
}
console.log('Called action ',action,' on element ',target);
});
This way you just have to add data-action=[action-name] and data-target=#idOfTarget to each button and they'll work on any valid <audio> element with the specified id.

var $play = $('#idj-play-button');
var $pause = $('#idj-pause-button');
var $aufgabe = $('#aufgabe');
$play.click(playAudio);
$pause.click(pauseAudio);
$aufgabe.on('ended', onEnd);
var toggleButtons = function() {
$play.toggleClass('hide');
$pause.toggleClass('hide');
}
var playAudio = function() {
$aufgabe.play();
toggleButtons();
}
var pauseAudio = function() {
$aufgabe.pause();
toggleButtons()
}
var onEnd = function() {
$aufgabe.load();
toggleButtons();
}

I've just compressed your code and now it looks like this:
var $play = $('#idj-play-button');
var $pause = $('#idj-pause-button');
var $aufgabe = $('#aufgabe');
$play.on('click', function() {
playAudio();
toggleButtons();
});
$pause.on('click', function() {
pauseAudio();
toggleButtons();
});
$aufgabe.on('ended', function() {
loadAudio();
toggleButtons();
});
var toggleButtons = function() {
$play.toggleClass('hide');
$pause.toggleClass('hide');
}
var playAudio = function() {
$aufgabe.play();
}
var pauseAudio = function() {
$aufgabe.pause();
}
var loadAudtion = function() {
$aufgabe.load();
}
At first, I've cached all elements... If your variable contains an element, I recommend that you start it with $, because it says us that the variable is a jquery-element.
If you need to add class and then remove it, you should use toggleClass.
The code that manipulates with audio was divided by functions, because we need to maintain one level of abstructions.

Related

Callback Function does not work with for Loop

Why doesn't the callButtonTwo() function work on all buttons? Only button1 reacts to it?
document.querySelector("h1").addEventListener("click", function() {
alert("Working!");
})
var totalButton = document.querySelectorAll(".testSecond").length;
for (var i = 0; i < totalButton; i++) {
document.querySelectorAll(".testSecond")[i].addEventListener("click", function() {
var buttonNow = this.innerHTML;
callButtonOne(buttonNow);
callButtonTwo(buttonNow);
});
}
function callButtonOne() {
alert("I got clicked!");
};
function callButtonTwo() {
var changeRed = document.querySelector(".testSecond");
changeRed.classList.add("red");
setTimeout(function() {
changeRed.classList.remove("red");
}, 300);
};
.red {
background-color: red;
}
<h1 class="testFirst">Hello World!</h1>
<button class="testSecond button1" type="button" name="button">button1</button>
<button class="testSecond button2" type="button" name="button">button2</button>
<button class="testSecond button3" type="button" name="button">button3</button>
<button class="testSecond button4" type="button" name="button">button4</button>
<button class="testSecond button5" type="button" name="button">button5</button>
While, inside your click handler you have var buttonNow = this.innerHTML; which operates on that button, when you call callButtonTwo you say var changeRed = document.querySelector(".testSecond"); which operates on the first button (no matter which button you click).
You need to tell it which button you are dealing with (e.g. by passing this as an argument)
The problem is, that your querySelector in callButtonTwo just finds the first button because all of them have the same class .testSecond.
One possible solution is to add the reference of the button which should be colored red to the callButtonTwo function and use the reference to add the class name.
It would look like this:
function callButtonTwo(button) {
button.classList.add("red");
setTimeout(function() {
button.classList.remove("red");
}, 300);
};
And you would call it like this: callButtonTwo(this);
Here's a working example based on the code you provided.
Inside callButtonTwo you're querying .testSecond again which will always return the first element in the page with that class. If you want to handle each button differently you should pass the button element as a parameter to callButtonTwo, like so:
var totalButton = document.querySelectorAll(".testSecond").length;
for (var i = 0; i < totalButton; i++) {
document.querySelectorAll(".testSecond")[i].addEventListener("click", function() {
var buttonNow = this.innerHTML;
callButtonOne(buttonNow);
callButtonTwo(this); // 'this' in this case is the clicked button element
});
}
[...]
function callButtonTwo(button) {
button.classList.add("red");
setTimeout(function() {
button.classList.remove("red");
}, 300);
};
I would also consider to change the way you're iterating your elements in order to query the DOM less frequently:
// 'querySelectorAll' returns an array which can be directly iterated using its method 'forEach'
document.querySelectorAll(".testSecond").forEach(function(button) {
button.addEventListener("click", function() {
var buttonNow = this.innerHTML;
callButtonOne(buttonNow);
callButtonTwo(this);
});
});

Javascript object methods evaluate functions

first of all, I'm new to javascript.
my question is how can I add an event listener to the button and call the function from the myObj script. I tried to google but I don't know what is the keyword for that. thank you
<div id="my-btn"></div>
<script>
myObj.button('my-btn',{
onClick: function() {
alert('Button is clicked !');
},
onCancel: function() {
alert('You cancel the process !');
}
});
</script>
and my object
var myObj = {
button: function(btnId, methods)
{
var btn = document.getElementById(btnId);
for (var method in methods)
{
if (method.toLowerCase() == 'onclick')
{
//btn.addEventListener('click', function(e) {
//}
// i want to add listener
// and call the function "onClick"
}
}
// render button
btn.innerHTML = '<input type="button" value="My Button"></button>';
}
}
thank you for your advice.
Here's one way.
<html>
<head></head>
<body>
<div id="my-btn"></div>
</body>
<script>
const myObj = {
button: (btnId, methods) => {
const btn = document.getElementById(btnId);
for (let method in methods) {
const nameLower = method.toLowerCase();
if (nameLower.startsWith('on')) {
btn.addEventListener(nameLower.substr(2), function(e) {
methods[method]();
});
}
}
// render button
btn.innerHTML = '<input type="button" value="My Button"></button>';
}
};
myObj.button('my-btn',{
onClick: () => alert('Button is clicked !'),
onCancel: () => alert('You cancel the process !')
});
</script>
</html>
We can map the function names to their events by converting to lowercase and stripping off the "on" prefix. So onClick becomes click. You could simplify things by just using the standard event names in your call to myObj.button.
Start by iterating over the functions, map the name and add the event listener. Inside the event listener all we do is call the function provided in the arguments.

Clipboard.js loop buttons

I use clipboard.js and after a click on one of my buttons I want to show a success message under the button, but I am not able to loop throught.
This is the button:
<button type="button" class="clipboard-button button-rect" data-clipboard-text="{{ site.author.email|safe_email }}">
<span class="button-text">Get in touch</span>
<span class="clipboard-message">My E-Mail has been copied</span>
</button>
And this the js:
var clipboard = new ClipboardJS('.clipboard-button');
clipboard.on('success', function () {
var message = document.querySelectorAll('.clipboard-message');
message.style.opacity = '1';
setTimeout(function () {
message.style.opacity = '0';
}, 2000);
});
I want to show the message under the button which was pressed and not for every button.
I would appreciate your help, I tried so much. I'm an JS beginner btw, so be patient please. :)
On thing you should look at is achieving to retrieve the clicked DOM element (a button in this case). It will then be easy to find the corresponding .clipboard-message span element.
To retrieve the clicked element you can use the parameter given to the success event callback function, like stated here: https://clipboardjs.com/#events
Then your JavaScript code becomes:
var clipboard = new ClipboardJS('.clipboard-button');
clipboard.on('success', function (e) {
// e.trigger corresponds to the clipboard-button DOM element that triggered the event
// You can then use querySelector(...) to retrieve to first child element with the class clipboard-message
var message = e.trigger.querySelector('.clipboard-message');
message.style.opacity = '1';
setTimeout(function () {
message.style.opacity = '0';
}, 2000);
});
Here is a working code snippet for you to try:
var clipboard = new ClipboardJS('.clipboard-button');
clipboard.on('success', function (e) {
var message = e.trigger.querySelector('.clipboard-message');
message.style.opacity = '1';
setTimeout(function () {
message.style.opacity = '0';
}, 2000);
});
.clipboard-message {
color: green;
opacity: 0;
}
<script src="https://cdn.jsdelivr.net/npm/clipboard#2/dist/clipboard.min.js"></script>
<button type="button" class="clipboard-button button-rect" data-clipboard-text="{{ site.author.email|safe_email }}">
<span class="button-text">Get in touch</span>
<span class="clipboard-message">My E-Mail has been copied</span>
</button>
<button type="button" class="clipboard-button button-rect" data-clipboard-text="{{ site.author.email|safe_email }}">
<span class="button-text">Here is your ID</span>
<span class="clipboard-message">My ID has been copied</span>
</button>

adding class and removing class on click

I have audio player and i made on button click for music to stop and play again but i want to change icon on it aswell, but i dont know how to add i class and remove it on click, thanks. Here is my code, i want to remove fa-pause and add fa-play
var player = document.getElementById("player");
var isPlaying = false;
function togglePlay() {
if (isPlaying) {
player.pause()
} else {
player.play();
}
};
player.onplaying = function() {
isPlaying = true;
};
player.onpause = function() {
isPlaying = false;
};
<button class="button" onclick="togglePlay()"><i class="fas fa-pause"></i></button>
First add an id for your play/pause button.
<button id="control-btn" class="button" onclick="togglePlay()"><i class="fas fa-pause"></i></button>
Then select the <i class="fas fa-pause"></i> item and remove/add the class
var player = document.getElementById("player");
var isPlaying = false;
function togglePlay() {
var item = document.querySelector("#control-btn i");
if(isPlaying) {
player.pause();
item.classList.remove("fa-pause");
item.classList.add("fa-play");
} else {
player.play();
item.classList.remove("fa-play");
item.classList.add("fa-pause");
}
};
player.onplaying = function(){
isPlaying = true;
};
player.onpause = function(){
isPlaying = false;
};
Here is a working example. Your code contains needed few refactoring since you are using html only. I would recommend you use jquery to simplify the code.
https://jsfiddle.net/c5ystb4t/16/
code below is your sample.
var player = document.getElementById("player");
var isPlaying = false;
function togglePlay() {
if (isPlaying) {
player.pause()
} else {
player.play();
}
};
player.onplaying = function() {
isPlaying = true;
};
player.onpause = function() {
isPlaying = false;
};
<button class="button" onclick="togglePlay()"><i class="fas fa-pause"></i></button>
Just use the toggleClass method from classList:
document.getElementById( 'player' ).classList.toggleClass( 'fa-pause' )
document.getElementById( 'player' ).classList.toggleClass( 'fa-play' )
Make sure one of both classes is already active, otherwise both will activate or deactivate at once.
Edit I checked the docs on toggle and you can only do one class name per call.
document.getElementById( 'test' ).addEventListener('click', function( event ){
event.preventDefault();
event.target.classList.toggle( 'a' );
event.target.classList.toggle( 'b' );
})
.a { color: red !important; }
.b { color: yellow !important; }
Click me to toggle Classes
Docs: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
On a sidenote, you might want to get rid of your isPlaying variable and just use plater.paused, since it contains a boolean as well that you don't have to track, and therefor saves you a little bit of memory.

Adding a timed delay after pressing a button to prevent button spam

Say I have 4 buttons
<button id="one">One</button>
<button id="two">Two</button>
<button id="three">Three</button>
<button id="four">Four</button>
and to prevent spam, I want to make it so that whenever any of the buttons are pressed, none of them are able to be pressed again for the next 0.6 seconds.
How might I achieve this?
You can use this javascript code:
var btns = document.getElementsByTagName('button');
for(var i=0;i<btns.length;i++){
btns[i].addEventListener('click', function(){
disableButtons(true);
setTimeout(function(){disableButtons(false);}, 600);
});
}
function disableButtons(state){
for(var i=0;i<btns.length;i++){
btns[i].disabled = !!state;
}
}
Of course, you need to run this code after your page is loaded.
One way to do this is with a "click shield".
Here's how you can do it with jQuery.
var clickShield = false;
$('button').on('click', function() {
if (!clickShield) {
clickShield = true;
console.log('handle click event');
setTimeout(function() {
clickShield = false;
}, 600);
}
});
With jQuery you can do something like:
<button id="one">One</button>
<button id="two">Two</button>
<button id="three">Three</button>
<button id="four">Four</button>
$("button").on("click", function(e) {
$("button").attr('disabled', 'disabled');
setTimeout(function() {
$("button").removeAttr('disabled');
}, 600);
});
// Get button elements
var els = document.getElementByTagName('button');
// Add an event handler to click event
// that triggers settimeout to set the disable value
els.addListener('click', function(){
setTimeout(els.disable, 600);
}, true);
not tested
Like prasadmadanayake says in his comment you can do it by disable/enable the button.
Here is a working example:
var intVal = 0;
$('button').on('click',function (e) {
var id = $(this).attr('id');
$('#'+id).attr('disabled', 'disabled');
setTimeout(function(){enable(id)}, 3000);
return true;
});
function enable (id) {
$('#'+id).removeAttr('disabled');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="one">One</button>
<button id="two">Two</button>
<button id="three">Three</button>
<button id="four">Four</button>

Categories

Resources