Walking Trip …

Walking Trip

Walking Trip

Offenbach's Suite ... Warts 'n All

Offenbach's Suite ... Warts 'n All

 📅  

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

Posted in Photography, Trips | Tagged , , | 34 Comments

YouTube API Songname Providence Tutorial

YouTube API Songname Providence Tutorial

YouTube API Songname Providence Tutorial

Today we’re trialling, using our inhouse The Wrecking Crew YouTube API calling web application to try out some …


Song providence overlay information via Wikipedia

… new functionality, further to the relatively recent YouTube API Caller Radio Play Playlist Songname Search List Tutorial, which features the CSS property …


pointer-events: none;

… regarding a topmost semi-transparent but high z-indexed “overlay” means of proceeding forward. Of course, we’ll refine (eg. later, make it “opt in”). Of course, we’ll apply the thinking to other web applications. But, as with most new ideas, it is good to iron out the issues with a guinea pig web application, and that is the changed the_wrecking_crew.html The Wrecking Crew (calling a changed http_methods.php) for us in this “first draft proof of concept” go.


Previous relevant YouTube API Caller Radio Play Playlist Songname Search List Tutorial is shown below.

YouTube API Caller Radio Play Playlist Songname Search List Tutorial

YouTube API Caller Radio Play Playlist Songname Search List Tutorial

We’re baaaccckkk, at our Tabular Single Row Media Gallery web application’s Radio Playlists, that is! Onto the recent YouTube API Caller Radio Play Connection Loss Implication Tutorial today, in a quiet way so far until fully bedded down, we’ve allowed for …

  • not only comma separated 11 character YouTube video IDs … go to make up an inhouse playlist (playing YouTube videos, that is) … but as of today’s work …
  • that comma separated list can be songnames … such as the example today being …

    It Must Be Him,Boogie Wonderland

    … to search YouTube regarding the derivation of those YouTube video IDs (presented in a dropdown)

… ready for a Radio button click to play in Radio Play mode, so far, in random order (see what we mean about “bedding down”).

Codewise, that involved …


Previous relevant YouTube API Caller Radio Play Connection Loss Implication Tutorial is shown below.

YouTube API Caller Radio Play Connection Loss Implication Tutorial

YouTube API Caller Radio Play Connection Loss Implication Tutorial

We synopsized some time ago now how important for our Tabular Single Row Media Gallery web application’s Radio Play mode of use, is a sound and consistent connection.

But it just so happened around about the time of the recent YouTube API Caller Radio Play Remembering Recall Words Tutorial one of our testing scenarios saw a break with the connection and this was on the MacBook Air while in a Radio Play mode popup window called off the original window scenario. You can use a red reload button to restart, but …

  • the Genre buttons down the bottom …
  • if they’re clicked at a time of loss of connection …
  • should abandon the savvy thinking of the recent YouTube API Caller Radio Webpage Persistence Tutorial where the existing webpage’s textboxes are reused and refilled with the new genre’s YouTube video ID references … because …
  • this amounts to “flogging a dead horse” because the loss of connection has your “grandparent” losing touch with the “grandchild” doing all the work … just think “Daffy Duck” if you will … and …
  • in this “loss of connection” scenario it would be better for those bottom Genre button clicks act more like the red reload button click and reload the webpage via the URL presented up at the web browser address bar … again

So, in order to outsavvy the supposedly savvy, what do we need to do? Anyone, anyone?

Yes, Herbert, you had your hand up?! You say …

Run away from the grandparents in a huff to the doll’s house in the backyard and hide there until somebody notices you’re missing …

… oh, there’s more …

… and if they don’t come … well … either sneak in some chocolate biscuits or some comfy mattress …

… yes, and …

… and settle in for the long haul.

Well, sounds a bit like some personal experience there, Herb?! But now, it’s sort of the opposite what we were thinking should happen … Anyone, anyone?

Mabel, good to hear from you … what do you think?! You say …

Kick up a stink

… yes, and …

… record the stink …

… yes, and …

… let the grandparents know …

… yes …

  1. you are the stink
  2. the stink will remain … unless …
  3. action is taken by the grandparent to refresh the stink … … …

… and are you advertising there, Mabel?! Sorry, we don’t advertise, usually, in class, that is … okay, just this once, but we insist on using Spell Checker …

Pine O Clean it!

But, yes, spot on there, Mabel. The grandchild needs to prove to the grandparent that they’re still around


function playingvideo() {
var aswellas=0, xvcen='', noret=false, ourdur=22234;
console.warn('playingvideo 0 ... ' + parent.document.URL);
if (window.top) {
if (typeof top.tsupd == 'function') {
top.tsupd();
}

}
// rest of playingvideo setTimeout (with delay of one second) function follows
}

… so that the grandparent can monitor …


var lastmsse=('' + Date.now());
var origmsse=lastmsse;
var maybeinplayscenario=false;

function tsupd() {
if (4 == 5) {
document.getElementById('msse').value=('' + Date.now());
lastmsse=document.getElementById('msse').value;
} else {
lastmsse=('' + Date.now());
}
}

… and then wrap any, what used to be maybeinplayscenario=true; Javascript codelines into maybeinplayscenario=maybeso(true);


function maybeso(inv) {
if (lastmsse == origmsse) { return inv; }
if (Math.abs(eval(('' + Date.now())) - lastmsse) > 12000) {
return false;
}
return inv;
}

… so that a false return amounts to ditching the past idea of “savvy” for the “outsavvying the saveloy” paradigm of 2025 (being that itsy bit more impactful than The Great Tea Trolley Disaster of ’67 in our humble opinion).

So, feel free to retry the changed swipe_media.html Tabular Single Row Media Gallery web application “grandparent” still in touch with the modified stop_start_youtube.html YouTube API caller “grandchild”.


Previous relevant YouTube API Caller Radio Play Remembering Recall Words Tutorial is shown below.

YouTube API Caller Radio Play Remembering Recall Words Tutorial

YouTube API Caller Radio Play Remembering Recall Words Tutorial

We both like and dislike the word …

static

… around here regarding programming. It can represent that “rock of Gibraltar” to rely on (and most webpages around here start with “static HTML” text editing on good ol’ macOS TextWrangler) … and we all need that. But it can also stop flexibility, and in that category for us was the restriction of YouTube video inhouse “genres” with our latest YouTube API Caller Radio Play Scheduling Tutorial to a list of 8 as per …


Movie Soundtracks, Slow Classical Movements, Solo Guitar, Solo Sax, Mr Smith Goes To Washington, Disco, The Wrecking Crew, Yacht Rock

… but what if we could “slice and dice” any window.localStorage names the user has used to save their inhouse playlists for recall, and allow these purely alphabetic words (eg. today’s Vikki Carr remembering via tube_Vikki-Carr playlist name analysis added “Vikki” and “Carr” into that list above, for us, on the web browser where we performed the remembering actions) into that rather “static” genre list above, further to yesterday’s YouTube API Caller Radio Play Scheduling Tutorial, and thus adding usable words for those scheduling smarts mentioned there? And flag that in the prompt window where we’ve associated each of the eight “static” ones with a number from 1 to 8? Sounds good to us, but we resist more number mapping, because …

  • it’s simpler to handle for now
  • we have a one character paradigm going on with this logic (and we have a burning hatred of 9)

Take a look at our “opening gambit” Javascript code looking at web browser stored playlists and schedules, regarding all this …


var lssssel='', schsel='', lcwordassociation=[], wordassociation=[], associationword=[], lssssors='';

if (schsel == '' && lssssel == '') {
for (wxls in window.sessionStorage) {
if (('' + decodeURIComponent(window.sessionStorage.getItem(wxls))).indexOf('/swipe_media.htm') != -1 && ('' + decodeURIComponent(window.sessionStorage.getItem(wxls)).replace('?b','isradio=').replace('=rad','isradio=')).indexOf('isradio=') != -1) {
if (lssssel.trim() == '') { lssssel='<select id=myselrads title="Recallable Radio Playlists ..." onchange="if (this.value.trim().length != 0) { alert(this.value); } "><option value="">&#x1F4FB;</option></select>'; }
thisentry=decodeURIComponent(window.sessionStorage.getItem(wxls));
lssssel=lssssel.replace('</select>', '<option title="' + thisentry + '" value="' + thisentry + '">' + wxls + '</option></select>');
partsare=wxls.replace(/\-/g,'_').split('_');
for (ips=0; ips<partsare.length; ips++) {
if (partsare[ips].trim() == '') {
lssssel=lssssel;
} else if (ips == 0 && partsare[ips].toLowerCase().indexOf('tube') != -1) {
lssssel=lssssel;
} else if (isAlphaString(partsare[ips])) {
if (wordassociation.indexOf(partsare[ips]) == -1) { // used to be .toLowerCase()
lcwordassociation.push(partsare[ips].toLowerCase());
wordassociation.push(partsare[ips]); // used to be .toLowerCase()
lssssors+=' or ' + partsare[ips];
associationword.push(thisentry);
//if (partsare[ips].toLowerCase() != partsare[ips] && partsare[ips].toUpperCase() != partsare[ips]) {
//}
}
}
}
} else if (wxls.indexOf('schedule_') == 0) {
if (schsel.trim() == '') { schsel='<select ontouchdown="event.stopPropagation();" onmousedown="event.stopPropagation();" onclick="event.stopPropagation();" style=width:30px; id=myschs title="Recallable Schedules ..." onchange="if (this.value.trim().length != 0) { genreideas(this.value); } "><option value="">&#x1F4C5;</option></select>'; }
schsel=schsel.replace('</select>', '<option title="' + decodeURIComponent(window.sessionStorage.getItem(wxls)) + '" value="' + decodeURIComponent(window.sessionStorage.getItem(wxls)) + '">' + wxls.replace(/^schedule/g,'').replace(/\_/g,' ') + '</option></select>');
}
}
for (wxls in window.localStorage) {
if (('' + decodeURIComponent(window.localStorage.getItem(wxls))).indexOf('/swipe_media.htm') != -1 && ('' + decodeURIComponent(window.localStorage.getItem(wxls)).replace('?b','isradio=').replace('=rad','isradio=')).indexOf('isradio=') != -1) {
if (lssssel.trim() == '') { lssssel='<select id=myselrads title="Recallable Radio Playlists ..." onchange="if (this.value.trim().length != 0) { alert(this.value); } "><option value="">&#x1F4FB;</option></select>'; }
thisentry=decodeURIComponent(window.localStorage.getItem(wxls));
lssssel=lssssel.replace('</select>', '<option title="' + thisentry + '" value="' + thisentry + '">' + wxls + '</option></select>');
partsare=wxls.replace(/\-/g,'_').split('_');
for (ips=0; ips<partsare.length; ips++) {
if (partsare[ips].trim() == '') {
lssssel=lssssel;
} else if (ips == 0 && partsare[ips].toLowerCase().indexOf('tube') != -1) {
lssssel=lssssel;
} else if (isAlphaString(partsare[ips])) {
if (wordassociation.indexOf(partsare[ips]) == -1) { // used to be .toLowerCase()
lcwordassociation.push(partsare[ips].toLowerCase());
wordassociation.push(partsare[ips]); // used to be .toLowerCase()
lssssors+=' or ' + partsare[ips];
associationword.push(thisentry);
//if (partsare[ips].toLowerCase() != partsare[ips] && partsare[ips].toUpperCase() != partsare[ips]) {
//}
}
}
}
} else if (wxls.indexOf('schedule_') == 0) {
if (schsel.trim() == '') { schsel='<select ontouchdown="event.stopPropagation();" onmousedown="event.stopPropagation();" onclick="event.stopPropagation();" style=width:30px; id=myschs title="Recallable Schedules ..." onchange="if (this.value.trim().length != 0) { genreideas(this.value); } "><option value="">&#x1F4C5;</option></select>'; }
schsel=schsel.replace('</select>', '<option title="' + decodeURIComponent(window.localStorage.getItem(wxls)) + '" value="' + decodeURIComponent(window.localStorage.getItem(wxls)) + '">' + wxls.replace(/^schedule/g,'').replace(/\_/g,' ') + '</option></select>');
}
}
if (schsel == '' && lssssel == '') { lssssel=' '; }
}

… within the changed swipe_media.html Tabular Single Row Media Gallery web application.


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

YouTube API Caller Radio Play Scheduling Tutorial

YouTube API Caller Radio Play Scheduling Tutorial

Lots of us like to work to a plan. Timed entertainments for an orderly work day, perhaps?

And so, onto the recent YouTube API Caller Radio Webpage Persistence Tutorial, it’s “handsfree” work of recent times can be harnessed to support …

scheduled radio play of YouTube videos

… on the basis of “genre”. Now this “genre” will get more exciting soon, but for today, we just wanted to bed down a user entered “scheduling schedule” (via right click (non-mobile) or ontouchmove (mobile) on the slivery leftmost table cell) such as …

Wrecking,60 Classical,09:00 Movie,13:00 Yacht,19:30 Disco

… would schedule …

  1. via a new webpage, perhaps, depending, playing The Wrecking Crew genre videos in Radio Play mode
  2. once officially playing (and we’d recommend the user establishes any initial clicks/taps or unmutes here to open the door to “handsfree from then on”) wait 60 seconds (and if it had been entered as a floating point number with a decimal point, it would have been seen as that many minutes)
  3. load Slow Classical Movement genre videos into the existant list of YouTube videos on the same last webpage (not requiring any new clicks/taps)
  4. until 09:00 local time
  5. load Movie Soundtrack genre videos into the existant list of YouTube videos on the same last webpage (not requiring any new clicks/taps)
  6. until 13:00 local time
  7. load Yacht Rock genre videos into the existant list of YouTube videos on the same last webpage (not requiring any new clicks/taps)
  8. until 19:30 local time
  9. load Disco genre videos into the existant list of YouTube videos on the same last webpage (not requiring any new clicks/taps)

Can you see how this can be an alternative to Speech to Text “handsfree thinking” for the many users out there who can never be in “the conditions window club“?

Codewise, we needed to establish …


Previous relevant YouTube API Caller Radio Webpage Persistence Tutorial is shown below.

YouTube API Caller Radio Webpage Persistence Tutorial

YouTube API Caller Radio Webpage Persistence Tutorial

Yesterday’s YouTube API Caller Radio Change of Genre Saying Playlist Title Tutorial‘s opens the door to, for either mobile or non-mobile …

When a user requests a YouTube video genre change of Radio Play we try to …

  1. rather than require any “first loading and/or unmuting” tap/click
  2. rather than open any new Radio Play webpages
  3. we infill using the existant Radio Play list with the new genre list (as can be fitted, that is)

… and, we’re pretty sure, in doing this, reducing resource requirements for …

You may notice, too, after the song we wait on finishes regarding yesterday’s butnotif logic, we now fill it’s slot in with a member of the new genre list should one be available to spare.


Previous relevant YouTube API Caller Radio Change of Genre Saying Playlist Title Tutorial is shown below.

YouTube API Caller Radio Change of Genre Saying Playlist Title Tutorial

YouTube API Caller Radio Change of Genre Saying Playlist Title Tutorial

Finally, after today’s work, after that of yesterday’s YouTube API Caller Radio Change of Genre Saying Playlist Tutorial we have a …

handsfree YouTube video genre change Radio Play

… scenario functional, and in a state …

  • where it may help elsewhere, with some mobile issues … primarily, we believe …
  • because it involves no new windows of webpages executing Radio Play, and so saves on resources that may otherwise overload the system

Today’s nuance, which helped, was a measure to “ease in” the new genre YouTube video records by modifying the textbox onblur event logic (in function checkval) to recognize any global variable butnotif value (at the appropriate time, set in the code …


butnotif=document.getElementById('youtubeid').value;
checkval(document.getElementById('i' + alti));

… to the currently playing YouTube video ID) matches within the textboxes as …

not to be changed

as seen in


for (neleven=1; neleven<setofelevens.length; neleven++) {
if (!document.getElementById('i' + ieleven)) {
ieleven=0;
} else if (document.getElementById('i' + ieleven).value.trim() == '') {
ieleven=0;
}
if (butnotif != '') {
if (document.getElementById('i' + ieleven).value.indexOf(butnotif) != -1) {
ieleven++;
if (!document.getElementById('i' + ieleven)) {
ieleven=0;
} else if (document.getElementById('i' + ieleven).value.trim() == '') {
ieleven=0;
}
}

}
document.getElementById('i' + ieleven).value='' + setofelevens[neleven];
document.getElementById('c' + ieleven).checked=true; // new line
ieleven++;
}

… and then butnotif value put back to nothing.

Then there were the window titles for the last two of the hierarchy below …

  1. top conditions window (can spawn, as of today, a sequential run of Speech to Text window(s) that stop happening should window below happen, or user close themselves ahead of time) … clicking or typing or saying a way towards creating …
  2. popup at top level window with it’s window.opener equating to window above, that is a YouTube video Radio Play or Normal Play execution window … can spawn, as of today, if no user controlled closing as explained above …
  3. a sequential run of Speech to Text window(s)

… to make more accurate, reflecting new genre detail, best seen codewise examining …


Previous relevant YouTube API Caller Radio Change of Genre Saying Playlist Tutorial is shown below.

YouTube API Caller Radio Change of Genre Saying Playlist Tutorial

YouTube API Caller Radio Change of Genre Saying Playlist Tutorial

Today’s work, onto yesterday’s YouTube API Caller Radio Change of Genre Playlist Tutorial has shown us …

handsfree YouTube video genre change Radio Play

… can happen, but we won’t bore you here with the conditions again. But it will take more time to comfortably bed it down, and we need it repeatable. Did I say we need to make it repeatable? Repeatability is an aim over the next day or two. Belch … ditto …

This Javascript monitors for the necessary action points …


function wolookfordivtitleschange() {
var alti=1, altarr=[], tent=10000;
if (parent.document.getElementById('divtitles').innerHTML.indexOf('>In play<') != -1 && parent.window.opener.document.getElementById('divtitles').innerHTML.indexOf('>In play<') == -1) {
parent.window.opener.document.getElementById('divtitles').innerHTML+='<p style="display:none;">In play</p>';
inplay=true;
}
if (parent.document.getElementById('divtitles').innerHTML.indexOf('>In play<') == -1 && parent.window.opener.document.getElementById('divtitles').innerHTML.indexOf('>In play<') != -1) {
parent.document.getElementById('divtitles').innerHTML+='<p style="display:none;">In play</p>';
inplay=true;
}
if (parent.document.getElementById('divnewtitles') && !parent.window.opener.document.getElementById('divnewtitles')) {
parent.window.opener.document.getElementById('divtitles').innerHTML+=parent.document.getElementById('divnewtitles').outerHTML;
inplay=true;
if (firstblank == ' ') { tent=120000; }
playcont=parent.document.getElementById('divnewtitles').innerHTML + firstblank;
firstblank='';
}
if (!parent.document.getElementById('divnewtitles') && parent.window.opener.document.getElementById('divnewtitles')) {
parent.document.getElementById('divtitles').innerHTML+=parent.window.opener.document.getElementById('divnewtitles').outerHTML;
inplay=true;
if (firstblank == ' ') { tent=120000; }
playcont=parent.window.opener.document.getElementById('divnewtitles').innerHTML + firstblank;
firstblank='';
}
if (parent.document.getElementById('divnewtitles') && parent.window.opener.document.getElementById('divnewtitles')) {
if (eval('' + parent.document.getElementById('divnewtitles').innerHTML.length) > eval('' + parent.window.opener.document.getElementById('divnewtitles').innerHTML.length)) {
parent.window.opener.document.getElementById('divnewtitles').innerHTML=parent.document.getElementById('divnewtitles').innerHTML;
}
if (eval('' + parent.document.getElementById('divnewtitles').innerHTML.length) < eval('' + parent.window.opener.document.getElementById('divnewtitles').innerHTML.length)) {
parent.document.getElementById('divnewtitles').innerHTML=parent.window.opener.document.getElementById('divnewtitles').innerHTML;
}
}
if (parent.document.getElementById('divtitles')) {
if (inplay && playcont == '') {
playcont=parent.document.getElementById('divtitles').innerHTML;
}
if (!inplay && parent.document.getElementById('divtitles').innerHTML.indexOf('>In play<') != -1) {
inplay=true;
}
if (inplay && playcont.trim() != '') {
if (parent.document.getElementById('divtitles').innerHTML != playcont && document.getElementById('i0').outerHTML.indexOf(' data-clash=') == -1) {
if (parent.document.getElementById('divnewtitles')) {
if (parent.document.getElementById('divnewtitles').innerHTML.trim() != '') {
altarr=parent.document.getElementById('divnewtitles').innerHTML.trim().split(',');
//alert('1:' + parent.document.getElementById('divnewtitles').innerHTML);
document.getElementById('i0').setAttribute('data-noclash', '' + document.getElementById('youtubeid').value);
if (document.getElementById('i0').value.indexOf(document.getElementById('youtubeid').value) == -1) {
document.getElementById('i0').value=parent.document.getElementById('divnewtitles').innerHTML;
alti=0;
} else if (document.getElementById('i' + alti)) {
while (document.getElementById('i' + alti)) {
if (document.getElementById('i' + alti).value.indexOf(document.getElementById('youtubeid').value) == -1) {
document.getElementById('i' + alti).value=parent.document.getElementById('divnewtitles').innerHTML;
alti=eval(0 - eval('' + alti));
} else {
alti++;
}
}
if (alti >= 0) {
document.getElementById('i0').value=parent.document.getElementById('divnewtitles').innerHTML;
alti=0;
} else {
alti=-alti;
}
} else {
document.getElementById('i0').value=parent.document.getElementById('divnewtitles').innerHTML;
alti=0;
}
parent.document.getElementById('divnewtitles').innerHTML='';
if (eval('' + altarr.length) > 0 && 5 == 7) {
var newalti=alti;
var jalti=0
for (var ialt=alti; ialt<eval(alti + eval('' + altarr.length)); ialt++) {
if (document.getElementById('i' + newalti)) {
if (document.getElementById('i' + newalti).value.trim() != -1) {
document.getElementById('i' + newalti).value='' + altarr[jalti];
} else {
newalti=0;
document.getElementById('i' + newalti).value='' + altarr[jalti];
}
} else {
newalti=0;
document.getElementById('i' + newalti).value='' + altarr[jalti];
}
newalti++;
jalti++;
}
} else {
checkval(document.getElementById('i' + alti));
}
}
}
playcont=parent.document.getElementById('divtitles').innerHTML;
}
} else if (inplay && parent.document.getElementById('divnewtitles')) {
if (parent.document.getElementById('divnewtitles').innerHTML.trim() != '') {
//alert('2:' + parent.document.getElementById('divnewtitles').innerHTML);
document.getElementById('i0').value=parent.document.getElementById('divnewtitles').innerHTML;
parent.document.getElementById('divnewtitles').innerHTML='';
checkval(document.getElementById('i0'));
}
playcont=parent.document.getElementById('divtitles').innerHTML;
}
}
setTimeout(wolookfordivtitleschange, tent);
}

As you can see, the timer Javascript function setTimeout helps out enormously in this …


Previous relevant YouTube API Caller Radio Change of Genre Playlist Tutorial is shown below.

YouTube API Caller Radio Change of Genre Playlist Tutorial

YouTube API Caller Radio Change of Genre Playlist Tutorial

Yesterday’s YouTube API Caller Radio Keyboard Playlist Tutorial crystallized for us what a …


Change of Genre

… looks like, as far as our Tabular Single Row Media Gallery web application, using Radio Play mode, goes. And so, given that, we asked ourselves …

Is it possible, midstream, to change genre on the fly, in terms of “minimal” user interaction and/or totally handsfree?

Well, regarding “totally handsfree” (and with this thinking, the “nirvana aim” would be no extra clicks or taps necessary, though we concede this will not always be feasible) and you’re out and about (even in the vehicle), it could only work (as far as working within the limitations of this web application’s architecture) with …

  • your laptop connected to the Internet via some means (eg. lassooed via your mobile’s Personal Hotspot or Free Public WiFi etcetera) … and then …
  • https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html … https: protocol users of our Tabular Single Row Media Gallery web application …
  • non-mobile
  • Google Chrome web browser
  • no arguments … none … so there
  • a top window (ie. not popup, not iframe) … and so running the link above on the laptop’s Google Chrome web browser, at the appropriate time a Radio Play song list is loaded and playing in the second window then you could …
  • say into (or loud enough away from) the red laptop microphone icon presented, for the example of a first run of Disco (Radio Play) …

    Find rock

    … to make Yacht Rock songs permeate the previous Disco Radio Play playlist in the more recent webpage window

… the first day’s progress of which gets somewhere down the line of achieving. On this first day of this new sub-project we just type …

Yacht 

… (with a space character at the end) as a keyboard alternative idea to see some, but not yet total, success with this new sub-project mission.

Codewise, all below were affected …


Previous relevant YouTube API Caller Radio Keyboard Playlist Tutorial is shown below.

YouTube API Caller Radio Keyboard Playlist Tutorial

YouTube API Caller Radio Keyboard Playlist Tutorial

We forgot to say about yesterday’s YouTube API Caller Radio Saying Playlist Tutorial

It’s Speech to Text Day!

… and the day before that, with YouTube API Caller Radio Playlist Genre Tutorial, going …

It’s Genre Day!

… and today … well …

It’s Keyboard Day!!!

Yes, the keyboard is there for all, and it may have been apparent to regular readers, apart from Javascript prompt window usage we’ve asked nothing of the keyboard “anything” up to now with our Tabular Single Row Media Gallery web application.

You would not be alone if you hadn’t noticed. I’ve been working on this project for what feels like aeons now, and it only just occurred to us today?! It’s one of those “heartwarming discoveries” because if such a situation “falls into your lap”, so to speak, it can be another layer of functionality to offer your users.

We got right into the coding for non-mobile, just getting places for a couple of hours. But what about mobile, with the keyboard not there as a physical entity for most users? And then it occurred to us …

  • don’t show in any new textboxes (which haven’t appeared up to now regarding the topmost window webpage usage … and we guess, here, this is the whole point, if you can arrange for that) … rather …
  • for mobile users, turn a hardcoded text part of that slivery leftmost table cell’s content … and we picked that “V” near the bottom … into a …

    <span onclick="gok=false; event.stopPropagation(); setTimeout(function(){ gok=true; }, 5000);" id=thev contenteditable=true>V</span>

    … and what a great wonder contenteditable=true is!

… for a mobile user’s access point, that still remains an optional piece of functionality, which we prefer to make happen, when functionality … is … optional … doh!

The (we can use the proper term) tap (to describe) of that “V” (now an HTML element) teams up with some new document.body event setting


<body onkeypress="onkd(event);" onclick="readyforswipe=true; swipechk(event,false);" onmousemove="swipechk(event,true);" onload="firstonl(); setTimeout(onl, 3000);">
// webpage content goes here
</body>

… allows for an independent layer of keyboard logic …


var okdsofar='';
var gtitle='', gok=true;
var ifire=-1, firedup=['','Movie Soundtracks','Slow Classical Movements','Solo Guitar','Solo Sax','Mr Smith Goes To Washington',' Disco','The Wrecking Crew','Yacht Rock'];

function onkd(e) {
var charx = e.which || e.keyCode;
if (String.fromCharCode(eval('' + charx)) >= '1' && String.fromCharCode(eval('' + charx)) <= '8' && okdsofar == '') {
document.getElementById('fplaythft').style.border='3px dotted green';
document.getElementById('fplaythft').title+=' ... fired up ' + firedup[eval('' + String.fromCharCode(eval('' + charx)))];
genreideas(String.fromCharCode(eval('' + charx)));
} else if (String.fromCharCode(eval('' + charx)) < '1' || String.fromCharCode(eval('' + charx)) > '8' || okdsofar != '') {
okdsofar+=String.fromCharCode(eval('' + charx));
if (okdsofar.trim() != '' && okdsofar.trim() != okdsofar && okdsofar.toLowerCase() != 'solo ') {
genreideas(okdsofar.replace(/^Mr\ /g,'Washington ').replace(/^MR\ /g,'Washington ').replace(/^mr\ /g,'Washington ').replace(/^The\ /g,'wrecking ').replace(/^THE\ /g,'wrecking ').replace(/^the\ /g,'wrecking ').trim());
okdsofar='';
}
}
setTimeout(function(){ document.getElementById('thev').innerHTML='V'; }, 20000);
return true;
}

… to take place (in a very much “behind the scenes” way on non-mobile) that can do quite a bit better than we’d ever expect the Speech to Text functionality to get to, at least for us, that is.

So feel free to try these new Keyboard logics, more likely, in the changed swipe_media.html Tabular Single Row Media Gallery web application.


Previous relevant YouTube API Caller Radio Saying Playlist Tutorial is shown below.

YouTube API Caller Radio Saying Playlist Tutorial

YouTube API Caller Radio Saying Playlist Tutorial

Yesterday’s YouTube API Caller Radio Playlist Genre Tutorial was heading towards what many algorithm creators dream of …

  • take a concept consisting of words (eg. Music Genres) … associate that with a …
  • number

… being that computers go a lot faster computing matters involving numbers rather than names or words.

And this set us to thinking for …

… phew! … users we’d offer Speech to Text functionality making use of Google’s excellent Web Speech API Demonstration inspiration, thanks.

We were thinking the user could start with the word …

Find

… and if they say, say (when the microphone icon is red, or clicked to become red) …

Find three

… the Solo Guitar music genre will wind up into preparatory action for them.

Similarly key words can work as per …

Find rock

… starting up Yacht Rock … or …

Find imagine

… will go off and show a dropdown showing YouTube video references involving the song Imagine (by John Lennon) or whatever else a YouTube search of “Imagine” lists highly.

Try this new Speech to Text, maybe, in the changed swipe_media.html Tabular Single Row Media Gallery web application feature this new document.body onload timed Javascript snippet …


if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && document.URL.indexOf('https:') == 0 && document.URL.indexOf('?') == -1 && document.URL.indexOf('rjmprogramming.com.au/HTMLCSS/swipe_media.htm') != -1) {
if (('' + window.navigator.userAgent).toLowerCase().replace('crios','chrome').indexOf('chrom') != -1) {
if (window.parent && window.parent != window.self) {
speechtotextwo=speechtotextwo;
} else {
if (window.opener) {
speechtotextwo=speechtotextwo;
} else {
speechtotextwo=window.open('https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?mode=3', '_blank', 'top=0,left=' + eval(-600 + screen.width) + ',width=600,height=' + eval(-100 + screen.height));
document.body.innerHTML+='<input type=hidden id=posturl style=display:none; value=""></input><input type=button id=dbutton onclick=checkforstt(); style=display:none;></input>';
setTimeout(checkforstt, 1000);
setTimeout(function(){ speechtotextwo.document.title='"Find Imagine" ... example of YouTube Genre Number or Name Listening'; }, 5000);
document.getElementById('td0000').title+=' Or speak your Radio Play music genre eg. Find three to Start Solo Guitar or Find rock to start Yacht Rock or Find imagine to do a YouTube search that populates a multiple selection dropdown.';
}
}
}
}


Previous relevant YouTube API Caller Radio Playlist Genre Tutorial is shown below.

YouTube API Caller Radio Playlist Genre Tutorial

YouTube API Caller Radio Playlist Genre Tutorial

Further to yesterday’s YouTube API Caller Radio Playlist Moderation Tutorial

It’s Moderation Day Nuance Afternoon … tea, anyone?!

Yes, we have a couple of “around moderation” issues today, they being …

  1. allow for …

    As requested by You

    … “blurbing” for the non-moderation ideas from a couple of days back

  2. introduce some new YouTube video ID list genres, so far, as per …
    • Movie Soundtracks https://www.rjmprogramming.com.au/HTMLCSS/disco_version.html?aprefix=001&atitle=Movie%2520Soundtracks&alist=gZXKl36YS9k%2CHWqKPWO5T4o%2CAFa1-kciCb4%2CF2RnxZnubCM%2C3JWTaaS7LdU%2CU5zbcTxxz6M%2CLGs_vGt0MY8%2CcH2PH0auTUU%2CYnzgdBAKyJo%2C-p6OH7FoWoQ%2C057A1RdssoU%2CDhlPAj38rHc%2CyyV_eb3p3Zw%2Cdfe8tCcHnKY%2CK69tbUo3vGs%2C_D0ZQPqeJkk%2CjA9NbU_R-y4%2C8XDB7GMnbUQ%2Cz9_S411e9RI%2CX6ymVaq3Fqk%2CJYMySrHL0Fo%2CRuxHLzwlDY4%2CWkr8iZlKaRk%2C4Yd2PzoF1y8%2C-9012SGz-yY%2C9NEQb6LdHGQ%2CgCTeh8avZQI%2C78N2SP6JFaI%2CntXJJwEk1NA
    • Slow Classical Movements https://www.rjmprogramming.com.au/HTMLCSS/disco_version.html?aprefix=002&atitle=Slow%2520Classical%2520Movements&alist=FtE3hoR_Nvo%2CW5IKT_xue4o%2CIfaGhyK78E8%2CBuN3yCmHb_U%2CTdiAwCPb_As%2CeuZcUku9XiE%2CaMs0rNtBZJk%2CsUgoBb8m1eE%2CPppexz-KKig%2Cs-CpJpWm9Vs%2CLGs_vGt0MY8%2C2WfaotSK3mI%2CGKkeDqJBlK8%2CCvFH_6DNRCY%2Cu-_hosF7TpI%2CIOWN5fQnzGk%2CYqVRcFQagtI
    • Solo Guitar https://www.rjmprogramming.com.au/HTMLCSS/disco_version.html?aprefix=004&atitle=Solo%2520Guitar&alist=_4E_924b9SU%2C6pR1cVgk7Is%2CjoUEC257ZS0%2CIxuThNgl3YA%2CTLV4_xaYynY%2CVJDJs9dumZI%2CJGJdU2dpYxg%2CPl9H9X1GoAc%2C09839DpTctU%2CN4bFqW_eu2I%2CQkF3oxziUI4%2C2BMT0L714S8
    • Solo Sax https://www.rjmprogramming.com.au/HTMLCSS/disco_version.html?aprefix=013&atitle=Solo%2520Sax&alist=Fo6aKnRnBxM%2CHoLhKJuGhK0%2ClW1RAYYs8RI%2C447yaU_4DF8%2CizGwDsrQ1eQ%2C4TYv2PhG89A%2CSECVGN4Bsgg%2C3JWTaaS7LdU%2C_leMA3_maBU%2CZtFUX4Y2U84%2CPXwF7g5wksQ
    • Mr Smith Goes To Washington https://www.rjmprogramming.com.au/HTMLCSS/disco_version.html?aprefix=014&atitle=Mr%2520Smith%2520Goes%2520To%2520Washington&alist=zPv0S1-ETdI%2CqYf35nBq8Oo%2CSe3kxManWUY%2Ci7hk-TupE5g%2CLnK0tnaNUag%2CdbH4Amzn-Rk%2CBL-Jg7CyqLQ%2C0v7Ea7kg2gA%2CNRjWEE0hmjQ

    … available to the user via leftmost slivery table cell right clicks (non-mobile) or “touch move gesture” (mobile) and using new Javascript …

    var allowotm=true;

    function genreideas(ind) {
    if (allowotm) {
    allowotm=false;
    setTimeout(otmallow, 10000);
    var ablurb='Can choose some other Genres out of 1 is Movie Soundtracks or 2 is Slow Classical Movements or 3 is Solo Guitar or 4 is Solo Sax or 5 is Mr Smith Goes To Washington or 6 is Disco or 7 is The Wrecking Crew or 8 is Yacht Rock';
    var ans=null;
    if (ind.trim() == '') {
    ans=prompt(ablurb, '');
    } else {
    ans=ind;
    }

    if (ans == null) { return ''; }
    if (ans == '1' || ans.toLowerCase().indexOf('soundtrack') != -1 || ans.toLowerCase().indexOf('movie') != -1) {
    prefix='isradio=bdiscoavb&atitle=Movie%20Soundtracks&';
    document.getElementById('spareif').src='/HTMLCSS/disco_version.html?aprefix=001&atitle=Movie%2520Soundtracks&alist=gZXKl36YS9k%2CHWqKPWO5T4o%2CAFa1-kciCb4%2CF2RnxZnubCM%2C3JWTaaS7LdU%2CU5zbcTxxz6M%2CLGs_vGt0MY8%2CcH2PH0auTUU%2CYnzgdBAKyJo%2C-p6OH7FoWoQ%2C057A1RdssoU%2CDhlPAj38rHc%2CyyV_eb3p3Zw%2Cdfe8tCcHnKY%2CK69tbUo3vGs%2C_D0ZQPqeJkk%2CjA9NbU_R-y4%2C8XDB7GMnbUQ%2Cz9_S411e9RI%2CX6ymVaq3Fqk%2CJYMySrHL0Fo%2CRuxHLzwlDY4%2CWkr8iZlKaRk%2C4Yd2PzoF1y8%2C-9012SGz-yY%2C9NEQb6LdHGQ%2CgCTeh8avZQI%2C78N2SP6JFaI%2CntXJJwEk1NA&rand=' + Math.floor(Math.random() * 1987865); // + dvl;
    } else if (ans == '2' || ans.toLowerCase().indexOf('classic') != -1 || ans.toLowerCase().indexOf('move') != -1) {
    prefix='isradio=bdiscoavb&atitle=Slow%20Classical%20Movements&';
    document.getElementById('spareif').src='/HTMLCSS/disco_version.html?aprefix=002&atitle=Slow%2520Classical%2520Movements&alist=FtE3hoR_Nvo%2CW5IKT_xue4o%2CIfaGhyK78E8%2CBuN3yCmHb_U%2CTdiAwCPb_As%2CeuZcUku9XiE%2CaMs0rNtBZJk%2CsUgoBb8m1eE%2CPppexz-KKig%2Cs-CpJpWm9Vs%2CLGs_vGt0MY8%2C2WfaotSK3mI%2CGKkeDqJBlK8%2CCvFH_6DNRCY%2Cu-_hosF7TpI%2CIOWN5fQnzGk%2CYqVRcFQagtI&rand=' + Math.floor(Math.random() * 1987865); // + dvl;
    } else if (ans == '3' || ans.toLowerCase().indexOf('guitar') != -1) {
    prefix='isradio=bdiscoavb&atitle=Solo%20Guitar&';
    document.getElementById('spareif').src='/HTMLCSS/disco_version.html?aprefix=004&atitle=Solo%2520Guitar&alist=_4E_924b9SU%2C6pR1cVgk7Is%2CjoUEC257ZS0%2CIxuThNgl3YA%2CTLV4_xaYynY%2CVJDJs9dumZI%2CJGJdU2dpYxg%2CPl9H9X1GoAc%2C09839DpTctU%2CN4bFqW_eu2I%2CQkF3oxziUI4%2C2BMT0L714S8&rand=' + Math.floor(Math.random() * 1987865); // + dvl;
    } else if (ans == '4' || ans.toLowerCase().indexOf('sax') != -1) {
    prefix='isradio=bdiscoavb&atitle=Solo%20Sax&';
    document.getElementById('spareif').src='/HTMLCSS/disco_version.html?aprefix=013&atitle=Solo%2520Sax&alist=Fo6aKnRnBxM%2CHoLhKJuGhK0%2ClW1RAYYs8RI%2C447yaU_4DF8%2CizGwDsrQ1eQ%2C4TYv2PhG89A%2CSECVGN4Bsgg%2C3JWTaaS7LdU%2C_leMA3_maBU%2CZtFUX4Y2U84%2CPXwF7g5wksQ&rand=' + Math.floor(Math.random() * 1987865); // + dvl;
    } else if (ans == '5' || ans.toLowerCase().indexOf('smith') != -1 || ans.toLowerCase().indexOf('washington') != -1) {
    prefix='isradio=bdiscoavb&atitle=Mr%20Smith%20Goes%20To%20Washington&';
    document.getElementById('spareif').src='/HTMLCSS/disco_version.html?aprefix=014&atitle=Mr%2520Smith%2520Goes%2520To%2520Washington&alist=zPv0S1-ETdI%2CqYf35nBq8Oo%2CSe3kxManWUY%2Ci7hk-TupE5g%2CLnK0tnaNUag%2CdbH4Amzn-Rk%2CBL-Jg7CyqLQ%2C0v7Ea7kg2gA%2CNRjWEE0hmjQ&rand=' + Math.floor(Math.random() * 1987865); // + dvl;
    } else if (ans == '6' || ans.toLowerCase().indexOf('disco') != -1) {
    document.getElementById('bdiscoavb').click();
    } else if (ans == '7' || ans.toLowerCase().indexOf('wreck') != -1 || ans.toLowerCase().indexOf('crew') != -1) {
    document.getElementById('bwcavb').click();
    } else if (ans == '8' || ans.toLowerCase().indexOf('yacht') != -1 || ans.toLowerCase().indexOf('rock') != -1) {
    document.getElementById('byravb').click();
    } else if (ind.trim() == '' && ans.toLowerCase().replace('+','=').replace('-','=').indexOf('=') != -1) {
    storageideas(ans);
    }
    }
    return '';
    }

    function otmallow() {
    allowotm=true;
    }

As for the first “As requested by MoiYou” idea goes, if you are into wrapping not just on …

  1. birthdays
  2. Christmas
  3. I Don’t Like Mondays Monday
  4. Chinese New Year
  5. Mid-Autumn Festival
  6. Diwali
  7. Wobble Wombat Wednesday
  8. Eid al-Fitr
  9. Oseibo
  10. Handmade Tupac & Biggie Ceramic Statue Tuesday
  11. Ochugen
  12. Aren’t Pronouns Just The Bee’s Knees Thursday
  13. Saturnalia
  14. Stuffed Toy Saturday

… then have we got an old chestnut for you! The wrapping of encryption encodeURIComponent and decodeURIComponent are just ripe for the picking we’re taking it, of fruit … damned AI didn’t say?! … as simple as …


var asrequestedbystuff='', dethingos=[];

function thisencodeURIComponent(inida) {
var thingos=inida.split(',');
for (var ity=0; ity<thingos.length; ity++) {
document.getElementById('bdiscoavb').setAttribute('data-you', '&asrequested=you');
asrequestedbystuff+='|' + thingos[ity] + '=You';
}
return encodeURIComponent(inida);
}

function andlateris() {
for (var ity=0; ity<dethingos.length; ity++) {
document.getElementById('bdiscoavb').setAttribute('data-you', '&asrequested=you');
asrequestedbystuff+='|' + dethingos[ity] + '=You';
}
}

function thisdecodeURIComponent(jnida) {
var inida=decodeURIComponent(jnida);
dethingos=inida.split(',');
if (4 == 45) {
andlateris();
} else {
setTimeout(andlateris, 6000);
}
return inida;
}

… applied at the appropriate junctionure. Nala?!!! Get off the keyboard! Luna!?!? Stop that mouse! The cat we do not have (okay, hey you, neighbour’s cat … yes, you … have you been making requests again?!) … “stop with the gestures, already?!” regarding the changed swipe_media.html Tabular Single Row Media Gallery web application.


Previous relevant YouTube API Caller Radio Playlist Moderation Tutorial is shown below.

YouTube API Caller Radio Playlist Moderation Tutorial

YouTube API Caller Radio Playlist Moderation Tutorial

Following up on yesterday’s YouTube API Caller Radio Playlist Control Tutorial

It’s Moderation Day!

… where ! equates to 1 … and is it “Bye, bye” to moderation tomorrow, who knows?! But, read all about it below …


function storageideas() {
var ablurb='Can redefine Disco or The Wrecking Crew or Yacht Rock or All playlists for web browser tab (only) via entry like Disco=Klh7sAv9hu4,hMOORQ1Mt2s,k4V3Mo61fJM#My 3 Songs' + String.fromCharCode(10) + ' or to delete one via entry like The Wrecking Crew-' + String.fromCharCode(10) + ' or to add into the mix (for this web browser usage) via entry like Yacht Rock+Klh7sAv9hu4,k4V3Mo61fJM#Two Songs into the mix' + String.fromCharCode(10) + ' Prefix of M for email moderation for chance of more permanent ongoing basis (after # would be regarding "as requested by [Name]" eg. Mall=HTzGMEfbnAw,CW_ZiojrkVY#Robert ).';
var ansp=prompt(ablurb, '');
var origansp='';
var moderate=0;
var buts=document.getElementsByTagName('button'), ibuts=0;
var spareihis='', sparerest='', sid=0, gsid=0;
var subjline=String.fromCodePoint(128251) + ' RJM Programming ... Please see whether YouTube links below suit xwz and DO NOT flag as such with "as requested by [yourEmailAddressGoesHere@alseChangeThisPleaseWithAName]" if all okay with YouTube ID list ';

if (ansp == null) { return ''; }
if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('mdisco=') == 0) {
gsid=('disco=').length;
subjline=subjline.replace(' xwz ', ' Disco music genre ');
moderate=(ansp.substring(0,1) == 'M' ? 2 : 1);
ansp=ansp.substring(1);
} else if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('myacht rock=') == 0) {
gsid=('yacht rock=').length;
subjline=subjline.replace(' xwz ', ' Yacht Rock music genre ');
moderate=(ansp.substring(0,1) == 'M' ? 2 : 1);
ansp=ansp.substring(1);
} else if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('mthe wrecking crew=') == 0) {
gsid=('the wrecking crew=').length;
subjline=subjline.replace(' xwz ', ' The Wrecking Crew music genre ');
moderate=(ansp.substring(0,1) == 'M' ? 2 : 1);
ansp=ansp.substring(1);
} else if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('mall=') == 0) {
gsid=('all=').length;
subjline=subjline.replace(' xwz ', ' ');
moderate=(ansp.substring(0,1) == 'M' ? 2 : 1);
ansp=ansp.substring(1);
}
var precomlist=ansp.split('&')[0].split('#')[0];
var comlist=precomlist.split(','), icl=0, bodyblurb='';
var boklast=['A','E','I','M','Q','U','Y','c','g','k','o','s','w','0','4','8'];
if (moderate == 2) {
subjline=subjline.replace(' DO NOT ', ' ');
if (ansp.indexOf('#') != -1 || ansp.indexOf('&') != -1) {
subjline=subjline.replace('[yourEmailAddressGoesHere@alseChangeThisPleaseWithAName]', ansp.substring(Math.max(ansp.indexOf('#'),ansp.indexOf('&'))).substring(1));
}
for (icl=eval(-1 + comlist.length); icl>=0; icl--) {
if (icl == 0) { sid=gsid; }
if (bodyblurb == '' && eval('' + comlist[icl].substring(sid).replace(/^\+/g,'').length) == 11 && comlist[icl].substring(sid).indexOf(' ') == -1 && boklast.indexOf(comlist[icl].slice(-1)) != -1) {
bodyblurb='https://www.youtube.com/watch?v=' + comlist[icl].substring(sid).replace(/^\+/g,'');
subjline+=comlist[icl].substring(sid).replace(/^\+/g,'');
} else if (eval('' + comlist[icl].substring(sid).replace(/^\+/g,'').length) == 11 && comlist[icl].substring(sid).indexOf(' ') == -1 && boklast.indexOf(comlist[icl].substring(sid).slice(-1)) != -1) {
bodyblurb+=String.fromCharCode(10) + 'https://www.youtube.com/watch?v=' + comlist[icl].substring(sid).replace(/^\+/g,'');
subjline+=',' + comlist[icl].substring(sid).replace(/^\+/g,'');
}
}
} else if (moderate == 1) {
if (ansp.indexOf('#') != -1 || ansp.indexOf('&') != -1) {
subjline=subjline.replace('[yourEmailAddressGoesHere@alseChangeThisPleaseWithAName]', ansp.substring(Math.max(ansp.indexOf('#'),ansp.indexOf('&'))).substring(1));
}
for (icl=eval(-1 + comlist.length); icl>=0; icl--) {
if (icl == 0) { sid=gsid; }
if (bodyblurb == '' && eval('' + comlist[icl].substring(sid).replace(/^\+/g,'').length) == 11 && comlist[icl].substring(sid).indexOf(' ') == -1 && boklast.indexOf(comlist[icl].slice(-1)) != -1) {
bodyblurb='https://www.youtube.com/watch?v=' + comlist[icl].substring(sid).replace(/^\+/g,'');
subjline+=comlist[icl].substring(sid).replace(/^\+/g,'');
} else if (eval('' + comlist[icl].substring(sid).replace(/^\+/g,'').length) == 11 && comlist[icl].substring(sid).indexOf(' ') == -1 && boklast.indexOf(comlist[icl].substring(sid).slice(-1)) != -1) {
bodyblurb+=String.fromCharCode(10) + 'https://www.youtube.com/watch?v=' + comlist[icl].substring(sid).replace(/^\+/g,'');
subjline+=',' + comlist[icl].substring(sid).replace(/^\+/g,'');
}
}
} else {
origansp=ansp;
if (origansp.toLowerCase().replace('+','=').replace('-','=').indexOf('all=') == 0) {
ansp='Disco' + origansp.substring(('all').length).substring(0,1) + origansp.substring(('all=').length);
}
if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('disco=') == 0) {
if (ansp.toLowerCase().indexOf('disco-') == 0) {
try {
window.sessionStorage.removeItem('disco_alt_list');
} catch (hgfh) { }
try {
window.localStorage.removeItem('disco_alt_list');
} catch (hgfh) { }
} else if (ansp.toLowerCase().indexOf('disco=') == 0) {
dvl='&videolist=' + encodeURIComponent(ansp.substring(('disco=').length).split('#')[0].split('&')[0]);
window.sessionStorage.setItem('disco_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
} else {
dvl='&listvideo=' + encodeURIComponent(ansp.substring(('disco=').length).split('#')[0].split('&')[0]);
window.localStorage.setItem('disco_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
}
if (ansp.substring(('disco=').length).replace(/\&/g,'#').indexOf('#') != -1) {
for (ibuts=0; ibuts<buts.length; ibuts++) {
if (buts[ibuts].innerHTML.indexOf('Disco') != -1) {
if (buts[ibuts].innerHTML.indexOf('<span') != -1) {
spareihis='<span' + buts[ibuts].innerHTML.split('<span')[1].split('</span>')[0] + '<span>';
sparerest=buts[ibuts].innerHTML.replace(spareihis,'');
buts[ibuts].innerHTML=spareihis + sparerest.replace(/Disco/g, ansp.substring(('disco=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
} else {
buts[ibuts].innerHTML=buts[ibuts].innerHTML.replace(/Disco/g, ansp.substring(('disco=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
}
}
}
}
}
if (origansp.toLowerCase().replace('+','=').replace('-','=').indexOf('all=') == 0) {
ansp='Yacht Rock' + origansp.substring(('all').length).substring(0,1) + origansp.substring(('all=').length);
}
if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('yacht rock=') == 0) {
if (ansp.toLowerCase().indexOf('yacht rock-') == 0) {
try {
window.sessionStorage.removeItem('yacht_rock_alt_list');
} catch (hgfh) { }
try {
window.localStorage.removeItem('yacht_rock_alt_list');
} catch (hgfh) { }
} else if (ansp.toLowerCase().indexOf('yacht rock=') == 0) {
yrvl='&videolist=' + encodeURIComponent(ansp.substring(('yacht rock=').length).split('#')[0].split('&')[0]);
window.sessionStorage.setItem('yacht_rock_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
} else {
yrvl='&listvideo=' + encodeURIComponent(ansp.substring(('yacht rock=').length).split('#')[0].split('&')[0]);
window.localStorage.setItem('yacht_rock_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
}
if (ansp.substring(('yacht rock=').length).replace(/\&/g,'#').indexOf('#') != -1) {
for (ibuts=0; ibuts<buts.length; ibuts++) {
if (buts[ibuts].innerHTML.indexOf('Yacht Rock') != -1) {
if (buts[ibuts].innerHTML.indexOf('<span') != -1) {
spareihis='<span' + buts[ibuts].innerHTML.split('<span')[1].split('</span>')[0] + '<span>';
sparerest=buts[ibuts].innerHTML.replace(spareihis,'');
buts[ibuts].innerHTML=spareihis + sparerest.replace(/Yacht\ Rock/g, ansp.substring(('yacht rock=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
} else {
buts[ibuts].innerHTML=buts[ibuts].innerHTML.replace(/Yacht\ Rock/g, ansp.substring(('yacht rock=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
}
}
}
}
}
if (origansp.toLowerCase().replace('+','=').replace('-','=').indexOf('all=') == 0) {
ansp='The Wrecking Crew' + origansp.substring(('all').length).substring(0,1) + origansp.substring(('all=').length);
}
if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('the wrecking crew=') == 0) {
if (ansp.toLowerCase().indexOf('the wrecking crew-') == 0) {
try {
window.sessionStorage.removeItem('the_wrecking_crew_alt_list');
} catch (hgfh) { }
try {
window.localStorage.removeItem('the_wrecking_crew_alt_list');
} catch (hgfh) { }
} else if (ansp.toLowerCase().indexOf('the wrecking crew=') == 0) {
twcvl='&videolist=' + encodeURIComponent(ansp.substring(('the wrecking crew=').length).split('#')[0].split('&')[0]);
window.sessionStorage.setItem('the_wrecking_crew_alt_list', encodeURIComponent(ansp.substring(('the wrecking crew=').length)));
} else {
twcvl='&listvideo=' + encodeURIComponent(ansp.substring(('the wrecking crew=').length).split('#')[0].split('&')[0]);
window.localStorage.setItem('the_wrecking_crew_alt_list', encodeURIComponent(ansp.substring(('the wrecking crew=').length)));
}
if (ansp.substring(('the wrecking crew=').length).replace(/\&/g,'#').indexOf('#') != -1) {
for (ibuts=0; ibuts<buts.length; ibuts++) {
if (buts[ibuts].innerHTML.indexOf('The Wrecking Crew') != -1) {
if (buts[ibuts].innerHTML.indexOf('<span') != -1) {
spareihis='<span' + buts[ibuts].innerHTML.split('<span')[1].split('</span>')[0] + '<span>';
sparerest=buts[ibuts].innerHTML.replace(spareihis,'');
buts[ibuts].innerHTML=spareihis + sparerest.replace(/The\ Wrecking\ Crew/g, ansp.substring(('the wrecking crew=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
} else {
buts[ibuts].innerHTML=buts[ibuts].innerHTML.replace(/The\ Wrecking\ Crew/g, ansp.substring(('the wrecking crew=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
}
}
}
}
}
}
if (bodyblurb != '') {
document.getElementById('aemail').href='mailto:rmetcalfe@rjmprogramming.com.au?subject=' + encodeURIComponent(subjline) + '&body=' + encodeURIComponent(bodyblurb);
document.getElementById('aemail').click();
}
}

… via those double clicks on the leftmost slivery table cell.

Codewise, all below were affected …

… believe it or not. Amongst changes within the last three you can see some trivial rearrangements of code designed to ensure a “one find only” scenario that may be used to simplify automation steps, for an administration user, regarding any follow up procedural steps off a successful application to permanently change the YouTube video lists inherent within those web applications.


Previous relevant YouTube API Caller Radio Playlist Control Tutorial is shown below.

YouTube API Caller Radio Playlist Control Tutorial

YouTube API Caller Radio Playlist Control Tutorial

Onto yesterday’s YouTube API Caller Radio Play Order Filled In Tutorial progress we’re starting another mini sub-project today that involves …

  • on this first day, the non-moderated ideas we have regarding users controlling YouTube API playlist content in more ways than we’ve allowed up to now …
  • on subsequent days, we are going to develop a moderation system allowing for “user requested” YouTube video ID contributions to any/all of …
    1. Disco
    2. The Wrecking Crew
    3. Yacht Rock

    … music genres we have associated with those Radio Play and single play buttons down the bottom, and instigated by the user via a double click on that left hand slivery table cell

In that first category we have two means by which user playlist content can be contributed …

Can redefine Disco or The Wrecking Crew or Yacht Rock playlists for this web browser tab (only) via entry like Disco=Klh7sAv9hu4,hMOORQ1Mt2s,k4V3Mo61fJM,-p6OH7FoWoQ,AIOAlaACuv4,HTzGMEfbnAw,CW_ZiojrkVY,FtE3hoR_Nvo#My Eight Songs
or to delete one via entry like The Wrecking Crew-
or to add into the mix (for this web browser usage) via entry like Yacht Rock+Klh7sAv9hu4,hMOORQ1Mt2s,k4V3Mo61fJM,-p6OH7FoWoQ,AIOAlaACuv4,HTzGMEfbnAw,CW_ZiojrkVY,FtE3hoR_Nvo#Eight Songs Into the Yacht Rock mix

… and the temporary (just current tab’s window.sessionStorage) nature of that first = means we can allow to forfeit moderation here and for the + means which uses URL calling arguments within the Javascript to achieve it’s work and we think, because a user can undo this web browser wide window.localStorage setting (via means), we see it as a non-moderation piece of functionality, too, in the changed swipe_media.html Tabular Single Row Media Gallery web application featuring a new Javascript function …


function storageideas() {
var ablurb='Can redefine Disco or The Wrecking Crew or Yacht Rock playlists for this web browser tab (only) via entry like Disco=Klh7sAv9hu4,hMOORQ1Mt2s,k4V3Mo61fJM,-p6OH7FoWoQ,AIOAlaACuv4,HTzGMEfbnAw,CW_ZiojrkVY,FtE3hoR_Nvo#My Eight Songs' + String.fromCharCode(10) + ' or to delete one via entry like The Wrecking Crew-' + String.fromCharCode(10) + ' or to add into the mix (for this web browser usage) via entry like Yacht Rock+Klh7sAv9hu4,hMOORQ1Mt2s,k4V3Mo61fJM,-p6OH7FoWoQ,AIOAlaACuv4,HTzGMEfbnAw,CW_ZiojrkVY,FtE3hoR_Nvo#Eight Songs Into the Yacht Rock mix';
var ansp=prompt(ablurb, '');
var buts=document.getElementsByTagName('button'), ibuts=0;
var spareihis='', sparerest='';

if (ansp == null) { return ''; }
if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('disco=') == 0) {
if (ansp.toLowerCase().indexOf('disco-') == 0) {
try {
window.sessionStorage.removeItem('disco_alt_list');
} catch (hgfh) { }
try {
window.localStorage.removeItem('disco_alt_list');
} catch (hgfh) { }
} else if (ansp.toLowerCase().indexOf('disco=') == 0) {
dvl='&videolist=' + encodeURIComponent(ansp.substring(('disco=').length).split('#')[0].split('&')[0]);
window.sessionStorage.setItem('disco_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
} else {
dvl='&listvideo=' + encodeURIComponent(ansp.substring(('disco=').length).split('#')[0].split('&')[0]);
window.localStorage.setItem('disco_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
}
if (ansp.substring(('disco=').length).replace(/\&/g,'#').indexOf('#') != -1) {
for (ibuts=0; ibuts<buts.length; ibuts++) {
if (buts[ibuts].innerHTML.indexOf('Disco') != -1) {
if (buts[ibuts].innerHTML.indexOf('<span') != -1) {
spareihis='<span' + buts[ibuts].innerHTML.split('<span')[1].split('</span>')[0] + '<span>';
sparerest=buts[ibuts].innerHTML.replace(spareihis,'');
buts[ibuts].innerHTML=spareihis + sparerest.replace(/Disco/g, ansp.substring(('disco=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
} else {
buts[ibuts].innerHTML=buts[ibuts].innerHTML.replace(/Disco/g, ansp.substring(('disco=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
}
}
}
}
} else if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('yacht rock=') == 0) {
if (ansp.toLowerCase().indexOf('yacht rock-') == 0) {
try {
window.sessionStorage.removeItem('yacht_rock_alt_list');
} catch (hgfh) { }
try {
window.localStorage.removeItem('yacht_rock_alt_list');
} catch (hgfh) { }
} else if (ansp.toLowerCase().indexOf('yacht rock=') == 0) {
yrvl='&videolist=' + encodeURIComponent(ansp.substring(('yacht rock=').length).split('#')[0].split('&')[0]);
window.sessionStorage.setItem('yacht_rock_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
} else {
yrvl='&listvideo=' + encodeURIComponent(ansp.substring(('yacht rock=').length).split('#')[0].split('&')[0]);
window.localStorage.setItem('yacht_rock_alt_list', encodeURIComponent(ansp.substring(('yacht rock=').length)));
}
if (ansp.substring(('yacht rock=').length).replace(/\&/g,'#').indexOf('#') != -1) {
for (ibuts=0; ibuts<buts.length; ibuts++) {
if (buts[ibuts].innerHTML.indexOf('Yacht Rock') != -1) {
if (buts[ibuts].innerHTML.indexOf('<span') != -1) {
spareihis='<span' + buts[ibuts].innerHTML.split('<span')[1].split('</span>')[0] + '<span>';
sparerest=buts[ibuts].innerHTML.replace(spareihis,'');
buts[ibuts].innerHTML=spareihis + sparerest.replace(/Yacht\ Rock/g, ansp.substring(('yacht rock=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
} else {
buts[ibuts].innerHTML=buts[ibuts].innerHTML.replace(/Yacht\ Rock/g, ansp.substring(('yacht rock=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
}
}
}
}
} else if (ansp.toLowerCase().replace('+','=').replace('-','=').indexOf('the wrecking crew=') == 0) {
if (ansp.toLowerCase().indexOf('the wrecking crew-') == 0) {
try {
window.sessionStorage.removeItem('the_wrecking_crew_alt_list');
} catch (hgfh) { }
try {
window.localStorage.removeItem('the_wrecking_crew_alt_list');
} catch (hgfh) { }
} else if (ansp.toLowerCase().indexOf('the wrecking crew=') == 0) {
twcvl='&videolist=' + encodeURIComponent(ansp.substring(('the wrecking crew=').length).split('#')[0].split('&')[0]);
window.sessionStorage.setItem('the_wrecking_crew_alt_list', encodeURIComponent(ansp.substring(('the wrecking crew=').length)));
} else {
twcvl='&listvideo=' + encodeURIComponent(ansp.substring(('the wrecking crew=').length).split('#')[0].split('&')[0]);
window.localStorage.setItem('the_wrecking_crew_alt_list', encodeURIComponent(ansp.substring(('the wrecking crew=').length)));
}
if (ansp.substring(('the wrecking crew=').length).replace(/\&/g,'#').indexOf('#') != -1) {
for (ibuts=0; ibuts<buts.length; ibuts++) {
if (buts[ibuts].innerHTML.indexOf('The Wrecking Crew') != -1) {
if (buts[ibuts].innerHTML.indexOf('<span') != -1) {
spareihis='<span' + buts[ibuts].innerHTML.split('<span')[1].split('</span>')[0] + '<span>';
sparerest=buts[ibuts].innerHTML.replace(spareihis,'');
buts[ibuts].innerHTML=spareihis + sparerest.replace(/The\ Wrecking\ Crew/g, ansp.substring(('the wrecking crew=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
} else {
buts[ibuts].innerHTML=buts[ibuts].innerHTML.replace(/The\ Wrecking\ Crew/g, ansp.substring(('the wrecking crew=').length).replace(/\&/g,'#').split('#')[1].replace(/\ /g,'<br>'));
}
}
}
}
}
}

… helping achieve this.


Previous relevant YouTube API Caller Radio Play Order Filled In Tutorial is shown below.

YouTube API Caller Radio Play Order Filled In Tutorial

YouTube API Caller Radio Play Order Filled In Tutorial

Going back to the Order and Completion themes of the previous YouTube API Caller Order and Completion Tutorial quite a while before the recent YouTube API Caller Radio Play Advice Tutorial

  • it worked awkwardly regarding, often the second video …
  • not preloaded to determine it’s …
    1. duration (where we say an interim duration of “-1”)
    2. title (where we say an interim title is “Will be filled in”)
  • and these would be properly updated when that video is next to be played

Well, this annoyed us, more than somewhat, and today we diagnosed the issues regarding …

  • the changed new important Javascript function …

    function mod_gtdzero(ineleven, indur, intit) {
    if (gelev != '' && gelev.trim() == gelev && gelev == ineleven) {
    gduris='' + indur;
    gtitis='' + intit;
    if (gtdzero.indexOf(gelev + '%23Will%20be%20filled%20in&j') != -1 && gtdzero.indexOf('=-1&') != -1) {
    gtdzero=gtdzero.replace('%23Will%20be%20filled%20in','').replace('=-1&', '=' + indur + '&').replace('&c1=off','&c1=on');
    }
    document.getElementById('navig').value=ineleven + ' ' + indur + ' ... ' + gtdzero.split('&j0=')[1];
    if (gtdzero.indexOf(gelev + '&j') != -1) {
    if (gtdzero.split(gelev + '&j')[1].split('=')[1].indexOf('22234') == 0 && ('' + gduris).indexOf('22234') == -1) {
    if (gtdzero.split(gelev + '&j')[1].split('=')[0] != '0') {
    gtdzero=gtdzero.replace('&c' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=off', '&c' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=on');
    gtdzero=gtdzero.replace('&j' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=22234' + gtdzero.split(gelev + '&j')[1].split('=')[1].split('22234')[1].split('&')[0] + '&', '&j' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=' + gduris + '&');
    gelev+=' ';
    } else {
    gelev+=' ';
    }
    } else if ((gtdzero.split(gelev + '&j')[1].split('=')[1].substring(0,1) < '0' || gtdzero.split(gelev + '&j')[1].split('=')[1].substring(0,1) > '9') && ('' + gduris).indexOf('22234') == -1) {
    if (gtdzero.split(gelev + '&j')[1].split('=')[0] != '0') {
    gtdzero=gtdzero.replace('&c' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=off', '&c' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=on');
    gtdzero=gtdzero.replace('&j' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=' + gtdzero.split(gelev + '&j')[1].split('=')[1].split('&')[0] + '&', '&j' + gtdzero.split(gelev + '&j')[1].split('=')[0] + '=' + gduris + '&');
    gelev+=' ';
    } else {
    gelev+=' ';
    }
    }
    } else if (gtdzero.split(gelev + '%23Will%20be%20filled%20in&j') != -1) {
    try {
    if ((gtdzero.split(gelev + '%23Will%20be%20filled%20in&j')[1].split('=')[1].substring(0,1) < '0' || gtdzero.split(gelev + '%23Will%20be%20filled%20in&j')[1].split('=')[1].substring(0,1) > '9') && ('' + gduris).indexOf('22234') == -1) {
    if (gtdzero.split(gelev + '%23Will%20be%20filled%20in&j')[1].split('=')[0] != '0') {
    gtdzero=gtdzero.replace('&c' + gtdzero.split(gelev + '%23Will%20be%20filled%20in&&j')[1].split('=')[0] + '=off', '&c' + gtdzero.split(gelev + '%23Will%20be%20filled%20in&&j')[1].split('=')[0] + '=on');
    gtdzero=gtdzero.replace('%23Will%20be%20filled%20in&j' + gtdzero.split(gelev + '%23Will%20be%20filled%20in&j')[1].split('=')[0] + '=' + gtdzero.split(gelev + '&j')[1].split('=')[1].split('&')[0] + '&', '&j' + gtdzero.split(gelev + '%23Will%20be%20filled%20in&j')[1].split('=')[0] + '=' + gduris + '&');
    gelev+=' ';
    } else {
    gelev+=' ';
    }
    }
    } catch(ytryutr) { gelev=''; }
    }
    }

    if (gtdzero.indexOf(ineleven + '&j') != -1) {
    if (gtdzero.split(ineleven + '&j')[1].split('=')[1].indexOf('22234') == 0 && ('' + indur).indexOf('22234') == -1) {
    if (gtdzero.split(ineleven + '&j')[1].split('=')[0] != '0') {
    gtdzero=gtdzero.replace('&c' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=off', '&c' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=on');
    gtdzero=gtdzero.replace('&j' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=22234' + gtdzero.split(ineleven + '&j')[1].split('=')[1].split('22234')[1].split('&')[0] + '&', '&j' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=' + indur + '&');
    }
    } else if ((gtdzero.split(ineleven + '&j')[1].split('=')[1].substring(0,1) < '0' || gtdzero.split(ineleven + '&j')[1].split('=')[1].substring(0,1) > '9') && ('' + indur).indexOf('22234') == -1) {
    if (gtdzero.split(ineleven + '&j')[1].split('=')[0] != '0') {
    gtdzero=gtdzero.replace('&c' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=off', '&c' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=on');
    gtdzero=gtdzero.replace('&j' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=' + gtdzero.split(ineleven + '&j')[1].split('=')[1].split('&')[0] + '&', '&j' + gtdzero.split(ineleven + '&j')[1].split('=')[0] + '=' + indur + '&');
    }
    }
    } else if (gtdzero.split(ineleven + '%23Will%20be%20filled%20in&j') != -1) {
    try {
    if ((gtdzero.split(ineleven + '%23Will%20be%20filled%20in&j')[1].split('=')[1].substring(0,1) < '0' || gtdzero.split(ineleven + '%23Will%20be%20filled%20in&j')[1].split('=')[1].substring(0,1) > '9') && ('' + indur).indexOf('22234') == -1) {
    if (gtdzero.split(ineleven + '%23Will%20be%20filled%20in&j')[1].split('=')[0] != '0') {
    gtdzero=gtdzero.replace('&c' + gtdzero.split(ineleven + '%23Will%20be%20filled%20in&&j')[1].split('=')[0] + '=off', '&c' + gtdzero.split(ineleven + '%23Will%20be%20filled%20in&&j')[1].split('=')[0] + '=on');
    gtdzero=gtdzero.replace('%23Will%20be%20filled%20in&j' + gtdzero.split(ineleven + '%23Will%20be%20filled%20in&j')[1].split('=')[0] + '=' + gtdzero.split(ineleven + '&j')[1].split('=')[1].split('&')[0] + '&', '&j' + gtdzero.split(ineleven + '%23Will%20be%20filled%20in&j')[1].split('=')[0] + '=' + indur + '&');
    }
    }
    } catch(hgfjhgfj) {
    if (6 == 4) {
    gelev=ineleven;
    gduris=indur;
    gtitis=intit;
    }
    }
    } else if (4 == 6) {
    gelev=ineleven;
    gduris=indur;
    gtitis=intit;
    }
    gccount++;
    }

    swipe_media.html Tabular Single Row Media Gallery web application … helped out by …
  • the modified calling

    if (top.document.getElementById('divtitles')) {
    if (top.document.getElementById('divtitles').innerHTML.indexOf('|' + parent.document.getElementById('youtubeid').value + '#') == -1) {
    if (('' + typeof window.top.mod_gtdzero) == 'function') {
    top.mod_gtdzero(parent.document.getElementById('youtubeid').value, parent.document.getElementById('youtube_duration').value, jtitl.replace(/\&\;/g,'and').replace(/\ \&\ /g,' and '));
    }

    top.document.getElementById('divtitles').innerHTML+='<span>' + parent.document.getElementById('youtube_duration').value + '</span><span>0|' + parent.document.getElementById('youtubeid').value + '#' + jtitl.replace(/\&\;/g,'and').replace(/\ \&\ /g,' and ') + '</span>';
    }
    }

    stop_start_youtube.html YouTube API caller

… calling the new shots. Aaaaaaaahhhhlll drinks to that?!


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

YouTube API Caller Radio Play Advice Tutorial

YouTube API Caller Radio Play Advice Tutorial

Regarding the recent YouTube API Caller Subsequent Post Winding Up For Now Tutorial‘s Tabular Single Row Media Gallery web application, we wanted to …

  • as far as Radio Play goes write some code … directing the user to …
  • not enforcing so much as encouraging the user not to click when the interim YouTube interfacing webpage screen happens, and a very tempting play button shows

… it being the case the authority rating on our inhouse web application will never match that of YouTube, and any YouTube play button that presents itself, but we want you to hang on not clicking that presented YouTube play button, until the playlist presents itself a little later on, where we want you to unmute to end the real interactions you have to make to start hearing YouTube video content.

And so, to encourage this …

  • we’d already written out some advice in English, but …
    1. it can be small
    2. it’s in English

    … and so in not doing the ideal job in terms of Internationalization thinking for how a user might work with this Radio Play mode of web application usage … and so, today, we’ve added …

  • during the interim webpage screen display, introduce …
    1. opacity: 0.6;
    2. border effects to left and right
    3. for non-mobile users a progress cursor on that table cell where the YouTube videos in Radio Play mode are being played

    … as well as …

  • a more noticeable and Internationization friendly “pseudo cursor” (available to both mobile and non-mobile) emoji set, as per …
    1. new shadowing array

      var cursanim=[' ',' | ', ' / ', ' - ', ' \ '];
      var cursanimtwo=[' ',' | ', ' / ', ' - ', ' \ '];
      if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || 2 == 2) { // phase of moon emojis for pseudo cursor purposes
      cursanimtwo[1]=' ' + String.fromCodePoint(127761) + ' ';
      cursanimtwo[2]=' ' + String.fromCodePoint(127762) + ' ';
      cursanimtwo[3]=' ' + String.fromCodePoint(127763) + ' ';
      cursanimtwo[4]=' ' + String.fromCodePoint(127764) + ' ';
      for (iij=127765; iij<=127768; iij++) {
      cursanimtwo.push(' ' + String.fromCodePoint(iij) + ' ');
      cursanim.push(cursanim[eval(eval(iij - 127764) % 5)]);
      }
      for (iij=127769; iij<=127772; iij++) {
      cursanimtwo.push(' ' + String.fromCodePoint(iij) + ' ');
      cursanim.push(cursanim[eval(eval(iij - 127768) % 5)]);
      }
      for (iij=127773; iij<=127773; iij++) {
      cursanimtwo.push(' ' + String.fromCodePoint(iij) + ' ');
      cursanim.push(cursanim[eval(eval(iij - 127772) % 5)]);
      }
      }

    2. new initial display measures regarding emoji based character(s) “pseudo cursor” content …

      <script type=text/javascript>
      // within head element ... downaways ...
      function postassoonas() {
      var huhpa=('' + document.getElementById('td0001').getAttribute('data-alt')).replace(/^undefined$/g,'').replace(/^null$/g,'');
      if (huhpa.indexOf('Playing ') == 0) {
      for (var ikh=1; ikh<cursanimtwo.length; ikh++) {
      cursanimtwo[ikh]=' ' + String.fromCodePoint(eval(128336 + eval(eval(-1 + ikh) % 12))) + ' ';
      }

      document.getElementById('td0000').style.borderRight='0px solid transparent';
      document.getElementById('td0001').style.borderLeft='0px solid transparent';
      document.getElementById('td0001').style.borderRight='0px solid transparent';
      document.getElementById('td0002').style.borderLeft='0px solid transparent';
      document.getElementById('td0001').style.opacity='1.0';
      document.getElementById('td0001').style.cursor='pointer';
      //document.getElementById('td0001').className='notapplicable';
      } else {
      setTimeout(postassoonas, 1000);
      }
      }

      function assoonas() {
      asa=true;
      if (document.getElementById('td0002')) {
      document.getElementById('td0000').style.borderRight='8px dashed orange';
      document.getElementById('td0002').style.borderLeft='8px dashed orange';
      document.getElementById('td0001').style.borderLeft='0px solid transparent';
      document.getElementById('td0001').style.borderRight='0px solid transparent';
      document.getElementById('td0001').style.opacity='0.6';
      document.getElementById('td0001').style.cursor='progress';
      //document.getElementById('td0001').className='eggtimer';
      window.opener.document.getElementById('td0000').style.borderRight='0px solid transparent';
      window.opener.document.getElementById('td0002').style.borderLeft='0px solid transparent';
      setTimeout(postassoonas, 1000);
      } else {
      setTimeout(assoonas, 1000);
      }
      }

      function as_soon_as() {
      asa=true;
      if (document.getElementById('td0002')) {
      document.getElementById('td0000').style.borderRight='8px dotted yellow';
      document.getElementById('td0002').style.borderLeft='8px dotted yellow';
      document.getElementById('td0001').style.borderLeft='0px solid transparent';
      document.getElementById('td0001').style.borderRight='0px solid transparent';
      document.getElementById('td0001').style.opacity='0.6';
      document.getElementById('td0001').style.cursor='progress';
      setTimeout(postassoonas, 1000);
      } else {
      setTimeout(postassoonas, 1000);
      }
      }


      // rest of head section Javascript follows
      </script>
      // in head element above
      <body>
      <script type=text/javascript>
      // within body element

      var asa=false;
      var dwfrom='youllneverfindthis';
      var dwto='youllneverfindthis';
      if (document.URL.indexOf('isradio=') != -1) {
      dwfrom=' style="min-width:';
      dwto=' style="opacity:0.6;cursor:progress;border-left:8px dotted yellow;border-right:8px dotted yellow;min-width:';
      }

      var bigline="      <button id=bdisco onclick=\"dodisco('bdisco=radnoiswas&');\" style='background-color:yellow;'>Disco<sup>A+V</sup> <span id=bdiscoavb title='Radio A+V ... double click for compilation' ondblclick=\"event.stopPropagation(); triplewhammy(this); \" onclick=\"event.stopPropagation(); setTimeout(function(){ dodisco('isradio=bdiscoavb&'); }, 2000);\" style='background-color:yellow;visibility:hidden;'>📻</span></button> <button id=bdiscoa onclick=\"dodisco('bdiscoa=radnoiswas&audio');\" style='background-color:yellow;'>Disco<sub>A-V</sub> <span id=bdiscob title='Radio A-V ... double click for compilation' ondblclick=\"event.stopPropagation(); triplewhammy(this); \" onclick=\"event.stopPropagation(); setTimeout(function(){ dodisco('isradio=bdiscob&audio'); }, 2000);\" style='background-color:yellow;visibility:hidden;'>📻</span></button>  <button id=bwc onclick=\"dowc('bwc=radnoiswas&');\" style='background-color:yellow;'>The Wrecking Crew<sup>A+V</sup> <span id=bwcavb title='Radio A+V ... double click for compilation' ondblclick=\"event.stopPropagation(); triplewhammy(this); \" onclick=\"event.stopPropagation(); setTimeout(function(){ dowc('isradio=bwcavb&'); }, 2000);\" style='background-color:yellow;visibility:hidden;'>📻</span></button> <button id=bwca onclick=\"dowc('bwca=radnoiswas&audio');\" style='background-color:yellow;'>The Wrecking Crew<sub>A-V</sub> <span id=bwcb title='Radio A-V ... double click for compilation' ondblclick=\"event.stopPropagation(); triplewhammy(this); \" onclick=\"event.stopPropagation(); setTimeout(function(){ dowc('isradio=bwcb&audio'); }, 2000);\" style='background-color:yellow;visibility:hidden;'>📻</span></button>  <button id=byr onclick=\"doyr('byr=radnoiswas&');\" style='background-color:yellow;'>Yacht Rock<sup>A+V</sup> <span id=byravb title='Radio A+V ... double click for compilation' ondblclick=\"event.stopPropagation(); triplewhammy(this); \" onclick=\"event.stopPropagation(); setTimeout(function(){ doyr('isradio=byravb&'); }, 2000);\" style='background-color:yellow;visibility:hidden;'>📻</span></button> <button id=byra onclick=\"doyr('byra=radnoiswas&audio');\" style='background-color:yellow;'>Yacht Rock<sub>A-V</sub> <span id=byrb title='Radio A-V ... double click for compilation' ondblclick=\"event.stopPropagation(); triplewhammy(this); \" onclick=\"event.stopPropagation(); setTimeout(function(){ doyr('isradio=byrb&audio'); }, 2000);\" style='background-color:yellow;visibility:hidden;'>📻</span></button>  <button id=recallable title=Saved onclick=\"recallit(this);\" style='background-color:orange;visibility:hidden;'></button>";
      if (window.opener) {
      if (document.URL.indexOf('isradio=') != -1 && document.URL.indexOf('youtube=') != -1) {
      if (!asa) { assoonas(); }
      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 {
      if (!asa) { as_soon_as(); } >
      radioblurb=' ... please wait for more than one checkbox checked before radio sequenced play is started above';
      }
      } else if (document.URL.indexOf('isradio=') != -1) {
      if (!asa) { as_soon_as(); } >
      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="' + cursanimtwo[cntcurs] + '" alt="Cell ' + kk + radioblurb + cursanimtwo[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>').replace(dwfrom,dwto);
      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 + cursanimtwo[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>').replace(dwfrom,dwto);
      }
      dwfrom='youllneverfindthis';
      dwto='youllneverfindthis';

      }
      // rest of Javascript after start of body element
      </script>
    3. new use of that shadowing array’s emoji based character(s) content …

      document.getElementById('td0001').setAttribute('alt', document.getElementById('td0001').getAttribute('alt').substring(0,altlen) + cursanimtwo[cntcurs]);
    4. dynamic emoji set change to differentiate the moon phase emoji set displayed before and into that interim webpage screen look and the hourly clock emoji set displayed once the user only has to unmute, and then there may not be any other interactions required by the user (though they can, just as they still can click the YouTube play button when the interim webpage screen is displaying …

      for (var ikh=1; ikh<cursanimtwo.length; ikh++) {
      cursanimtwo[ikh]=' ' + String.fromCodePoint(eval(128336 + eval(eval(-1 + ikh) % 12))) + ' ';
      }


      … but it’s just that we hope they don’t), at which point the three effects as listed above are undone, as well

… in the changed swipe_media.html Tabular Single Row Media Gallery web application.


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

YouTube API Caller Subsequent Post Winding Up For Now Tutorial

YouTube API Caller Subsequent Post Winding Up For Now Tutorial

Today, we’re conjoining … yes, conjoining … two inhouse blog posting threads, those being …

We think the former is a more savvy approach to YouTube API video “Radio Play” rather than the latter because the latter just works with crude setTimeout() delays based on the video being played straight through with no backtracking or non-video-play delays … and not continuous regarding mobile platforms.

However, we think the latter has it’s “action packed” merits regarding it’s details/summary reveal elements that add a bit of razzamatazz, and so we are conjoining … yes, conjoining … two inhouse blog posting thread web applications regarding …

  1. abilities to call each other off emoji button clicks …
  2. abilities to save to each other’s “Save” functionalities so that a potential “Recall” of a playlist becomes available to each of the web applications, separately, in that web application’s modus operandi regarding YouTube API video “Radio Play”

That should leave you free to try, either …

… as different takes on our inhouse ways regarding YouTube API video “Radio Play”, which we hope you enjoy!


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

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.


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 eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , | Leave a comment

Pairings Game Aesthetics Tutorial

Pairings Game Aesthetics Tutorial

Pairings Game Aesthetics Tutorial

We find with small projects like yesterday’s Pairings Game Makeover Tutorial‘s Pairings++ Game with such projects we often leave it to later to try to improve the aesthetics of the web application. As you can surmise surfing the net it is not always this way around with content creators, because to attract attention with anything, it is often the aesthetics that mean most. Even so, we prioritise the …

  • how it works … rather than …
  • what it looks like

… because we find the how a lot more interesting than the what but grant you it is pretty exciting when a touch of aesthetics really does improve a web application. In either case, the online world of online advice is great for either priority, and today, with the …


CSS styling

… phase of our project a make html button look 3d offered great ideas, thanks, for us to end up with this CSS …


<style>
button { height: 280px; width:95%; background-color: yellow; font-size:24px; overflow-wrap: anywhere; }
div { overflow-wrap: anywhere; color: blue; text-shadow:-1px 1px 1px #ff2d95; }

#iown { background-color: yellow; border-radius: 5px; }
#scells { background-color: pink; border-radius: 5px; }
#sdim { background-color: cyan; border-radius: 5px; }
#mytable { background-color: #f9f9f9; border-radius: 55px; }

/* Thanks to https://www.google.com/search?q=make+html+button+look+3d&rlz=1C5OZZY_en&oq=make+html+button+look+3d&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQIRigATIHCAIQIRigATIHCAMQIRigATIHCAQQIRifBTIHCAUQIRifBTIHCAYQIRifBdIBCDk4MDBqMGo0qAIAsAIB&sourceid=chrome&ie=UTF-8 */

.btn-3d {
/* Core Structure */
position: relative;
display: inline-block;
padding: 15px 30px;
/* font-size: 18px; */
text-shadow:-1px 1px 1px #ff2d95;
font-weight: bold;
cursor: pointer;

/* Remove Default Styling */
border: none;
outline: none;

/* Colors and Shape */
color: #ffffff;
background-color: lightgreen; /* Bright top surface */
border-radius: 12px;

/* 3D Edge Effect (No blur, offset downwards) */
box-shadow: 0 8px 0 #1899d6;

/* Smooth animation back to position */
transition: all 0.1s ease;
}

/* Hover State: Makes the button feel tactile */
.btn-3d:hover {
background-color: #24baff;
}

/* Clicked State: Moves the button down and shrinks the shadow */
.btn-3d:active {
box-shadow: 0 2px 0 #1899d6; /* Thinner side edge */
transform: translateY(6px); /* Pushes down to match shadow reduction */
}
</style>

… to include the changed and more complete CSS styling code into a “third draft” Pairings++ Game below more palatable.


Previous relevant Pairings Game Makeover Tutorial is shown below.

Pairings Game Makeover Tutorial

Pairings Game Makeover Tutorial

We often find that the “second draft” of a web application that represents a game or quiz can be a rewarding experience. The “first draft” of such web applications is often a “scurrying to represent those initial ideas before they are forgotten exercise”.

But a “second draft” can be done under less pressure, where ideas to extend the initial premise of the game or quiz, come far easier on revisiting and retesting. In that way, we extended into a “second draft” quite a few tinkerings …

  • make number of table cells a selectable setting (within reason)
  • make number of components within each synergy set a selectable setting (within reason)
  • allow the user to add their own rememberable synergy set(s)
  • allow the user to share their own rememberable synergy set(s) with an email or SMS recipient
  • add emoji tick or cross to score to indicate answer correctness
  • add seconds elapsed for those competitive players

… that, though minor by nature, and “optional”, of course, yet, can make the project, we had as of the day before yesterday’s Pairings Game Tutorial, far more interesting, we feel.

You can try the Pairings++ Game below, if you like.


Previous relevant Pairings Game Tutorial is shown below.

Pairings Game Tutorial

Pairings Game Tutorial

In this programming world, it is comforting to think of the “pairings” that go on. But it’s everywhere, the comfort a “pairing” can represent for people.

With this in mind, we designed a simple game …

  • the player is presented with 5 ideas of a “pairing” … it’s subjective, but …
  • we believe only one of these will score you a point by clicking on

… in this first draft Pairings Game whose tabular cell innards consist of 5 buttons and 5 overlaying …


var rectos=[];

function prepopulate() { // called at document.body onload
for (var icell=0; icell<5; icell++) {
rectos.push(document.getElementById('td' + eval(1 + icell)).getBoundingClientRect());
}
}

function populate() { // called whenever question changes
var fivebuts=[], fiveoverlays=[];
var makecorrect=Math.floor(Math.random() * 5), recto=null;
var interestg=-1, tg=-1;
sofarb=',';
sofaro=',';

for (var icell=0; icell<5; icell++) {
recto=rectos[icell]; //document.getElementById('td' + eval(1 + icell)).getBoundingClientRect();
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
if (makecorrect == icell) {
while ((sofarb + sofaro).indexOf(',' + interestg + ',') != -1) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
fivebuts.push(interestg);
fiveoverlays.push(interestg);
sofarb+='' + interestg + ',';
sofaro+='' + interestg + ',';
if (eval(Math.floor(Math.random() * 19876754) % 2) == 0) {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(1);>' + pairingsa[interestg].split('&')[1] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[0] + '</div>';
} else {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(1);>' + pairingsa[interestg].split('&')[0] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[1] + '</div>';
}
} else {
while (sofarb.indexOf(',' + interestg + ',') != -1) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
sofarb+='' + interestg + ',';
tg=interestg;
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
while ((sofarb + sofaro).indexOf(',' + interestg + ',') != -1 || tg == interestg) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
sofaro+='' + interestg + ',';
if (eval(Math.floor(Math.random() * 19876754) % 2) == 0) {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(0);>' + pairingsa[interestg].split('&')[1] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[tg].split('&')[0] + '</div>';
} else {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(0);>' + pairingsa[tg].split('&')[0] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[1] + '</div>';
}
}
}


}

… div elements (optionally we’ve decided to apply pointer-events:none; to, per game question.

Pretty, simple, huh?!

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

Pairings Game Makeover Tutorial

Pairings Game Makeover Tutorial

Pairings Game Makeover Tutorial

We often find that the “second draft” of a web application that represents a game or quiz can be a rewarding experience. The “first draft” of such web applications is often a “scurrying to represent those initial ideas before they are forgotten exercise”.

But a “second draft” can be done under less pressure, where ideas to extend the initial premise of the game or quiz, come far easier on revisiting and retesting. In that way, we extended into a “second draft” quite a few tinkerings …

  • make number of table cells a selectable setting (within reason)
  • make number of components within each synergy set a selectable setting (within reason)
  • allow the user to add their own rememberable synergy set(s)
  • allow the user to share their own rememberable synergy set(s) with an email or SMS recipient
  • add emoji tick or cross to score to indicate answer correctness
  • add seconds elapsed for those competitive players

… that, though minor by nature, and “optional”, of course, yet, can make the project, we had as of the day before yesterday’s Pairings Game Tutorial, far more interesting, we feel.

You can try the Pairings++ Game below, if you like.


Previous relevant Pairings Game Tutorial is shown below.

Pairings Game Tutorial

Pairings Game Tutorial

In this programming world, it is comforting to think of the “pairings” that go on. But it’s everywhere, the comfort a “pairing” can represent for people.

With this in mind, we designed a simple game …

  • the player is presented with 5 ideas of a “pairing” … it’s subjective, but …
  • we believe only one of these will score you a point by clicking on

… in this first draft Pairings Game whose tabular cell innards consist of 5 buttons and 5 overlaying …


var rectos=[];

function prepopulate() { // called at document.body onload
for (var icell=0; icell<5; icell++) {
rectos.push(document.getElementById('td' + eval(1 + icell)).getBoundingClientRect());
}
}

function populate() { // called whenever question changes
var fivebuts=[], fiveoverlays=[];
var makecorrect=Math.floor(Math.random() * 5), recto=null;
var interestg=-1, tg=-1;
sofarb=',';
sofaro=',';

for (var icell=0; icell<5; icell++) {
recto=rectos[icell]; //document.getElementById('td' + eval(1 + icell)).getBoundingClientRect();
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
if (makecorrect == icell) {
while ((sofarb + sofaro).indexOf(',' + interestg + ',') != -1) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
fivebuts.push(interestg);
fiveoverlays.push(interestg);
sofarb+='' + interestg + ',';
sofaro+='' + interestg + ',';
if (eval(Math.floor(Math.random() * 19876754) % 2) == 0) {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(1);>' + pairingsa[interestg].split('&')[1] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[0] + '</div>';
} else {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(1);>' + pairingsa[interestg].split('&')[0] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[1] + '</div>';
}
} else {
while (sofarb.indexOf(',' + interestg + ',') != -1) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
sofarb+='' + interestg + ',';
tg=interestg;
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
while ((sofarb + sofaro).indexOf(',' + interestg + ',') != -1 || tg == interestg) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
sofaro+='' + interestg + ',';
if (eval(Math.floor(Math.random() * 19876754) % 2) == 0) {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(0);>' + pairingsa[interestg].split('&')[1] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[tg].split('&')[0] + '</div>';
} else {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(0);>' + pairingsa[tg].split('&')[0] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[1] + '</div>';
}
}
}


}

… div elements (optionally we’ve decided to apply pointer-events:none; to, per game question.

Pretty, simple, huh?!

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, Games, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Canvas Interfacer Image Map Circle Tutorial

Canvas Interfacer Image Map Circle Tutorial

Canvas Interfacer Image Map Circle Tutorial

Further to the recent Canvas Interfacer Image Map Collaboration Tutorial‘s Image Map creation modes …

  • shape=rect … via 2 pointings … and …
  • shape=poly … via an initial click and a series of right click (non-mobile) and double click (mobile) ending polygon with up to 2 separated clicks … today we also allow for …
  • shape=circle … in the two modes of use the user enters as C0 or C2 at the first prompt window respectively …
    1. Image Map ends up just with shape=circle (rather than any shape=rect)
    2. Image Map ends up with shape=circle then shape=rect combinations (allowing for both to play their part, as required)

… to round out what Image Maps allow.

Again, rubberbanding in amongst HTML div element innerHTML SVG innards is the go, but for shape=circle we use SVG circle element types rather than the SVG polyline used for rubberbanding the shape=poly Image Map area subelements.

We hope you try …

… to see this in action.


Previous relevant Canvas Interfacer Image Map Collaboration Tutorial is shown below.

Canvas Interfacer Image Map Collaboration Tutorial

Canvas Interfacer Image Map Collaboration Tutorial

So far, with our currently running Image Map creating project yesterday’s Canvas Interfacer Mobile Image Map Tutorial continued on at, we’ve had a bit of focus on …

  • a single user getting as far into the Image Map creation process themselves because there are advantages to “strike while the iron is hot” marrying up Image Map area element positioning with a description, that can help later with stitching together Javascript event logic that can be useful making the Image Map … useful … but …
  • that doesn’t mean sharing and collaboration are of no use … perhaps the originator is a better designer than coder, for example

Anyway, that made us turn our attention to sharing and collaboration, email or SMS based, communication functionality, and we saw the two intervention points being …

  1. share the contents of the Image Map only HTML textarea element (with some default surrounding HTML and Javascript supplied) … and after a few double clicks, perhaps, the user might get to be able to …
  2. share the contents of the Image Map (with user tailored surrounding HTML and Javascript) textarea element

So how does a user make this happen? On mobile, it’s ontouchmove over the textarea concerned, where with non-mobile (you’re not going to like this, but we’ve run out of viable event types to use, so plumped for) onmouseout out of that textarea, to use. But won’t this get triggered too often? Well, we’ve coded for a couple of ways this can annoy less but still be that ever useful collaboration tool, via …


var hniis=false, hniisv='';

function shareask(tao) { // share Image Map outerHTML
var anchor=null, laterdo=null;
var proposedurlis='https://' + document.URL.split('//')[1].split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#imagemapize=' + encodeURIComponent(tao.value);
if (!hniis) {
laterdo=hniisv;
if (1 == 1) {
console.log('message length is ' + proposedurlis.length);
} else {
document.title='' + proposedurlis.length + ' ' + document.title;
}
if (laterdo == '') {
laterdo=prompt('Please enter an email address or SMS number to send the Image Map to. To not ask again regarding Image Map progress email or SMS communications in this session click Cancel. If your answer you are happy with from here on append a space to it.', hniisv);
}
if (laterdo == null) { hniis=true; laterdo=''; }
if (laterdo.indexOf('@') > 0) {
if (laterdo != laterdo.trim()) { hniisv=laterdo.trim(); }
anchor = document.createElement('a');
if (tao.value.indexOf('<html') != -1) { // (includes tailored HTML and Javascript around it)
anchor.href = 'mailto:' + laterdo.trim() + '?subject=' + encodeURIComponent('Image Map (includes tailored HTML and Javascript around it) ...') + '&body=' + encodeURIComponent(proposedurlis);
} else {
anchor.href = 'mailto:' + laterdo.trim() + '?subject=' + encodeURIComponent('Image Map (includes default HTML and Javascript around it) ...') + '&body=' + encodeURIComponent(proposedurlis);
}
anchor.style.display='none';
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
} else if (laterdo.trim() != '' && laterdo.trim().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,'') == '') {
if (laterdo != laterdo.trim()) { hniisv=laterdo.trim(); }
anchor = document.createElement('a');
anchor.href = 'sms:' + laterdo.trim() + '&body=' + encodeURIComponent(proposedurlis);
anchor.style.display='none';
anchor.innerHTML='SMS';
anchor.target='_top';
anchor.click();
}
}
}

… and we may improve the mechanism for this if Luna doesn’t snore tonight?!

Good ol’ hashtag data in emails or SMS comes into play here, and we found, even with Lorem Picsum images, we got viable results, though we found on mobile, the Gmail app “View Entire Message” hold finger down “Open Link” methodology was needed to get through. Gmail URL on macOS just needed the “View Entire Message” part of the workflow here.

Yet again, feel free to try …


Previous relevant Canvas Interfacer Mobile Image Map Tutorial is shown below.

Canvas Interfacer Mobile Image Map Tutorial

Canvas Interfacer Mobile Image Map Tutorial

On the same themes as yesterday’s Canvas Interfacer Three Finger Gesture Usage Tutorial‘s …

  • mobile platform chance to have three finger gestures help with scrolling functionality … today we have it so that …
  • mobile platforms are better suited creating Image Maps via canvas and image based inhouse web application (looking out for 🗺️🖼️ emoji button means to create Image Map when ready, as a double click on the canvas can do as well)

… our changes being helped out by the discovery that our previous …


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
// is identified around here as a mobile platform
}

… was a bit unreliable identifying mobile iOS platform Safari web browser usage, but this useful link got us to refine that thinking to …


if ( navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) > 0 ) {
// is better identified around here as a mobile platform
}

… with more success. Yayyyyy!

Along the way the HTML textarea elements used to identify Image Map subelement area rectangular limits have their disabled attribute set, which has the benefit …

  • that there is no need to allow any focus to these textarea elements when nothing any user can enter into them would make any difference anyway … and yet …
  • at least on non-mobile platforms the useful resizing talents of textarea elements are not stopped because of the disabled attribute being set

We found that the URL usage …


https://www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm#imagemap=url

… had become a little obsolete (at least, regarding the emoji button workflow), in the sense that, like with the canvas ondblclick event (ie. double click) functionality, why not, when clicking that 🗺️🖼️ Image Map creator emoji button grab the contents of the canvas already displaying as the default content presented to the “potential” (ie. it depends, sometimes, whether you double click that canvas element the next time) Image Map creation session?

Relevant to Random Background Image Map Area Polygons Tutorial and the decision then regarding non-mobile platforms to use an initial click followed by right clicks to enable Image Map area element shape=poly components, today, thinking with respect to mobile platforms, we’ve decided Image Map area element shape=poly components can be created via an initial click followed by double click sequences and going back to the polygon start, with either platform type, ending the polygon with two separated clicks. Also relevant to that same tutorial and it’s pointer-events:none; discovery, today’s mobile work regarding the textarea elements plotted to show the rectangular limits of user defined areas already created we found “real world relevance” to applying this to mobile such textarea elements. That is because on some mobile platforms these textarea elements will never be able to be resized out of the way, but if we apply pointer-events:none; to these, it does not matter, as the user can, as required, click/touch through these overlayed elements that have a huge z-index and semi-transparency applied to them.

Again, perhaps on a mobile platform web browser, feel free to try …

Did You Know?

There are known Safari mobile web browser textarea resizing limitations as we discovered trying a Google search of allow textarea resizing on mobile safari web browser, thanks, that we gleaned from the use of …

Solution 2: Standard JavaScript Auto-Grow
If you need to support older versions of iOS Safari that lack the newest CSS specs, you can dynamically update the box height using a tiny JavaScript event listener. This removes the scrollbar and expands the container vertically as they type:

HTML: html
<textarea id=”mobile-textarea” rows=”3″ oninput=”autoGrow(this)”></textarea>

JavaScript: javascript
function autoGrow(element) {
element.style.height = “auto”;
element.style.height = (element.scrollHeight) + “px”;
}

… incorporated ideas to help here.


Previous relevant Canvas Interfacer Three Finger Gesture Usage Tutorial is shown below.

Canvas Interfacer Three Finger Gesture Usage Tutorial

Canvas Interfacer Three Finger Gesture Usage Tutorial

There’s more research needed around here regarding mobile platform usage to the HTML5 canvas based ideas swirling around yesterday’s Random Background Image Map Area Polygons Tutorial‘s work, and one issue we came across was …

  • on mobile platforms you can get to gesture results whereby the canvas is all you see on the screen (eg. of an iPhone) …
  • but what if you are in “scribble mode” at that point?
  • before today, we were having trouble using …
    1. two finger “pinch” gesture to zoom out … or …
    2. one finger “swipe” to reveal more to the right (where, if we could have reached it, that right hand menu of annotation options has none of these “scribble mode” oddities) … because …
    3. before today, that last idea just drew a “scribble” “free drawing” line to the canvas

    … to reach the menu or any other non-canvas element not in “scribble mode” (ie. scrolling could not be achieved, at least in a way we could immediately access)

And so, we asked Google, thanks, “detect three finger gesture and if so scroll in the direction indicated” and got this useful advice …

Web Implementation (JavaScript)

If you are building this for a website or web app, you can use the touchstart and touchmove events to capture finger coordinates, check if exactly three fingers are on the screen, and then calculate the direction.

… to (start with globalvar isthree=false; and) end up with


if (eval('' + event.touches.length) >= 3 && event.type == "touchstart") {
isthree=true;
return;
} else if (isthree && event.type == "touchend") {
//if (isthree) {
isthree=false;
window.top.scrollBy(200,0);
return;
//}
}

… near the top of our function toptouchHandler(event) Javascript code in our changed signature_signature.js external Javascript canvas interfacer helper.


Previous relevant Random Background Image Map Area Polygons Tutorial is shown below.

Random Background Image Map Area Polygons Tutorial

Random Background Image Map Area Polygons Tutorial

Further to the recent Random Background Alternate Image Source Tutorial

  • Image Map only allowing for area subelements with shape=rect … today we also allow for …
  • Image Map now allowing for area subelements with shape=poly …

… via …

Right clicks after an initial click are the means by which you can define area shape=poly ( as distinct from the default shape=rect ) elements where to finish a polygon two click back close to the start point.

… as a modus operandi for the user to cater for more complex shape definitions in their Image Maps.

That doesn’t mean the rectangle around such a polygon is not also significant. Do you know why?

Yes, a hosting HTML div of a specific width and height and positioned absolutely at a precise left and top screen position allows SVG innerHTML like …


<svg xmlns="http://w3.org" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"><polyline points="0,67,56,7,100,0,150,17,0,67"></polyline></svg>
... be showing a polygonal user clicked shape, scaled appropriately, yet responsively, and allowing for those % unit definitions above making all this methodology useful here. Notice the zero co-ordinates? That is no accident. We make the co-ordinates relative to the minimum x and minimum y "datum" to the co-ordinating.

Feel free to try ...

Did You Know?

We broached the idea "pass event logic down through even though an element has a bigger z-index" to Google, thanks, and got back ...

To pass events down through a higher z-index element, add pointer-events: none; to the top element. This tells the browser to ignore the overlay for mouse events, allowing clicks and hovers to "fall through" to the element stacked beneath it.

... to learn a whole new technique we've been looking for for quite some time now ... now, where did we put that "Overlay Disappointments File"?! ... bye bye!


Previous relevant Random Background Alternate Image Source Tutorial is shown below.

Random Background Alternate Image Source Tutorial

Random Background Alternate Image Source Tutorial

Onto the recent Random Background Image Map Integration Tutorial's web application's use of ...

  • Lorem Picsum image repository "source" of image data ... today we allow the user to, instead, get images from ...
  • RJM Programming WordPress Tutorial Images (ie. this WordPress.org blog)

... and we've shored up the copy and pasting of screen logic, so that ...

  • the screen is more filled with image data, and the relevant graphical pasting place "border enhanced", in the process ...
  • the images have better resolution, in the process

... as the two areas of improvement within ...

... regarding it's newish Random Image Map integrations.


Previous relevant Random Background Image Map Integration Tutorial is shown below.

Random Background Image Map Integration Tutorial

Random Background Image Map Integration Tutorial

Like with ...

... and allowing users using our inhouse Random Background interfacer the chance to create some Image Maps using incarnations of these images as the visual basis to them.

We've chosen ...

  • the oncontextmenu (ie. right click) as an intervention point to facilitate this ... or ...
  • if using a macOS operating system a ...
    1. control-command-shift-3
    2. control-command-shift-5

    ...

    document.addEventListener('keydown', (event) => { // thanks to https://www.google.com/search?q=javascript+detecting+control-command-shift-3&rlz=1C5OZZY_en&oq=javascript+detecting+control-command-shift-3&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQIRigATIHCAIQIRigATIHCAMQIRigATIHCAQQIRigATIHCAUQIRiPAjIHCAYQIRiPAjIHCAcQIRiPAtIBCTE3NzMyajBqN6gCALACAA&sourceid=chrome&ie=UTF-8
    // Check if Control, Command (metaKey), and Shift are all held down
    // AND the key pressed is the number 3
    if (
    event.ctrlKey &&
    event.metaKey &&
    event.shiftKey &&
    event.code === 'Digit5'
    ) {
    // Prevent the default browser action if necessary
    //event.preventDefault();

    //var kc=eval(-2 + event.keyCode);

    event.preventDefault();
    event.stopImmediatePropagation();

    // Create a fake event with a modified code (e.g., ArrowDown)
    const simulatedEvent = new KeyboardEvent("keydown", {
    key: "3",
    code: "Digit3",
    ctrlKey: true,
    metaKey: true,
    shiftKey: true
    }); // keyCode: kc, bubbles: true, cancelable: true,

    // Fire the fake event into the DOM
    event.target.dispatchEvent(simulatedEvent);

    if (immap && !holdoff) { holdoff=true; setTimeout(function(){ wowo=window.open('/HTMLCSS/user_of_signature_signature.htm?askforpaste=y&imagemap=url#' + myco.toDataURL('image/jpeg',0.4), '_blank', 'top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height)); setTimeout(function(){ holdoff=false; }, 8000); }, 2000); }

    console.log('Control + Command + Shift + 3 combination detected!');
    // Insert your custom logic here
    }
    });

    ... combination is another modus operandi in play

... within ...

... regarding it's new Random Image Map integrations.


Previous relevant Inhouse Image Map WordPress Integration Tutorial is shown below.

Inhouse Image Map WordPress Integration Tutorial

Inhouse Image Map WordPress Integration Tutorial

The recent work of Inhouse Image Map Creator Browsing Tutorial ...

  • established a URL means by which a single URL call from the canvas residing Inhouse Image Map Creator and Canvas Annotation web application via a data URI hashtag conduit ... and today just ...
  • allowing for an absolute URL in that hashtag is the relatively simple change needed so that, using this, our WordPress "right click over an img image element" functionality can be tweaked ...


var huhifs=prompt('Optionally, please, any CSS for images ... append 3 spaces to be able to edit this ' + (gthing == 'image' ? gthing + ' (and answer of #imagemap will use this image as basis for creation of an image map in a new window)' : gthing) + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
if (huhifs == null) {
huhifs='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (event.target.outerHTML.indexOf('<a ') == 0) {
console.log(6);
ggurl=event.target.href;
} else {
console.log(66);
ggurl=document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="')[eval(-1 + document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="').length)].split('"')[0];
}
if (6 == 6) {
console.log(ggurl);
window.open(ggurl,'_blank'); ggurl='';
// huhifs=window.prompt('Optionally, please, any CSS for images ... append three spaces to be able to edit this ' + gthing + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
} else {
setTimeout(function(){ window.open(ggurl,'_blank'); ggurl=''; }, 5000); //alert(event.currentTarget.outerHTML); //event.currentTarget.click();
}
}
}
if (huhifs.toLowerCase() == '#imagemap') {
event.preventDefault();
event.stopPropagation();
ggurl=event.target.src;
window.open('//www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm?imagemap=url#' + (ggurl.indexOf('//') != -1 ? '//' + ggurl.split('//')[1] : (ggurl.replace(/^\.\//g,'/').indexOf('/') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(1).replace(/^\//g,'ITblog/') : (ggurl.indexOf('../') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(3) : ggurl))),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height));
ggurl='';
} else
if (huhifs.indexOf('data:image/') == 0) {
if (document.getElementById('imgcopycheck') && usuff != '') { //if (document.URL.indexOf('/streetart/') != -1) {
uplitc(huhifs); //alert(document.URL);
}
return '';
}

... as an excerpt from the changed onrightclick.js external Javascript called by WordPress, and calling ...


Previous relevant Inhouse Image Map Creator Browsing Tutorial is shown below.

Inhouse Image Map Creator Browsing Tutorial

Inhouse Image Map Creator Browsing Tutorial

Repeat after me ...

an image is a canvas is an image

?

an image is a canvas is an image

... good, now, again ... an image is a canvas is an image ...

an image is a canvas is an image

... excellent, now, backwards ... egami na si savnac a si egami na ...

egami na si savnac a si egami na

... wow! ... Now, lastly … I want my mamma! Now! ...

I want my mamma! Now!

 

But it's true. Our thinking behind allowing browsed for image files become data URIs that can be the img element "image" part of the "image map", further to yesterday's Inhouse Image Map Creator Mobile Debug Tutorial, we can now create using our inhouse Image Map Creator capable web application uses the "an image via [canvasContext].drawImage() is a canvas via [canvas].toDataURL() is an image" concept that can save us heaps of time with this project. Instead of intervening at each dropdown option mentioning "Browse" to make this design change, we, instead, introduce to the HTML5 canvas element a new ondblclick event ...


<canvas ondblclick="qwowo=window.open(document.URL.split('?')[0].split('#')[0] + '?imagemap=url#' + this.toDataURL('image/jpeg',0.4),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height) + '');" ondragstart="dragstart(event);" draggable="false" title="Ready for you to create your canvas 🎨 content above any signature 💳 panel ... keys U for Undo and R for Redo can work after a discrete click ending any scribble mode of use. Double click can facilitate turning this canvas content into an image map, and this canvas content can be populated by so many of the options in the menu to the right, which includes many local image file browsing choices." id="topcanvas" width=850 height=600 style="background-color:white; position: absolute; top:0; left:0; border-bottom:5px solid yellow; border-right:5px solid blue;"></canvas>

... allowing that "on double click" result in the web application turning into an Image Map Creator where now ...

Image Map ( ie. <img src="[image URL as entered by user or data URI browsed for by the user, or, come to think of it, from a couple of days back, entered in by the user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... is that very pithy redefinition of our web application's view of what an Image Map can be! Though?!

 

Again, feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Mobile Debug Tutorial is shown below.

Inhouse Image Map Creator Mobile Debug Tutorial

Inhouse Image Map Creator Mobile Debug Tutorial

Apologies to any mobile users wanting to access this new inhouse Image Map creator web application last talked about with yesterday's Inhouse Image Map Creator Interactive Drill Down Tutorial before today, that is, but we were leaving the issue until a proper hardware ...

  • Mac Book Air
  • Apple white lead
  • iPhone

... that once the middle one plugs into the top and bottom allows for ...

  • iPhone Safari web browser call of the inhouse Image Map creator ... could tee up with (ie. attain a "connection" with) ...
  • Mac Book Air Safari web browser Develop -> (in our case) Robert's iPhone -> user_of_signature_signature.htm

... online debugging session, could be arranged and a block of time set aside to concentrate on, because "concentrate" is the name of the game here!

Luckily, the issue was straightforward, where many are not. In the overseeing code, we had ...


<script type=text/javascript>
var oklj=0;
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || document.URL.indexOf('?fcol=') != -1) {
oklj=oklj;
} else {
document.write("<iframe id=ifconto name=ifconto src='/PHP/animegif/tutorial_to_animated_gif.php#rand=" + Math.floor(Math.random() * 19878675) + "' style='width:100%;height:900px;display:BLOCK;'></iframe>");
}
</script>

... ba bow ... because in the external Javascript we got pulled up by the debugging of the iPhone execution attempt at a codeline, where the user decides to take on an Image Map creation task ...


top.document.getElementById('ifconto').src='/About_Us.html';

... ba bow. On mobile, that necessary HTML iframe was non-existant! So, with the external Javascript, at this similar juncture, we came up with ...


if (!top.document.getElementById('ifconto')) {
top.document.body.innerHTML+="<iframe id=ifconto name=ifconto src='/About_Us.html' style='width:100%;height:900px;display:none;'></iframe>";
} else {

top.document.getElementById('ifconto').src='/About_Us.html';
}

... to start getting somewhere, here, with these inhouse Image Map creation ideas on mobile platforms.

And what about ...

  1. allow for data URIs pasted into the prompt window
  2. create non-mobile rubber banded overlays to help contextualize further

? Huh?! Feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Interactive Drill Down Tutorial is shown below.

Inhouse Image Map Creator Interactive Drill Down Tutorial

Inhouse Image Map Creator Interactive Drill Down Tutorial

It might be the case, often, with Image Map creations, as with our recent web application featuring in yesterday's Inhouse Image Map Creator Drill Down Tutorial that the user needs to ...

strike while the iron is hot

... regarding having the event logic be nuanced as the image map area subelements are created in terms of ...

  • area subelement inline event logic definitions (pointing at, perhaps, local Javascript functions) ... as well as ...
  • the content of those local Javascript functions

... in such a way that, if you come back to "flesh out" the image map HTML coding the next day, say, there are enough clues you've left that you do not have to go and match the "coords" attribute values to a screen position to get some context. That takes a lot longer we find.

And so, today, we now offer ...

Enter an Image URL (append space to create Image Maps where click/tap pairs can define rectangle corners ... cursor is a crosshair for lower left click/tap, first, then cursor is pointer top right ... append another one space to prompt for tailored event logic each time and two spaces to also review the default Javascript used for double click logic image map testing purposes ... we are going to discourage scrolling here, but you can still zoom out or in)

... Javascript prompt windows "on the fly" to allow for this to be a possibility for the Image Map creator using ...


Previous relevant Inhouse Image Map Creator Drill Down Tutorial is shown below.

Inhouse Image Map Creator Drill Down Tutorial

Inhouse Image Map Creator Drill Down Tutorial

Onto yesterday's Inhouse Image Map Creator Tutorial we've decided today's work should stay within non-mobile realms but flesh out more user available functionality to help with "stage two" thinking. With that in mind ...

  • the image map HTML containing textarea created (with yesterday's efforts using the Canvas and Image Map web application (now featuring a new emoji button 🗺️🖼️ to allow for a non-dropdown usage approach)) has an ondblclick event logic added so that when double clicking, at any stage of the image map creation processing, it ...
  • opens a new popup window where that HTML you have so far is surrounded by a default "rest of webpage" scenario as the HTML that goes into making up that popup window HTML content, and where you can test out it's workings ... as well as ...
  • that popup window image map, itself, is given an ondblclick event logic whereby a double click there can create below that image map within the same popup window a new textarea element containing all that HTML (default "rest of webpage" and all) which can be copied into a clipboard buffer as required ... and ...
  • if that textarea within the popup window is edited and the user double clicks that textarea element, a new popup window reflecting your changes is opened above that ... etcetera etcetera etcetera

All this can be used to either/both validate your image map and follow through further to incorporating the image map into a functional HTML webpage, using the changed signature_signature.js external Javascript to make all this possible. Within that changed external Javascript we allow the user to cancel the proposed area subelement currently embarked upon between where the user has clicked/tapped the bottom left and before they shape to click/tap the top right rectangle definition, via a right click, so as to reset back to the click/tap using the crosshair cursor back at a bottom left area shape=rect subelement definition.


Previous relevant Inhouse Image Map Creator Tutorial is shown below.

Inhouse Image Map Creator Tutorial

Inhouse Image Map Creator Tutorial

The "largely canvas" using web application last talked about with WordPress Blog Image Editing Media Tutorial, today, we're excited to announce, has been given an "on first draft just image URL" using new ...

Image Map ( ie. <img src="[image URL as entered by user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... arrangement inhouse means to construct image maps, so far, just via an image URL.

Why hook into the largely canvas savvy web application? Well, it is that basic positional mouse event logic that is needed to create image maps, and here, it is a dominant theme, and useful, even though the rearrangement of data needed is quite substantial, still, that is where we think this new functionality appears most at home, being a new suboption ("Image 🖼 Canvas Matches Actual URL or Image Map rectangle area creations") off a dropdown option means of deploying.

No tests on mobile, yet, but on non-mobile, we're happy, once the user chooses to create Image Maps, so long as ...

  1. we stop user web page scrolling ... while still allowing ...
  2. webpage zooming out or in

... in conjunction with ...

  • replacing the webpage table's left cell content, which used to contain a canvas element, with the user defined image, via it's URL ...
  • replacing the webpage table's right cell content, which used to contain an canvas annotation menu, with the image map URL HTML built up from user lower left and upper right rectangle defining click/taps

... we have the wherewithal to create image map HTML code the user can copy and use, with "stage two" fleshing out!

Try this at ...

... to allow for this image map inhouse functionality. The talents of HTML textarea elements, with their resizing abilities, helps out here, allowing these overlayed textarea elements ...

  1. containing image map HTML ... and/or ...
  2. overlaying semi-transparentally to see what has been clicked already

... also be able to be resized "out of the way" should that be needed perhaps regarding overlapping scenarios, without having to resort to any other type of event logic to allow for. The other big and relevant talent of textarea elements is their ability to contain HTML code and be editable with that HTML code, perhaps user amended, and to be able to Select All then Copy into a clipboard buffer, via it's right click web browser menu, ready to paste somewhere else, that HTML content ready for any required "stage two" embellishment and usage.


Previous relevant WordPress Blog Image Editing Media Tutorial is shown below.

WordPress Blog Image Editing Media Tutorial

WordPress Blog Image Editing Media Tutorial

We're happy to be revisiting ...

... to add to our recent WordPress Blog Image Editing functionality, extending it's capabilities to be able to optionally create either/both ...

  • Video
  • Animated GIF

... media presentations off this should the user pick more than one image, to be edited, in any one web browser tab (via window.sessionStorage) session. So far, we're creating ...

  • window.open
  • background image
  • background-size: contain

... "Video" and "Animated GIF" presentations, and see this as a shareable commodity, into the future, especially as the image slide data ends up being an HTML canvas [canvas].toDataURL() data URI that represents ...

  1. lots of data
  2. but understood everywhere

... and content wise has included within it, any canvas manipulations and annotating and reworking the user has applied plus, at least for Google Chrome, any image filtering CSS the user has requested, into that canvas. We shape to involve the cowsay actual web server disk based media creating interfacing, but not for now. We'll see, because WordPress Visual Synopsis Media Tutorial methodologies also ended up presentation wise, with "inhouse" "Video" and "Animated GIF" presentations.

How does the user make this happen? Well, at the opportune call of our Canvas Image Editor web application some "Mantissa MadnessMagic" takes place using ...


if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").indexOf('.') != -1) {
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]))) {
if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "") >= '1') {
setTimeout(function(){
if (document.getElementById('storyboard') && document.getElementById('toptd')) {
document.getElementById('toptd').innerHTML=document.getElementById('toptd').innerHTML.replace(document.getElementById('storyboard').outerHTML, '  <button onclick="top.videoshow();">Video &#128249;</button>  <button onclick="top.agshow();">Animated GIF &#128444;</button> ' + document.getElementById('storyboard').outerHTML);
}
}, 8100);
}
setInterval(function(){
var mycisv=document.getElementById('topcanvas');
var mycisvcon=mycisv.getContext('2d');
var mycanc=mycisv.toDataURL('data/jpeg', 10);
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value.length != mycanc.length) {
top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value=mycanc;
top.agup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
top.vdup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
}
}, 10000);
}
}

... to look like ...

    

... appearing in the right cell hosted Annotation Menu tools of the changed user_of_signature_signature.htm inhouse image data fed canvas editor web application.

The fourth draft onrightclick.js external Javascript now includes those onclick logic event functions ...


function agshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var ist=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts; } else { document.title=dtp + dtstwo; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist++; setTimeout(startit, 5000); } setTimeout(startit, 2000); </scr' + 'ipt>';
woagis=window.open('','_blank','top=110,left=110,width=700,height=700');
woagis.document.write('<html><head><title>Animated GIF of selected images ... start of looping presentation ...</title>' + ascr + '</head><body style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

function videoshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var verbs=[" paused"," playing"], ist=0, inc=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation ", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts + verbs[inc]; } else { document.title=dtp + dtstwo + verbs[inc]; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist+=inc; setTimeout(startit, 1000); } setTimeout(startit, 1000); </scr' + 'ipt>';
wovdis=window.open('','_blank','top=100,left=100,width=700,height=700');
wovdis.document.write('<html><head><title>Video of selected images ... start of looping presentation </title>' + ascr + '</head><body title="Initially paused but on loop when started. Click to toggle between pause and play." onclick="inc=eval(1 - inc);" style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

... creating those popup window "Video" and/or "Animated GIF" presentations we've been talking about above.

The WordPress Blog TwentyTen theme's header.php gets a crucial new Javascript function referenced elsewhere ...

<?php echo "

function firstuptop() {
var ifnum=1, arrc=['cow', 'ime'], butsuff='', arrbw=['', ' of Selected Images'], arrolp=['vif','ime'];
var utd='<div id=divime style=display:none;>';
for (var jime=0; jime<2; jime++) {
if (jime > 0) {
utd+="</b><br><iframe name=my" + arrc[jime] + "ifr id=my" + arrc[jime] + "ifr style=display:none; src=/About_Us.html></iframe><form target=my" + arrc[jime] + "ifr action=/cowsay.php method=POST id=my" + arrc[jime] + "pf><div id=div" + arrc[jime] + "pf></div><input type=submit id=vlist" + butsuff + " style=display:none;background-color:lightblue; name=vlist" + butsuff + " value='Video &#128249; " + arrbw[jime] + "'></input> <input type=submit style=display:none;background-color:lightblue; id=aglist" + butsuff + " name=aglist" + butsuff + " value='Animated GIF &#128444; " + arrbw[jime] + "'></input></form><table cellpadding=20><tbody><tr></tr></tbody></table></div><p id='backtoblog'></p>";
}
butsuff='ime';
}
utd+='</div>';
document.body.innerHTML+=utd;
}

"; ?>

... to help create, within the blog posting webpage content, the HTML skeletal necessaries modelled on how WordPress Visual Synopsis Media Tutorial worked it for Visual Synopsis (Slideshows) functionality which included inhouse "Video" and/or "Animated GIF" media presentations.


Previous relevant WordPress Blog Posting Feature Image Editing Tutorial is shown below.

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

Yesterday's ...

  • One Image Website Image Snapshot Editing Tutorial used web browser new tab webpages to allow for image editing and annotating ... but with today's ...
  • WordPress Blog Posting Feature Image Editing Tutorial we're using a hosted HTML iframe window within the blog posting webpage of interest

And that should be a lot easier to handle, yes?! Well, yes, maybe, but not that much easier. A little bit "easier" because the logic is largely funnelled into code that is common to both modus operandi.

In amongst the commonalities, thankfully, the means to get to the "image editing and annotating" and/or "image styling" functionality remains ...

Non-mobile right click or spread/pinch mobile gesture on most blog posting images can lead to image editing and annotating functionality, where for animated GIFs first slide is chosen.

We learnt a bit making the mobile ontouchend spread/pinch detection more bulletproof ...


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
setTimeout(function(){
document.ontouchend=function(e){
if (document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') != -1) {
lastsp=eval(e.touches.length);
}
if (eval('' + e.touches.length) >= 1) {
if (document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') == -1) {
onrightclickask();
} else if (e.touches[0].target.outerHTML.split('>')[0].indexOf('<img ') == 0 && e.touches[0].target.outerHTML.split('>')[0].indexOf(' tabindex=') != -1) {
onrightclickask(); //document.title=':' + e.touches[0].target.outerHTML.split('>')[0].substring(1);
}

}
};
}, 4000);
}

... but ahead of this, for the TwentyTen theme changes to codex webpage structure we predominantly do with a good ol' tailored header.php the most effective modified (which is new) codeline now goes ...

<?php

$post->post_content=str_replace('<i' . 'mg' . ' i' . 'd=', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); i' . 'd=', str_replace('<i' . 'mg' . ' s' . 'rc=', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); s' . 'rc=', str_replace('<i' . 'mg' . ' st' . 'yle="border', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); st' . 'yle="border', str_replace('<i' . 'mg' . ' st' . 'yle="float', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); st' . 'yle="float', str_replace('<i' . 'mg' . ' deco' . 'ding=', '<i' . 'mg' . ' tabindex=0 onconte' . 'xtmenu=imgedit(event); ontou' . 'chend=imgedit(event); deco' . 'ding=', $post->post_content)))));

?>

... calling new Javascript function ...

<?php echo "

function imgedit(evt) {
if (('' + evt.target.outerHTML.split('>')[0]).indexOf(' class="iiconlist') == -1) {
preonrightclickask(evt);
}
}

"; ?>

Other than header.php WordPress PHP code we changed ...


Previous relevant One Image Website Image Snapshot Editing Tutorial is shown below.

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

Augmenting yesterday's One Image Website SessionStorage Image Filtering Tutorial adding cropped image editing functionality, we see it as ...

Running against us regarding One Image Website design .. Running for us regarding One Image Website design ...
the programmatical scrolling means embedded iframe hosting will not work way window.prompt freezes all Javascript at a snapshot of time ...
hashtag navigation can be the conduit to pass data onto inhouse Canvas Editor of Image Data
[canvasContext].drawImage has a variety of useful calls (in that OOP method feel) allowing for dynamic cropping

That "one against" stopped how we envisaged the work at the start of the day. We thought we'd use window.sessionStorage (or maybe window.localStorage) as the only data conduit needed, and we'll be continuing that idea with another approach into the future, but back to today, hashtagging provided that conduit means, even if we were using data URIs (though all we need today are image absolute URLs).

And then there was "the unknown factor" ...

Can [canvasContext].drawImage draw that image with CSS filter styling applied?

Well, we found using Javascript DOM ahead of the new Image() call ...


xcelem=document.getElementById('topcanvas');
xccontext = xcelem.getContext("2d");
xcimg=new Image;
xcimg.onload = function(){
var mysx=('' + window.sessionStorage.getItem('user_of_signature_signature_sx')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sx')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The x coordinate where to start clipping
var mysy=('' + window.sessionStorage.getItem('user_of_signature_signature_sy')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sy')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The y coordinate where to start clipping
var myswidth=('' + window.sessionStorage.getItem('user_of_signature_signature_swidth')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_swidth')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The width of the clipped image
var mysheight=('' + window.sessionStorage.getItem('user_of_signature_signature_sheight')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sheight')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The height of the clipped image
var myx=('' + window.sessionStorage.getItem('user_of_signature_signature_x')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_x')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // The x coordinate where to place the image on the canvas
var myy=('' + window.sessionStorage.getItem('user_of_signature_signature_y')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_y')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // The y coordinate where to place the image on the canvas
var mywidth=('' + window.sessionStorage.getItem('user_of_signature_signature_width')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_width')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The width of the image to use (stretch or reduce the image)
var myheight=('' + window.sessionStorage.getItem('user_of_signature_signature_height')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_height')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The height of the image to use (stretch or reduce the image)
if (mywidth != '' && myheight != '') {
xcelem.width=eval('' + mywidth);
xcelem.height=eval('' + myheight);
if (('' + xcimg.style.filter).replace(/^undefined/g,'').replace(/^null/g,'').trim() != '') {
xccontext.filter=xcimg.style.filter;
}
if (myx != '' && myy != '' && myswidth == '' && mysheight == '') {
xccontext.drawImage(xcimg,eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight));
setTimeout(function(){ xccontext.drawImage(xcimg,eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight)); }, 3000);
window.sessionStorage.removeItem('user_of_signature_signature_x');
window.sessionStorage.removeItem('user_of_signature_signature_y');
window.sessionStorage.removeItem('user_of_signature_signature_width');
window.sessionStorage.removeItem('user_of_signature_signature_height');
} else {
xccontext.drawImage(xcimg,eval('' + mysx),eval('' + mysy),eval('' + myswidth),eval('' + mysheight),eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight));
setTimeout(function(){ xccontext.drawImage(xcimg,eval('' + mysx),eval('' + mysy),eval('' + myswidth),eval('' + mysheight),eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight)); }, 3000);
window.sessionStorage.removeItem('user_of_signature_signature_sx');
window.sessionStorage.removeItem('user_of_signature_signature_sy');
window.sessionStorage.removeItem('user_of_signature_signature_swidth');
window.sessionStorage.removeItem('user_of_signature_signature_sheight');
window.sessionStorage.removeItem('user_of_signature_signature_x');
window.sessionStorage.removeItem('user_of_signature_signature_y');
window.sessionStorage.removeItem('user_of_signature_signature_width');
window.sessionStorage.removeItem('user_of_signature_signature_height');
}
} else {
xcelem.width=xcimg.width;
xcelem.height=xcimg.height;
if (('' + xcimg.style.filter).replace(/^undefined/g,'').replace(/^null/g,'').trim() != '') {
xccontext.filter=xcimg.style.filter;
}
xccontext.drawImage(xcimg,0,0);
setTimeout(function(){ xccontext.drawImage(xcimg,0,0); }, 3000);
}
if (window.parent) {
if (parent.document.getElementById('if_image_canvas')) {
if (('' + parent.document.getElementById('if_image_canvas').style.height).replace('px','').trim() != '') {
if (eval('' + ('' + parent.document.getElementById('if_image_canvas').style.height).replace('px','').trim()) < eval(200 + eval('' + xcelem.height))) {
parent.document.getElementById('if_image_canvas').style.height='' + eval(200 + eval('' + xcelem.height)) + 'px';
}
} else {
parent.document.getElementById('if_image_canvas').style.height='' + eval(200 + eval('' + xcelem.height)) + 'px';
}
parent.document.getElementById('if_image_canvas').style.display='block';
if (parent.document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') != -1) {
parent.document.getElementById('if_image_canvas').scrollIntoView();
}
}
}
};
var incomings=('' + window.sessionStorage.getItem('user_of_signature_signature_filter')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_filter')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The image filter CSS styling to apply
if ((incomings.indexOf('%20') != -1 || 7 == 7) && incomings.replace(':',')').indexOf(')') != -1 && incomings.indexOf('style=') != -1) {
incomings='style=' + encodeURIComponent((incomings.split('style=')[1].split('&')[0].split('#')[0]).replace(/\%20/g,' ').replace(/\+/g,' '));
}
var relincomings=incomings.split('style=')[1] ? decodeURIComponent(incomings.split('style=')[1].split('&')[0].split('#')[0]).replace(/\%20/g,' ').replace(/\+/g,' ') : '';
if (relincomings.indexOf('filter:') != -1) {
xcimg.style.filter=relincomings.split('filter:')[1].split(';')[0].split('}')[0];
}
xcimg.src=xcont;

... didn't help, and then we asked the online woooorrrrrllllddd to come across this very useful link, thanks to teach us ...

That [canvasContext].filter is a thaing ... yay!!!

Luckily we didn't need to change One Image Website base HTML to make this happen, but, rather ...

... with the user able to make this happen with those right click (non-mobile) or pinch or swipe gesture (mobile) actions (talked about with yesterday's One Image Website SessionStorage Image Filtering Tutorial) getting the user to a prompt window with the modified "blurb" ...

Optionally, please, any CSS for images ... append three spaces to be able to edit this screenshot in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. filter: grayscale(100%);

... talking about the three appended spaces needed.


Previous relevant One Image Website SessionStorage Image Filtering Tutorial is shown below.

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

Further to the long ago One Image Website Scrolling Position Fix Tutorial last mention of our inhouse One Image Website series, today we have ...

  • clientside image filtering functionality to offer ...
  • almost exclusively using window.sessionStorage ideas (rather than our usual window.localStorage (ie. like Cookies) usage)

Why is that last point any big deal? Well, programmers will tell you, often the tidy up of a new arrangement involves as much, or more, coding to do than the instigation. And a lot of programmers, am sure, will agree that that is a pain in the neck, often. But the use of window.sessionStorage at the expense of window.localStorage allows the programmer to go ...

Aaaaaahhhhh

There is so much less to tidy up. Using window.sessionStorage it is only data on that web browser tab that comes into play, and as soon as that web browser tab no longer exists, nor does the window.sessionStorage data you stored. Yayyyyyyy!

We found we couldn't quite make it exclusively with window.sessionStorage because in the One Image Website paradigm of offering music playing we lost window.sessionStorage data for one of the two web browser tabs that become involved to start the music rolling. So sad. Nevertheless, we transferred some controllable temporary window.localStorage data storage over to window.sessionStorage data storage at the opportune time ...


if (('' + window.localStorage.getItem(prefss + '_filter')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
if (('' + window.sessionStorage.getItem(prefss + '_filter')).replace(/^undefined/g,'').replace(/^null/g,'') == '') {
window.sessionStorage.setItem(prefss + '_filter', window.localStorage.getItem(prefss + '_filter'));
window.localStorage.removeItem(prefss + '_filter');
} else {
window.localStorage.removeItem(prefss + '_filter');
}
}

... (we figured after a day of tinkering ... so sad).

How can the non-mobile user access these new aesthetic settings? Via a right click, as our new unfettered layer of functionality option, encapsulated by onrightclick.js external Javascript "proof of concept" effort, on the way to a Javascript prompt window, is the way we've gone about it. From there, the user can enter CSS non-selector actions such as the use of CSS filter property.

And as such, it's worth a revisit of one or all of our reworked One Image Website web applications ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately

... or you can start them off yourself up at the address bar with (typed in ... or just click) URLs such as ...


https://www.rjmprogramming.com.au/thecommute/?style=filter:invert(100%);

... or ...


https://www.rjmprogramming.com.au/ephemeral/?style=filter:blur(5px);

... or ...


https://www.rjmprogramming.com.au/streetart/?style=filter:hue-rotate(90deg);

... or ...


https://www.rjmprogramming.com.au/pyrmontultimo/?style=filter:sepia(100%);

... or ...


https://www.rjmprogramming.com.au/walkingtrip/?style=filter:saturate(200%);

... or ...


https://www.rjmprogramming.com.au/bygone/?style=filter:contrast(200%);

... or ...


https://www.rjmprogramming.com.au/thewest/?style=filter:brightness(240%);

Did you know?

All this begs the question ...

What about mobile?

Well, at least for iOS we think ...


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
setTimeout(function(){
document.ontouchend=function(e){
if (eval('' + e.touches.length) >= 1) {
onrightclickask();
}
};
}, 4000);
}

... did the job, with a pinch or swipe gesture, of getting us to that Javascript prompt window place, and then the rest is the same!


Previous relevant One Image Website Scrolling Position Fix Tutorial is shown below.

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

Today, we've bitten the bullet, and decided to shore up the webpage scrolling issues that could occur in yesterday's One Image Website VTT Tracks Tutorial, and before, with our set of One Image Websites. They represent, perhaps, a slightly unusual scenario whereby the image data is allowed to be itself, and being bigger than the dimensions of the webpage (straight from its digital source), in all probability. Hence, the randomized document.body scrolling that occurs.

But up until today our randomized range of scrollLeft and scrollTop positioning that could occur ranged over the entire width and height of the underlying image, while we think we should only be scrolling over the range ([imageWidth] - window.innerWidth (screen width)) x ([imageHeight] - window.innerHeight (screen height)). This could lead to white bands to the right and/or bottom of the webpage, in its presentation. And so we've fixed all the Javascript code to replace the old with the new in all the One Image Website codesets ...


var recti=document.getElementById(place).getBoundingClientRect();
//
document.getElementById("body").scrollTop = Math.floor(Math.random() * document.getElementById("body").scrollHeight);
//document.getElementById("body").scrollLeft = Math.floor(Math.random() * document.getElementById("body").scrollWidth);
document.getElementById("body").scrollTop = Math.max(0,Math.floor(Math.random() * eval(eval('' + recti.height) - eval('' + window.innerHeight))));
document.getElementById("body").scrollLeft = Math.max(0,Math.floor(Math.random() * eval(eval('' + recti.width) - eval('' + window.innerWidth))));

Any white bands you still see now will be caused by that being on the original photograph data stock (we're hoping), in ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately


Previous relevant One Image Website VTT Tracks Tutorial is shown below.

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

Using yesterday's Ffmpeg Log Helper Towards VTT File Primer Tutorial VTT files we could choose to use ...

... and, am sorry, but cannot award any points to those who chose the former, because ... well ... it's doubtful we'd mention the second unless we'd done it. And so the answer is ... the former ... down Nala ... the latter!

Today's blog posting is also a little story about the benefits of what we like to call client pre-emptive iframe logic, whereby we open an HTML iframe element, blazing away with its src attribute pointing at a URL that may or may not exist, and if it does, we do something about its content, usually, in the HTML iframe onload event logic. In our case the URL is a VTT file suiting the One Image Website of relevance given the upload and renaming of the VTTs created using yesterday's PHP ffmpeg log to VTT file creator web application.

As a programmer who would like to pursue true track cue Javascript coding, develop the function tracks in the One Image Website index-ssmhalf.html you could View -> Page Source from your favourite web browser, for any of ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately

... where, now, where the user plays music, perhaps continuously (like a radio) with an HTML audio element play button press, the currently playing song, thanks to Royalty Free Music For Video, help you keep in touch with the song playing up at the web browser tab and the image title.

This amounted to Javascript changes, as per ...

index.htm ...


var foreground=null; // and get rid of var in var foreground below
var plusstuff='';

function ftchange(tob) {
plusstuff=' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
if (document.getElementById('place').title.indexOf(' Playing ') == -1) {
document.getElementById('place').title+=' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
document.getElementById('place').title=document.getElementById('place').title.split(' Playing ')[0] + ' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
}
}


function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i) && document.URL.indexOf('?audio=') == -1) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.body.innerHTML+='<iframe id=ifmusicone title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" src="./index-ssmhalf.html?justmusic=00" style="opacity:0.5;z-index:345;position:absolute;width:140px;height:100px;left:' + eval(-140 + eval('' + window.innerWidth)) + 'px;top:0px;"></iframe>';
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}

function FadeInImage()
{
var foreground=document.getElementById("place");
window.clearTimeout("FadeInImage('" + "place" + "')");
rotateImage("place");
}

function rotateImage(place) {

while (number_of_image == 0)
{
place = place;
}
xplace=place;
//alert('yay2');

anotherNew();

var foreground=document.getElementById(place);
//alert(place);

var thedivlink=document.getElementById("thedivlink");
var thediv=document.getElementById("thediv");

if (foreground.width > 0) {
thedivlink.style.display = "none";
thediv.style.display = "none";
if (document.getElementById('ifmusicone')) {
document.getElementById('ifmusicone').style.display='none';
}

//alert('yay2a');
var alink=document.getElementById("alink");
var xxxx=alink.href;
if (xxxx.indexOf("mp3") != -1)
{
//alink.href="index-ssm.html";
//alink.onclick="javascript:void(0);";

alink.href="filewrite.php?id=session&name="+bigrandnumber+"&ext=txt&rand="+bigrandnumber;
alink.onclick="javascript:void(0);";
foreground.onclick="javascript:hasBeenClicked();";
foreground.title="Click for Bamboozled provided by http://www.freesoundtrackmusic.com" + plusstuff;

}
else
{
if (bigrandnumber >= 0) {
if (hasbeenclicked == 1 || NumOpen > 0 || does_file_exist("session",bigrandnumber,"txt"))
{
bigrandnumber = -1;
alink.href="upload.php";
//alink.onclick="javascript: window.open('index-ssm.html','Pyrmont, Ultimo - Inner Burbs - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');";
alink.onclick = "javascript:void(0);";
//alink.ondblclick = "javascript:void(0);";
foreground.title="Click for Upload functionality.";
alink.target = "_blank";
}
}
}
alink.target = "_blank";
}
else
{
thedivlink.style.display = "block";
thediv.style.display = "block";
}

SetOpacity(foreground,0.3);
// more rotateImage code follows
}
index-ssmhalf.html ...

var mycurt=-1;
var vttcont='';
var vtttitles=[];
var vttstartsecs=[];
var vttendsecs=[];
var vttlastt='';

function getct() {
if (document.getElementById('myaudio')) {
mycurt=document.getElementById('myaudio').currentTime;
console.log('ct=' + mycurt);
//top.document.title='Current time = ' + mycurt;
for (var jjk=0; jjk<vtttitles.length; jjk++) {
if (eval('' + mycurt) >= eval(-0.0001 + eval('' + vttstartsecs[jjk])) && eval('' + mycurt) <= eval(0.0001 + eval('' + vttendsecs[jjk]))) {
if ((vttlastt != vtttitles[jjk] || vttlastt.trim() != vttlastt) || vttlastt.trim() != vtttitles[jjk] || vttlastt == '') {
if (vttlastt.trim() != vtttitles[jjk]) { vttlastt=vtttitles[jjk]; } else { vttlastt+=' '; }
console.log('ct title=' + vtttitles[jjk]);
if (parent.document.title.indexOf(' - ') != -1) {
var huhsare=parent.document.title.split(' - ');
if (eval('' + huhsare.length) >= 3) {
parent.document.title=(parent.document.title.replace(' - ','`').split(' - ')[0] + ' - ' + 'Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ').replace('`', ' - ');
} else {
parent.document.title=parent.document.title.split(' - ')[0] + ' - ' + 'Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
if (parent.document.getElementById('place').title.indexOf(' Playing ') == -1) {
parent.document.getElementById('place').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
parent.document.getElementById('place').title=parent.document.getElementById('place').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
parent.ftchange(vtttitles[jjk]);
if (parent.document.getElementById('alink').title.indexOf(' Playing ') == -1) {
parent.document.getElementById('alink').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
parent.document.getElementById('alink').title=parent.document.getElementById('alink').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
if (document.getElementById('myaudio').title.indexOf(' Playing ') == -1) {
document.getElementById('myaudio').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
document.getElementById('myaudio').title=document.getElementById('myaudio').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
} else {
parent.document.getElementById('place').title='Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
parent.document.getElementById('myaudio').title='Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
}
}
}
}
}

function pushit() {
var timings=vttcont.split(' --> ');
console.log('timings length=' + timings.length);
if (eval('' + timings.length) == 1) {
//console.log('vttcont=' + vttcont);
timings=vttcont.split(' --> ');
console.log('Timings length=' + timings.length);
}
var spares='',sparesa=[], jspare=0.0;
var sparee='',spareea=[];
var ispare=0, iifg=0, ifactor=1.0;
var thistt='';
if (eval('' + timings.length) > 1) {
for (var kkll=1; kkll<timings.length; kkll++) {
spares='';
sparee=''
ispare=0;
while ((timings[kkll].substring(ispare).substring(0,1) >= '0' && timings[kkll].substring(ispare).substring(0,1) <= '9') || timings[kkll].substring(ispare).substring(0,1) == '.' || timings[kkll].substring(ispare).substring(0,1) == ':') {
sparee+=timings[kkll].substring(ispare).substring(0,1);
ispare++;
}
console.log('sparee=' + sparee + ' and ispare=' + ispare);
while (timings[kkll].substring(ispare).substring(0,1) <= String.fromCharCode(32)) {
ispare++;
}
console.log('ispare=' + ispare);
vtttitles.push(timings[kkll].substring(ispare).split(String.fromCharCode(10))[0].split('{')[0]);
console.log('title=' + vtttitles[-1 + eval('' + vtttitles.length)]);
spareea=sparee.split(':');
ifactor=1.0;
jspare=0.0;
for (iifg=eval(-1 + eval('' + spareea.length)); iifg>=0; iifg--) {
console.log('iifg=' + iifg + ' via ' + spareea[iifg] + '!');
jspare+=eval(ifactor * eval('' + spareea[iifg].replace(/^0/g,'')));
console.log('Jspare=' + jspare);
ifactor*=60;
}
vttendsecs.push(jspare);
ispare=-1;
console.log('jspare=' + jspare);
while ((timings[-1 + kkll].slice(ispare).substring(0,1) >= '0' && timings[-1 + kkll].slice(ispare).substring(0,1) <= '9') || timings[-1 + kkll].slice(ispare).substring(0,1) == '.' || timings[-1 + kkll].slice(ispare).substring(0,1) == ':') {
spares=timings[-1 + kkll].slice(ispare).substring(0,1) + spares;
ispare--;
}
console.log('spares=' + spares);
sparesa=spares.split(':');
ifactor=1.0;
jspare=0.0;
for (iifg=eval(-1 + eval('' + sparesa.length)); iifg>=0; iifg--) {
jspare+=eval(ifactor * eval('' + sparesa[iifg].replace(/^0/g,'')));
ifactor*=60;
}
vttstartsecs.push(jspare);
}

}
}

function gotback(iois) {
if (iois != null) {
//if (iois.src.indexOf('?placegeo=') != -1) {
//alert(1);
var aconto = (iois.contentWindow || iois.contentDocument);
//alert(11);
if (aconto != null) {
//alert(111);
if (aconto.document) { aconto = aconto.document; }
//alert(1111);
if (aconto.body != null) {
vttcont=aconto.body.innerHTML.replace('<pre>','').replace('</pre>','');
pushit();
}
}
//}
}
}

function tracks(iois) {
}


function showScroll() {
if ((navigator.userAgent.match(/iPhone|iPod|iPad/i) || top.document.URL.indexOf('?audio=') != -1) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
if (document.URL.indexOf('justmusic=0') != -1) {
document.getElementById('next').innerHTML+='<audio onloadedmetadata=tracks(this); id=myaudio title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + '; parent.document.body.setAttribute(' + "'data-music','yes'" + ');" style=position:absolute;top:0px;left:0px; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source><track kind="subtitles" src="sound/all.vtt" srclang="en"></track></audio><iframe onload=gotback(this) src=sound/all.vtt style=display:none;></iframe>';
} else {
document.getElementById('next').innerHTML+='<audio onloadedmetadata=tracks(this); id=myaudio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop data-ideanogo=autostart><source type=audio/mp3 src=sound/all.mp3></source><track kind="subtitles" src="sound/all.vtt" srclang="en"></track></audio><iframe onload=gotback(this) src=sound/all.vtt style=display:none;></iframe>';
}
//alert(document.getElementById('next').innerHTML);
console.log("1");
//var textTrackElem = document.getElementById("myaudio");
mycurt=0;
setInterval(getct, 2000);

setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}
if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}


Previous relevant Ffmpeg Log Helper Towards VTT File Primer Tutorial is shown below.

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday's One Image Website iOS Radio Music One Less Tutorial set us on an "off to the side, but eventually forward" project that intertwines ...

  • ffmpeg ... with its great logging and media concatenation talents, thanks ...
  • macOS Terminal desktop app ... regarding its great GUI design feature allowing you to gather up actions of the past into a copy buffer via its Edit -> Find functionality, thanks
  • Audio and Video HTML element track cue functionality VTT file interface ... you can read more about at HTML5 Track Element Primer Tutorial

Don't know about you, but have always found the creation of track data VTT files (and their predecessor SRT files) one of the most tedious jobs in programming?

But the work of the day before yesterday's One Image Website iOS Radio Music Tutorial and its audio concatenation via ffmpeg themes had us looking back, wistfully, back up our (macOS) Terminal (desktop apps) logging of a few days past, hoping for an escape from VTT file manual text editing for our wish to enhance our One Image Website work of recent days. Wow, the ffmpeg logging was brilliant!

There was enough there to program the creation of VTT files from the ffmpeg, and our "cd"ing and "ls"ing and other stuff, in the (let's more accurately say, Terminal) logging. Yayyyyy!

And so we have an albeit defaults very particular to my situation in its HTML form textarea and input type=text textbox defaults (shown via placeholder attributes), but we think it could be a tweakable basis for your own ffmpeg media concatenation work, perhaps, with our first draft proof of concept ffmpeg logging, via Terminal, PHP helper towards VTT file creation.

If you click the light green form submit button, in the iframe way below, yourself, it will reveal, in details/summary (revealing) tags, both the input and output (VTT files) for you to see this more clearly, or to have it clicked for you in a new window, click this button clicker incarnation. In the works of the HTML form below, for the first time we can remember, and because the defaults are so arcane, we developed HTML form onsubmit logic as per ...


<form id=myform onsubmit=" var ins=document.getElementsByTagName('textarea'); if (document.getElementById(ins[0].id).value == '') { document.getElementById(ins[0].id).value=('' + document.getElementById(ins[0].id).placeholder); } ins=document.getElementsByTagName('input'); for (var ii=0; ii<ins.length; ii++) { if (document.getElementById(ins[ii].id).value == '' && document.getElementById(ins[ii].id).type == 'text') { document.getElementById(ins[ii].id).value=('' + document.getElementById(ins[ii].id).placeholder); } } return true;" action=./ffmpeg_log_to_vtt.php method=POST>
<textarea name=infile id=infile title='Or paste in your ffmpeg log file data' placeholder='all_bar_thecommute.txt' value='' style="background-color:yellow;"></textarea><br><br>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Output Basename Prefixing Delimiter</th><th>Output Basename Suffixing Delimiter</th></tr>
<tr><td><input name=inbasenameprefix id=inbasenameprefix type=text placeholder='user@Users-Air' value=''></input></td><td><input name=inbasenamesuffix id=inbasenamesuffix type=text placeholder='% cd' value=''></input></td></tr>
</table>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Metadata Prefixing String</th><th>Metadata Name Value Delimiter</th><th>Metadata Title Value Case Insensitive Start String</th></tr>
<tr><td><input name=metaprefix id=metaprefix type=text placeholder='Metadata:' value=''></input></td><td><input name=metadelimiter id=metadelimiter type=text placeholder=':' value=''></input></td><td><input name=metatitleprefix id=metatitleprefix type=text placeholder='tit' value=''></input></td></tr>
</table>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Duration Prefixing String</th><th>Duration Time Part Delimiter</th></tr>
<tr><td><input name=durationprefix id=durationprefix type=text placeholder='Duration:' value=''></input></td><td><input name=durationdelimiter id=durationdelimiter type=text placeholder=':' value=''></input></td></tr>
</table>
<br><br><br>
<input id=mysub type=submit value="Create VTTs" style="background-color:lightgreen;"></input>
</form>

... as a way to deal with arcane defaults, where the encouragement is there for an interested programmer to download PHP code (perhaps to a MAMP local Apache/PHP/mySql web server environment) and tweak to their purposes. Note that you can paste your own logging into the textarea as a way this PHP application can be useful even up at the RJM Programming domain ...


Previous relevant One Image Website iOS Radio Music One Less Tutorial is shown below.

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday's One Image Website iOS Radio Music Tutorial "Stop Press" promised ...

For tomorrow, we offer an optional "one less click", "one less window" methodology improvement on the work above, as we transition the other "One Image Websites" over to the new iOS music paradigm.

... and so, it being tomorrow we're here starting our discussion starting with the "one less window" thought. Have a look at this table outlining some (off the top of the head) clientside navigation techniques in two categories ...

No new window created ... New window created ...
window.open([URL],'_self') window.open([URL],'_blank')
location.href=[URL] window.open([URL],'_top')
window.location=[URL] top.window.location=[URL]; // if in an iframe
Ajax (with or without new FormData()) whether 'GET' or 'POST' form target=_blank action=[URL]
form target=_self action=[URL] form target=_top action=[URL] // if in an iframe
iframe srcdoc=[webpageHTML] form target=_parent action=[URL] // if in an iframe
iframe src=[URL] parent.window.location=[URL]; // if in an iframe

... and it's that last left hand column iframe src=[URL] we like for the purposes of these changes today. That new HTML iframe in the "One Image Website" index.htm supervisories is now worked via ...


function rotateImage(place) {

while (number_of_image == 0)
{
place = place;
}
xplace=place;

anotherNew();

var foreground=document.getElementById(place);


var thedivlink=document.getElementById("thedivlink");
var thediv=document.getElementById("thediv");


if (foreground.width > 0) {
thedivlink.style.display = "none";
thediv.style.display = "none";
if (document.getElementById('ifmusicone')) {
document.getElementById('ifmusicone').style.display='none';
}

//
// more rotateImage code follows ...
//
}
//
// more rotateImage code follows ...
//
}

function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i)) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.body.innerHTML+='<iframe id=ifmusicone title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" src="./index-ssmhalf.html?justmusic=0" style="opacity:0.5;z-index:345;position:absolute;width:140px;height:100px;left:' + eval(-140 + eval('' + window.innerWidth)) + 'px;top:0px;"></iframe>';
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}


</script>
</head>
<body id="body" onload=' xonl(); if (document.URL.indexOf("exif=") != -1) { dexifit(); } showScroll(); window.setTimeout("FadeInImage()", 4000); '>
<div id="thediv" style="display:block;" >
<span><a id="thedivlink" style="display:inline-block;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." onclick="javascript: window.open('index-ssmhalf.html?justmusic=','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="#" data-href="sound/Prelude_Melody-Mike_Vekris.mp3" >The Commute - RJM Programming ... you might see this while loading ... &#127926; click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery &#127926; ... else please wait for full functionality ...</a> versus <a onclick=huhit(); onmousedown=huhittwo(); style=display:inline-block;cursor:pointer;text-decoration:underline;>Exif Run</a></span>
</div>
<a id="alink" style="font-size:28px;background-color:yellow;" onclick="javascript: window.open('index-ssmhalf.html','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)'); disableHref();" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="sound/Prelude_Melody-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming" src="siteimage.jpg" /-->
<img border=0 id="place" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." src="siteimage.jpg" />
</a>

... now, with the iOS platforms, presenting a new HTML audio (loop attribute set) in a slightly different incarnation as per index-ssmhalf.html ...



function nextPage()
{
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
image_index=image_index;
} else {

window.location = "index-saf.html";
}
}

function setvv() {
document.getElementById('place').style.visibility='visible';
}


function showScroll() {
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
if (document.URL.indexOf('justmusic=0') != -1) {
document.getElementById('next').innerHTML+='<audio title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + '; parent.document.body.setAttribute(' + "'data-music','yes'" + ');" style=position:absolute;top:0px;left:0px; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
} else {

document.getElementById('next').innerHTML+='<audio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
}
//alert(document.getElementById('next').innerHTML);
setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}

if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}

</script>
</head>
<body id="body" onload='showScroll(); window.setTimeout("rotateImage()", 4000); '>
<a id="next" onclick="javascript: window.open('index-safhalf.html','The Commute - Playing With Filters (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" title="" href="sound/Playing_with_Filters-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" alt="DSCF1486" src="DSCF1486.jpg" /-->
<img border=0 id="place" alt="" src="DSCF1486.jpg" style=visibility:hidden; />
</a>

... up towards the top right of the index.htm webpage when using an iOS platform. It is optional whether the user ...

  • clicks Play button of that new top right audio element for continuous "looped audio track sets" mode of use with no new second window required (and so, no window focus changes and no second click required either)
  • clicks blue link for continuous "looped audio track sets" mode of use with a new second window's audio element that the user clicks the Play button of
  • clicks none of those modes of use above that are offered for a short time to then click appropriately to start up music, optionally, as required, at a later date as possible

So feel free to try a One Image Website in the list below ...

... where this new iOS music arrangement logic has been incorporated.

Stop Press

The Webpage Meta Refresh Primer Tutorial has reminded us of another left hand "No new window created" navigation methodology using the HTML meta "refresh" tag.


Previous relevant One Image Website iOS Radio Music Tutorial is shown below.

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

Did you read the recent Responsive Web Design Landing Page Image Map Tutorial? Its core takeaway was the linking of One Image Website functionalities. In these One Image Websites we've picked out a guinea pig ...


"The Commute"

... to have a day's worth of experimenting trialling a solution to the "chestnut of a" problem getting iOS music to play continuously without supervision, like a radio program, albeit on a cycle of repeated content (set (such as the oneoffive.mp3 twooffive.mp3 threeoffive.mp3 fouroffive.mp3 fiveoffive.mp3 set of 5 tracks in example below)). Years ago Apple's iOS started requiring a user click to validate the playing of media, hence the interest in today's topic.

The ingredients for the solution, and testing thereof, are ...

  • macOS command line ffmpeg ... capable of ...
  • concatenating audio files ... with command like ...


     
    ffmpeg -i oneoffive.mp3 -i twooffive.mp3 -i threeoffive.mp3 -i fouroffive.mp3 -i fiveoffive.mp3 -filter_complex "[0:a][1:a]concat=n=5:v=0:a=1" all.mp3

     

    ... into ...
  • compilation audio ... all.mp3 ... uploaded to RJM Programming domain ... is now called on ...
  • within an audio tagged HTML element ... with ...
  • loop attribute set ... using as a device ...
  • an iPhone ... teamed ...
  • optionally, (we're just suggesting this headphone idea if you want to keep the music to yourself) via Bluetooth, with a set up involving a connection to a set of AirPods (and connected to your ears) ... are chosen as ...
  • the default speakers for sound ... then use ...
  • web browser app such as Safari ...
  • into the address bar type


    https://www.rjmprogramming.com.au/thecommute

    ... to arrive at the calling window ...

  • click the blue link up the top that appears for a short time ... then ...
  • in the resultant new music window click the Audio play button presented (the point of interest being that this could be the last click required for continuous music playing, in that audio loop) ... music should play continuously and ...
  • if more interesting visuals are also required focus back to calling window

And given that the iPhone and AirPods are charged, and you don't charge out of Bluetooth range with the iPhone, you could get that "radio feeling" out of an iOS user experience!

Code changes, all just clientside HTML and Javascript, went ...

calling window's index.htm changes around the document.body onload event area of interest 🎶 ...


function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i)) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}


</script>
</head>
<body id="body" onload=' xonl(); if (document.URL.indexOf("exif=") != -1) { dexifit(); } showScroll(); window.setTimeout("FadeInImage()", 4000); '>
<div id="thediv" style="display:block;" >
<span><a id="thedivlink" style="display:inline-block;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." onclick="javascript: window.open('index-ssmhalf.html?justmusic=','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="#" data-href="sound/Prelude_Melody-Mike_Vekris.mp3" >The Commute - RJM Programming ... you might see this while loading ... &#127926; click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery &#127926; ... else please wait for full functionality ...</a> versus <a onclick=huhit(); onmousedown=huhittwo(); style=display:inline-block;cursor:pointer;text-decoration:underline;>Exif Run</a></span>
</div>
<a id="alink" style="font-size:28px;background-color:yellow;" onclick="javascript: window.open('index-ssmhalf.html','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)'); disableHref();" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="sound/Prelude_Melody-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming" src="siteimage.jpg" /-->
<img border=0 id="place" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." src="siteimage.jpg" />
</a>
music window's index-ssmhalf.html changes around the document.body onload event area of interest ...


function nextPage()
{
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
image_index=image_index;
} else {

window.location = "index-saf.html";
}
}

function setvv() {
document.getElementById('place').style.visibility='visible';
}


function showScroll() {
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
document.getElementById('next').innerHTML+='<audio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
//alert(document.getElementById('next').innerHTML);
setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}

if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}

</script>
</head>
<body id="body" onload='showScroll(); window.setTimeout("rotateImage()", 4000); '>
<a id="next" onclick="javascript: window.open('index-safhalf.html','The Commute - Playing With Filters (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" title="" href="sound/Playing_with_Filters-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" alt="DSCF1486" src="DSCF1486.jpg" /-->
<img border=0 id="place" alt="" src="DSCF1486.jpg" style=visibility:hidden; />
</a>

... and off up to the RJM Programming domain as "The Commute", with music courtesy of the generous Royalty Free Music For Video, thanks.

Stop Press

For tomorrow, we offer an optional "one less click", "one less window" methodology improvement on the work above, as we transition the other "One Image Websites" over to the new iOS music paradigm.


Previous relevant Responsive Web Design Landing Page Image Map Tutorial is shown below.

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said ...

So, why keep the old way? Well, we packed the "old way" with content rich functionality, and do not want to ditch that yet, but maybe over time?!

We're just over time, aren't you?! And so, we arrive at a long planned for tilt at Image Map functionality that we often turn to Mobilefish.Com and its excellent Image Map Creation to help us out ... but not today?! Why not? We have a funny set of needs, they being ...

  • our Image Map's image will have a variable set of width x height dimensions ...
  • our Image Map's image will be transparent
  • our Image Map needs to have a hole left aside inside it where the functionality that originally existed (and pointed to WordPress Blog content like you are reading), is still working

... the last condition of which we realized, down the track, required us to create four Image Maps. But ... but ... Nala hears you say?!

Yes, we can reference the one image, in its data URL guise, as a smaller, or not, version of itself, by specifying CSS properties ...

  • position:absolute; (our usual for overlay scenarios)
  • z-index:56; (for both transparent image and its associated Image Map ... more on this later)
  • left (to appropriately position in X to be in the relevant section of dark green Image Map overlaying in the Landing Page)
  • top (to appropriately position in Y to be in the relevant section of dark green Image Map overlaying in the Landing Page)
  • width (which will be up to the transparent image width)
  • height (which will be up to the transparent image height)

... and no concern about opacity given the transparent image and z-index considerations, here.

So, how can we involve a transparent image here? Well, that is where the new Responsive Web Design Landing Page being PHP, though up to today it had contained no PHP, is in our favour. We can use PHP's GD to create one, grab its associated data URL and tidy up, and constructing the four image and associated Image Map HTML elements populated, in its "child iframe", and sending back up into the "parent webpage's" new ...

<?php echo "

<div id=divimif></div>
<iframe style='display:none;' id=myimif src=></iframe>

"; ?>

... placed at the bottom of the Landing Page body element, and used in the changed document.body onload event Javascript function ...

<?php echo "

function onl() {
if (eval('' + screen.width) <= 420) {
//alert(screen.width);
document.getElementById('topspan').innerHTML=document.getElementById('topspan').innerHTML.replace('RJM Programming', 'RJM</h1><h1>Programming').replace(/\<\/hJUNK1/g, '</h2');
} //else if (eval('' + screen.width) <= 480) {
//alert('0' + screen.width);
//}
var myiz=document.getElementById('ifzero').getBoundingClientRect();
var myhr=document.getElementById('myheader').getBoundingClientRect();
var myh=eval('' + myhr.height);
var myt=eval('' + myhr.top);
var widthleft=eval(eval('' + myiz.left) - eval('' + myhr.left));
var widthmiddle=eval('' + myiz.width);
var widthright=eval(eval('' + myhr.width) - eval('' + myiz.width) - eval('' + myiz.left));
if (document.getElementById('navTop')) {
var myalthr=document.getElementById('navTop').getBoundingClientRect();
myh-=eval('' + myalthr.height);
myt=eval('' + myalthr.height);
}
var heighttop=eval(eval('' + myiz.top) - eval('' + myt));
var heightmiddle=eval('' + myiz.height);
var heightbottom=eval(eval('' + myh) - eval('' + myiz.height)); // - eval('' + myiz.top));
if (window.parent != window) {
myh=myh;
} else if (('' + window.opener).replace(/^undefined/g,'').replace(/^null/g,'')) {
myh=myh;
} else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPaJUNKd|iPod|Opera Mini|IEMobile/i)) {
myh=myh;
} else {
document.getElementById('myimif').src=document.URL.split('?')[0].split('#')[0] + '?left=' + myhr.left + '&top=' + myt + '&width=' + myhr.width + '&height=' + myh + '&ifleft=' + myiz.left + '&iftop=' + myiz.top + '&ifwidth=' + myiz.width + '&ifheight=' + myiz.height + '&widthleft=' + widthleft + '&widthmiddle=' + widthmiddle + '&widthright=' + widthright + '&heighttop=' + heighttop + '&heightmiddle=' + heightmiddle + '&heightbottom=' + heightbottom;
setTimeout(imbit, 5000);
}

}

"; ?>

... to call on that new PHP ...

<?php

if (isset($_GET['left']) && isset($_GET['top']) && isset($_GET['width']) && isset($_GET['height'])) {
$uw="";
$postuw="";
$uw1="";
$postuw1="";
$uw2="";
$postuw2="";
$uw3="";
$postuw3="";
if (isset($_GET['widthleft']) && isset($_GET['widthmiddle']) && isset($_GET['widthright']) && isset($_GET['heighttop']) && isset($_GET['heightmiddle']) && isset($_GET['heightbottom'])) {
$uw=" usemap=#workmap";
$uw1=" usemap=#workmap1";
$uw2=" usemap=#workmap2";
$uw3=" usemap=#workmap3";

$postuw="<map name=workmap style=z-index:56;>";
$postuw1="<map name=workmap1 style=z-index:56;>";
$postuw2="<map name=workmap2 style=z-index:56;>";
$postuw3="<map name=workmap3 style=z-index:56;>";

$postuw.="<area shape=rect title=Ephemeral onmouseover=omoiset(1); onmouseout=omoiset(-2); coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=LeftTop onclick=ouralert(1); target=_blank href=//www.rjmprogramming.com.au/ephemeral />";
$postuw.="<area shape=rect title=StreetArt onmouseover=omoiset(2); onmouseout=omoiset(-2); coords=" . explode('.',$_GET['widthleft'])[0] . ",0," . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=CenterTop onclick=ouralert(2); target=_blank href=//www.rjmprogramming.com.au/streetart />";
$postuw.="<area shape=rect title=TheCommute onmouseover=omoiset(3); onmouseout=omoiset(-2); coords=" . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . ",0," . explode('.',$_GET['width'])[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=RightTop onclick=ouralert(3); target=_blank href=//www.rjmprogramming.com.au/thecommute />";

$postuw1.="<area id=area4 title=? onmouseover=omoiset(4); onmouseout=omoiset(-1); shape=rect coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',(0 + $_GET['heightmiddle']))[0] . " alt=LeftMiddle onclick=ouralert(4); target=_blank nohref />";
$postuw2.="<area id=area6 title=? onmouseover=omoiset(6); onmouseout=omoiset(-1); shape=rect coords=0,0," . explode('.',$_GET['widthright'])[0] . "," . explode('.',(0 + $_GET['heightmiddle']))[0] . " alt=RightMiddle onclick=ouralert(6); target=_blank nohref />";

$postuw3.="<area shape=rect title=InnerBurbs onmouseover=omoiset(7); onmouseout=omoiset(-2); coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=LeftBottom onclick=ouralert(7); target=_blank href=//www.rjmprogramming.com.au/pyrmontultimo />";
$postuw3.="<area shape=rect title=Bygone onmouseover=omoiset(8); onmouseout=omoiset(-2); coords=" . explode('.',$_GET['widthleft'])[0] . ",0," . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=CenterBottom onclick=ouralert(8); target=_blank href=//www.rjmprogramming.com.au/bygone />";
$postuw3.="<area shape=rect title=West onmouseover=omoiset(9); onmouseout=omoiset(-2); coords=" . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . ",0," . explode('.',$_GET['width'])[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=RightBottom onclick=ouralert(9); target=_blank href=//www.rjmprogramming.com.au/thewest />";

$postuw.="</map>";
$postuw1.="</map>";
$postuw2.="</map>";
$postuw3.="</map>";
}


// Create a transparent image thanks to https://www.php.net/manual/en/function.imagecolortransparent.php
$im = imagecreatetruecolor($_GET['width'], $_GET['height']);
$red = imagecolorallocate($im, 255, 0, 0);
$black = imagecolorallocate($im, 0, 0, 0);

// Make the background transparent
imagecolortransparent($im, $black);

// Save the image
$udirnameprebimg='/tmp/imagecolortransparent.png';
imagepng($im, $udirnameprebimg);

$duis='data:image/' . str_replace('jpg','jpeg',strtolower(explode('.',$udirnameprebimg)[-1 + sizeof(explode('.',$udirnameprebimg))])) . ';base64,' . base64_encode(file_get_contents($udirnameprebimg));
imagedestroy($im);
unlink($udirnameprebimg);



echo "<html>
<body onload=\"parent.document.getElementById('divimif').innerHTML='<img id=myimg style=height:" . $_GET['heighttop'] . "px;z-index:56;position:absolute;top:" . $_GET['top'] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['width'] . "px; src=" . $duis . "" . $uw . "></img>" . $postuw . "<img id=myimg1 style=height:" . $_GET['heightmiddle'] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop']))[0] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['widthleft'] . "px; src=" . $duis . "" . $uw1 . "<>/img>" . $postuw1 . "<img id=myimg2 style=height:" . $_GET['heightmiddle'] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop']))[0] . "px;left:" . explode('.',($_GET['width'] - $_GET['widthright']))[0] . "px;width:" . $_GET['widthright'] . "px; src=" . $duis . "" . $uw2 . "></img>" . $postuw2 . "<img id=myimg3 style=height:" . explode('.',($_GET['height'] - $_GET['heighttop'] - $_GET['heightmiddle']))[0] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop'] + $_GET['heightmiddle']))[0] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['width'] . "px; src=" . $duis . "" . $uw3 . "></img>" . $postuw3 . "'; \"></body>
</html>";

exit;
}

?>

... and once setup, helped out by new Javascript, as per ...

<?php echo "

var urls=['', '', '', ' ', '', ' ', '', '', ''];
var omoi=-1;
var isrelp=false;

function postomoiset() {
if (isrelp) {
isrelp=false;
if (omoi == 4 || omoi == 6) {
var wasomoi=omoi;
omoi=-1;
ouralert(wasomoi);
}
}
}

function omoiset(jnnum) {
if (eval('' + jnnum) == -1) {
omoi=jnnum;
//document.title='omoi=' + omoi;
isrelp=false;
//setTimeout(postomoiset, 8000);
} else if (eval('' + jnnum) == -2) {
if (omoi != 4 && omoi != 6) {
omoi=jnnum;
//document.title='omoi=' + omoi;
isrelp=false;
//setTimeout(postomoiset, 8000);
}
} else {
omoi=jnnum;
//document.title='omoi=' + omoi;
if (omoi != 4 && omoi != 6) {
isrelp=false;
} else {
isrelp=true;
//document.title='omoi=' + omoi + '|';
setTimeout(postomoiset, 8000);
}
}
}

function ouralert(innum) {
var ans='';
switch ('' + innum) {
case '1':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '2':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '3':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '4':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.) Eg. https://www.rjmprogramming.com.au/slideshow.html', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '5':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '6':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.) Eg. https://www.rjmprogramming.com.au/plus/', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '7':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '8':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', '');
}
break;
case '9':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', '');
}
break;
default:
break;
}
if (!ans) { ans=''; }
if (ans != '') {
window.open(ans.trim(), '_blank');
if (ans != ans.trim()) {
window.localStorage.setItem('area' + innum + 'url', encodeURIComponent(ans.trim()));
}
}
}


function imbit() {
//if (document.getElementById('myimg')) {
// document.getElementById('myimg').style.border='5px dashed purple';
//}
if (('' + window.localStorage.getItem('area4url')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
urls[3]=decodeURIComponent('' + window.localStorage.getItem('area4url'));
document.getElementById('area4').title=decodeURIComponent('' + window.localStorage.getItem('area4url')) + '# ... long hover of at least 8 seconds for chance to change';
document.getElementById('area4').href=decodeURIComponent('' + window.localStorage.getItem('area4url'));
document.getElementById('area4').onclick=function(){ omoiset=-1; urls[3]=urls[3]; }
//document.getElementById('area4').ondblclick=function(){ ouralert(4); }
}
if (('' + window.localStorage.getItem('area6url')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
urls[5]=decodeURIComponent('' + window.localStorage.getItem('area6url'));
document.getElementById('area6').title=decodeURIComponent('' + window.localStorage.getItem('area6url')) + '# ... long hover of at least 8 seconds for chance to change';
document.getElementById('area6').href=decodeURIComponent('' + window.localStorage.getItem('area6url'));
document.getElementById('area6').onclick=function(){ omoiset=-1; urls[5]=urls[5]; }
//document.getElementById('area6').ondblclick=function(){ ouralert(6); }
}
}

"; ?>

... in a changed index.php Landing Page whose guises as ...

  • Landing Page in mobile phone devices
  • Landing Page in an iframe
  • Landing Page in a popup window

... we all excluded from new functionality Image Map potential "dark green area clicking" access to photography themed "One Image Websites" ...

... accessible from Image Map area elements up above and down below the WordPress Blog posting iframe whose CSS property z-index is set to ...

<?php echo "

<iframe title='Recent posts' onload='check_if(this);' src='PHP/zero.html?totalwidth=y' class='zero' id='ifzero' style='z-index:57;'></iframe>

"; ?>

... 57.


Previous relevant Responsive Web Design Landing Page Incarnation Tutorial is shown below.

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

Along the same "Responsive Design" themes of Responsive Web Design Primer Tutorial, we stumbled upon the excellent W3Schools Responsive Design Based Start Page Idea which inspired us to retry RJM Programming Landing Page thoughts ...

  • separating out totally "uninvolved" Landing Page calls hooked up with a new index.php (actually just HTML) Landing Page incarnation that has better Responsive Design credentials ... from ...
  • any other call of any complexity or having a query string etcetera, reverting to the "old way"

... new paradigm? So, why keep the old way? Well, we packed the "old way" with content rich functionality, and do not want to ditch that yet, but maybe over time?!

You'll see, though, using the new index.php Responsive Design Landing Page incarnation ...

... how the clutter melts away like a hot knife through margarinebutter!


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of "responsive web design" ...

Responsive web design (RWD) is an approach to web design that makes web pages render well on a variety of devices and window or screen sizes from minimum to maximum display size. Recent work also considers the viewer proximity as part of the viewing context as an extension for RWD.[1] Content, design and performance are necessary across all devices to ensure usability and satisfaction.[2][3][4][5]

... coming at it from the idea "Can a responsive shell webpage host a non-responsive iframe?"

In turn this got us to the excellent ideas of this webpage which we'll try out for a while ...

  • honing in on our "Landing Page and friends" set of unresponsively designed webpages ...
  • honing in on iPhone sized devices (ie. not iPads nor laptops) ...
  • host web browser address bar calls of "Landing Page and friends" set of unresponsively designed webpages within a caller.html responsively web designed shell supervisory webpage and start using some of that ...
    Unresponsive Landing Page
    Responsive Shell around Unresponsive Landing Page

    ... as food for (your) thought ...


    function bodonl() {
    var wasih=document.body.innerHTML;
    var huhd=document.getElementById('Container').getBoundingClientRect();
    var pb=0;
    if (eval('' + huhd.height) > eval('' + huhd.width)) {
    isportrait=true;
    pb=eval(eval('' + huhd.width) / eval('' + huhd.height) * 100.0);
    nowih='<div id="Container" style="padding-right:' + pb + '%; position:relative; display:block; height: 100vh;"><iframe' + wasih.split('<iframe')[1].split('</div>')[0].replace('" frameborder', fname + '" style="position:absolute; top:0; left: 0;" frameborder') + '</div>';
    //if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    //document.getElementById('myvis').setAttribute('initial-scale','0.5');
    //}
    } else {
    isportrait=false;
    pb=eval(eval('' + huhd.height) / eval('' + huhd.width) * 100.0);
    nowih='<div id="Container" style="padding-bottom:' + pb + '%; position:relative; display:block; width: 100%;"><iframe' + wasih.split('<iframe')[1].split('</div>')[0].replace('" frameborder', fname + '" style="position:absolute; top:0; left: 0;" frameborder') + '</div>';
    }
    document.body.innerHTML=nowih;
    }

    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.


    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

Pairings Game Tutorial

Pairings Game Tutorial

Pairings Game Tutorial

In this programming world, it is comforting to think of the “pairings” that go on. But it’s everywhere, the comfort a “pairing” can represent for people.

With this in mind, we designed a simple game …

  • the player is presented with 5 ideas of a “pairing” … it’s subjective, but …
  • we believe only one of these will score you a point by clicking on

… in this first draft Pairings Game whose tabular cell innards consist of 5 buttons and 5 overlaying …


var rectos=[];

function prepopulate() { // called at document.body onload
for (var icell=0; icell<5; icell++) {
rectos.push(document.getElementById('td' + eval(1 + icell)).getBoundingClientRect());
}
}

function populate() { // called whenever question changes
var fivebuts=[], fiveoverlays=[];
var makecorrect=Math.floor(Math.random() * 5), recto=null;
var interestg=-1, tg=-1;
sofarb=',';
sofaro=',';

for (var icell=0; icell<5; icell++) {
recto=rectos[icell]; //document.getElementById('td' + eval(1 + icell)).getBoundingClientRect();
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
if (makecorrect == icell) {
while ((sofarb + sofaro).indexOf(',' + interestg + ',') != -1) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
fivebuts.push(interestg);
fiveoverlays.push(interestg);
sofarb+='' + interestg + ',';
sofaro+='' + interestg + ',';
if (eval(Math.floor(Math.random() * 19876754) % 2) == 0) {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(1);>' + pairingsa[interestg].split('&')[1] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[0] + '</div>';
} else {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(1);>' + pairingsa[interestg].split('&')[0] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[1] + '</div>';
}
} else {
while (sofarb.indexOf(',' + interestg + ',') != -1) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
sofarb+='' + interestg + ',';
tg=interestg;
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
while ((sofarb + sofaro).indexOf(',' + interestg + ',') != -1 || tg == interestg) {
interestg=Math.floor(Math.random() * eval('' + pairingsa.length));
}
sofaro+='' + interestg + ',';
if (eval(Math.floor(Math.random() * 19876754) % 2) == 0) {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(0);>' + pairingsa[interestg].split('&')[1] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[tg].split('&')[0] + '</div>';
} else {
document.getElementById('td' + eval(1 + icell)).innerHTML='<button onclick=scoreit(0);>' + pairingsa[tg].split('&')[0] + '</button><div style="margin-left:10px;margin-top:10px;font-size:24px;position:absolute;top:' + ('' + recto.top).split('.')[0] + 'px;' + 'left:' + ('' + recto.left).split('.')[0] + 'px;width:' + ('' + recto.width).split('.')[0] + 'px;height:' + ('' + recto.height).split('.')[0] + 'px;z-index:2345;opacity:0.6;pointer-events:none;">' + pairingsa[interestg].split('&')[1] + '</div>';
}
}
}


}

… div elements (optionally we’ve decided to apply pointer-events:none; to, per game question.

Pretty, simple, huh?!

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

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

The Little QR Code That Could Tutorial

The Little QR Code That Could Tutorial

The Little QR Code That Could Tutorial

Is it wrong to feel for an inanimate object? We’ll leave that one to the experts!

But we’ve been guilty of naming many inanimate objects. For heaven’s sake, we slept with some Peck’s Paste we were given for Christmas when we were … perhaps … 63?! And then there was that polyarmoured bat at … perhaps … 66?! How time flies?!

Yesterday, though, we were moved, discovering a discarded parking ticket, perhaps, containing a QR Code … all crushed and forlorn and forgotten.

How many QR Codes is humanity going to subject to being crushed and forlorn and forgotten !?!#!?@

Will you please get back to me on this?!

Anyway, then we thought, pulling out the mobile with it’s Camera app …

Can this crushed and forlorn and forgotten QR Code be repurposed !?!#!?@

Will you please get back to me on this?! Oh yeah, that’s why we’re here today … that’s right … we wrote a web application for the honour of …

This crushed and forlorn and, now, not so forgotten QR Code.

We decided making this web application, we’d start using our recent Image Map creation logic “lead in” which got us to a first draft HTML and Javascript (and image map) web application, and then the more sophisticated … like … second draft, featuring this new overlay related Javascript function …


function placeiframe(inurl) {
document.getElementsByTagName('area')[0].title='Looking for QR Code now ...';
if (eval('' + thefour.length) == 0) {
thefour=('' + document.getElementsByTagName('area')[0].coords).split(',');
}
if (inurl.toLowerCase().indexOf('http') == 0) {
document.getElementById('myif').style.position='absolute';
document.getElementById('myif').style.left='' + thefour[0] + 'px';
document.getElementById('myif').style.top='' + thefour[1] + 'px';
document.getElementById('myif').style.width='' + eval(90 + eval(eval('' + thefour[2]) - eval('' + thefour[0]))) + 'px';
document.getElementById('myif').style.height='' + eval(70 + eval(eval('' + thefour[3]) - eval('' + thefour[1]))) + 'px';
document.getElementById('myif').style.marginLeft='265px';
document.getElementById('myif').style.marginTop='180px';
document.getElementById('myif').style.transform='scaleX(2)';
//document.getElementById('myif').src='//www.rjmprogramming.com.au/recording_ideas.php?noinitialwo=y#' + inurl.trim();
document.getElementById('myif').src='/recording_ideas.php?noinitialwo=transparent#' + inurl.trim();
document.getElementById('myif').style.display='block';
document.getElementById('myif').style.zIndex='999';
//document.getElementsByTagName('area')[0].style.zIndex='9999';
//document.getElementsByTagName('area')[0].style.mixBlendMode='multiply';
passedurl=inurl;
}

setTimeout(function(){
askaway=true;
if (passedurl != '') { document.getElementsByTagName('area')[0].title=passedurl; passedurl=''; }
document.body.style.cursor='pointer';
document.getElementById('rhs').style.visibility='visible';
}, 8000);

if (inurl.trim() != '' && inurl != inurl.trim()) {
shareask(inurl.trim());
}

setTimeout(function(){
askaway=true;
}, 30000);
}

… of The Little QR Code That Could web application that we think is reasonably self evident in it’s use (but please don’t underestimate this woooorrrrlllldddd this golden orb‘s crushed and forlorn and, now, not so forgotten QR Code)

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

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

Canvas Interfacer Image Map Collaboration Tutorial

Canvas Interfacer Image Map Collaboration Tutorial

Canvas Interfacer Image Map Collaboration Tutorial

So far, with our currently running Image Map creating project yesterday’s Canvas Interfacer Mobile Image Map Tutorial continued on at, we’ve had a bit of focus on …

  • a single user getting as far into the Image Map creation process themselves because there are advantages to “strike while the iron is hot” marrying up Image Map area element positioning with a description, that can help later with stitching together Javascript event logic that can be useful making the Image Map … useful … but …
  • that doesn’t mean sharing and collaboration are of no use … perhaps the originator is a better designer than coder, for example

Anyway, that made us turn our attention to sharing and collaboration, email or SMS based, communication functionality, and we saw the two intervention points being …

  1. share the contents of the Image Map only HTML textarea element (with some default surrounding HTML and Javascript supplied) … and after a few double clicks, perhaps, the user might get to be able to …
  2. share the contents of the Image Map (with user tailored surrounding HTML and Javascript) textarea element

So how does a user make this happen? On mobile, it’s ontouchmove over the textarea concerned, where with non-mobile (you’re not going to like this, but we’ve run out of viable event types to use, so plumped for) onmouseout out of that textarea, to use. But won’t this get triggered too often? Well, we’ve coded for a couple of ways this can annoy less but still be that ever useful collaboration tool, via …


var hniis=false, hniisv='';

function shareask(tao) { // share Image Map outerHTML
var anchor=null, laterdo=null;
var proposedurlis='https://' + document.URL.split('//')[1].split('?')[0].split('#')[0] + '?rand=' + Math.floor(Math.random() * 19897865) + '#imagemapize=' + encodeURIComponent(tao.value);
if (!hniis) {
laterdo=hniisv;
if (1 == 1) {
console.log('message length is ' + proposedurlis.length);
} else {
document.title='' + proposedurlis.length + ' ' + document.title;
}
if (laterdo == '') {
laterdo=prompt('Please enter an email address or SMS number to send the Image Map to. To not ask again regarding Image Map progress email or SMS communications in this session click Cancel. If your answer you are happy with from here on append a space to it.', hniisv);
}
if (laterdo == null) { hniis=true; laterdo=''; }
if (laterdo.indexOf('@') > 0) {
if (laterdo != laterdo.trim()) { hniisv=laterdo.trim(); }
anchor = document.createElement('a');
if (tao.value.indexOf('<html') != -1) { // (includes tailored HTML and Javascript around it)
anchor.href = 'mailto:' + laterdo.trim() + '?subject=' + encodeURIComponent('Image Map (includes tailored HTML and Javascript around it) ...') + '&body=' + encodeURIComponent(proposedurlis);
} else {
anchor.href = 'mailto:' + laterdo.trim() + '?subject=' + encodeURIComponent('Image Map (includes default HTML and Javascript around it) ...') + '&body=' + encodeURIComponent(proposedurlis);
}
anchor.style.display='none';
anchor.innerHTML='Email';
anchor.target='_top';
anchor.click();
} else if (laterdo.trim() != '' && laterdo.trim().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,'') == '') {
if (laterdo != laterdo.trim()) { hniisv=laterdo.trim(); }
anchor = document.createElement('a');
anchor.href = 'sms:' + laterdo.trim() + '&body=' + encodeURIComponent(proposedurlis);
anchor.style.display='none';
anchor.innerHTML='SMS';
anchor.target='_top';
anchor.click();
}
}
}

… and we may improve the mechanism for this if Luna doesn’t snore tonight?!

Good ol’ hashtag data in emails or SMS comes into play here, and we found, even with Lorem Picsum images, we got viable results, though we found on mobile, the Gmail app “View Entire Message” hold finger down “Open Link” methodology was needed to get through. Gmail URL on macOS just needed the “View Entire Message” part of the workflow here.

Yet again, feel free to try …


Previous relevant Canvas Interfacer Mobile Image Map Tutorial is shown below.

Canvas Interfacer Mobile Image Map Tutorial

Canvas Interfacer Mobile Image Map Tutorial

On the same themes as yesterday’s Canvas Interfacer Three Finger Gesture Usage Tutorial‘s …

  • mobile platform chance to have three finger gestures help with scrolling functionality … today we have it so that …
  • mobile platforms are better suited creating Image Maps via canvas and image based inhouse web application (looking out for 🗺️🖼️ emoji button means to create Image Map when ready, as a double click on the canvas can do as well)

… our changes being helped out by the discovery that our previous …


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
// is identified around here as a mobile platform
}

… was a bit unreliable identifying mobile iOS platform Safari web browser usage, but this useful link got us to refine that thinking to …


if ( navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) > 0 ) {
// is better identified around here as a mobile platform
}

… with more success. Yayyyyy!

Along the way the HTML textarea elements used to identify Image Map subelement area rectangular limits have their disabled attribute set, which has the benefit …

  • that there is no need to allow any focus to these textarea elements when nothing any user can enter into them would make any difference anyway … and yet …
  • at least on non-mobile platforms the useful resizing talents of textarea elements are not stopped because of the disabled attribute being set

We found that the URL usage …


https://www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm#imagemap=url

… had become a little obsolete (at least, regarding the emoji button workflow), in the sense that, like with the canvas ondblclick event (ie. double click) functionality, why not, when clicking that 🗺️🖼️ Image Map creator emoji button grab the contents of the canvas already displaying as the default content presented to the “potential” (ie. it depends, sometimes, whether you double click that canvas element the next time) Image Map creation session?

Relevant to Random Background Image Map Area Polygons Tutorial and the decision then regarding non-mobile platforms to use an initial click followed by right clicks to enable Image Map area element shape=poly components, today, thinking with respect to mobile platforms, we’ve decided Image Map area element shape=poly components can be created via an initial click followed by double click sequences and going back to the polygon start, with either platform type, ending the polygon with two separated clicks. Also relevant to that same tutorial and it’s pointer-events:none; discovery, today’s mobile work regarding the textarea elements plotted to show the rectangular limits of user defined areas already created we found “real world relevance” to applying this to mobile such textarea elements. That is because on some mobile platforms these textarea elements will never be able to be resized out of the way, but if we apply pointer-events:none; to these, it does not matter, as the user can, as required, click/touch through these overlayed elements that have a huge z-index and semi-transparency applied to them.

Again, perhaps on a mobile platform web browser, feel free to try …

Did You Know?

There are known Safari mobile web browser textarea resizing limitations as we discovered trying a Google search of allow textarea resizing on mobile safari web browser, thanks, that we gleaned from the use of …

Solution 2: Standard JavaScript Auto-Grow
If you need to support older versions of iOS Safari that lack the newest CSS specs, you can dynamically update the box height using a tiny JavaScript event listener. This removes the scrollbar and expands the container vertically as they type:

HTML: html
<textarea id=”mobile-textarea” rows=”3″ oninput=”autoGrow(this)”></textarea>

JavaScript: javascript
function autoGrow(element) {
element.style.height = “auto”;
element.style.height = (element.scrollHeight) + “px”;
}

… incorporated ideas to help here.


Previous relevant Canvas Interfacer Three Finger Gesture Usage Tutorial is shown below.

Canvas Interfacer Three Finger Gesture Usage Tutorial

Canvas Interfacer Three Finger Gesture Usage Tutorial

There’s more research needed around here regarding mobile platform usage to the HTML5 canvas based ideas swirling around yesterday’s Random Background Image Map Area Polygons Tutorial‘s work, and one issue we came across was …

  • on mobile platforms you can get to gesture results whereby the canvas is all you see on the screen (eg. of an iPhone) …
  • but what if you are in “scribble mode” at that point?
  • before today, we were having trouble using …
    1. two finger “pinch” gesture to zoom out … or …
    2. one finger “swipe” to reveal more to the right (where, if we could have reached it, that right hand menu of annotation options has none of these “scribble mode” oddities) … because …
    3. before today, that last idea just drew a “scribble” “free drawing” line to the canvas

    … to reach the menu or any other non-canvas element not in “scribble mode” (ie. scrolling could not be achieved, at least in a way we could immediately access)

And so, we asked Google, thanks, “detect three finger gesture and if so scroll in the direction indicated” and got this useful advice …

Web Implementation (JavaScript)

If you are building this for a website or web app, you can use the touchstart and touchmove events to capture finger coordinates, check if exactly three fingers are on the screen, and then calculate the direction.

… to (start with globalvar isthree=false; and) end up with


if (eval('' + event.touches.length) >= 3 && event.type == "touchstart") {
isthree=true;
return;
} else if (isthree && event.type == "touchend") {
//if (isthree) {
isthree=false;
window.top.scrollBy(200,0);
return;
//}
}

… near the top of our function toptouchHandler(event) Javascript code in our changed signature_signature.js external Javascript canvas interfacer helper.


Previous relevant Random Background Image Map Area Polygons Tutorial is shown below.

Random Background Image Map Area Polygons Tutorial

Random Background Image Map Area Polygons Tutorial

Further to the recent Random Background Alternate Image Source Tutorial

  • Image Map only allowing for area subelements with shape=rect … today we also allow for …
  • Image Map now allowing for area subelements with shape=poly …

… via …

Right clicks after an initial click are the means by which you can define area shape=poly ( as distinct from the default shape=rect ) elements where to finish a polygon two click back close to the start point.

… as a modus operandi for the user to cater for more complex shape definitions in their Image Maps.

That doesn’t mean the rectangle around such a polygon is not also significant. Do you know why?

Yes, a hosting HTML div of a specific width and height and positioned absolutely at a precise left and top screen position allows SVG innerHTML like …


<svg xmlns="http://w3.org" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"><polyline points="0,67,56,7,100,0,150,17,0,67"></polyline></svg>
... be showing a polygonal user clicked shape, scaled appropriately, yet responsively, and allowing for those % unit definitions above making all this methodology useful here. Notice the zero co-ordinates? That is no accident. We make the co-ordinates relative to the minimum x and minimum y "datum" to the co-ordinating.

Feel free to try ...

Did You Know?

We broached the idea "pass event logic down through even though an element has a bigger z-index" to Google, thanks, and got back ...

To pass events down through a higher z-index element, add pointer-events: none; to the top element. This tells the browser to ignore the overlay for mouse events, allowing clicks and hovers to "fall through" to the element stacked beneath it.

... to learn a whole new technique we've been looking for for quite some time now ... now, where did we put that "Overlay Disappointments File"?! ... bye bye!


Previous relevant Random Background Alternate Image Source Tutorial is shown below.

Random Background Alternate Image Source Tutorial

Random Background Alternate Image Source Tutorial

Onto the recent Random Background Image Map Integration Tutorial's web application's use of ...

  • Lorem Picsum image repository "source" of image data ... today we allow the user to, instead, get images from ...
  • RJM Programming WordPress Tutorial Images (ie. this WordPress.org blog)

... and we've shored up the copy and pasting of screen logic, so that ...

  • the screen is more filled with image data, and the relevant graphical pasting place "border enhanced", in the process ...
  • the images have better resolution, in the process

... as the two areas of improvement within ...

... regarding it's newish Random Image Map integrations.


Previous relevant Random Background Image Map Integration Tutorial is shown below.

Random Background Image Map Integration Tutorial

Random Background Image Map Integration Tutorial

Like with ...

... and allowing users using our inhouse Random Background interfacer the chance to create some Image Maps using incarnations of these images as the visual basis to them.

We've chosen ...

  • the oncontextmenu (ie. right click) as an intervention point to facilitate this ... or ...
  • if using a macOS operating system a ...
    1. control-command-shift-3
    2. control-command-shift-5

    ...

    document.addEventListener('keydown', (event) => { // thanks to https://www.google.com/search?q=javascript+detecting+control-command-shift-3&rlz=1C5OZZY_en&oq=javascript+detecting+control-command-shift-3&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQIRigATIHCAIQIRigATIHCAMQIRigATIHCAQQIRigATIHCAUQIRiPAjIHCAYQIRiPAjIHCAcQIRiPAtIBCTE3NzMyajBqN6gCALACAA&sourceid=chrome&ie=UTF-8
    // Check if Control, Command (metaKey), and Shift are all held down
    // AND the key pressed is the number 3
    if (
    event.ctrlKey &&
    event.metaKey &&
    event.shiftKey &&
    event.code === 'Digit5'
    ) {
    // Prevent the default browser action if necessary
    //event.preventDefault();

    //var kc=eval(-2 + event.keyCode);

    event.preventDefault();
    event.stopImmediatePropagation();

    // Create a fake event with a modified code (e.g., ArrowDown)
    const simulatedEvent = new KeyboardEvent("keydown", {
    key: "3",
    code: "Digit3",
    ctrlKey: true,
    metaKey: true,
    shiftKey: true
    }); // keyCode: kc, bubbles: true, cancelable: true,

    // Fire the fake event into the DOM
    event.target.dispatchEvent(simulatedEvent);

    if (immap && !holdoff) { holdoff=true; setTimeout(function(){ wowo=window.open('/HTMLCSS/user_of_signature_signature.htm?askforpaste=y&imagemap=url#' + myco.toDataURL('image/jpeg',0.4), '_blank', 'top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height)); setTimeout(function(){ holdoff=false; }, 8000); }, 2000); }

    console.log('Control + Command + Shift + 3 combination detected!');
    // Insert your custom logic here
    }
    });

    ... combination is another modus operandi in play

... within ...

... regarding it's new Random Image Map integrations.


Previous relevant Inhouse Image Map WordPress Integration Tutorial is shown below.

Inhouse Image Map WordPress Integration Tutorial

Inhouse Image Map WordPress Integration Tutorial

The recent work of Inhouse Image Map Creator Browsing Tutorial ...

  • established a URL means by which a single URL call from the canvas residing Inhouse Image Map Creator and Canvas Annotation web application via a data URI hashtag conduit ... and today just ...
  • allowing for an absolute URL in that hashtag is the relatively simple change needed so that, using this, our WordPress "right click over an img image element" functionality can be tweaked ...


var huhifs=prompt('Optionally, please, any CSS for images ... append 3 spaces to be able to edit this ' + (gthing == 'image' ? gthing + ' (and answer of #imagemap will use this image as basis for creation of an image map in a new window)' : gthing) + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
if (huhifs == null) {
huhifs='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (event.target.outerHTML.indexOf('<a ') == 0) {
console.log(6);
ggurl=event.target.href;
} else {
console.log(66);
ggurl=document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="')[eval(-1 + document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="').length)].split('"')[0];
}
if (6 == 6) {
console.log(ggurl);
window.open(ggurl,'_blank'); ggurl='';
// huhifs=window.prompt('Optionally, please, any CSS for images ... append three spaces to be able to edit this ' + gthing + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
} else {
setTimeout(function(){ window.open(ggurl,'_blank'); ggurl=''; }, 5000); //alert(event.currentTarget.outerHTML); //event.currentTarget.click();
}
}
}
if (huhifs.toLowerCase() == '#imagemap') {
event.preventDefault();
event.stopPropagation();
ggurl=event.target.src;
window.open('//www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm?imagemap=url#' + (ggurl.indexOf('//') != -1 ? '//' + ggurl.split('//')[1] : (ggurl.replace(/^\.\//g,'/').indexOf('/') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(1).replace(/^\//g,'ITblog/') : (ggurl.indexOf('../') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(3) : ggurl))),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height));
ggurl='';
} else
if (huhifs.indexOf('data:image/') == 0) {
if (document.getElementById('imgcopycheck') && usuff != '') { //if (document.URL.indexOf('/streetart/') != -1) {
uplitc(huhifs); //alert(document.URL);
}
return '';
}

... as an excerpt from the changed onrightclick.js external Javascript called by WordPress, and calling ...


Previous relevant Inhouse Image Map Creator Browsing Tutorial is shown below.

Inhouse Image Map Creator Browsing Tutorial

Inhouse Image Map Creator Browsing Tutorial

Repeat after me ...

an image is a canvas is an image

?

an image is a canvas is an image

... good, now, again ... an image is a canvas is an image ...

an image is a canvas is an image

... excellent, now, backwards ... egami na si savnac a si egami na ...

egami na si savnac a si egami na

... wow! ... Now, lastly … I want my mamma! Now! ...

I want my mamma! Now!

 

But it's true. Our thinking behind allowing browsed for image files become data URIs that can be the img element "image" part of the "image map", further to yesterday's Inhouse Image Map Creator Mobile Debug Tutorial, we can now create using our inhouse Image Map Creator capable web application uses the "an image via [canvasContext].drawImage() is a canvas via [canvas].toDataURL() is an image" concept that can save us heaps of time with this project. Instead of intervening at each dropdown option mentioning "Browse" to make this design change, we, instead, introduce to the HTML5 canvas element a new ondblclick event ...


<canvas ondblclick="qwowo=window.open(document.URL.split('?')[0].split('#')[0] + '?imagemap=url#' + this.toDataURL('image/jpeg',0.4),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height) + '');" ondragstart="dragstart(event);" draggable="false" title="Ready for you to create your canvas 🎨 content above any signature 💳 panel ... keys U for Undo and R for Redo can work after a discrete click ending any scribble mode of use. Double click can facilitate turning this canvas content into an image map, and this canvas content can be populated by so many of the options in the menu to the right, which includes many local image file browsing choices." id="topcanvas" width=850 height=600 style="background-color:white; position: absolute; top:0; left:0; border-bottom:5px solid yellow; border-right:5px solid blue;"></canvas>

... allowing that "on double click" result in the web application turning into an Image Map Creator where now ...

Image Map ( ie. <img src="[image URL as entered by user or data URI browsed for by the user, or, come to think of it, from a couple of days back, entered in by the user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... is that very pithy redefinition of our web application's view of what an Image Map can be! Though?!

 

Again, feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Mobile Debug Tutorial is shown below.

Inhouse Image Map Creator Mobile Debug Tutorial

Inhouse Image Map Creator Mobile Debug Tutorial

Apologies to any mobile users wanting to access this new inhouse Image Map creator web application last talked about with yesterday's Inhouse Image Map Creator Interactive Drill Down Tutorial before today, that is, but we were leaving the issue until a proper hardware ...

  • Mac Book Air
  • Apple white lead
  • iPhone

... that once the middle one plugs into the top and bottom allows for ...

  • iPhone Safari web browser call of the inhouse Image Map creator ... could tee up with (ie. attain a "connection" with) ...
  • Mac Book Air Safari web browser Develop -> (in our case) Robert's iPhone -> user_of_signature_signature.htm

... online debugging session, could be arranged and a block of time set aside to concentrate on, because "concentrate" is the name of the game here!

Luckily, the issue was straightforward, where many are not. In the overseeing code, we had ...


<script type=text/javascript>
var oklj=0;
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || document.URL.indexOf('?fcol=') != -1) {
oklj=oklj;
} else {
document.write("<iframe id=ifconto name=ifconto src='/PHP/animegif/tutorial_to_animated_gif.php#rand=" + Math.floor(Math.random() * 19878675) + "' style='width:100%;height:900px;display:BLOCK;'></iframe>");
}
</script>

... ba bow ... because in the external Javascript we got pulled up by the debugging of the iPhone execution attempt at a codeline, where the user decides to take on an Image Map creation task ...


top.document.getElementById('ifconto').src='/About_Us.html';

... ba bow. On mobile, that necessary HTML iframe was non-existant! So, with the external Javascript, at this similar juncture, we came up with ...


if (!top.document.getElementById('ifconto')) {
top.document.body.innerHTML+="<iframe id=ifconto name=ifconto src='/About_Us.html' style='width:100%;height:900px;display:none;'></iframe>";
} else {

top.document.getElementById('ifconto').src='/About_Us.html';
}

... to start getting somewhere, here, with these inhouse Image Map creation ideas on mobile platforms.

And what about ...

  1. allow for data URIs pasted into the prompt window
  2. create non-mobile rubber banded overlays to help contextualize further

? Huh?! Feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Interactive Drill Down Tutorial is shown below.

Inhouse Image Map Creator Interactive Drill Down Tutorial

Inhouse Image Map Creator Interactive Drill Down Tutorial

It might be the case, often, with Image Map creations, as with our recent web application featuring in yesterday's Inhouse Image Map Creator Drill Down Tutorial that the user needs to ...

strike while the iron is hot

... regarding having the event logic be nuanced as the image map area subelements are created in terms of ...

  • area subelement inline event logic definitions (pointing at, perhaps, local Javascript functions) ... as well as ...
  • the content of those local Javascript functions

... in such a way that, if you come back to "flesh out" the image map HTML coding the next day, say, there are enough clues you've left that you do not have to go and match the "coords" attribute values to a screen position to get some context. That takes a lot longer we find.

And so, today, we now offer ...

Enter an Image URL (append space to create Image Maps where click/tap pairs can define rectangle corners ... cursor is a crosshair for lower left click/tap, first, then cursor is pointer top right ... append another one space to prompt for tailored event logic each time and two spaces to also review the default Javascript used for double click logic image map testing purposes ... we are going to discourage scrolling here, but you can still zoom out or in)

... Javascript prompt windows "on the fly" to allow for this to be a possibility for the Image Map creator using ...


Previous relevant Inhouse Image Map Creator Drill Down Tutorial is shown below.

Inhouse Image Map Creator Drill Down Tutorial

Inhouse Image Map Creator Drill Down Tutorial

Onto yesterday's Inhouse Image Map Creator Tutorial we've decided today's work should stay within non-mobile realms but flesh out more user available functionality to help with "stage two" thinking. With that in mind ...

  • the image map HTML containing textarea created (with yesterday's efforts using the Canvas and Image Map web application (now featuring a new emoji button 🗺️🖼️ to allow for a non-dropdown usage approach)) has an ondblclick event logic added so that when double clicking, at any stage of the image map creation processing, it ...
  • opens a new popup window where that HTML you have so far is surrounded by a default "rest of webpage" scenario as the HTML that goes into making up that popup window HTML content, and where you can test out it's workings ... as well as ...
  • that popup window image map, itself, is given an ondblclick event logic whereby a double click there can create below that image map within the same popup window a new textarea element containing all that HTML (default "rest of webpage" and all) which can be copied into a clipboard buffer as required ... and ...
  • if that textarea within the popup window is edited and the user double clicks that textarea element, a new popup window reflecting your changes is opened above that ... etcetera etcetera etcetera

All this can be used to either/both validate your image map and follow through further to incorporating the image map into a functional HTML webpage, using the changed signature_signature.js external Javascript to make all this possible. Within that changed external Javascript we allow the user to cancel the proposed area subelement currently embarked upon between where the user has clicked/tapped the bottom left and before they shape to click/tap the top right rectangle definition, via a right click, so as to reset back to the click/tap using the crosshair cursor back at a bottom left area shape=rect subelement definition.


Previous relevant Inhouse Image Map Creator Tutorial is shown below.

Inhouse Image Map Creator Tutorial

Inhouse Image Map Creator Tutorial

The "largely canvas" using web application last talked about with WordPress Blog Image Editing Media Tutorial, today, we're excited to announce, has been given an "on first draft just image URL" using new ...

Image Map ( ie. <img src="[image URL as entered by user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... arrangement inhouse means to construct image maps, so far, just via an image URL.

Why hook into the largely canvas savvy web application? Well, it is that basic positional mouse event logic that is needed to create image maps, and here, it is a dominant theme, and useful, even though the rearrangement of data needed is quite substantial, still, that is where we think this new functionality appears most at home, being a new suboption ("Image 🖼 Canvas Matches Actual URL or Image Map rectangle area creations") off a dropdown option means of deploying.

No tests on mobile, yet, but on non-mobile, we're happy, once the user chooses to create Image Maps, so long as ...

  1. we stop user web page scrolling ... while still allowing ...
  2. webpage zooming out or in

... in conjunction with ...

  • replacing the webpage table's left cell content, which used to contain a canvas element, with the user defined image, via it's URL ...
  • replacing the webpage table's right cell content, which used to contain an canvas annotation menu, with the image map URL HTML built up from user lower left and upper right rectangle defining click/taps

... we have the wherewithal to create image map HTML code the user can copy and use, with "stage two" fleshing out!

Try this at ...

... to allow for this image map inhouse functionality. The talents of HTML textarea elements, with their resizing abilities, helps out here, allowing these overlayed textarea elements ...

  1. containing image map HTML ... and/or ...
  2. overlaying semi-transparentally to see what has been clicked already

... also be able to be resized "out of the way" should that be needed perhaps regarding overlapping scenarios, without having to resort to any other type of event logic to allow for. The other big and relevant talent of textarea elements is their ability to contain HTML code and be editable with that HTML code, perhaps user amended, and to be able to Select All then Copy into a clipboard buffer, via it's right click web browser menu, ready to paste somewhere else, that HTML content ready for any required "stage two" embellishment and usage.


Previous relevant WordPress Blog Image Editing Media Tutorial is shown below.

WordPress Blog Image Editing Media Tutorial

WordPress Blog Image Editing Media Tutorial

We're happy to be revisiting ...

... to add to our recent WordPress Blog Image Editing functionality, extending it's capabilities to be able to optionally create either/both ...

  • Video
  • Animated GIF

... media presentations off this should the user pick more than one image, to be edited, in any one web browser tab (via window.sessionStorage) session. So far, we're creating ...

  • window.open
  • background image
  • background-size: contain

... "Video" and "Animated GIF" presentations, and see this as a shareable commodity, into the future, especially as the image slide data ends up being an HTML canvas [canvas].toDataURL() data URI that represents ...

  1. lots of data
  2. but understood everywhere

... and content wise has included within it, any canvas manipulations and annotating and reworking the user has applied plus, at least for Google Chrome, any image filtering CSS the user has requested, into that canvas. We shape to involve the cowsay actual web server disk based media creating interfacing, but not for now. We'll see, because WordPress Visual Synopsis Media Tutorial methodologies also ended up presentation wise, with "inhouse" "Video" and "Animated GIF" presentations.

How does the user make this happen? Well, at the opportune call of our Canvas Image Editor web application some "Mantissa MadnessMagic" takes place using ...


if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").indexOf('.') != -1) {
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]))) {
if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "") >= '1') {
setTimeout(function(){
if (document.getElementById('storyboard') && document.getElementById('toptd')) {
document.getElementById('toptd').innerHTML=document.getElementById('toptd').innerHTML.replace(document.getElementById('storyboard').outerHTML, '  <button onclick="top.videoshow();">Video &#128249;</button>  <button onclick="top.agshow();">Animated GIF &#128444;</button> ' + document.getElementById('storyboard').outerHTML);
}
}, 8100);
}
setInterval(function(){
var mycisv=document.getElementById('topcanvas');
var mycisvcon=mycisv.getContext('2d');
var mycanc=mycisv.toDataURL('data/jpeg', 10);
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value.length != mycanc.length) {
top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value=mycanc;
top.agup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
top.vdup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
}
}, 10000);
}
}

... to look like ...

    

... appearing in the right cell hosted Annotation Menu tools of the changed user_of_signature_signature.htm inhouse image data fed canvas editor web application.

The fourth draft onrightclick.js external Javascript now includes those onclick logic event functions ...


function agshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var ist=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts; } else { document.title=dtp + dtstwo; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist++; setTimeout(startit, 5000); } setTimeout(startit, 2000); </scr' + 'ipt>';
woagis=window.open('','_blank','top=110,left=110,width=700,height=700');
woagis.document.write('<html><head><title>Animated GIF of selected images ... start of looping presentation ...</title>' + ascr + '</head><body style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

function videoshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var verbs=[" paused"," playing"], ist=0, inc=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation ", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts + verbs[inc]; } else { document.title=dtp + dtstwo + verbs[inc]; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist+=inc; setTimeout(startit, 1000); } setTimeout(startit, 1000); </scr' + 'ipt>';
wovdis=window.open('','_blank','top=100,left=100,width=700,height=700');
wovdis.document.write('<html><head><title>Video of selected images ... start of looping presentation </title>' + ascr + '</head><body title="Initially paused but on loop when started. Click to toggle between pause and play." onclick="inc=eval(1 - inc);" style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

... creating those popup window "Video" and/or "Animated GIF" presentations we've been talking about above.

The WordPress Blog TwentyTen theme's header.php gets a crucial new Javascript function referenced elsewhere ...

<?php echo "

function firstuptop() {
var ifnum=1, arrc=['cow', 'ime'], butsuff='', arrbw=['', ' of Selected Images'], arrolp=['vif','ime'];
var utd='<div id=divime style=display:none;>';
for (var jime=0; jime<2; jime++) {
if (jime > 0) {
utd+="</b><br><iframe name=my" + arrc[jime] + "ifr id=my" + arrc[jime] + "ifr style=display:none; src=/About_Us.html></iframe><form target=my" + arrc[jime] + "ifr action=/cowsay.php method=POST id=my" + arrc[jime] + "pf><div id=div" + arrc[jime] + "pf></div><input type=submit id=vlist" + butsuff + " style=display:none;background-color:lightblue; name=vlist" + butsuff + " value='Video &#128249; " + arrbw[jime] + "'></input> <input type=submit style=display:none;background-color:lightblue; id=aglist" + butsuff + " name=aglist" + butsuff + " value='Animated GIF &#128444; " + arrbw[jime] + "'></input></form><table cellpadding=20><tbody><tr></tr></tbody></table></div><p id='backtoblog'></p>";
}
butsuff='ime';
}
utd+='</div>';
document.body.innerHTML+=utd;
}

"; ?>

... to help create, within the blog posting webpage content, the HTML skeletal necessaries modelled on how WordPress Visual Synopsis Media Tutorial worked it for Visual Synopsis (Slideshows) functionality which included inhouse "Video" and/or "Animated GIF" media presentations.


Previous relevant WordPress Blog Posting Feature Image Editing Tutorial is shown below.

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

Yesterday's ...

  • One Image Website Image Snapshot Editing Tutorial used web browser new tab webpages to allow for image editing and annotating ... but with today's ...
  • WordPress Blog Posting Feature Image Editing Tutorial we're using a hosted HTML iframe window within the blog posting webpage of interest

And that should be a lot easier to handle, yes?! Well, yes, maybe, but not that much easier. A little bit "easier" because the logic is largely funnelled into code that is common to both modus operandi.

In amongst the commonalities, thankfully, the means to get to the "image editing and annotating" and/or "image styling" functionality remains ...

Non-mobile right click or spread/pinch mobile gesture on most blog posting images can lead to image editing and annotating functionality, where for animated GIFs first slide is chosen.

We learnt a bit making the mobile ontouchend spread/pinch detection more bulletproof ...


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
setTimeout(function(){
document.ontouchend=function(e){
if (document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') != -1) {
lastsp=eval(e.touches.length);
}
if (eval('' + e.touches.length) >= 1) {
if (document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') == -1) {
onrightclickask();
} else if (e.touches[0].target.outerHTML.split('>')[0].indexOf('<img ') == 0 && e.touches[0].target.outerHTML.split('>')[0].indexOf(' tabindex=') != -1) {
onrightclickask(); //document.title=':' + e.touches[0].target.outerHTML.split('>')[0].substring(1);
}

}
};
}, 4000);
}

... but ahead of this, for the TwentyTen theme changes to codex webpage structure we predominantly do with a good ol' tailored header.php the most effective modified (which is new) codeline now goes ...

<?php

$post->post_content=str_replace('<i' . 'mg' . ' i' . 'd=', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); i' . 'd=', str_replace('<i' . 'mg' . ' s' . 'rc=', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); s' . 'rc=', str_replace('<i' . 'mg' . ' st' . 'yle="border', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); st' . 'yle="border', str_replace('<i' . 'mg' . ' st' . 'yle="float', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); st' . 'yle="float', str_replace('<i' . 'mg' . ' deco' . 'ding=', '<i' . 'mg' . ' tabindex=0 onconte' . 'xtmenu=imgedit(event); ontou' . 'chend=imgedit(event); deco' . 'ding=', $post->post_content)))));

?>

... calling new Javascript function ...

<?php echo "

function imgedit(evt) {
if (('' + evt.target.outerHTML.split('>')[0]).indexOf(' class="iiconlist') == -1) {
preonrightclickask(evt);
}
}

"; ?>

Other than header.php WordPress PHP code we changed ...


Previous relevant One Image Website Image Snapshot Editing Tutorial is shown below.

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

Augmenting yesterday's One Image Website SessionStorage Image Filtering Tutorial adding cropped image editing functionality, we see it as ...

Running against us regarding One Image Website design .. Running for us regarding One Image Website design ...
the programmatical scrolling means embedded iframe hosting will not work way window.prompt freezes all Javascript at a snapshot of time ...
hashtag navigation can be the conduit to pass data onto inhouse Canvas Editor of Image Data
[canvasContext].drawImage has a variety of useful calls (in that OOP method feel) allowing for dynamic cropping

That "one against" stopped how we envisaged the work at the start of the day. We thought we'd use window.sessionStorage (or maybe window.localStorage) as the only data conduit needed, and we'll be continuing that idea with another approach into the future, but back to today, hashtagging provided that conduit means, even if we were using data URIs (though all we need today are image absolute URLs).

And then there was "the unknown factor" ...

Can [canvasContext].drawImage draw that image with CSS filter styling applied?

Well, we found using Javascript DOM ahead of the new Image() call ...


xcelem=document.getElementById('topcanvas');
xccontext = xcelem.getContext("2d");
xcimg=new Image;
xcimg.onload = function(){
var mysx=('' + window.sessionStorage.getItem('user_of_signature_signature_sx')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sx')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The x coordinate where to start clipping
var mysy=('' + window.sessionStorage.getItem('user_of_signature_signature_sy')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sy')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The y coordinate where to start clipping
var myswidth=('' + window.sessionStorage.getItem('user_of_signature_signature_swidth')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_swidth')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The width of the clipped image
var mysheight=('' + window.sessionStorage.getItem('user_of_signature_signature_sheight')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sheight')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The height of the clipped image
var myx=('' + window.sessionStorage.getItem('user_of_signature_signature_x')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_x')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // The x coordinate where to place the image on the canvas
var myy=('' + window.sessionStorage.getItem('user_of_signature_signature_y')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_y')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // The y coordinate where to place the image on the canvas
var mywidth=('' + window.sessionStorage.getItem('user_of_signature_signature_width')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_width')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The width of the image to use (stretch or reduce the image)
var myheight=('' + window.sessionStorage.getItem('user_of_signature_signature_height')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_height')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The height of the image to use (stretch or reduce the image)
if (mywidth != '' && myheight != '') {
xcelem.width=eval('' + mywidth);
xcelem.height=eval('' + myheight);
if (('' + xcimg.style.filter).replace(/^undefined/g,'').replace(/^null/g,'').trim() != '') {
xccontext.filter=xcimg.style.filter;
}
if (myx != '' && myy != '' && myswidth == '' && mysheight == '') {
xccontext.drawImage(xcimg,eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight));
setTimeout(function(){ xccontext.drawImage(xcimg,eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight)); }, 3000);
window.sessionStorage.removeItem('user_of_signature_signature_x');
window.sessionStorage.removeItem('user_of_signature_signature_y');
window.sessionStorage.removeItem('user_of_signature_signature_width');
window.sessionStorage.removeItem('user_of_signature_signature_height');
} else {
xccontext.drawImage(xcimg,eval('' + mysx),eval('' + mysy),eval('' + myswidth),eval('' + mysheight),eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight));
setTimeout(function(){ xccontext.drawImage(xcimg,eval('' + mysx),eval('' + mysy),eval('' + myswidth),eval('' + mysheight),eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight)); }, 3000);
window.sessionStorage.removeItem('user_of_signature_signature_sx');
window.sessionStorage.removeItem('user_of_signature_signature_sy');
window.sessionStorage.removeItem('user_of_signature_signature_swidth');
window.sessionStorage.removeItem('user_of_signature_signature_sheight');
window.sessionStorage.removeItem('user_of_signature_signature_x');
window.sessionStorage.removeItem('user_of_signature_signature_y');
window.sessionStorage.removeItem('user_of_signature_signature_width');
window.sessionStorage.removeItem('user_of_signature_signature_height');
}
} else {
xcelem.width=xcimg.width;
xcelem.height=xcimg.height;
if (('' + xcimg.style.filter).replace(/^undefined/g,'').replace(/^null/g,'').trim() != '') {
xccontext.filter=xcimg.style.filter;
}
xccontext.drawImage(xcimg,0,0);
setTimeout(function(){ xccontext.drawImage(xcimg,0,0); }, 3000);
}
if (window.parent) {
if (parent.document.getElementById('if_image_canvas')) {
if (('' + parent.document.getElementById('if_image_canvas').style.height).replace('px','').trim() != '') {
if (eval('' + ('' + parent.document.getElementById('if_image_canvas').style.height).replace('px','').trim()) < eval(200 + eval('' + xcelem.height))) {
parent.document.getElementById('if_image_canvas').style.height='' + eval(200 + eval('' + xcelem.height)) + 'px';
}
} else {
parent.document.getElementById('if_image_canvas').style.height='' + eval(200 + eval('' + xcelem.height)) + 'px';
}
parent.document.getElementById('if_image_canvas').style.display='block';
if (parent.document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') != -1) {
parent.document.getElementById('if_image_canvas').scrollIntoView();
}
}
}
};
var incomings=('' + window.sessionStorage.getItem('user_of_signature_signature_filter')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_filter')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The image filter CSS styling to apply
if ((incomings.indexOf('%20') != -1 || 7 == 7) && incomings.replace(':',')').indexOf(')') != -1 && incomings.indexOf('style=') != -1) {
incomings='style=' + encodeURIComponent((incomings.split('style=')[1].split('&')[0].split('#')[0]).replace(/\%20/g,' ').replace(/\+/g,' '));
}
var relincomings=incomings.split('style=')[1] ? decodeURIComponent(incomings.split('style=')[1].split('&')[0].split('#')[0]).replace(/\%20/g,' ').replace(/\+/g,' ') : '';
if (relincomings.indexOf('filter:') != -1) {
xcimg.style.filter=relincomings.split('filter:')[1].split(';')[0].split('}')[0];
}
xcimg.src=xcont;

... didn't help, and then we asked the online woooorrrrrllllddd to come across this very useful link, thanks to teach us ...

That [canvasContext].filter is a thaing ... yay!!!

Luckily we didn't need to change One Image Website base HTML to make this happen, but, rather ...

... with the user able to make this happen with those right click (non-mobile) or pinch or swipe gesture (mobile) actions (talked about with yesterday's One Image Website SessionStorage Image Filtering Tutorial) getting the user to a prompt window with the modified "blurb" ...

Optionally, please, any CSS for images ... append three spaces to be able to edit this screenshot in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. filter: grayscale(100%);

... talking about the three appended spaces needed.


Previous relevant One Image Website SessionStorage Image Filtering Tutorial is shown below.

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

Further to the long ago One Image Website Scrolling Position Fix Tutorial last mention of our inhouse One Image Website series, today we have ...

  • clientside image filtering functionality to offer ...
  • almost exclusively using window.sessionStorage ideas (rather than our usual window.localStorage (ie. like Cookies) usage)

Why is that last point any big deal? Well, programmers will tell you, often the tidy up of a new arrangement involves as much, or more, coding to do than the instigation. And a lot of programmers, am sure, will agree that that is a pain in the neck, often. But the use of window.sessionStorage at the expense of window.localStorage allows the programmer to go ...

Aaaaaahhhhh

There is so much less to tidy up. Using window.sessionStorage it is only data on that web browser tab that comes into play, and as soon as that web browser tab no longer exists, nor does the window.sessionStorage data you stored. Yayyyyyyy!

We found we couldn't quite make it exclusively with window.sessionStorage because in the One Image Website paradigm of offering music playing we lost window.sessionStorage data for one of the two web browser tabs that become involved to start the music rolling. So sad. Nevertheless, we transferred some controllable temporary window.localStorage data storage over to window.sessionStorage data storage at the opportune time ...


if (('' + window.localStorage.getItem(prefss + '_filter')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
if (('' + window.sessionStorage.getItem(prefss + '_filter')).replace(/^undefined/g,'').replace(/^null/g,'') == '') {
window.sessionStorage.setItem(prefss + '_filter', window.localStorage.getItem(prefss + '_filter'));
window.localStorage.removeItem(prefss + '_filter');
} else {
window.localStorage.removeItem(prefss + '_filter');
}
}

... (we figured after a day of tinkering ... so sad).

How can the non-mobile user access these new aesthetic settings? Via a right click, as our new unfettered layer of functionality option, encapsulated by onrightclick.js external Javascript "proof of concept" effort, on the way to a Javascript prompt window, is the way we've gone about it. From there, the user can enter CSS non-selector actions such as the use of CSS filter property.

And as such, it's worth a revisit of one or all of our reworked One Image Website web applications ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately

... or you can start them off yourself up at the address bar with (typed in ... or just click) URLs such as ...


https://www.rjmprogramming.com.au/thecommute/?style=filter:invert(100%);

... or ...


https://www.rjmprogramming.com.au/ephemeral/?style=filter:blur(5px);

... or ...


https://www.rjmprogramming.com.au/streetart/?style=filter:hue-rotate(90deg);

... or ...


https://www.rjmprogramming.com.au/pyrmontultimo/?style=filter:sepia(100%);

... or ...


https://www.rjmprogramming.com.au/walkingtrip/?style=filter:saturate(200%);

... or ...


https://www.rjmprogramming.com.au/bygone/?style=filter:contrast(200%);

... or ...


https://www.rjmprogramming.com.au/thewest/?style=filter:brightness(240%);

Did you know?

All this begs the question ...

What about mobile?

Well, at least for iOS we think ...


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
setTimeout(function(){
document.ontouchend=function(e){
if (eval('' + e.touches.length) >= 1) {
onrightclickask();
}
};
}, 4000);
}

... did the job, with a pinch or swipe gesture, of getting us to that Javascript prompt window place, and then the rest is the same!


Previous relevant One Image Website Scrolling Position Fix Tutorial is shown below.

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

Today, we've bitten the bullet, and decided to shore up the webpage scrolling issues that could occur in yesterday's One Image Website VTT Tracks Tutorial, and before, with our set of One Image Websites. They represent, perhaps, a slightly unusual scenario whereby the image data is allowed to be itself, and being bigger than the dimensions of the webpage (straight from its digital source), in all probability. Hence, the randomized document.body scrolling that occurs.

But up until today our randomized range of scrollLeft and scrollTop positioning that could occur ranged over the entire width and height of the underlying image, while we think we should only be scrolling over the range ([imageWidth] - window.innerWidth (screen width)) x ([imageHeight] - window.innerHeight (screen height)). This could lead to white bands to the right and/or bottom of the webpage, in its presentation. And so we've fixed all the Javascript code to replace the old with the new in all the One Image Website codesets ...


var recti=document.getElementById(place).getBoundingClientRect();
//
document.getElementById("body").scrollTop = Math.floor(Math.random() * document.getElementById("body").scrollHeight);
//document.getElementById("body").scrollLeft = Math.floor(Math.random() * document.getElementById("body").scrollWidth);
document.getElementById("body").scrollTop = Math.max(0,Math.floor(Math.random() * eval(eval('' + recti.height) - eval('' + window.innerHeight))));
document.getElementById("body").scrollLeft = Math.max(0,Math.floor(Math.random() * eval(eval('' + recti.width) - eval('' + window.innerWidth))));

Any white bands you still see now will be caused by that being on the original photograph data stock (we're hoping), in ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately


Previous relevant One Image Website VTT Tracks Tutorial is shown below.

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

Using yesterday's Ffmpeg Log Helper Towards VTT File Primer Tutorial VTT files we could choose to use ...

... and, am sorry, but cannot award any points to those who chose the former, because ... well ... it's doubtful we'd mention the second unless we'd done it. And so the answer is ... the former ... down Nala ... the latter!

Today's blog posting is also a little story about the benefits of what we like to call client pre-emptive iframe logic, whereby we open an HTML iframe element, blazing away with its src attribute pointing at a URL that may or may not exist, and if it does, we do something about its content, usually, in the HTML iframe onload event logic. In our case the URL is a VTT file suiting the One Image Website of relevance given the upload and renaming of the VTTs created using yesterday's PHP ffmpeg log to VTT file creator web application.

As a programmer who would like to pursue true track cue Javascript coding, develop the function tracks in the One Image Website index-ssmhalf.html you could View -> Page Source from your favourite web browser, for any of ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately

... where, now, where the user plays music, perhaps continuously (like a radio) with an HTML audio element play button press, the currently playing song, thanks to Royalty Free Music For Video, help you keep in touch with the song playing up at the web browser tab and the image title.

This amounted to Javascript changes, as per ...

index.htm ...


var foreground=null; // and get rid of var in var foreground below
var plusstuff='';

function ftchange(tob) {
plusstuff=' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
if (document.getElementById('place').title.indexOf(' Playing ') == -1) {
document.getElementById('place').title+=' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
document.getElementById('place').title=document.getElementById('place').title.split(' Playing ')[0] + ' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
}
}


function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i) && document.URL.indexOf('?audio=') == -1) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.body.innerHTML+='<iframe id=ifmusicone title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" src="./index-ssmhalf.html?justmusic=00" style="opacity:0.5;z-index:345;position:absolute;width:140px;height:100px;left:' + eval(-140 + eval('' + window.innerWidth)) + 'px;top:0px;"></iframe>';
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}

function FadeInImage()
{
var foreground=document.getElementById("place");
window.clearTimeout("FadeInImage('" + "place" + "')");
rotateImage("place");
}

function rotateImage(place) {

while (number_of_image == 0)
{
place = place;
}
xplace=place;
//alert('yay2');

anotherNew();

var foreground=document.getElementById(place);
//alert(place);

var thedivlink=document.getElementById("thedivlink");
var thediv=document.getElementById("thediv");

if (foreground.width > 0) {
thedivlink.style.display = "none";
thediv.style.display = "none";
if (document.getElementById('ifmusicone')) {
document.getElementById('ifmusicone').style.display='none';
}

//alert('yay2a');
var alink=document.getElementById("alink");
var xxxx=alink.href;
if (xxxx.indexOf("mp3") != -1)
{
//alink.href="index-ssm.html";
//alink.onclick="javascript:void(0);";

alink.href="filewrite.php?id=session&name="+bigrandnumber+"&ext=txt&rand="+bigrandnumber;
alink.onclick="javascript:void(0);";
foreground.onclick="javascript:hasBeenClicked();";
foreground.title="Click for Bamboozled provided by http://www.freesoundtrackmusic.com" + plusstuff;

}
else
{
if (bigrandnumber >= 0) {
if (hasbeenclicked == 1 || NumOpen > 0 || does_file_exist("session",bigrandnumber,"txt"))
{
bigrandnumber = -1;
alink.href="upload.php";
//alink.onclick="javascript: window.open('index-ssm.html','Pyrmont, Ultimo - Inner Burbs - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');";
alink.onclick = "javascript:void(0);";
//alink.ondblclick = "javascript:void(0);";
foreground.title="Click for Upload functionality.";
alink.target = "_blank";
}
}
}
alink.target = "_blank";
}
else
{
thedivlink.style.display = "block";
thediv.style.display = "block";
}

SetOpacity(foreground,0.3);
// more rotateImage code follows
}
index-ssmhalf.html ...

var mycurt=-1;
var vttcont='';
var vtttitles=[];
var vttstartsecs=[];
var vttendsecs=[];
var vttlastt='';

function getct() {
if (document.getElementById('myaudio')) {
mycurt=document.getElementById('myaudio').currentTime;
console.log('ct=' + mycurt);
//top.document.title='Current time = ' + mycurt;
for (var jjk=0; jjk<vtttitles.length; jjk++) {
if (eval('' + mycurt) >= eval(-0.0001 + eval('' + vttstartsecs[jjk])) && eval('' + mycurt) <= eval(0.0001 + eval('' + vttendsecs[jjk]))) {
if ((vttlastt != vtttitles[jjk] || vttlastt.trim() != vttlastt) || vttlastt.trim() != vtttitles[jjk] || vttlastt == '') {
if (vttlastt.trim() != vtttitles[jjk]) { vttlastt=vtttitles[jjk]; } else { vttlastt+=' '; }
console.log('ct title=' + vtttitles[jjk]);
if (parent.document.title.indexOf(' - ') != -1) {
var huhsare=parent.document.title.split(' - ');
if (eval('' + huhsare.length) >= 3) {
parent.document.title=(parent.document.title.replace(' - ','`').split(' - ')[0] + ' - ' + 'Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ').replace('`', ' - ');
} else {
parent.document.title=parent.document.title.split(' - ')[0] + ' - ' + 'Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
if (parent.document.getElementById('place').title.indexOf(' Playing ') == -1) {
parent.document.getElementById('place').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
parent.document.getElementById('place').title=parent.document.getElementById('place').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
parent.ftchange(vtttitles[jjk]);
if (parent.document.getElementById('alink').title.indexOf(' Playing ') == -1) {
parent.document.getElementById('alink').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
parent.document.getElementById('alink').title=parent.document.getElementById('alink').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
if (document.getElementById('myaudio').title.indexOf(' Playing ') == -1) {
document.getElementById('myaudio').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
document.getElementById('myaudio').title=document.getElementById('myaudio').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
} else {
parent.document.getElementById('place').title='Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
parent.document.getElementById('myaudio').title='Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
}
}
}
}
}

function pushit() {
var timings=vttcont.split(' --> ');
console.log('timings length=' + timings.length);
if (eval('' + timings.length) == 1) {
//console.log('vttcont=' + vttcont);
timings=vttcont.split(' --> ');
console.log('Timings length=' + timings.length);
}
var spares='',sparesa=[], jspare=0.0;
var sparee='',spareea=[];
var ispare=0, iifg=0, ifactor=1.0;
var thistt='';
if (eval('' + timings.length) > 1) {
for (var kkll=1; kkll<timings.length; kkll++) {
spares='';
sparee=''
ispare=0;
while ((timings[kkll].substring(ispare).substring(0,1) >= '0' && timings[kkll].substring(ispare).substring(0,1) <= '9') || timings[kkll].substring(ispare).substring(0,1) == '.' || timings[kkll].substring(ispare).substring(0,1) == ':') {
sparee+=timings[kkll].substring(ispare).substring(0,1);
ispare++;
}
console.log('sparee=' + sparee + ' and ispare=' + ispare);
while (timings[kkll].substring(ispare).substring(0,1) <= String.fromCharCode(32)) {
ispare++;
}
console.log('ispare=' + ispare);
vtttitles.push(timings[kkll].substring(ispare).split(String.fromCharCode(10))[0].split('{')[0]);
console.log('title=' + vtttitles[-1 + eval('' + vtttitles.length)]);
spareea=sparee.split(':');
ifactor=1.0;
jspare=0.0;
for (iifg=eval(-1 + eval('' + spareea.length)); iifg>=0; iifg--) {
console.log('iifg=' + iifg + ' via ' + spareea[iifg] + '!');
jspare+=eval(ifactor * eval('' + spareea[iifg].replace(/^0/g,'')));
console.log('Jspare=' + jspare);
ifactor*=60;
}
vttendsecs.push(jspare);
ispare=-1;
console.log('jspare=' + jspare);
while ((timings[-1 + kkll].slice(ispare).substring(0,1) >= '0' && timings[-1 + kkll].slice(ispare).substring(0,1) <= '9') || timings[-1 + kkll].slice(ispare).substring(0,1) == '.' || timings[-1 + kkll].slice(ispare).substring(0,1) == ':') {
spares=timings[-1 + kkll].slice(ispare).substring(0,1) + spares;
ispare--;
}
console.log('spares=' + spares);
sparesa=spares.split(':');
ifactor=1.0;
jspare=0.0;
for (iifg=eval(-1 + eval('' + sparesa.length)); iifg>=0; iifg--) {
jspare+=eval(ifactor * eval('' + sparesa[iifg].replace(/^0/g,'')));
ifactor*=60;
}
vttstartsecs.push(jspare);
}

}
}

function gotback(iois) {
if (iois != null) {
//if (iois.src.indexOf('?placegeo=') != -1) {
//alert(1);
var aconto = (iois.contentWindow || iois.contentDocument);
//alert(11);
if (aconto != null) {
//alert(111);
if (aconto.document) { aconto = aconto.document; }
//alert(1111);
if (aconto.body != null) {
vttcont=aconto.body.innerHTML.replace('<pre>','').replace('</pre>','');
pushit();
}
}
//}
}
}

function tracks(iois) {
}


function showScroll() {
if ((navigator.userAgent.match(/iPhone|iPod|iPad/i) || top.document.URL.indexOf('?audio=') != -1) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
if (document.URL.indexOf('justmusic=0') != -1) {
document.getElementById('next').innerHTML+='<audio onloadedmetadata=tracks(this); id=myaudio title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + '; parent.document.body.setAttribute(' + "'data-music','yes'" + ');" style=position:absolute;top:0px;left:0px; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source><track kind="subtitles" src="sound/all.vtt" srclang="en"></track></audio><iframe onload=gotback(this) src=sound/all.vtt style=display:none;></iframe>';
} else {
document.getElementById('next').innerHTML+='<audio onloadedmetadata=tracks(this); id=myaudio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop data-ideanogo=autostart><source type=audio/mp3 src=sound/all.mp3></source><track kind="subtitles" src="sound/all.vtt" srclang="en"></track></audio><iframe onload=gotback(this) src=sound/all.vtt style=display:none;></iframe>';
}
//alert(document.getElementById('next').innerHTML);
console.log("1");
//var textTrackElem = document.getElementById("myaudio");
mycurt=0;
setInterval(getct, 2000);

setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}
if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}


Previous relevant Ffmpeg Log Helper Towards VTT File Primer Tutorial is shown below.

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday's One Image Website iOS Radio Music One Less Tutorial set us on an "off to the side, but eventually forward" project that intertwines ...

  • ffmpeg ... with its great logging and media concatenation talents, thanks ...
  • macOS Terminal desktop app ... regarding its great GUI design feature allowing you to gather up actions of the past into a copy buffer via its Edit -> Find functionality, thanks
  • Audio and Video HTML element track cue functionality VTT file interface ... you can read more about at HTML5 Track Element Primer Tutorial

Don't know about you, but have always found the creation of track data VTT files (and their predecessor SRT files) one of the most tedious jobs in programming?

But the work of the day before yesterday's One Image Website iOS Radio Music Tutorial and its audio concatenation via ffmpeg themes had us looking back, wistfully, back up our (macOS) Terminal (desktop apps) logging of a few days past, hoping for an escape from VTT file manual text editing for our wish to enhance our One Image Website work of recent days. Wow, the ffmpeg logging was brilliant!

There was enough there to program the creation of VTT files from the ffmpeg, and our "cd"ing and "ls"ing and other stuff, in the (let's more accurately say, Terminal) logging. Yayyyyy!

And so we have an albeit defaults very particular to my situation in its HTML form textarea and input type=text textbox defaults (shown via placeholder attributes), but we think it could be a tweakable basis for your own ffmpeg media concatenation work, perhaps, with our first draft proof of concept ffmpeg logging, via Terminal, PHP helper towards VTT file creation.

If you click the light green form submit button, in the iframe way below, yourself, it will reveal, in details/summary (revealing) tags, both the input and output (VTT files) for you to see this more clearly, or to have it clicked for you in a new window, click this button clicker incarnation. In the works of the HTML form below, for the first time we can remember, and because the defaults are so arcane, we developed HTML form onsubmit logic as per ...


<form id=myform onsubmit=" var ins=document.getElementsByTagName('textarea'); if (document.getElementById(ins[0].id).value == '') { document.getElementById(ins[0].id).value=('' + document.getElementById(ins[0].id).placeholder); } ins=document.getElementsByTagName('input'); for (var ii=0; ii<ins.length; ii++) { if (document.getElementById(ins[ii].id).value == '' && document.getElementById(ins[ii].id).type == 'text') { document.getElementById(ins[ii].id).value=('' + document.getElementById(ins[ii].id).placeholder); } } return true;" action=./ffmpeg_log_to_vtt.php method=POST>
<textarea name=infile id=infile title='Or paste in your ffmpeg log file data' placeholder='all_bar_thecommute.txt' value='' style="background-color:yellow;"></textarea><br><br>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Output Basename Prefixing Delimiter</th><th>Output Basename Suffixing Delimiter</th></tr>
<tr><td><input name=inbasenameprefix id=inbasenameprefix type=text placeholder='user@Users-Air' value=''></input></td><td><input name=inbasenamesuffix id=inbasenamesuffix type=text placeholder='% cd' value=''></input></td></tr>
</table>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Metadata Prefixing String</th><th>Metadata Name Value Delimiter</th><th>Metadata Title Value Case Insensitive Start String</th></tr>
<tr><td><input name=metaprefix id=metaprefix type=text placeholder='Metadata:' value=''></input></td><td><input name=metadelimiter id=metadelimiter type=text placeholder=':' value=''></input></td><td><input name=metatitleprefix id=metatitleprefix type=text placeholder='tit' value=''></input></td></tr>
</table>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Duration Prefixing String</th><th>Duration Time Part Delimiter</th></tr>
<tr><td><input name=durationprefix id=durationprefix type=text placeholder='Duration:' value=''></input></td><td><input name=durationdelimiter id=durationdelimiter type=text placeholder=':' value=''></input></td></tr>
</table>
<br><br><br>
<input id=mysub type=submit value="Create VTTs" style="background-color:lightgreen;"></input>
</form>

... as a way to deal with arcane defaults, where the encouragement is there for an interested programmer to download PHP code (perhaps to a MAMP local Apache/PHP/mySql web server environment) and tweak to their purposes. Note that you can paste your own logging into the textarea as a way this PHP application can be useful even up at the RJM Programming domain ...


Previous relevant One Image Website iOS Radio Music One Less Tutorial is shown below.

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday's One Image Website iOS Radio Music Tutorial "Stop Press" promised ...

For tomorrow, we offer an optional "one less click", "one less window" methodology improvement on the work above, as we transition the other "One Image Websites" over to the new iOS music paradigm.

... and so, it being tomorrow we're here starting our discussion starting with the "one less window" thought. Have a look at this table outlining some (off the top of the head) clientside navigation techniques in two categories ...

No new window created ... New window created ...
window.open([URL],'_self') window.open([URL],'_blank')
location.href=[URL] window.open([URL],'_top')
window.location=[URL] top.window.location=[URL]; // if in an iframe
Ajax (with or without new FormData()) whether 'GET' or 'POST' form target=_blank action=[URL]
form target=_self action=[URL] form target=_top action=[URL] // if in an iframe
iframe srcdoc=[webpageHTML] form target=_parent action=[URL] // if in an iframe
iframe src=[URL] parent.window.location=[URL]; // if in an iframe

... and it's that last left hand column iframe src=[URL] we like for the purposes of these changes today. That new HTML iframe in the "One Image Website" index.htm supervisories is now worked via ...


function rotateImage(place) {

while (number_of_image == 0)
{
place = place;
}
xplace=place;

anotherNew();

var foreground=document.getElementById(place);


var thedivlink=document.getElementById("thedivlink");
var thediv=document.getElementById("thediv");


if (foreground.width > 0) {
thedivlink.style.display = "none";
thediv.style.display = "none";
if (document.getElementById('ifmusicone')) {
document.getElementById('ifmusicone').style.display='none';
}

//
// more rotateImage code follows ...
//
}
//
// more rotateImage code follows ...
//
}

function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i)) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.body.innerHTML+='<iframe id=ifmusicone title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" src="./index-ssmhalf.html?justmusic=0" style="opacity:0.5;z-index:345;position:absolute;width:140px;height:100px;left:' + eval(-140 + eval('' + window.innerWidth)) + 'px;top:0px;"></iframe>';
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}


</script>
</head>
<body id="body" onload=' xonl(); if (document.URL.indexOf("exif=") != -1) { dexifit(); } showScroll(); window.setTimeout("FadeInImage()", 4000); '>
<div id="thediv" style="display:block;" >
<span><a id="thedivlink" style="display:inline-block;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." onclick="javascript: window.open('index-ssmhalf.html?justmusic=','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="#" data-href="sound/Prelude_Melody-Mike_Vekris.mp3" >The Commute - RJM Programming ... you might see this while loading ... &#127926; click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery &#127926; ... else please wait for full functionality ...</a> versus <a onclick=huhit(); onmousedown=huhittwo(); style=display:inline-block;cursor:pointer;text-decoration:underline;>Exif Run</a></span>
</div>
<a id="alink" style="font-size:28px;background-color:yellow;" onclick="javascript: window.open('index-ssmhalf.html','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)'); disableHref();" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="sound/Prelude_Melody-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming" src="siteimage.jpg" /-->
<img border=0 id="place" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." src="siteimage.jpg" />
</a>

... now, with the iOS platforms, presenting a new HTML audio (loop attribute set) in a slightly different incarnation as per index-ssmhalf.html ...



function nextPage()
{
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
image_index=image_index;
} else {

window.location = "index-saf.html";
}
}

function setvv() {
document.getElementById('place').style.visibility='visible';
}


function showScroll() {
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
if (document.URL.indexOf('justmusic=0') != -1) {
document.getElementById('next').innerHTML+='<audio title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + '; parent.document.body.setAttribute(' + "'data-music','yes'" + ');" style=position:absolute;top:0px;left:0px; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
} else {

document.getElementById('next').innerHTML+='<audio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
}
//alert(document.getElementById('next').innerHTML);
setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}

if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}

</script>
</head>
<body id="body" onload='showScroll(); window.setTimeout("rotateImage()", 4000); '>
<a id="next" onclick="javascript: window.open('index-safhalf.html','The Commute - Playing With Filters (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" title="" href="sound/Playing_with_Filters-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" alt="DSCF1486" src="DSCF1486.jpg" /-->
<img border=0 id="place" alt="" src="DSCF1486.jpg" style=visibility:hidden; />
</a>

... up towards the top right of the index.htm webpage when using an iOS platform. It is optional whether the user ...

  • clicks Play button of that new top right audio element for continuous "looped audio track sets" mode of use with no new second window required (and so, no window focus changes and no second click required either)
  • clicks blue link for continuous "looped audio track sets" mode of use with a new second window's audio element that the user clicks the Play button of
  • clicks none of those modes of use above that are offered for a short time to then click appropriately to start up music, optionally, as required, at a later date as possible

So feel free to try a One Image Website in the list below ...

... where this new iOS music arrangement logic has been incorporated.

Stop Press

The Webpage Meta Refresh Primer Tutorial has reminded us of another left hand "No new window created" navigation methodology using the HTML meta "refresh" tag.


Previous relevant One Image Website iOS Radio Music Tutorial is shown below.

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

Did you read the recent Responsive Web Design Landing Page Image Map Tutorial? Its core takeaway was the linking of One Image Website functionalities. In these One Image Websites we've picked out a guinea pig ...


"The Commute"

... to have a day's worth of experimenting trialling a solution to the "chestnut of a" problem getting iOS music to play continuously without supervision, like a radio program, albeit on a cycle of repeated content (set (such as the oneoffive.mp3 twooffive.mp3 threeoffive.mp3 fouroffive.mp3 fiveoffive.mp3 set of 5 tracks in example below)). Years ago Apple's iOS started requiring a user click to validate the playing of media, hence the interest in today's topic.

The ingredients for the solution, and testing thereof, are ...

  • macOS command line ffmpeg ... capable of ...
  • concatenating audio files ... with command like ...


     
    ffmpeg -i oneoffive.mp3 -i twooffive.mp3 -i threeoffive.mp3 -i fouroffive.mp3 -i fiveoffive.mp3 -filter_complex "[0:a][1:a]concat=n=5:v=0:a=1" all.mp3

     

    ... into ...
  • compilation audio ... all.mp3 ... uploaded to RJM Programming domain ... is now called on ...
  • within an audio tagged HTML element ... with ...
  • loop attribute set ... using as a device ...
  • an iPhone ... teamed ...
  • optionally, (we're just suggesting this headphone idea if you want to keep the music to yourself) via Bluetooth, with a set up involving a connection to a set of AirPods (and connected to your ears) ... are chosen as ...
  • the default speakers for sound ... then use ...
  • web browser app such as Safari ...
  • into the address bar type


    https://www.rjmprogramming.com.au/thecommute

    ... to arrive at the calling window ...

  • click the blue link up the top that appears for a short time ... then ...
  • in the resultant new music window click the Audio play button presented (the point of interest being that this could be the last click required for continuous music playing, in that audio loop) ... music should play continuously and ...
  • if more interesting visuals are also required focus back to calling window

And given that the iPhone and AirPods are charged, and you don't charge out of Bluetooth range with the iPhone, you could get that "radio feeling" out of an iOS user experience!

Code changes, all just clientside HTML and Javascript, went ...

calling window's index.htm changes around the document.body onload event area of interest 🎶 ...


function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i)) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}


</script>
</head>
<body id="body" onload=' xonl(); if (document.URL.indexOf("exif=") != -1) { dexifit(); } showScroll(); window.setTimeout("FadeInImage()", 4000); '>
<div id="thediv" style="display:block;" >
<span><a id="thedivlink" style="display:inline-block;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." onclick="javascript: window.open('index-ssmhalf.html?justmusic=','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="#" data-href="sound/Prelude_Melody-Mike_Vekris.mp3" >The Commute - RJM Programming ... you might see this while loading ... &#127926; click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery &#127926; ... else please wait for full functionality ...</a> versus <a onclick=huhit(); onmousedown=huhittwo(); style=display:inline-block;cursor:pointer;text-decoration:underline;>Exif Run</a></span>
</div>
<a id="alink" style="font-size:28px;background-color:yellow;" onclick="javascript: window.open('index-ssmhalf.html','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)'); disableHref();" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="sound/Prelude_Melody-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming" src="siteimage.jpg" /-->
<img border=0 id="place" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." src="siteimage.jpg" />
</a>
music window's index-ssmhalf.html changes around the document.body onload event area of interest ...


function nextPage()
{
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
image_index=image_index;
} else {

window.location = "index-saf.html";
}
}

function setvv() {
document.getElementById('place').style.visibility='visible';
}


function showScroll() {
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
document.getElementById('next').innerHTML+='<audio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
//alert(document.getElementById('next').innerHTML);
setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}

if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}

</script>
</head>
<body id="body" onload='showScroll(); window.setTimeout("rotateImage()", 4000); '>
<a id="next" onclick="javascript: window.open('index-safhalf.html','The Commute - Playing With Filters (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" title="" href="sound/Playing_with_Filters-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" alt="DSCF1486" src="DSCF1486.jpg" /-->
<img border=0 id="place" alt="" src="DSCF1486.jpg" style=visibility:hidden; />
</a>

... and off up to the RJM Programming domain as "The Commute", with music courtesy of the generous Royalty Free Music For Video, thanks.

Stop Press

For tomorrow, we offer an optional "one less click", "one less window" methodology improvement on the work above, as we transition the other "One Image Websites" over to the new iOS music paradigm.


Previous relevant Responsive Web Design Landing Page Image Map Tutorial is shown below.

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said ...

So, why keep the old way? Well, we packed the "old way" with content rich functionality, and do not want to ditch that yet, but maybe over time?!

We're just over time, aren't you?! And so, we arrive at a long planned for tilt at Image Map functionality that we often turn to Mobilefish.Com and its excellent Image Map Creation to help us out ... but not today?! Why not? We have a funny set of needs, they being ...

  • our Image Map's image will have a variable set of width x height dimensions ...
  • our Image Map's image will be transparent
  • our Image Map needs to have a hole left aside inside it where the functionality that originally existed (and pointed to WordPress Blog content like you are reading), is still working

... the last condition of which we realized, down the track, required us to create four Image Maps. But ... but ... Nala hears you say?!

Yes, we can reference the one image, in its data URL guise, as a smaller, or not, version of itself, by specifying CSS properties ...

  • position:absolute; (our usual for overlay scenarios)
  • z-index:56; (for both transparent image and its associated Image Map ... more on this later)
  • left (to appropriately position in X to be in the relevant section of dark green Image Map overlaying in the Landing Page)
  • top (to appropriately position in Y to be in the relevant section of dark green Image Map overlaying in the Landing Page)
  • width (which will be up to the transparent image width)
  • height (which will be up to the transparent image height)

... and no concern about opacity given the transparent image and z-index considerations, here.

So, how can we involve a transparent image here? Well, that is where the new Responsive Web Design Landing Page being PHP, though up to today it had contained no PHP, is in our favour. We can use PHP's GD to create one, grab its associated data URL and tidy up, and constructing the four image and associated Image Map HTML elements populated, in its "child iframe", and sending back up into the "parent webpage's" new ...

<?php echo "

<div id=divimif></div>
<iframe style='display:none;' id=myimif src=></iframe>

"; ?>

... placed at the bottom of the Landing Page body element, and used in the changed document.body onload event Javascript function ...

<?php echo "

function onl() {
if (eval('' + screen.width) <= 420) {
//alert(screen.width);
document.getElementById('topspan').innerHTML=document.getElementById('topspan').innerHTML.replace('RJM Programming', 'RJM</h1><h1>Programming').replace(/\<\/hJUNK1/g, '</h2');
} //else if (eval('' + screen.width) <= 480) {
//alert('0' + screen.width);
//}
var myiz=document.getElementById('ifzero').getBoundingClientRect();
var myhr=document.getElementById('myheader').getBoundingClientRect();
var myh=eval('' + myhr.height);
var myt=eval('' + myhr.top);
var widthleft=eval(eval('' + myiz.left) - eval('' + myhr.left));
var widthmiddle=eval('' + myiz.width);
var widthright=eval(eval('' + myhr.width) - eval('' + myiz.width) - eval('' + myiz.left));
if (document.getElementById('navTop')) {
var myalthr=document.getElementById('navTop').getBoundingClientRect();
myh-=eval('' + myalthr.height);
myt=eval('' + myalthr.height);
}
var heighttop=eval(eval('' + myiz.top) - eval('' + myt));
var heightmiddle=eval('' + myiz.height);
var heightbottom=eval(eval('' + myh) - eval('' + myiz.height)); // - eval('' + myiz.top));
if (window.parent != window) {
myh=myh;
} else if (('' + window.opener).replace(/^undefined/g,'').replace(/^null/g,'')) {
myh=myh;
} else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPaJUNKd|iPod|Opera Mini|IEMobile/i)) {
myh=myh;
} else {
document.getElementById('myimif').src=document.URL.split('?')[0].split('#')[0] + '?left=' + myhr.left + '&top=' + myt + '&width=' + myhr.width + '&height=' + myh + '&ifleft=' + myiz.left + '&iftop=' + myiz.top + '&ifwidth=' + myiz.width + '&ifheight=' + myiz.height + '&widthleft=' + widthleft + '&widthmiddle=' + widthmiddle + '&widthright=' + widthright + '&heighttop=' + heighttop + '&heightmiddle=' + heightmiddle + '&heightbottom=' + heightbottom;
setTimeout(imbit, 5000);
}

}

"; ?>

... to call on that new PHP ...

<?php

if (isset($_GET['left']) && isset($_GET['top']) && isset($_GET['width']) && isset($_GET['height'])) {
$uw="";
$postuw="";
$uw1="";
$postuw1="";
$uw2="";
$postuw2="";
$uw3="";
$postuw3="";
if (isset($_GET['widthleft']) && isset($_GET['widthmiddle']) && isset($_GET['widthright']) && isset($_GET['heighttop']) && isset($_GET['heightmiddle']) && isset($_GET['heightbottom'])) {
$uw=" usemap=#workmap";
$uw1=" usemap=#workmap1";
$uw2=" usemap=#workmap2";
$uw3=" usemap=#workmap3";

$postuw="<map name=workmap style=z-index:56;>";
$postuw1="<map name=workmap1 style=z-index:56;>";
$postuw2="<map name=workmap2 style=z-index:56;>";
$postuw3="<map name=workmap3 style=z-index:56;>";

$postuw.="<area shape=rect title=Ephemeral onmouseover=omoiset(1); onmouseout=omoiset(-2); coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=LeftTop onclick=ouralert(1); target=_blank href=//www.rjmprogramming.com.au/ephemeral />";
$postuw.="<area shape=rect title=StreetArt onmouseover=omoiset(2); onmouseout=omoiset(-2); coords=" . explode('.',$_GET['widthleft'])[0] . ",0," . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=CenterTop onclick=ouralert(2); target=_blank href=//www.rjmprogramming.com.au/streetart />";
$postuw.="<area shape=rect title=TheCommute onmouseover=omoiset(3); onmouseout=omoiset(-2); coords=" . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . ",0," . explode('.',$_GET['width'])[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=RightTop onclick=ouralert(3); target=_blank href=//www.rjmprogramming.com.au/thecommute />";

$postuw1.="<area id=area4 title=? onmouseover=omoiset(4); onmouseout=omoiset(-1); shape=rect coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',(0 + $_GET['heightmiddle']))[0] . " alt=LeftMiddle onclick=ouralert(4); target=_blank nohref />";
$postuw2.="<area id=area6 title=? onmouseover=omoiset(6); onmouseout=omoiset(-1); shape=rect coords=0,0," . explode('.',$_GET['widthright'])[0] . "," . explode('.',(0 + $_GET['heightmiddle']))[0] . " alt=RightMiddle onclick=ouralert(6); target=_blank nohref />";

$postuw3.="<area shape=rect title=InnerBurbs onmouseover=omoiset(7); onmouseout=omoiset(-2); coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=LeftBottom onclick=ouralert(7); target=_blank href=//www.rjmprogramming.com.au/pyrmontultimo />";
$postuw3.="<area shape=rect title=Bygone onmouseover=omoiset(8); onmouseout=omoiset(-2); coords=" . explode('.',$_GET['widthleft'])[0] . ",0," . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=CenterBottom onclick=ouralert(8); target=_blank href=//www.rjmprogramming.com.au/bygone />";
$postuw3.="<area shape=rect title=West onmouseover=omoiset(9); onmouseout=omoiset(-2); coords=" . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . ",0," . explode('.',$_GET['width'])[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=RightBottom onclick=ouralert(9); target=_blank href=//www.rjmprogramming.com.au/thewest />";

$postuw.="</map>";
$postuw1.="</map>";
$postuw2.="</map>";
$postuw3.="</map>";
}


// Create a transparent image thanks to https://www.php.net/manual/en/function.imagecolortransparent.php
$im = imagecreatetruecolor($_GET['width'], $_GET['height']);
$red = imagecolorallocate($im, 255, 0, 0);
$black = imagecolorallocate($im, 0, 0, 0);

// Make the background transparent
imagecolortransparent($im, $black);

// Save the image
$udirnameprebimg='/tmp/imagecolortransparent.png';
imagepng($im, $udirnameprebimg);

$duis='data:image/' . str_replace('jpg','jpeg',strtolower(explode('.',$udirnameprebimg)[-1 + sizeof(explode('.',$udirnameprebimg))])) . ';base64,' . base64_encode(file_get_contents($udirnameprebimg));
imagedestroy($im);
unlink($udirnameprebimg);



echo "<html>
<body onload=\"parent.document.getElementById('divimif').innerHTML='<img id=myimg style=height:" . $_GET['heighttop'] . "px;z-index:56;position:absolute;top:" . $_GET['top'] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['width'] . "px; src=" . $duis . "" . $uw . "></img>" . $postuw . "<img id=myimg1 style=height:" . $_GET['heightmiddle'] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop']))[0] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['widthleft'] . "px; src=" . $duis . "" . $uw1 . "<>/img>" . $postuw1 . "<img id=myimg2 style=height:" . $_GET['heightmiddle'] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop']))[0] . "px;left:" . explode('.',($_GET['width'] - $_GET['widthright']))[0] . "px;width:" . $_GET['widthright'] . "px; src=" . $duis . "" . $uw2 . "></img>" . $postuw2 . "<img id=myimg3 style=height:" . explode('.',($_GET['height'] - $_GET['heighttop'] - $_GET['heightmiddle']))[0] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop'] + $_GET['heightmiddle']))[0] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['width'] . "px; src=" . $duis . "" . $uw3 . "></img>" . $postuw3 . "'; \"></body>
</html>";

exit;
}

?>

... and once setup, helped out by new Javascript, as per ...

<?php echo "

var urls=['', '', '', ' ', '', ' ', '', '', ''];
var omoi=-1;
var isrelp=false;

function postomoiset() {
if (isrelp) {
isrelp=false;
if (omoi == 4 || omoi == 6) {
var wasomoi=omoi;
omoi=-1;
ouralert(wasomoi);
}
}
}

function omoiset(jnnum) {
if (eval('' + jnnum) == -1) {
omoi=jnnum;
//document.title='omoi=' + omoi;
isrelp=false;
//setTimeout(postomoiset, 8000);
} else if (eval('' + jnnum) == -2) {
if (omoi != 4 && omoi != 6) {
omoi=jnnum;
//document.title='omoi=' + omoi;
isrelp=false;
//setTimeout(postomoiset, 8000);
}
} else {
omoi=jnnum;
//document.title='omoi=' + omoi;
if (omoi != 4 && omoi != 6) {
isrelp=false;
} else {
isrelp=true;
//document.title='omoi=' + omoi + '|';
setTimeout(postomoiset, 8000);
}
}
}

function ouralert(innum) {
var ans='';
switch ('' + innum) {
case '1':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '2':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '3':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '4':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.) Eg. https://www.rjmprogramming.com.au/slideshow.html', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '5':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '6':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.) Eg. https://www.rjmprogramming.com.au/plus/', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '7':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '8':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', '');
}
break;
case '9':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', '');
}
break;
default:
break;
}
if (!ans) { ans=''; }
if (ans != '') {
window.open(ans.trim(), '_blank');
if (ans != ans.trim()) {
window.localStorage.setItem('area' + innum + 'url', encodeURIComponent(ans.trim()));
}
}
}


function imbit() {
//if (document.getElementById('myimg')) {
// document.getElementById('myimg').style.border='5px dashed purple';
//}
if (('' + window.localStorage.getItem('area4url')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
urls[3]=decodeURIComponent('' + window.localStorage.getItem('area4url'));
document.getElementById('area4').title=decodeURIComponent('' + window.localStorage.getItem('area4url')) + '# ... long hover of at least 8 seconds for chance to change';
document.getElementById('area4').href=decodeURIComponent('' + window.localStorage.getItem('area4url'));
document.getElementById('area4').onclick=function(){ omoiset=-1; urls[3]=urls[3]; }
//document.getElementById('area4').ondblclick=function(){ ouralert(4); }
}
if (('' + window.localStorage.getItem('area6url')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
urls[5]=decodeURIComponent('' + window.localStorage.getItem('area6url'));
document.getElementById('area6').title=decodeURIComponent('' + window.localStorage.getItem('area6url')) + '# ... long hover of at least 8 seconds for chance to change';
document.getElementById('area6').href=decodeURIComponent('' + window.localStorage.getItem('area6url'));
document.getElementById('area6').onclick=function(){ omoiset=-1; urls[5]=urls[5]; }
//document.getElementById('area6').ondblclick=function(){ ouralert(6); }
}
}

"; ?>

... in a changed index.php Landing Page whose guises as ...

  • Landing Page in mobile phone devices
  • Landing Page in an iframe
  • Landing Page in a popup window

... we all excluded from new functionality Image Map potential "dark green area clicking" access to photography themed "One Image Websites" ...

... accessible from Image Map area elements up above and down below the WordPress Blog posting iframe whose CSS property z-index is set to ...

<?php echo "

<iframe title='Recent posts' onload='check_if(this);' src='PHP/zero.html?totalwidth=y' class='zero' id='ifzero' style='z-index:57;'></iframe>

"; ?>

... 57.


Previous relevant Responsive Web Design Landing Page Incarnation Tutorial is shown below.

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

Along the same "Responsive Design" themes of Responsive Web Design Primer Tutorial, we stumbled upon the excellent W3Schools Responsive Design Based Start Page Idea which inspired us to retry RJM Programming Landing Page thoughts ...

  • separating out totally "uninvolved" Landing Page calls hooked up with a new index.php (actually just HTML) Landing Page incarnation that has better Responsive Design credentials ... from ...
  • any other call of any complexity or having a query string etcetera, reverting to the "old way"

... new paradigm? So, why keep the old way? Well, we packed the "old way" with content rich functionality, and do not want to ditch that yet, but maybe over time?!

You'll see, though, using the new index.php Responsive Design Landing Page incarnation ...

... how the clutter melts away like a hot knife through margarinebutter!


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of "responsive web design" ...

Responsive web design (RWD) is an approach to web design that makes web pages render well on a variety of devices and window or screen sizes from minimum to maximum display size. Recent work also considers the viewer proximity as part of the viewing context as an extension for RWD.[1] Content, design and performance are necessary across all devices to ensure usability and satisfaction.[2][3][4][5]

... coming at it from the idea "Can a responsive shell webpage host a non-responsive iframe?"

In turn this got us to the excellent ideas of this webpage which we'll try out for a while ...

  • honing in on our "Landing Page and friends" set of unresponsively designed webpages ...
  • honing in on iPhone sized devices (ie. not iPads nor laptops) ...
  • host web browser address bar calls of "Landing Page and friends" set of unresponsively designed webpages within a caller.html responsively web designed shell supervisory webpage and start using some of that ...
    Unresponsive Landing Page
    Responsive Shell around Unresponsive Landing Page

    ... as food for (your) thought ...


    function bodonl() {
    var wasih=document.body.innerHTML;
    var huhd=document.getElementById('Container').getBoundingClientRect();
    var pb=0;
    if (eval('' + huhd.height) > eval('' + huhd.width)) {
    isportrait=true;
    pb=eval(eval('' + huhd.width) / eval('' + huhd.height) * 100.0);
    nowih='<div id="Container" style="padding-right:' + pb + '%; position:relative; display:block; height: 100vh;"><iframe' + wasih.split('<iframe')[1].split('</div>')[0].replace('" frameborder', fname + '" style="position:absolute; top:0; left: 0;" frameborder') + '</div>';
    //if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    //document.getElementById('myvis').setAttribute('initial-scale','0.5');
    //}
    } else {
    isportrait=false;
    pb=eval(eval('' + huhd.height) / eval('' + huhd.width) * 100.0);
    nowih='<div id="Container" style="padding-bottom:' + pb + '%; position:relative; display:block; width: 100%;"><iframe' + wasih.split('<iframe')[1].split('</div>')[0].replace('" frameborder', fname + '" style="position:absolute; top:0; left: 0;" frameborder') + '</div>';
    }
    document.body.innerHTML=nowih;
    }

    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.


    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 Not Categorised | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Canvas Interfacer Mobile Image Map Tutorial

Canvas Interfacer Mobile Image Map Tutorial

Canvas Interfacer Mobile Image Map Tutorial

On the same themes as yesterday’s Canvas Interfacer Three Finger Gesture Usage Tutorial‘s …

  • mobile platform chance to have three finger gestures help with scrolling functionality … today we have it so that …
  • mobile platforms are better suited creating Image Maps via canvas and image based inhouse web application (looking out for 🗺️🖼️ emoji button means to create Image Map when ready, as a double click on the canvas can do as well)

… our changes being helped out by the discovery that our previous …


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
// is identified around here as a mobile platform
}

… was a bit unreliable identifying mobile iOS platform Safari web browser usage, but this useful link got us to refine that thinking to …


if ( navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) > 0 ) {
// is better identified around here as a mobile platform
}

… with more success. Yayyyyy!

Along the way the HTML textarea elements used to identify Image Map subelement area rectangular limits have their disabled attribute set, which has the benefit …

  • that there is no need to allow any focus to these textarea elements when nothing any user can enter into them would make any difference anyway … and yet …
  • at least on non-mobile platforms the useful resizing talents of textarea elements are not stopped because of the disabled attribute being set

We found that the URL usage …


https://www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm#imagemap=url

… had become a little obsolete (at least, regarding the emoji button workflow), in the sense that, like with the canvas ondblclick event (ie. double click) functionality, why not, when clicking that 🗺️🖼️ Image Map creator emoji button grab the contents of the canvas already displaying as the default content presented to the “potential” (ie. it depends, sometimes, whether you double click that canvas element the next time) Image Map creation session?

Relevant to Random Background Image Map Area Polygons Tutorial and the decision then regarding non-mobile platforms to use an initial click followed by right clicks to enable Image Map area element shape=poly components, today, thinking with respect to mobile platforms, we’ve decided Image Map area element shape=poly components can be created via an initial click followed by double click sequences and going back to the polygon start, with either platform type, ending the polygon with two separated clicks. Also relevant to that same tutorial and it’s pointer-events:none; discovery, today’s mobile work regarding the textarea elements plotted to show the rectangular limits of user defined areas already created we found “real world relevance” to applying this to mobile such textarea elements. That is because on some mobile platforms these textarea elements will never be able to be resized out of the way, but if we apply pointer-events:none; to these, it does not matter, as the user can, as required, click/touch through these overlayed elements that have a huge z-index and semi-transparency applied to them.

Again, perhaps on a mobile platform web browser, feel free to try …

Did You Know?

There are known Safari mobile web browser textarea resizing limitations as we discovered trying a Google search of allow textarea resizing on mobile safari web browser, thanks, that we gleaned from the use of …

Solution 2: Standard JavaScript Auto-Grow
If you need to support older versions of iOS Safari that lack the newest CSS specs, you can dynamically update the box height using a tiny JavaScript event listener. This removes the scrollbar and expands the container vertically as they type:

HTML: html
<textarea id=”mobile-textarea” rows=”3″ oninput=”autoGrow(this)”></textarea>

JavaScript: javascript
function autoGrow(element) {
element.style.height = “auto”;
element.style.height = (element.scrollHeight) + “px”;
}

… incorporated ideas to help here.


Previous relevant Canvas Interfacer Three Finger Gesture Usage Tutorial is shown below.

Canvas Interfacer Three Finger Gesture Usage Tutorial

Canvas Interfacer Three Finger Gesture Usage Tutorial

There’s more research needed around here regarding mobile platform usage to the HTML5 canvas based ideas swirling around yesterday’s Random Background Image Map Area Polygons Tutorial‘s work, and one issue we came across was …

  • on mobile platforms you can get to gesture results whereby the canvas is all you see on the screen (eg. of an iPhone) …
  • but what if you are in “scribble mode” at that point?
  • before today, we were having trouble using …
    1. two finger “pinch” gesture to zoom out … or …
    2. one finger “swipe” to reveal more to the right (where, if we could have reached it, that right hand menu of annotation options has none of these “scribble mode” oddities) … because …
    3. before today, that last idea just drew a “scribble” “free drawing” line to the canvas

    … to reach the menu or any other non-canvas element not in “scribble mode” (ie. scrolling could not be achieved, at least in a way we could immediately access)

And so, we asked Google, thanks, “detect three finger gesture and if so scroll in the direction indicated” and got this useful advice …

Web Implementation (JavaScript)

If you are building this for a website or web app, you can use the touchstart and touchmove events to capture finger coordinates, check if exactly three fingers are on the screen, and then calculate the direction.

… to (start with globalvar isthree=false; and) end up with


if (eval('' + event.touches.length) >= 3 && event.type == "touchstart") {
isthree=true;
return;
} else if (isthree && event.type == "touchend") {
//if (isthree) {
isthree=false;
window.top.scrollBy(200,0);
return;
//}
}

… near the top of our function toptouchHandler(event) Javascript code in our changed signature_signature.js external Javascript canvas interfacer helper.


Previous relevant Random Background Image Map Area Polygons Tutorial is shown below.

Random Background Image Map Area Polygons Tutorial

Random Background Image Map Area Polygons Tutorial

Further to the recent Random Background Alternate Image Source Tutorial

  • Image Map only allowing for area subelements with shape=rect … today we also allow for …
  • Image Map now allowing for area subelements with shape=poly …

… via …

Right clicks after an initial click are the means by which you can define area shape=poly ( as distinct from the default shape=rect ) elements where to finish a polygon two click back close to the start point.

… as a modus operandi for the user to cater for more complex shape definitions in their Image Maps.

That doesn’t mean the rectangle around such a polygon is not also significant. Do you know why?

Yes, a hosting HTML div of a specific width and height and positioned absolutely at a precise left and top screen position allows SVG innerHTML like …


<svg xmlns="http://w3.org" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"><polyline points="0,67,56,7,100,0,150,17,0,67"></polyline></svg>
... be showing a polygonal user clicked shape, scaled appropriately, yet responsively, and allowing for those % unit definitions above making all this methodology useful here. Notice the zero co-ordinates? That is no accident. We make the co-ordinates relative to the minimum x and minimum y "datum" to the co-ordinating.

Feel free to try ...

Did You Know?

We broached the idea "pass event logic down through even though an element has a bigger z-index" to Google, thanks, and got back ...

To pass events down through a higher z-index element, add pointer-events: none; to the top element. This tells the browser to ignore the overlay for mouse events, allowing clicks and hovers to "fall through" to the element stacked beneath it.

... to learn a whole new technique we've been looking for for quite some time now ... now, where did we put that "Overlay Disappointments File"?! ... bye bye!


Previous relevant Random Background Alternate Image Source Tutorial is shown below.

Random Background Alternate Image Source Tutorial

Random Background Alternate Image Source Tutorial

Onto the recent Random Background Image Map Integration Tutorial's web application's use of ...

  • Lorem Picsum image repository "source" of image data ... today we allow the user to, instead, get images from ...
  • RJM Programming WordPress Tutorial Images (ie. this WordPress.org blog)

... and we've shored up the copy and pasting of screen logic, so that ...

  • the screen is more filled with image data, and the relevant graphical pasting place "border enhanced", in the process ...
  • the images have better resolution, in the process

... as the two areas of improvement within ...

... regarding it's newish Random Image Map integrations.


Previous relevant Random Background Image Map Integration Tutorial is shown below.

Random Background Image Map Integration Tutorial

Random Background Image Map Integration Tutorial

Like with ...

... and allowing users using our inhouse Random Background interfacer the chance to create some Image Maps using incarnations of these images as the visual basis to them.

We've chosen ...

  • the oncontextmenu (ie. right click) as an intervention point to facilitate this ... or ...
  • if using a macOS operating system a ...
    1. control-command-shift-3
    2. control-command-shift-5

    ...

    document.addEventListener('keydown', (event) => { // thanks to https://www.google.com/search?q=javascript+detecting+control-command-shift-3&rlz=1C5OZZY_en&oq=javascript+detecting+control-command-shift-3&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQIRigATIHCAIQIRigATIHCAMQIRigATIHCAQQIRigATIHCAUQIRiPAjIHCAYQIRiPAjIHCAcQIRiPAtIBCTE3NzMyajBqN6gCALACAA&sourceid=chrome&ie=UTF-8
    // Check if Control, Command (metaKey), and Shift are all held down
    // AND the key pressed is the number 3
    if (
    event.ctrlKey &&
    event.metaKey &&
    event.shiftKey &&
    event.code === 'Digit5'
    ) {
    // Prevent the default browser action if necessary
    //event.preventDefault();

    //var kc=eval(-2 + event.keyCode);

    event.preventDefault();
    event.stopImmediatePropagation();

    // Create a fake event with a modified code (e.g., ArrowDown)
    const simulatedEvent = new KeyboardEvent("keydown", {
    key: "3",
    code: "Digit3",
    ctrlKey: true,
    metaKey: true,
    shiftKey: true
    }); // keyCode: kc, bubbles: true, cancelable: true,

    // Fire the fake event into the DOM
    event.target.dispatchEvent(simulatedEvent);

    if (immap && !holdoff) { holdoff=true; setTimeout(function(){ wowo=window.open('/HTMLCSS/user_of_signature_signature.htm?askforpaste=y&imagemap=url#' + myco.toDataURL('image/jpeg',0.4), '_blank', 'top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height)); setTimeout(function(){ holdoff=false; }, 8000); }, 2000); }

    console.log('Control + Command + Shift + 3 combination detected!');
    // Insert your custom logic here
    }
    });

    ... combination is another modus operandi in play

... within ...

... regarding it's new Random Image Map integrations.


Previous relevant Inhouse Image Map WordPress Integration Tutorial is shown below.

Inhouse Image Map WordPress Integration Tutorial

Inhouse Image Map WordPress Integration Tutorial

The recent work of Inhouse Image Map Creator Browsing Tutorial ...

  • established a URL means by which a single URL call from the canvas residing Inhouse Image Map Creator and Canvas Annotation web application via a data URI hashtag conduit ... and today just ...
  • allowing for an absolute URL in that hashtag is the relatively simple change needed so that, using this, our WordPress "right click over an img image element" functionality can be tweaked ...


var huhifs=prompt('Optionally, please, any CSS for images ... append 3 spaces to be able to edit this ' + (gthing == 'image' ? gthing + ' (and answer of #imagemap will use this image as basis for creation of an image map in a new window)' : gthing) + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
if (huhifs == null) {
huhifs='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (event.target.outerHTML.indexOf('<a ') == 0) {
console.log(6);
ggurl=event.target.href;
} else {
console.log(66);
ggurl=document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="')[eval(-1 + document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="').length)].split('"')[0];
}
if (6 == 6) {
console.log(ggurl);
window.open(ggurl,'_blank'); ggurl='';
// huhifs=window.prompt('Optionally, please, any CSS for images ... append three spaces to be able to edit this ' + gthing + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
} else {
setTimeout(function(){ window.open(ggurl,'_blank'); ggurl=''; }, 5000); //alert(event.currentTarget.outerHTML); //event.currentTarget.click();
}
}
}
if (huhifs.toLowerCase() == '#imagemap') {
event.preventDefault();
event.stopPropagation();
ggurl=event.target.src;
window.open('//www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm?imagemap=url#' + (ggurl.indexOf('//') != -1 ? '//' + ggurl.split('//')[1] : (ggurl.replace(/^\.\//g,'/').indexOf('/') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(1).replace(/^\//g,'ITblog/') : (ggurl.indexOf('../') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(3) : ggurl))),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height));
ggurl='';
} else
if (huhifs.indexOf('data:image/') == 0) {
if (document.getElementById('imgcopycheck') && usuff != '') { //if (document.URL.indexOf('/streetart/') != -1) {
uplitc(huhifs); //alert(document.URL);
}
return '';
}

... as an excerpt from the changed onrightclick.js external Javascript called by WordPress, and calling ...


Previous relevant Inhouse Image Map Creator Browsing Tutorial is shown below.

Inhouse Image Map Creator Browsing Tutorial

Inhouse Image Map Creator Browsing Tutorial

Repeat after me ...

an image is a canvas is an image

?

an image is a canvas is an image

... good, now, again ... an image is a canvas is an image ...

an image is a canvas is an image

... excellent, now, backwards ... egami na si savnac a si egami na ...

egami na si savnac a si egami na

... wow! ... Now, lastly … I want my mamma! Now! ...

I want my mamma! Now!

 

But it's true. Our thinking behind allowing browsed for image files become data URIs that can be the img element "image" part of the "image map", further to yesterday's Inhouse Image Map Creator Mobile Debug Tutorial, we can now create using our inhouse Image Map Creator capable web application uses the "an image via [canvasContext].drawImage() is a canvas via [canvas].toDataURL() is an image" concept that can save us heaps of time with this project. Instead of intervening at each dropdown option mentioning "Browse" to make this design change, we, instead, introduce to the HTML5 canvas element a new ondblclick event ...


<canvas ondblclick="qwowo=window.open(document.URL.split('?')[0].split('#')[0] + '?imagemap=url#' + this.toDataURL('image/jpeg',0.4),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height) + '');" ondragstart="dragstart(event);" draggable="false" title="Ready for you to create your canvas 🎨 content above any signature 💳 panel ... keys U for Undo and R for Redo can work after a discrete click ending any scribble mode of use. Double click can facilitate turning this canvas content into an image map, and this canvas content can be populated by so many of the options in the menu to the right, which includes many local image file browsing choices." id="topcanvas" width=850 height=600 style="background-color:white; position: absolute; top:0; left:0; border-bottom:5px solid yellow; border-right:5px solid blue;"></canvas>

... allowing that "on double click" result in the web application turning into an Image Map Creator where now ...

Image Map ( ie. <img src="[image URL as entered by user or data URI browsed for by the user, or, come to think of it, from a couple of days back, entered in by the user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... is that very pithy redefinition of our web application's view of what an Image Map can be! Though?!

 

Again, feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Mobile Debug Tutorial is shown below.

Inhouse Image Map Creator Mobile Debug Tutorial

Inhouse Image Map Creator Mobile Debug Tutorial

Apologies to any mobile users wanting to access this new inhouse Image Map creator web application last talked about with yesterday's Inhouse Image Map Creator Interactive Drill Down Tutorial before today, that is, but we were leaving the issue until a proper hardware ...

  • Mac Book Air
  • Apple white lead
  • iPhone

... that once the middle one plugs into the top and bottom allows for ...

  • iPhone Safari web browser call of the inhouse Image Map creator ... could tee up with (ie. attain a "connection" with) ...
  • Mac Book Air Safari web browser Develop -> (in our case) Robert's iPhone -> user_of_signature_signature.htm

... online debugging session, could be arranged and a block of time set aside to concentrate on, because "concentrate" is the name of the game here!

Luckily, the issue was straightforward, where many are not. In the overseeing code, we had ...


<script type=text/javascript>
var oklj=0;
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || document.URL.indexOf('?fcol=') != -1) {
oklj=oklj;
} else {
document.write("<iframe id=ifconto name=ifconto src='/PHP/animegif/tutorial_to_animated_gif.php#rand=" + Math.floor(Math.random() * 19878675) + "' style='width:100%;height:900px;display:BLOCK;'></iframe>");
}
</script>

... ba bow ... because in the external Javascript we got pulled up by the debugging of the iPhone execution attempt at a codeline, where the user decides to take on an Image Map creation task ...


top.document.getElementById('ifconto').src='/About_Us.html';

... ba bow. On mobile, that necessary HTML iframe was non-existant! So, with the external Javascript, at this similar juncture, we came up with ...


if (!top.document.getElementById('ifconto')) {
top.document.body.innerHTML+="<iframe id=ifconto name=ifconto src='/About_Us.html' style='width:100%;height:900px;display:none;'></iframe>";
} else {

top.document.getElementById('ifconto').src='/About_Us.html';
}

... to start getting somewhere, here, with these inhouse Image Map creation ideas on mobile platforms.

And what about ...

  1. allow for data URIs pasted into the prompt window
  2. create non-mobile rubber banded overlays to help contextualize further

? Huh?! Feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Interactive Drill Down Tutorial is shown below.

Inhouse Image Map Creator Interactive Drill Down Tutorial

Inhouse Image Map Creator Interactive Drill Down Tutorial

It might be the case, often, with Image Map creations, as with our recent web application featuring in yesterday's Inhouse Image Map Creator Drill Down Tutorial that the user needs to ...

strike while the iron is hot

... regarding having the event logic be nuanced as the image map area subelements are created in terms of ...

  • area subelement inline event logic definitions (pointing at, perhaps, local Javascript functions) ... as well as ...
  • the content of those local Javascript functions

... in such a way that, if you come back to "flesh out" the image map HTML coding the next day, say, there are enough clues you've left that you do not have to go and match the "coords" attribute values to a screen position to get some context. That takes a lot longer we find.

And so, today, we now offer ...

Enter an Image URL (append space to create Image Maps where click/tap pairs can define rectangle corners ... cursor is a crosshair for lower left click/tap, first, then cursor is pointer top right ... append another one space to prompt for tailored event logic each time and two spaces to also review the default Javascript used for double click logic image map testing purposes ... we are going to discourage scrolling here, but you can still zoom out or in)

... Javascript prompt windows "on the fly" to allow for this to be a possibility for the Image Map creator using ...


Previous relevant Inhouse Image Map Creator Drill Down Tutorial is shown below.

Inhouse Image Map Creator Drill Down Tutorial

Inhouse Image Map Creator Drill Down Tutorial

Onto yesterday's Inhouse Image Map Creator Tutorial we've decided today's work should stay within non-mobile realms but flesh out more user available functionality to help with "stage two" thinking. With that in mind ...

  • the image map HTML containing textarea created (with yesterday's efforts using the Canvas and Image Map web application (now featuring a new emoji button 🗺️🖼️ to allow for a non-dropdown usage approach)) has an ondblclick event logic added so that when double clicking, at any stage of the image map creation processing, it ...
  • opens a new popup window where that HTML you have so far is surrounded by a default "rest of webpage" scenario as the HTML that goes into making up that popup window HTML content, and where you can test out it's workings ... as well as ...
  • that popup window image map, itself, is given an ondblclick event logic whereby a double click there can create below that image map within the same popup window a new textarea element containing all that HTML (default "rest of webpage" and all) which can be copied into a clipboard buffer as required ... and ...
  • if that textarea within the popup window is edited and the user double clicks that textarea element, a new popup window reflecting your changes is opened above that ... etcetera etcetera etcetera

All this can be used to either/both validate your image map and follow through further to incorporating the image map into a functional HTML webpage, using the changed signature_signature.js external Javascript to make all this possible. Within that changed external Javascript we allow the user to cancel the proposed area subelement currently embarked upon between where the user has clicked/tapped the bottom left and before they shape to click/tap the top right rectangle definition, via a right click, so as to reset back to the click/tap using the crosshair cursor back at a bottom left area shape=rect subelement definition.


Previous relevant Inhouse Image Map Creator Tutorial is shown below.

Inhouse Image Map Creator Tutorial

Inhouse Image Map Creator Tutorial

The "largely canvas" using web application last talked about with WordPress Blog Image Editing Media Tutorial, today, we're excited to announce, has been given an "on first draft just image URL" using new ...

Image Map ( ie. <img src="[image URL as entered by user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... arrangement inhouse means to construct image maps, so far, just via an image URL.

Why hook into the largely canvas savvy web application? Well, it is that basic positional mouse event logic that is needed to create image maps, and here, it is a dominant theme, and useful, even though the rearrangement of data needed is quite substantial, still, that is where we think this new functionality appears most at home, being a new suboption ("Image 🖼 Canvas Matches Actual URL or Image Map rectangle area creations") off a dropdown option means of deploying.

No tests on mobile, yet, but on non-mobile, we're happy, once the user chooses to create Image Maps, so long as ...

  1. we stop user web page scrolling ... while still allowing ...
  2. webpage zooming out or in

... in conjunction with ...

  • replacing the webpage table's left cell content, which used to contain a canvas element, with the user defined image, via it's URL ...
  • replacing the webpage table's right cell content, which used to contain an canvas annotation menu, with the image map URL HTML built up from user lower left and upper right rectangle defining click/taps

... we have the wherewithal to create image map HTML code the user can copy and use, with "stage two" fleshing out!

Try this at ...

... to allow for this image map inhouse functionality. The talents of HTML textarea elements, with their resizing abilities, helps out here, allowing these overlayed textarea elements ...

  1. containing image map HTML ... and/or ...
  2. overlaying semi-transparentally to see what has been clicked already

... also be able to be resized "out of the way" should that be needed perhaps regarding overlapping scenarios, without having to resort to any other type of event logic to allow for. The other big and relevant talent of textarea elements is their ability to contain HTML code and be editable with that HTML code, perhaps user amended, and to be able to Select All then Copy into a clipboard buffer, via it's right click web browser menu, ready to paste somewhere else, that HTML content ready for any required "stage two" embellishment and usage.


Previous relevant WordPress Blog Image Editing Media Tutorial is shown below.

WordPress Blog Image Editing Media Tutorial

WordPress Blog Image Editing Media Tutorial

We're happy to be revisiting ...

... to add to our recent WordPress Blog Image Editing functionality, extending it's capabilities to be able to optionally create either/both ...

  • Video
  • Animated GIF

... media presentations off this should the user pick more than one image, to be edited, in any one web browser tab (via window.sessionStorage) session. So far, we're creating ...

  • window.open
  • background image
  • background-size: contain

... "Video" and "Animated GIF" presentations, and see this as a shareable commodity, into the future, especially as the image slide data ends up being an HTML canvas [canvas].toDataURL() data URI that represents ...

  1. lots of data
  2. but understood everywhere

... and content wise has included within it, any canvas manipulations and annotating and reworking the user has applied plus, at least for Google Chrome, any image filtering CSS the user has requested, into that canvas. We shape to involve the cowsay actual web server disk based media creating interfacing, but not for now. We'll see, because WordPress Visual Synopsis Media Tutorial methodologies also ended up presentation wise, with "inhouse" "Video" and "Animated GIF" presentations.

How does the user make this happen? Well, at the opportune call of our Canvas Image Editor web application some "Mantissa MadnessMagic" takes place using ...


if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").indexOf('.') != -1) {
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]))) {
if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "") >= '1') {
setTimeout(function(){
if (document.getElementById('storyboard') && document.getElementById('toptd')) {
document.getElementById('toptd').innerHTML=document.getElementById('toptd').innerHTML.replace(document.getElementById('storyboard').outerHTML, '  <button onclick="top.videoshow();">Video &#128249;</button>  <button onclick="top.agshow();">Animated GIF &#128444;</button> ' + document.getElementById('storyboard').outerHTML);
}
}, 8100);
}
setInterval(function(){
var mycisv=document.getElementById('topcanvas');
var mycisvcon=mycisv.getContext('2d');
var mycanc=mycisv.toDataURL('data/jpeg', 10);
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value.length != mycanc.length) {
top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value=mycanc;
top.agup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
top.vdup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
}
}, 10000);
}
}

... to look like ...

    

... appearing in the right cell hosted Annotation Menu tools of the changed user_of_signature_signature.htm inhouse image data fed canvas editor web application.

The fourth draft onrightclick.js external Javascript now includes those onclick logic event functions ...


function agshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var ist=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts; } else { document.title=dtp + dtstwo; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist++; setTimeout(startit, 5000); } setTimeout(startit, 2000); </scr' + 'ipt>';
woagis=window.open('','_blank','top=110,left=110,width=700,height=700');
woagis.document.write('<html><head><title>Animated GIF of selected images ... start of looping presentation ...</title>' + ascr + '</head><body style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

function videoshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var verbs=[" paused"," playing"], ist=0, inc=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation ", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts + verbs[inc]; } else { document.title=dtp + dtstwo + verbs[inc]; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist+=inc; setTimeout(startit, 1000); } setTimeout(startit, 1000); </scr' + 'ipt>';
wovdis=window.open('','_blank','top=100,left=100,width=700,height=700');
wovdis.document.write('<html><head><title>Video of selected images ... start of looping presentation </title>' + ascr + '</head><body title="Initially paused but on loop when started. Click to toggle between pause and play." onclick="inc=eval(1 - inc);" style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

... creating those popup window "Video" and/or "Animated GIF" presentations we've been talking about above.

The WordPress Blog TwentyTen theme's header.php gets a crucial new Javascript function referenced elsewhere ...

<?php echo "

function firstuptop() {
var ifnum=1, arrc=['cow', 'ime'], butsuff='', arrbw=['', ' of Selected Images'], arrolp=['vif','ime'];
var utd='<div id=divime style=display:none;>';
for (var jime=0; jime<2; jime++) {
if (jime > 0) {
utd+="</b><br><iframe name=my" + arrc[jime] + "ifr id=my" + arrc[jime] + "ifr style=display:none; src=/About_Us.html></iframe><form target=my" + arrc[jime] + "ifr action=/cowsay.php method=POST id=my" + arrc[jime] + "pf><div id=div" + arrc[jime] + "pf></div><input type=submit id=vlist" + butsuff + " style=display:none;background-color:lightblue; name=vlist" + butsuff + " value='Video &#128249; " + arrbw[jime] + "'></input> <input type=submit style=display:none;background-color:lightblue; id=aglist" + butsuff + " name=aglist" + butsuff + " value='Animated GIF &#128444; " + arrbw[jime] + "'></input></form><table cellpadding=20><tbody><tr></tr></tbody></table></div><p id='backtoblog'></p>";
}
butsuff='ime';
}
utd+='</div>';
document.body.innerHTML+=utd;
}

"; ?>

... to help create, within the blog posting webpage content, the HTML skeletal necessaries modelled on how WordPress Visual Synopsis Media Tutorial worked it for Visual Synopsis (Slideshows) functionality which included inhouse "Video" and/or "Animated GIF" media presentations.


Previous relevant WordPress Blog Posting Feature Image Editing Tutorial is shown below.

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

Yesterday's ...

  • One Image Website Image Snapshot Editing Tutorial used web browser new tab webpages to allow for image editing and annotating ... but with today's ...
  • WordPress Blog Posting Feature Image Editing Tutorial we're using a hosted HTML iframe window within the blog posting webpage of interest

And that should be a lot easier to handle, yes?! Well, yes, maybe, but not that much easier. A little bit "easier" because the logic is largely funnelled into code that is common to both modus operandi.

In amongst the commonalities, thankfully, the means to get to the "image editing and annotating" and/or "image styling" functionality remains ...

Non-mobile right click or spread/pinch mobile gesture on most blog posting images can lead to image editing and annotating functionality, where for animated GIFs first slide is chosen.

We learnt a bit making the mobile ontouchend spread/pinch detection more bulletproof ...


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
setTimeout(function(){
document.ontouchend=function(e){
if (document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') != -1) {
lastsp=eval(e.touches.length);
}
if (eval('' + e.touches.length) >= 1) {
if (document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') == -1) {
onrightclickask();
} else if (e.touches[0].target.outerHTML.split('>')[0].indexOf('<img ') == 0 && e.touches[0].target.outerHTML.split('>')[0].indexOf(' tabindex=') != -1) {
onrightclickask(); //document.title=':' + e.touches[0].target.outerHTML.split('>')[0].substring(1);
}

}
};
}, 4000);
}

... but ahead of this, for the TwentyTen theme changes to codex webpage structure we predominantly do with a good ol' tailored header.php the most effective modified (which is new) codeline now goes ...

<?php

$post->post_content=str_replace('<i' . 'mg' . ' i' . 'd=', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); i' . 'd=', str_replace('<i' . 'mg' . ' s' . 'rc=', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); s' . 'rc=', str_replace('<i' . 'mg' . ' st' . 'yle="border', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); st' . 'yle="border', str_replace('<i' . 'mg' . ' st' . 'yle="float', '<i' . 'mg' . ' tabindex=0 oncon' . 'textmenu=imgedit(event); ontou' . 'chend=imgedit(event); st' . 'yle="float', str_replace('<i' . 'mg' . ' deco' . 'ding=', '<i' . 'mg' . ' tabindex=0 onconte' . 'xtmenu=imgedit(event); ontou' . 'chend=imgedit(event); deco' . 'ding=', $post->post_content)))));

?>

... calling new Javascript function ...

<?php echo "

function imgedit(evt) {
if (('' + evt.target.outerHTML.split('>')[0]).indexOf(' class="iiconlist') == -1) {
preonrightclickask(evt);
}
}

"; ?>

Other than header.php WordPress PHP code we changed ...


Previous relevant One Image Website Image Snapshot Editing Tutorial is shown below.

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

Augmenting yesterday's One Image Website SessionStorage Image Filtering Tutorial adding cropped image editing functionality, we see it as ...

Running against us regarding One Image Website design .. Running for us regarding One Image Website design ...
the programmatical scrolling means embedded iframe hosting will not work way window.prompt freezes all Javascript at a snapshot of time ...
hashtag navigation can be the conduit to pass data onto inhouse Canvas Editor of Image Data
[canvasContext].drawImage has a variety of useful calls (in that OOP method feel) allowing for dynamic cropping

That "one against" stopped how we envisaged the work at the start of the day. We thought we'd use window.sessionStorage (or maybe window.localStorage) as the only data conduit needed, and we'll be continuing that idea with another approach into the future, but back to today, hashtagging provided that conduit means, even if we were using data URIs (though all we need today are image absolute URLs).

And then there was "the unknown factor" ...

Can [canvasContext].drawImage draw that image with CSS filter styling applied?

Well, we found using Javascript DOM ahead of the new Image() call ...


xcelem=document.getElementById('topcanvas');
xccontext = xcelem.getContext("2d");
xcimg=new Image;
xcimg.onload = function(){
var mysx=('' + window.sessionStorage.getItem('user_of_signature_signature_sx')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sx')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The x coordinate where to start clipping
var mysy=('' + window.sessionStorage.getItem('user_of_signature_signature_sy')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sy')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The y coordinate where to start clipping
var myswidth=('' + window.sessionStorage.getItem('user_of_signature_signature_swidth')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_swidth')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The width of the clipped image
var mysheight=('' + window.sessionStorage.getItem('user_of_signature_signature_sheight')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_sheight')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The height of the clipped image
var myx=('' + window.sessionStorage.getItem('user_of_signature_signature_x')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_x')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // The x coordinate where to place the image on the canvas
var myy=('' + window.sessionStorage.getItem('user_of_signature_signature_y')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_y')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // The y coordinate where to place the image on the canvas
var mywidth=('' + window.sessionStorage.getItem('user_of_signature_signature_width')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_width')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The width of the image to use (stretch or reduce the image)
var myheight=('' + window.sessionStorage.getItem('user_of_signature_signature_height')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_height')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The height of the image to use (stretch or reduce the image)
if (mywidth != '' && myheight != '') {
xcelem.width=eval('' + mywidth);
xcelem.height=eval('' + myheight);
if (('' + xcimg.style.filter).replace(/^undefined/g,'').replace(/^null/g,'').trim() != '') {
xccontext.filter=xcimg.style.filter;
}
if (myx != '' && myy != '' && myswidth == '' && mysheight == '') {
xccontext.drawImage(xcimg,eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight));
setTimeout(function(){ xccontext.drawImage(xcimg,eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight)); }, 3000);
window.sessionStorage.removeItem('user_of_signature_signature_x');
window.sessionStorage.removeItem('user_of_signature_signature_y');
window.sessionStorage.removeItem('user_of_signature_signature_width');
window.sessionStorage.removeItem('user_of_signature_signature_height');
} else {
xccontext.drawImage(xcimg,eval('' + mysx),eval('' + mysy),eval('' + myswidth),eval('' + mysheight),eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight));
setTimeout(function(){ xccontext.drawImage(xcimg,eval('' + mysx),eval('' + mysy),eval('' + myswidth),eval('' + mysheight),eval('' + myx),eval('' + myy),eval('' + mywidth),eval('' + myheight)); }, 3000);
window.sessionStorage.removeItem('user_of_signature_signature_sx');
window.sessionStorage.removeItem('user_of_signature_signature_sy');
window.sessionStorage.removeItem('user_of_signature_signature_swidth');
window.sessionStorage.removeItem('user_of_signature_signature_sheight');
window.sessionStorage.removeItem('user_of_signature_signature_x');
window.sessionStorage.removeItem('user_of_signature_signature_y');
window.sessionStorage.removeItem('user_of_signature_signature_width');
window.sessionStorage.removeItem('user_of_signature_signature_height');
}
} else {
xcelem.width=xcimg.width;
xcelem.height=xcimg.height;
if (('' + xcimg.style.filter).replace(/^undefined/g,'').replace(/^null/g,'').trim() != '') {
xccontext.filter=xcimg.style.filter;
}
xccontext.drawImage(xcimg,0,0);
setTimeout(function(){ xccontext.drawImage(xcimg,0,0); }, 3000);
}
if (window.parent) {
if (parent.document.getElementById('if_image_canvas')) {
if (('' + parent.document.getElementById('if_image_canvas').style.height).replace('px','').trim() != '') {
if (eval('' + ('' + parent.document.getElementById('if_image_canvas').style.height).replace('px','').trim()) < eval(200 + eval('' + xcelem.height))) {
parent.document.getElementById('if_image_canvas').style.height='' + eval(200 + eval('' + xcelem.height)) + 'px';
}
} else {
parent.document.getElementById('if_image_canvas').style.height='' + eval(200 + eval('' + xcelem.height)) + 'px';
}
parent.document.getElementById('if_image_canvas').style.display='block';
if (parent.document.URL.replace('/wordpress','/ITblog').indexOf('/ITblog') != -1) {
parent.document.getElementById('if_image_canvas').scrollIntoView();
}
}
}
};
var incomings=('' + window.sessionStorage.getItem('user_of_signature_signature_filter')).replace(/^undefined/g,'').replace(/^null/g,'') != '' ? ('' + window.sessionStorage.getItem('user_of_signature_signature_filter')).replace(/^undefined/g,'').replace(/^null/g,'') : ''; // Optional. The image filter CSS styling to apply
if ((incomings.indexOf('%20') != -1 || 7 == 7) && incomings.replace(':',')').indexOf(')') != -1 && incomings.indexOf('style=') != -1) {
incomings='style=' + encodeURIComponent((incomings.split('style=')[1].split('&')[0].split('#')[0]).replace(/\%20/g,' ').replace(/\+/g,' '));
}
var relincomings=incomings.split('style=')[1] ? decodeURIComponent(incomings.split('style=')[1].split('&')[0].split('#')[0]).replace(/\%20/g,' ').replace(/\+/g,' ') : '';
if (relincomings.indexOf('filter:') != -1) {
xcimg.style.filter=relincomings.split('filter:')[1].split(';')[0].split('}')[0];
}
xcimg.src=xcont;

... didn't help, and then we asked the online woooorrrrrllllddd to come across this very useful link, thanks to teach us ...

That [canvasContext].filter is a thaing ... yay!!!

Luckily we didn't need to change One Image Website base HTML to make this happen, but, rather ...

... with the user able to make this happen with those right click (non-mobile) or pinch or swipe gesture (mobile) actions (talked about with yesterday's One Image Website SessionStorage Image Filtering Tutorial) getting the user to a prompt window with the modified "blurb" ...

Optionally, please, any CSS for images ... append three spaces to be able to edit this screenshot in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. filter: grayscale(100%);

... talking about the three appended spaces needed.


Previous relevant One Image Website SessionStorage Image Filtering Tutorial is shown below.

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

Further to the long ago One Image Website Scrolling Position Fix Tutorial last mention of our inhouse One Image Website series, today we have ...

  • clientside image filtering functionality to offer ...
  • almost exclusively using window.sessionStorage ideas (rather than our usual window.localStorage (ie. like Cookies) usage)

Why is that last point any big deal? Well, programmers will tell you, often the tidy up of a new arrangement involves as much, or more, coding to do than the instigation. And a lot of programmers, am sure, will agree that that is a pain in the neck, often. But the use of window.sessionStorage at the expense of window.localStorage allows the programmer to go ...

Aaaaaahhhhh

There is so much less to tidy up. Using window.sessionStorage it is only data on that web browser tab that comes into play, and as soon as that web browser tab no longer exists, nor does the window.sessionStorage data you stored. Yayyyyyyy!

We found we couldn't quite make it exclusively with window.sessionStorage because in the One Image Website paradigm of offering music playing we lost window.sessionStorage data for one of the two web browser tabs that become involved to start the music rolling. So sad. Nevertheless, we transferred some controllable temporary window.localStorage data storage over to window.sessionStorage data storage at the opportune time ...


if (('' + window.localStorage.getItem(prefss + '_filter')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
if (('' + window.sessionStorage.getItem(prefss + '_filter')).replace(/^undefined/g,'').replace(/^null/g,'') == '') {
window.sessionStorage.setItem(prefss + '_filter', window.localStorage.getItem(prefss + '_filter'));
window.localStorage.removeItem(prefss + '_filter');
} else {
window.localStorage.removeItem(prefss + '_filter');
}
}

... (we figured after a day of tinkering ... so sad).

How can the non-mobile user access these new aesthetic settings? Via a right click, as our new unfettered layer of functionality option, encapsulated by onrightclick.js external Javascript "proof of concept" effort, on the way to a Javascript prompt window, is the way we've gone about it. From there, the user can enter CSS non-selector actions such as the use of CSS filter property.

And as such, it's worth a revisit of one or all of our reworked One Image Website web applications ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately

... or you can start them off yourself up at the address bar with (typed in ... or just click) URLs such as ...


https://www.rjmprogramming.com.au/thecommute/?style=filter:invert(100%);

... or ...


https://www.rjmprogramming.com.au/ephemeral/?style=filter:blur(5px);

... or ...


https://www.rjmprogramming.com.au/streetart/?style=filter:hue-rotate(90deg);

... or ...


https://www.rjmprogramming.com.au/pyrmontultimo/?style=filter:sepia(100%);

... or ...


https://www.rjmprogramming.com.au/walkingtrip/?style=filter:saturate(200%);

... or ...


https://www.rjmprogramming.com.au/bygone/?style=filter:contrast(200%);

... or ...


https://www.rjmprogramming.com.au/thewest/?style=filter:brightness(240%);

Did you know?

All this begs the question ...

What about mobile?

Well, at least for iOS we think ...


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
setTimeout(function(){
document.ontouchend=function(e){
if (eval('' + e.touches.length) >= 1) {
onrightclickask();
}
};
}, 4000);
}

... did the job, with a pinch or swipe gesture, of getting us to that Javascript prompt window place, and then the rest is the same!


Previous relevant One Image Website Scrolling Position Fix Tutorial is shown below.

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

Today, we've bitten the bullet, and decided to shore up the webpage scrolling issues that could occur in yesterday's One Image Website VTT Tracks Tutorial, and before, with our set of One Image Websites. They represent, perhaps, a slightly unusual scenario whereby the image data is allowed to be itself, and being bigger than the dimensions of the webpage (straight from its digital source), in all probability. Hence, the randomized document.body scrolling that occurs.

But up until today our randomized range of scrollLeft and scrollTop positioning that could occur ranged over the entire width and height of the underlying image, while we think we should only be scrolling over the range ([imageWidth] - window.innerWidth (screen width)) x ([imageHeight] - window.innerHeight (screen height)). This could lead to white bands to the right and/or bottom of the webpage, in its presentation. And so we've fixed all the Javascript code to replace the old with the new in all the One Image Website codesets ...


var recti=document.getElementById(place).getBoundingClientRect();
//
document.getElementById("body").scrollTop = Math.floor(Math.random() * document.getElementById("body").scrollHeight);
//document.getElementById("body").scrollLeft = Math.floor(Math.random() * document.getElementById("body").scrollWidth);
document.getElementById("body").scrollTop = Math.max(0,Math.floor(Math.random() * eval(eval('' + recti.height) - eval('' + window.innerHeight))));
document.getElementById("body").scrollLeft = Math.max(0,Math.floor(Math.random() * eval(eval('' + recti.width) - eval('' + window.innerWidth))));

Any white bands you still see now will be caused by that being on the original photograph data stock (we're hoping), in ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately


Previous relevant One Image Website VTT Tracks Tutorial is shown below.

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

Using yesterday's Ffmpeg Log Helper Towards VTT File Primer Tutorial VTT files we could choose to use ...

... and, am sorry, but cannot award any points to those who chose the former, because ... well ... it's doubtful we'd mention the second unless we'd done it. And so the answer is ... the former ... down Nala ... the latter!

Today's blog posting is also a little story about the benefits of what we like to call client pre-emptive iframe logic, whereby we open an HTML iframe element, blazing away with its src attribute pointing at a URL that may or may not exist, and if it does, we do something about its content, usually, in the HTML iframe onload event logic. In our case the URL is a VTT file suiting the One Image Website of relevance given the upload and renaming of the VTTs created using yesterday's PHP ffmpeg log to VTT file creator web application.

As a programmer who would like to pursue true track cue Javascript coding, develop the function tracks in the One Image Website index-ssmhalf.html you could View -> Page Source from your favourite web browser, for any of ...

Normal Run ... Run for All Platforms that Presents an Audio Element You Can Play Immmediately

... where, now, where the user plays music, perhaps continuously (like a radio) with an HTML audio element play button press, the currently playing song, thanks to Royalty Free Music For Video, help you keep in touch with the song playing up at the web browser tab and the image title.

This amounted to Javascript changes, as per ...

index.htm ...


var foreground=null; // and get rid of var in var foreground below
var plusstuff='';

function ftchange(tob) {
plusstuff=' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
if (document.getElementById('place').title.indexOf(' Playing ') == -1) {
document.getElementById('place').title+=' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
document.getElementById('place').title=document.getElementById('place').title.split(' Playing ')[0] + ' Playing ' + tob + ' thanks to http://www.freesoundtrackmusic.com ';
}
}


function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i) && document.URL.indexOf('?audio=') == -1) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.body.innerHTML+='<iframe id=ifmusicone title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" src="./index-ssmhalf.html?justmusic=00" style="opacity:0.5;z-index:345;position:absolute;width:140px;height:100px;left:' + eval(-140 + eval('' + window.innerWidth)) + 'px;top:0px;"></iframe>';
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}

function FadeInImage()
{
var foreground=document.getElementById("place");
window.clearTimeout("FadeInImage('" + "place" + "')");
rotateImage("place");
}

function rotateImage(place) {

while (number_of_image == 0)
{
place = place;
}
xplace=place;
//alert('yay2');

anotherNew();

var foreground=document.getElementById(place);
//alert(place);

var thedivlink=document.getElementById("thedivlink");
var thediv=document.getElementById("thediv");

if (foreground.width > 0) {
thedivlink.style.display = "none";
thediv.style.display = "none";
if (document.getElementById('ifmusicone')) {
document.getElementById('ifmusicone').style.display='none';
}

//alert('yay2a');
var alink=document.getElementById("alink");
var xxxx=alink.href;
if (xxxx.indexOf("mp3") != -1)
{
//alink.href="index-ssm.html";
//alink.onclick="javascript:void(0);";

alink.href="filewrite.php?id=session&name="+bigrandnumber+"&ext=txt&rand="+bigrandnumber;
alink.onclick="javascript:void(0);";
foreground.onclick="javascript:hasBeenClicked();";
foreground.title="Click for Bamboozled provided by http://www.freesoundtrackmusic.com" + plusstuff;

}
else
{
if (bigrandnumber >= 0) {
if (hasbeenclicked == 1 || NumOpen > 0 || does_file_exist("session",bigrandnumber,"txt"))
{
bigrandnumber = -1;
alink.href="upload.php";
//alink.onclick="javascript: window.open('index-ssm.html','Pyrmont, Ultimo - Inner Burbs - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');";
alink.onclick = "javascript:void(0);";
//alink.ondblclick = "javascript:void(0);";
foreground.title="Click for Upload functionality.";
alink.target = "_blank";
}
}
}
alink.target = "_blank";
}
else
{
thedivlink.style.display = "block";
thediv.style.display = "block";
}

SetOpacity(foreground,0.3);
// more rotateImage code follows
}
index-ssmhalf.html ...

var mycurt=-1;
var vttcont='';
var vtttitles=[];
var vttstartsecs=[];
var vttendsecs=[];
var vttlastt='';

function getct() {
if (document.getElementById('myaudio')) {
mycurt=document.getElementById('myaudio').currentTime;
console.log('ct=' + mycurt);
//top.document.title='Current time = ' + mycurt;
for (var jjk=0; jjk<vtttitles.length; jjk++) {
if (eval('' + mycurt) >= eval(-0.0001 + eval('' + vttstartsecs[jjk])) && eval('' + mycurt) <= eval(0.0001 + eval('' + vttendsecs[jjk]))) {
if ((vttlastt != vtttitles[jjk] || vttlastt.trim() != vttlastt) || vttlastt.trim() != vtttitles[jjk] || vttlastt == '') {
if (vttlastt.trim() != vtttitles[jjk]) { vttlastt=vtttitles[jjk]; } else { vttlastt+=' '; }
console.log('ct title=' + vtttitles[jjk]);
if (parent.document.title.indexOf(' - ') != -1) {
var huhsare=parent.document.title.split(' - ');
if (eval('' + huhsare.length) >= 3) {
parent.document.title=(parent.document.title.replace(' - ','`').split(' - ')[0] + ' - ' + 'Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ').replace('`', ' - ');
} else {
parent.document.title=parent.document.title.split(' - ')[0] + ' - ' + 'Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
if (parent.document.getElementById('place').title.indexOf(' Playing ') == -1) {
parent.document.getElementById('place').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
parent.document.getElementById('place').title=parent.document.getElementById('place').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
parent.ftchange(vtttitles[jjk]);
if (parent.document.getElementById('alink').title.indexOf(' Playing ') == -1) {
parent.document.getElementById('alink').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
parent.document.getElementById('alink').title=parent.document.getElementById('alink').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
if (document.getElementById('myaudio').title.indexOf(' Playing ') == -1) {
document.getElementById('myaudio').title+=' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
} else {
document.getElementById('myaudio').title=document.getElementById('myaudio').title.split(' Playing ')[0] + ' Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
} else {
parent.document.getElementById('place').title='Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
parent.document.getElementById('myaudio').title='Playing ' + vtttitles[jjk] + ' thanks to http://www.freesoundtrackmusic.com ';
}
}
}
}
}
}

function pushit() {
var timings=vttcont.split(' --> ');
console.log('timings length=' + timings.length);
if (eval('' + timings.length) == 1) {
//console.log('vttcont=' + vttcont);
timings=vttcont.split(' --> ');
console.log('Timings length=' + timings.length);
}
var spares='',sparesa=[], jspare=0.0;
var sparee='',spareea=[];
var ispare=0, iifg=0, ifactor=1.0;
var thistt='';
if (eval('' + timings.length) > 1) {
for (var kkll=1; kkll<timings.length; kkll++) {
spares='';
sparee=''
ispare=0;
while ((timings[kkll].substring(ispare).substring(0,1) >= '0' && timings[kkll].substring(ispare).substring(0,1) <= '9') || timings[kkll].substring(ispare).substring(0,1) == '.' || timings[kkll].substring(ispare).substring(0,1) == ':') {
sparee+=timings[kkll].substring(ispare).substring(0,1);
ispare++;
}
console.log('sparee=' + sparee + ' and ispare=' + ispare);
while (timings[kkll].substring(ispare).substring(0,1) <= String.fromCharCode(32)) {
ispare++;
}
console.log('ispare=' + ispare);
vtttitles.push(timings[kkll].substring(ispare).split(String.fromCharCode(10))[0].split('{')[0]);
console.log('title=' + vtttitles[-1 + eval('' + vtttitles.length)]);
spareea=sparee.split(':');
ifactor=1.0;
jspare=0.0;
for (iifg=eval(-1 + eval('' + spareea.length)); iifg>=0; iifg--) {
console.log('iifg=' + iifg + ' via ' + spareea[iifg] + '!');
jspare+=eval(ifactor * eval('' + spareea[iifg].replace(/^0/g,'')));
console.log('Jspare=' + jspare);
ifactor*=60;
}
vttendsecs.push(jspare);
ispare=-1;
console.log('jspare=' + jspare);
while ((timings[-1 + kkll].slice(ispare).substring(0,1) >= '0' && timings[-1 + kkll].slice(ispare).substring(0,1) <= '9') || timings[-1 + kkll].slice(ispare).substring(0,1) == '.' || timings[-1 + kkll].slice(ispare).substring(0,1) == ':') {
spares=timings[-1 + kkll].slice(ispare).substring(0,1) + spares;
ispare--;
}
console.log('spares=' + spares);
sparesa=spares.split(':');
ifactor=1.0;
jspare=0.0;
for (iifg=eval(-1 + eval('' + sparesa.length)); iifg>=0; iifg--) {
jspare+=eval(ifactor * eval('' + sparesa[iifg].replace(/^0/g,'')));
ifactor*=60;
}
vttstartsecs.push(jspare);
}

}
}

function gotback(iois) {
if (iois != null) {
//if (iois.src.indexOf('?placegeo=') != -1) {
//alert(1);
var aconto = (iois.contentWindow || iois.contentDocument);
//alert(11);
if (aconto != null) {
//alert(111);
if (aconto.document) { aconto = aconto.document; }
//alert(1111);
if (aconto.body != null) {
vttcont=aconto.body.innerHTML.replace('<pre>','').replace('</pre>','');
pushit();
}
}
//}
}
}

function tracks(iois) {
}


function showScroll() {
if ((navigator.userAgent.match(/iPhone|iPod|iPad/i) || top.document.URL.indexOf('?audio=') != -1) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
if (document.URL.indexOf('justmusic=0') != -1) {
document.getElementById('next').innerHTML+='<audio onloadedmetadata=tracks(this); id=myaudio title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + '; parent.document.body.setAttribute(' + "'data-music','yes'" + ');" style=position:absolute;top:0px;left:0px; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source><track kind="subtitles" src="sound/all.vtt" srclang="en"></track></audio><iframe onload=gotback(this) src=sound/all.vtt style=display:none;></iframe>';
} else {
document.getElementById('next').innerHTML+='<audio onloadedmetadata=tracks(this); id=myaudio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop data-ideanogo=autostart><source type=audio/mp3 src=sound/all.mp3></source><track kind="subtitles" src="sound/all.vtt" srclang="en"></track></audio><iframe onload=gotback(this) src=sound/all.vtt style=display:none;></iframe>';
}
//alert(document.getElementById('next').innerHTML);
console.log("1");
//var textTrackElem = document.getElementById("myaudio");
mycurt=0;
setInterval(getct, 2000);

setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}
if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}


Previous relevant Ffmpeg Log Helper Towards VTT File Primer Tutorial is shown below.

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday's One Image Website iOS Radio Music One Less Tutorial set us on an "off to the side, but eventually forward" project that intertwines ...

  • ffmpeg ... with its great logging and media concatenation talents, thanks ...
  • macOS Terminal desktop app ... regarding its great GUI design feature allowing you to gather up actions of the past into a copy buffer via its Edit -> Find functionality, thanks
  • Audio and Video HTML element track cue functionality VTT file interface ... you can read more about at HTML5 Track Element Primer Tutorial

Don't know about you, but have always found the creation of track data VTT files (and their predecessor SRT files) one of the most tedious jobs in programming?

But the work of the day before yesterday's One Image Website iOS Radio Music Tutorial and its audio concatenation via ffmpeg themes had us looking back, wistfully, back up our (macOS) Terminal (desktop apps) logging of a few days past, hoping for an escape from VTT file manual text editing for our wish to enhance our One Image Website work of recent days. Wow, the ffmpeg logging was brilliant!

There was enough there to program the creation of VTT files from the ffmpeg, and our "cd"ing and "ls"ing and other stuff, in the (let's more accurately say, Terminal) logging. Yayyyyy!

And so we have an albeit defaults very particular to my situation in its HTML form textarea and input type=text textbox defaults (shown via placeholder attributes), but we think it could be a tweakable basis for your own ffmpeg media concatenation work, perhaps, with our first draft proof of concept ffmpeg logging, via Terminal, PHP helper towards VTT file creation.

If you click the light green form submit button, in the iframe way below, yourself, it will reveal, in details/summary (revealing) tags, both the input and output (VTT files) for you to see this more clearly, or to have it clicked for you in a new window, click this button clicker incarnation. In the works of the HTML form below, for the first time we can remember, and because the defaults are so arcane, we developed HTML form onsubmit logic as per ...


<form id=myform onsubmit=" var ins=document.getElementsByTagName('textarea'); if (document.getElementById(ins[0].id).value == '') { document.getElementById(ins[0].id).value=('' + document.getElementById(ins[0].id).placeholder); } ins=document.getElementsByTagName('input'); for (var ii=0; ii<ins.length; ii++) { if (document.getElementById(ins[ii].id).value == '' && document.getElementById(ins[ii].id).type == 'text') { document.getElementById(ins[ii].id).value=('' + document.getElementById(ins[ii].id).placeholder); } } return true;" action=./ffmpeg_log_to_vtt.php method=POST>
<textarea name=infile id=infile title='Or paste in your ffmpeg log file data' placeholder='all_bar_thecommute.txt' value='' style="background-color:yellow;"></textarea><br><br>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Output Basename Prefixing Delimiter</th><th>Output Basename Suffixing Delimiter</th></tr>
<tr><td><input name=inbasenameprefix id=inbasenameprefix type=text placeholder='user@Users-Air' value=''></input></td><td><input name=inbasenamesuffix id=inbasenamesuffix type=text placeholder='% cd' value=''></input></td></tr>
</table>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Metadata Prefixing String</th><th>Metadata Name Value Delimiter</th><th>Metadata Title Value Case Insensitive Start String</th></tr>
<tr><td><input name=metaprefix id=metaprefix type=text placeholder='Metadata:' value=''></input></td><td><input name=metadelimiter id=metadelimiter type=text placeholder=':' value=''></input></td><td><input name=metatitleprefix id=metatitleprefix type=text placeholder='tit' value=''></input></td></tr>
</table>
<table border=2 cellpadding=10 cellspacing=10>
<tr><th>Duration Prefixing String</th><th>Duration Time Part Delimiter</th></tr>
<tr><td><input name=durationprefix id=durationprefix type=text placeholder='Duration:' value=''></input></td><td><input name=durationdelimiter id=durationdelimiter type=text placeholder=':' value=''></input></td></tr>
</table>
<br><br><br>
<input id=mysub type=submit value="Create VTTs" style="background-color:lightgreen;"></input>
</form>

... as a way to deal with arcane defaults, where the encouragement is there for an interested programmer to download PHP code (perhaps to a MAMP local Apache/PHP/mySql web server environment) and tweak to their purposes. Note that you can paste your own logging into the textarea as a way this PHP application can be useful even up at the RJM Programming domain ...


Previous relevant One Image Website iOS Radio Music One Less Tutorial is shown below.

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday's One Image Website iOS Radio Music Tutorial "Stop Press" promised ...

For tomorrow, we offer an optional "one less click", "one less window" methodology improvement on the work above, as we transition the other "One Image Websites" over to the new iOS music paradigm.

... and so, it being tomorrow we're here starting our discussion starting with the "one less window" thought. Have a look at this table outlining some (off the top of the head) clientside navigation techniques in two categories ...

No new window created ... New window created ...
window.open([URL],'_self') window.open([URL],'_blank')
location.href=[URL] window.open([URL],'_top')
window.location=[URL] top.window.location=[URL]; // if in an iframe
Ajax (with or without new FormData()) whether 'GET' or 'POST' form target=_blank action=[URL]
form target=_self action=[URL] form target=_top action=[URL] // if in an iframe
iframe srcdoc=[webpageHTML] form target=_parent action=[URL] // if in an iframe
iframe src=[URL] parent.window.location=[URL]; // if in an iframe

... and it's that last left hand column iframe src=[URL] we like for the purposes of these changes today. That new HTML iframe in the "One Image Website" index.htm supervisories is now worked via ...


function rotateImage(place) {

while (number_of_image == 0)
{
place = place;
}
xplace=place;

anotherNew();

var foreground=document.getElementById(place);


var thedivlink=document.getElementById("thedivlink");
var thediv=document.getElementById("thediv");


if (foreground.width > 0) {
thedivlink.style.display = "none";
thediv.style.display = "none";
if (document.getElementById('ifmusicone')) {
document.getElementById('ifmusicone').style.display='none';
}

//
// more rotateImage code follows ...
//
}
//
// more rotateImage code follows ...
//
}

function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i)) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.body.innerHTML+='<iframe id=ifmusicone title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" src="./index-ssmhalf.html?justmusic=0" style="opacity:0.5;z-index:345;position:absolute;width:140px;height:100px;left:' + eval(-140 + eval('' + window.innerWidth)) + 'px;top:0px;"></iframe>';
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}


</script>
</head>
<body id="body" onload=' xonl(); if (document.URL.indexOf("exif=") != -1) { dexifit(); } showScroll(); window.setTimeout("FadeInImage()", 4000); '>
<div id="thediv" style="display:block;" >
<span><a id="thedivlink" style="display:inline-block;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." onclick="javascript: window.open('index-ssmhalf.html?justmusic=','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="#" data-href="sound/Prelude_Melody-Mike_Vekris.mp3" >The Commute - RJM Programming ... you might see this while loading ... &#127926; click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery &#127926; ... else please wait for full functionality ...</a> versus <a onclick=huhit(); onmousedown=huhittwo(); style=display:inline-block;cursor:pointer;text-decoration:underline;>Exif Run</a></span>
</div>
<a id="alink" style="font-size:28px;background-color:yellow;" onclick="javascript: window.open('index-ssmhalf.html','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)'); disableHref();" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="sound/Prelude_Melody-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming" src="siteimage.jpg" /-->
<img border=0 id="place" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." src="siteimage.jpg" />
</a>

... now, with the iOS platforms, presenting a new HTML audio (loop attribute set) in a slightly different incarnation as per index-ssmhalf.html ...



function nextPage()
{
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
image_index=image_index;
} else {

window.location = "index-saf.html";
}
}

function setvv() {
document.getElementById('place').style.visibility='visible';
}


function showScroll() {
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
if (document.URL.indexOf('justmusic=0') != -1) {
document.getElementById('next').innerHTML+='<audio title="Play http://www.freesoundtrackmusic.com (thanks) Music Set on Loop Here" onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + '; parent.document.body.setAttribute(' + "'data-music','yes'" + ');" style=position:absolute;top:0px;left:0px; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
} else {

document.getElementById('next').innerHTML+='<audio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
}
//alert(document.getElementById('next').innerHTML);
setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}

if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}

</script>
</head>
<body id="body" onload='showScroll(); window.setTimeout("rotateImage()", 4000); '>
<a id="next" onclick="javascript: window.open('index-safhalf.html','The Commute - Playing With Filters (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" title="" href="sound/Playing_with_Filters-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" alt="DSCF1486" src="DSCF1486.jpg" /-->
<img border=0 id="place" alt="" src="DSCF1486.jpg" style=visibility:hidden; />
</a>

... up towards the top right of the index.htm webpage when using an iOS platform. It is optional whether the user ...

  • clicks Play button of that new top right audio element for continuous "looped audio track sets" mode of use with no new second window required (and so, no window focus changes and no second click required either)
  • clicks blue link for continuous "looped audio track sets" mode of use with a new second window's audio element that the user clicks the Play button of
  • clicks none of those modes of use above that are offered for a short time to then click appropriately to start up music, optionally, as required, at a later date as possible

So feel free to try a One Image Website in the list below ...

... where this new iOS music arrangement logic has been incorporated.

Stop Press

The Webpage Meta Refresh Primer Tutorial has reminded us of another left hand "No new window created" navigation methodology using the HTML meta "refresh" tag.


Previous relevant One Image Website iOS Radio Music Tutorial is shown below.

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

Did you read the recent Responsive Web Design Landing Page Image Map Tutorial? Its core takeaway was the linking of One Image Website functionalities. In these One Image Websites we've picked out a guinea pig ...


"The Commute"

... to have a day's worth of experimenting trialling a solution to the "chestnut of a" problem getting iOS music to play continuously without supervision, like a radio program, albeit on a cycle of repeated content (set (such as the oneoffive.mp3 twooffive.mp3 threeoffive.mp3 fouroffive.mp3 fiveoffive.mp3 set of 5 tracks in example below)). Years ago Apple's iOS started requiring a user click to validate the playing of media, hence the interest in today's topic.

The ingredients for the solution, and testing thereof, are ...

  • macOS command line ffmpeg ... capable of ...
  • concatenating audio files ... with command like ...


     
    ffmpeg -i oneoffive.mp3 -i twooffive.mp3 -i threeoffive.mp3 -i fouroffive.mp3 -i fiveoffive.mp3 -filter_complex "[0:a][1:a]concat=n=5:v=0:a=1" all.mp3

     

    ... into ...
  • compilation audio ... all.mp3 ... uploaded to RJM Programming domain ... is now called on ...
  • within an audio tagged HTML element ... with ...
  • loop attribute set ... using as a device ...
  • an iPhone ... teamed ...
  • optionally, (we're just suggesting this headphone idea if you want to keep the music to yourself) via Bluetooth, with a set up involving a connection to a set of AirPods (and connected to your ears) ... are chosen as ...
  • the default speakers for sound ... then use ...
  • web browser app such as Safari ...
  • into the address bar type


    https://www.rjmprogramming.com.au/thecommute

    ... to arrive at the calling window ...

  • click the blue link up the top that appears for a short time ... then ...
  • in the resultant new music window click the Audio play button presented (the point of interest being that this could be the last click required for continuous music playing, in that audio loop) ... music should play continuously and ...
  • if more interesting visuals are also required focus back to calling window

And given that the iPhone and AirPods are charged, and you don't charge out of Bluetooth range with the iPhone, you could get that "radio feeling" out of an iOS user experience!

Code changes, all just clientside HTML and Javascript, went ...

calling window's index.htm changes around the document.body onload event area of interest 🎶 ...


function xonl() {
if (!navigator.userAgent.match(/iPhone|iPod|iPad/i)) {
document.getElementById('thedivlink').href=document.getElementById('thedivlink').getAttribute('data-href');
} else {
document.getElementById('thedivlink').href='index-ssmhalf.html?justmusic=';
document.getElementById('thedivlink').onclick=function() { document.getElementById('thedivlink').href=document.getElementById('thedivlink').href; };
document.getElementById('thedivlink').target='_blank';
}
}


</script>
</head>
<body id="body" onload=' xonl(); if (document.URL.indexOf("exif=") != -1) { dexifit(); } showScroll(); window.setTimeout("FadeInImage()", 4000); '>
<div id="thediv" style="display:block;" >
<span><a id="thedivlink" style="display:inline-block;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." onclick="javascript: window.open('index-ssmhalf.html?justmusic=','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="#" data-href="sound/Prelude_Melody-Mike_Vekris.mp3" >The Commute - RJM Programming ... you might see this while loading ... &#127926; click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery &#127926; ... else please wait for full functionality ...</a> versus <a onclick=huhit(); onmousedown=huhittwo(); style=display:inline-block;cursor:pointer;text-decoration:underline;>Exif Run</a></span>
</div>
<a id="alink" style="font-size:28px;background-color:yellow;" onclick="javascript: window.open('index-ssmhalf.html','The Commute - Soul Tracker Mechanism (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)'); disableHref();" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" href="sound/Prelude_Melody-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming" src="siteimage.jpg" /-->
<img border=0 id="place" title="Click for Prelude Melody provided by http://www.freesoundtrackmusic.com" alt="The Commute - RJM Programming ... you might see this while loading ... click here now to just play music (Prelude Melody provided by http://www.freesoundtrackmusic.com) with less variety of imagery ... else please wait for full functionality ..." src="siteimage.jpg" />
</a>
music window's index-ssmhalf.html changes around the document.body onload event area of interest ...


function nextPage()
{
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
image_index=image_index;
} else {

window.location = "index-saf.html";
}
}

function setvv() {
document.getElementById('place').style.visibility='visible';
}


function showScroll() {
if (navigator.userAgent.match(/iPhone|iPod|iPad/i) && ('' + document.referer).indexOf('index-') == -1 && document.URL.indexOf('justmusic') != -1) {
document.getElementById('next').onclick=function() { image_index=image_index; }
document.getElementById('next').href='#' + document.getElementById('next').href.replace('Playing_with_Filters-Mike_Vekris', 'all');
//alert(document.getElementById('next').href);
document.getElementById('next').innerHTML+='<audio onclick=" document.getElementById(' + "'place'" + ').style.visibility=' + "'visible'" + ';" style=position:absolute;top:50%;left:50%; type=audio/mp3 controls loop><source type=audio/mp3 src=sound/all.mp3></source></audio>';
//alert(document.getElementById('next').innerHTML);
setTimeout(setvv, 30000);
} else {
document.getElementById('place').style.visibility='visible';
}

if (document.URL.indexOf('yesscroll' + 'check=') != -1 || document.head.innerHTML.indexOf('yesscr' + 'ollcheck=') != -1) {
var oif=document.getElementById('iframeshowscrollxy');
if (oif == null) {
if (document.URL.indexOf('noscroll' + 'check=') == -1 && document.head.innerHTML.indexOf('noscr' + 'ollcheck=') == -1) {
document.body.innerHTML+="<iframe id='iframeshowscrollxy' style='display:none;' src='http://www.rjmprogramming.com.au/HTMLCSS/scroll_check.html'></iframe>";
}
}
}
}

</script>
</head>
<body id="body" onload='showScroll(); window.setTimeout("rotateImage()", 4000); '>
<a id="next" onclick="javascript: window.open('index-safhalf.html','The Commute - Playing With Filters (via http://www.freesoundtrackmusic.com) - RJM Programming - http://www.rjmprogramming.com.au (Copyright © 2011 rjmprogramming.com.au all rights reserved.)');" title="" href="sound/Playing_with_Filters-Mike_Vekris.mp3" >
<!--img border=0 id="place" style="width: 2816px; height: 2120px;" alt="DSCF1486" src="DSCF1486.jpg" /-->
<img border=0 id="place" alt="" src="DSCF1486.jpg" style=visibility:hidden; />
</a>

... and off up to the RJM Programming domain as "The Commute", with music courtesy of the generous Royalty Free Music For Video, thanks.

Stop Press

For tomorrow, we offer an optional "one less click", "one less window" methodology improvement on the work above, as we transition the other "One Image Websites" over to the new iOS music paradigm.


Previous relevant Responsive Web Design Landing Page Image Map Tutorial is shown below.

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said ...

So, why keep the old way? Well, we packed the "old way" with content rich functionality, and do not want to ditch that yet, but maybe over time?!

We're just over time, aren't you?! And so, we arrive at a long planned for tilt at Image Map functionality that we often turn to Mobilefish.Com and its excellent Image Map Creation to help us out ... but not today?! Why not? We have a funny set of needs, they being ...

  • our Image Map's image will have a variable set of width x height dimensions ...
  • our Image Map's image will be transparent
  • our Image Map needs to have a hole left aside inside it where the functionality that originally existed (and pointed to WordPress Blog content like you are reading), is still working

... the last condition of which we realized, down the track, required us to create four Image Maps. But ... but ... Nala hears you say?!

Yes, we can reference the one image, in its data URL guise, as a smaller, or not, version of itself, by specifying CSS properties ...

  • position:absolute; (our usual for overlay scenarios)
  • z-index:56; (for both transparent image and its associated Image Map ... more on this later)
  • left (to appropriately position in X to be in the relevant section of dark green Image Map overlaying in the Landing Page)
  • top (to appropriately position in Y to be in the relevant section of dark green Image Map overlaying in the Landing Page)
  • width (which will be up to the transparent image width)
  • height (which will be up to the transparent image height)

... and no concern about opacity given the transparent image and z-index considerations, here.

So, how can we involve a transparent image here? Well, that is where the new Responsive Web Design Landing Page being PHP, though up to today it had contained no PHP, is in our favour. We can use PHP's GD to create one, grab its associated data URL and tidy up, and constructing the four image and associated Image Map HTML elements populated, in its "child iframe", and sending back up into the "parent webpage's" new ...

<?php echo "

<div id=divimif></div>
<iframe style='display:none;' id=myimif src=></iframe>

"; ?>

... placed at the bottom of the Landing Page body element, and used in the changed document.body onload event Javascript function ...

<?php echo "

function onl() {
if (eval('' + screen.width) <= 420) {
//alert(screen.width);
document.getElementById('topspan').innerHTML=document.getElementById('topspan').innerHTML.replace('RJM Programming', 'RJM</h1><h1>Programming').replace(/\<\/hJUNK1/g, '</h2');
} //else if (eval('' + screen.width) <= 480) {
//alert('0' + screen.width);
//}
var myiz=document.getElementById('ifzero').getBoundingClientRect();
var myhr=document.getElementById('myheader').getBoundingClientRect();
var myh=eval('' + myhr.height);
var myt=eval('' + myhr.top);
var widthleft=eval(eval('' + myiz.left) - eval('' + myhr.left));
var widthmiddle=eval('' + myiz.width);
var widthright=eval(eval('' + myhr.width) - eval('' + myiz.width) - eval('' + myiz.left));
if (document.getElementById('navTop')) {
var myalthr=document.getElementById('navTop').getBoundingClientRect();
myh-=eval('' + myalthr.height);
myt=eval('' + myalthr.height);
}
var heighttop=eval(eval('' + myiz.top) - eval('' + myt));
var heightmiddle=eval('' + myiz.height);
var heightbottom=eval(eval('' + myh) - eval('' + myiz.height)); // - eval('' + myiz.top));
if (window.parent != window) {
myh=myh;
} else if (('' + window.opener).replace(/^undefined/g,'').replace(/^null/g,'')) {
myh=myh;
} else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPaJUNKd|iPod|Opera Mini|IEMobile/i)) {
myh=myh;
} else {
document.getElementById('myimif').src=document.URL.split('?')[0].split('#')[0] + '?left=' + myhr.left + '&top=' + myt + '&width=' + myhr.width + '&height=' + myh + '&ifleft=' + myiz.left + '&iftop=' + myiz.top + '&ifwidth=' + myiz.width + '&ifheight=' + myiz.height + '&widthleft=' + widthleft + '&widthmiddle=' + widthmiddle + '&widthright=' + widthright + '&heighttop=' + heighttop + '&heightmiddle=' + heightmiddle + '&heightbottom=' + heightbottom;
setTimeout(imbit, 5000);
}

}

"; ?>

... to call on that new PHP ...

<?php

if (isset($_GET['left']) && isset($_GET['top']) && isset($_GET['width']) && isset($_GET['height'])) {
$uw="";
$postuw="";
$uw1="";
$postuw1="";
$uw2="";
$postuw2="";
$uw3="";
$postuw3="";
if (isset($_GET['widthleft']) && isset($_GET['widthmiddle']) && isset($_GET['widthright']) && isset($_GET['heighttop']) && isset($_GET['heightmiddle']) && isset($_GET['heightbottom'])) {
$uw=" usemap=#workmap";
$uw1=" usemap=#workmap1";
$uw2=" usemap=#workmap2";
$uw3=" usemap=#workmap3";

$postuw="<map name=workmap style=z-index:56;>";
$postuw1="<map name=workmap1 style=z-index:56;>";
$postuw2="<map name=workmap2 style=z-index:56;>";
$postuw3="<map name=workmap3 style=z-index:56;>";

$postuw.="<area shape=rect title=Ephemeral onmouseover=omoiset(1); onmouseout=omoiset(-2); coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=LeftTop onclick=ouralert(1); target=_blank href=//www.rjmprogramming.com.au/ephemeral />";
$postuw.="<area shape=rect title=StreetArt onmouseover=omoiset(2); onmouseout=omoiset(-2); coords=" . explode('.',$_GET['widthleft'])[0] . ",0," . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=CenterTop onclick=ouralert(2); target=_blank href=//www.rjmprogramming.com.au/streetart />";
$postuw.="<area shape=rect title=TheCommute onmouseover=omoiset(3); onmouseout=omoiset(-2); coords=" . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . ",0," . explode('.',$_GET['width'])[0] . "," . explode('.',$_GET['heighttop'])[0] . " alt=RightTop onclick=ouralert(3); target=_blank href=//www.rjmprogramming.com.au/thecommute />";

$postuw1.="<area id=area4 title=? onmouseover=omoiset(4); onmouseout=omoiset(-1); shape=rect coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',(0 + $_GET['heightmiddle']))[0] . " alt=LeftMiddle onclick=ouralert(4); target=_blank nohref />";
$postuw2.="<area id=area6 title=? onmouseover=omoiset(6); onmouseout=omoiset(-1); shape=rect coords=0,0," . explode('.',$_GET['widthright'])[0] . "," . explode('.',(0 + $_GET['heightmiddle']))[0] . " alt=RightMiddle onclick=ouralert(6); target=_blank nohref />";

$postuw3.="<area shape=rect title=InnerBurbs onmouseover=omoiset(7); onmouseout=omoiset(-2); coords=0,0," . explode('.',$_GET['widthleft'])[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=LeftBottom onclick=ouralert(7); target=_blank href=//www.rjmprogramming.com.au/pyrmontultimo />";
$postuw3.="<area shape=rect title=Bygone onmouseover=omoiset(8); onmouseout=omoiset(-2); coords=" . explode('.',$_GET['widthleft'])[0] . ",0," . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=CenterBottom onclick=ouralert(8); target=_blank href=//www.rjmprogramming.com.au/bygone />";
$postuw3.="<area shape=rect title=West onmouseover=omoiset(9); onmouseout=omoiset(-2); coords=" . explode('.',($_GET['widthleft'] + $_GET['widthmiddle']))[0] . ",0," . explode('.',$_GET['width'])[0] . "," . explode('.',$_GET['heightbottom'])[0] . " alt=RightBottom onclick=ouralert(9); target=_blank href=//www.rjmprogramming.com.au/thewest />";

$postuw.="</map>";
$postuw1.="</map>";
$postuw2.="</map>";
$postuw3.="</map>";
}


// Create a transparent image thanks to https://www.php.net/manual/en/function.imagecolortransparent.php
$im = imagecreatetruecolor($_GET['width'], $_GET['height']);
$red = imagecolorallocate($im, 255, 0, 0);
$black = imagecolorallocate($im, 0, 0, 0);

// Make the background transparent
imagecolortransparent($im, $black);

// Save the image
$udirnameprebimg='/tmp/imagecolortransparent.png';
imagepng($im, $udirnameprebimg);

$duis='data:image/' . str_replace('jpg','jpeg',strtolower(explode('.',$udirnameprebimg)[-1 + sizeof(explode('.',$udirnameprebimg))])) . ';base64,' . base64_encode(file_get_contents($udirnameprebimg));
imagedestroy($im);
unlink($udirnameprebimg);



echo "<html>
<body onload=\"parent.document.getElementById('divimif').innerHTML='<img id=myimg style=height:" . $_GET['heighttop'] . "px;z-index:56;position:absolute;top:" . $_GET['top'] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['width'] . "px; src=" . $duis . "" . $uw . "></img>" . $postuw . "<img id=myimg1 style=height:" . $_GET['heightmiddle'] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop']))[0] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['widthleft'] . "px; src=" . $duis . "" . $uw1 . "<>/img>" . $postuw1 . "<img id=myimg2 style=height:" . $_GET['heightmiddle'] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop']))[0] . "px;left:" . explode('.',($_GET['width'] - $_GET['widthright']))[0] . "px;width:" . $_GET['widthright'] . "px; src=" . $duis . "" . $uw2 . "></img>" . $postuw2 . "<img id=myimg3 style=height:" . explode('.',($_GET['height'] - $_GET['heighttop'] - $_GET['heightmiddle']))[0] . "px;z-index:56;position:absolute;top:" . explode('.',($_GET['top'] + $_GET['heighttop'] + $_GET['heightmiddle']))[0] . "px;left:" . $_GET['left'] . "px;width:" . $_GET['width'] . "px; src=" . $duis . "" . $uw3 . "></img>" . $postuw3 . "'; \"></body>
</html>";

exit;
}

?>

... and once setup, helped out by new Javascript, as per ...

<?php echo "

var urls=['', '', '', ' ', '', ' ', '', '', ''];
var omoi=-1;
var isrelp=false;

function postomoiset() {
if (isrelp) {
isrelp=false;
if (omoi == 4 || omoi == 6) {
var wasomoi=omoi;
omoi=-1;
ouralert(wasomoi);
}
}
}

function omoiset(jnnum) {
if (eval('' + jnnum) == -1) {
omoi=jnnum;
//document.title='omoi=' + omoi;
isrelp=false;
//setTimeout(postomoiset, 8000);
} else if (eval('' + jnnum) == -2) {
if (omoi != 4 && omoi != 6) {
omoi=jnnum;
//document.title='omoi=' + omoi;
isrelp=false;
//setTimeout(postomoiset, 8000);
}
} else {
omoi=jnnum;
//document.title='omoi=' + omoi;
if (omoi != 4 && omoi != 6) {
isrelp=false;
} else {
isrelp=true;
//document.title='omoi=' + omoi + '|';
setTimeout(postomoiset, 8000);
}
}
}

function ouralert(innum) {
var ans='';
switch ('' + innum) {
case '1':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '2':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '3':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '4':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.) Eg. https://www.rjmprogramming.com.au/slideshow.html', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '5':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '6':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.) Eg. https://www.rjmprogramming.com.au/plus/', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '7':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', urls[eval(-1 + eval('' + innum))].trim());
}
break;
case '8':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', '');
}
break;
case '9':
if (urls[eval(-1 + eval('' + innum))] != '') {
ans=prompt('Want to go anywhere? (To save for future append a blank.)', '');
}
break;
default:
break;
}
if (!ans) { ans=''; }
if (ans != '') {
window.open(ans.trim(), '_blank');
if (ans != ans.trim()) {
window.localStorage.setItem('area' + innum + 'url', encodeURIComponent(ans.trim()));
}
}
}


function imbit() {
//if (document.getElementById('myimg')) {
// document.getElementById('myimg').style.border='5px dashed purple';
//}
if (('' + window.localStorage.getItem('area4url')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
urls[3]=decodeURIComponent('' + window.localStorage.getItem('area4url'));
document.getElementById('area4').title=decodeURIComponent('' + window.localStorage.getItem('area4url')) + '# ... long hover of at least 8 seconds for chance to change';
document.getElementById('area4').href=decodeURIComponent('' + window.localStorage.getItem('area4url'));
document.getElementById('area4').onclick=function(){ omoiset=-1; urls[3]=urls[3]; }
//document.getElementById('area4').ondblclick=function(){ ouralert(4); }
}
if (('' + window.localStorage.getItem('area6url')).replace(/^undefined/g,'').replace(/^null/g,'') != '') {
urls[5]=decodeURIComponent('' + window.localStorage.getItem('area6url'));
document.getElementById('area6').title=decodeURIComponent('' + window.localStorage.getItem('area6url')) + '# ... long hover of at least 8 seconds for chance to change';
document.getElementById('area6').href=decodeURIComponent('' + window.localStorage.getItem('area6url'));
document.getElementById('area6').onclick=function(){ omoiset=-1; urls[5]=urls[5]; }
//document.getElementById('area6').ondblclick=function(){ ouralert(6); }
}
}

"; ?>

... in a changed index.php Landing Page whose guises as ...

  • Landing Page in mobile phone devices
  • Landing Page in an iframe
  • Landing Page in a popup window

... we all excluded from new functionality Image Map potential "dark green area clicking" access to photography themed "One Image Websites" ...

... accessible from Image Map area elements up above and down below the WordPress Blog posting iframe whose CSS property z-index is set to ...

<?php echo "

<iframe title='Recent posts' onload='check_if(this);' src='PHP/zero.html?totalwidth=y' class='zero' id='ifzero' style='z-index:57;'></iframe>

"; ?>

... 57.


Previous relevant Responsive Web Design Landing Page Incarnation Tutorial is shown below.

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

Along the same "Responsive Design" themes of Responsive Web Design Primer Tutorial, we stumbled upon the excellent W3Schools Responsive Design Based Start Page Idea which inspired us to retry RJM Programming Landing Page thoughts ...

  • separating out totally "uninvolved" Landing Page calls hooked up with a new index.php (actually just HTML) Landing Page incarnation that has better Responsive Design credentials ... from ...
  • any other call of any complexity or having a query string etcetera, reverting to the "old way"

... new paradigm? So, why keep the old way? Well, we packed the "old way" with content rich functionality, and do not want to ditch that yet, but maybe over time?!

You'll see, though, using the new index.php Responsive Design Landing Page incarnation ...

... how the clutter melts away like a hot knife through margarinebutter!


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of "responsive web design" ...

Responsive web design (RWD) is an approach to web design that makes web pages render well on a variety of devices and window or screen sizes from minimum to maximum display size. Recent work also considers the viewer proximity as part of the viewing context as an extension for RWD.[1] Content, design and performance are necessary across all devices to ensure usability and satisfaction.[2][3][4][5]

... coming at it from the idea "Can a responsive shell webpage host a non-responsive iframe?"

In turn this got us to the excellent ideas of this webpage which we'll try out for a while ...

  • honing in on our "Landing Page and friends" set of unresponsively designed webpages ...
  • honing in on iPhone sized devices (ie. not iPads nor laptops) ...
  • host web browser address bar calls of "Landing Page and friends" set of unresponsively designed webpages within a caller.html responsively web designed shell supervisory webpage and start using some of that ...
    Unresponsive Landing Page
    Responsive Shell around Unresponsive Landing Page

    ... as food for (your) thought ...


    function bodonl() {
    var wasih=document.body.innerHTML;
    var huhd=document.getElementById('Container').getBoundingClientRect();
    var pb=0;
    if (eval('' + huhd.height) > eval('' + huhd.width)) {
    isportrait=true;
    pb=eval(eval('' + huhd.width) / eval('' + huhd.height) * 100.0);
    nowih='<div id="Container" style="padding-right:' + pb + '%; position:relative; display:block; height: 100vh;"><iframe' + wasih.split('<iframe')[1].split('</div>')[0].replace('" frameborder', fname + '" style="position:absolute; top:0; left: 0;" frameborder') + '</div>';
    //if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    //document.getElementById('myvis').setAttribute('initial-scale','0.5');
    //}
    } else {
    isportrait=false;
    pb=eval(eval('' + huhd.height) / eval('' + huhd.width) * 100.0);
    nowih='<div id="Container" style="padding-bottom:' + pb + '%; position:relative; display:block; width: 100%;"><iframe' + wasih.split('<iframe')[1].split('</div>')[0].replace('" frameborder', fname + '" style="position:absolute; top:0; left: 0;" frameborder') + '</div>';
    }
    document.body.innerHTML=nowih;
    }

    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.


    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, iOS, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment