YouTube API Caller Post Winding Up For Now Tutorial

YouTube API Caller Post Winding Up For Now Tutorial

YouTube API Caller Post Winding Up For Now Tutorial

You knew we were “winding you up” when we presented YouTube API Caller Winding Up For Now Tutorial, didn’t you?! It can’t be the total end of the story, right?!

Yes, we found both …

  • issues … and …
  • improvements to make

… regarding that “compilation mode” 📻 “emoji button” double click within bottom buttons mode of YouTube video Radio Play modus operandi. Clearly, Luna …

… knew the jig was up!

Under “issues” we’d say it boiled down to URLs capable of going past the error 414 length limits. And what of “improvements to make”? Well, the most interesting one, for us, was to …


if (!independent) {
prefix='isradio=YES&completionmatters=y' + argshuffle + '&';
if (eval('' + dsa.length) > 1 && eval('' + wsa.length) > 1) {
var anarr=ytlist.split(',');
anarr.sort();
ytlist='' + anarr[0];
for (var inb=1; inb<anarr.length; inb++) {
ytlist+=',' + anarr[inb];
}
}
}

… aid with the randomization of YouTube video songs (in amongst the three categorizations we’ve got going out of Disco and The Wrecking Crew and Yacht Rock) …

  • collected as three separate “lump components” to the YouTube video list (before this new sorting idea) … but, of course …
  • sorting via YouTube video ID brings back the randomness to the order … and fits in with …
  • the default “shuffle on” setting for this “compilation play” Radio Play

… thinking.

And so, feel ever so free to try the changed swipe_media.html Tabular Single Row Media Gallery web application.


Previous relevant YouTube API Caller Winding Up For Now Tutorial is shown below.

YouTube API Caller Winding Up For Now Tutorial

YouTube API Caller Winding Up For Now Tutorial

We’re calling it quits after today regarding the YouTube media aspects to the Media Gallery web application yesterday’s YouTube API Caller Order and Completion Tutorial.

We’ll be back, because we always find things, and come across, via others mostly (thanks), new ways to do things, but what are the things achieved for the firstish time, for us, in this project? We think …

  • Radio Play (better than a previous incarnation) of YouTube videos on mobile or non-mobile (and for the first time we can remember there were days when mobile was out ahead of non-mobile for it all working, curiously)
  • Bluetooth has “hidden powers” … sorry to be this vague, but you need to test this YouTube API logics going into and out of Bluetooth
  • continuous YouTube media play, this way, at the end of the day, needs your website to not be struggling, the logic dependent on setTimeout logics (which have to be continually called) … ie. you need to maintain “connection”
  • how good is Lorem Picsum, thanks, regarding being a great free image repository … old news but good news

And so, today, we fixed up an issue that appeared to us using the macOS Opera browser. The bottom buttons were missing, and the fix will surprise some. Not fancy pants thinking


var isOpera = (navigator.userAgent.match(/Opera|OPR\//) ? true : false);
var agentruew=eval('' + document.documentElement.clientWidth);
var agentrueh=eval('' + document.documentElement.clientHeight);
var amax=Math.max(agentruew,agentrueh);
var amin=Math.min(agentruew,agentrueh);
amin-=60;
//if (isOpera) {
// amin-=80;
//}

… just “dumbing it down” if you will. Trying a simple fix, like …

  • removing two of the left hand cell | characters fixed the issue (highlighting the CSS subtleties of visibility:hidden; (still retaining the whitespace) versus display:none; (no retension of whitespace) approaches to hiding elements, in our case the “breadcrumb navigation” first approach we’re leaving in, in case we return to the idea under a visibility:hidden; paradigm)
  • and while we were there removed the grating underlining of these

Doh!

And so, feel free to try the mildly tweaked swipe_media.html Tabular Single Row Media Gallery web application.

Did you know?

Yes, overthinking things can be detrimental. It is good to think complex issues through, away from any struggle you’ve been having for hours, when you only expected that issue to take a few minutes.

But … even above … we would not have arrived at the “| character removal” fix quickly, if we had not gone though the other “overthinking part tests” to ascertain what was possible, if you get my drift. How you spend development hours, and how efficient you are are variables, and will change from day to day. There might be days you are best not touching the keyboard (and ditch the mobile too).


Previous relevant YouTube API Caller Order and Completion Tutorial is shown below.

YouTube API Caller Order and Completion Tutorial

YouTube API Caller Order and Completion Tutorial

Up until yesterday’s YouTube API Caller Breadcrumb Navigation Tutorial a lot of the theme to …

  • YouTube video presentation tended towards “the random” … fun for programmers and gamers alike (actually pretty essential for a lot of the work of the latter) … but eventuality for human mental health, or for episodic video media data, you’ll want a way to introduce …
  • “order” … as designated by the user in an amended prompt window …

    Enter YouTube 11 character code video (comma separated) or audio stream only of video (semicolon separated) list to Radio Play (and add ! to start in shuffle mode and/or # to honour the order you enter and/or & to ensure whole list passes through) … or a YouTube Search String basis to create a playlist via a Radio📻? button to activate, later.

    … and/or …

  • talked about today and in

  • “completion” … as designated by the user in same prompt window … ie. hang around for whole list to be scanned for video durations, and passed on

And further to the work of the day before yesterday’s YouTube API Caller Replaced Video Entry Tutorial we wanted to extend that logic introduced there in two ways …

  • allow for a comma separated list of 11 character YouTube video IDs be accepted …
  • have entries be immediately processed should the entry (or comma separated entries) be made in the currently active YouTube playing video’s associated textbox … via …

    var geleven=-1;

    function onoff() {
    var nnum=0;
    if (geleven >= 0) {
    backtolist=['c' + eval('' + geleven)];
    document.getElementById('c' + geleven).checked=false;
    while (document.getElementById('i' + nnum)) {
    if (('' + nnum) != ('' + geleven)) {
    if (document.getElementById('c' + nnum).checked) {
    backtolist.push('c' + eval('' + nnum));
    }
    document.getElementById('c' + nnum).checked=false;
    }
    nnum++;
    }
    //document.getElementById('c' + geleven).checked=true;
    geleven=-geleven;
    //checkval(document.getElementById('i' + Math.abs(geleven)));
    setTimeout(function(){ document.getElementById('c0').checked=false; document.getElementById('c' + Math.abs(geleven)).checked=true; }, 2400);
    setTimeout(function(){ for (var ik=0; ik<backtolist.length; ik++) { document.getElementById(backtolist[ik]).checked=true; } backtolist=[]; }, 6500);
    }
    }

… into the mix in …


Previous relevant YouTube API Caller Breadcrumb Navigation Tutorial is shown below.

YouTube API Caller Breadcrumb Navigation Tutorial

YouTube API Caller Breadcrumb Navigation Tutorial

Further to yesterday’s YouTube API Caller Replaced Video Entry Tutorial we wanted to offer the “Radio Play” users of our Tabular Single Row Media Gallery web application the chance to use Breadcrumb style navigation aids regarding …

  • << … navigate to first YouTube video of interest in the playlist
  • < … navigate to previous YouTube video of interest in the playlist
  • > … navigate to next YouTube video of interest in the playlist
  • >> … navigate to last YouTube video of interest in the playlist

… referencing this onclick Javascript logic …


function knaviga(evt) {
var oso=evt.target;
evt.stopPropagation();
if (eval('' + backtolist.length) > 0) {
for (var iik=0; iik<backtolist.length; iik++) {
document.getElementById('' + backtolist[iik]).checked=true;
}
}
backtolist=[];
var keepg=true, ik=0, lva='0';
prevwoin='0';
woinnext='0';
woinlast='0.0';
firstwoin='0.0';
//xnextwoin='999';
var knum=0;
while (document.getElementById('xx' + knum)) {
if (('' + document.getElementById('xx' + knum).outerHTML).indexOf('green') != -1) {
prevwoin='' + lva;
if (1 == 1 || eval('' + knum) > eval('' + xnextwoin)) { xnextwoin='' + knum; }
lva='' + knum;
woinnext=woinnext.replace('.0','');
}
if (document.getElementById('c' + knum)) {
if (document.getElementById('c' + knum).checked) {
if (firstwoin.indexOf('.0') != -1) {
firstwoin='' + knum;
woinlast='' + knum;
} else {
woinlast='' + knum;
}
if (eval('' + knum) == eval('' + xnextwoin)) {
woinnext='' + knum + '';
} else if (eval('' + knum) > eval('' + xnextwoin) && woinnext.indexOf('.0') == -1) {
woinnext='' + knum + '.0';
}
backtolist.push('c' + knum);
}
}
knum++;
}
knum=0;
while (document.getElementById('c' + knum)) {
if (eval('' + knum) < eval('' + xnextwoin)) { prevwoin='' + knum; }
knum++;
}
var ourthisval='' + oso.id;
//top.document.title='' + xnextwoin + ':' + document.getElementById('xx0').outerHTML.split('>')[0] + ':' + ('' + new Date());
if (keepg && window.parent) {
if (top.document.getElementById('navig')) {
if (ourthisval.trim() != '') {
if (ourthisval.trim() == 'sback') {
if (document.getElementById('c' + xnextwoin)) {
for (ik=0; ik<knum; ik++) {
if (('' + ik) != ('' + prevwoin) && document.getElementById('c' + ik)) {
document.getElementById('c' + ik).checked=false;
}
}
setTimeout(function(){ for (var ik=0; ik<backtolist.length; ik++) { document.getElementById(backtolist[ik]).checked=true; } backtolist=[]; }, 3500);
}
} else if (ourthisval.trim() == 'snext') {
if (document.getElementById('c' + xnextwoin)) {
for (ik=0; ik<knum; ik++) {
if (('' + ik) != ('' + woinnext.split('.')[0]) && document.getElementById('c' + ik)) {
document.getElementById('c' + ik).checked=false;
}
}
setTimeout(function(){ for (var ik=0; ik<backtolist.length; ik++) { document.getElementById(backtolist[ik]).checked=true; } backtolist=[]; }, 3500);
}
//alert('bYES ' + nextwoin + parent.document.getElementById('navig').value);
} else if (ourthisval.trim() == 'sfirst') {
if (document.getElementById('c' + xnextwoin)) {
for (ik=0; ik<knum; ik++) {
if (('' + ik) != ('' + firstwoin.split('.')[0]) && document.getElementById('c' + ik)) {
document.getElementById('c' + ik).checked=false;
}
}
setTimeout(function(){ for (var ik=0; ik<backtolist.length; ik++) { document.getElementById(backtolist[ik]).checked=true; } backtolist=[]; }, 3500);
}
} else if (ourthisval.trim() == 'slast') {
if (document.getElementById('c' + xnextwoin)) {
for (ik=0; ik<knum; ik++) {
if (('' + ik) != ('' + woinlast.split('.')[0]) && document.getElementById('c' + ik)) {
document.getElementById('c' + ik).checked=false;
}
}
setTimeout(function(){ for (var ik=0; ik<backtolist.length; ik++) { document.getElementById(backtolist[ik]).checked=true; } backtolist=[]; }, 3500);
}
}
parent.document.getElementById('navig').value='';
}
}
}
}

… along with the “single song obsessional looping” logic of a couple of days ago made toggleable (to better fit in with these new ideas, we felt), all in the changed karaoke_youtube_api.htm inhouse YouTube video interfacer and establish a two day limit of availability regarding data URI public URL media links, enough time we figure for sharing and any collaboration (but will not translate well for any saved playlist arrangements involving any data URI user based entries and outside those two days, alas) in our changed PHP helper signature_signature.php

<?php

if (isset($_POST['an_i_tidy']) || isset($_GET['an_i_tidy'])) {
foreach (glob($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'karaoke_i_bizzo_' . '*.*') as $dfilename) {
$filemtime = filemtime($dfilename);
if (time() - $filemtime >= 172800) { // 86400 seconds in a day
unlink($dfilename);
}
}
}

?>

… called by the modified stop_start_youtube.html YouTube API caller.


Previous relevant YouTube API Caller Replaced Video Entry Tutorial is shown below.

YouTube API Caller Replaced Video Entry Tutorial

YouTube API Caller Replaced Video Entry Tutorial

In addition to the …

  • user entry URL … and now …
  • user entry data URI … optionally using local file browsing …

… playlist amending tools available to users within yesterday’s YouTube API Caller Radio Play Phase Two Data URI PHP Tutorial today we’ve added the more obvious …


user entry of different YouTube 11 character video ID

… into the mix in …


Previous relevant YouTube API Caller Radio Play Phase Two Data URI PHP Tutorial is shown below.

YouTube API Caller Radio Play Phase Two Data URI PHP Tutorial

YouTube API Caller Radio Play Phase Two Data URI PHP Tutorial

Further to yesterday’s YouTube API Caller Radio Play Obsession Looping Tutorial, and concerning …

  • phase two data URI user media interactive textbox entries …
  • we’d actually started down it’s road in our first pass of PHP work a couple of weeks ago … and we are really happy we “let that stew” because …
  • returning to the work today we developed a much easier concept than …
    1. give the data URI a nickname shortening that data URI and bring it into play at the appropriate moment … versus today’s much better …
    2. store the data as a media file on our server for a length of time (we haven’t organized yet)

That way a …

  1. data URI is entered into a textbox by the user … and they can locally browse for this if they want …
  2. the onblur event logic immediately calls the PHP to create the temporary web server media file (stored in a public URL place) … so …
  3. into the textbox we map the public URL place media URL over the data URI

… and avoid any “too long URL” errors as well as not needing to map between any nicknames with real data URI data … much easier!

Why involve PHP? The amounts of data regarding data URIs precludes a feasible (ie. we’re not saying it’s impossible) clientside only approach. We need to create data files and the serverside is the best place we can think of to do that in …


Previous relevant YouTube API Caller Radio Play Obsession Looping Tutorial is shown below.

YouTube API Caller Radio Play Obsession Looping Tutorial

YouTube API Caller Radio Play Obsession Looping Tutorial

Yesterday’s YouTube API Caller Phase Two Console Warning Tutorial outlined why …

  • single song obsessional looping” … sits uneasily with …
  • set of song videos looping” … in Radio Play mode of use

… with our recent Tabular Single Row Image Gallery web application.

But they don’t have to be totally inalienable concepts, as we outlined …

where, now, if you are after some “single song obsessional looping” try unchecking all checkboxes except the one of your obsession … and good luck ending the itch!

That remains true, but we wanted an easier way to allow for “single song obsessional looping” in Radio Play modes of use. We wanted to hook into an unused event arrangement related to those textboxes to the right of the left hand side checkboxes. We decided on …

  • oncontextmenu … ie. right click … on non-mobile platforms … and …
  • ontouchmove … on mobile platforms

via (at the grandchild level) …


for (var iipp=0; iipp<=29; iipp++) {
if (('' + top.document.URL).indexOf('isradio=') != -1) {
if (parent.document.getElementById('i' + iipp).outerHTML.indexOf(' oncontextmmenu=') == -1) {
parent.document.getElementById('i' + iipp).oncontextmenu=function(event){ parent.obsessabout(event); };
parent.document.getElementById('i' + iipp).ontouchmove=function(event){ parent.obsessabout(event); };
if (istitles.indexOf(iipp) == -1) {
istitles.push(iipp);
}
if (iipp == 0) {
setTimeout(function(){
for (var jipp=0; jipp<istitles.length; jipp++) {
if (('' + parent.document.getElementById('i' + jipp).title) == '') {
parent.document.getElementById('i' + jipp).title+=' Right click or touch move to loop just this video';
} else {
parent.document.getElementById('i' + jipp).title+=' and right click or touch move to loop just this video';
}
}
}, 8000);
}
}
}

// rest of for loop code
}

actioned (at the child/parent level) …


function obsessabout(evt) {
evt.stopPropagation();
var theonetokeep=('' + evt.target.id).replace('i','');
var nnum=0;
document.getElementById('c' + theonetokeep).checked=true;
while (document.getElementById('i' + nnum)) {
if (('' + nnum) != ('' + theonetokeep)) {
document.getElementById('c' + nnum).checked=false;
}
nnum++;
}
}

… in …

… especially related to the grandparent level Tabular Single Row Image Gallery web application’s “Radio Play” mode of use.


Previous relevant YouTube API Caller Phase Two Console Warning Tutorial is shown below.

YouTube API Caller Phase Two Console Warning Tutorial

YouTube API Caller Phase Two Console Warning Tutorial

Continuing on from yesterday’s YouTube API Caller Phase Two Text Cursor Tutorial

What the dickens is “Console Warning”?

Well, it’s a new good friend to us using the Google Chrome web browser (but other web browsers can work it too) Web Inspector‘s division of “issue or not” reporting you can get your web applications to do via Javascript to debug or inform as the web application executes. We have found …


console.warn('Any text of your interest, not just the technical sense of a warning error in http land.');

… as a useful way to sort the chaff from the rest trying to analyse issues. Tissues for issues?! Most web application get issues from the time you give birth and well into their adolescent years to when they get deprecated and sent to “the scrapheap of the online wooooorrrrrllllddddd” … shipped off to Mars we’re predicting next … oops … too many plays of this we’re suspecting … although …

… it might have passed the notice of some?!

Anyway, the day of “shoring up” our Tabular Single Row Image Gallery web application’s “Radio Play” mode of use started with an innocent question …

Why is the web application “less flaky” just after we clear the web browser cache for an hour?

Our first suspect we just launched into without proof, but really conditionally did much less of


if (('' + parent.document.URL).replace(/\%23http$/g,'#http').replace(/\#http$/g,'') == ('' + parent.document.URL)) { // ie. "Radio Play"
if (('' + window.sessionStorage.getItem('loop_' + vid.split(',')[0])).replace(/^undefined/g,'').replace(/^null/g,'').trim() != '') {
window.sessionStorage.removeItem('loop_' + vid.split(',')[0]);
}
window.sessionStorage.setItem('loop_' + vid.split(',')[0], 'y');
}

… window.sessionStorage means by which to encourage the “single song obsessional looping” talked about below.

Our second suspect, that the thinking above leads to, was the “encouragement of single song obsessional looping” (from audio stream of video days early on in this project, even) as distinct from …


"encouragement of set of song videos looping"

… this latter mode of use asking in our “three tier hierarchical web application environment” that …

The grandchild must be set free … aka Home Alone … to work alone and unsupported.

… an idea which is anathema to other ways we’ve worked our inhouse YouTube API calling work.

In this new wooooorrrrllllddd calls to YouTube API’s …


player.stopVideo(); /// or player.pauseVideo() for that matter

… are definite nonos, as are calls from the “middle child”. But the code is full of such calls, and other uses of player.stopVideo() suit other modes of use? Right?!

You betcha!

We need to debug which codelines containing player.stopVideo() or “middle child” calls to narrow down the relevant one or two making the web application “flaky”. Well, using codelines such as …


// Middle child ...
console.warn('here at 13 ' + ('' + new Date()) + ' ' + document.getElementById('myiframe').title + ' ?vid=' + ourvid + "&playtime=" + thisd + "&start=" + document.getElementById('i' + i).value.split(';')[0] + '&ct=' + encodeURIComponent(ndt.toUTCString()) + onestodoprefix + encodeURIComponent(onestodosuffix));
// Grandchild ...
console.log('' + ('' + new Date()) + ' ViD=' + vid + ' ivid=' + ivid + ' referrer=' + document.referrer + ' uRl=' + document.URL);

… with those timestamps and “relative isolation” into the console tab’s “Warning section” helping heaps, thanks to the powers that be! It got us to where we knew when to intervene … a variable kpi became -1 (the one place possible being) …


kpi=-1;
console.log('document.URL=' + document.URL + ' ' + ('' + new Date()));
console.warn('document.URL=' + document.URL + ' ' + ('' + new Date()));
keepParentInformed();

… the debugging information of which narrowed down the contention to this fix


function updatesc() {
cnt+=one;
cntpause+=onepause;
if (toggle == 0) secscnt+=one;
var ours="00" + eval(secscnt % 60);
var ourm="00" + eval((secscnt - ours) / 60);
suffix="#t=" + ourm.substring(eval(ourm.length - 2)) + "m" + ours.substring(eval(ours.length - 2)) + "s";
if (presuffix != "") presuffix=suffix;
if (eval(eval(cnt) - eval(cntpause)) >= duration && eval(duration) > 0) { // && eval(playtime) < 0) {
if (tobechecked != null) {
if (tobechecked.value != '') {
document.getElementById('oform').submit();
}
} else if (nexturl != '') {
console.warn('9875');
if (urlis == '') location.href=nexturl;
} else {
secscnt=cnt;
if (('' + parent.document.URL + 's').replace(/\#https/g,'') == ('' + parent.document.URL + 's')) { // but not for "Radio Play"
stopVideo();
}
}
}
if (window.parent) {
if (parent.document.getElementById('i0')) {
if (('' + parent.document.URL + 's').replace(/\#https/g,'') != ('' + parent.document.URL + 's')) {
//top.document.title='x';
if (('' + parent.document.getElementById('i0').title + ' ').indexOf('#') == 0 || ('' + top.window.sessionStorage.getItem('ssytemp')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
//top.document.title='z';
//alert(5643);
monitorplh();
}
}
}
if (parent.document.getElementById('an_i_thingo')) {
if (parent.document.getElementById('an_i_thingo').value != '') {
parent.document.getElementById('an_i_thingo').value='';
//top.document.title='w';
//alert(5643);
monitorplh();
}
}
}
}

… which further contributed to less …

❄️ – ( ☃️ – 🧍‍♂️ )

… via …

… especially related to the grandparent level Tabular Single Row Image Gallery web application’s “Radio Play” mode of use, where, now, if you are after some “single song obsessional looping” try unchecking all checkboxes except the one of your obsession … and good luck ending the itch!

Did you know?

But the codeline conditionally ignored goes stopVideo(); not player.stopVideo(); … so what’s the go? Well, with an OOPy class scenario with an instance of that class called player the two are equivalent. You may also see event.target.stopVideo(); which can also work within an event’s logic within the code of that class. Sorry, but we crash around the brilliance of YouTube API class purity with lots of our own ideas that cloud issues. How about the two days we spent thinking we could map player to an altplayer variable and overmap player to our non-YouTube media window object …

Non good times

… it got ditched … otherwise our thinking would have extended to Javascript functions such as stopVideo being added to the non-class Javascript to address the execution swap over! Bit crazy, thinking back, but luckily we no longer do any mapping of instances, you’ll be pleased to hear!


Previous relevant YouTube API Caller Phase Two Text Cursor Tutorial is shown below.

YouTube API Caller Phase Two Text Cursor Tutorial

YouTube API Caller Phase Two Text Cursor Tutorial

As a bit of a sidestep away from the forward progress of yesterday’s YouTube API Caller Phase Two Other Mimetypes Sharing Tutorial

  • yes, we will get onto user data URI entries soon … but …
  • let’s, today, for mobile platforms …
    1. lament they cannot have the joy of the cursors non-mobile can show you on the non-mobile screen … and our favourite is cursor:progress as an easy way to say to the user “hang on … for a bit” … so we looked for …
    2. any way with “just text” (that we animate down the bottom of the leftmost table cell) … we can indicate “things are going on”

… and yes, we’ve applied this idea everywhere because it may help indicate to a user if they lose a connection, perhaps, too, as a secondary role this …

text cursor

… could play. It consists of

Javascript creating HTML as per …


<script type=text/javascript>
if (window.opener) {
if (document.URL.indexOf('isradio=') != -1 && document.URL.indexOf('youtube=') != -1) {
radioblurb=' ... click on start song (when emojis appear) then we suggest minimising window small but on top (next to other work windows) for radio sequenced play';
var doctt='' + document.title;
document.title=String.fromCodePoint(128251) + ' ' + (location.search.split('regarding=')[1] ? decodeURIComponent(location.search.split('regarding=')[1].split('&')[0]) : '') + ' Radio Play ... ' + doctt;
} else {
radioblurb=' ... please wait for more than one checkbox checked before radio sequenced play is started above';
}
} else if (document.URL.indexOf('isradio=') != -1) {
radioblurb=' ... please wait for more than one checkbox checked before radio sequenced play is started above';
if (document.URL.indexOf('youtube=') != -1) {
var xdoctt='' + document.title;
document.title=String.fromCodePoint(128251) + ' ' + (location.search.split('regarding=')[1] ? decodeURIComponent(location.search.split('regarding=')[1].split('&')[0]) : '') + ' Radio Play ... ' + xdoctt;
}
}
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
radioblurb+=' and we recommend screen lock on';
}
for (var kk=1; kk<=eval(100 * numc); kk++) {
if (eval(kk % eval('' + bcol.length)) == 0) {
dw+=('<td class=loremipsum data-alt="" data-curs="' + cursanim[cntcurs] + '" alt="Cell ' + kk + radioblurb + cursanim[cntcurs] + '" title="If not showing an image ( this one thanks to Lorem Picsum at https://picsum.photos/ ) or to reveal it behind audio or video foreground content please double click here at cell ' + kk + '." ondblclick=refresh(this.id); id="td' + ('0000' + kk).slice(-4) + '" style="min-width:' + amin + 'px;min-height:' + amin + 'px;width:' + amin + 'px;height:' + amin + "px;background-color:" + bcol[eval(kk % eval('' + bcol.length))] + ";" + 'background-size:contain;background-repeat:no-repeat;">' + grabcontent(eval(-1 + kk)) + '</td>');
setTimeout(cursanimate, 600);
} else {
dw+=('<td onmousedown="checkmeout(event,false);" ontouchdown="checkmeout(event,false);" oncontextmenu="checkmeout(event,true);" class=inhouse data-alt="" alt="Cell ' + kk + radioblurb + cursanim[cntcurs] + '" title="If not showing an image ( yellow cell ones thanks to Lorem Picsum at https://picsum.photos/ ) please double click here at cell ' + kk + ' or just click to get popup window of associated WordPress Blog Posting else right click for associated Cut to the Chase." ondblclick=refresh(this.id); id="td' + ('0000' + kk).slice(-4) + '" style="min-width:' + amin + 'px;min-height:' + amin + 'px;width:' + amin + 'px;height:' + amin + "px;background-color:" + bcol[eval(kk % eval('' + bcol.length))] + ";" + 'background-size:contain;background-repeat:no-repeat;">' + grabcontent(eval(-1 + kk)) + '</td>');
}
}
document.write(dw);
</script>

… and the accompanying CSS text content creation means


<style>
td {
border: 1px dotted green;
}

a {
text-shadow:-1px 1px 1px #ff2d95;
background-color:rgba(255,255,255,0.3);
}

.inhouse {
vertical-align: bottom;
padding-bottom: 20px;
}

.inhouse::after {
font-size: 8px;
content: 'Media Gallery \a RJM Programming \a August, 2025 \a Thanks to Lorem Picsum at https://picsum.photos/ \a Thanks to YouTube at https://youtube.com \a ' attr(data-alt) attr(alt);
white-space: pre-wrap;
}

</style>

… made to be more noticeable and animated via Javascript …


var cntcurs=0, lastcurs=0, altlen=-1;
var cursanim=[' ',' | ', ' / ', ' - ', ' \ '];

function cursanimate() {
if (altlen == -1) {
if (document.getElementById('td0001').getAttribute('alt').indexOf(' (when emojis appear) ') != -1) {
document.getElementById('td0001').setAttribute('alt', document.getElementById('td0001').getAttribute('alt').replace(' (when emojis appear) ', ' '));
}
altlen=eval(0 + eval('' + document.getElementById('td0001').getAttribute('alt').length));
}
lastcurs=cntcurs;
cntcurs++;
if (cntcurs >= eval('' + cursanim.length)) { cntcurs=1; }
document.getElementById('td0001').setAttribute('alt', document.getElementById('td0001').getAttribute('alt').substring(0,altlen) + cursanim[cntcurs]);
setTimeout(cursanimate, 600);
}

… either straight away, or when the user should expect a delay, using the changed swipe_media.html Tabular Single Row Image Gallery web application.


Previous relevant YouTube API Caller Phase Two Other Mimetypes Sharing Tutorial is shown below.

YouTube API Caller Phase Two Other Mimetypes Sharing Tutorial

YouTube API Caller Phase Two Other Mimetypes Sharing Tutorial

We were hoping we could say “yesterday’s” but, three days later, the struggle is over regarding work after YouTube API Caller Phase Two Other Mimetypes Tutorial regarding sharing with someone when including …

  • (albeit, so far, restricted) audio media mimetypes presented in an HTML audio element … and …
  • (albeit, so far, restricted) video media mimetypes presented in an HTML video element … while today we’re adding support for …
  • (albeit, so far, restricted) image media mimetypes presented in an HTML img element … and …
  • (albeit, so far, restricted) other mimetypes presented in an HTML iframe element

… is achievable, but not for data URIs yet, just media URLs. That is an upcoming struggle, we’re predicting?!

Who‘d have thought Do You See What I See could be so involved …

…?


Previous relevant YouTube API Caller Phase Two Other Mimetypes Tutorial is shown below.

YouTube API Caller Phase Two Other Mimetypes Tutorial

YouTube API Caller Phase Two Other Mimetypes Tutorial

Up until yesterday’s YouTube API Caller Phase Two Intermediate Buttons Tutorial phase two user media work established …

  • (albeit, so far, restricted) audio media mimetypes presented in an HTML audio element … and …
  • (albeit, so far, restricted) video media mimetypes presented in an HTML video element … while today we’re adding support for …
  • (albeit, so far, restricted) image media mimetypes presented in an HTML img element … and …
  • (albeit, so far, restricted) other mimetypes presented in an HTML iframe element

Not yet, but eventually, what we’re doing with the 3 hierarchies and hashtagging will be crucial for a sharing recipient to “see what you see”, and we needed tweaking of this to ensure the hashtagging order used corresponded to the order of user media (so far just URL) creations in those textboxes.

We were also correct worrying about if two such user media URLs appeared in a row, but fixed this within …


Previous relevant YouTube API Caller Phase Two Intermediate Buttons Tutorial is shown below.

YouTube API Caller Phase Two Intermediate Buttons Tutorial

YouTube API Caller Phase Two Intermediate Buttons Tutorial

Further to yesterday’s YouTube API Caller Phase Two Absolute URL Tutorial‘s three tier Tabular Single Row Image Gallery web application design …

Had we been letting middle child syndrome develop?

We’d not attended to a lot of the buttons to the right of the changed karaoke_youtube_api.htm inhouse YouTube video interfacer‘s webpages, in any serious way during this latest push. But the fact is, it is worth the effort, even in terms of them …

  • helping better email share
  • shore up recovery means should connections be lost during Radio Play
  • help switch between video play and audio stream of video only play and vice versa modes of Radio Play

The thing is, in the three tier design, we’ve introduced a new top tier as far as this middle tier player is concerned. But we can tailor it to use those buttons differently, and we found the onmousedown and ontouchdown events related to those buttons often useful here, depending on conditions


var mbmode=false, mbinter='';

var cbut="<br><div style='" + defidea + "'><div id='ddkaraoke' style='display:inline; visibility: hidden; '><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input> <input style=width:60%; onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '><input id='mousej' type='button' style='background-color:#f0f0f0; display:inline; visibility: hidden;' onclick=' mousebelowj(this);' value='Fill Table Below via Mouse Video Pauses Starting with '></input> <input id='mousei' type='button' style='background-color:#f5f5f5; display:inline; visibility: hidden;' onclick=' mousebelowi(this);' value='Fill Table Starting with 0 cell'></input> <input id='karaoke' onclick=\" mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '></div></div>";
var cbutl="<div style='" + defidea + " height: 60px;'><div style=' " + defidea + " height: 60px;'><div id='dkaraoke' style=' display:inline; visibility: hidden; '><div style='" + defidea + "'><div style='" + defidea + "'><input id='karaoke' onclick=\" mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div></div></div><br><div id='ddkaraoke' style='margin-top:-100px; visibility: hidden; " + defidea + " '><div style='" + defidea + "'><div style='" + defidea + "'><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input><input onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div></div></div></div></div><br><br>✔ (<a onclick=\" prearwo=window.open(this.getAttribute('data-href'),'_blank','top=' + eval(-400 + screen.height) + ',left=' + eval(-1050 + screen.width) + ',width=500,height=400'); setInterval(arwoaudioablook, 5000); }, 1500);\" data-target=_blank id=arecord title='Thanks to https://online-voice-recorder.com/#google_vignette ... if it works for your browser. If not, you can consider using a desktop microphone recorder app such as Mac OS X QuickTime Player as an alternative perhaps.' data-href='https://online-voice-recorder.com/#google_vignette'>Record</a> own parts? <input type=hidden id=justaudio" + bsuffis + " value=''></input><input style=visibility:hidden; onchanged='dorecord=!dorecord;' type=checkbox name=recown id=recown value='Record own parts?'></input>) ";
if (window.parent) {
if (('' + parent.document.URL + '&').indexOf('#http&') != -1 || ('' + parent.document.URL + '&').indexOf('isradio=') != -1) {
mbinter=" window.open(('' + parent.get_docurl()),'_top'); ";
if (('' + parent.document.URL + '&').indexOf('justaudio=y') != -1) {
cbut="<br><div style='" + defidea + "'><div id='ddkaraoke' style='display:inline; visibility: hidden; '><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input> <input style=width:60%; onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '><input id='mousej' type='button' style='background-color:#f0f0f0; display:inline; visibility: hidden;' onclick=' mousebelowj(this);' value='Fill Table Below via Mouse Video Pauses Starting with '></input> <input id='mousei' type='button' style='background-color:#f5f5f5; display:inline; visibility: hidden;' onclick=' mousebelowi(this);' value='Fill Table Starting with 0 cell'></input> <input id='karaoke' onclick=\" " + mbinter.replace(",",".replace('justaudio','audjustio'),") + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '></div></div>";
cbutl="<div style='" + defidea + " height: 60px;'><div style=' " + defidea + " height: 60px;'><div id='dkaraoke' style=' display:inline; visibility: hidden; '><div style='" + defidea + "'><div style='" + defidea + "'><input id='karaoke' onclick=\" " + mbinter.replace(",",".replace('justaudio','audjustio'),") + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div></div></div><br><div id='ddkaraoke' style='margin-top:-100px; visibility: hidden; " + defidea + " '><div style='" + defidea + "'><div style='" + defidea + "'><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input><input onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div></div></div></div></div><br><br>✔ (<a onclick=\" prearwo=window.open(this.getAttribute('data-href'),'_blank','top=' + eval(-400 + screen.height) + ',left=' + eval(-1050 + screen.width) + ',width=500,height=400'); setInterval(arwoaudioablook, 5000); }, 1500);\" data-target=_blank id=arecord title='Thanks to https://online-voice-recorder.com/#google_vignette ... if it works for your browser. If not, you can consider using a desktop microphone recorder app such as Mac OS X QuickTime Player as an alternative perhaps.' data-href='https://online-voice-recorder.com/#google_vignette'>Record</a> own parts? <input type=hidden id=justaudio" + bsuffis + " value=''></input><input style=visibility:hidden; onchanged='dorecord=!dorecord;' type=checkbox name=recown id=recown value='Record own parts?'></input>) ";
topbuturl=('' + parent.get_docurl()).replace('justaudio','audjustio');
mbinter=""; //mbinter=mbinter.replace(",",".replace('justaudio','audjustio'),");
setTimeout(function(){
if (document.getElementById('audioejkaraoke') || document.getElementById('repeat')) {
if (document.getElementById('audioejkaraoke')) {
document.getElementById('audioejkaraoke').type='button';
document.getElementById('audioejkaraoke').onmousedown=function(){ window.open(topbuturl,'_top'); };
document.getElementById('audioejkaraoke').ontouchdown=function(){ window.open(topbuturl,'_top'); };
}
if (document.getElementById('repeat')) {
document.getElementById('repeat').onmousedown=function(){ if (document.URL.indexOf('i0=') != -1) { window.open(topbuturl,'_top'); } };
document.getElementById('repeat').ontouchdown=function(){ if (document.URL.indexOf('i0=') != -1) { window.open(topbuturl,'_top'); } };
}
}
}, 12000);
} else {
cbut="<br><div style='" + defidea + "'><div id='ddkaraoke' style='display:inline; visibility: hidden; '><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input> <input style=width:60%; onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '><input id='mousej' type='button' style='background-color:#f0f0f0; display:inline; visibility: hidden;' onclick=' mousebelowj(this);' value='Fill Table Below via Mouse Video Pauses Starting with '></input> <input id='mousei' type='button' style='background-color:#f5f5f5; display:inline; visibility: hidden;' onclick=' mousebelowi(this);' value='Fill Table Starting with 0 cell'></input> <input id='karaoke' onclick=\" " + mbinter + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '></div></div>";
cbutl="<div style='" + defidea + " height: 60px;'><div style=' " + defidea + " height: 60px;'><div id='dkaraoke' style=' display:inline; visibility: hidden; '><div style='" + defidea + "'><div style='" + defidea + "'><input id='karaoke' onclick=\" " + mbinter + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div></div></div><br><div id='ddkaraoke' style='margin-top:-100px; visibility: hidden; " + defidea + " '><div style='" + defidea + "'><div style='" + defidea + "'><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input><input onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div></div></div></div></div><br><br>✔ (<a onclick=\" prearwo=window.open(this.getAttribute('data-href'),'_blank','top=' + eval(-400 + screen.height) + ',left=' + eval(-1050 + screen.width) + ',width=500,height=400'); setInterval(arwoaudioablook, 5000); }, 1500);\" data-target=_blank id=arecord title='Thanks to https://online-voice-recorder.com/#google_vignette ... if it works for your browser. If not, you can consider using a desktop microphone recorder app such as Mac OS X QuickTime Player as an alternative perhaps.' data-href='https://online-voice-recorder.com/#google_vignette'>Record</a> own parts? <input type=hidden id=justaudio" + bsuffis + " value=''></input><input style=visibility:hidden; onchanged='dorecord=!dorecord;' type=checkbox name=recown id=recown value='Record own parts?'></input>) ";
}
} else if (('' + top.document.URL + '&').indexOf('#http&') != -1 || ('' + top.document.URL + '&').indexOf('isradio=') != -1) {
mbinter=" window.open(('' + parent.get_docurl()),'_top'); ";
if (('' + parent.document.URL + '&').indexOf('justaudio=y') != -1) {
cbut="<br><div style='" + defidea + "'><div id='ddkaraoke' style='display:inline; visibility: hidden; '><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input> <input style=width:60%; onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '><input id='mousej' type='button' style='background-color:#f0f0f0; display:inline; visibility: hidden;' onclick=' mousebelowj(this);' value='Fill Table Below via Mouse Video Pauses Starting with '></input> <input id='mousei' type='button' style='background-color:#f5f5f5; display:inline; visibility: hidden;' onclick=' mousebelowi(this);' value='Fill Table Starting with 0 cell'></input> <input id='karaoke' onclick=\" " + mbinter.replace(",",".replace('justaudio','audjustio'),") + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '></div></div>";
cbutl="<div style='" + defidea + " height: 60px;'><div style=' " + defidea + " height: 60px;'><div id='dkaraoke' style=' display:inline; visibility: hidden; '><div style='" + defidea + "'><div style='" + defidea + "'><input id='karaoke' onclick=\" " + mbinter.replace(",",".replace('justaudio','audjustio'),") + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div></div></div><br><div id='ddkaraoke' style='margin-top:-100px; visibility: hidden; " + defidea + " '><div style='" + defidea + "'><div style='" + defidea + "'><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input><input onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div></div></div></div></div><br><br>✔ (<a onclick=\" prearwo=window.open(this.getAttribute('data-href'),'_blank','top=' + eval(-400 + screen.height) + ',left=' + eval(-1050 + screen.width) + ',width=500,height=400'); setInterval(arwoaudioablook, 5000); }, 1500);\" data-target=_blank id=arecord title='Thanks to https://online-voice-recorder.com/#google_vignette ... if it works for your browser. If not, you can consider using a desktop microphone recorder app such as Mac OS X QuickTime Player as an alternative perhaps.' data-href='https://online-voice-recorder.com/#google_vignette'>Record</a> own parts? <input type=hidden id=justaudio" + bsuffis + " value=''></input><input style=visibility:hidden; onchanged='dorecord=!dorecord;' type=checkbox name=recown id=recown value='Record own parts?'></input>) ";
topbuturl=('' + parent.get_docurl()).replace('justaudio','audjustio');
mbinter=""; //mbinter=mbinter.replace(",",".replace('justaudio','audjustio'),");
setTimeout(function(){
if (document.getElementById('audioejkaraoke') || document.getElementById('repeat')) {
if (document.getElementById('audioejkaraoke')) {
document.getElementById('audioejkaraoke').type='button';
document.getElementById('audioejkaraoke').onmousedown=function(){ window.open(topbuturl,'_top'); };
document.getElementById('audioejkaraoke').ontouchdown=function(){ window.open(topbuturl,'_top'); };
}
if (document.getElementById('repeat')) {
document.getElementById('repeat').onmousedown=function(){ if (document.URL.indexOf('i0=') != -1) { window.open(topbuturl,'_top'); } };
document.getElementById('repeat').ontouchdown=function(){ if (document.URL.indexOf('i0=') != -1) { window.open(topbuturl,'_top'); } };
}
}
}, 12000);
} else {
cbut="<br><div style='" + defidea + "'><div id='ddkaraoke' style='display:inline; visibility: hidden; '><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input> <input style=width:60%; onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '><input id='mousej' type='button' style='background-color:#f0f0f0; display:inline; visibility: hidden;' onclick=' mousebelowj(this);' value='Fill Table Below via Mouse Video Pauses Starting with '></input> <input id='mousei' type='button' style='background-color:#f5f5f5; display:inline; visibility: hidden;' onclick=' mousebelowi(this);' value='Fill Table Starting with 0 cell'></input> <input id='karaoke' onclick=\" " + mbinter + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div><div id='dkaraoke' style='display:inline; visibility: hidden; '></div></div>";
cbutl="<div style='" + defidea + " height: 60px;'><div style=' " + defidea + " height: 60px;'><div id='dkaraoke' style=' display:inline; visibility: hidden; '><div style='" + defidea + "'><div style='" + defidea + "'><input id='karaoke' onclick=\" " + mbinter + " mbmode=false; document.getElementById('ddkaraoke').style.visibility='visible'; if (document.URL.indexOf('i0=') != -1) { next=0; } queuenext();\" type='submit' style='background-color:orange;' value='Play Karaoke Style YouTube Via Entries Below'></input></div></div></div><br><div id='ddkaraoke' style='margin-top:-100px; visibility: hidden; " + defidea + " '><div style='" + defidea + "'><div style='" + defidea + "'><input onclick=\"if (document.URL.indexOf('i0=') != -1) { location.href=itd(document.URL); } \" id='repeat' type='button' style='background-color:red;' value='Replay Karaoke Style YouTube Above'></input><br><input onclick=clickto(); id=karaokeshare value='Email Share to ' type='button'></input><input onblur=doto(this.value); type=text name=email id=karaokeemail value=></input></div></div></div></div></div><br><br>✔ (<a onclick=\" prearwo=window.open(this.getAttribute('data-href'),'_blank','top=' + eval(-400 + screen.height) + ',left=' + eval(-1050 + screen.width) + ',width=500,height=400'); setInterval(arwoaudioablook, 5000); }, 1500);\" data-target=_blank id=arecord title='Thanks to https://online-voice-recorder.com/#google_vignette ... if it works for your browser. If not, you can consider using a desktop microphone recorder app such as Mac OS X QuickTime Player as an alternative perhaps.' data-href='https://online-voice-recorder.com/#google_vignette'>Record</a> own parts? <input type=hidden id=justaudio" + bsuffis + " value=''></input><input style=visibility:hidden; onchanged='dorecord=!dorecord;' type=checkbox name=recown id=recown value='Record own parts?'></input>) ";
}
}
}

var cbutm="<div style='" + defidea + " height: 60px;'><div id='dkaraokem' style='display:inline; visibility: hidden; '><input id='mousei' type='button' style='background-color:#f5f5f5; display:inline; visibility: hidden;' onclick=' mousebelowi(this);' value='Fill Table Below via Mouse Video Pauses'></input></div></div><br>Start time in seconds <span id=nm style='display:none;'>(negative means you will be singing or Prefix by Audio file URL or YouTube ID delimited by :)</span>";
var cbutr="<div style='" + defidea + " height: 60px;'><div id='dkaraoker' style='display:inline; visibility: hidden; '>        <input id='mousej' type='button' style=' background-color:#f0f0f0; display:inline; visibility: hidden;' onclick=' mousebelowj(this);' value='Fill Table Starting with '></input></div></div><br><span style=text-align:right;width:100%;>Finish</span>";

var audiobut='';
if ((mbinter != '' && ('' + parent.document.URL).indexOf('justaudio=y') != -1) || ((documentURL + '&' + asuffis).indexOf('justaudio=&') != -1 && (documentURL.indexOf('youtube_duration=&') == -1 && documentURL.indexOf('youtube_duration=') != -1) && documentURL.indexOf('youtubeid=') != -1 && documentURL.indexOf('emoji=') != -1)) {
audiobut=('<input class="emoji" id="audioejkaraoke" onclick=" ' + mbinter + ' document.getElementById(`myiframe`).style.marginTop=`0px`; document.getElementById(`myiframe`).style.opacity=`1`; document.getElementById(`myiframe`).style.filter="invert(0)"; this.style.display=`none`; " type="submit" style="background-color: orange; visibility: visible;" value="' + String.fromCodePoint(128249) + ' Play Video as below" title="Play Karaoke Style YouTube Video Via Entries Below">').replace(/\`/g,"'");
} else if (('' + parent.document.URL).indexOf('justaudio=y') != -1) {
audiobut=('<input class="emoji" id="audioejkaraoke" onclick=" document.getElementById(`justaudio`).name=`justaudio`; ' + mbinter.replace(",",".replace('?','?justaudio=y&'),") + ' mbmode=false; document.getElementById(`ddejkaraoke`).style.visibility=`visible`; if (document.URL.indexOf(`i0=`) != -1) { next=0; } isendof=ieo; queuenext(); " type="submit" style="background-color: orange; visibility: visible;" value="' + String.fromCodePoint(128483) + ' Play Video as below" title="Play Karaoke Style YouTube Video Via Entries Below">').replace(/\`/g,"'");

} else {
audiobut=('<input class="emoji" id="audioejkaraoke" onclick=" document.getElementById(`justaudio`).name=`justaudio`; ' + mbinter.replace(",",".replace('?','?justaudio=y&'),") + ' mbmode=false; document.getElementById(`ddejkaraoke`).style.visibility=`visible`; if (document.URL.indexOf(`i0=`) != -1) { next=0; } isendof=ieo; queuenext(); " type="submit" style="background-color: orange; visibility: visible;" value="' + String.fromCodePoint(128483) + ' Play Audio as below" title="Play Karaoke Style YouTube Audio Via Entries Below">').replace(/\`/g,"'");
}

… helping out in the changed swipe_media.html Tabular Single Row Image Gallery web application “Radio Play” mode of use.


Previous relevant YouTube API Caller Phase Two Absolute URL Tutorial is shown below.

YouTube API Caller Phase Two Absolute URL Tutorial

YouTube API Caller Phase Two Absolute URL Tutorial

Onto yesterday’s YouTube API Caller Other Media Playlist Regarding Tutorial it’s taken a long time, even for the conditional blurb below to crystallize, but …

  • regarding testing we only did, so far, on non-mobile regarding Radio Play interspersing of YouTube media video plays with non-YouTube ones, so far …
  • regarding users entering their own URLs into the textboxes next to the left hand checkboxes during Radio Play usage …
  • regarding user entered absolute or relative URLs (but not data URIs yet)
  • pointing to audio or video media mimetype data (so far)

… we finally think we have a presentable web application scenario, worth putting into the mix.

This concerns the Tabular Single Row Image Gallery web application in “Radio Play” mode of use helped out by the changed karaoke_youtube_api.htm inhouse YouTube video interfacer in turn helped out by the modified stop_start_youtube.html YouTube API caller.

Pretty obviously, more to do, and more to shore up, but encouraging signs it’s all possible, this interspersing of YouTube media video plays with non-YouTube ones!


Previous relevant YouTube API Caller Other Media Playlist Regarding Tutorial is shown below.

YouTube API Caller Other Media Playlist Compilation Tutorial

YouTube API Caller Other Media Playlist Regarding Tutorial

Further to yesterday’s YouTube API Caller Other Media Playlist Compilation Tutorial it’s not going to cut the mustard with as many users …

… if you forget to put front and center what it is the user has given you as a piece of their information …

… rather than what some of us (cough, cough) can tend to do as software developers, and bury this in the data out of sight.

What could be better than yesterday’s allowing via emoji 🔀 button for Playlist creation via 11 character YouTube video ID list, albeit “some people’s cup of tea”, than to place the whole …

Playlist Thaing

… back into a user driven chance to control matters? In other words


function createplaylist(insvalo) {
var tdsare=[], itds=0, itdone=false;;
var oklast=['A','E','I','M','Q','U','Y','c','g','k','o','s','w','0','4','8'];

var argshuf='';
var plist=prompt('Enter YouTube 11 character code video (comma separated) or audio stream only of video (semicolon separated) list to Radio Play (and add ! to start in shuffle mode) ... or a YouTube Search String basis to create a playlist via a Radio' + String.fromCodePoint(128251) + '? button to activate, later.', '');
if (plist != null) {
if (plist.trim() != '') {
if (plist.trim().indexOf(' ') != -1 || eval('' + plist.trim().split(',')[0].split(';')[0].length) != 11 || oklast.indexOf(plist.trim().split(',')[0].split(';')[0].slice(-1)) == -1) {
tdsare=document.getElementsByTagName('td');
for (itds=0; itds<tdsare.length; itds++) {
if (!itdone && tdsare[itds].innerHTML == '' && ('' + tdsare[itds].id) != 'td0001') {
itdone=true;
tdsare[itds].innerHTML='<iframe style="width:100%;height:100%;" id=karsearch name=karsearch src="/HTMLCSS/karaoke_youtube_api.htm?youtubeid=++++++++++++' + encodeURIComponent(plist.trim()) + '&minimize=y&youtube_duration=&email=&emoji=on&clickcheck=y"></iframe>';
tdsare[itds].scrollIntoView();
}
}
} else {

if (plist.replace(/\!$/g,'') != plist) { argshuf='&shuffle=y'; }
if (plist.indexOf(';') != -1 && plist.indexOf(',') == -1) {
window.open('./swipe_media.html?isradio=y' + argshuf + '&audioyoutube=' + encodeURIComponent(extraatendmaybe(plist.replace(/\;/g,',').replace(/\!$/g,''),'isradio=y' + argshuf)),'_blank');
} else {
window.open('./swipe_media.html?isradio=y' + argshuf + '&youtube=' + encodeURIComponent(extraatendmaybe(plist.replace(/\;/g,',').replace(/\!$/g,''),'isradio=y' + argshuf)),'_blank');
}
}
}
}
}

… and should the user go on to remember that playlist, what they entered as a YouTube Search String basis gets remembered in Radio Play webpage titling (and hence, in web browser window name lists). And the user can see how the playlist was created, especially if they named their recallable playlist well, in a more transparent way in the changed swipe_media.html Tabular Single Row Image Gallery web application “Radio Play” mode of use, now allowing via emoji 🔀 button for Playlist creation via 11 character YouTube video ID lists, all helped out by the changed karaoke_youtube_api.htm inhouse YouTube video interfacer.

Some Vikki Carr magic, anyone?!


Previous relevant YouTube API Caller Other Media Playlist Compilation Tutorial is shown below.

YouTube API Caller Other Media Playlist Compilation Tutorial

YouTube API Caller Other Media Playlist Compilation Tutorial

Onto yesterday’s YouTube API Caller Other Media Playlist Recall Tutorial

  • work has progressed on Phase Two integrations, sideways then forwards, and “getting there” … but for the meantime there are other features we want here …
  • like a way to compile songs from our three featured music ideas into an immediately shuffled longer playlist …

… via double clicks on Radio Play 📻 emojis, as per …


var independent=true, didothers=false;

function triplewhammy() {
independent=false;
location.hash='#independent=false';
argshuffle='&shuffle=y';
prefix='isradio=y' + argshuffle + '&';
dodisco('ISRADIO=BDISCOAVB&');
setTimeout(function(){
prefix='isradio=y' + argshuffle + '&';
dowc('ISRADIO=BWCAVB&');
}, 3000);
setTimeout(function(){
prefix='isradio=y' + argshuffle + '&';
doyr('ISRADIO=BYRAVB&');
}, 7000);
setTimeout(function(){ independent=true; }, 37000);
}

function split_embed(iois) {
var iso=-1;
if (('' + location.hash).indexOf('independent') != -1) { independent=false; iso=0; }
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
var tyembeds=aconto.body.innerHTML.split('/embed/');
if (eval('' + tyembeds.length) <= 1) { setTimeout(function(){ checkiflater(document.getElementById(iois.id)); }, 6000); } else {
for (var it=1; it<tyembeds.length; it++) {
if (iso < 0 || iso < 9) {
if (iso >= 0) { iso++ }
if (ytlist.trim() == '') {
ytlist+='' + tyembeds[it].substring(0,11);
} else {
ytlist+=',' + tyembeds[it].substring(0,11);
}
}
}
if (ytlist != '') {
if (prefix.indexOf('isradio=') != -1 && !navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (ytwo) {
if (!ytwo.closed) {
ytwo.close();
ytwo=null;
}
ytwo=null;
}
if (!independent) {
prefix='isradio=y' + argshuffle + '&';
}
if (!didothers) {
ytwo=window.open(document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim()),'_blank','top=0,left=0,width=' + screen.width + ',height=' + screen.height);
} else {
setTimeout(function(){
ytwo=window.open(document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim()),'_blank','top=0,left=0,width=' + screen.width + ',height=' + screen.height);
}, 4000);
}
} else {
if (!independent) {
prefix='isradio=y' + argshuffle + '&';
}
if (!didothers) {
location.href=document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim());
} else {
setTimeout(function(){
location.href=document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim());
}, 4000);
}
//}
}
}
}
}
}
}

function split_embed_two(iois) {
//didothers=true;
var iso=-1;
if (('' + location.hash).indexOf('independent') != -1) { independent=false; iso=0; }
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
var tyembeds=aconto.body.innerHTML.split('/embed/');
if (eval('' + tyembeds.length) <= 1) { setTimeout(function(){ checkiflater(document.getElementById(iois.id)); }, 6000); } else {
for (var it=1; it<tyembeds.length; it++) {
if (iso < 0 || iso < 9) {
if (iso >= 0) { iso++ }
if (ytlist.trim() == '') {
ytlist+='' + tyembeds[it].substring(0,11);
} else {
ytlist+=',' + tyembeds[it].substring(0,11);
}
}
}
if (ytlist != '') {
if (prefix.indexOf('isradio=') != -1 && !navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (ytwo) {
if (!ytwo.closed) {
ytwo.close();
ytwo=null;
}
ytwo=null;
}
if (1 == 5) {
ytwo=window.open(document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim()),'_blank','top=0,left=0,width=' + screen.width + ',height=' + screen.height);
}
} else {
if (1 == 5) {
location.href=document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim());
}
}
}
}
}
}
}

function split_embed_three(iois) {
//didothers=true;
var iso=-1;
if (('' + location.hash).indexOf('independent') != -1) { independent=false; iso=0; }
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
var tyembeds=aconto.body.innerHTML.split('/embed/');
if (eval('' + tyembeds.length) <= 1) { setTimeout(function(){ checkiflater(document.getElementById(iois.id)); }, 6000); } else {
for (var it=1; it<tyembeds.length; it++) {
if (iso < 0 || iso < 9) {
if (iso >= 0) { iso++ }
if (ytlist.trim() == '') {
ytlist+='' + tyembeds[it].substring(0,11);
} else {
ytlist+=',' + tyembeds[it].substring(0,11);
}
}
}
if (ytlist != '') {
if (prefix.indexOf('isradio=') != -1 && !navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (ytwo) {
if (!ytwo.closed) {
ytwo.close();
ytwo=null;
}
ytwo=null;
}
if (1 == 5) {
ytwo=window.open(document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim()),'_blank','top=0,left=0,width=' + screen.width + ',height=' + screen.height);
}
} else {
if (1 == 5) {
location.href=document.URL.split('?')[0].split('#')[0] + '?' + prefix + 'youtube=' + encodeURIComponent(extraatendmaybe(ytlist,prefix).trim());
}
}
}
}
}
}
}


function dodisco(dwhat) {
if (independent) {
if (prefix.indexOf('shuffle=') == -1) { prefix=dwhat; }
document.getElementById('spareif').src='/HTMLCSS/disco_version.html?rand=' + Math.floor(Math.random() * 1987865);
} else if (dwhat == dwhat.toUpperCase()) {
if (ytlist == '') { ytlist=' '; }
document.getElementById('spareifthree').src='/HTMLCSS/disco_version.html?rand=' + Math.floor(Math.random() * 1987865);
//document.getElementById('spareiftwo').src='/HTMLCSS/the_wrecking_crew.html?rand=' + Math.floor(Math.random() * 1987865);
//document.getElementById('spareif').src='/HTMLCSS/yacht_rock.html?rand=' + Math.floor(Math.random() * 1987865);
}
}

function dowc(dwhat) {
if (independent) {
if (prefix.indexOf('shuffle=') == -1) { prefix=dwhat; }
document.getElementById('spareif').src='/HTMLCSS/the_wrecking_crew.html?rand=' + Math.floor(Math.random() * 1987865);
} else if (dwhat == dwhat.toUpperCase()) {
if (ytlist == '') { ytlist=' '; }
//document.getElementById('spareifthree').src='/HTMLCSS/disco_version.html?rand=' + Math.floor(Math.random() * 1987865);
document.getElementById('spareiftwo').src='/HTMLCSS/the_wrecking_crew.html?rand=' + Math.floor(Math.random() * 1987865);
//document.getElementById('spareif').src='/HTMLCSS/yacht_rock.html?rand=' + Math.floor(Math.random() * 1987865);
}
}

function doyr(dwhat) {
if (independent) {
if (prefix.indexOf('shuffle=') == -1) { prefix=dwhat; }
document.getElementById('spareif').src='/HTMLCSS/yacht_rock.html?rand=' + Math.floor(Math.random() * 1987865);
} else if (dwhat == dwhat.toUpperCase()) {
if (ytlist == '') { ytlist=' '; }
//document.getElementById('spareifthree').src='/HTMLCSS/disco_version.html?rand=' + Math.floor(Math.random() * 1987865);
//document.getElementById('spareiftwo').src='/HTMLCSS/the_wrecking_crew.html?rand=' + Math.floor(Math.random() * 1987865);
document.getElementById('spareif').src='/HTMLCSS/yacht_rock.html?rand=' + Math.floor(Math.random() * 1987865);
}
}

… in the changed swipe_media.html Tabular Single Row Image Gallery web application “Radio Play” mode of use, now allowing via emoji 🔀 button for Playlist creation via 11 character YouTube video ID lists, all helped out by the changed karaoke_youtube_api.htm inhouse YouTube video interfacer.


Previous relevant YouTube API Caller Other Media Playlist Recall Tutorial is shown below.

YouTube API Caller Other Media Playlist Recall Tutorial

YouTube API Caller Other Media Playlist Recall Tutorial

Onto yesterday’s YouTube API Caller Other Media Playlist Creation Tutorial

  • work has progressed on Phase Two integrations, forwards, and “getting there” … but for the meantime there are other features we want here …
  • like more ways to recall user determined YouTube derived playlists and we found that …

the changed karaoke_youtube_api.htm inhouse YouTube video interfacer‘s playlist recall functionality needed this overhaul


function hoverplaylist(tboxrelo, doprompt) {
var p_ans='';
perused_list='';
Object.keys(window.localStorage).forEach(function(key){
if (('' + key).indexOf('tube') == 0) {
if (perused_list == '') { perused_list=tboxrelo.title.split(String.fromCharCode(10))[0] + String.fromCharCode(10) + ' ( and we found )'; }
perused_list=perused_list.replace(' )', ' ' + String.fromCharCode(10) + key.replace('tube_','').replace(/\-/g,' ') + String.fromCharCode(10) + ' )');
} else if (('' + key).indexOf('karaoke_youtube_api-') == 0) {
if (perused_list == '') { perused_list=tboxrelo.title.split(String.fromCharCode(10))[0] + String.fromCharCode(10) + ' ( and we found )'; }
perused_list=perused_list.replace(' )', ' ' + String.fromCharCode(10) + key.replace('karaoke_youtube_api-','').replace(/\-/g,' ') + String.fromCharCode(10) + ' )');
}
});
if (perused_list != '') { tboxrelo.title=perused_list; p_ans=null; if (doprompt) { p_ans=prompt(perused_list,perused_list); } if (p_ans != null) { if (p_ans != perused_list) { if (document.getElementById('namethechk') && document.URL.indexOf('#http') != -1 && !document.getElementById('namechk').checked) { document.getElementById('namethechk').value=p_ans; saveplaylist(); } } } }
}


function saveplaylist() {
if (document.getElementById('namechk') && document.getElementById('namethechk') && document.URL.indexOf('#http') != -1) {
if (!document.getElementById('namechk').checked && document.getElementById('namethechk').value.trim() != '') {
if (document.getElementById('namethechk').value.indexOf('tube_') == 0 || document.getElementById('namethechk').value.indexOf('karaoke_youtube_api-') == 0) {
if (('' + window.localStorage.getItem(document.getElementById('namethechk').value.replace(/\ /g, '-'))).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.open(decodeURIComponent(window.localStorage.getItem(document.getElementById('namethechk').value.replace(/\ /g, '-'))), '_blank', 'top=100,left=100,width=800,height=800');
document.getElementById('namethechk').placeholder=document.getElementById('namethechk').value;
document.getElementById('namethechk').title=document.getElementById('namethechk').title.replace(document.getElementById('namethechk').value, String.fromCharCode(10) + ' and you selected ' + String.fromCharCode(10) + document.getElementById('namethechk').value);
document.getElementById('namethechk').value='';
}
} else if (('' + window.localStorage.getItem('karaoke_youtube_api-' + document.getElementById('namethechk').value.replace(/\ /g, '-'))).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.open(decodeURIComponent(window.localStorage.getItem('karaoke_youtube_api-' + document.getElementById('namethechk').value.replace(/\ /g, '-'))), '_blank', 'top=100,left=100,width=800,height=800');
document.getElementById('namethechk').placeholder=document.getElementById('namethechk').value;
document.getElementById('namethechk').title=document.getElementById('namethechk').title.replace(document.getElementById('namethechk').value, String.fromCharCode(10) + ' and you selected ' + String.fromCharCode(10) + document.getElementById('namethechk').value);
document.getElementById('namethechk').value='';
} else if (('' + window.localStorage.getItem('tube_' + document.getElementById('namethechk').value.replace(/\ /g, '-'))).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.open(decodeURIComponent(window.localStorage.getItem('tube_' + document.getElementById('namethechk').value.replace(/\ /g, '-'))), '_blank', 'top=100,left=100,width=800,height=800');
document.getElementById('namethechk').placeholder=document.getElementById('namethechk').value;
document.getElementById('namethechk').title=document.getElementById('namethechk').title.replace(document.getElementById('namethechk').value, String.fromCharCode(10) + ' and you selected ' + String.fromCharCode(10) + document.getElementById('namethechk').value);
document.getElementById('namethechk').value='';
}
} else
if (document.getElementById('namechk').checked && document.getElementById('namethechk').value.trim() != '') {
if (('' + window.localStorage.getItem('karaoke_youtube_api-' + document.getElementById('namethechk').value.replace(/\ /g, '-'))).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('karaoke_youtube_api-' + document.getElementById('namethechk').value.replace(/\ /g, '-'));
}
if (('' + window.localStorage.getItem('tube_' + document.getElementById('namethechk').value.replace(/\ /g, '-'))).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('tube_' + document.getElementById('namethechk').value.replace(/\ /g, '-'));
}
var wpd='';
if (window.parent) {
if (parent.document.URL.indexOf('/swipe_media.htm') != -1) {
wpd=parent.get_doc();
}
}
if (wpd != '') {
window.localStorage.setItem('tube_' + document.getElementById('namethechk').value.replace(/\ /g, '-'), encodeURIComponent(decodeURIComponent(wpd)));
} else
if (docURL != document.URL || ('' + document.URL + 's').replace(/\#https/g,'') != ('' + document.URL + 's')) {
window.localStorage.setItem('karaoke_youtube_api-' + document.getElementById('namethechk').value.replace(/\ /g, '-'), encodeURIComponent(decodeURIComponent(docURL)));
} else {
window.localStorage.setItem('karaoke_youtube_api-' + document.getElementById('namethechk').value.replace(/\ /g, '-'), encodeURIComponent(decodeURIComponent(document.URL.split('#')[1]).split('&loop=')[0].split('&name=')[0] + '#' + document.URL.split('#')[1]));
}
}
}
}

… and feeding this into the workings of the changed swipe_media.html Tabular Single Row Image Gallery web application “Radio Play” mode of use.


Previous relevant YouTube API Caller Other Media Playlist Creation Tutorial is shown below.

YouTube API Caller Other Media Playlist Creation Tutorial

YouTube API Caller Other Media Playlist Creation Tutorial

Onto the recent YouTube API Caller Other Media Phase Two Iframe Tutorial

  • work has progressed on Phase Two integrations, forwards, and “getting there” … but for the meantime there are other features we want here …
  • like more ways to create user determined YouTube derived playlists and the best place we’ve found for this is via

the changed karaoke_youtube_api.htm inhouse YouTube video interfacer‘s YouTube Search capabilities.

These searches off that top textbox can lead to a …

  • (user should select) multi-select dropdown … off which the user could select a number of YouTube videos (without having to know their 11 character IDs) … and then …
  • click the new Radio📻? button … to hook in with …
  • the changed swipe_media.html Tabular Single Row Image Gallery web application “Radio Play” mode of use

Stay tuned for more ways to create playlists!


Previous relevant YouTube API Caller Other Media Phase Two Iframe Tutorial is shown below.

YouTube API Caller Other Media Phase Two Iframe Tutorial

YouTube API Caller Other Media Phase Two Iframe Tutorial

Yesterday’s YouTube API Caller Other Media Phase Two Interfacing Tutorial featured the use of …

  • popup windows … much maligned … so if there is a way we can transfer to the less maligned …
  • iframe

… keeping the work within the one window, that would be good, yes? Happily, yes is the go, and with little bother too, with referencing code structure like …


function feedoff(intr, compduris, comptitleis) {
var iqw=0;
if (window.parent != window.self) {
if (window.parent.window.opener) {
//alert('vHere ' + ivid);
iqw=0;
while (parent.document.getElementById('i' + iqw)) {
if (parent.document.getElementById('i' + iqw).value.indexOf('cannotenda2') != -1) {
vidarrv[iqw]='cannotenda2';
}
iqw++;
}
//alert('Here ' + ivid);
window.parent.window.opener.nonytopen(ivid, compduris, comptitleis);
} else {
iqw=0;
while (parent.document.getElementById('i' + iqw)) {
if (parent.document.getElementById('i' + iqw).value.indexOf('cannotenda2') != -1) {
vidarrv[iqw]='cannotenda2';
}
iqw++;
}
//alert('gere ' + ivid);
parent.nonytopen(ivid, compduris, comptitleis);
}
//} else {
// alert('therE');
}
return intr;
}

function localended(avo) {
var iqw=0;
if (window.parent) {
if (parent.document.URL.indexOf('tbox=') != -1) {
if (window.parent.window.opener) {
iqw=0;
while (parent.document.getElementById('i' + iqw)) {
if (parent.document.getElementById('i' + iqw).value.indexOf('cannotenda2') != -1) {
vidarrv[iqw]='cannotenda2';
}
iqw++;
}
setTimeout(function() { parent.window.opener.document.getElementById('j' + parent.document.URL.split('tbox=')[1].split('&')[0]).value='' + Math.ceil(eval('' + contdurs[whichnonyt(eval(-1 + contstarts.length))])) + '.00'; parent.document.getElementById('mytopspan').innerHTML='You can close me now ... ' + parent.document.getElementById('mytopspan').innerHTML; parent.window.opener.focus(); parent.window.opener.backtobase(); parent.window.opener.focus(); duration=-1; aminytnon=false; player=altplayer; }, 1000);

//window.close();
}
} else if (parent.document.URL.indexOf('/karaoke_youtube_api.htm') != -1) {
iqw=0;
while (parent.document.getElementById('i' + iqw)) {
if (parent.document.getElementById('i' + iqw).value.indexOf('cannotenda2') != -1) {
vidarrv[iqw]='cannotenda2';
}
iqw++;
}
if (('' + parent.document.URL + 's').replace(/\#https/g,'') != ('' + parent.document.URL + 's')) {
aminytnon=false;
player=altplayer;
duration=-9999;
playingvideo(); //setTimeout(playingvideo, 800);
}
} else if ('blog' != 'blog') {
parent.document.title='Finished ' + avo.outerHTML.substring(1).split(' ')[0];
}
}

}

… essentially unaffected by the pretty dramatic change of window usage configuration. Cute, huh?! But how is this made to happen? It’s really simple, really, as the second parameter of window.open can point to an iframe name attribute …


<iframe name=radioif id=radioif data-laterclick="" data-position=relative data-top=0 data-left=0 data-width=0 data-height=0 data-z=-999 style=display:none; src='//www.rjmprogramming.com.au/HTMLCSS/karaoke_youtube_api.htm#http'></iframe>

… and then we can wrap window.open calls, in amongst very “overlay” minded Javascript code, into our new inhouse “function windowopen” …


function windowopen(w1,w2,w3) {
if (('' + document.getElementById('radioif').getAttribute('data-height')) == '0') {
document.getElementById('radioif').setAttribute('data-height', '' + document.getElementById('tablenmup').getBoundingClientRect().top);
document.getElementById('radioif').setAttribute('data-width', '' + screen.width);
document.getElementById('radioif').setAttribute('data-top', '' + document.getElementById('tablenmup').getBoundingClientRect().top);
}
if (document.getElementById('xx' + nextwoin).outerHTML.indexOf('green') != -1) {
document.getElementById('radioif').style.position='absolute';
document.getElementById('radioif').style.top='0px';
document.getElementById('radioif').style.left='0px';
document.getElementById('radioif').style.width='' + document.getElementById('radioif').getAttribute('data-width') + 'px';
document.getElementById('radioif').style.height='' + document.getElementById('radioif').getAttribute('data-height') + 'px';
document.getElementById('radioif').style.zIndex='999';
document.getElementById('radioif').style.display='block';
} else {
document.getElementById('radioif').style.zIndex='-999';
document.getElementById('radioif').style.display='none';
lastw1=w1;
lastw2=w2;
lastw3=w3;
lastnextwoin=nextwoin;
}
if (w1.indexOf('&rand=') != -1) {
w1=w1.replace('&rand=', '&rand=' + Math.floor(Math.random() * 9));
} else if (w1.indexOf('#') != -1) {
w1=w1.replace('#', '&rand=' + Math.floor(Math.random() * 129) + '#');
}
if (w1.indexOf('&tbox=') != -1) {
w1=w1.replace('&tbox=' + w1.split('&tbox=')[1].split('&')[0].split('#')[0], '&tbox=' + nextwoin);
} else if (w1.indexOf('&') != -1) {
w1=w1.replace('&', '&tbox=' + nextwoin + '&');
}
if (nextwo) {
if (!nextwo.closed) {
nextwo.close();
nextwo=null;
}
}
return window.open(w1,"radioif");
}

… happening in the changed karaoke_youtube_api.htm inhouse YouTube video interfacer in “Radio Play” mode.

And then there was “what we noted as a to do” as …

make click on checkbox after textbox entry work

… in the changed karaoke_youtube_api.htm inhouse YouTube video interfacer in “Radio Play” mode.

And so, for the rest of the day, more progress, but still not there with …


Previous relevant YouTube API Caller Other Media Phase Two Interfacing Tutorial is shown below.

YouTube API Caller Other Media Phase Two Interfacing Tutorial

YouTube API Caller Other Media Phase Two Interfacing Tutorial

Onto the recent YouTube API Caller Other Media Interfacing Tutorial we found that …

  • isolation interfacing as in our first designated phase 1 … is a doddle compared to when …
  • interfacing among a number of players in this (what pans out to be day one of) phase 2

… making it work in with the supervisor of YouTube API “inhouse” web application, and all it’s usage incarnations. We did not expect otherwise. but naturally hoped for the miracle of it all happening in a day.

Never mind … but what can we say about phase 2 we got “contained” today. It’s, to our mind …

  • start up supervisor of YouTube API “inhouse” web application in “Radio Play” simulated mode (ie. #http hashtag) …
  • enter in an 11 character YouTube ID (eg.

    0Gz_7am23rk

    ) and tab out …

  • click first left hand checkbox …
  • in the textbox to the right enter a media URL (we’ve been doing) like …

    /Mac/iPad/slide1.m4a

    … (and we are not ready for data URIs yet) … and tab out …

  • at this stage, so far a new popup window opens
  • non YouTube media plays on non-mobile starting muted … and at the end of it’s play …
  • the user can close popup to return to original supervisor of YouTube API “inhouse” web application incarnation

Further along, but not there yet, with …


Previous relevant YouTube API Caller Other Media Interfacing Tutorial is shown below.

YouTube API Caller Other Media Interfacing Tutorial

YouTube API Caller Other Media Interfacing Tutorial

Today’s work is the result of a “generic push” by us to improve on attempts in the past to use our inhouse YouTube video playing interfacing suite of web applications to mix …

  • YouTube video media content … interspersed with …
  • non YouTube media content

… when we presented Spliced Audio/Video YouTube Shuffle Tutorial blog posting thread. We better like this “generic push” idea of adapting our inhouse YouTube API interfacing web application to process both types of media input categories and be handled just within it’s remit, if there are non YouTube media items, within a (newly nesting) …

  • table element … with …
  • left hand cell handling YouTube video media content presented via YouTube API’s iframe element approach … and the …
  • right hand cell handling non YouTube video media content presented via video or audio or img or iframe element depending on the data mimetype …

… and it is our inhouse YouTube API interfacing web application’s job to toggle between CSS display:none; and display:table-cell; for these two cells appropriately.

This work we see as a two part mini-project where …

  1. today’s phase 1 work isolates that inhouse YouTube API interfacing web application and asks it to handle new hashtag based data arguments coming in to demonstrate it, in that isolation, works both for the new paradigm and any previous scenarios … and then …
  2. after today we start phase 2 work interfacings, where we will rejoin the blog posting thread of yesterday’s Tabular Single Row Emoji Sharing Menu Tutorial and allow for the smarter inhouse YouTube API interfacing web application to be relatively seamless changing between YouTube and non YouTube media playing should a user enter a data URI, for example, in one of those textboxes to the right of the checkboxes

… for the modified stop_start_youtube.html YouTube API caller.

Here is a non YouTube video example …

… and here is a YouTube example

… and here is a non YouTube audio example …

… and here is a non YouTube animated GIF example …

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.


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.

Posted in Animation, eLearning, Event-Driven Programming, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Co-ordinate Mercator Projection Mobile TimeZone DateTime Tutorial

Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial

Co-ordinate Mercator Projection Mobile TimeZone DateTime Tutorial

We find lots of need to use the word …

non-mobile

… and perhaps you’re regular enough to have noticed?! Yes, of course there are quite of lot of differences between how a …

  • non-mobile web browser webpage behaves … compared to how a …
  • mobile web browser webpage behaves

Two quite glaring differences are …

  • way on non-mobile regarding elements containing a title attribute that you hover over, you will be shown that title attribute … hence our recent interest in CSS Tooltips … and today regarding the …
  • way on non-mobile the user can see a cursor (which can be programmatically tailored) as the mouse moves across the webpage screen

But, today, the cursor work of yesterday’s Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial is not lost to the mobile woooorrrrlllddd because …

  • the non-mobile onmousemove event means by which a webpage screen position can help determine a contextual cursor with useful SVG+XML display content … and today …
  • the mobile ontouchmove event is called into play as a means by which a webpage screen position can help determine a contextual position:absolute “overlay” span element whose innerHTML contains the SVG part of the SVG+XML display content talked about above

We’re not saying that we will not tweak the way it works over time for …

again. But at least for now a user can trail their finger down across the Mercator Projection map and one of …

  • current date time at functionality data addition … non-mobile cursor wise … in addition to existant …
  • latitude, longitude
  • responsive percentage left%, top%

… appears as they move, holding that finger down. The effect created resembles a non-mobile cursor on a mobile platform because the quick changes of data modes as above, makes the Clayton‘s cursor blink like on non-mobile with non-Clayton’s cursors (my head hurts), thanks to the changed the lefttopcursor.js external Javascript helper.


Previous relevant Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial is shown below.

Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial

Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial

We’re baaaaack! And … loving it! Yes, back at GeoJson world map work as last talked about with Co-ordinate Cursor Mercator Projection External Javascript Tutorial, regarding your better than garden variety non-mobile cursor, today, we’re adding a …

  • current date time at functionality data addition … non-mobile cursor wise … in addition to existant …
  • latitude, longitude
  • responsive percentage left%, top%

… information carried along as a cursor over the Mercator Projection maps used in …

Huh?! No changes to the parents? Luckily, we have a scenario only needing changes to the lefttopcursor.js external Javascript.

What question did these changes seek to improve upon (shall we say, because a perfect solution is not on the cards, in any free way, here … but it works a lot of the time)?

Given latitude and longitude lookup current local time?

If you follow through on this research you will see there is no free native Javascript that neatly addresses solutions, directly, but, around here, because of the wonderful …

  • PHP in our lives … that means that …
  • PHP TimeZone functionality is also in our lives … and we’ve sort of memorized what PHP does here in Javascript terms … hence have a …
  • Javascript “one liner” variable made up of that PHP TimeZone data (if you will) … as a first call (we’ve decided if near enough to latitude and longitude of interest) … else falling back to …
  • TimeZone UTC hour offset = Math.floor(longitude / 15) … mostly in International waters

… as a paradigm we’ve used (where longlattotime() is called near the webpage document.body onload event timing) …


var yourtzlist="<option value=\"GMT\" data-geo=\"51.4934,0.0098,GMT,GB,+0\">GMT</option><option value=\"Africa/Abidjan\" data-geo=\"5.31666,-4.03334,GMT,CI,+0\">Africa/Abidjan</option><option value=\"Africa/Accra\" data-geo=\"5.55,-0.21667,GMT,GH,+0\">Africa/Accra</option> ... blah blah blah";
var tznamelists=[], tzlatlist=[], tzlonglist=[], tzoffsetlist=[], tzisolist=[], lastlongis='', lastlatis='', lasttzsuff='', lasttzname='', withingettz=false;

function toIso(date, timeZone) { // thanks to https://stackoverflow.com/questions/73576351/how-do-you-get-the-dst-time-adjustment-from-a-timezone
return new Date(date).toLocaleString('sv', { timeZone } ).replace(' ', 'T').replace(',', '.');
}

function getUTCOffset(year, month, day, hour, minute, second, timeZone) { // thanks to https://stackoverflow.com/questions/73576351/how-do-you-get-the-dst-time-adjustment-from-a-timezone
const date = [year, month, day].map(e => (e + '').padStart(2, '0')).join('-') + 'T' + [hour, minute, second].map(e => (e + '').padStart(2, '0')).join(':');
const dt = Date.parse(date + 'Z');
for(let offsetMinutes = -900; offsetMinutes <= 900; offsetMinutes += 15) {
const test = new Date(dt - offsetMinutes * 60000);
if (date === toIso(test, timeZone)) {
return offsetMinutes;
}
}
}

function getDSTDetails(zone, year) { // thanks to https://stackoverflow.com/questions/73576351/how-do-you-get-the-dst-time-adjustment-from-a-timezone
const jan = getUTCOffset(year, 1, 1, 0, 0, 0, zone);
const jul = getUTCOffset(year, 7, 1, 0, 0, 0, zone);
if (jan === jul) return { zone, year, standardOffsetMinutes: Math.min(jan, jul), dstOffsetMinutes: Math.max(jan, jul), janOffsetMinutes: jan, julOffsetMinutes: jul }
return { zone, year, standardOffsetMinutes: Math.min(jan, jul), dstOffsetMinutes: Math.max(jan, jul), dstChangeMinutes: Math.abs(jan - jul) }
}

function gettzsuff() {
var defoff=-999, wasdefoff=-999, deftz='';
if (withingettz) {
setTimeout(gettzsuff, 50);
} else {
var xlastlongis=lastlongis;
var xlastlatis=lastlatis;
withingettz=true;
defoff=Math.floor(eval('' + xlastlongis) / 15);
var nearestone=-1, nearestsum=-1, newsum=-1;
for (var iuh=1; iuh<tzlonglist.length; iuh++) {
if (nearestone < 0) {
nearestone=iuh;
wasdefoff=defoff;
try {
defoff=eval('' + tzoffsetlist[iuh]);
} catch(ytryt) {
console.warn('bad is ' + tzoffsetlist[iuh]);
defoff=wasdefoff;
}
nearestsum=eval(Math.abs(tzlonglist[iuh] - xlastlongis) + Math.abs(tzlatlist[iuh] - xlastlatis));
if (nearestsum < 10) {
deftz=tznamelists[iuh].replace('GMT','UTC');
lasttzname=' (near to TimeZone ' + deftz + ')';
}
} else {
newsum=eval(Math.abs(tzlonglist[iuh] - xlastlongis) + Math.abs(tzlatlist[iuh] - xlastlatis));
if (newsum < nearestsum) {
nearestone=iuh;
try {
defoff=eval('' + tzoffsetlist[iuh]);
} catch(ytrayt) {
console.warn('Bad is ' + tzoffsetlist[iuh]);
defoff=wasdefoff;
}
nearestsum=newsum;
if (nearestsum < 10) {
deftz=tznamelists[iuh].replace('GMT','UTC');
lasttzname=' (near to TimeZone ' + deftz + ')';
}
}
}
}
if (deftz != '' && nearestsum < 10) {
var xcd = new Date();
var xcyear = xcd.getUTCFullYear();
console.log('' + (new Date(new Date().toLocaleString("en-US", {timeZone: deftz}))).getTimezoneOffset() + ' ');
console.log(getDSTDetails(deftz, xcyear));
lasttzsuff=String.fromCharCode(32) + ' ' + ('' + (new Date(new Date().toLocaleString("en-US", {timeZone: deftz})))).split(' GMT')[0].split(' UTC')[0];
console.warn('0:' + lasttzsuff);
} else if (defoff != -999) {
lasttzname='';
var ud = new Date();
var uhour = ud.getUTCHours();
var umin = ud.getUTCMinutes();
var uday = ud.getUTCDay();
var usec = 0;
var udate = ud.getUTCDate();
var umonth = ud.getUTCMonth();
var uyear = ud.getUTCFullYear();
var newudt = new Date(Date.UTC(uyear, umonth, udate, uhour, umin, usec));
console.warn('defoff=' + defoff + ' RE ' + ('' + newudt));
if (('' + newudt).indexOf(' GMT+') != -1) {
defoff-=eval(('' + newudt).split(' GMT+')[1].substring(0,2));
defoff-=eval(eval(('' + newudt).split(' GMT+')[1].substring(2).substring(0,2).replace(/^0/g,'')) / 60);
} else if (('' + newudt).indexOf(' GMT-') != -1) {
defoff+=eval(('' + newudt).split(' GMT-')[1].substring(0,2));
defoff+=eval(eval(('' + newudt).split(' GMT-')[1].substring(2).substring(0,2).replace(/^0/g,'')) / 60);
}
console.warn(('' + (addHours(newudt,defoff))).split(' GMT')[0].split(' UTC')[0]);
lasttzsuff=String.fromCharCode(32) + ' ' + ('' + (addHours(newudt,defoff))).split(' GMT')[0].split(' UTC')[0];
console.warn('1:' + lasttzsuff);
}
//lasttzsuff=''; // temporary
withingettz=false;
}
}

function addHours(xdate, hoursToAdd) {
var newDate = new Date(xdate); // Create a copy to avoid modifying the original date
newDate.setHours(newDate.getHours() + hoursToAdd);
return newDate;
}

function longlattotime() {
var tzs=yourtzlist.split('" data-geo="');
for (var itzs=1; itzs<tzs.length; itzs++) {
tznamelists.push(tzs[eval(-1 + itzs)].split(' value="')[eval(-1 + tzs[eval(-1 + itzs)].split(' value="').length)]);
tzlatlist.push(tzs[itzs].split(',')[0]);
tzlonglist.push(tzs[itzs].split(',')[1]);
tzisolist.push(tzs[itzs].split(',')[3]);
if (eval('' + tzs[itzs].split(',').length) > 4) {
tzoffsetlist.push(tzs[itzs].split(',')[4].split('"')[0].replace('+',''));
} else {
tzoffsetlist.push('0');
}
}
console.warn('tzlonglist.length=' + tzlonglist.length);
}


function xmap(inidx) {
var outidx=eval('' + inidx);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscalex != 1.0) {
outidx=('' + eval(eval('' + altoriginx) + (eval('' + inidx) - eval('' + genoriginx)) * eval('' + altscalex)).toPrecision(15));
//document.title='' + inidx + ' fixed=' + (eval('' + inidx) - eval('' + genoriginx)) + ' then ' + outidx;
if (outidx.indexOf('.') != -1) {
lastlongis=outidx.split('.')[0] + '.' + outidx.split('.')[1].substring(0,2);
return lastlongis.replace(/0$/g,String.fromCodePoint(176)); //outidx.split('.')[0] + '.' + outidx.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
lastlongis=outidx;
return outidx.replace(/0$/g,String.fromCodePoint(176));
//} else {
// alert('Oops');
}
}
lastlongis='' + inidx;
return inidx;
}

function ymap(inidy) {
var outidy=eval('' + inidy);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscaley != 1.0) {
outidy=('' + eval(eval('' + altoriginy) + (eval('' + inidy) - eval('' + genoriginy)) * eval('' + altscaley)).toPrecision(15));
if (outidy.indexOf('.') != -1) {
lastlatis=outidy.split('.')[0] + '.' + outidy.split('.')[1].substring(0,2);
setTimeout(gettzsuff, 50);

return lastlatis.replace(/0$/g,String.fromCodePoint(176)); //outidy.split('.')[0] + '.' + outidy.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
lastlatis=outidy;
setTimeout(gettzsuff, 50);

return outidy.replace(/0$/g,String.fromCodePoint(176));
}
}
lastlatis='' + inidy;
setTimeout(gettzsuff, 50);

return inidy;
}

function toTimestamp(strDate) { // thanks to https://stackoverflow.com/questions/9873197/how-to-convert-date-to-timestamp
var datum = Date.parse(strDate);
return datum/1000;
}

function timestamped(inidt) {
if (inidt.split(':').length == 3) {
var uhour = inidt.split(':')[0].split(' ')[eval(-1 + inidt.split(':')[0].split(' ').length)];
var umin = inidt.split(':')[1];
inidt=inidt.split(' ' + uhour + ':' + umin)[0];
var uyear = inidt.split(' ')[eval(-1 + inidt.split(' ').length)];
var udate = ('0' + inidt.split(' ')[eval(-2 + inidt.split(' ').length)]).slice(-2);
var umonth = inidt.split(' ')[eval(-3 + inidt.split(' ').length)].substring(0,3).replace('Jan','01').replace('Feb','02').replace('Mar','03').replace('Apr','04').replace('May','05').replace('Jun','06').replace('Jul','07').replace('Aug','08').replace('Sep','09').replace('Oct','10').replace('Nov','11').replace('Dec','12');
return udate + '/' + umonth + '/' + uyear + ' ' + uhour + ':' + umin;
}
return inidt;
}

function lottery(valone, valtwo) {
var anum=Math.floor(Math.random() * 20);
if (valtwo != '' && anum <= 5) {
var bittoch=valone.split('</text>')[0].split('>')[eval(-1 + valone.split('</text>')[0].split('>').length)];
console.warn('4:' + valtwo.slice(-8).replace(/\:/g,' '));
return valone.replace(bittoch, timestamped(valtwo)); //valtwo.slice(-8).replace(/\:/g,' ');
}
console.warn('5:' + valone);
return valone;
}


Previous relevant Co-ordinate Cursor Mercator Projection External Javascript Tutorial is shown below.

Co-ordinate Cursor Mercator Projection External Javascript Tutorial

Co-ordinate Cursor Mercator Projection External Javascript Tutorial

For describing where you are on Earth humans have set up the …


Longitude,Latitude

(usually measured in degrees, especially in Mbeya and Madrid) system of describing positions, and on a Mercator Projection (ie. at school, the ones showing Greenland huge (when it is, in actuality, roughly, similar in surface area to Saudi Arabia)) that globe is slapped onto a 2d rectangular sheet of map (like perfectly peeling an apple but fixing up the tears in forming a rectangle, sort of), if you will …


360,-180

… wide,high starting up at the top left of that rectangle with Longitude,Latitude …


-180,90

… degrees. We’re saying the height is -180 because down the bottom right of this Mercator Projection arrangement the Longitude,Latitude is …


180,-90

Knowing all this and working out the webpage stuff as per usual we can, with a call, now catered for …


function xmap(inidx) {
var outidx=eval('' + inidx);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscalex != 1.0) {
outidx=('' + eval(eval('' + altoriginx) + (eval('' + inidx) - eval('' + genoriginx)) * eval('' + altscalex)).toPrecision(15));
//document.title='' + inidx + ' fixed=' + (eval('' + inidx) - eval('' + genoriginx)) + ' then ' + outidx;
if (outidx.indexOf('.') != -1) {
return outidx.split('.')[0] + '.' + outidx.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
return outidx.replace(/0$/g,String.fromCodePoint(176));
//} else {
// alert('Oops');
}
}
return inidx;
}

function ymap(inidy) {
var outidy=eval('' + inidy);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscaley != 1.0) {
outidy=('' + eval(eval('' + altoriginy) + (eval('' + inidy) - eval('' + genoriginy)) * eval('' + altscaley)).toPrecision(15));
if (outidy.indexOf('.') != -1) {
return outidy.split('.')[0] + '.' + outidy.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
return outidy.replace(/0$/g,String.fromCodePoint(176));
}
}
return inidy;
}

… in a changed lefttopcursor.js external Javascript call of the ilk …


<script type=text/javascript src='//www.rjmprogramming.com.au/lefttopcursor.js?rand=876538765&scp=1F310&type=img&tl=-180,90&wh=360,-180'></script>

… affecting, further to yesterday’s Co-ordinate Cursor External Javascript Primer Tutorial, as per …

… to improve these web applications.


Previous relevant Co-ordinate Cursor External Javascript Primer Tutorial is shown below.

Co-ordinate Cursor External Javascript Primer Tutorial

Co-ordinate Cursor External Javascript Primer Tutorial

Today we’re taking what we learnt regarding …

co-ordinated cursors

(only regarding non-mobile platforms, alas) we implemented via the document.body onmousemove event logics in the recent Animated Plane Refuel Game Tutorial, and creating new external Javascript useful calleetool whereby …

  • not needing to implement it for that project above (except before launching into it making responsive design percentage friendly units into the mix via a changed “latest draft” Animated Plane Plane Refuel Game web application below), but doing a quick check to see that even if you did, the external Javascript would know enough to “lay off” … and ….
  • try out on yesterday’s Background Blend Mode Example web application (and which, eventually, we said “What the heck, so what if it gets an inapt cursor?!” and ended up creating a “second draft”) calling this new lefttopcursor.js external Javascript … via …

    <script type=text/javascript src='//www.rjmprogramming.com.au/lefttopcursor.js?scp=26fd'></script>

    … as an example call implementing cursor text with the ⛽ fuel pump emoji mentioned, on our macOS MAMP local Apache/PHP/MySql web server, and you can see working within today’s animated GIF presentation
  • try out on our changed do_away_with_the_boring_bits.html Try Your Own HTML web application‘s iframe HTML validator using it’s srcdoc

    <iframe srcdoc="<html><head><script type=text/javascript src='//www.rjmprogramming.com.au/lefttopcursor.js?rand=7635476'></script></head><body style=width:100%;height:650px;> </body></html>" data-src='about:blank' name='ihtmlcontent' id='ihtmlcontent' style='z-index:99;height:650px; background-color:lightblue;'></iframe>

    … attribute

… all happening.

It being external Javascript we wanted to see it working from a localhost web browser address bar URL call, and it did, making it a tool, to our mind.


Previous relevant Animated Plane Refuel Game Tutorial is shown below.

Animated Plane and Coconut Hunt Game Nuances Tutorial

Animated Plane Refuel Game Tutorial

Today we wondered how best to involve the …

  • plane … mainly, but perhaps also the …
  • gymnast … with a guest starring role …

… in an online game in our recent Animated Plane and Coconut Hunt Game Nuances Tutorial‘s web application, because their existence to do with Hunt Games seems a bit obscure.

And so, we thought, you see those games where characters get strength by picking up objects they “run into” or “run over” and we thought …

Plane Refuel Game

(where the longer the flight survives the more skillful the player) as a result of that thinking, plus being able to find an apt emoji ⛽ for the fuel pump we wanted to base the game around, along with an HTML progress element to inform the user regarding how much fuel is left, in a changed “latest draft” Animated Plane Plane Refuel Game web application below!


Previous relevant Animated Plane and Coconut Hunt Game Nuances Tutorial is shown below.

Animated Plane and Coconut Hunt Game Nuances Tutorial

Animated Plane and Coconut Hunt Game Nuances Tutorial

Today’s a day of nuanced progress, after yesterday’s Coconut Hunt Game Tutorial‘s “filling in sideways” work on our Animated Plane and Coconut Hunt Game web application. Today, we …

  • fixed some document.body.title annoyances whereby it would appear too often
  • worked on the default A option textarea via …
    1. some “panda 🐼 led recovery” modelling of a p emoji usage (with animation) and span emoji usage (without animation) … and …
    2. modelling of how iframe onload event can be used to develop dynamic Javascript (the default example changing the coconut 🥥 hunt into a bear 🐻 hunt?!) … as opposed to a document.createElement(‘script’) alternative approach
  • fixed some window.open too small size annoyances
  • allowed for screen co-ordinates cursor (on non-mobile), via onmousemove event logic, to assist intrepid users going above and beyond “overlay” positioning their own elements via position:absolute; left:?; top:?; in A option textareas
  • allowed for toggling of non-mobile cursor between as above and crosshair via right click
  • allowed for the last left:?; top:?; as above detected be remembered and involve itself as the default position:absolute; “overlay” positioning of the A option textarea default “panda 🐼 led recovery” emoji of above
  • allow for 8 seconds of time for a user to change default coconut 🥥 emoji to some other text via contenteditable=true ahead of the Hunt Game starting … thanks to this useful link regarding hiding a contenteditable=true focus border
  • allow for sharing of the Hunt Game
  • Hunt Game sound effects

Feel free to try these tweaks to our Animated Plane and Coconut Hunt Game, in a nuanced “latest draft” Animated Plane Coconut Hunt Game web application below!


Previous relevant Coconut Hunt Game Tutorial is shown below.

Coconut Hunt Game Tutorial

Coconut Hunt Game Tutorial

Are you a reader who has been amused or bemused by the word Game being in the blog posting titles lately, up to yesterday’s Animated Plane Game User Animations and Styling Tutorial, when No Game really, about any of it? Well, today, it’s …

Game On

Do you like coconuts? Can I ask you, have you ever looked into a coconut, and asked yourself …

I shell always love you.

? Well, have we got the game for you?! Start the ball rollingshell shaking via the first click/top on the coconut fallen from the tree. And from there, it’s a fast reactions game, to score well! Good luck, in the changed “latest draft” Animated Plane Coconut Hunt Game web application below!


Previous relevant Animated Plane Game User Animations and Styling Tutorial is shown below.

Animated Plane Game User Animations and Styling Tutorial

Animated Plane Game User Animations and Styling Tutorial

On top of yesterday’s Animated Plane Game User Content Sharing Tutorial‘s honing in on the five “nouns” of interest …

  • trees
  • plane
  • gymnast
  • clouds
  • ground

… today we wanted to offer two more user controllable parts to this Animated Plane Game web application, those being …

  • CSS styling … easy, as CSS can be dynamically added to a web application at the clientside, as the Javascript is executing … and, a bit more of a learning curve for beginners is …
  • user animations … we’re envisaging, in it’s “easiest to understand encapsulation for a newbie” uses …
    1. @keyframes
    2. transition

    … a whole big wooooorrrrlllldddd of animation study just by itself (and in order for modelling to, perhaps, help we used an example from this excellent link, thanks, as the default option A textarea usage model)

… but a hell of a lot easier for a user to establish than some arcane Javascript DOM animations involving setTimeout or setInterval timers?!

For these two new ideas, popup textarea windows appear to give the user plenty of space to play around in. As ever, email and SMS can follow up for that user to share with others what their animation ideas are, perhaps far removed from the original plane and gymnast scenario by the time they finish. And here it may be pertinent to point out that even using hashtag emailing (and even more so with SMSing) there must be message size limits that will stop you event-u-al-ly!

Try this in the changed “latest draft” Animated Plane Game web application below.

Did you know?

In yesterday’s “noun” work we talked about “content” defined by the user in terms of real references to media data URIs or URLs. Well, the other way a user can now affect “content” is via CSS. Below we make the plane and gymnast disappear via the C (for CSS styling) option (that can take you to a popup window textarea where you can Apply this) …


<style>
#myif { /* plane */
display:none; /* other choice could be visibility:hidden; */
}

#mytwoif { /* gymnast */
visibility:hidden; /* other choice could be display:none; */
}
</style>


Previous relevant Animated Plane Game User Content Sharing Tutorial is shown below.

Animated Plane Game User Content Sharing Tutorial

Animated Plane Game User Content Sharing Tutorial

Yesterday’s Animated Plane Game Primer Tutorial set up five “nouns” of interest …

  • trees
  • plane
  • gymnast
  • clouds
  • ground

… each of which has a relationship to a piece of media content. The border-image (ie. ground) content aspects we allow a user to define emoji text for, but the rest are associated with a data URI or URL.

Today’s work is to allow the user to specify these “content” data items themselves, as well as share this via email or SMS to another user, with those user “content” data items recreated for the recipient user clicking the email or SMS link containing those hashtagged user data components. Later we hope to expand the functionality more, from today’s …


function getsrc(fromoh) {
var forvpre='Currently this content points at ... ' + String.fromCharCode(10);
var forvsuf=String.fromCharCode(10) + 'Enter an alternative content URL (can be clipart style data URI you see often using Google Image (Copy Image Address via right click) Searches) ... or ... ' + String.fromCharCode(10) + String.fromCharCode(10) + '1[:URL] for trees, 2[:URL] for plane, 3[:URL] for gymnast, 4[:URL] for clouds, 5[:emoji(s)] for ground, E for email, S for SMS';
if (fromoh.indexOf(' src="//') != -1) {
return forvpre + document.URL.split('//')[0] + fromoh.split(' src="')[1].split('"')[0] + forvsuf;
} else if (fromoh.indexOf(" src='//") != -1) {
return forvpre + document.URL.split('//')[0] + fromoh.split(" src='")[1].split("'")[0] + forvsuf;
} else if (fromoh.indexOf(" src=//") != -1) {
return forvpre + document.URL.split('//')[0] + fromoh.split(" src=")[1].split(" ")[0].split(">")[0] + forvsuf;
} else if (fromoh.indexOf(' src="') != -1) {
return forvpre + fromoh.split(' src="')[1].split('"')[0] + forvsuf;
} else if (fromoh.indexOf(" src='") != -1) {
return forvpre + fromoh.split(" src='")[1].split("'")[0] + forvsuf;
} else if (fromoh.indexOf(" src=") != -1) {
return forvpre + fromoh.split(" src=")[1].split(" ")[0].split(">")[0] + forvsuf;
}
return fromoh;
}

function yourprompt(ino, intlis) {
var ei=-1, si=-1;
isac=true;
var opsd=prompt(getsrc(ino.outerHTML), '');
if (opsd == null) { isac=false; return false; }
if (opsd.trim() != '') {
switch (opsd.substring(0,1).toLowerCase().replace('+','s')) {
case '1': // trees
if ((opsd + ' ').substring(0,2) == '1:') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + (opsd + ' ').substring(2) + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where trees are.', '');
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
}
break;


case '2': // plane
if ((opsd + ' ').substring(0,2) == '2:') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where plane is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '3': // gymnast
if ((opsd + ' ').substring(0,2) == '3:') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where gymnast is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '4': // clouds
if ((opsd + ' ').substring(0,2) == '4:') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps via Google image search) data URI or URL suiting where cloud background image is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '5': // ground
if ((opsd + ' ').substring(0,2) == '5:') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + (opsd + ' ').substring(2) + suffixbiu + '") !important; </sty' + 'le>'
} else {
opsd=prompt('Enter your (probably quite long) emoji (we are guessing) border image text.', '');
if (opsd != null) {
if (opsd != '') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + suffixbiu + '") !important; </sty' + 'le>'
} else {
groundalt='&groundalt='; // + encodeURIComponent(opsd);
document.body.style.borderImage='none';
document.body.style.borderBottom='1px solid transparent';
document.body.style.borderBottomWidth='0px';
//document.body.innerHTML+='<sty' + 'le> body { border-bottom-width:0px !important; } </sty' + 'le>';
}
}
}
break;

case 'e': // email
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.trim().indexOf('@') != -1) {
anchor.href = 'mailto:' + opsd.split('@')[0].split(' ')[eval(-1 + opsd.split('@')[0].split(' ').length)] + opsd.split(opsd.split('@')[0])[1].split(' ')[0] + '?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'mailto:?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

case 's': // SMS
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.substring(0,1).toLowerCase() == '+') {
anchor.href = 'sms:' + opsd.split(' ')[0] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else if (opsd.indexOf(' ') != -1) {
anchor.href = 'sms:' + opsd.split(' ')[eval(-1 + opsd.split(' ').length)] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

default:
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
break;
}
} else {
setTimeout(function(){ ino.click(); }, 100); return true;
}
isac=false;
return false;
}

function anyprompt(opsd) {
if (opsd.trim() != '') {
opsd=opsd;
switch (opsd.substring(0,1).toLowerCase().replace('+','s')) {
case '1': // trees
if ((opsd + ' ').substring(0,2) == '1:') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + (opsd + ' ').substring(2) + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where trees are.', '');
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
}
break;

case '2': // plane
if ((opsd + ' ').substring(0,2) == '2:') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where plane is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '3': // gymnast
if ((opsd + ' ').substring(0,2) == '3:') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where gymnast is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '4': // clouds
if ((opsd + ' ').substring(0,2) == '4:') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps via Google image search) data URI or URL suiting where cloud background image is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '5': // ground
if ((opsd + ' ').substring(0,2) == '5:') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + (opsd + ' ').substring(2) + suffixbiu + '") !important; </sty' + 'le>'
} else {
opsd=prompt('Enter your (probably quite long) emoji (we are guessing) border image text.', '');
if (opsd != null) {
if (opsd != '') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + suffixbiu + '") !important; </sty' + 'le>'
} else {
groundalt='&groundalt='; // + encodeURIComponent(opsd);
document.body.style.borderImage='none';
document.body.style.borderBottom='1px solid transparent';
document.body.style.borderBottomWidth='0px';
//document.body.innerHTML+='<sty' + 'le> body { border-bottom-width:0px !important; } </sty' + 'le>';
}
}
}
break;

case 'e': // email
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.trim().indexOf('@') != -1) {
anchor.href = 'mailto:' + opsd.split('@')[0].split(' ')[eval(-1 + opsd.split('@')[0].split(' ').length)] + opsd.split(opsd.split('@')[0])[1].split(' ')[0] + '?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'mailto:?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

case 's': // SMS
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.substring(0,1).toLowerCase() == '+') {
anchor.href = 'sms:' + opsd.split(' ')[0] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else if (opsd.indexOf(' ') != -1) {
anchor.href = 'sms:' + opsd.split(' ')[eval(-1 + opsd.split(' ').length)] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

default:
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
break;
}
}
}

function ourprompt(ino, intlis) {
var ei=-1, si=-1;
isac=true;
var opsd=null;
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
opsd=prompt(intlis + String.fromCharCode(10) + String.fromCharCode(10) + intlis, '');
} else {
opsd=prompt(getsrc(document.getElementById('myimg').outerHTML), '');
}
if (opsd == null) { isac=false; return false; }
if (opsd.trim() != '') {
opsd=opsd;
switch (opsd.substring(0,1).toLowerCase().replace('+','s')) {
case '1': // trees
if ((opsd + ' ').substring(0,2) == '1:') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + (opsd + ' ').substring(2) + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where trees are.', '');
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
}
break;

case '2': // plane
if ((opsd + ' ').substring(0,2) == '2:') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where plane is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '3': // gymnast
if ((opsd + ' ').substring(0,2) == '3:') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where gymnast is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '4': // clouds
if ((opsd + ' ').substring(0,2) == '4:') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps via Google image search) data URI or URL suiting where cloud background image is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '5': // ground
if ((opsd + ' ').substring(0,2) == '5:') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + (opsd + ' ').substring(2) + suffixbiu + '") !important; </sty' + 'le>'
} else {
opsd=prompt('Enter your (probably quite long) emoji (we are guessing) border image text.', '');
if (opsd != null) {
if (opsd != '') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + suffixbiu + '") !important; </sty' + 'le>'
} else {
groundalt='&groundalt='; // + encodeURIComponent(opsd);
document.body.style.borderImage='none';
document.body.style.borderBottom='1px solid transparent';
document.body.style.borderBottomWidth='0px';
//document.body.innerHTML+='<sty' + 'le> body { border-bottom-width:0px !important; } </sty' + 'le>';
}
}
}
break;

case 'e': // email
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.trim().indexOf('@') != -1) {
anchor.href = 'mailto:' + opsd.split('@')[0].split(' ')[eval(-1 + opsd.split('@')[0].split(' ').length)] + opsd.split(opsd.split('@')[0])[1].split(' ')[0] + '?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'mailto:?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

case 's': // SMS
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.substring(0,1).toLowerCase() == '+') {
anchor.href = 'sms:' + opsd.split(' ')[0] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else if (opsd.indexOf(' ') != -1) {
anchor.href = 'sms:' + opsd.split(' ')[eval(-1 + opsd.split(' ').length)] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

default:
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
break;
}
} else {
setTimeout(function(){ ino.click(); }, 100); return true;
}
isac=false;
return false;
}

… in the changed “eighth draft” Animated Plane Game web application.


Previous relevant Animated Plane Game Primer Tutorial is shown below.

Animated Plane Game Primer Tutorial

Animated Plane Game Primer Tutorial

The mix-blend-mode:multiply; discoveries (along with those naive previous usage without realizing it’s implications) we made creating Periodic Table Image Map Primer Tutorial recently has opened up new “vistas of possibility” (VOP, of course) for us, and has inspired us to give “just Javascript and CSS and HTML animated games” (aided in large part by clipart free content components) another go …

… with a “widget feel” now realizable, for us, knowing that white backgrounded HTML iframe content no longer has to hold us back piecing together animations (in an “OOP feeling” way) consisting of …

  • base webpage CSS and HTML and Javascript (DOM, also helping out the control of) …
  • HTML iframe components (and in our case the image content is it’s background image with background-size:contain; and background-repeat:no-repeat; along with a specific iframe width and height) for any one “noun” (or class of object) in your game storyboard … if you will … if you will … if you will … and …
  • HTML img components in a similar vein … but today’s trees did not need mix-blend-mode:multiply; because the originator made the background transparent (ie. another option with all this “animated pieces thinking”)

Animation(s) can be CSS @keyframe transitions (though not yet with animation above) or Javascript DOM logic via setTimeout (or setInterval) timers or animated GIF/webp content or, we daresay, many other approaches.

We’re going to tabularize below “how we got to the result above” below …

We started with a “first draft” … getting Freepik image plane image animated with a rudimentary green border-bottom representing the ground …
then to “second draft” … adding https://i.makeagif.com/media/8-11-2023/Xu_roP.gif animated GIF cloud background to go with edited Freepik image because mix-blend-mode:multiply will not mask out the non heterogenous bluish clouds in the image …
then to “third draft” … tweaking https://i.makeagif.com/media/8-11-2023/Xu_roP.gif animated GIF cloud background … …
then to “fourth draft” … establishing an SVG+XML (with SVG text emoji content) border-image for the bottom border representing the ground …
then to “fifth draft” … added acknowledgements for all the help …

Thanks to Image by brgfx on Freepik and https://i.makeagif.com/media/8-11-2023/Xu_roP.gif and https://procul.org/images/2025/Animated-Clouds-Gif/ and and https://au.pinterest.com/pin/587930926347995281/ and https://giphy.com/explore/trees-swaying-stickers

then to “sixth draft” … added https://au.pinterest.com/pin/587930926347995281/ animated GIF gymnast background and thereby proving that overlapping “iframe widgets” (helped out by mix-blend-mode:multiply presumably) was possible, and important …
then to “seventh draft” … added https://giphy.com/explore/trees-swaying-stickers giphy.com/explore/trees-swaying-stickers animated (and transparently backgrounded) webp swaying trees image along with tweaked Freepik image now animated GIF to animate the plane itself a little, in place, separate to the Javascript DOM based animation moving across the screen … for today’s final draft …

Stop Press

In tomorrow’s installment we allow for user defined content, and sharing, as per …

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.

Posted in eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial

Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial

Co-ordinate Cursor Mercator Projection TimeZone DateTime Tutorial

We’re baaaaack! And … loving it! Yes, back at GeoJson world map work as last talked about with Co-ordinate Cursor Mercator Projection External Javascript Tutorial, regarding your better than garden variety non-mobile cursor, today, we’re adding a …

  • current date time at functionality data addition … non-mobile cursor wise … in addition to existant …
  • latitude, longitude
  • responsive percentage left%, top%

… information carried along as a cursor over the Mercator Projection maps used in …

Huh?! No changes to the parents? Luckily, we have a scenario only needing changes to the lefttopcursor.js external Javascript.

What question did these changes seek to improve upon (shall we say, because a perfect solution is not on the cards, in any free way, here … but it works a lot of the time)?

Given latitude and longitude lookup current local time?

If you follow through on this research you will see there is no free native Javascript that neatly addresses solutions, directly, but, around here, because of the wonderful …

  • PHP in our lives … that means that …
  • PHP TimeZone functionality is also in our lives … and we’ve sort of memorized what PHP does here in Javascript terms … hence have a …
  • Javascript “one liner” variable made up of that PHP TimeZone data (if you will) … as a first call (we’ve decided if near enough to latitude and longitude of interest) … else falling back to …
  • TimeZone UTC hour offset = Math.floor(longitude / 15) … mostly in International waters

… as a paradigm we’ve used (where longlattotime() is called near the webpage document.body onload event timing) …


var yourtzlist="<option value=\"GMT\" data-geo=\"51.4934,0.0098,GMT,GB,+0\">GMT</option><option value=\"Africa/Abidjan\" data-geo=\"5.31666,-4.03334,GMT,CI,+0\">Africa/Abidjan</option><option value=\"Africa/Accra\" data-geo=\"5.55,-0.21667,GMT,GH,+0\">Africa/Accra</option> ... blah blah blah";
var tznamelists=[], tzlatlist=[], tzlonglist=[], tzoffsetlist=[], tzisolist=[], lastlongis='', lastlatis='', lasttzsuff='', lasttzname='', withingettz=false;

function toIso(date, timeZone) { // thanks to https://stackoverflow.com/questions/73576351/how-do-you-get-the-dst-time-adjustment-from-a-timezone
return new Date(date).toLocaleString('sv', { timeZone } ).replace(' ', 'T').replace(',', '.');
}

function getUTCOffset(year, month, day, hour, minute, second, timeZone) { // thanks to https://stackoverflow.com/questions/73576351/how-do-you-get-the-dst-time-adjustment-from-a-timezone
const date = [year, month, day].map(e => (e + '').padStart(2, '0')).join('-') + 'T' + [hour, minute, second].map(e => (e + '').padStart(2, '0')).join(':');
const dt = Date.parse(date + 'Z');
for(let offsetMinutes = -900; offsetMinutes <= 900; offsetMinutes += 15) {
const test = new Date(dt - offsetMinutes * 60000);
if (date === toIso(test, timeZone)) {
return offsetMinutes;
}
}
}

function getDSTDetails(zone, year) { // thanks to https://stackoverflow.com/questions/73576351/how-do-you-get-the-dst-time-adjustment-from-a-timezone
const jan = getUTCOffset(year, 1, 1, 0, 0, 0, zone);
const jul = getUTCOffset(year, 7, 1, 0, 0, 0, zone);
if (jan === jul) return { zone, year, standardOffsetMinutes: Math.min(jan, jul), dstOffsetMinutes: Math.max(jan, jul), janOffsetMinutes: jan, julOffsetMinutes: jul }
return { zone, year, standardOffsetMinutes: Math.min(jan, jul), dstOffsetMinutes: Math.max(jan, jul), dstChangeMinutes: Math.abs(jan - jul) }
}

function gettzsuff() {
var defoff=-999, wasdefoff=-999, deftz='';
if (withingettz) {
setTimeout(gettzsuff, 50);
} else {
var xlastlongis=lastlongis;
var xlastlatis=lastlatis;
withingettz=true;
defoff=Math.floor(eval('' + xlastlongis) / 15);
var nearestone=-1, nearestsum=-1, newsum=-1;
for (var iuh=1; iuh<tzlonglist.length; iuh++) {
if (nearestone < 0) {
nearestone=iuh;
wasdefoff=defoff;
try {
defoff=eval('' + tzoffsetlist[iuh]);
} catch(ytryt) {
console.warn('bad is ' + tzoffsetlist[iuh]);
defoff=wasdefoff;
}
nearestsum=eval(Math.abs(tzlonglist[iuh] - xlastlongis) + Math.abs(tzlatlist[iuh] - xlastlatis));
if (nearestsum < 10) {
deftz=tznamelists[iuh].replace('GMT','UTC');
lasttzname=' (near to TimeZone ' + deftz + ')';
}
} else {
newsum=eval(Math.abs(tzlonglist[iuh] - xlastlongis) + Math.abs(tzlatlist[iuh] - xlastlatis));
if (newsum < nearestsum) {
nearestone=iuh;
try {
defoff=eval('' + tzoffsetlist[iuh]);
} catch(ytrayt) {
console.warn('Bad is ' + tzoffsetlist[iuh]);
defoff=wasdefoff;
}
nearestsum=newsum;
if (nearestsum < 10) {
deftz=tznamelists[iuh].replace('GMT','UTC');
lasttzname=' (near to TimeZone ' + deftz + ')';
}
}
}
}
if (deftz != '' && nearestsum < 10) {
var xcd = new Date();
var xcyear = xcd.getUTCFullYear();
console.log('' + (new Date(new Date().toLocaleString("en-US", {timeZone: deftz}))).getTimezoneOffset() + ' ');
console.log(getDSTDetails(deftz, xcyear));
lasttzsuff=String.fromCharCode(32) + ' ' + ('' + (new Date(new Date().toLocaleString("en-US", {timeZone: deftz})))).split(' GMT')[0].split(' UTC')[0];
console.warn('0:' + lasttzsuff);
} else if (defoff != -999) {
lasttzname='';
var ud = new Date();
var uhour = ud.getUTCHours();
var umin = ud.getUTCMinutes();
var uday = ud.getUTCDay();
var usec = 0;
var udate = ud.getUTCDate();
var umonth = ud.getUTCMonth();
var uyear = ud.getUTCFullYear();
var newudt = new Date(Date.UTC(uyear, umonth, udate, uhour, umin, usec));
console.warn('defoff=' + defoff + ' RE ' + ('' + newudt));
if (('' + newudt).indexOf(' GMT+') != -1) {
defoff-=eval(('' + newudt).split(' GMT+')[1].substring(0,2));
defoff-=eval(eval(('' + newudt).split(' GMT+')[1].substring(2).substring(0,2).replace(/^0/g,'')) / 60);
} else if (('' + newudt).indexOf(' GMT-') != -1) {
defoff+=eval(('' + newudt).split(' GMT-')[1].substring(0,2));
defoff+=eval(eval(('' + newudt).split(' GMT-')[1].substring(2).substring(0,2).replace(/^0/g,'')) / 60);
}
console.warn(('' + (addHours(newudt,defoff))).split(' GMT')[0].split(' UTC')[0]);
lasttzsuff=String.fromCharCode(32) + ' ' + ('' + (addHours(newudt,defoff))).split(' GMT')[0].split(' UTC')[0];
console.warn('1:' + lasttzsuff);
}
//lasttzsuff=''; // temporary
withingettz=false;
}
}

function addHours(xdate, hoursToAdd) {
var newDate = new Date(xdate); // Create a copy to avoid modifying the original date
newDate.setHours(newDate.getHours() + hoursToAdd);
return newDate;
}

function longlattotime() {
var tzs=yourtzlist.split('" data-geo="');
for (var itzs=1; itzs<tzs.length; itzs++) {
tznamelists.push(tzs[eval(-1 + itzs)].split(' value="')[eval(-1 + tzs[eval(-1 + itzs)].split(' value="').length)]);
tzlatlist.push(tzs[itzs].split(',')[0]);
tzlonglist.push(tzs[itzs].split(',')[1]);
tzisolist.push(tzs[itzs].split(',')[3]);
if (eval('' + tzs[itzs].split(',').length) > 4) {
tzoffsetlist.push(tzs[itzs].split(',')[4].split('"')[0].replace('+',''));
} else {
tzoffsetlist.push('0');
}
}
console.warn('tzlonglist.length=' + tzlonglist.length);
}


function xmap(inidx) {
var outidx=eval('' + inidx);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscalex != 1.0) {
outidx=('' + eval(eval('' + altoriginx) + (eval('' + inidx) - eval('' + genoriginx)) * eval('' + altscalex)).toPrecision(15));
//document.title='' + inidx + ' fixed=' + (eval('' + inidx) - eval('' + genoriginx)) + ' then ' + outidx;
if (outidx.indexOf('.') != -1) {
lastlongis=outidx.split('.')[0] + '.' + outidx.split('.')[1].substring(0,2);
return lastlongis.replace(/0$/g,String.fromCodePoint(176)); //outidx.split('.')[0] + '.' + outidx.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
lastlongis=outidx;
return outidx.replace(/0$/g,String.fromCodePoint(176));
//} else {
// alert('Oops');
}
}
lastlongis='' + inidx;
return inidx;
}

function ymap(inidy) {
var outidy=eval('' + inidy);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscaley != 1.0) {
outidy=('' + eval(eval('' + altoriginy) + (eval('' + inidy) - eval('' + genoriginy)) * eval('' + altscaley)).toPrecision(15));
if (outidy.indexOf('.') != -1) {
lastlatis=outidy.split('.')[0] + '.' + outidy.split('.')[1].substring(0,2);
setTimeout(gettzsuff, 50);

return lastlatis.replace(/0$/g,String.fromCodePoint(176)); //outidy.split('.')[0] + '.' + outidy.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
lastlatis=outidy;
setTimeout(gettzsuff, 50);

return outidy.replace(/0$/g,String.fromCodePoint(176));
}
}
lastlatis='' + inidy;
setTimeout(gettzsuff, 50);

return inidy;
}

function toTimestamp(strDate) { // thanks to https://stackoverflow.com/questions/9873197/how-to-convert-date-to-timestamp
var datum = Date.parse(strDate);
return datum/1000;
}

function timestamped(inidt) {
if (inidt.split(':').length == 3) {
var uhour = inidt.split(':')[0].split(' ')[eval(-1 + inidt.split(':')[0].split(' ').length)];
var umin = inidt.split(':')[1];
inidt=inidt.split(' ' + uhour + ':' + umin)[0];
var uyear = inidt.split(' ')[eval(-1 + inidt.split(' ').length)];
var udate = ('0' + inidt.split(' ')[eval(-2 + inidt.split(' ').length)]).slice(-2);
var umonth = inidt.split(' ')[eval(-3 + inidt.split(' ').length)].substring(0,3).replace('Jan','01').replace('Feb','02').replace('Mar','03').replace('Apr','04').replace('May','05').replace('Jun','06').replace('Jul','07').replace('Aug','08').replace('Sep','09').replace('Oct','10').replace('Nov','11').replace('Dec','12');
return udate + '/' + umonth + '/' + uyear + ' ' + uhour + ':' + umin;
}
return inidt;
}

function lottery(valone, valtwo) {
var anum=Math.floor(Math.random() * 20);
if (valtwo != '' && anum <= 5) {
var bittoch=valone.split('</text>')[0].split('>')[eval(-1 + valone.split('</text>')[0].split('>').length)];
console.warn('4:' + valtwo.slice(-8).replace(/\:/g,' '));
return valone.replace(bittoch, timestamped(valtwo)); //valtwo.slice(-8).replace(/\:/g,' ');
}
console.warn('5:' + valone);
return valone;
}


Previous relevant Co-ordinate Cursor Mercator Projection External Javascript Tutorial is shown below.

Co-ordinate Cursor Mercator Projection External Javascript Tutorial

Co-ordinate Cursor Mercator Projection External Javascript Tutorial

For describing where you are on Earth humans have set up the …


Longitude,Latitude

(usually measured in degrees, especially in Mbeya and Madrid) system of describing positions, and on a Mercator Projection (ie. at school, the ones showing Greenland huge (when it is, in actuality, roughly, similar in surface area to Saudi Arabia)) that globe is slapped onto a 2d rectangular sheet of map (like perfectly peeling an apple but fixing up the tears in forming a rectangle, sort of), if you will …


360,-180

… wide,high starting up at the top left of that rectangle with Longitude,Latitude …


-180,90

… degrees. We’re saying the height is -180 because down the bottom right of this Mercator Projection arrangement the Longitude,Latitude is …


180,-90

Knowing all this and working out the webpage stuff as per usual we can, with a call, now catered for …


function xmap(inidx) {
var outidx=eval('' + inidx);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscalex != 1.0) {
outidx=('' + eval(eval('' + altoriginx) + (eval('' + inidx) - eval('' + genoriginx)) * eval('' + altscalex)).toPrecision(15));
//document.title='' + inidx + ' fixed=' + (eval('' + inidx) - eval('' + genoriginx)) + ' then ' + outidx;
if (outidx.indexOf('.') != -1) {
return outidx.split('.')[0] + '.' + outidx.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
return outidx.replace(/0$/g,String.fromCodePoint(176));
//} else {
// alert('Oops');
}
}
return inidx;
}

function ymap(inidy) {
var outidy=eval('' + inidy);
if (geno) {
if (altotherx != 0.0 || altothery != 0.0 || altoriginx != 0.0 || altoriginy != 0.0 || altscaley != 1.0) {
outidy=('' + eval(eval('' + altoriginy) + (eval('' + inidy) - eval('' + genoriginy)) * eval('' + altscaley)).toPrecision(15));
if (outidy.indexOf('.') != -1) {
return outidy.split('.')[0] + '.' + outidy.split('.')[1].substring(0,2).replace(/0$/g,String.fromCodePoint(176));
}
return outidy.replace(/0$/g,String.fromCodePoint(176));
}
}
return inidy;
}

… in a changed lefttopcursor.js external Javascript call of the ilk …


<script type=text/javascript src='//www.rjmprogramming.com.au/lefttopcursor.js?rand=876538765&scp=1F310&type=img&tl=-180,90&wh=360,-180'></script>

… affecting, further to yesterday’s Co-ordinate Cursor External Javascript Primer Tutorial, as per …

… to improve these web applications.


Previous relevant Co-ordinate Cursor External Javascript Primer Tutorial is shown below.

Co-ordinate Cursor External Javascript Primer Tutorial

Co-ordinate Cursor External Javascript Primer Tutorial

Today we’re taking what we learnt regarding …

co-ordinated cursors

(only regarding non-mobile platforms, alas) we implemented via the document.body onmousemove event logics in the recent Animated Plane Refuel Game Tutorial, and creating new external Javascript useful calleetool whereby …

  • not needing to implement it for that project above (except before launching into it making responsive design percentage friendly units into the mix via a changed “latest draft” Animated Plane Plane Refuel Game web application below), but doing a quick check to see that even if you did, the external Javascript would know enough to “lay off” … and ….
  • try out on yesterday’s Background Blend Mode Example web application (and which, eventually, we said “What the heck, so what if it gets an inapt cursor?!” and ended up creating a “second draft”) calling this new lefttopcursor.js external Javascript … via …

    <script type=text/javascript src='//www.rjmprogramming.com.au/lefttopcursor.js?scp=26fd'></script>

    … as an example call implementing cursor text with the ⛽ fuel pump emoji mentioned, on our macOS MAMP local Apache/PHP/MySql web server, and you can see working within today’s animated GIF presentation
  • try out on our changed do_away_with_the_boring_bits.html Try Your Own HTML web application‘s iframe HTML validator using it’s srcdoc

    <iframe srcdoc="<html><head><script type=text/javascript src='//www.rjmprogramming.com.au/lefttopcursor.js?rand=7635476'></script></head><body style=width:100%;height:650px;> </body></html>" data-src='about:blank' name='ihtmlcontent' id='ihtmlcontent' style='z-index:99;height:650px; background-color:lightblue;'></iframe>

    … attribute

… all happening.

It being external Javascript we wanted to see it working from a localhost web browser address bar URL call, and it did, making it a tool, to our mind.


Previous relevant Animated Plane Refuel Game Tutorial is shown below.

Animated Plane and Coconut Hunt Game Nuances Tutorial

Animated Plane Refuel Game Tutorial

Today we wondered how best to involve the …

  • plane … mainly, but perhaps also the …
  • gymnast … with a guest starring role …

… in an online game in our recent Animated Plane and Coconut Hunt Game Nuances Tutorial‘s web application, because their existence to do with Hunt Games seems a bit obscure.

And so, we thought, you see those games where characters get strength by picking up objects they “run into” or “run over” and we thought …

Plane Refuel Game

(where the longer the flight survives the more skillful the player) as a result of that thinking, plus being able to find an apt emoji ⛽ for the fuel pump we wanted to base the game around, along with an HTML progress element to inform the user regarding how much fuel is left, in a changed “latest draft” Animated Plane Plane Refuel Game web application below!


Previous relevant Animated Plane and Coconut Hunt Game Nuances Tutorial is shown below.

Animated Plane and Coconut Hunt Game Nuances Tutorial

Animated Plane and Coconut Hunt Game Nuances Tutorial

Today’s a day of nuanced progress, after yesterday’s Coconut Hunt Game Tutorial‘s “filling in sideways” work on our Animated Plane and Coconut Hunt Game web application. Today, we …

  • fixed some document.body.title annoyances whereby it would appear too often
  • worked on the default A option textarea via …
    1. some “panda 🐼 led recovery” modelling of a p emoji usage (with animation) and span emoji usage (without animation) … and …
    2. modelling of how iframe onload event can be used to develop dynamic Javascript (the default example changing the coconut 🥥 hunt into a bear 🐻 hunt?!) … as opposed to a document.createElement(‘script’) alternative approach
  • fixed some window.open too small size annoyances
  • allowed for screen co-ordinates cursor (on non-mobile), via onmousemove event logic, to assist intrepid users going above and beyond “overlay” positioning their own elements via position:absolute; left:?; top:?; in A option textareas
  • allowed for toggling of non-mobile cursor between as above and crosshair via right click
  • allowed for the last left:?; top:?; as above detected be remembered and involve itself as the default position:absolute; “overlay” positioning of the A option textarea default “panda 🐼 led recovery” emoji of above
  • allow for 8 seconds of time for a user to change default coconut 🥥 emoji to some other text via contenteditable=true ahead of the Hunt Game starting … thanks to this useful link regarding hiding a contenteditable=true focus border
  • allow for sharing of the Hunt Game
  • Hunt Game sound effects

Feel free to try these tweaks to our Animated Plane and Coconut Hunt Game, in a nuanced “latest draft” Animated Plane Coconut Hunt Game web application below!


Previous relevant Coconut Hunt Game Tutorial is shown below.

Coconut Hunt Game Tutorial

Coconut Hunt Game Tutorial

Are you a reader who has been amused or bemused by the word Game being in the blog posting titles lately, up to yesterday’s Animated Plane Game User Animations and Styling Tutorial, when No Game really, about any of it? Well, today, it’s …

Game On

Do you like coconuts? Can I ask you, have you ever looked into a coconut, and asked yourself …

I shell always love you.

? Well, have we got the game for you?! Start the ball rollingshell shaking via the first click/top on the coconut fallen from the tree. And from there, it’s a fast reactions game, to score well! Good luck, in the changed “latest draft” Animated Plane Coconut Hunt Game web application below!


Previous relevant Animated Plane Game User Animations and Styling Tutorial is shown below.

Animated Plane Game User Animations and Styling Tutorial

Animated Plane Game User Animations and Styling Tutorial

On top of yesterday’s Animated Plane Game User Content Sharing Tutorial‘s honing in on the five “nouns” of interest …

  • trees
  • plane
  • gymnast
  • clouds
  • ground

… today we wanted to offer two more user controllable parts to this Animated Plane Game web application, those being …

  • CSS styling … easy, as CSS can be dynamically added to a web application at the clientside, as the Javascript is executing … and, a bit more of a learning curve for beginners is …
  • user animations … we’re envisaging, in it’s “easiest to understand encapsulation for a newbie” uses …
    1. @keyframes
    2. transition

    … a whole big wooooorrrrlllldddd of animation study just by itself (and in order for modelling to, perhaps, help we used an example from this excellent link, thanks, as the default option A textarea usage model)

… but a hell of a lot easier for a user to establish than some arcane Javascript DOM animations involving setTimeout or setInterval timers?!

For these two new ideas, popup textarea windows appear to give the user plenty of space to play around in. As ever, email and SMS can follow up for that user to share with others what their animation ideas are, perhaps far removed from the original plane and gymnast scenario by the time they finish. And here it may be pertinent to point out that even using hashtag emailing (and even more so with SMSing) there must be message size limits that will stop you event-u-al-ly!

Try this in the changed “latest draft” Animated Plane Game web application below.

Did you know?

In yesterday’s “noun” work we talked about “content” defined by the user in terms of real references to media data URIs or URLs. Well, the other way a user can now affect “content” is via CSS. Below we make the plane and gymnast disappear via the C (for CSS styling) option (that can take you to a popup window textarea where you can Apply this) …


<style>
#myif { /* plane */
display:none; /* other choice could be visibility:hidden; */
}

#mytwoif { /* gymnast */
visibility:hidden; /* other choice could be display:none; */
}
</style>


Previous relevant Animated Plane Game User Content Sharing Tutorial is shown below.

Animated Plane Game User Content Sharing Tutorial

Animated Plane Game User Content Sharing Tutorial

Yesterday’s Animated Plane Game Primer Tutorial set up five “nouns” of interest …

  • trees
  • plane
  • gymnast
  • clouds
  • ground

… each of which has a relationship to a piece of media content. The border-image (ie. ground) content aspects we allow a user to define emoji text for, but the rest are associated with a data URI or URL.

Today’s work is to allow the user to specify these “content” data items themselves, as well as share this via email or SMS to another user, with those user “content” data items recreated for the recipient user clicking the email or SMS link containing those hashtagged user data components. Later we hope to expand the functionality more, from today’s …


function getsrc(fromoh) {
var forvpre='Currently this content points at ... ' + String.fromCharCode(10);
var forvsuf=String.fromCharCode(10) + 'Enter an alternative content URL (can be clipart style data URI you see often using Google Image (Copy Image Address via right click) Searches) ... or ... ' + String.fromCharCode(10) + String.fromCharCode(10) + '1[:URL] for trees, 2[:URL] for plane, 3[:URL] for gymnast, 4[:URL] for clouds, 5[:emoji(s)] for ground, E for email, S for SMS';
if (fromoh.indexOf(' src="//') != -1) {
return forvpre + document.URL.split('//')[0] + fromoh.split(' src="')[1].split('"')[0] + forvsuf;
} else if (fromoh.indexOf(" src='//") != -1) {
return forvpre + document.URL.split('//')[0] + fromoh.split(" src='")[1].split("'")[0] + forvsuf;
} else if (fromoh.indexOf(" src=//") != -1) {
return forvpre + document.URL.split('//')[0] + fromoh.split(" src=")[1].split(" ")[0].split(">")[0] + forvsuf;
} else if (fromoh.indexOf(' src="') != -1) {
return forvpre + fromoh.split(' src="')[1].split('"')[0] + forvsuf;
} else if (fromoh.indexOf(" src='") != -1) {
return forvpre + fromoh.split(" src='")[1].split("'")[0] + forvsuf;
} else if (fromoh.indexOf(" src=") != -1) {
return forvpre + fromoh.split(" src=")[1].split(" ")[0].split(">")[0] + forvsuf;
}
return fromoh;
}

function yourprompt(ino, intlis) {
var ei=-1, si=-1;
isac=true;
var opsd=prompt(getsrc(ino.outerHTML), '');
if (opsd == null) { isac=false; return false; }
if (opsd.trim() != '') {
switch (opsd.substring(0,1).toLowerCase().replace('+','s')) {
case '1': // trees
if ((opsd + ' ').substring(0,2) == '1:') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + (opsd + ' ').substring(2) + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where trees are.', '');
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
}
break;


case '2': // plane
if ((opsd + ' ').substring(0,2) == '2:') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where plane is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '3': // gymnast
if ((opsd + ' ').substring(0,2) == '3:') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where gymnast is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '4': // clouds
if ((opsd + ' ').substring(0,2) == '4:') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps via Google image search) data URI or URL suiting where cloud background image is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '5': // ground
if ((opsd + ' ').substring(0,2) == '5:') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + (opsd + ' ').substring(2) + suffixbiu + '") !important; </sty' + 'le>'
} else {
opsd=prompt('Enter your (probably quite long) emoji (we are guessing) border image text.', '');
if (opsd != null) {
if (opsd != '') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + suffixbiu + '") !important; </sty' + 'le>'
} else {
groundalt='&groundalt='; // + encodeURIComponent(opsd);
document.body.style.borderImage='none';
document.body.style.borderBottom='1px solid transparent';
document.body.style.borderBottomWidth='0px';
//document.body.innerHTML+='<sty' + 'le> body { border-bottom-width:0px !important; } </sty' + 'le>';
}
}
}
break;

case 'e': // email
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.trim().indexOf('@') != -1) {
anchor.href = 'mailto:' + opsd.split('@')[0].split(' ')[eval(-1 + opsd.split('@')[0].split(' ').length)] + opsd.split(opsd.split('@')[0])[1].split(' ')[0] + '?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'mailto:?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

case 's': // SMS
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.substring(0,1).toLowerCase() == '+') {
anchor.href = 'sms:' + opsd.split(' ')[0] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else if (opsd.indexOf(' ') != -1) {
anchor.href = 'sms:' + opsd.split(' ')[eval(-1 + opsd.split(' ').length)] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

default:
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
break;
}
} else {
setTimeout(function(){ ino.click(); }, 100); return true;
}
isac=false;
return false;
}

function anyprompt(opsd) {
if (opsd.trim() != '') {
opsd=opsd;
switch (opsd.substring(0,1).toLowerCase().replace('+','s')) {
case '1': // trees
if ((opsd + ' ').substring(0,2) == '1:') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + (opsd + ' ').substring(2) + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where trees are.', '');
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
}
break;

case '2': // plane
if ((opsd + ' ').substring(0,2) == '2:') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where plane is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '3': // gymnast
if ((opsd + ' ').substring(0,2) == '3:') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where gymnast is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '4': // clouds
if ((opsd + ' ').substring(0,2) == '4:') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps via Google image search) data URI or URL suiting where cloud background image is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '5': // ground
if ((opsd + ' ').substring(0,2) == '5:') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + (opsd + ' ').substring(2) + suffixbiu + '") !important; </sty' + 'le>'
} else {
opsd=prompt('Enter your (probably quite long) emoji (we are guessing) border image text.', '');
if (opsd != null) {
if (opsd != '') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + suffixbiu + '") !important; </sty' + 'le>'
} else {
groundalt='&groundalt='; // + encodeURIComponent(opsd);
document.body.style.borderImage='none';
document.body.style.borderBottom='1px solid transparent';
document.body.style.borderBottomWidth='0px';
//document.body.innerHTML+='<sty' + 'le> body { border-bottom-width:0px !important; } </sty' + 'le>';
}
}
}
break;

case 'e': // email
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.trim().indexOf('@') != -1) {
anchor.href = 'mailto:' + opsd.split('@')[0].split(' ')[eval(-1 + opsd.split('@')[0].split(' ').length)] + opsd.split(opsd.split('@')[0])[1].split(' ')[0] + '?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'mailto:?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

case 's': // SMS
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.substring(0,1).toLowerCase() == '+') {
anchor.href = 'sms:' + opsd.split(' ')[0] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else if (opsd.indexOf(' ') != -1) {
anchor.href = 'sms:' + opsd.split(' ')[eval(-1 + opsd.split(' ').length)] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

default:
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
break;
}
}
}

function ourprompt(ino, intlis) {
var ei=-1, si=-1;
isac=true;
var opsd=null;
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
opsd=prompt(intlis + String.fromCharCode(10) + String.fromCharCode(10) + intlis, '');
} else {
opsd=prompt(getsrc(document.getElementById('myimg').outerHTML), '');
}
if (opsd == null) { isac=false; return false; }
if (opsd.trim() != '') {
opsd=opsd;
switch (opsd.substring(0,1).toLowerCase().replace('+','s')) {
case '1': // trees
if ((opsd + ' ').substring(0,2) == '1:') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + (opsd + ' ').substring(2) + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where trees are.', '');
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
}
break;

case '2': // plane
if ((opsd + ' ').substring(0,2) == '2:') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where plane is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
planealt='&planealt=' + encodeURIComponent(opsd);
document.getElementById('myif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '3': // gymnast
if ((opsd + ' ').substring(0,2) == '3:') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps clipart via Google image search) data URI or URL suiting where gymnast is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
gymnastalt='&gymnastalt=' + encodeURIComponent(opsd);
document.getElementById('mytwoif').style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '4': // clouds
if ((opsd + ' ').substring(0,2) == '4:') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + ((opsd + ' ').substring(2)).replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
} else {
opsd=prompt('Enter your (perhaps via Google image search) data URI or URL suiting where cloud background image is.', '');
if (opsd != null) {
if (opsd.trim() != '') {
cloudsalt='&cloudsalt=' + encodeURIComponent(opsd);
document.body.style.backgroundImage='url(' + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + ')';
}
}
}
break;

case '5': // ground
if ((opsd + ' ').substring(0,2) == '5:') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + (opsd + ' ').substring(2) + suffixbiu + '") !important; </sty' + 'le>'
} else {
opsd=prompt('Enter your (probably quite long) emoji (we are guessing) border image text.', '');
if (opsd != null) {
if (opsd != '') {
groundalt='&groundalt=' + encodeURIComponent(opsd);
document.body.innerHTML+='<sty' + 'le> body { border-image:url("' + prefixbiu + opsd.replace(/^http\:/g,'').replace(/^https\:/g,'') + suffixbiu + '") !important; </sty' + 'le>'
} else {
groundalt='&groundalt='; // + encodeURIComponent(opsd);
document.body.style.borderImage='none';
document.body.style.borderBottom='1px solid transparent';
document.body.style.borderBottomWidth='0px';
//document.body.innerHTML+='<sty' + 'le> body { border-bottom-width:0px !important; } </sty' + 'le>';
}
}
}
break;

case 'e': // email
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.trim().indexOf('@') != -1) {
anchor.href = 'mailto:' + opsd.split('@')[0].split(' ')[eval(-1 + opsd.split('@')[0].split(' ').length)] + opsd.split(opsd.split('@')[0])[1].split(' ')[0] + '?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'mailto:?subject=My%20Animation&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

case 's': // SMS
opsd=opsd.replace(/\:/g,' ');
anchor = document.createElement('a');
if (opsd.substring(0,1).toLowerCase() == '+') {
anchor.href = 'sms:' + opsd.split(' ')[0] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else if (opsd.indexOf(' ') != -1) {
anchor.href = 'sms:' + opsd.split(' ')[eval(-1 + opsd.split(' ').length)] + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
} else {
anchor.href = 'sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#' + treesalt + planealt + gymnastalt + cloudsalt + groundalt);
}
anchor.style.display='none';
document.body.appendChild(anchor);
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
break;

default:
if (opsd != null) {
if (opsd.trim() != '') {
treesalt='&treesalt=' + encodeURIComponent(opsd);
document.getElementById('myimg').src=('' + opsd + '').replace(/^http\:/g,'').replace(/^https\:/g,'');
}
}
break;
}
} else {
setTimeout(function(){ ino.click(); }, 100); return true;
}
isac=false;
return false;
}

… in the changed “eighth draft” Animated Plane Game web application.


Previous relevant Animated Plane Game Primer Tutorial is shown below.

Animated Plane Game Primer Tutorial

Animated Plane Game Primer Tutorial

The mix-blend-mode:multiply; discoveries (along with those naive previous usage without realizing it’s implications) we made creating Periodic Table Image Map Primer Tutorial recently has opened up new “vistas of possibility” (VOP, of course) for us, and has inspired us to give “just Javascript and CSS and HTML animated games” (aided in large part by clipart free content components) another go …

… with a “widget feel” now realizable, for us, knowing that white backgrounded HTML iframe content no longer has to hold us back piecing together animations (in an “OOP feeling” way) consisting of …

  • base webpage CSS and HTML and Javascript (DOM, also helping out the control of) …
  • HTML iframe components (and in our case the image content is it’s background image with background-size:contain; and background-repeat:no-repeat; along with a specific iframe width and height) for any one “noun” (or class of object) in your game storyboard … if you will … if you will … if you will … and …
  • HTML img components in a similar vein … but today’s trees did not need mix-blend-mode:multiply; because the originator made the background transparent (ie. another option with all this “animated pieces thinking”)

Animation(s) can be CSS @keyframe transitions (though not yet with animation above) or Javascript DOM logic via setTimeout (or setInterval) timers or animated GIF/webp content or, we daresay, many other approaches.

We’re going to tabularize below “how we got to the result above” below …

We started with a “first draft” … getting Freepik image plane image animated with a rudimentary green border-bottom representing the ground …
then to “second draft” … adding https://i.makeagif.com/media/8-11-2023/Xu_roP.gif animated GIF cloud background to go with edited Freepik image because mix-blend-mode:multiply will not mask out the non heterogenous bluish clouds in the image …
then to “third draft” … tweaking https://i.makeagif.com/media/8-11-2023/Xu_roP.gif animated GIF cloud background … …
then to “fourth draft” … establishing an SVG+XML (with SVG text emoji content) border-image for the bottom border representing the ground …
then to “fifth draft” … added acknowledgements for all the help …

Thanks to Image by brgfx on Freepik and https://i.makeagif.com/media/8-11-2023/Xu_roP.gif and https://procul.org/images/2025/Animated-Clouds-Gif/ and and https://au.pinterest.com/pin/587930926347995281/ and https://giphy.com/explore/trees-swaying-stickers

then to “sixth draft” … added https://au.pinterest.com/pin/587930926347995281/ animated GIF gymnast background and thereby proving that overlapping “iframe widgets” (helped out by mix-blend-mode:multiply presumably) was possible, and important …
then to “seventh draft” … added https://giphy.com/explore/trees-swaying-stickers giphy.com/explore/trees-swaying-stickers animated (and transparently backgrounded) webp swaying trees image along with tweaked Freepik image now animated GIF to animate the plane itself a little, in place, separate to the Javascript DOM based animation moving across the screen … for today’s final draft …

Stop Press

In tomorrow’s installment we allow for user defined content, and sharing, as per …

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.

Posted in eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , | Leave a comment

Font Awesome Icons Primer Tutorial

Font Awesome Icons Primer Tutorial

Font Awesome Icons Primer Tutorial

Further to the work of HTML Icons Primer Tutorial we’re going to include some Font Awesome icons into the mix of the look of our RJM Programming Landing Page today.

In this context, on a webpage, regarding small button style elements, these Font Awesome …

  • icons … can be an alternative to …
  • inhouse image thumbnails …
  • other image thumbnails …
  • emoji buttons and/or links …
  • SVG buttons …
  • background image arrangements to button like HTML elements

… where the Font Awesome website was our means towards …

  1. Information about the products …
  2. Download functionality … and then …
  3. Zip in Downloads folder we unzipped to a new folder …
  4. Uploaded to the RJM Programming web server … and regarding the PHP …
  5. Landing Page we called the CSS link to Font Awesome suite Uploaded above … and got great help from Search functionality back at Font Awesome website to code for …
  6. Navigation bar menu improvements to internationalization credentials and self-help aspects to usage … such as

    <a href="./Welcome.html" class="w3-bar-item w3-button w3-padding-large w3-white logo">Home <i class="fa fa-solid fa-house"></i></a>
    <a href="./Welcome.html" class="w3-bar-item w3-button w3-hide-small w3-padding-large w3-hover-white xwelcome">Welcome <i class="fa-solid fa-door-open"></i></a>
    <a href="./About_Us.html" class="w3-bar-item w3-button w3-hide-small w3-padding-large w3-hover-white xabout">About Us <i class="fa-solid fa-address-card"></i></a>
    <a href="./Contact_Us.html" class="w3-bar-item w3-button w3-hide-small w3-padding-large w3-hover-white xcontact">Contact Us <i class="fa-solid fa-address-book"></i></a>
    <a href="./Services.html" class="w3-bar-item w3-button w3-hide-small w3-padding-large w3-hover-white xservices">Services <i class="fa-solid fa-bell-concierge"></i></a>
    <a href="./News.html" class="w3-bar-item w3-button w3-hide-small w3-padding-large w3-hover-white xnews">News <i class="fa-solid fa-newspaper"></i></a>
    <a href="./Guestbook.html" class="w3-bar-item w3-button w3-hide-small w3-padding-large w3-hover-white xguestbook">Guestbook <i class="fa-solid fa-book"></i></a>
    <a href="./Link.html" class="w3-bar-item w3-button w3-hide-small w3-padding-large w3-hover-white xlinks">Links <i class="fa-solid fa-link"></i></a>

… which you can now see on RJM Programming’s Landing Page.


Previous relevant HTML Icons Primer Tutorial is shown below.

HTML Icons Primer Tutorial

HTML Icons Primer Tutorial

Today we’re delving further into the HTML Icons start we made with yesterday’s Negative Margin CSS Primer Tutorial.

W3school’s CSS Icons

How To Add Icons

The simplest way to add an icon to your HTML page, is with an icon library, such as Font Awesome.

Add the name of the specified icon class to any inline HTML element (like <i> or <span>).

All the icons in the icon libraries below, are scalable vectors that can be customized with CSS (size, color, shadow, etc.)

… thanks, mentions three of the major players for you to explore the HTML “i” (as one tag idea) Icons …

With this in mind we’ve written a proof of concept html_icons.html web application to help newbies, here, to explore some more for themselves. We hope it helps, and will leave you with the chance to try it below …


Previous relevant Negative Margin CSS Primer Tutorial is shown below.

Negative Margin CSS Primer Tutorial

Negative Margin CSS Primer Tutorial

That HTML editor (in the form of a textarea element) of yesterday’s HTML Editor Inline HTML Email Tutorial may help you learn some …

  • HTML design
  • Javascript dynamics … and …
  • CSS styling

… and though for most programmers the Javascript will be the most fun and most demanding aspect to learn regarding the client side of the “client/server” web application model. The most “ooh” “aahs” of interest, though, and so motivation to continue learning, are likely to come from an appreciation of CSS styling.

With today’s web application we try to help the user to see where these “giant wooooorrrrlllllddds” meet. Do you remember XML on the Fly via PHP Primer Tutorial‘s observation …

To get from “DOM” thinking to “DOMDocument” thinking, reminded us of that CSS “mapping” to Javascript DOM idea that you substitute the CSS “-” (minus) and next lowercase letter for a Javascript DOM capital letter …

… a Javascript DOM hint for dynamic CSS styling used in (all the Javascript scripting of negative_margins.html) …


<script type='text/javascript'>
function leftchange(iotb) {
document.getElementById('animg').style.marginLeft='' + iotb.value + 'px';
}

function topchange(iotb) {
document.getElementById('animg').style.marginTop='' + iotb.value + 'px';
}

function cdov(iotb) {
document.getElementById('divencaser').style.overflow='' + iotb.value;
}

function domit(incl) {
var bits=incl.split('-');
var retval=bits[0];
for (var ibits=1; ibits<bits.length; ibits++) {
retval+=(bits[ibits] + ' ').substring(0,1).trim().toUpperCase() + (bits[ibits] + ' ').substring(1).trim().toLowerCase();
}
return retval;
}

function cssdiv(iotb) {
var clauses=iotb.value.split(';');
for (var ic=0; ic<clauses.length; ic++) {
if (clauses[ic].indexOf(':') != -1) {
eval("document.getElementById('divencaser').style." + domit(clauses[ic].split(':')[0]) + '="' + clauses[ic].split(':')[1].replace(/\"/g,'').replace(/\'/g,'') + '";');
}
}
}

function cssimg(iotb) {
var clauses=iotb.value.split(';');
for (var ic=0; ic<clauses.length; ic++) {
if (clauses[ic].indexOf(':') != -1) {
eval("document.getElementById('animg').style." + domit(clauses[ic].split(':')[0]) + '="' + clauses[ic].split(':')[1].replace(/\"/g,'').replace(/\'/g,'') + '";');
}
}
}

</script>

And in the spirit of trying to get early CSS learners interested in webpage styling we set up a “nester DIV element” nesting a “nested IMG element” with negative “margin-left” and “margin-top”. We’ve added a “nester DIV element” user controllable “overflow” property to contextualize this a bit. Change these settings, and we defy you not to be a tad interested. The two textboxes open to whatever CSS you want to apply fit into those blue Javascript functions above that you can call into action with today’s live run link.

Lastly, there is a first, for us, with today’s web application, our first “tipping toes into the ocean” regarding the HTML icon element topic we started our research about at CSS Icons discussion regarding the “i” HTML element (as an alternative to emojis, to our mind). Within that we gave “Font Awesome Icons” a go, search through the external Javascript (script) …


<script src="//kit.fontawesome.com/a076d05399.js"></script>

… searching through for some apt icon for “margin talk”, opting for


<h1 style='z-index:200;'>Negative Margins Etcetera - RJM Programming - April, 2020 ... <i class="fas fa-border-style" style="font-size:96px;color:blue;"></i></h1>

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.

Posted in eLearning, GUI, Installers, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , | Leave a comment

CSS Tooltip Primer Tutorial

CSS Tooltip Primer Tutorial

CSS Tooltip Primer Tutorial

Again, CSS themes of interest regarding yesterday’s CSS Image Clip and Shape Outside Primer Tutorial are here for today’s Tooltip tutorial, where we have chosen the day before’s CSS Variables Textarea Tutorial‘s web application to be the one to work with and expand.

What’s a tooltip? Wikipedia says …

The tooltip, also known as infotip or hint, is a common graphical user interface (GUI) element in which, when hovering over a screen element or component, a text box displays information about that element, such as a description of a button’s function, what an abbreviation stands for, or the exact absolute time stamp over a relative time (“… ago”). In common practice, the tooltip is displayed continuously as long as the user hovers over the element or the text box provided by the tool.[1] It is sometimes possible for the mouse to hover within the text box provided to activate a nested tooltip, and this can continue to any depth, often with multiple text boxes overlapped.

And what interests us the most about the concept?

Well, we’re always looking for ways to explain the workings of web applications via their webpage HTML elements’ title attributes, which, on non-mobile can happen hovering over the element. But this does not work for mobile. There, and for mobile, we, more and more, use textbox placeholder attributes to help.
Tooltips are another approach and call on CSS like …

/* Show the tooltip text on hover */
.tooltip:hover .tooltiptext {
opacity: 0.3;
visibility: visible;
}

… thanks to W3schools here, to go somewhere downup the roadavenue, for some types of HTML elements, like the ones with a proper innerHTML attribute (but not textarea with it’s special relationship between innerHTML and value … so there, we had to nest the textarea in a div element)

You could statically arrange the tooltips, but, for us here today, we’ve allowed for a dropdown selection to make a dynamically created className association happen


function anal(selo) {
var newst='';
if (selo.value.trim() != '') {
newst='<style> @property --my' + selo.value.toLowerCase() + 'Color { syntax: "<color>"; inherits: true; initial-value: ' + ('#' + document.getElementById('mycolourpicker').value).replace('##','#') + '; } #' + selo.value.toLowerCase() + ' { background-color: var(--my' + selo.value.toLowerCase() + 'Color); } .tooltip { position: relative; border-bottom: 1px dotted black; cursor: pointer; } .tooltiptext { visibility: hidden; width: 130px; background-color: black; color: #ffffff; text-align: center; padding: 5px 0; border-radius: 6px; position: absolute; z-index: 1; } .tooltip:hover .tooltiptext { opacity: 0.3; visibility: visible; } </style>';
if (selo.value == selo.value.toUpperCase()) {
document.getElementById('myta').value=newst.replace(/\{/g,'{ ' + String.fromCharCode(10)).replace(/\}/g,'} ' + String.fromCharCode(10) + String.fromCharCode(10)).replace(/\;/g,'; ' + String.fromCharCode(10))
doit(document.getElementById('myta').value);
} else if (selo.value == selo.value.toLowerCase()) {
document.getElementById('myta').value=newst.replace(/\{/g,'{ ' + String.fromCharCode(10)).replace(/\}/g,'} ' + String.fromCharCode(10) + String.fromCharCode(10)).replace(/\;/g,'; ' + String.fromCharCode(10))
} else if (('' + document.getElementById(selo.value.toLowerCase()).className) != '') {
if (('' + document.getElementById(selo.value.toLowerCase()).className).indexOf('tooltip') == -1) {
document.getElementById(selo.value.toLowerCase()).className+=' tooltip';
if (('' + document.getElementById(selo.value.toLowerCase()).title) == '') {
document.getElementById(selo.value.toLowerCase()).title='Hovering over ' + selo.value.toLowerCase();
}
document.getElementById(selo.value.toLowerCase()).innerHTML+='<span id=myspan' + lastttnum + ' class="tooltiptext">Hovering over ' + selo.value.toLowerCase().replace(/^divta$/g,'myta') + '<br></span>';
lastttnum++;
}
} else {
document.getElementById(selo.value.toLowerCase()).className='tooltip';
if (('' + document.getElementById(selo.value.toLowerCase()).title) == '') {
document.getElementById(selo.value.toLowerCase()).title='Hovering over ' + selo.value.toLowerCase();
}
document.getElementById(selo.value.toLowerCase()).innerHTML+='<span id=myspan' + lastttnum + ' class="tooltiptext">Hovering over ' + selo.value.toLowerCase().replace(/^divta$/g,'myta') + '<br></span>';
lastttnum++;
}

}
}

… to make an existant HTML element one that the mobile user taps (to :hover) and the non-mobile user just hovers over, to see the resultant tooltip adjacent to the HTML element being explained, in this changed second draft CSS @property variables and tooltips web application, also below


Previous relevant CSS Image Clip and Shape Outside Primer Tutorial is shown below.

CSS Image Clip and Shape Outside Primer Tutorial

CSS Image Clip and Shape Outside Primer Tutorial

Further to the CSS themes of interest regarding yesterday’s CSS Variables Textarea Tutorial, today we continue that “theme” regarding …


CSS Image Clip and Shape Outside

… inspiration we got from this W3school very useful webpage, thanks.

With this work, there are two display aspects at play …

CSS Property Applicability regarding Shape …
Circle Ellipse Polygon
clip-path Yes Yes Yes
shape-outside Yes Yes No

… which you can play around (again involving user input textarea CSS styling elements) with this first draft CSS Image Clip and Shape Outside web application


Previous relevant CSS Variables Textarea Tutorial is shown below.

CSS Variables Textarea Tutorial

CSS Variables Textarea Tutorial

Today we’ve got a “proof of concept” CSS web application idea that is inspired by this W3school’s webpage, thanks, but adding user interaction functionality, regarding …


CSS @property variables

… bringing some Javascript feeling logic excitement to CSS styling smarts. You can try this user interactive approach with this first draft CSS @property variables web application

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.

Posted in eLearning, Event-Driven Programming | Tagged , , , , , , , , , , , , , | Leave a comment

CSS Image Clip and Shape Outside Primer Tutorial

CSS Image Clip and Shape Outside Primer Tutorial

CSS Image Clip and Shape Outside Primer Tutorial

Further to the CSS themes of interest regarding yesterday’s CSS Variables Textarea Tutorial, today we continue that “theme” regarding …


CSS Image Clip and Shape Outside

… inspiration we got from this W3school very useful webpage, thanks.

With this work, there are two display aspects at play …

CSS Property Applicability regarding Shape …
Circle Ellipse Polygon
clip-path Yes Yes Yes
shape-outside Yes Yes No

… which you can play around (again involving user input textarea CSS styling elements) with this first draft CSS Image Clip and Shape Outside web application


Previous relevant CSS Variables Textarea Tutorial is shown below.

CSS Variables Textarea Tutorial

CSS Variables Textarea Tutorial

Today we’ve got a “proof of concept” CSS web application idea that is inspired by this W3school’s webpage, thanks, but adding user interaction functionality, regarding …


CSS @property variables

… bringing some Javascript feeling logic excitement to CSS styling smarts. You can try this user interactive approach with this first draft CSS @property variables web application

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Not Categorised | Tagged , , , , , , , , , , , , , , , , , | Leave a comment

CSS Variables Textarea Tutorial

CSS Variables Textarea Tutorial

CSS Variables Textarea Tutorial

Today we’ve got a “proof of concept” CSS web application idea that is inspired by this W3school’s webpage, thanks, but adding user interaction functionality, regarding …


CSS @property variables

… bringing some Javascript feeling logic excitement to CSS styling smarts. You can try this user interactive approach with this first draft CSS @property variables web application

If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming | Tagged , , , , , , , , , , , , | Leave a comment

Text Background Clip Animation Emoji Overlay HTML Entities Tutorial

Text Background Clip Animation Emoji Overlay HTML Entities Tutorial

Text Background Clip Animation Emoji Overlay HTML Entities Tutorial

Further to yesterday’s Text Background Clip Animation Emoji Overlay SVG CSS Tutorial we think …

  • regarding topics like HTML Entities … once in the mood …

    Be like a dog with a bone

  • when concentrating on a topic you can get closer to cracking (at least until the next campaign), so to speak

It’s one of those topics where, sure, somebody with weird emoji data requirements can make yesterday’s starting logic fail, and in cases like this, we think …

  1. go back to basics …
  2. incorporate the Javascript functions you want to improve …
  3. into a new “proof of concept” web application … which …
  4. just concentrates on the isolated scenario you are talking about … notwithstanding …
  5. optionally, but preferably, tests the work in a total cycle between “real text data” and “HTML Entity data representation” back and forth, both ways
  6. … as does our new “proof of concept” web application

    … the construction of which, indeed, did teach us a lot … and there was a lot to learn, again.

    And then, plonking this back into the changed seventh draft version of a “Text Background Clip” client web application

    1. first and foremost, did not seem to make anything that used to work, go backwards … plus …
    2. made more cases of user entry we could think of, work better, including mixes of emoji and ansi textual data

    … but “comment away” if you find a failure!


    Previous relevant Text Background Clip Animation Emoji Overlay SVG CSS Tutorial is shown below.

    Text Background Clip Animation Emoji Overlay SVG CSS Tutorial

    Text Background Clip Animation Emoji Overlay SVG CSS Tutorial

    The SVG we are using for sharing functionality, as we talked about yesterday with Text Background Clip Animation Emoji Overlay SVG Sharing Tutorial has another amazing talent. You can adjust it’s display in the same way the HTML of a body element can be adjusted, via embedding CSS inline style element data inside that SVG (or body element) innerHTML and in so doing continue it’s independent usefulness.

    • this extension to the right hand textarea functionality consisted of making this style element embedding happen within the SVG that in turn is within the iframe element hosting it … as one of today’s jobs, with the other being …
    • as far as emoji data goes, sometimes it is impossible to find the emoji of interest in those emoji menus you can access these days, and so we wanted to offer the …

      Code point(s) approach

    … for users to specify emojis (or other textual data) to be displayed in that newish textbox we created for the purpose a couple of days ago. What’s the big deal here? Well, take a look at a typical fileformat.info page such as the one below for “banana” …

    Look at all the different ways a banana 🍌 emoji can be specified! We allow logic for …

    • HTML Entity (decimal)
    • HTML Entity (hex)
    • Unicode character
    • C/C++/Java source code … and then, inhouse, we allow for …
    • Decimal Code point(s) comma separated
    • Hex Code point(s) comma separated

    … as per the new Javascript code …


    function allownums(ininvl, tboxo) {
    // 20320,22909 // alert("你好".replace(/[\u00A0-\u9999<>\&]/g, i => '&#'+i.charCodeAt(0)+';'));
    var inm=0, itdepends=false;
    var invl=ininvl;
    var iwords=invl.replace(/\&nbsp\;/g,' ').split(' ');
    ininvl=ininvl.replace(/\ U\+/g, ',U+').replace(/\ u\+/g, ',u+').replace(/\ \\U/g, ",\\U").replace(/\ \\u/g, ",\\u").replace(/\ u\+/g, ',u+').replace(/\;\ \&\#/g, ',&#').replace(/\;\&\#/g, ',&#').replace(/\ \&\#/g, ',&#').replace(/\&\#x/g, '0x').replace(/\&\#/g, '').replace(/\;\ /g, ',').replace(/\;/g, ',').replace(/U\+/g,'0x').replace(/u\+/g,'0x').replace(/\\u/g,'0x').replace(/\\U/g,'0x').replace(/\.\,/g,',').replace(/\,\./g,',').replace(/\&nbsp\;/g,' ');
    if (ininvl != invl) { itdepends=true; iwords=ininvl.trim().toLowerCase().split(' '); }
    if (ininvl != invl && (!itdepends || eval('' + iwords.length) == 1)) {
    if (('' + ininvl.trim().toLowerCase()) != '' && ('' + ininvl.trim().toLowerCase()).replace(/\./g,'').replace(/\,/g,'').replace(/\x/g,'') != '' && ('' + ininvl.trim().toLowerCase()).replace(/\./g,'').replace(/\,/g,'').replace(/\x/g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/a/g,'').replace(/b/g,'').replace(/c/g,'').replace(/d/g,'').replace(/e/g,'').replace(/f/g,'') == '') {
    if (ininvl.trim().toLowerCase().replace(/\./g,',').indexOf(',') != -1 || ininvl.trim().toLowerCase().replace(/\./g,',').indexOf('0x') != -1 || eval('' + ininvl.trim().length) > 3) {
    if (ininvl.trim().toLowerCase().replace(/a/g,'').replace(/b/g,'').replace(/c/g,'').replace(/d/g,'').replace(/e/g,'').replace(/f/g,'') != ininvl.trim().toLowerCase() && ininvl.trim().toLowerCase().indexOf('x') == -1) {
    eval("ininvl=String.fromCodePoint(0x" + ininvl.trim().toLowerCase().replace(/\./g,',').replace(/\,/g,',0x') + ');');
    } else {
    eval("ininvl=String.fromCodePoint(" + ininvl.trim().toLowerCase().replace(/\./g,',') + ');');
    }
    } else {
    ininvl=invl;
    }
    tboxo.value='' + ininvl;
    invl='' + ininvl;
    }
    } else if (('' + iwords[0].trim().toLowerCase()) != '' && ('' + iwords[0].trim().toLowerCase()).replace(/\./g,'').replace(/\,/g,'').replace(/\x/g,'') != '' && ('' + iwords[0].trim().toLowerCase()).replace(/\./g,'').replace(/\,/g,'').replace(/\x/g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/a/g,'').replace(/b/g,'').replace(/c/g,'').replace(/d/g,'').replace(/e/g,'').replace(/f/g,'') == '') {
    if (iwords[0].trim().toLowerCase().replace(/\./g,',').indexOf(',') != -1 || iwords[0].trim().toLowerCase().replace(/\./g,',').indexOf('0x') != -1 || eval('' + iwords[0].trim().length) > 3) {
    if (iwords[0].trim().toLowerCase().replace(/a/g,'').replace(/b/g,'').replace(/c/g,'').replace(/d/g,'').replace(/e/g,'').replace(/f/g,'') != iwords[0].trim().toLowerCase() && iwords[0].trim().toLowerCase().indexOf('x') == -1) {
    eval("invl=String.fromCodePoint(0x" + iwords[0].trim().toLowerCase().replace(/\./g,',').replace(/\,/g,',0x') + ');');
    } else {
    eval("invl=String.fromCodePoint(" + iwords[0].trim().toLowerCase().replace(/\./g,',') + ');');
    }
    for (inm=1; inm<iwords.length; inm++) {
    if (('' + iwords[inm].trim().toLowerCase()) != '' && ('' + iwords[inm].trim().toLowerCase()).replace(/\./g,'').replace(/\,/g,'').replace(/\x/g,'') != '' && ('' + iwords[inm].trim().toLowerCase()).replace(/\./g,'').replace(/\,/g,'').replace(/\x/g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/a/g,'').replace(/b/g,'').replace(/c/g,'').replace(/d/g,'').replace(/e/g,'').replace(/f/g,'') == '') {
    if (iwords[inm].trim().toLowerCase().replace(/a/g,'').replace(/b/g,'').replace(/c/g,'').replace(/d/g,'').replace(/e/g,'').replace(/f/g,'') != iwords[inm].trim().toLowerCase() && iwords[inm].trim().toLowerCase().indexOf('x') == -1) {
    eval("invl+=' ' + String.fromCodePoint(0x" + iwords[inm].trim().toLowerCase().replace(/\./g,',').replace(/\,/g,',0x') + ');');
    } else {
    eval("invl+=' ' + String.fromCodePoint(" + iwords[inm].trim().toLowerCase().replace(/\./g,',') + ');');
    }
    } else {
    invl+=' ' + iwords[inm].trim();
    }
    }
    } else {
    invl=ininvl;
    }
    tboxo.value='' + invl;
    }
    return invl;
    }

    … in the changed sixth draft version of a “Text Background Clip” client web application.


    Previous relevant Text Background Clip Animation Emoji Overlay SVG Sharing Tutorial is shown below.

    Text Background Clip Animation Emoji Overlay SVG Sharing Tutorial

    Text Background Clip Animation Emoji Overlay SVG Sharing Tutorial

    Further to yesterday’s Text Background Clip Animation Emoji Overlay SVG Tutorial you start getting web browser support for context (ie. right click) menu options such as …

    • Copy image
    • Copy image address
    • Save image as

    the latter effectively your “download option” when we can reach the HTML scenario whereby the user’s right click is over (an element such as) …


    <img type="image/svg" src="//www.rjmprogramming.com.au/tmp/svg_e_a_o_17_09_2025_13_32_14.svg"></img>

    … which today’s work is all about trying to achieve in adding more practical “export aid tools” into the “sharing mix”.

    As with our last Media Gallery project, with our changed PHP helper signature_signature.php‘s

    <?php

    if (isset($_POST['an_i_thingo'])) {
    $ds=DIRECTORY_SEPARATOR;
    if (isset($_POST['svg_filename'])) {
    foreach (glob($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'svg_e_a_o_' . '*.*') as $dfilename) {
    $filemtime = filemtime($dfilename);
    if (time() - $filemtime >= 172800) { // 86400 seconds in a day
    unlink($dfilename);
    }
    }
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . $ds . 'tmp' . $ds . '' . basename(str_replace('+',' ',urldecode($_POST['svg_filename']))), str_replace('+',' ',urldecode($_POST['an_i_thingo'])));
    exit;
    }

    // rest of the usual if block
    }

    ?>

    … PHP code called into play via some Ajax Javascript calling …


    var outfile='', wootoo=null;
    var czhr=null, czform=null;

    function ourprompt(svgoh) {
    var oursvgoh=svgoh;
    var tag=null;
    var recipient='';
    var dt=new Date();
    var dsuff=('' + dt.toLocaleDateString() + ' ' + dt.toLocaleTimeString()).replace(/\:/g,'_').replace(/\ /g,'_').replace(/\//g,'_').replace(/\-/g,'_');
    outfile='http://www.rjmprogramming.com.au/tmp/svg_e_a_o_' + dsuff + '.svg';
    var xc=prompt('Optionally copy SVG below and save to a SVG file ( eg. text.svg ) that will open via a web browser Open File option ( eg. file:///Applications/MAMP/htdocs/test.svg ) or on a macOS MAMP local web server environment ( or http://localhost:8888/test.svg could also work here ). Or leave as is and use OK answer to save to URL ' + outfile + ' and display and/or share. To just email enter email address or to SMS enter a mobile number. An alternative filename suffix to ' + dsuff + ' is another OK answer option. Any other OK answers do nothing more.', svgoh);
    if (xc == null) {
    outfile='';
    } else if (xc == svgoh) {
    outfile=outfile;
    } else if (xc.indexOf(' ') == -1 && xc.indexOf('@') != -1) {
    recipient=xc;
    tag = document.createElement('a');
    tag.id='aem';
    tag.target='_top';
    tag.href='mailto:' + recipient + '?subject=Emoji%20Animated%20Overlay%20SVG%20image&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#' + encodeURIComponent(svgoh.replace(' onclick="top.ourprompt(this.outerHTML);"', ' title="' + outfile + '"')));
    tag.style.display='none';
    document.body.appendChild(tag);
    tag.click();
    } else if (xc.trim() != '' && xc.indexOf(' ') == -1 && xc.replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '') {
    recipient=xc;
    tag = document.createElement('a');
    tag.id='aem';
    tag.target='_top';
    tag.href='sms:' + recipient + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#' + encodeURIComponent(svgoh.replace(' onclick="top.ourprompt(this.outerHTML);"', ' title="' + outfile + '"')));
    tag.style.display='none';
    document.body.appendChild(tag);
    tag.click();
    } else if (xc.trim() != '' && xc.indexOf('<') == -1 && xc.indexOf(' ') == -1) {
    outfile='http://www.rjmprogramming.com.au/tmp/svg_e_a_o_' + xc + '.svg';
    } else if (xc.trim() != '' && xc.indexOf('<svg') == 0 && xc.indexOf('</svg>') != -1) {
    oursvgoh='' + xc.split('</svg>')[0] + '</svg>';
    } else {
    outfile='';
    }

    if (outfile != '') {

    czhr = new XMLHttpRequest();
    czform = new FormData();
    czform.append('an_i_thingo', oursvgoh);
    czform.append('svg_filename', outfile);
    czhr.onreadystatechange = showStuff;
    czhr.open('post', '/HTMLCSS/signature_signature.php', true);
    czhr.send(czform);



    }
    }

    function showStuff() {
    if (czhr != null) {
    if (czhr.readyState == 4) {
    if (czhr.status == 200) {
    setTimeout(function(){
    wootoo=window.open('','_blank','top=50,left=50,width=800,height=800');
    wootoo.document.write('<html><body onload="document.title=document.body.title;" title="' + outfile + '"><img type="image/svg" src="//' + outfile.split('//')[1] + '"></img><scri' + 'pt type=text/javascript> setTimeout(function(){ document.title=document.body.title; }, 5000); </scr' + 'ipt></body></html>');
    }, 1000);
    }
    }
    }
    }

    … and where we set up an arrangement so that …

    • for a couple of days …
    • we arrange for the creation of SVG files in a public URL place …
    • should the user make use of our new functionality

      var xc=prompt(‘Optionally copy SVG below and save to a SVG file ( eg. text.svg ) that will open via a web browser Open File option ( eg. file:///Applications/MAMP/htdocs/test.svg ) or on a macOS MAMP local web server environment ( or http://localhost:8888/test.svg could also work here ). Or leave as is and use OK answer to save to URL ‘ + outfile + ‘ and display and/or share. To just email enter email address or to SMS enter a mobile number. An alternative filename suffix to ‘ + dsuff + ‘ is another OK answer option. Any other OK answers do nothing more.‘, svgoh);

      … off that amended Javascript prompt window added yesterday

    And if the two days is up (possible for an email or SMS link (again depending on hashtag methodologies) click after the initial action)? Well, we construct some SVG within a webpage for that scenario, but, as we say, that is not as cute, as far as web browser native functionality smarts go (though you can still View Page Source and work from there, for masochists out there), as when an actual SVG image file sits there on the web server, regarding the SVG sharably changed fifth draft version of a “Text Background Clip” client web application.


    Previous relevant Text Background Clip Animation Emoji Overlay SVG Tutorial is shown below.

    Text Background Clip Animation Emoji Overlay SVG Tutorial

    Text Background Clip Animation Emoji Overlay SVG Tutorial

    As far as “heading towards creating a tool” from yesterday’s Text Background Clip Animation Emoji Overlay Tutorial‘s …

    1. emoji
    2. overlay
    3. animation

    … work beginnings we’re harnessing SVG’s foreignObject subelement to start up that avenue (as some relief from the roads heading down lately).

    SVG has it’s own animation abilities, but thinking we could simulate the keyframes and transitions CSS animations over the last couple of days sounded daunting. As were HTML5 canvas usage ideas. So we went down the foreignObject avenue and have been pleased we did, really. Those keyframes and transitions animations worked but we think the background text clipping may need more research or will pan out not to be translatable to the …


    Standalone SVG image creator

    within our “reveal” details/summary hosting tool we hope to improve upon, from our start, today, in the SVG saveably changed fourth draft version of a “Text Background Clip” client web application.


    Previous relevant Text Background Clip Animation Emoji Overlay Tutorial is shown below.

    Text Background Clip Animation Emoji Overlay Tutorial

    Text Background Clip Animation Emoji Overlay Tutorial

    It’s “overlay day” onto yesterday’s Text Background Clip Animation Tutorial, and we like “overlay days” much better than any “underlay days” it’s got to be said … although?!

    So what constitutes a good “overlay day” to us? It’s one that includes some/all of (the CSS concepts) …

    • position: absolute;
    • left: [position in X]px; top: [position in Y]px;
    • opacity: [from 0 to 1];
    • z-index: [the larger the more prominent];

    … though the last we did not need so far, and the use of the great Javascript method [element].getBoundingClientRect() as exemplified by


    var rectis=document.getElementById('box').getBoundingClientRect();
    document.getElementById('bbox').style.position='absolute';
    document.getElementById('bbox').style.left='' + rectis.left + 'px';
    document.getElementById('bbox').style.top='' + rectis.top + 'px';
    document.getElementById('bbox').style.display='inline-block';
    document.getElementById('box').className='box';
    document.getElementById('bbox').className='box';

    … where you will also see us better synchronizing the animation start by dynamically allocating element class (via Javascript DOM means) as close to the same time as possible in the “overlay” changed third draft version of a “Text Background Clip” client web application.


    Previous relevant Text Background Clip Animation Tutorial is shown below.

    Text Background Clip Animation Tutorial

    Text Background Clip Animation Tutorial

    Today we’re returning to the work of Text Background Clip Primer Tutorial and adding a layer of …

    Do It Yourself animation

    … possibilities for the user. We grant you, the Text Background Clip aspects are, and remain, at least in our mind, the main talking point here, but it represents to us “a way in” (perhaps to a dead-end, but we are hoping not) regarding the concepts of …

    1. emoji
    2. overlay
    3. animation

    … and this project had the first, and now we’re easing our way into the third today, with the reason we chose it as “a guinea pig” project being that textarea way the user has control. We want the user to explore possibilities themselves, and making it easier for us to see what’s possible regarding combinations of the three concepts above, we’re hoping, regarding the changed second draft version of a “Text Background Clip” client web application?!


    Previous relevant Text Background Clip Primer Tutorial is shown below.

    Text Background Clip Primer Tutorial

    Text Background Clip Primer Tutorial

    Again, today, we’re cloning and modifying a new “proof of concept” version of a “Text Background Clip” server web application

    And, again, it’s that “interactive input duo” of …

    … forming that shareable dataset (helped out by diff and ed command line commands via PHP exec and shell_exec) whereby you can email or SMS your “creations” to other interested parties.

    And, again, there is a “proof of concept” version of a “Text Background Clip” client web application choice of usage here, for you to try for yourself!


    Previous relevant Emoji Animation Primer Tutorial is shown below.

    Emoji Animation Primer Tutorial

    Emoji Animation Primer Tutorial

    Today we’re cloning and modifying a new “proof of concept” version of an “Emoji Animation” server web application (or “proof of concept” client web application) …

    We generally corral commonalities today when we think about cloning, and its here in spades regarding …

    We break the “user controllable” components of the card into …

    1. wording of the card
    2. emoji (maybe) border of card CSS styling

    … but just substitute “animation” for “border of card” or just “card” above. With help regarding the CSS above we’d like to thank How to Animate an Emoji with CSS.

    We hope you try it out, creating your own webpages!


    Previous relevant Simple Emoji Border Card Primer Tutorial is shown below.

    Simple Emoji Border Card Primer Tutorial

    Simple Emoji Border Card Primer Tutorial

    We were really happy to stumble upon StackOverflow‘s excellent Use Emoji as CSS Border webpage (of dreams and ideas) the other day, and immediately want to …

    We break the “user controllable” components of the card into …

    1. wording of the card
    2. emoji (maybe) border of card CSS styling

    … used by the user via some HTML textarea content they could edit to click a “Post” button creating their tailored (left hand table cell containing) HTML div element, that if double clicked (or just clicked within the surrounding table cell below the HTML “card” div) opens the user’s created card, alone, in a new window.


    Previous relevant Emoji Animation CSS Block Tutorial is shown below.

    Emoji Animation CSS Block Tutorial

    Emoji Animation CSS Block Tutorial

    Do you recall a few days back, with Simple Emoji Border Card Sharing Tutorial how we avoided “too long” mailto: and/or sms: “a” link href arrangements, before we harnessed the command line combination of …

    • diff
    • ed

    … the latter of which worked fine on this macOS system where we are writing this blog, but, sadly, not on our RJM Programming Linux web server? Well, we could install “ed”, but decided, instead, to “act like mister ed” with a new PHP function, which, today, caters for “ed asks” that might involve more than one line of change, with some “comma usages” can be seen explained, here, at ed – Use ed line oriented text editor – IBM Documentation. Here is the PHP function for your perusal …

    <?php

    function viacolon($instuff) {

    //21c
    // background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' height='30' width='30'><text x='50%' y='50%' dominant-baseline='middle' text-anchor='middle'></text></svg>");
    //.
    //13,14c
    //.box:after {
    // content: "Well I never";
    //.
    //w

    $sprevln="";
    $ldm=";";
    $prevln='';
    $inlns=explode("\n", $instuff);
    $lns=file('/tmp/emoji_animation.diff');
    foreach ($lns as $line_num => $ln) {
    $lastinteresting=false;
    if (($ln == 'w' || $ln == "w\n") && strpos($prevln, "d") !== false && strlen($prevln) <= 10 && strpos(trim($prevln), ' ') === false && strpos($prevln, ",") !== false) {
    if (1 == 2) { $lastinteresting=true; }
    $fromi=explode(",", explode("d", $prevln)[0])[0];
    $toi=explode(",", explode("d", $prevln)[0])[1];
    for ($fromtoi=$fromi; $fromtoi<=$toi; $fromtoi++) {
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $fromtoi]), " ", $instuff);
    }
    }
    if (!$lastinteresting && $ln != '.' && $ln != 'w' && $ln != ".\n" && $ln != "w\n") {
    if (strpos($ln, ':') !== false && (strpos($ln, ';') !== false || strpos($ln, '{') !== false)) {
    if (strpos($ln, 'background:') === false) {
    $bg=explode(':', $ln);
    if (strpos($instuff, $bg[0] . ':') !== false) {
    $ldm=";";
    if (strpos($bg[1], ";") === false && strpos($bg[1], "{") !== false) { $ldm="{"; }
    //if (strpos($bg[0], ".box") !== false) { file_put_contents('ax.ax', $instuff . "\n\n\n" . $bg[0] . ':' . explode($ldm, explode($bg[0] . ':', $instuff)[1])[0] . ':' . "\n\n\n" . $bg[0] . ':' . explode($ldm, explode($bg[0] . ':', file_get_contents('/tmp/emoji_animation.diff'))[1])[0] . "\n\n\n" . str_replace($bg[0] . ':' . explode($ldm, explode($bg[0] . ':', $instuff)[1])[0],$bg[0] . ':' . explode($ldm, explode($bg[0] . ':', file_get_contents('/tmp/emoji_animation.diff'))[1])[0],$instuff)); }
    $instuff=str_replace_once($bg[0] . ':' . explode($ldm, explode($bg[0] . ':', $instuff)[1])[0],$bg[0] . ':' . explode($ldm, explode($bg[0] . ':', file_get_contents('/tmp/emoji_animation.diff'))[1])[0],$instuff);
    } else if (strpos($prevln, "a") !== false) {
    $fromi=explode(",", explode("a", $prevln)[0])[0];
    $toi=$fromi;
    $prefx=explode($inlns[-1 + explode("a", $prevln)[0]], $instuff)[0];
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + explode("a", $prevln)[0]]), str_replace("\n", "", $inlns[-1 + explode("a", $prevln)[0]]) . " " . $bg[0] . ':' . explode(';', explode($bg[0] . ':', file_get_contents('/tmp/emoji_animation.diff'))[1])[0] . '; ', $instuff);
    $inlns[-1 + explode("a", $prevln)[0]]=$inlns[-1 + explode("a", $prevln)[0]] . " " . $bg[0] . ':' . explode(';', explode($bg[0] . ':', file_get_contents('/tmp/emoji_animation.diff'))[1])[0] . '; ';
    if (('' . $toi) == '1') {
    //$instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $toi + $fromi]), " ", $instuff);
    $sprevln="";
    } else {
    $toi--;
    //$instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $toi + $fromi]), " ", $instuff);
    $sprevln="" . $fromi . "a";
    }
    }
    }
    }
    if (strlen($ln) <= 10 && str_replace("\n","", str_replace("d","", str_replace("c","", str_replace("a","", str_replace(",","", str_replace("0","", str_replace("1","", str_replace("2","", str_replace("3","", str_replace("4","", str_replace("5","", str_replace("6","", str_replace("7","", str_replace("8","", str_replace("9","",$ln))))))))))))))) == "") {
    if (str_replace("\n","", str_replace("c","", str_replace("a","", str_replace(",","", str_replace("0","", str_replace("1","", str_replace("2","", str_replace("3","", str_replace("4","", str_replace("5","", str_replace("6","", str_replace("7","", str_replace("8","", str_replace("9","",$ln)))))))))))))) != "") {
    $prevln=$ln;
    }
    }
    //if (strlen($ln) <= 10 && str_replace("\n","", str_replace("c","", str_replace("a","", str_replace(",","", str_replace("0","", str_replace("1","", str_replace("2","", str_replace("3","", str_replace("4","", str_replace("5","", str_replace("6","", str_replace("7","", str_replace("8","", str_replace("9","",$ln)))))))))))))) == "") {
    if (strlen($ln) <= 10 && str_replace("\n","", str_replace("d","", str_replace("c","", str_replace("A","", str_replace(",","", str_replace("0","", str_replace("1","", str_replace("2","", str_replace("3","", str_replace("4","", str_replace("5","", str_replace("6","", str_replace("7","", str_replace("8","", str_replace("9","",$ln))))))))))))))) == "") {
    $instuff=$instuff;
    } else if (strpos($prevln, "d") !== false && strlen($prevln) <= 10 && strpos(trim($prevln), ' ') === false && strpos($prevln, ",") === false) {
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + explode("d", $prevln)[0]]), " ", $instuff);
    } else if (strpos($prevln, "a") !== false && strlen($prevln) <= 10 && strpos(trim($prevln), ' ') === false && strpos($prevln, ",") === false) {
    $fromi=explode(",", explode("a", $prevln)[0])[0];
    $lnbig="";
    $lni=(-1 + explode("a", $prevln)[0]);
    $toi=$fromi;
    $isok=true;
    while (('' . $toi) != '0' && $isok) {
    //$prefx=explode($inlns[-1 + explode("a", $prevln)[0]], $instuff)[0];
    if ($ln == '.' || $ln == 'w' || $ln == ".\n" || $ln == "w\n") {
    $isok=false;
    $sprevln=$ln; //"";
    } else if ($ln != '.' && $ln != 'w' && $ln != ".\n" && $ln != "w\n") {
    //file_put_contents('/tmp/emoji_animation.zzz', $ln);
    //file_put_contents('/tmp/emoji_animation.yyy', $prevln);
    //$instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + explode("a", $prevln)[0]]), str_replace("\n", "", $inlns[-1 + explode("a", $prevln)[0]]) . " " . $ln, $instuff);
    //if (!file_exists('/tmp/emoji_animation.www')) { file_put_contents('/tmp/emoji_animation.www', $instuff); }
    $lnbig.=' ' . str_replace("\n", "", $ln) . ' '; //$inlns[-1 + explode("a", $prevln)[0]]=$inlns[-1 + explode("a", $prevln)[0]] . " " . $ln;
    }
    if (('' . $toi) == '1') {
    //$instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $toi + $fromi]), " ", $instuff);
    //$instuff=str_replace_once(str_replace("\n", "", $ln), " ", $instuff);
    $sprevln=$ln; //"";
    $toi--;
    $ln=$lns[($fromi - $toi) + $line_num];
    } else {
    $toi--;
    //$instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $toi + $fromi]), " ", $instuff);
    //$instuff=str_replace_once(str_replace("\n", "", $ln), " ", $instuff);
    $sprevln="" . $fromi . "a";
    $ln=$lns[($fromi - $toi) + $line_num];
    }
    }
    $instuff=str_replace_once(str_replace("\n", "", $inlns[$lni]), str_replace("\n", "", $inlns[$lni]) . " " . $lnbig, $instuff);
    //$inlns[$lni]=$inlns[$lni] . " " . $lnbig;
    $sprevln=' ';
    } else if (strpos($prevln, "c") !== false && strlen($prevln) <= 10 && strpos(trim($prevln), ' ') === false && strpos($prevln, ",") === false) {
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + explode("c", $prevln)[0]]), str_replace("\n", "", $ln), $instuff);
    } else if (strpos($prevln, "d") !== false && strlen($prevln) <= 10 && strpos(trim($prevln), ' ') === false && strpos($prevln, ",") !== false) {
    $fromi=explode(",", explode("d", $prevln)[0])[0];
    $toi=explode(",", explode("d", $prevln)[0])[1];
    for ($fromtoi=$fromi; $fromtoi<=$toi; $fromtoi++) {
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $fromtoi]), " ", $instuff);
    }
    //$instuff=str_replace(str_replace("\n", "", $inlns[-1 + $fromi]), " ", $instuff);
    //if ($fromi != $toi) {
    // $fromi++;
    // $sprevln="" . $fromi . "," . $toi . "d";
    //} else {
    $sprevln=$ln;
    //}
    } else if (strpos($prevln, "c") !== false && strlen($prevln) <= 10 && strpos(trim($prevln), ' ') === false && strpos($prevln, ",") !== false) {
    $origln=$ln;
    $lnbig='';
    $isokay=true;
    $fromi=explode(",", explode("c", $prevln)[0])[0];
    $toi=explode(",", explode("c", $prevln)[0])[1];
    $one=1;
    $ln=$lns[$one + $line_num];
    while ($ln != '.' && $ln != 'w' && $ln != ".\n" && $ln != "w\n") {
    $lnbig.=' ' . str_replace("\n", "", $ln) . ' ';
    $one++;
    $ln=$lns[$one + $line_num];
    }
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $fromi]), str_replace("\n", "", $origln) . $lnbig, $instuff);
    if ($fromi != $toi) {
    $fromi++;
    $sprevln="" . $fromi . "," . $toi . "c";
    for ($fromtoi=$fromi; $fromtoi<=$toi; $fromtoi++) {
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + $fromtoi]), " ", $instuff);
    }
    } else {
    $sprevln=$ln;
    }
    }
    if ($sprevln != "") {
    $prevln=$sprevln;
    $sprevln="";
    } else {
    $prevln=$ln;
    }
    if (strpos($prevln, "d") !== false && strlen($prevln) <= 10 && strpos(trim($prevln), ' ') === false && strpos($prevln, ",") === false) {
    $instuff=str_replace_once(str_replace("\n", "", $inlns[-1 + explode("d", $prevln)[0]]), " ", $instuff);
    }
    }
    }
    return $instuff;
    }

    function str_replace_once($needle, $replace, $haystack) { // thanks to https://stackoverflow.com/questions/1252693/using-str-replace-so-that-it-only-acts-on-the-first-match
    $newstring=$haystack;
    $pos = strpos($haystack, $needle);
    if ($pos !== false) {
    $newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
    }
    return $newstring;
    }

    ?>

    … improving on yesterday’s Emoji Animation Primer Tutorial.

    That work not only helped out with the changed “proof of concept” Emoji Animation server web application, but also with (its “clone partner”) the changed “proof of concept” Card with Emoji Border Design client web application.


    Previous relevant Emoji Animation Primer Tutorial is shown below.

    Emoji Animation Primer Tutorial

    Emoji Animation Primer Tutorial

    Today we’re cloning and modifying a new “proof of concept” version of an “Emoji Animation” server web application (or “proof of concept” client web application) …

    We generally corral commonalities today when we think about cloning, and its here in spades regarding …

    We break the “user controllable” components of the card into …

    1. wording of the card
    2. emoji (maybe) border of card CSS styling

    … but just substitute “animation” for “border of card” or just “card” above. With help regarding the CSS above we’d like to thank How to Animate an Emoji with CSS.

    We hope you try it out, creating your own webpages!


    Previous relevant Simple Emoji Border Card Primer Tutorial is shown below.

    Simple Emoji Border Card Primer Tutorial

    Simple Emoji Border Card Primer Tutorial

    We were really happy to stumble upon StackOverflow‘s excellent Use Emoji as CSS Border webpage (of dreams and ideas) the other day, and immediately want to …

    We break the “user controllable” components of the card into …

    1. wording of the card
    2. emoji (maybe) border of card CSS styling

    … used by the user via some HTML textarea content they could edit to click a “Post” button creating their tailored (left hand table cell containing) HTML div element, that if double clicked (or just clicked within the surrounding table cell below the HTML “card” div) opens the user’s created card, alone, in a new window.

    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.

Posted in Ajax, Animation, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment