Today’s work enhancing yesterday’s The Wrecking Crew Dynamic Javascript YouTube Embedded API Peer Genericity Tutorial progress for the recently “made over” “The Wrecking Crew” and “Disco” web applications is not only to do with YouTube video …
- shoring up the search functionality (in that top textbox), now “subcontracting that out” to …
- the integration functionality with …
… the last talked about Karaoke YouTube Video Search Update Tutorial HTML and Javascript changed karaoke_youtube_api.htm web application with the cosy YouTube search relationship it has. In turn, integration goes the other way around as well via a multiple dropdown select mode via a new “Grid?” button mode of use, including the cute …
if multiple dropdown choice number correspond to number of clicks used, that order of clicking becomes the video order within that (potentially) 3x3 grid
… as we sometimes are very interested in “order” and “context” and “sequencing” with video content …
The Wrecking Crew | Disco |
---|---|
the changed HTML | the changed HTML |
the_wrecking_crew.html | disco_version.html |
The Wrecking Crew | Disco |
Previous relevant The Wrecking Crew Dynamic Javascript YouTube Embedded API Peer Genericity Tutorial is shown below.
Today we are genericizing (and thereby personalising) on top of the work of The Wrecking Crew Dynamic Javascript YouTube Embedded API Web Inspector Tutorial the recently “made over” “The Wrecking Crew” and “Disco” YouTube IFrame Player API web applications, which now have a “peer” relationship, by allowing for …
- comma separated YouTube video ID list (that can be entered into the topmost textbox)
- vertical bar delimited user defined video list Title
But what are we getting at by saying we are developing a peer relationship? It means via new select (dropdown) elements up the top of each, have URL values that when selected, can navigate you to, and the form of these URLs can be …
- the “home” default web application
- the “other” web application (ie. for “The Wrecking Crew” the “other” web application is “Disco”, and vice versa)
- user defined comma separated YouTube video ID list URLs …
… saved away for optional recall via window.localStorage logic, that is reflected by a hard coded web application title within a span element mapped to a select (dropdown) element within that same span element when the user has stored such a user defined list in localStorage …
var ourtwc=location.search.split('aprefix=')[1] ? decodeURIComponent(location.search.split('aprefix=')[1].split('&')[0]) : 'disco';
var yourtwc="Disco";
if (ourtwc != 'disco') { yourtwc=location.search.split('atitle=')[1] ? decodeURIComponent(location.search.split('atitle=')[1].split('&')[0]) : "Your List"; }
if (document.URL.indexOf('clear=') != -1) {
if (window.localStorage) {
localStorage.removeItem('list' + ourtwc);
localStorage.removeItem(ourtwc + 'list');
if (ourtwc != 'disco') { location.href=document.URL.split('?')[0].split('#')[0]; }
}
}
function ddit(yts) {
var outsug=yts, thisttl='', outyts=yts, yoursug='', sofarc='', altttl='';
var ione=1;
var lastlslook=' ';
if (window.localStorage) {
while (lastlslook != '') {
outsug=('000' + ione).slice(-3);
lastlslook=decodeURIComponent(('' + localStorage.getItem('list' + outsug))).replace(/\+/g,' ').replace(/^null$/g,'').trim();
console.log('yts=' + yts + ' and ione=' + ione + ' and lastlslook=' + lastlslook);
if (lastlslook.toLowerCase().indexOf('http') == 0) {
sofarc+=lastlslook;
//alert(lastlslook + ' ... ' + outyts);
if (lastlslook.indexOf('&atitle=') != -1) {
thisttl=decodeURIComponent(lastlslook.split('&atitle=')[1].split('&')[0].split('#')[0]);
} else {
thisttl=outsug;
}
if (outyts.indexOf('<SELECT') == -1) {
if (yts == 'Disco') {
console.log('a');
outyts="<SELECT id=syztitle onchange='location.href=this.value;'><option value='" + document.URL.split('?')[0].split('#')[0] + "'>Disco</option><option value='" + lastlslook.split('#')[0] + "'>" + thisttl + "</option><option value='" + lastlslook.split('#')[0].replace('?','?clear=y&') + "'>-" + thisttl + "</option><option value='" + document.URL.split('?')[0].split('#')[0].replace('/disco_version.','/the_wrecking_crew.') + "'>The Wrecking Crew</option></SELECT>";
} else if (document.URL.indexOf('atitle=') != -1) {
altttl=decodeURIComponent(document.URL.split('atitle=')[1].split('&')[0].split('#')[0]);
console.log('ta:' + thisttl);
outyts="<SELECT id=syztitle onchange='location.href=this.value;'><option value='" + document.URL.split('#')[0] + "'>" + altttl + "</option><option value='" + document.URL.split('#')[0].replace('?','?clear=y&') + "'>-" + altttl + "</option><option value='" + document.URL.split('?')[0].split('#')[0] + "'>Disco</option><option value='" + lastlslook.split('#')[0] + "'>" + thisttl + "</option><option value='" + lastlslook.split('#')[0].replace('?','?clear=y&') + "'>-" + thisttl + "</option><option value='" + document.URL.split('?')[0].split('#')[0].replace('/disco_version.','/the_wrecking_crew.') + "'>The Wrecking Crew</option></SELECT>";
} else if (document.URL.indexOf('aprefix=') != -1) {
altttl=decodeURIComponent(document.URL.split('aprefix=')[1].split('&')[0].split('#')[0]);
console.log('tb:' + thisttl);
outyts="<SELECT id=syztitle onchange='location.href=this.value;'><option value='" + document.URL.split('#')[0] + "'>" + altttl + "</option><option value='" + document.URL.split('#')[0].replace('?','?clear=y&') + "'>-" + altttl + "</option><option value='" + document.URL.split('?')[0].split('#')[0] + "'>Disco</option><option value='" + lastlslook.split('#')[0] + "'>" + thisttl + "</option><option value='" + lastlslook.split('#')[0].replace('?','?clear=y&') + "'>-" + thisttl + "</option><option value='" + document.URL.split('?')[0].split('#')[0].replace('/disco_version.','/the_wrecking_crew.') + "'>The Wrecking Crew</option></SELECT>";
} else {
console.log('b');
outyts="<SELECT id=syztitle onchange='location.href=this.value;'><option value='" + lastlslook.split('#')[0] + "'>" + thisttl + "</option><option value='" + lastlslook.split('#')[0].replace('?','?clear=y&') + "'>-" + thisttl + "</option><option value='" + document.URL.split('?')[0].split('#')[0] + "'>Disco</option><option value='" + document.URL.split('?')[0].split('#')[0].replace('/disco_version.','/the_wrecking_crew.') + "'>The Wrecking Crew</option></SELECT>";
}
} else if (lastlslook.toLowerCase().indexOf('http') == 0 && outyts.indexOf("<option value='" + lastlslook.split('#')[0] + "'>" + thisttl + "</option>") == -1) {
outyts=outyts.replace("</SELECT>","<option value='" + lastlslook.split('#')[0] + "'>" + thisttl + "</option><option value='" + lastlslook.split('#')[0].replace('?','?clear=y&') + "'>-" + thisttl + "</option></SELECT>");
}
} else if (outyts.indexOf('<SELECT') == -1) {
if (yts != 'Disco' && document.URL.indexOf('clear=') == -1) {
console.log('Yts=' + yts + ' and ione=' + ione + ' and lastlslook=' + lastlslook);
if (yourtwc.replace("Disco","") != '') {
thisttl=yourtwc;
} else {
thisttl=outsug;
}
console.log('c');
outyts="<SELECT id=syztitle onchange=location.href=this.value;><option value='" + document.URL.split('#')[0] + "'>" + thisttl + "</option><option value='" + document.URL.split('#')[0].replace('?','?clear=y&') + "'>-" + thisttl + "</option><option value='" + document.URL.split('?')[0].split('#')[0] + "'>Disco</option><option value='" + document.URL.split('?')[0].split('#')[0].replace('/disco_version.','/the_wrecking_crew.') + "'>The Wrecking Crew</option></SELECT>";
console.log('Yts=' + yts + ' and outsug=' + outsug + ' and thisttl=' + thisttl);
localStorage.setItem('list' + outsug, encodeURIComponent(document.URL.split('#')[0]));
lastlslook=decodeURIComponent(('' + window.localStorage.getItem('list' + outsug))).replace(/\+/g,' ').replace(/^null$/g,'').trim();
console.log('YTs=' + yts + ' and outsug=' + outsug + ' and lastlslook=' + lastlslook);
sofarc+=document.URL.split('#')[0];
yoursug=outsug;
}
} else {
}
ione++;
}
}
if (yoursug != '') {
if (sofarc.indexOf(document.URL.split('#')[0]) == -1 && document.URL.indexOf('clear=') == -1) {
console.log('5');
window.localStorage.setItem('list' + yoursug, encodeURIComponent(document.URL.split('#')[0]));
}
} else if (yts != 'Disco' && sofarc.indexOf(document.URL.split('#')[0]) == -1 && document.URL.indexOf('clear=') == -1) {
console.log('15');
window.localStorage.setItem('list' + outsug, encodeURIComponent(document.URL.split('#')[0]));
}
if (outyts.toLowerCase().indexOf('<select') == 0) {
tselih=outyts;
setTimeout(muchlater, 2000);
}
return outyts;
}
function undostop() {
document.getElementById('sytitle').innerHTML=ddit(yourtwc);
// rest of function code
}
setTimeout(undostop, 9000);
… as per … table above.
Previous relevant The Wrecking Crew Dynamic Javascript YouTube Embedded API Web Inspector Tutorial is shown below.
With the last couple of days of blog posting, including yesterday’s The Wrecking Crew Dynamic Javascript YouTube Embedded API Onerror Tutorial we risked the ire of many an internet reader by including in the blog posting itself HTML iframes of those twin “The Wrecking Crew” and “Disco” YouTube IFrame Player API web applications. Por que? Well, it is a bit of a sin to not give fair warning of future sound coming from a computer source of the internet. And, unless we were dreaming, earlier on this morning Australian Eastern Standard Time, that faux pas was possible. Sorry, if you were caught out.
We noticed the problem on an iPad, but never, so far, on our MacBook Pro. And this is quite possible. The stringency with which Apple tries to stop this happening with iOS is very noticeable to this programmer. It is understandable, though, that Apple would want to precede the creation of sound after an action (like a button press), so that a real human is part of the decision making.
We weren’t there ready with the tools to “scoop up” the information necessary to debug our “one off” iPad disappointment, alas. What is the next best? We have a lot of time for the web inspectors of the web browsers back at macOS (for the MacBook Pro). Team their use with Javascript …
console.log([Informational messaging]);
… (not alert([Informational messaging]); as we often settle for, but not today with the emphasis on trying to understand …
- the order
- the relationship
… among the YouTube IFrame Player API events, without the interference alert([Informational messaging]); (Javascript popup windows) could cause) … and you have a powerful debugging tool at your disposal. Even better if you can test on the iPad itself with the macOS Safari web browser Web Inspector (and the Apple white lead) as outlined with HTML5 Web Audio Piano Mobile Safari Web Inspector Debug Tutorial.
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.BUFFERING) { // && !done) {
curplay=curplay;
} else if (event.data == YT.PlayerState.CUED) { // && !done) {
curplay=curplay;
} else if (event.data == YT.PlayerState.PAUSED) { // && !done) {
//curv=eval(eval(1 + curv) % eval('' + 9));
//alert('' + curv);
if (curplay != '') { precv=curv; precp=curplay; }
curplay='';
//vplayer[curv].playVideo();
} else if (event.data == YT.PlayerState.PLAYING) { // && !done) {
if (dostop) {
console.log('onPlayerStateChange: dostop');
stopthese.push(event.target);
setTimeout(stopVideo, 6000);
} else if (curplay == '') {
if (precp == event.target.getVideoUrl().split('=')[1].split('&')[0]) {
//alert(1);
console.log('onPlayerStateChange: 2;' +precp);
curplay=precp;
curv=precv;
} else if (1 == 6) {
//alert(11);
mid=precv;
if (1 == 2) { vplayer[curv].mute(); }
}
curplay=event.target.getVideoUrl().split('=')[1].split('&')[0];
curdur=eval('' + event.target.getDuration());
console.log('onPlayerStateChange: 3;precp=' + precp + ';' + event.target.getVideoUrl() + ';' + curplay + ';' + curdur);
for (var ijj=0; ijj<yid.length; ijj++) {
if (yid[ijj].indexOf(curplay + '|') == 0) { curv=ijj; }
}
if (mid >= 0) { setTimeout(midit, 2000); }
//}
//alert(curplay + ' ... ' + curv);
} else {
//console.log('' + eval('' + event.target.getCurrentTime()) + ' >= ' + curdur);
if (eval(2 + eval('' + event.target.getCurrentTime())) >= curdur) {
// alert('ready');
vplayer[curv].mute();
console.log('onPlayerStateChange: 4;' + vplayer[curv].getVideoData().title + ';mute;seekTo;unMute;play');
curv=eval(eval(1 + curv) % eval('' + 9));
//alert('' + curv);
//vplayer[curv]=eval("new YT.Player('vplayer" + eval(1 + curv) + "', { height: '260', width: '33%', videoId: '" + yid[curv] + "', events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange }})");
curplay='';
vplayer[curv].seekTo(0,true);
vplayer[curv].unMute();
vplayer[curv].playVideo();
//alert('2:' + curv);
}
}
//done = true;
} else if (curplay != '') {
//console.log('' + eval('' + event.target.getCurrentTime()) + ' >= ' + curdur);
if (eval(2 + eval('' + event.target.getCurrentTime())) >= curdur) {
// alert('Ready');
vplayer[curv].mute();
console.log('onPlayerStateChange: 5;' + vplayer[curv].getVideoData().title + ';mute;seekTo;unMute;play');
curv=eval(eval(1 + curv) % eval('' + 9));
//alert('' + curv);
curplay='';
vplayer[curv].seekTo(0,true);
vplayer[curv].unMute();
vplayer[curv].playVideo();
//alert('3:' + curv);
}
}
}
… leading to the eventual three codeline solution you see below …
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
var dis, cti, gvd, uri, jis, prv='', iyi=0, huht='';
if (!lsdone) {
lsdone=true;
scont=scont.replace('</option>', '</option>' + tryls());
//alert(('' + scont.split('</option>').length));
}
uri=event.target.getVideoUrl();
jis=yid.indexOf(uri.split('=')[1].split('&')[0]);
dis=event.target.getDuration();
cti=event.target.getCurrentTime();
gvd=event.target.getVideoData().title;
console.log('onPlayerReady:' + uri + ';' + dis + '|' + cti + '|' + gvd);
yid[jis]+='|' + dis + '|' + cti + '|' + gvd;
//alert(yid[jis]);
splaycnt++;
if (splaycnt > 9) {
if (scont.indexOf(yid[jis]) == -1) {
prv=scont;
if (scont.indexOf('>' + gvd + '<') == -1) { scont=prv.split('</option>')[0] + '</option><option id="' + yid[jis].split('|')[0] + '" onclick="oclick(this);" value="' + yid[jis] + '">' + gvd + '</option>' + prv.replace(prv.split('</option>')[0] + '</option>',''); }
}
} else {
if (scont.indexOf('>' + gvd + '<') == -1) { scont+='<option id="' + yid[jis].split('|')[0] + '" onclick="oclick(this);" value="' + yid[jis] + '">' + gvd + '</option>'; }
if (splaycnt == 9 && yid.length > 9) {
for (iyi=0; iyi<yid.length; iyi++) {
if (scont.indexOf(yid[iyi]) == -1) {
try {
huht=vplayer[splaycnt].getVideoData().title;
prv=scont;
if (scont.indexOf('>' + gvd + '<') == -1) { scont=prv.split('</option>')[0] + '</option><option id="' + yid[iyi].split('|')[0] + '" value="' + yid[iyi] + '" onclick="oclick(this);">' + gvd + '</option>' + prv.replace(prv.split('</option>')[0] + '</option>',''); }
} catch(rtde) {
}
}
}
}
}
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
event.target.mute();
}
event.target.playVideo();
event.target.mute();
}
… and in action with today’s tutorial picture … and … see table up the webpage.
Previous relevant The Wrecking Crew Dynamic Javascript YouTube Embedded API Onerror Tutorial is shown below.
Again, both yesterday’s The Wrecking Crew Dynamic Javascript YouTube Embedded API Ajax Tutorial and User Controlled Dynamic Javascript YouTube Embedded API Ajax Tutorial before it can benefit from today’s improvement idea regarding videos whose creators have stopped their YouTube videos from being able to be launched from non-YouTube websites, as we are asking of YouTube content we link to with our YouTube IFrame Player API driven twin web applications. What’s needed to avoid the …
Video unavailable
Watch this video on YouTube.
Playback on other websites has been disabled by the
video owner.
…. issue we are talking about here? That issue is annoying in two parts …
- cannot play video in that embedded iframe element … and …
- if playing on a non-mobile platform, encountering an iframe with this error halts any thoughts of “continuous play” (like a playlist that repeats and keeps playing, like on the radio) that the user may like (on in the background, while they do something else, for instance)
Well, it’s an event we have to “kick into play”, that you ordinarily might be able to ignore, as per …
vplayer.push(eval("new YT.Player('vplayer" + ii + "', { height: '260', width: '33%', videoId: '" + yid[-1 + ii] + "', playerVars: { autoplay: 0, controls: 1, disablekb: 1, loop: 0, modestbranding: 0, showinfo: 0, autohide: 1, color: 'white', iv_load_policy: 3, theme: 'light', rel: 0 }, events: { 'onError': onProblem, 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange }})"));
… calling on a new Javascript event function …
function onProblem(event) {
console.log(event.target.f);
console.log(event.target.l);
var pvidid='', embedurl='', vtitle='';
if (event.target.f.outerHTML.indexOf('embed/') != -1) {
pvidid=event.target.f.outerHTML.split('embed/')[1].split('?')[0];
}
if (pvidid != '') {
if (lastscont.indexOf(pvidid) != -1) {
// D-TC8CRCIKM|194|0|The Grass Roots - Sooner Or Later - [original STEREO]
//alert(lastscont.split(pvidid)[1]);
var vbs=lastscont.split(pvidid)[1].split('|');
if (eval('' + vbs.length) >= 4) {
vtitle='' + vbs[3];
}
}
if (event.target.f.outerHTML.indexOf(' class="player-unavailable"') != -1 || pvidid != '') {
embedurl='http' + event.target.f.outerHTML.split('http')[1].split('"')[0];
if (document.URL.toLowerCase().indexOf('rjmprogramming.com.au/') != -1) {
var zzhr = new XMLHttpRequest();
var zzform=new FormData();
zzform.append('inline', '');
zzform.append('to', 'rmetcalfe@rjmprogramming.com.au');
zzform.append('subj', 'Please find alternative to YouTube ' + pvidid + ' in relevant code ... ' + vtitle);
zzform.append('body', encodeURIComponent('Problem video is first iframe of ... ' + String.fromCharCode(10) + String.fromCharCode(10) + document.URL.split('#')[0].split('?')[0] + '?hastoinclude=' + pvidid + String.fromCharCode(10) + String.fromCharCode(10) + 'Problem YouTube video is ... ' + String.fromCharCode(10) + String.fromCharCode(10) + "https://www.youtube.com/watch?v=" + pvidid));
zzhr.open('post', '//www.rjmprogramming.com.au/HTMLCSS/emailhtml.php', true);
zzhr.send(zzform);
//var remurl='mailto:rmetcalfe@rjmprogramming.com.au?subject=' + encodeURIComponent('Please find alternative to YouTube ' + pvidid + ' in relevant code ... ' + vtitle) + '&body=' + encodeURIComponent('Problem video is first iframe of ... ' + String.fromCharCode(10) + String.fromCharCode(10) + document.URL.split('#')[0].split('?')[0] + '?hastoinclude=' + pvidid + String.fromCharCode(10) + String.fromCharCode(10) + 'Problem YouTube video is ... ' + String.fromCharCode(10) + String.fromCharCode(10) + "https://www.youtube.com/watch?v=" + pvidid);
//if (('' + document.getElementById('badvideo').href).indexOf('mailto') != 0) { document.getElementById('badvideo').href=remurl; document.getElementById('badvideo').click(); }
} else {
var emurl='mailto:rmetcalfe@rjmprogramming.com.au?subject=' + encodeURIComponent('Please find alternative to YouTube ' + pvidid + ' in relevant code ... ' + vtitle) + '&body=' + encodeURIComponent('Problem video is first iframe of ... ' + String.fromCharCode(10) + String.fromCharCode(10) + document.URL.split('#')[0].split('?')[0] + '?hastoinclude=' + pvidid + String.fromCharCode(10) + String.fromCharCode(10) + 'Problem YouTube video is ... ' + String.fromCharCode(10) + String.fromCharCode(10) + "https://www.youtube.com/watch?v=" + pvidid);
if (('' + document.getElementById('badvideo').href).indexOf('mailto') != 0) { document.getElementById('badvideo').href=emurl; document.getElementById('badvideo').click(); }
}
}
}
}
… which, as you may have gleaned, provides us an email mechanism by which we, here at RJM Programming, can be informed about when a YouTube video ID we reference, perhaps into the future, becomes restrictive, this way (and hopefully we can find an alternative YouTube video ID to use) … see table up the webpage.
Previous relevant The Wrecking Crew Dynamic Javascript YouTube Embedded API LocalStorage Tutorial is shown below.
Both yesterday’s The Wrecking Crew Dynamic Javascript YouTube Embedded API Ajax Tutorial and User Controlled Dynamic Javascript YouTube Embedded API Ajax Tutorial before it can benefit from today’s improvement idea. That idea involves data storage that stays on the “client” side of the “client/server” web application architecture. Yes, as you may have noticed, these web applications were not offering all the options they could for those user controlled entry list dropdowns at the bottom.
We use the window.localStorage now to gradually store all the content those dropdowns could hold. So it is as if the web application “learns its lines” over time with these improvements …
var lsdone=false;
if (document.URL.indexOf('clear=') != -1) {
if (window.localStorage) {
window.localStorage.removeItem('twclist');
}
}
function lessopt(selih) {
var outih=selih, opttoadd='';
var opta=selih.split('</option>');
if (opta.length > 1) {
outih='';
for (var iop=0; iop<opta.length; iop++) {
if (opta[iop] != '') {
opttoadd='<option' + opta[iop].split('<option')[1] + '</option>';
if (outih.indexOf(opttoadd) == -1) {
outih+=opttoadd;
}
}
}
}
return outih;
}
function tryls() {
var lastscont='';
if (window.localStorage) {
lastscont=decodeURIComponent(('' + window.localStorage.getItem('twclist'))).replace(/\+/g,' ').replace(/^null$/g,'');
}
return lastscont;
}
function setls(towhat) {
var lastscont='';
if (window.localStorage) {
window.localStorage.setItem('twclist', encodeURIComponent(towhat));
}
return lastscont;
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
var dis, cti, gvd, uri, jis, prv='', iyi=0, huht='';
if (!lsdone) {
lsdone=true;
scont=scont.replace('</option>', '</option>' + tryls());
}
// Rest of code
}
function undostop() {
document.getElementById('xshuffle').style.visibility='visible';
bprefix=topics.replace(/\|/g, ', ');
if (bprefix != '') {
var huhb=document.getElementById('wshuffle').innerHTML;
document.getElementById('wshuffle').innerHTML=bprefix + ', ' + huhb;
}
document.getElementById('wshuffle').style.visibility='visible';
document.getElementById('pshuffle').style.visibility='visible';
document.getElementById('qshuffle').style.visibility='visible';
document.getElementById('rshuffle').style.visibility='visible';
if (yid.length > 9 || 1 == 1) {
var tdsl=document.getElementsByTagName('td');
document.getElementById('oone').innerHTML=document.getElementById('oone').innerHTML.replace(' 9 slots available)', ' 9 slots available, ' + tdsl.length + ' total)');
document.getElementById('ashuffle').style.visibility='visible';
document.getElementById('zshuffle').style.visibility='visible';
scont=lessopt(scont);
document.getElementById('sshuffle').size=eval(-1 + eval('' + scont.split('</option>').length));
document.getElementById('sshuffle').innerHTML=scont;
setls(document.getElementById('sshuffle').innerHTML.replace(document.getElementById('sshuffle').innerHTML.split('</option>')[0] + '</option>', ''));
document.getElementById('dshuffle').style.visibility='visible';
}
document.getElementById('rshuffle').focus();
dostop=false;
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//alert(1);
//const huhss=document.querySelectorAll('video');
//alert(11);
for (var hdiv=0; hdiv<vplayer.length; hdiv++) {
//alert(111);
vplayer[hdiv].unMute();
//alert(hdiv.id);
}
//.webkitEnterFullScreen();
}
}
… gleaning information about the videos as they load them (especially the video titles and durations) via the YouTube Embedded Iframe API code for … see table up the webpage.
Previous relevant User Controlled Dynamic Javascript YouTube Embedded API Ajax Tutorial is shown below.
Around here we have our favourite Javascript and PHP function names. And in that list, the Javascript “ajaxit([argument1])” features strongly and commonly. After reaching below the sink After talking excitedly to the kitchen taps about my plans … oddly, receiving no reply … probably because it’s a Monday here … we expect … we use that Javascript client Ajax approach that can do for you what you would often call on a serverside language, like PHP, to do?! Anyone, anyone? No, Barbara Woodhouse, we do not wrelease the tap dancing dogs on Mondays … ever … any more serious suggestions please? Yes, Jesse James Garrett it’s interesting your blurtings include …
the asynchronous technology behind emerging services like Google Maps and Google Suggest, as well as the resulting user experience which made it possible to browse without interruption by eliminating the reloading of the whole page
… though I’d like you to run a plagorism checker on all “blurtings” and “lerts” for the next lesson please.
Yes, under certain conditions, Ajax (methodologies) can retrieve information and not have to leave what you are interacting with on the current webpage, to do this.
Can you imagine how we might apply this with our current project? Yes, patently not everyone is in the mood for “Disco”, especially on the first draft way back when, when we allowed sound to happen before a decently “flagged” button press to forewarn … a fairly big “Internet sin”, since fixed. And so, we now add HTML input textbox (ie.type=text) element, with onblur event “ajaxit([argument1])” logic (passing across the textbox’s value) as per …
var zhr=null;
var url='';
var zok=0;
function ajaxit(qsel) {
if (qsel != '') {
url="//www.rjmprogramming.com.au/HTMLCSS/legend_via_map.php?url=" + encodeURIComponent("http://www.youtube.com/results?search_query=" + encodeURIComponent(qsel));
if (!zhr) {
zhr = getXMLHttpRequest();
}
if (zhr != null) {
zhr = zhr;
} else {
try {
zhr = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
zhr = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
zhr = false;
}
}
}
if (zhr) {
if (url != '') {
zok=0;
zhr.open("GET", url, true);
zhr.onreadystatechange = showStuff;
zhr.send(null);
url='';
}
} else {
zok = 1; //alert("Sorry ... no XMLHttpRequest possible");
}
}
}
… to add new concepts into the mix of option (sub)elements offered off that aforesaid mentioned (multiple selection mode) dropdown (of YouTube videos). As an optional “off default workflow” piece of functionality we show it prominently (above the fold) now, as well as “below the fold” where the dropdown is positioned on the webpage of the Ajax changed disco_version.html‘s live run.
Adding to yesterday’s User Controlled Dynamic Javascript YouTube Embedded API Ordered Tutorial …
Previous relevant User Controlled Dynamic Javascript YouTube Embedded API Ordered Tutorial is shown below.
We think that whenever you …
- deprive many people of “order” in their lives … they’ll crave for (and maybe seek out) “order” … and when you …
- deprive many people of “randomosity” in their lives … they’ll crave for (and maybe seek out) “randomosity”
… and so we see a mix of both in a web application as an advantage. Today, for the first time we can remember, extending onto yesterday’s User Controlled Dynamic Javascript YouTube Embedded API Tutorial functionality, definitely lacking some “order” we feel, we’ve allowed a …
- select “dropdown” element …
- multiple mode … have its …
- button press “finish of selections” event logic …
function process(bsin) {
var jj=0, mbo='', mlist='', mdelim='', vscnt=0;
var sin=document.getElementById(bsin.id.replace('b','s'));
for (var i=0; i<sin.options.length; i++) {
if (sin.options[i].selected) {
if (sin.options[i].value != '') {
jj++;
vscnt++;
mbo=sin.options[i].value.split('|')[0];
mlist+=mdelim + sin.options[i].value.split('|')[0];
mdelim=',';
}
}
}
if (jj == 1) {
location.href=(document.URL.split('#')[0].replace('mustbeone=','mustxxxbeone=') + '&mustbeone=' + encodeURIComponent(mbo)).replace('.html&','.html?').replace('.htm&','.htm?').replace('.php&','.php?').replace('/&','/?');
} else if (jj > 1) {
if (oclickcnt == vscnt) { mlist=olist; }
location.href=(document.URL.split('#')[0].replace('mustbeone=','mustxxxbeone=').replace('videolist=','videoxxxlist=') + '&videolist=' + encodeURIComponent(mlist)).replace('.html&','.html?').replace('.htm&','.htm?').replace('.php&','.php?').replace('/&','/?');
}
oclickcnt=0;
occ=[];
olist='';
odelim='';
}
- take into account the order the user clicked select element option elements …
var oclickcnt=0;
var occ=[];
var olist='';
var odelim='';
function oclick(opto) {
oclickcnt++;
olist+=odelim + opto.id.split('|')[0];
odelim=',';
}
… option element onclick event Javascript event logic… so long as … - these two or more clicks/touches on option elements (via their onclick event logics) (total in) number (to) the same (total) as the final number of options selected (ie. most “shift” key arrangement selections cannot be catered for in this logic, but totally “ctrl” (Windows) / “command” (macOS) key may work)
… allowing for the user to control the video list, and its order.
And on non-mobile platforms, we allow for a natural “sequencing” of play, once the first video is played and unmuted. That way, on non-mobile, your changed disco_version.html live run web application can act like a continuous (radio like) “stream” of music. Even so, on non-mobile, a user can “pause” a video, and start another via their own user actions, and the “stream” sequencing will change to fit in with the changed arrangements.
Previous relevant User Controlled Dynamic Javascript YouTube Embedded API Tutorial is shown below.
The recent Dynamic Javascript and the YouTube Embedded API Tutorial showed the great YouTube IFrame Player API in action, including … and this dovetails well into today’s work … no advertisements.
A lot of us will know how great YouTube playlists are. Today, we offer a(n example of) …
- an up to 9 “Disco Version” random array of YouTube videos that can be played ina session …
- from a possible array of 24 table cell slots (10-24 not shown, but “duration”able behind the scenes) …
- the 15 not randomly picked available to the user in a dropdown selection they can, optionally …
- pick one from,click a “Shuffle” button, and a randomized list of 8 others is headedby your selected video … or …
- pick more than one and the first (up to 9) forms your ordered selection of playable videos
… and the progress today leaves you controlling when to play the videos, yourself, clicking YouTube play buttons to make that happen.
Enjoy the “how we got there” disco_version.html upbeat disco selection live run link.
Previous relevant Dynamic Javascript and the YouTube Embedded API Tutorial is shown below.
Webpages without Javascript are generally pretty static and boring. Javascript is that dynamic client addition to webpage functionality, but perhaps you only think of it as that statically written part of the webpage unable to be reloaded into effect after that initial webpage load. Well, that is not taking into account Javascript such as …
<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
</script>
… taken from the excellent YouTube IFrame Player API we really like to use around here to embed and control YouTube videos embedded into an HTML iframe element.
In today’s small extension of that we load nine such HTML iframe embedded YouTube videos into a 3×3 grid. We resisted the previous Brady Bunch usage of such an arrangement (perhaps you’ll be sad to hear?!) in favour of showing you a “collage” of video snippets from one of my favourite films ever, Mr Smith Goes to Washington.
We hope the HTML and Javascript dynamic_js.html‘s code will be food for thought, that you can test for yourself at this live run link.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.