Audio not loading on mobile browser (Plyr player) - javascript

I have found a nice HTML 5 audio player with playlist and artwork based on plyr. It works nicely on my desktop browser, but on my mobile device (iOS), it's not playing after pressing play. There's a codepen to demonstrate:
https://codepen.io/gifteconomist/pen/LREwXv
I've tried debugging via mobile browser, but no errors are shown.
Any ideas what could be going wrong here? Thanks a lot!
html
<head>
<meta charset="UTF-8">
<title>Responsive Audio Playlist with Cover Art Player</title>
<link rel='stylesheet' href='http://cdn.plyr.io/1.6.13/plyr.css'>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<main>
<section>
<div class="playlist">
<div class="plyr">
<audio controls></audio>
</div>
<ul class='playlist--list'>
<li data-id="0" data-image="https://www.callofduty.com/content/dam/atvi/callofduty/hub/main-hub/iw-hub/games/key-art/aw-key-art.jpg" data-audio="http://cdn.ascap.com/Member/Jach_Wall/BlackOps3.mp3">Call of Duty: Black Ops 3
<span class="artist">Jack Wall</span>
</li>
<li data-id="1" data-image="https://seussblog.files.wordpress.com/2013/03/143056e8473127ab6a665773884132bc.jpg" data-artist="StarBelly" data-title="Broken Hearts in Stereo" data-audio="http://cdn.ascap.com/network/audioportraits/Starbelly/03.mp3">Broken Hearts in Stereo
<span class="artist">Starbelly</span>
</li>
<li data-id="2" data-image="http://east.myna1.net/wp-content/uploads/sites/24/2016/03/nathan-east-pic.jpg" data-audio="http://cdn.ascap.com/Member/Nathan_East/Approach.mp3">Approach
<span class="artist">Nathan East</span>
</li>
</ul>
</div>
</section>
</main>
<script src='http://cdn.plyr.io/1.6.13/plyr.js'></script>
<script src="js/index.js"></script>
</body>
js
//Using JS Audio Player Plyr
plyr.setup(document.querySelector('.plyr'));
var radio = document.querySelector('.plyr').plyr;
var player = document.querySelector('.playlist');
var playerControls = document.querySelector('.plyr__controls');
var songs = player.querySelectorAll('.playlist--list li');
var i;
var active = null;
for(i = 0; i < songs.length; i++) {
songs[i].onclick = changeChannel;
}
setSource( getId(songs[0]), buildSource(songs[0]) );
document.querySelector('.plyr').addEventListener('ended', nextSong);
function changeChannel(e) {
setSource( getId(e.target), buildSource(e.target), true );
setArt(e.target);
}
function getId(el) {
return Number(el.getAttribute('data-id'));
}
function buildSource(el) {
var obj = [{
src: el.getAttribute('data-audio'),
image: el.getAttribute('data-image'),
artist: el.getAttribute('data-artist'),
type: 'audio/ogg'
}];
console.log(obj[0].image);
return obj;
}
function setSource(selected, sourceAudio, play) {
if(active !== selected) {
active = selected;
playerControls.style.background = "linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0.99) 100%), url("+sourceAudio[0].image+")";
radio.source({
type: 'audio',
title: 'test',
poster: sourceAudio[0].image,
sources: sourceAudio
});
for(var i = 0; i < songs.length; i++) {
if(Number(songs[i].getAttribute('data-id')) === selected) {
songs[i].className = 'active';
} else {
songs[i].className = '';
}
}
if(play) {
radio.play();
}
} else {
radio.togglePlay();
}
}
function setArt(e) {
console.log(e);
}
function nextSong(e) {
var next = active + 1;
if(next < songs.length) {
setSource( getId(songs[next]), buildSource(songs[next]), true );
}
}

Safari browser doesn't support ogg audio file type make sure you are not using this file type in your browser and also make sure the extension of audio file is correct.

Related

Local storage and window.location.href.replace

I and my course mate are trying to write a code where when the order button is clicked it should save on local storage and redirect to an order page.
So far when we click on order it is not registered in the application/local storage section of the google developer tool and thus does not redirect to a new page.
We put an eventlistener to show a console.log for when we click, just to be sure the buttons are in order(this part is not important).
We also used an online javascript validator to eliminate typos and errors.
Also do we need any specific code on the order.html file to interface with local storage?
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>grc</title>
<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
<header>
<nav>
<ul>
<li>Home</li>
<li>Groceries</li>
<li>Contact</li>
</ul>
</nav>
</header>
<main>
<aside><img class="imgclass1" src="images/rounded logo.png" alt="Grocer Nigeria"></aside>
<article class="preinventory">
<section class="columns-desktop">
<div class="inventory">
<img class="sales" src="images/tomato.jpg" alt="Tomato"/>
<div class="columns">
<div class="title">Tomato</div>
<div class="Price">$100</div>
</div>
<p class="Desc"> Our Tomato2</p>
<button data-order="Tomato2">Order</button>
</div>
<div class="inventory">
<img class="sales" src="images/tomato.jpg" alt="Tomato"/>
<div class="columns">
<div class="title">Tomato</div>
<div class="Price">$100</div>
</div>
<p class="desc"> Our Tomato</p>
<button data-order="Tomato">Order</button>
</div>
</section>
</article>
</main>
<footer>
<nav>
<ul>
<li>Home</li>
<li>Groceries</li>
<li>Contact</li>
</ul>
</nav>
</footer>
<script type="text/javascript">
window.addEventListener("DOMcontentLoaded", function(e){
const orderButtons= document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button){
button.addEventListener("click",function(e){
const button= e.currentTarget;
const container= button.parentNode;
const order={
id:button.getAttribute("data-order"),
title: container.querySelector(".title").innerText,
price1: container.querySelector(".Price").innerText,
desc:container.querySelector(".desc").innerText
};
localStorage.setItem('order', JSON.stringify(order));
const url = window.location.href.replace("grc.html","order.html");
window.location.href = url;
});
});
});
window.addEventListener("DOMcontentLoaded", function(e){
console.log("The page is loaded.");
});
const orderButtons= document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button){
button.addEventListener("click", function(e){
console.log("The button was clicked.");
});
});
</script>
</body>
</html>
**Below is what I see when I run the live server**
<!-- Code injected by live-server -->
<script type="text/javascript">
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function() {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
head.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
head.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function(msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
console.log('Live reload enabled.');
})();
}
// ]]>
</script>
</body>
</html>
The issue here is that the event DOMContentLoaded does not fire.
Here is how I have used the load event instead; for redirection, I have simply used URL search params (because I don't know what your other html file looks like) although you may use your other html document instead.
The snippet is below
However note: Stackoverflow will not allow the JavaScript to run, and will throw a securityError. To run this code you must save it on your computer or use a jsFiddle
function continue_ordering() {
alert("Now continue with order");
};
window.addEventListener("load", function(e) {
const orderButtons = document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button) {
button.addEventListener("click", function(e) {
const button = e.currentTarget;
const container = button.parentNode;
const id = button.getAttribute("data-order");
const order = {
id,
title: container.querySelector(".title").innerText,
price1: container.querySelector(".price").innertext,
desc: container.querySelector(".desc").innerText
};
localStorage.setItem("order-" + id, JSON.stringify(order));
window.location.search = "?ordering=true&order-id=" + id;
});
});
});
window.addEventListener("load", function(e) {
if (window.location.search.search("ordering=true") != -1) {
console.log("User is ordering");
const params = new URLSearchParams(location.search)
const id = params.get("order-id");
if (!id || id == null) throw "There is no order id, error. Remove the ?ordering=true from the url and try again.";
const order_info = JSON.parse(localStorage.getItem("order-" + id));
if (!order_info) throw "Order information is not present: try ordering again. Remove the ?ordering=true from the url";
console.log("Order info is:\n", order_info);
document.getElementById("ordering").removeAttribute("hidden");
return;
};
document.getElementById("make-order").removeAttribute("hidden");
});
const orderButtons = document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button) {
button.addEventListener("click", function(e) {
console.log("The button was clicked.");
});
});
<div id="make-order" hidden>
<button data-order="test">Order</button>
<div class="title">This is the title</div>
<div class="price">130 USD</div>
<div class="desc">Lorem</div>
</div>
<div id="ordering" hidden>
<h1>
You are ordering.
<br> Choose
Stop ordering Or Continue with order
</h1>
</div>
The DOMcontentLoaded event has already fired by the time that code hooks it.
Check this post;
Code inside DOMContentLoaded event not working

JavaScript not working for all HTML pages

I am working on the tablet's display of a Pepper robot; I have a functional HTML index page comprising a list of questions—each question redirects to its respective HTML when clicked on—, 2 volume buttons and 2 other buttons—one that pops up an instruction image and the other one that closes the index page and gets back to the splash screen, which when clicked upon, reveals the index page. So far everything is working. The issue is that when I click a question—I get redirected to its HTML page, but then I get stuck there, as neither the 2 volume buttons nor the 2 other buttons work;
I made sure to include the following in each HTML page:
<script type="text/javascript" src="/libs/qimessaging/2/qimessaging.js"></script>
<script type="text/javascript" src="faq.js"></script>
I also reused the same JavaScript functions that worked for the index page.
I commented out some line:
btnPrevious.addEventListener('click', goToPreviousPage);
because I noticed it prevented the splash screen from disappearing when clicked on—i.e., the visibility attribute stays on visible instead of switching to hidden thus revealing the index page, but still, the 3 remaining buttons don't work anyway.
Here is my faq.js code:
/* global QiSession */
var serviceName = 'ADFAQ';
var volumeUpEvent = serviceName + '/VolumeUp';
var volumeDownEvent = serviceName + '/VolumeDown';
var volumeData = serviceName + '/Volume';
/* Clickable buttons */
var btnReturn = document.getElementById('return');
var btnHelp = document.getElementById('call_help');
var btnPrevious = document.getElementById('previous_page');
var btnVolUp = document.getElementById('volume-up');
var btnVolDown = document.getElementById('volume-down');
/* Help image and splash screen */
var helper = document.getElementById('helper');
var img = document.getElementById('click_on_me');
var memory;
var volume;
var audioDevice;
QiSession(connected, disconnected);
function connected (s) {
console.log('QiSession connected');
var questions = document.getElementById('questions');
/* Associating buttons to their respective functions */
btnHelp.addEventListener('click', showHelper);
btnReturn.addEventListener('click', closeQuestions);
//btnPrevious.addEventListener('click', goToPreviousPage);
btnVolUp.addEventListener('click', raiseVolume);
btnVolDown.addEventListener('click', lowerVolume);
img.addEventListener('click', loadQuestions);
questions.addEventListener('click', clickOnQuestion);
s.service('ALMemory').then(function (m) {
m.subscriber(serviceName + '/DialogEnded').then(function (subscriber) {
subscriber.signal.connect(hideQuestions);
});
m.subscriber(serviceName + '/Pepper').then(function (subscriber) {
subscriber.signal.connect(displayPepperHTML)
});
m.subscriber(serviceName + '/RaiseVolume').then(function (subscriber) {
subscriber.signal.connect(raiseVolume);
});
m.subscriber(serviceName + '/LowerVolume').then(function (subscriber) {
subscriber.signal.connect(lowerVolume);
});
memory = m;
});
s.service('ALAudioDevice').then(function (a) {
a.getOutputVolume().then(assignVolume);
audioDevice = a
});
}
function disconnected () {
console.log('QiSession disconnected');
}
function assignVolume(value){
volume = value;
}
function raiseVolume (event) {
var changed = 0;
if(volume < 100) {
volume = Math.min(volume + 5, 100);
audioDevice.setOutputVolume(volume);
changed = 1;
}
memory.insertData(volumeData, volume);
memory.raiseEvent(volumeUpEvent, changed);
}
function lowerVolume (event) {
var changed = 0;
if(volume > 30) {
volume = Math.max(volume - 5, 0);
audioDevice.setOutputVolume(volume);
changed = 1;
}
memory.insertData(volumeData, volume);
memory.raiseEvent(volumeDownEvent, changed);
}
function showHelper (event) {
if (btnHelp.innerHTML === '?') {
helper.style.opacity = '1';
helper.style.zIndex = '1';
btnHelp.innerHTML = '←';
} else {
helper.style.opacity = '0';
helper.style.zIndex = '-1';
btnHelp.innerHTML = '?';
}
btnHelp.blur();
}
function loadQuestions (event) {
memory.raiseEvent(serviceName + '/LoadQuestions', 1);
img.style.visibility = 'hidden';
}
function goToPreviousPage () {
window.location.href = "index.html";
}
function displayPepperHTML() {
window.location.href = "pepper.html";
}
function closeQuestions (event) {
if(location.href != "index.html")
{window.location.href = "index.html";}
memory.raiseEvent(serviceName + '/CloseQuestions', 1);
btnReturn.blur();
}
function hideQuestions (data) {
if (data !== 0) {
img.style.visibility = 'visible';
helper.style.opacity = '0';
btnHelp.innerHTML = '?';
}
}
function clickOnQuestion (event) {
memory.raiseEvent(serviceName + '/' + event.target.id, 1);
}
Here is my non-functioning pepper.html code:
<!DOCTYPE html>
<html lang="fr">
<head>
<title>Pepper</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=1280, user-scalable=no" />
<link type="text/css" rel="stylesheet" href="css/style.css" />
<link type="text/css" rel="stylesheet" href="css/faq.css" />
</head>
<body>
<header>
<h1>Bla bla bla</h1>
<span class="buttons">
<button id="previous_page" class="button-help"> ← </button>
<button id="return" class="button-return">X</button>
</span>
<div id="helper" class="pop-up">
<img src="img/interactionscreen_frf.png" alt="Bla bla bla">
</div>
</header>
<ul id="questions">
<p>
Bla bla bla
</p>
<div class="volume-part">
<div id="volume-up" class="Click-me">+</div>
<img src="img/speaker.png" alt="Bla bla bla" style="vertical-align: middle;">
<div id="volume-down" class="Click-me">-</div>
</div>
</ul>
<script type="text/javascript" src="/libs/qimessaging/2/qimessaging.js"></script>
<script type="text/javascript" src="faq.js"></script>
</body>
</html>
Thank you for your help.
I am expecting the pepper.html page to respond to both the volume and ← and X buttons, as the index.html should, since they use the exact same Javascript.
I was able to find some workaround: creating one JavaScript file for each HTML page, this is redundant and non-optimal I know, but at least it works.
This also made me realize that the commented-out line was blocking the program because the index.html page doesn't use the previous_page button, that's what led me to make a JS file for each HTML page.
If anybody has any other suggestions I am all ears.
Edit: I reduced the number of JS scripts to only 2. One for the index.html and the other for the identically-structured html pages of the other questions.

preview elements in the same page after click

I am trying to preview the files in the same page using the < embed> tag after clicking on them.
I found this way of displaying the directories from the file-system, but after I click on a file, either it downloads directly(ppt, pdf...) or opens in new page(jpeg, png)
help!
This is a screenshot of the result:Screenshot of webpage after dropping a file direcory
this is the HTML code:
<!DOCTYPE html>
<html>
<head>
<script src="jquery-3.2.1.min.js"></script>
</head>
<body>
<p>Drag files and/or directories to the box below!</p>
<div id="dropzone">
<div id="boxtitle">
Drop Files Here
</div>
</div>
<h2>Directory tree:</h2>
<ul id="listing">
</ul>
</body>
</html>
this is the javascript code:
let dropzone = document.getElementById("dropzone");
let listing = document.getElementById("listing");
function scanFiles(item, container) {
let elem = document.createElement("li");
elem.innerHTML = item.name;
container.appendChild(elem);
if (item.isDirectory) {
let directoryReader = item.createReader();
let directoryContainer = document.createElement("ul");
container.appendChild(directoryContainer);
directoryReader.readEntries(function(entries) {
entries.forEach(function(entry) {
scanFiles(entry, directoryContainer);
});
});
}
}
dropzone.addEventListener("dragover", function(event) {
event.preventDefault();
}, false);
dropzone.addEventListener("drop", function(event) {
let items = event.dataTransfer.items;
event.preventDefault();
listing.innerHTML = "";
for (let i=0; i<items.length; i++) {
let item = items[i].webkitGetAsEntry();
if (item) {
scanFiles(item, listing);
}
}
}, false);

html5 movie playlist, How to Count file

i have this code for autoplay (playlist) movie
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Movie Playlist</title>
<script>
var videoPlayer;
var video_count = 1;
window.onload = function (){
videoPlayer = document.getElementById("homevideo");
videoPlayer.addEventListener("ended", function (){
video_count++;
if (video_count == 6) video_count = 1;
var nextVideo = video_count+".mp4";
videoPlayer.src = nextVideo;
}, false);
}
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div style="width:100%;margin:0px auto;">
<video id="homevideo" width="100%" autoplay autobuffer src="1.mp4"></video>
</div>
on the code above, i have 5 .mp4 movie, but if i have more than 5 .mp4 movie, the 6.mp4, 7.mp4 and other will not be played. so, how can i dynamically set the movie count pure using html5 or javascript?
You are better off having your server provide this information.
But for your existing approach, I'm assuming your video names are in sequential order ... so 1.mp4, 2.mp4, 3.mp4, etc ... so you could keep looping through the videos while increasing the count, and once a video fails to load at a given video_count, you can know that it is the limit and loop back to the start if you wanted.
function videoExists(videoUrl){
var http = new XMLHttpRequest();
http.open('HEAD', videoUrl, false);
http.send();
return http.status != 404;
}
So, for example ...
var videoPlayer;
var video_count = 1;
var video_max = 0;
window.onload = function (){
videoPlayer = document.getElementById("homevideo");
videoPlayer.addEventListener("ended", function (){
var nextVideo = (video_count+1)+".mp4";
if(video_count <= video_max || videoExists(nextVideo)){
videoPlayer.src = nextVideo;
video_count++;
}else{
video_max = video_count;
//reset back to original video
video_count = 1;
videoPlayer.src = video_count+".mp4";
}
}, false);
}
I didn't test the code, but you should get the idea. Please let me know if you have any questions about this approach.

Image alternating function alternates wrong image

I'm new to HTML, JavaScript, CSS, and am taking a Web Design class. I'm required to make a banner ad that alternates between two different images (banner1.jpg & banner2.jpg). The problem I'm having is when my site loads it displays banner1.jpg above the <h2>, and court.jpg below. Then it changes court.jpg to banner2.jpg then to banner1.jpg, alternating back & forth between the two banners. The banner1.jpg above the <h2> stays static. Here's the relevant code:
<script type="text/javascript">
/* <![CDATA[ */
var curImage="banner1";
function bannerAd() {
if (curImage == "banner2") {
document.images[1].src = "images/banner1.jpg";
curImage = "banner1";
}
else {
document.images[1].src = "images/banner2.jpg";
curImage = "banner2";
}
}
/* ]]> */
</script>
</head>
<body onload="var changeImages=setInterval('bannerAd()', 2000);">
<header>
<h1>Basketball Almanac</h1>
</header>
<section class="main">
<img src="images/banner1.jpg" alt="Banner image" />
<h2>Basketball Analysis</h2>
<p><span class="companyname">Basketball Almanac</span> is your one-stop site for in-depth basketball analysis and statistics.</p>
<img class="main" src="images/court.jpg" alt="NBA Court" />
How do I make it so only banner1.jpg changes? Thanks in advance for any help, and let me know if it would help to include more of the code here.
Simple, in javascript, arrays are 0 based, so the frist object is [0]
So you want
var curImage="banner1";
function bannerAd() {
if (curImage == "banner2") {
document.images[0].src = "images/banner1.jpg";
curImage = "banner1";
}
else {
document.images[0].src = "images/banner2.jpg";
curImage = "banner2";
}
}
or to simplify it a little
var curImage="images/banner2.jpg";
function bannerAd() {
if (curImage == "images/banner1.jpg") {
curImage= "images/banner2.jpg";
}
else {
curImage = "images/banner1.jpg";
}
document.images[0].src = curImage;
}
var curImage="images/banner2.jpg";
function bannerAd() {
if (curImage == "images/banner1.jpg") {
curImage= "images/banner2.jpg";
}
else {
curImage = "images/banner1.jpg";
}
document.images[0].src = curImage;
}
var curImage="banner1";
function bannerAd(n) {
if (curImage == "banner2") {
document.images[n].src = "images/banner1.jpg";
curImage = "banner1";
}
else {
document.images[n].src = "images/banner2.jpg";
curImage = "banner2";
}
}
//bannerAd(1)
<body onload="var changeImages=setInterval('bannerAd(0)', 2000);">
<header>
<h1>Basketball Almanac</h1>
</header>
<section class="main">
<img src="images/banner1.jpg" alt="Banner image" />
<h2>Basketball Analysis</h2>
<p><span class="companyname">Basketball Almanac</span> is your one-stop site for in-depth basketball analysis and statistics.</p>
<img class="main" src="images/court.jpg" alt="NBA Court" />

Categories

Resources