HTML image/video playlist - javascript

I have a set of images and videos. And I want to implement a player which can loop through all the images and videos.
As an example,
A - image, B - video, C - image;
assets = [A, B, C];
I want a html player which loop through this array, first show A(image) for an interval[5s], then autoplay the B(video) and end of the video, shows C(image) for an interval(5s) and repeat the flow. I have tried something like below code. But this is not a solution for a video.
var previewContainer = $(".previews-container");
var curIndex = 1;
appendMediaElement(loopAssets[0]); //initial
setInterval(function() {
if(curIndex >= loopAssets.length) {
curIndex = 1;
}
appendMediaElement(loopAssets[curIndex]); //loopAssets array contains all the images and vidoes with meta data which is retrive from a ajax call
curIndex++;
}, 5000);
function appendMediaElement(asset) {
var mediaEl = "";
if(asset.mediaType == "IMAGE") {
mediaEl = '<img id="lp-preview-image" src="' + asset.contentUrl + '">';
previewContainer.html(mediaEl);
} else if(asset.mediaType == "VIDEO") {
mediaEl = "<video id='lp-preview-video' autoplay controls>";
mediaEl += "<source src='"+ asset.contentUrl + "' type='" + asset.contentType + "'>";
mediaEl += "</video>";
previewContainer.html(mediaEl);
}
}
<div class="col-xs-8">
<div id="loop-preview">
<div class="item previews-container" style="width: 700px; height: 450px">
<!-- images/vidoes-->
</div>
</div>
</div>
any better solution will be appreciated!

Here is a solution with what you mentioned on your comments:
Images will be displayed for 5 seconds, and
Videos will be displayed completely
before moving to the next media element.
Trying to change your code minimally, this is a list of things that could be done:
Remove the setInterval (but keep the function that changes the media, rename it to something like changeMedia)
At the end of the code when it is an image, add a setTimeout that calls the new function that you created (changeMedia) after 5 seconds.
At the end of the code when it is a video, add a listener to the end of the video (ended event) in which you call the function that you created (changeMedia).
And that should be it. For my code, I assumed this is the data that you get from AJAX (it follows all the requirements from your original code, although it's possibly just a minified version of what you get):
var loopAssets = [
{ contentUrl: "http://lorempixel.com/200/200/abstract/", contentType: "image/jpg", mediaType:"IMAGE" },
{ contentUrl: "http://www.w3schools.com/html/mov_bbb.mp4", contentType: "video/mp4", mediaType: "VIDEO"},
{ contentUrl: "http://lorempixel.com/200/200/people/", contentType: "image/jpg", mediaType:"IMAGE" }
];
So, here is a working demo (see the comments in the places that I changed):
var loopAssets = [
{ contentUrl: "http://lorempixel.com/200/200/abstract/", contentType: "image/jpg", mediaType:"IMAGE" },
{ contentUrl: "http://www.w3schools.com/html/mov_bbb.mp4", contentType: "video/mp4", mediaType: "VIDEO"},
{ contentUrl: "http://lorempixel.com/200/200/people/", contentType: "image/jpg", mediaType:"IMAGE" }
];
var previewContainer = $(".previews-container");
var curIndex = 1;
appendMediaElement(loopAssets[0]);
// removed the setInterval but kept the function
function changeMedia() {
if(curIndex >= loopAssets.length) {
// modified this so it would display the first image/video when looping
curIndex = 0;
}
appendMediaElement(loopAssets[curIndex]);
curIndex++;
};
function appendMediaElement(asset) {
var mediaEl = "";
if(asset.mediaType == "IMAGE") {
mediaEl = '<img id="lp-preview-image" src="' + asset.contentUrl + '">';
previewContainer.html(mediaEl);
// image: go to the next media after 5 seconds
setTimeout("changeMedia()", 5000);
} else if(asset.mediaType == "VIDEO") {
mediaEl = "<video id='lp-preview-video' autoplay controls>";
mediaEl += "<source src='"+ asset.contentUrl + "' type='" + asset.contentType + "'>";
mediaEl += "</video>";
previewContainer.html(mediaEl);
// video: go to the next media when the video ends
document.getElementById("lp-preview-video").addEventListener("ended", function(e) {
changeMedia();
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="col-xs-8">
<div id="loop-preview">
<div class="item previews-container" style="width: 700px; height: 450px">
</div>
</div>
</div>
As I said, this is the simplest change to make your code work as you defined in your question and comments, to make it better/more efficient, you may want to look into doing other enhancements (for example: hide/show instead of create/delete elements).

Here is the JSFiddle demo
//CODE
<!DOCTYPE html>
<html>
<head>
<style>
body{
width: 100vw;
height: 100vh;
margin: 0 !important;
display: -webkit-flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
}
#media{
display: -webkit-flex;
display: flex;
-webkit-align-self: center;
align-self:center;
}
#media>img{
height: 500px;
width: 500px;
}
</style>
<script>
var imgFormat = ["jpg","png"];
var content = [
"http://cdn.wonderfulengineering.com/wp-content/uploads/2014/04/space-wallpapers-9.jpg",
"http://ak8.picdn.net/shutterstock/videos/1694950/preview/stock-footage-operator-cleans-lens-of-professional-videocamera-and-on-background-scenery-are-prepared.mp4",
"http://www.sciencesortof.com/wp-content/uploads/2015/04/218_space_beer.jpg",
"http://www.spirit1059.com/pics/Feeds/Articles/2015611/118317/Beach.jpg",
"http://ak7.picdn.net/shutterstock/videos/3775625/preview/stock-footage-northern-lights-aurora-borealis-reflected-on-a-lake-timelapse-in-iceland.mp4"
];
document.onreadystatechange = function(){
if(document.readyState == "interactive"){mediaChange();}
}
function mediaChange(){
var mediaBox = document.getElementById("media");
setInterval(function(){
var media = mediaBox.children[0];
var key = content.indexOf(media.getAttribute("src"));
if((key+1) == content.length){key = 0;}
else{key += 1;}
var format = content[key].substr(content[key].length - 3);
changeMedia(mediaBox,media,key,format);
}, 5000);
}
function changeMedia(mediaBox,media,key,format){
if(imgFormat.indexOf(format) < 0){
var ele = document.createElement("video");
ele.setAttribute("autoplay", true);
}
else{var ele = document.createElement("img");}
ele.setAttribute("src",content[key]);
mediaBox.replaceChild(ele,media);
}
</script>
</head>
<body>
<section id="media">
<img src="http://cdn.wonderfulengineering.com/wp-content/uploads/2014/04/space-wallpapers-9.jpg">
</section>
</body>
</html>

Related

How to smoothly change background (animate) in JavaScript?

I have 30 images that make together a full turn of a 3D model. I want to display the animation in browser. I can not use CSS animation, which otherwise worked good. The problem with JavaScript is flickering when the next image loads. Is there any way to make it smoother?
<div id="image" style="width: 1920px; height: 1080px;">
</div>
<script>
let suffix;
let i = 0;
let image = document.getElementById("image");
function setSuffix(){
suffix = ("0" + (i+1)).slice(-2);
i++;
i = i % 30;
image.style.background = "URL('" + suffix + ".jpg')";
}
setInterval(setSuffix, 1000);
</script>
Perhaps you can use a supplemental image, load it, then bring it to the front using z-index. Something like:
let suffix;
let i = 0;
let image1 = document.getElementById("image1");
let image2 = document.getElementById("image2");
// TIP: Remove these
let url1 = "https://scontent-iad3-1.xx.fbcdn.net/v/t1.0-9/41667401_10155851253461762_5185170392754421760_n.png?_nc_cat=101&oh=beb534388a04dd5ea101bc9560fa5e24&oe=5C1F4FAD";
let url2 = "https://scontent-iad3-1.xx.fbcdn.net/v/t1.0-9/34661720_10155632057856762_4698625317663670272_n.jpg?_nc_cat=106&oh=dd89a8d15e587dba4b7fe8b3ea38143e&oe=5C1E5CC0";
function setSuffix(){
// TIP: Uncomment this
//imageUrl = ("0" + (i+1)).slice(-2) + ".jpg";
if (i % 2 === 0) {
imageUrl = url1; // TIP: Remove this.
image1.style.background = `URL('${imageUrl}')`;
image1.style.zIndex = "1";
image2.style.zIndex = "0";
} else {
imageUrl = url2; // TIP: Remove this.
image2.style.background = `URL('${imageUrl}')`;
image2.style.zIndex = "1";
image1.style.zIndex = "0";
}
i++;
}
setInterval(setSuffix, 1000);
#image1, #image2{
position:absolute;
top: 0px;
left: 0px;
}
<div id="image1" style="width: 1920px; height: 1080px;"></div>
<div id="image2" style="width: 1920px; height: 1080px;"></div>

Simple method to define variable with parsed text from csv?

I am attempting to use a switch statement in JavaScript to determine server status from an external serverlist.csv. If the csv reads "online", switch statement displays success.svg, if "offline", switch statement displays error.svg and so forth.
In the switch statement, I am attempting to define a variable with information extracted from an external csv report:
<p id="demo"></p>
<script>
function myFunction() {
var online = "online"
var offline = "offline"
var waiting = "waiting"
var x;
var y;
var d = /* outcome of this variable will be extracted from serverlist.csv, but manually enter value here for now */ online;
switch (d) {
case 'waiting':
x = "Waiting...";
y = 'waiting';
break;
case 'online':
x = "Online!";
y = 'success';
break;
case 'offline':
x = "Offline!";
y = 'error';
break;
}
document.getElementById("demo").innerHTML = x;
document.getElementById(y).style.display = 'block';
}
window.onload = myFunction;
</script>
<img src="https://image.flaticon.com/icons/svg/130/130879.svg" id="success" style="display:none; width: 100px; height: 100px;"/>
<img src="https://image.flaticon.com/icons/svg/130/130877.svg" id="error" style="display:none; width: 100px; height: 100px;"/>
<img src="https://image.flaticon.com/icons/svg/130/130920.svg" id="waiting" style="display:none; width: 100px; height: 100px;"/>
https://jsfiddle.net/6o5dLfne/4/
Here is the serverlist.csv
I would just place the server statuses into an array, than it is easy to manipulate with it:
var response = 'Server,Status\n\
Server1,Online\n\
Server2,Offline\n\
';
var lines = response.split('\n');
var servers = [];
$.each(lines, function(l, line) {
if( l && line ) {
var status = line.split(',');
servers.push({
'name': status[0],
'status': status[1]
})
};
});
var demo = $('#demo');
var demoHtml = '';
$.each(servers, function(s, server) {
demoHtml += '<p class="server-status server-' + server.status + '">' + server.name + '</p>\n'
});
demo.html( demoHtml );
.server-status::after {
content: '';
display: inline-block;
margin-left: 5px;
width: 20px;
height: 20px;
background-position: center;
background-size: 20px auto;
}
.server-Online::after {
background-image: url('https://image.flaticon.com/icons/svg/130/130879.svg');
}
.server-Offline::after {
background-image: url('https://image.flaticon.com/icons/svg/130/130877.svg');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>This demo is attempting to test out the functionality of switching images depending on server status from an external .csv report that will be generated from a powershell script. The goal is to build a responsive webpage dashboard.</p>
<div id="demo"></div>
Please note, it is easier to control the layout with CSS, as done above. Also for this and similar apps, you can consider using frameworks as Knockout is, take a look how easy the implementation is here.
Example also on JSFiddle.

Preload mp3 file in queue to avoid any delay in playing the next file in queue

I am working on a script where i am playing multiple mp3 and each files is in queue. There is slight delay in playing next .mp3 file as it takes time to buffer/load the file.
How can i buffer the next .mp3 file which is queue so that all file run smoothly without any delay.
getData(1);
function getData(id) {
//Emty div
$("#surah-wrapper").empty();
$.ajaxSetup({
cache: true,
jsonpCallback: 'quranData'
}); // define ajax setup
// Quran Text Type quran-uthmani | quran-simple | quran-simple-clean | quran-wordbyword
$.getJSON("http://api.globalquran.com/surah/" + id + "/quran-uthmani?key=api_key&jsoncallback=?", {
format: "jsonp"
}, function(data) {
if (id > 1) {
$("<span class='qspan qspan-bsm'>").html("بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ").appendTo("#surah-wrapper");
}
$.each(data.quran, function(i, by) {
$.each(by, function(verseNo, line) {
//$("<p>").html('('+ line.surah+':'+line.ayah+') '+line.verse).appendTo("#surah-wrapper");
$("<span class='qspan' id='" + verseNo + "'>").html(line.verse + '<span class="qspan-ayahno">(' + line.surah + ':' + line.ayah + ')</span>').appendTo("#surah-wrapper");
});
});
});
}
//Play Script & highlight script
var audioIndex = 0;
var countSpan = 0;
countSpan = $('#surah-wrapper').children().length;
var surahNo = 1;
var strCat = "http://download.quranicaudio.com/verses/Sudais/mp3/001001.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001002.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001003.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001004.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001005.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001006.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001007.mp3";
setPlayer();
$('.customSurah').change(function() {
$('.play-btn').css('display', 'none');
$aud.pause();
surahNo = $('#surah option:selected').val();
setTimeout(function() {
countSpan = $('#surah-wrapper').children().length;
var i = 0;
strCat = '';
for (i = 0; i <= countSpan; i++) {
if (i == 0) {
strCat = "http://download.quranicaudio.com/verses/Sudais/mp3/001001.mp3,";
i += 1
}
if (i == countSpan) {
if (surahNo == 1) {
} else {
if (i < 10) {
strCat += "http://download.quranicaudio.com/verses/Sudais/mp3/00" + surahNo + "00" + i + ".mp3,";
}
}
} else {
if (i < 10) {
strCat += "http://download.quranicaudio.com/verses/Sudais/mp3/00" + surahNo + "00" + i + ".mp3,";
}
}
}
if (surahNo == 1) {
strCat = null;
strCat = "http://download.quranicaudio.com/verses/Sudais/mp3/001001.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001002.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001003.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001004.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001005.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001006.mp3,http://download.quranicaudio.com/verses/Sudais/mp3/001007.mp3";
}
setPlayer();
$('.play-btn').css('display', 'block');
}, 3000);
});
function setPlayer() {
//reset values
audioIndex = 0;
countSpan = 0;
countSpan = $('#surah-wrapper').children().length;
strCat = strCat.trim();
var audioTracks = strCat;
var audioAddress = audioTracks.split(',');
var playing = false;
$(function() {
$aud = $("#myAudio")[0];
$btn = $(".play-btn");
function setAudio(index) {
$("#surah-wrapper > .qspan").removeClass("qplaying");
$aud.preload = 'auto';
$aud.src = audioAddress[index];
}
setAudio(audioIndex);
$btn.click(function() {
if (playing) {
playing = false;
$aud.pause();
} else
$aud.play();
});
$aud.onended = function() {
if (audioIndex < audioAddress.length - 1) {
audioIndex++;
setAudio(audioIndex);
$aud.play();
} else {
audioIndex = 0;
setAudio(audioIndex);
playing = false;
$btn.text("Play");
}
};
$aud.onpause = function() {
if (!playing) $btn.text("Play");
$(".play-btn").css("background-image", "url(https://cdn0.iconfinder.com/data/icons/cosmo-player/40/button_play_1-64.png)");
};
$aud.onplay = function() {
$btn.text("Pause");
$(".play-btn").css("background-image", "url(https://cdn0.iconfinder.com/data/icons/cosmo-player/40/button_pause_1-64.png)");
playing = true;
$("#surah-wrapper > .qspan:nth-child(" + (audioIndex + 1) + ")").addClass("qplaying");
var wHeight = $(window).height();
var wHalfHeight = wHeight;
var x = $(".qplaying").offset();
var curentSpanPosition = x.top;
wHalfHeight = wHalfHeight / 2;
if (curentSpanPosition > wHalfHeight) {
$('html, body').animate({
scrollTop: curentSpanPosition - 50
}, 1000);
}
};
});
}
.play-btn {
background-image: url("https://cdn0.iconfinder.com/data/icons/cosmo-player/40/button_play_1-64.png");
float: none;
font-size: 0 !important;
height: 50px;
margin: 15px auto;
padding: 5px 10px;
text-align: center;
width: 50px;
}
body{float:right; direction:rtl;}
span{padding:5px 10px; direction:rtl; text-align:right;
margin:5px 1px;
font-size:20px}
.qplaying {
background: #f00 none repeat scroll 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<audio id="myAudio" >
<source src="" type="audio/mpeg">
</audio>
<div class="play-btn-wrapper">
<select class="customSurah form-control ddCountry styled-select" id="surah" name="surah" onchange="getData($('#surah option:selected').val())"><option value="1">Al-Faatiha</option><option value="2">Al-Baqara</option><option value="3">Aal-i-Imraan</option><option value="4">An-Nisaa</option><option value="5">Al-Maaida</option><option value="6">Al-An'aam</option><option value="7">Al-A'raaf</option><option value="8">Al-Anfaal</option><option value="9">At-Tawba</option><option value="10">Yunus</option><option value="11">Hud</option><option value="12">Yusuf</option><option value="13">Ar-Ra'd</option><option value="14">Ibrahim</option><option value="15">Al-Hijr</option><option value="16">An-Nahl</option><option value="17">Al-Israa</option><option value="18">Al-Kahf</option><option value="19">Maryam</option><option value="20">Taa-Haa</option><option value="21">Al-Anbiyaa</option><option value="22">Al-Hajj</option><option value="23">Al-Muminoon</option><option value="24">An-Noor</option><option value="25">Al-Furqaan</option><option value="26">Ash-Shu'araa</option><option value="27">An-Naml</option><option value="28">Al-Qasas</option><option value="29">Al-Ankaboot</option><option value="30">Ar-Room</option><option value="31">Luqman</option><option value="32">As-Sajda</option><option value="33">Al-Ahzaab</option><option value="34">Saba</option><option value="35">Faatir</option><option value="36">Yaseen</option><option value="37">As-Saaffaat</option><option value="38">Saad</option><option value="39">Az-Zumar</option><option value="40">Al-Ghaafir</option><option value="41">Fussilat</option><option value="42">Ash-Shura</option><option value="43">Az-Zukhruf</option><option value="44">Ad-Dukhaan</option><option value="45">Al-Jaathiya</option><option value="46">Al-Ahqaf</option><option value="47">Muhammad</option><option value="48">Al-Fath</option><option value="49">Al-Hujuraat</option><option value="50">Qaaf</option><option value="51">Adh-Dhaariyat</option><option value="52">At-Tur</option><option value="53">An-Najm</option><option value="54">Al-Qamar</option><option value="55">Ar-Rahmaan</option><option value="56">Al-Waaqia</option><option value="57">Al-Hadid</option><option value="58">Al-Mujaadila</option><option value="59">Al-Hashr</option><option value="60">Al-Mumtahana</option><option value="61">As-Saff</option><option value="62">Al-Jumu'a</option><option value="63">Al-Munaafiqoon</option><option value="64">At-Taghaabun</option><option value="65">At-Talaaq</option><option value="66">At-Tahrim</option><option value="67">Al-Mulk</option><option value="68">Al-Qalam</option><option value="69">Al-Haaqqa</option><option value="70">Al-Ma'aarij</option><option value="71">Nooh</option><option value="72">Al-Jinn</option><option value="73">Al-Muzzammil</option><option value="74">Al-Muddaththir</option><option value="75">Al-Qiyaama</option><option value="76">Al-Insaan</option><option value="77">Al-Mursalaat</option><option value="78">An-Naba</option><option value="79">An-Naazi'aat</option><option value="80">Abasa</option><option value="81">At-Takwir</option><option value="82">Al-Infitaar</option><option value="83">Al-Mutaffifin</option><option value="84">Al-Inshiqaaq</option><option value="85">Al-Burooj</option><option value="86">At-Taariq</option><option value="87">Al-A'laa</option><option value="88">Al-Ghaashiya</option><option value="89">Al-Fajr</option><option value="90">Al-Balad</option><option value="91">Ash-Shams</option><option value="92">Al-Lail</option><option value="93">Ad-Dhuhaa</option><option value="94">Ash-Sharh</option><option value="95">At-Tin</option><option value="96">Al-Alaq</option><option value="97">Al-Qadr</option><option value="98">Al-Bayyina</option><option value="99">Az-Zalzala</option><option value="100">Al-Aadiyaat</option><option value="101">Al-Qaari'a</option><option value="102">At-Takaathur</option><option value="103">Al-Asr</option><option value="104">Al-Humaza</option><option value="105">Al-Fil</option><option value="106">Quraish</option><option value="107">Al-Maa'un</option><option value="108">Al-Kawthar</option><option value="109">Al-Kaafiroon</option><option value="110">An-Nasr</option><option value="111">Al-Masad</option><option value="112">Al-Ikhlaas</option><option value="113">Al-Falaq</option><option value="114">An-Naas</option></select>
<div class="play-btn"></div>
</div>
<div id="surah-wrapper"></div>
THIS IS THE ACTUAL SCRIPT that i want to implement same: I would appreciate solution in context with script mentioned in the fiddle.
http://codepen.io/anon/pen/pRKreo
Here's you go. The biggest challenge I had was handling the value of this within the handler. Set your <audio> elements to preload="none". My script loads the next song as soon as you play one before it and auto-plays next song once first one finishes.
If you're worried about Global Scope just put it in an IIFE. Enjoy!
var files = document.getElementsByTagName('audio');
var songs = [];
var index = 0;
var Song = function(element) {
this.index = index;
this.playing = function(event) {
try {
files[this.index].preload = "auto";
}
catch (e) {
}
};
this.ended = function(event) {
try {
files[this.index].play();
}
catch (e) {
}
};
element.addEventListener('playing', this.playing.bind(this), false);
element.addEventListener('ended', this.ended.bind(this), false); // Trick
};
for (var len = files.length, i = 0; i < len; ++i) {
index++;
songs.push(new Song(files[i]));
}
ul{
list-style: none;
}
<!DOCTYPE html>
<html lang="en">
<meta name="description" content="HTML5 Media Auto Player Skeleton" />
<title>HTML5 Media Auto Player Skeleton</title>
<style>
</style>
</head>
<body>
<main>
<ul>
<li class="album">
<h3 class="album-title">HTML5 Media Player w Auto Next</h3>
</li>
<li>
<audio controls="controls" class="full-width" preload="metadata">
<source src="//rack.international/samples/AttritionDantesKitchenwWHellmixSAMPLE.mp3" type="audio/mpeg">
<source src="//rack.international/samples/AttritionDantesKitchenwWHellmixSAMPLE.ogg" type="audio/ogg">
Your browser does not support the audio element.
</audio>
</li>
<li>
<audio controls="controls" class="full-width" preload="metadata">
<source src="//rack.international/samples/AttritionDantesKitchenRascalKlonermxSAMPLE3.mp3" type="audio/mpeg">
<source src="//rack.international/samples/AttritionDantesKitchenRascalKlonermxSAMPLE3.ogg" type="audio/ogg">
Your browser does not support the audio element.
</audio>
</li>
<li>
<audio controls="controls" class="full-width" preload="metadata">
<source src="//rack.international/samples/crankRingtone.mp3" type="audio/mpeg">
<source src="//rack.international/samples/crankRingtone.ogg" type="audio/ogg">
Your browser does not support the audio element.
</audio>
</li>
</body>
</html>
You can use Promise.all(), Array.prototype.map(), Audio() constructor, canplaythrough event to load all audio first; then use Array.prototype.reduce(), Promise constructor to play audio in sequence at ended event.
var audioAddress = [
"http://download.quranicaudio.com/verses/Sudais/mp3/003001.mp3",
"http://download.quranicaudio.com/verses/Sudais/mp3/003002.mp3",
"http://download.quranicaudio.com/verses/Sudais/mp3/003003.mp3",
"http://download.quranicaudio.com/verses/Sudais/mp3/003004.mp3",
"http://download.quranicaudio.com/verses/Sudais/mp3/003005.mp3",
"http://download.quranicaudio.com/verses/Sudais/mp3/003006.mp3"
];
$("button").click(function() {
Promise.all(audioAddress.map(function(url) {
return new Promise(function(resolve) {
var audio = new Audio(url);
audio.oncanplay = function() {
resolve(audio);
}
})
}))
.then(function(data) {
data.reduce(function(promise, a, index) {
return promise.then(function() {
return new Promise(function(resolve) {
a.onended = resolve;
a.play();
$("p > span").removeClass("playing");
$("p > span:nth-child(" + (index + 1) + ")")
.addClass("playing");
})
})
}, Promise.resolve())
})
});
#myAudio {
display: none;
}
span {
margin: 0px 10px;
}
.playing {
background: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<button>Play Audio</button>
<p>
<span>Verse 1</span>
<span>Verse 2</span>
<span>Verse 3</span>
<span>Verse 4</span>
<span>Verse 5</span>
<span>Verse 6</span>
</p>
You can also create a mix of the sequence of audio tracks to play as a single track Is it possible to mix multiple audio files on top of each other preferably with javascript and use AudioContext.linearRampToValueAtTime Web audio api, stop sound gracefully.

HTML5 File API Upload Multiple Images with Ajax

I am trying to upload multiple images with File API. I want to show picture thumbnails and their names as title tag. The problem is I am not getting correct picture name as title tag. All pictures are showing same name.
Here is my Original code...
jQuery, CSS and HTML
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; i < iCount; i++)
{
var file = files[i];
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", function (event)
{
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + file['name'] + "'/>";
output.insertBefore(div, null);
});
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
I tried to figure it out and come to know that the value of var i changes automatically inside the
addEventListener("load", function (event){
// value of “var i” is not the same here as the value coming from outside this function.
});
I have no idea why value is changing inside the “load” function.
I Googled to see how others are doing same and ended up with this working example on SitePoint http://www.sitepoint.com/html5-file-drag-and-drop/
In this example I see these 2 major differences which I do not understand (my little knowledge in programming).
1. Syntax of for loop he is using in example
for (var i = 0, f; f = files[i]; i++) {
See he is assigning value to var f instead of applying stop condition.
Now my question is how the loop is working without stop condition is specified?
2. Separate function for reading files
He has made a separate function ParseFile(); to read files.
When I tried to read files without a separate function for file reading it is not working (as shown in my original code). But when I put that code in a separate function showThumbnail() for reading files and call that function inside loop it is working as it should be (as showing in below snippet). Why is this so?
Anyone here explain these two things to me.
Thanks in advance.
I followed the example and rearranged my code which is working as it should be. (Code is in below snippet.)
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; f = files[i]; i++)
{
showThumbnail(f);
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
function showThumbnail(file)
{
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", function (event)
{
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + file['name'] + "'/>";
output.insertBefore(div, null);
});
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
Haven't seen the edits to question before posting + misread it
So for your questions :
1 This for loop is waiting for file[i] to be undefined. :
for( var i=0, f; f=files[i]; i++).
If files[x]is undefined, then the loop stops (even if files[x+1] is defined)
2 It is because in your first snippet, your file variable is in the global scope and gets replaced during the iteration. In the second, however, it is linked to the showThumbnail function scope, and then passed in the EventListener.
To avoid calling an external function, you will need to call a file binded function :
From mdn : reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
So for you,
picReader.addEventListener("load", (function(aImg) { return function (event)
{
var picFile = event.target;
console.log(picFile);
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + aImg['name'] + "'/>";
output.insertBefore(div, null);
}; })(file));
Example below :
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; i < iCount; i++)
{
var file = files[i];
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", (function(aImg) { return function (event)
{
var picFile = event.target;
console.log(picFile);
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + aImg['name'] + "'/>";
output.insertBefore(div, null);
}; })(file));
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
Answer to question 1:
The for loop increments i with 1 on every iteration. When i is not an index of files the returned value will be undefined, which breaks the loop.
Answer to question 2:
I created a fiddle which shows how to put the code of showThumbnail in the for loop. It aslo explains the question.
The reason is behind the addEventListener function, which will run asynchronously with the for loop after load is triggered and has different scope. The function outside the loop is however permanent and the listener can use variables declared in that scope (the argument file).
What you can do however is to bind the listener function to the file object. The scope (this) of the function will be the file. See the fiddle for this to work.

How to handle multi key press for game purposes in jquery/javascript?

I'm trying to do a multi-key press combination validation for a "little game" test im doing.
Basically is a character from Mortal Kombat which I move with ASDW keys... but what happens if I want to duck and block at the same time (would be S + K) for example. And I couldn't make it work :S
Now... not only that, if I'm pressing only S, which will duck. Then I press K (while keeping S pushed) it should block while ducking. If I release the K, it should keep ducking. Is this one possible as well?
How to handle for example combinations for doing skills in javascript?
Like if I press S->D->Punch would do a skill (not pressed at the same time but a sequence)
Is there any possible way of doing all this?
This is my entire code inside a simple HTML so you can see it entirely:
P.S: Look at the comment in the preload image part, i mean, the animations are choppy while trying to move the character from one way to another... why is that? what am i doing wrong?
<! DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<style>
#reptile_wrapper {
top: 120px;
left: 140px;
position:relative;
}
#container {
margin-top: 240px;
margin-left: 470px;
width: 890px;
height: 301px; /* entire one 547px */
background: url("img/bgs/pit_background.png") no-repeat;
background-size: 100%;
}
#pit {
top: 0px;
position: relative;
width: 890px;
height: 300px;
background: url("img/bgs/pit.png") no-repeat;
background-size: 100%;
}
#pit_chain {
position: absolute;
width: 150px;
height: 340px;
background: url("img/bgs/pit_chains.png") no-repeat;
margin-left: 695;
}
</style>
</head>
<body>
<audio src="sounds/mk3thepit.mp3" preload="auto" loop="true" autoplay="true" autobuffer></audio>
<div id="pit_chain">
</div>
<div id="container">
<div id="pit">
<div id="reptile_wrapper">
<img src="img/reptile_idle.gif"/>
</div>
</div>
</div>
<script>
/* Preload all the images and gifs */
function preloadImages(srcs, imgs, callback) {
var img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
img.onload = function() {
--remaining;
if (remaining <= 0) {
callback();
}
};
img.src = srcs[i];
imgs.push(img);
}
}
// then to call it, you would use this
var imageSrcs = ["img", "img/bgs"];
var images = [];
preloadImages(imageSrcs, images, startGame());
/* End of preloading images and gifs */
var duckImages = ["d01", "d02"];
var defaultY = '120px';
reptileIdleAnimation();
function startGame() {
var keys = [];
window.addEventListener("keydown",
function(e){
keys[e.keyCode] = e.keyCode;
var keysArray = getNumberArray(keys);
if(keysArray.toString() == "68"){
$("#reptile_wrapper img").attr('src', 'img/reptile_walk_forward.gif')
.parent().css({left: '+=5px'});
}else if(keysArray.toString() == "17,65"){
// document.body.innerHTML += " Select all!"
}
},
false);
window.addEventListener('keyup',
function(e){
keys[e.keyCode] = false;
reptileIdleAnimation();
},
false);
function getNumberArray(arr){
var newArr = new Array();
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] == "number"){
newArr[newArr.length] = arr[i];
}
}
return newArr;
}
}
</script>
</body>
</html>
Thanks.
You don't necessarily need to rely on jQuery for capturing the keys.
Here is a plain javascript solution
var keys = [];
document.body.innerHTML = "Keys currently pressed: "
window.addEventListener("keydown",
function(e){
keys[e.keyCode] = e.keyCode;
var keysArray = getNumberArray(keys);
document.body.innerHTML = "Keys currently pressed:" + keysArray;
if(keysArray.toString() == "17,65"){
document.body.innerHTML += " Select all!"
}
},
false);
window.addEventListener('keyup',
function(e){
keys[e.keyCode] = false;
document.body.innerHTML = "Keys currently pressed: " + getNumberArray(keys);
},
false);
function getNumberArray(arr){
var newArr = new Array();
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] == "number"){
newArr[newArr.length] = arr[i];
}
}
return newArr;
}
As you can see, detecting multiple keypresses and releases at the same time is not a problem, technically speaking.
I think the only browser culprit here (for plain JS) is e.keyCode. If you want to use jQuery you can rewrite the listener definitions so that they use jQuery.
In this question i asked for a proper but plain image preloader.
See the answer supplied; you can use this code to handle the preloading properly.
Hope that helps!

Categories