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 HTMLand Javascript changed karaoke_youtube_apihtm 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 |
---|---|
thechanged HTML | thechanged HTML |
the_wrecking_crew |
disco_version |
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("//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 theAjax changed disco_versionhtmlโ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, yourchanged disco_versionhtml 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 โhowwe got thereโ disco_versionhtml 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_jshtmlโ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.