I have created an audio player using javascript,
with the below Javascript, html, css I am getting expected result for one audio file in the HTML, when i add another audio file in the html, its not working.
Can you please anyone suggest how this can be handled for multiple audio files in the HTML?
Javascript
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.substr(0, 2),
time = minutes + ':' + seconds
return time;
}
function calculateCurrentValue(currentTime) {
var current_hour = parseInt(currentTime / 3600) % 24,
current_minute = parseInt(currentTime / 60) % 60,
current_seconds_long = currentTime % 60,
current_seconds = current_seconds_long.toFixed(),
current_time = (current_minute < 10 ? "0" + current_minute : current_minute) + ":" + (current_seconds < 10 ? "0" + current_seconds : current_seconds);
return current_time;
}
function initProgressBar() {
var player = document.getElementById('player');
var length = player.duration
var current_time = player.currentTime;
// calculate total length of value
var totalLength = calculateTotalValue(length)
jQuery(".end-time").html(totalLength);
// calculate current value time
var currentTime = calculateCurrentValue(current_time);
jQuery(".start-time").html(currentTime);
var progressbar = document.getElementById('seekObj');
progressbar.value = (player.currentTime / player.duration);
progressbar.addEventListener("click", seek);
if (player.currentTime == player.duration) {
$('#play-btn').removeClass('pause');
}
function seek(evt) {
var percent = evt.offsetX / this.offsetWidth;
player.currentTime = percent * player.duration;
progressbar.value = percent / 100;
}
};
function initPlayers(num) {
for (var i = 0; i < num; i++) {
(function() {
var playerContainer = document.getElementById('player-container'),
player = document.getElementById('player'),
isPlaying = false,
playBtn = document.getElementById('play-btn');
if (playBtn != null) {
playBtn.addEventListener('click', function() {
togglePlay()
});
}
// Controls & Sounds Methods
// ----------------------------------------------------------
function togglePlay() {
if (player.paused === false) {
player.pause();
isPlaying = false;
$('#play-btn').removeClass('pause');
} else {
player.play();
$('#play-btn').addClass('pause');
isPlaying = true;
}
}
}());
}
}
function muteAud(){
if (player.muted === false) {
player.muted = true;
$('#btn_muteUnmute').addClass('mute');
}
else
{
player.muted = false;
$('#btn_muteUnmute').removeClass('mute');
}
}
initPlayers(jQuery('#player-container').length);
Here is the HTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="audio-player">
<div id="play-btn"></div>
<div class="audio-wrapper" id="player-container">
<audio id="player" ontimeupdate="initProgressBar()">
<source
src="mmc03-01-9780128023198.mp3" type="audio/mp3"/></audio>
</div>
<div class="player-controls scrubber">
<div id="seekObjContainer">
<progress id="seekObj" value="0" max="1"></progress>
</div>
<small style="float: left; position: relative; left: 15px;" class="start-time"></small>
<small style="float: right; position: relative; right: 20px;" class="end-time"></small>
<div id="btn_muteUnmute"></div>
</div>
</div>
<script src="js/jquery.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
CSS:
html {
height: 100%;
display: table;
margin: auto;
}
body {
height: 100%;
display: table-cell;
vertical-align: middle;
}
.start-time
{
margin: 0rem 0rem 0 0rem;
}
.end-time
{
margin: 0rem 15rem 0 0rem;
}
.audio-player {
background: white;
width: 50vw;
text-align: center;
display: flex;
flex-flow: row;
margin: 4rem 0 4rem 0;
}
.audio-player .player-controls {
align-items: center;
justify-content: center;
margin-top: 2.5rem;
flex: 3;
}
.audio-player .player-controls progress {
width: 70%;
margin-left: -15.5rem;
}
.audio-player .player-controls progress[value] {
-webkit-appearance: none;
appearance: none;
background-color: white;
color: grey;
height: 6px;
}
.audio-player .player-controls progress[value]::-webkit-progress-bar {
background-color: #d3d3d3;
border-radius: 2px;
border: 1px solid #dfdfdf;
color: grey;
}
.audio-player .player-controls progress::-webkit-progress-value {
background-color: grey;
}
.audio-player .player-controls p {
font-size: 1.6rem;
}
.audio-player #play-btn {
background-image: url("../img/play.png");
background-size: cover;
width: 25px;
height: 25px;
margin: 2.7rem 0 2rem 2rem;
}
.audio-player #play-btn.pause {
background-image: url("../img/pause.png");
}
.audio-player #btn_muteUnmute {
background-image: url("../img/unmute.png");
background-size: cover;
width: 25px;
height: 25px;
margin: -1.9rem 0 2rem 48rem;
}
.audio-player #btn_muteUnmute.mute {
background-image: url("../img/mute.png");
}
html{font-size:10px;)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}
Here you id instead of class:
Change some of your code like this:
var playerContainer = document.querySelectorAll('.player-container'),
player = document.querySelectorAll('.player'),
isPlaying = false,
playBtn = document.querySelectorAll('.play-btn');
Note: You should loop through the element playerContainer, player and playBtn variable because querySelectorAll returns a list of Node.
Advice: if you use jQuery, use it for the selector.
Related
I currently use a marquee effect in the project!
I hope that in class = "placard", there is only one set of placard item, and the marquee stops executing. If
there is more than one set of placard item, the marquee will be executed. How to write my JavaScript What?
Since I am a newbie to JavaScript, I don't know how to implement it at all. I hope I can get your help.
function slideLine(box, stf, delay, speed, h) {
console.log('slideLine')
var slideBox = document.getElementById(box);
var delay = delay || 500,
speed = speed || 20,
h = h || 20;
var tid = null,
pause = false;
var s = function() {
tid = setInterval(slide, speed);
}
var slide = function() {
if (pause) return;
slideBox.scrollTop += 1;
if (slideBox.scrollTop % h == 0) {
clearInterval(tid);
slideBox.appendChild(slideBox.getElementsByTagName(stf)[0]);
slideBox.scrollTop = 0;
setTimeout(s, delay);
}
}
slideBox.onmouseover = function() {
pause = true;
}
slideBox.onmouseout = function() {
pause = false;
}
setTimeout(s, delay);
}
slideLine('js-placard', 'div', 1000, 25, 20);
.contact_placard .placard {
background-color: #fff0d8;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
padding: 8px 0px;
margin-top: 58px;
margin-bottom: 12px;
height: 20px;
overflow: hidden;
}
.contact_placard .placard_item {
display: flex;
align-items: center;
line-height: 5px;
}
.contact_placard .placard .megaphone {
display: inline-block;
width: 20px;
height: 20px;
background-size: cover;
margin-right: 8px;
}
.contact_placard .placard .placard_text {
font-size: 13px;
letter-spacing: 0.43px;
}
.contact_placard .placard .placard_link {
font-size: 13px;
letter-spacing: 0.43px;
margin-left: 8px;
color: red;
}
<section class="contact_placard">
<div class="placard" id="js-placard">
<div class="placard_item">
<span class="megaphone"></span>
<h3 class="placard_text">apple</h3>
</div>
<div class="placard_item">
<span class="megaphone"></span>
<h3 class="placard_text">Strawberry</h3>
</div>
<div class="placard_item">
<span class="megaphone"></span>
<h3 class="placard_text">banana</h3>
</div>
</div>
</section>
Thank you for your help~
At the beginning of the slideLine function you can test whether there are more than one elaments in the marquee - i.e. with class placard_item.
If there aren't then this snippet just returns without doing anything.
if (document.querySelectorAll('.placard_item').length <= 1) return;
Note: the test is put within the function rather than just before it is called because I don't know how dynamic your situation is. If more things are added or removed at run time and this function is called then it will do what is required.
function slideLine(box, stf, delay, speed, h) {
if (document.querySelectorAll('.placard_item').length <= 1) return;
console.log('slideLine')
var slideBox = document.getElementById(box);
var delay = delay || 500,
speed = speed || 20,
h = h || 20;
var tid = null,
pause = false;
var s = function() {
tid = setInterval(slide, speed);
}
var slide = function() {
if (pause) return;
slideBox.scrollTop += 1;
if (slideBox.scrollTop % h == 0) {
clearInterval(tid);
slideBox.appendChild(slideBox.getElementsByTagName(stf)[0]);
slideBox.scrollTop = 0;
setTimeout(s, delay);
}
}
slideBox.onmouseover = function() {
pause = true;
}
slideBox.onmouseout = function() {
pause = false;
}
setTimeout(s, delay);
}
slideLine('js-placard', 'div', 1000, 25, 20);
.contact_placard .placard {
background-color: #fff0d8;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
padding: 8px 0px;
margin-top: 58px;
margin-bottom: 12px;
height: 20px;
overflow: hidden;
}
.contact_placard .placard_item {
display: flex;
align-items: center;
line-height: 5px;
}
.contact_placard .placard .megaphone {
display: inline-block;
width: 20px;
height: 20px;
background-size: cover;
margin-right: 8px;
}
.contact_placard .placard .placard_text {
font-size: 13px;
letter-spacing: 0.43px;
}
.contact_placard .placard .placard_link {
font-size: 13px;
letter-spacing: 0.43px;
margin-left: 8px;
color: red;
}
<section class="contact_placard">
<div class="placard" id="js-placard">
<div class="placard_item">
<span class="megaphone"></span>
<h3 class="placard_text">apple</h3>
</div>
<div class="placard_item">
<span class="megaphone"></span>
<h3 class="placard_text">Strawberry</h3>
</div>
<div class="placard_item">
<span class="megaphone"></span>
<h3 class="placard_text">banana</h3>
</div>
</div>
</section>
My timer does not show when I input a certain time, and I have checked several times what the issue could be but have no errors. I am not sure if it is related to the javascript code.
Everything else works perfectly fine, e.g. the buttons for submit, continue and stop.
This is the HTML code:
<!DOCTYPE html>
<html>
<head>
<title>CountDown</title>
<link rel="stylesheet" type="text/css" href="style.css">
<link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet">
</head>
<body>
<header>
<h1>CountDown</h1>
</header>
<div class="content">
<div class="counter"></div>
<input type="number" id="seconds" placeholder="Seconds">
<div class="buttons">
<button class="btn start" id="start" value="1" onclick="check(this)">Start</button>
<button class="btn start" id="continue" value="1" onclick="check(this)">Continue</button>
<button class="btn stop" id="stop" value="0" onclick="check(this)">Stop</button>
<button class="btn start" id="ok" onclick="toSubmit()">Submit</button>
</div>
</div>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
This is the javascript code:
const container = document.querySelector('.counter');
const buttonsDiv = document.querySelector('.buttons');
const secInput = document.getElementById('.seconds');
var seconds;
var remseconds;
var minuts;
var toCount = false;
function toSubmit(){
display('start');
remove('seconds');
remove('ok');
seconds = Number(secInput.value);
counting();
}
function display(e){
document.getElementById(e).style.display = 'block';
}
function remove(e){
document.getElementById(e).style.display = 'none';
}
function check(stat){
toCount = this.value;
if(stat.id == "start"){
display("stop");
remove("start");
}
else if(stat.id == "stop"){
display("continue");
remove("stop");
}
else{
display("stop");
remove("continue");
}
}
function count(){
if(seconds > 0){
if(toCount == true){
seconds--;
remseconds = seconds % 60;
minuts = Math.floor(seconds / 60);
if(minuts < 10){
minuts = "0" + minuts;
}
if(remseconds < 10){
remseconds = "0" + remseconds;
}
container.innerHTML = minuts + " : " + remseconds;
}
}
else{
container.innerHTML = "DONE!";
buttonsDiv.style.opacity = "0";
}
}
function counting(){
remseconds = seconds % 60;
minuts = Math.floor(seconds / 60);
if(remseconds < 10){
remseconds = "0" + remseconds;
}
container.innerHTML = minuts + " : " + remseconds;
setInterval(count, 1000);
}
This is the CSS code:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
html, body{
height: 100%;
}
body{
width: 100%;
height: 100%;
background: linear-gradient(to left top, #0045D6, #00A9f6);
}
header{
width: 100%;
height: 13vh;
background-color: #fff;
color: #0045F6;
display: flex;
justify-content: center;
align-items: center;
}
.content{
width: 100%;
height: 60vh;
font-size: 3rem;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.content #seconds{
width: 250px;
font-size: 2rem;
padding: 1rem;
outline: none;
background: none;
border: none;
border-bottom: 3px solid #fff;
color: #fff;
}
#seconds::placeholder{
color: #ddd;
font-size: 1.7rem;
}
.btn{
background-color: #fff;
border-radius: 4px;
border: none;
outline: none;
cursor: pointer;
padding: 0.8rem 1.7rem;
font-size: 1.2rem;
font-weight: 700;
}
.start{
color: #1f0;
}
.stop{
color: #E00;
}
#start, #stop, #continue{
display: none;
}
.counter{
color: #fff;
}
Your selector is wrong: const secInput = document.getElementById('.seconds'); use . for classes. change this line as following: const secInput = document.getElementById('seconds');
After Edit:
Ok. take a look at following snippet:
usage of toCount variable was incorrect.
const container = document.querySelector('.counter');
const buttonsDiv = document.querySelector('.buttons');
const secInput = document.getElementById('seconds');
var seconds;
var remseconds;
var minuts;
var toCount = false;
function toSubmit(){
display('start');
remove('seconds');
remove('ok');
seconds = Number(secInput.value);
counting();
}
function display(e){
document.getElementById(e).style.display = 'block';
}
function remove(e){
document.getElementById(e).style.display = 'none';
}
function check(stat){
if(stat.id == "start"){
display("stop");
remove("start");
toCount = true;
}
else if(stat.id == "stop"){
display("continue");
remove("stop");
toCount = false;
}
else{
display("stop");
remove("continue");
toCount =true;
}
}
function count(){
if(seconds > 0){
if(toCount == true){
seconds--;
remseconds = seconds % 60;
minuts = Math.floor(seconds / 60);
if(minuts < 10){
minuts = "0" + minuts;
}
if(remseconds < 10){
remseconds = "0" + remseconds;
}
container.innerHTML = minuts + " : " + remseconds;
}
}
else{
container.innerHTML = "DONE!";
buttonsDiv.style.opacity = "0";
}
}
function counting(){
remseconds = seconds % 60;
minuts = Math.floor(seconds / 60);
if(remseconds < 10){
remseconds = "0" + remseconds;
}
container.innerHTML = minuts + " : " + remseconds;
setInterval(count, 1000);
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
html, body{
height: 100%;
}
body{
width: 100%;
height: 100%;
background: linear-gradient(to left top, #0045D6, #00A9f6);
}
header{
width: 100%;
height: 13vh;
background-color: #fff;
color: #0045F6;
display: flex;
justify-content: center;
align-items: center;
}
.content{
width: 100%;
height: 60vh;
font-size: 3rem;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.content #seconds{
width: 250px;
font-size: 2rem;
padding: 1rem;
outline: none;
background: none;
border: none;
border-bottom: 3px solid #fff;
color: #fff;
}
#seconds::placeholder{
color: #ddd;
font-size: 1.7rem;
}
.btn{
background-color: #fff;
border-radius: 4px;
border: none;
outline: none;
cursor: pointer;
padding: 0.8rem 1.7rem;
font-size: 1.2rem;
font-weight: 700;
}
.start{
color: #1f0;
}
.stop{
color: #E00;
}
#start, #stop, #continue{
display: none;
}
.counter{
color: #fff;
}
<head>
<title>CountDown</title>
<link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet">
</head>
<body>
<header>
<h1>CountDown</h1>
</header>
<div class="content">
<div class="counter"></div>
<input type="number" id="seconds" placeholder="Seconds">
<div class="buttons">
<button class="btn start" id="start" value="1" onclick="check(this)">Start</button>
<button class="btn start" id="continue" value="1" onclick="check(this)">Continue</button>
<button class="btn stop" id="stop" value="0" onclick="check(this)">Stop</button>
<button class="btn start" id="ok" onclick="toSubmit()">Submit</button>
</div>
</div>
</body>
Here is a fix which should make your code work
function check(stat){
seconds = Number(document.getElementById('seconds').value);
if(stat.id == "start"){
display("stop");
remove("start");
}
else if(stat.id == "stop"){
display("continue");
remove("stop");
}
else{
display("stop");
remove("continue");
}
counting();
}
you should be reading value inside check
Also when you are using getElementById do not use (.seconds)
It would be document.getElementById('seconds')
Call counting inside the check function to start counting
In counting function make the toCount flag = true
Make the toCount flag = false when 'DONE'
You only need to update a few things:
function check(stat){
toCount = stat.value;
// not this.value
const secInput = document.getElementById('seconds');
// not const secInput = document.getElementById('.seconds');
This is enough to make it work.
Tip: if you are not sure what the value of a variable is during execution, you can try a console.log. In Firefox, Chrome you can go to developer tools - inspector, tab console to view the result.
This is wat I did:
function check(stat){
toCount = this.value;
console.log(toCount);
This showed me that toCount was undefined, not the value I expected and made me clear that "this" is not valid here, it's about the passed object "stat".
I'm practicing js and for long time i cant solve problem bellow.
I have function for changing the blurry background "changeBg", but it does not work when called.
Also key event function are not working dont know why.
I will appreciate any hints where to search for problems.
I know the code is wet but it's far from end "product".
//counting img tags
var n = $("img").length;
var m = n - 2;
//alert("jest " + m + "tagow img");
//adding onclick to source of file
var source = $(".slider-inner > img").attr("src");
$(".slider-inner > img").attr("onclick", "location.href=\'" + source + "\'");
for (i = 1; i <= m; i++) {
$(".dotcontainer").append($("<div class=\"dot\">x</div>"));
$('.slider-inner img').attr('id', function (i) {
return 'x' + (i + 1);
});
$('.dotcontainer div').attr('id', function (i) {
return 'x' + (i + 1);
});
var url = $('.slider-inner img:nth-child(' + i + ')').attr("src");
console.log(i);
}
///temporary solution for initial background
$(".bg").css('background', "url('"+ source +"')");
$(".bg").css('background-repeat', "no-repeat");
$(".bg").css('background-size', "cover");
$(".bg").css('background-position', "center");
//making first dot active
$('.dotcontainer div:nth-child(' + 1 + ')').addClass('activee');
//function changing backgorund
function changeBg() {
$(".bg").css('background', "url('"+ source +"')");
$(".bg").css('background-repeat', "no-repeat");
$(".bg").css('background-size', "cover");
$(".bg").css('background-position', "center");
};
// next buttton
$('.next').on('click', function nextImage() {
var currentImg = $('.active');
var nextImg = currentImg.next();
var currentdot = $('.activee');
var nextdot = currentdot.next();
if (nextImg.length) {
currentImg.removeClass('active').css('z-index', -10);
nextImg.addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
nextdot.addClass('activee');
var source = nextImg.attr("src");
nextImg.attr("onclick", "location.href=\'" + source + "\'");
changeBg();
} else {
currentImg.removeClass('active').css('z-index', -10);
$('#x1').addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
$('.dotcontainer div:nth-child(' + 1 + ')').addClass('activee');
}
});
//prev button
$('.prev').on('click', function prevImage() {
var currentImg = $('.active');
var prevImg = currentImg.prev();
var currentdot = $('.activee');
var prevdot = currentdot.prev();
var n = $("img").length;
var m = n - 2;
if (prevImg.length) {
currentImg.removeClass('active').css('z-index', -10);
prevImg.addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
prevdot.addClass('activee');
changeBg();
} else {
currentImg.removeClass('active').css('z-index', -10);
$('.slider-inner img:nth-child(' + m + ')').addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
$('.dotcontainer div:nth-child(' + m + ')').addClass('activee');
}
});
//switch active dots
$(".dot").click(function (event) {
$('.activee').attr('class', 'dot');
$(this).attr('class', 'dot activee');
var aktkrop = $(".activee").attr("id");
var fotoa = $('.slider-inner .active').attr("id");
$(".active").removeClass("active");
$("#" + aktkrop).attr("class", "active")
});
//temp shadowbox temporary solution
$('.btn').on('click', function () {
$(".boxx").css("display", "block");
});
$('.close').on('click', function () {
$(".boxx").css("display", "none");
});
document.addEventListener('keydown',function(e){
if (e.keyCode === 37) {
prevImage();
} else if(e.keyCode === 39) {
nextImage();
}
});
body {
font-family: "Arial", sans-serif;
font-size: 14px;
color: #fff;
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
margin: 0;
padding: 0;
}
.bg{
z-index: -2;
position: absolute;
width: 100%;
height: 100%;
filter: blur(30px);
-webkit-filter: blur(30px);
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
margin: 0;
padding: 0;
}
.blackshadow{
z-index: -1;
position: absolute;
width: 100%;
height: 100%;
background-color: black;
opacity: 0.6;
}
a {
color: #fff;
text-decoration: none;
}
h1 {
text-align: center;
}
.container {
width: 540px;
margin: 40px auto;
overflow: auto;
}
.slider-inner {
width: 500px;
height: 300px;
position: relative;
overflow: hidden;
float: left;
padding: 3px;
border: #666 solid 1px;
}
.slider-inner img {
display: none;
width: 500px;
height: 300px;
}
.slider-inner img.active {
display: inline-block;
}
.prev,
.next {
float: left;
margin-top: 130px;
cursor: pointer;
}
.prev {
position: relative;
margin-right: -45px;
z-index: 100;
}
.next {
position: relative;
margin-left: -45px;
z-index: 100;
}
.buba {
display: flex;
align-items: center;
justify-content: center;
}
.dotcontainer {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
align-items: center;
justify-content: center;
}
.dot {
cursor: pointer;
margin: 5px;
width: 20px;
height: 20px;
background-color: gray;
border-radius: 50%;
text-align: center;
justify-content: center;
color: black;
font-weight: 800;
}
.activee {
background-color: white;
}
.boxx {
width: 100%;
height: 100%;
background-color: black;
opacity: 0.6;
position: fixed;
z-index: 11;
margin: 0;
padding: 0;
display: none;
}
.close {
margin-left: 300px;
margin-top: 300px;
z-index: 11;
}
<html>
<head>
<title>Page Title</title>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA="
crossorigin="anonymous"></script>
</head>
<body>
<div class="bg"></div>
<div class="blackshadow"></div>
<div class="boxx">
<div class="closee">
<button class="close">Close</button>
</div>
</div>
<button class="btn">Kliknij</button>
<div class="container">
<h1>JQSlider</h1>
<div class="slider-outer">
<img src="http://www.fotem.pl/data/7d87e07a3066629171add66003d.png" id="prev" class="prev" alt="Prev">
<div class="slider-inner">
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832_1280.jpg" class="active">
<img src="https://cdn.pixabay.com/photo/2015/12/01/20/28/green-1072828_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2015/06/19/21/24/the-road-815297_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2015/01/28/23/35/landscape-615429_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2019/09/30/14/51/squirrel-4515962_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2016/07/22/16/29/fog-1535201_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2016/11/23/13/48/beach-1852945_1280.jpg">
</div>
<img src="http://www.fotem.pl/data/6f1498615d84ca14dbf0de784bd.png" id="next" class="next" alt="Next">
</div>
</div>
<div class="dotcontainer">
</div>
</body>
<script type="text/javascript" src="script.js">
</script>
</html>
Thank you in advance.
Code:
https://codepen.io/odzeradodeveloperajava/pen/EMLbzz
The background did not change as the source variable was not up-to date with the image src. You will need to ensure, that the source is not only declared once, but the value in it will always be updated on every event.
The keyup event handler is throwing exceptions as it cannot access the nextImage() and prevImage() methods. You will need to separate the methods and re-use them when needed as callBackFunction or just call it directly:
function prevImage() {
// code inside
}
function nextImage() {
// code inside
}
$('.next').on('click', nextImage);
$('.prev').on('click', prevImage);
document.addEventListener('keyup', function (e) {
if (e.keyCode === 37) {
prevImage();
} else if (e.keyCode === 39) {
nextImage();
}
});
I've made several changes to the example you've shared. Here is a working Pen: https://codepen.io/attila-antal/pen/KKKVGEd
first of all you have to declare your function nextImage and prevImage outside of the event listener. for example:
function nextImage() {
// your code
}
$('.next').on('click', nextImage);
The background does not change because you have to pass new source to your function. for example:
function changeBg(source) {
// your code
}
When you want to invoke changeBg function you should pass new source: for example: changeBg(newImageUrl);
I'm trying to replicate this audio player:
https://medium.com/s/story/the-law-of-least-effort-is-the-success-secret-nobody-talks-about-c713eeab8ade)
with a grey progress line, but I can't seem to figure out the following 4 things:
How to put the progress bar next to the play/pause button?
How to have 2 decimals for the total time digit? (The 48 seconds)
How to have 2 decimals for the currentTimer? (First 9 seconds)
How to place the timers at the beginning and the end?
var barSize = 640;
var bar = document.getElementById('defaultBar');
var progressBar = document.getElementById('progressBar');
mytrack.addEventListener("loadedmetadata", function() {
var minutes = parseInt(mytrack.duration / 60);
var seconds = parseInt(mytrack.duration % 60);
duration.innerHTML = minutes + ':' + seconds;
})
duration.innerHTML = mytrack.duration;
playButton.addEventListener('click', playOrPause, false);
bar.addEventListener('click', clickedBar, false);
#progressBar {
position: absolute;
height: 2px;
background-color: #C6C6C6;
width: 0px;
float: left;
}
#playButton {
background-color: #FFFFFF;
border: none;
outline: none;
height: 60px;
width: 60px;
background-image: url(../Desktop/Play%20button.png);
background-repeat: no-repeat;
background-position: center;
}
#player {
background-color: #FFFFFF;
width: 400px;
margin-left: 300px;
padding: 5px;
box-sizing: border-box;
}
<div id="wrapper">
<audio id="mytrack">
<source src="file:///Users/Pier/Desktop/Narrated%20Story%20-%20Example.m4a" type="audio/mp3"/>
</audio>
<nav>
<div id="defaultBar">
<div id="progressBar"></div>
</div>
<div id="buttons">
<button type="button" id="playButton"></button>
<span id="currentTime">0:00</span>
<span id="fullDuration">0:00</span>
</div>
</nav>
</div>
The page you referenced uses flexbox for layout. You might consider a similar approach.
Below, I restructured your HTML and made each control element a flexbox item.
I also centered all items vertically with align-items:center.
var myTrack = document.getElementById('myTrack');
var progressBar = document.getElementById('progressBar');
var currentTime = document.getElementById('currentTime');
var fullDuration = document.getElementById('fullDuration');
function zeroPad(s) {
return ('00' + s).slice(-2);
}
function formatTime(t) {
var m = Math.floor(t / 60);
var s = Math.floor(t % 60);
return zeroPad(m) + ':' + zeroPad(s);
}
function playOrPause() {
myTrack.paused ? myTrack.play() : myTrack.pause();
}
myTrack.addEventListener("loadedmetadata", function() {
fullDuration.innerHTML = formatTime(this.duration);
});
myTrack.addEventListener("timeupdate", function() {
var thisTime = this.currentTime;
var duration = this.duration;
progressBar.style.width = thisTime / duration * 100 + '%';
currentTime.innerHTML = formatTime(thisTime);
});
playButton.addEventListener('click', playOrPause, false);
#audioControls {
display: flex;
align-items: center;
}
.controlTime {
margin: 0 1em;
}
#progressWrap {
/* Allow this element to grow */
flex: 1 0 auto;
border: 1px solid #EEE;
border-radius: 0.5em;
overflow: hidden;
}
#progressBar {
height: 0.5em;
background-color: #55AA55;
width: 0;
}
#playButton {
background-color: #FFFFFF;
border: 1px solid #CCC;
border-radius: 3px;
padding: 0.7em 1em;
outline: none;
cursor: pointer;
}
#playButton:hover {
background-color: darkgray;
color: white;
}
<div id="wrapper">
<audio id="myTrack">
<source src="https://example-files.online-convert.com/audio/m4a/example.m4a" type="audio/mp3"/>
</audio>
<nav id="audioControls">
<button type="button" id="playButton">play</button>
<span class="controlTime" id="currentTime">00:00</span>
<div id="progressWrap">
<div id="progressBar"></div>
</div>
<span class="controlTime" id="fullDuration">00:00</span>
</nav>
</div>
I'm converting a player in html into a Vue component.
Half of the component is already created, only the time control slider is missing.
Here is the html player code (Lines with multiple tabs are already implemented in the Vue component):
var audioPlayer = document.querySelector('.green-audio-player');
var playPause = audioPlayer.querySelector('#playPause');
var playpauseBtn = audioPlayer.querySelector('.play-pause-btn');
var loading = audioPlayer.querySelector('.loading');
var progress = audioPlayer.querySelector('.progress');
var sliders = audioPlayer.querySelectorAll('.slider');
var player = audioPlayer.querySelector('audio');
var currentTime = audioPlayer.querySelector('.current-time');
var totalTime = audioPlayer.querySelector('.total-time');
var speaker = audioPlayer.querySelector('#speaker');
var draggableClasses = ['pin'];
var currentlyDragged = null;
window.addEventListener('mousedown', function(event) {
if(!isDraggable(event.target)) return false;
currentlyDragged = event.target;
let handleMethod = currentlyDragged.dataset.method;
this.addEventListener('mousemove', window[handleMethod], false);
window.addEventListener('mouseup', () => {
currentlyDragged = false;
window.removeEventListener('mousemove', window[handleMethod], false);
}, false);
});
playpauseBtn.addEventListener('click', togglePlay);
player.addEventListener('timeupdate', updateProgress);
player.addEventListener('loadedmetadata', () => {
totalTime.textContent = formatTime(player.duration);
});
player.addEventListener('canplay', makePlay);
player.addEventListener('ended', function(){
playPause.attributes.d.value = "M18 12L0 24V0";
player.currentTime = 0;
});
sliders.forEach(slider => {
let pin = slider.querySelector('.pin');
slider.addEventListener('click', window[pin.dataset.method]);
});
function isDraggable(el) {
let canDrag = false;
let classes = Array.from(el.classList);
draggableClasses.forEach(draggable => {
if(classes.indexOf(draggable) !== -1)
canDrag = true;
})
return canDrag;
}
function inRange(event) {
let rangeBox = getRangeBox(event);
let rect = rangeBox.getBoundingClientRect();
let direction = rangeBox.dataset.direction;
if(direction == 'horizontal') {
var min = rangeBox.offsetLeft;
var max = min + rangeBox.offsetWidth;
if(event.clientX < min || event.clientX > max) return false;
} else {
var min = rect.top;
var max = min + rangeBox.offsetHeight;
if(event.clientY < min || event.clientY > max) return false;
}
return true;
}
function updateProgress() {
var current = player.currentTime;
var percent = (current / player.duration) * 100;
progress.style.width = percent + '%';
currentTime.textContent = formatTime(current);
}
function getRangeBox(event) {
let rangeBox = event.target;
let el = currentlyDragged;
if(event.type == 'click' && isDraggable(event.target)) {
rangeBox = event.target.parentElement.parentElement;
}
if(event.type == 'mousemove') {
rangeBox = el.parentElement.parentElement;
}
return rangeBox;
}
function getCoefficient(event) {
let slider = getRangeBox(event);
let rect = slider.getBoundingClientRect();
let K = 0;
if(slider.dataset.direction == 'horizontal') {
let offsetX = event.clientX - slider.offsetLeft;
let width = slider.clientWidth;
K = offsetX / width;
} else if(slider.dataset.direction == 'vertical') {
let height = slider.clientHeight;
var offsetY = event.clientY - rect.top;
K = 1 - offsetY / height;
}
return K;
}
function rewind(event) {
if(inRange(event)) {
player.currentTime = player.duration * getCoefficient(event);
}
}
function formatTime(time) {
var min = Math.floor(time / 60);
var sec = Math.floor(time % 60);
return min + ':' + ((sec<10) ? ('0' + sec) : sec);
}
function togglePlay() {
if(player.paused) {
playPause.attributes.d.value = "M0 0h6v24H0zM12 0h6v24h-6z";
player.play();
} else {
playPause.attributes.d.value = "M18 12L0 24V0";
player.pause();
}
}
function makePlay() {
playpauseBtn.style.display = 'block';
loading.style.display = 'none';
}
.audio.green-audio-player {
width: 400px;
min-width: 300px;
height: 56px;
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.07);
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 24px;
padding-right: 24px;
border-radius: 4px;
user-select: none;
-webkit-user-select: none;
background-color: #fff;
}
.audio.green-audio-player .play-pause-btn {
display: none;
cursor: pointer;
}
.audio.green-audio-player .spinner {
width: 18px;
height: 18px;
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/355309/loading.png);
background-size: cover;
background-repeat: no-repeat;
animation: spin 0.4s linear infinite;
}
.audio.green-audio-player .slider {
flex-grow: 1;
background-color: #D8D8D8;
cursor: pointer;
position: relative;
}
.audio.green-audio-player .slider .progress {
background-color: #44BFA3;
border-radius: inherit;
position: absolute;
pointer-events: none;
}
.audio.green-audio-player .slider .progress .pin {
height: 16px;
width: 16px;
border-radius: 8px;
background-color: #44BFA3;
position: absolute;
pointer-events: all;
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.32);
}
.audio.green-audio-player .controls {
font-family: 'Roboto', sans-serif;
font-size: 16px;
line-height: 18px;
color: #55606E;
display: flex;
flex-grow: 1;
justify-content: space-between;
align-items: center;
margin-left: 24px;
}
.audio.green-audio-player .controls .slider {
margin-left: 16px;
margin-right: 16px;
border-radius: 2px;
height: 4px;
}
.audio.green-audio-player .controls .slider .progress {
width: 0;
height: 100%;
}
.audio.green-audio-player .controls .slider .progress .pin {
right: -8px;
top: -6px;
}
.audio.green-audio-player .controls span {
cursor: default;
}
svg, img {
display: block;
}
#keyframes spin {
from {
transform: rotateZ(0);
}
to {
transform: rotateZ(1turn);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="audio green-audio-player">
<div class="loading">
<div class="spinner"></div>
</div>
<div class="play-pause-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="24" viewBox="0 0 18 24">
<path fill="#566574" fill-rule="evenodd" d="M18 12L0 24V0" class="play-pause-icon" id="playPause"/>
</svg>
</div>
<div class="controls">
<span class="current-time">0:00</span>
<div class="slider" data-direction="horizontal">
<div class="progress">
<div class="pin" id="progress-pin" data-method="rewind"></div>
</div>
</div>
<span class="total-time">0:00</span>
</div>
<audio>
<source src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/355309/Swing_Jazz_Drum.mp3" type="audio/mpeg">
</audio>
</div>
Html Codepen: https://codepen.io/caiokawasaki/pen/JwVwry
Here is the Vue component:
Vue.component('audio-player', {
props: ['message'],
data: () => ({
audio: undefined,
loaded: false,
playing: false,
currentTime: '00:00',
totalTime: '00:00',
percent: '0%',
draggableClasses: ['pin'],
currentlyDragged: null
}),
computed: {},
methods: {
formatTime(time) {
var min = Math.floor(time / 60);
var sec = Math.floor(time % 60);
return min + ':' + ((sec < 10) ? ('0' + sec) : sec);
},
loadedMetaData() {
this.totalTime = this.formatTime(this.audio.duration)
},
canPlay() {
this.loaded = true
},
timeUpdate(){
var current = this.audio.currentTime;
var percent = (current / this.audio.duration) * 100;
this.percent = percent + '%';
this.currentTime = this.formatTime(current);
},
ended(){
this.playing = false
this.audio.currentTime = 0
},
isDraggable(el) {
let canDrag = false;
let classes = Array.from(el.classList);
this.draggableClasses.forEach(draggable => {
if (classes.indexOf(draggable) !== -1)
canDrag = true;
})
return canDrag;
},
inRange(event) {
let rangeBox = getRangeBox(event);
let rect = rangeBox.getBoundingClientRect();
let direction = rangeBox.dataset.direction;
if (direction == 'horizontal') {
var min = rangeBox.offsetLeft;
var max = min + rangeBox.offsetWidth;
if (event.clientX < min || event.clientX > max) return false;
} else {
var min = rect.top;
var max = min + rangeBox.offsetHeight;
if (event.clientY < min || event.clientY > max) return false;
}
return true;
},
togglePlay() {
if (this.audio.paused) {
this.audio.play();
this.playing = true;
} else {
this.audio.pause();
this.playing = false;
}
},
makePlay() {
playpauseBtn.style.display = 'block';
loading.style.display = 'none';
},
getRangeBox(event) {
let rangeBox = event.target;
let el = currentlyDragged;
if (event.type == 'click' && isDraggable(event.target)) {
rangeBox = event.target.parentElement.parentElement;
}
if (event.type == 'mousemove') {
rangeBox = el.parentElement.parentElement;
}
return rangeBox;
},
getCoefficient(event) {
let slider = getRangeBox(event);
let rect = slider.getBoundingClientRect();
let K = 0;
if (slider.dataset.direction == 'horizontal') {
let offsetX = event.clientX - slider.offsetLeft;
let width = slider.clientWidth;
K = offsetX / width;
} else if (slider.dataset.direction == 'vertical') {
let height = slider.clientHeight;
var offsetY = event.clientY - rect.top;
K = 1 - offsetY / height;
}
return K;
},
rewind(event) {
if (this.inRange(event)) {
this.audio.currentTime = this.audio.duration * getCoefficient(event);
}
}
},
mounted() {
this.audio = this.$refs.audio
},
template: `<div class="audio-message-content">
<a v-if="loaded" class="play-pause-btn" href="#" :title="playing ? 'Clique aqui para pausar o audio' : 'Clique aqui ouvir o audio'" #click.prevent="togglePlay">
<svg key="pause" v-if="playing" x="0px" y="0px" viewBox="0 0 18 20" style="width: 18px; height: 20px; margin-top: -10px">
<path d="M17.1,20c0.49,0,0.9-0.43,0.9-0.96V0.96C18,0.43,17.6,0,17.1,0h-5.39c-0.49,0-0.9,0.43-0.9,0.96v18.07c0,0.53,0.4,0.96,0.9,0.96H17.1z M17.1,20"/>
<path d="M6.29,20c0.49,0,0.9-0.43,0.9-0.96V0.96C7.19,0.43,6.78,0,6.29,0H0.9C0.4,0,0,0.43,0,0.96v18.07C0,19.57,0.4,20,0.9,20H6.29z M6.29,20"/>
</svg>
<svg key="play" v-else x="0px" y="0px" viewBox="0 0 18 22" style="width: 18px; height: 22px; margin-top: -11px">
<path d="M17.45,10.01L1.61,0.14c-0.65-0.4-1.46,0.11-1.46,0.91V20.8c0,0.81,0.81,1.32,1.46,0.91l15.84-9.87C18.1,11.43,18.1,10.41,17.45,10.01L17.45,10.01z M17.45,10.01"/>
</svg>
</a>
<div v-else class="loading">
<div class="spinner"></div>
</div>
<div class="controls">
<span class="current-time">{{ currentTime }}</span>
<div class="slider" data-direction="horizontal" #click="">
<div class="progress" :style="{width: percent}">
<div class="pin" id="progress-pin" data-method="rewind"></div>
</div>
</div>
<span class="total-time">{{ totalTime }}</span>
</div>
<audio ref="audio" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/355309/Swing_Jazz_Drum.mp3" #loadedmetadata="loadedMetaData" #canplay="canPlay" #timeupdate="timeUpdate" #ended="ended"></audio>
</div>`
})
var app = new Vue({
el: '#app'
})
.audio-message-content {
width: 400px;
min-width: 300px;
height: 56px;
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.07);
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 24px;
padding-right: 24px;
border-radius: 4px;
user-select: none;
-webkit-user-select: none;
background-color: #fff;
}
.audio-message-content .play-pause-btn {
position: relative;
width: 18px;
height: 22px;
cursor: pointer;
}
.audio-message-content .play-pause-btn svg {
display: block;
position: absolute;
top: 50%;
left: 50%;
margin-left: -9px;
}
.audio-message-content .spinner {
width: 18px;
height: 18px;
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/355309/loading.png);
background-size: cover;
background-repeat: no-repeat;
animation: spin 0.4s linear infinite;
}
.audio-message-content .slider {
flex-grow: 1;
background-color: #D8D8D8;
cursor: pointer;
position: relative;
}
.audio-message-content .slider .progress {
background-color: #44BFA3;
border-radius: inherit;
position: absolute;
pointer-events: none;
}
.audio-message-content .slider .progress .pin {
height: 16px;
width: 16px;
border-radius: 8px;
background-color: #44BFA3;
position: absolute;
pointer-events: all;
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.32);
}
.audio-message-content .controls {
font-family: 'Roboto', sans-serif;
font-size: 16px;
line-height: 18px;
color: #55606E;
display: flex;
flex-grow: 1;
justify-content: space-between;
align-items: center;
margin-left: 24px;
}
.audio-message-content .controls .slider {
margin-left: 16px;
margin-right: 16px;
border-radius: 2px;
height: 4px;
}
.audio-message-content .controls .slider .progress {
width: 0;
height: 100%;
}
.audio-message-content .controls .slider .progress .pin {
right: -8px;
top: -6px;
}
.audio-message-content .controls span {
cursor: default;
}
svg, img {
display: block;
}
#keyframes spin {
from {
transform: rotateZ(0);
}
to {
transform: rotateZ(1turn);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<audio-player></audio-player>
</div>
Vue Component Codepen: https://codepen.io/caiokawasaki/pen/QzRMwz
Functions like the following I could not understand nor find anything on the internet:
window[handleMethod]
window[pin.dataset.method]
Can anyone help me finalize this component?
Edit
I've converted all of the html and javascript into a Vue component but anyway it still is not working properly.
The only thing that is not working properly is the progress bar. It needs to perform two functions:
Clicking it should go to the desired time.
When clicking on the pin and drag it should go to the desired time.
I use Vue Cli, neither of the above two work in the form of .vue files, but in Codepen normally written only function 2 works.
Codepen: https://codepen.io/caiokawasaki/pen/VqOqBQ
The function: window[handleMethod] is executed by deriving the name of the method off of the data- property from the pin element:
<div class="pin" id="progress-pin" data-method="rewind"></div>
So window[handleMethod] is equivalent to window.rewind()
The same is true for window[pin.dataset.method].
So in your case:
this[handleMethod](event)
and:
this[pin.dataset.method](event)
Should be suitable replacements.