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

Ffmpeg Voiceover AlmaLiux Tutorial

Ffmpeg Voiceover AlmaLiux Tutorial

Ffmpeg Voiceover AlmaLiux Tutorial

Two recent aspects to work here have meant that the Voiceover work of Ffmpeg Shelling Peas Tutorial can be improved upon …

  • migrating the web server from CentOS to AlmaLinux gave us the opportunity to have ffmpeg installed on the (public) web server … and …
  • when we presented Making of iPhone Videos Play Around the Traps Tutorial we created a Javascript clientside approach to synchronizing two separate video and audio tracks, a topic that has interested us since “ever knows when”

… the implications of the first idea above meaning, depending on user supplied video and audio compatible files (small enough), we’ll be able to show an ffmpeg created video combining the two, all the work taking place on our AlmaLinux’s /tmp/ folder for a five minute period, as time enough to gather the video and audio data and try the ffmpeg command shown to you ahead of doing it.

Codewise, this involved …


Previous relevant Ffmpeg Shelling Peas Tutorial is shown below.

Ffmpeg Shelling Peas Tutorial

Ffmpeg Shelling Peas Tutorial

Well, our wish to “shell peas” setting up more ffmpeg media options based on the excellent FFmpeg cheat sheet, thanks, today, had its ups and downs for speed of progress, but, yes, to have a solid “framework” to work within, that you are happy with, barring those tweaks you inevitably discover in projects as they gain complexity, is the best first endeavour you might need to do, to feel more relaxed about the parts of the project requiring that third party expertise, which it is your job to test that you have successfully merged into the project. And so, onto yesterday’s Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Linear Gradient Tutorial, we have included new

<?php

$vssfi='img%03d.png';
$bn='*';
$bntwo='.*';

foreach (glob('newfolder_*') as $idfilename) {
if (file_exists($idfilename) && $vssfi == 'img%03d.png') {
foreach (glob($idfilename . DIRECTORY_SEPARATOR . '*') as $idifilename) {
if ($vssfi == 'img%03d.png' && strpos($idifilename, '.') !== false) {
$bnis=basename($idifilename);
$bn='';
$bntwo='';
for ($ibn=0; $ibn<strlen(explode('.', $bnis)[0]); $ibn++) {
if (substr(substr($bnis, $ibn),0,1) >= '0' && substr(substr($bnis, $ibn),0,1) <= '9') {
if ($bntwo == '') {
if (substr(substr($bnis, $ibn),0,1) == '0') {
$bntwo='%0' . strlen(substr(explode('.', $bnis)[0], $ibn)) . 'd' . '.' . explode('.', $idifilename)[-1 + sizeof(explode('.', $idifilename))];
} else {
$bntwo='%d' . '.' . explode('.', $idifilename)[-1 + sizeof(explode('.', $idifilename))];
}
}
} else if ($bntwo == '') {
$bn.=substr(substr($bnis, $ibn),0,1);
}
}
if ($bntwo == '') {
$bn='*';
$bntwo='.' . explode('.', $idifilename)[-1 + sizeof(explode('.', $idifilename))];
}
$vssfi=$idfilename . substr(DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR,0,1) . $bn . $bntwo;
}
}
}
}

?>
<?php echo ”

var ffstr=' Concat demuxer, Display the frame number on each frame, Trimming, Delay video, Delay audio, Extract a frame per second, Extract the frames from a video, Mute some of the audio, Extract one frame, Create a video slideshow from images,', offstr=null, kffstr=0, affstr=[];

//
// And then ... later ...
//
if (newv == 'Trimming') {


document.getElementById('moreb').innerHTML=firstdivih;

document.getElementById('precmds').innerHTML=' ';
document.getElementById('secondi').innerHTML='';
document.getElementById('minusi').innerHTML=' -ss 00:00:00.000 -i ';
document.getElementById('minusi').title='Start time';

document.getElementById('sswitches').innerHTML='-t 60 -c copy ';
document.getElementById('sswitches').title='Duration';

document.getElementById('mysub').value=newv;
} else if (newv == 'Delay video') {

document.getElementById('moreb').innerHTML=firstdivih;
document.getElementById('precmds').innerHTML=' ';

document.getElementById('betweenis').innerHTML='-itsoffset 1.00';
document.getElementById('betweenis').title='Delay in seconds';

document.getElementById('sswitches').innerHTML='-map 1:v -map 0:a <span id=svac contenteditable=false>-vcodec copy -acodec copy </span>';
document.getElementById('sswitches').title='The 1:v 0:a represents video track else use 0:v 1:a for audio track';

document.getElementById('mysub').value=newv;
} else if (newv == 'Delay audio') {

document.getElementById('moreb').innerHTML=firstdivih;
document.getElementById('precmds').innerHTML=' ';

document.getElementById('betweenis').innerHTML='-itsoffset 1.00';
document.getElementById('betweenis').title='Delay in seconds';

document.getElementById('sswitches').innerHTML='-map 0:v -map 1:a <span id=svac contenteditable=false>-vcodec copy -acodec copy </span>';
document.getElementById('sswitches').title='The 0:v 1:a represents audio track else use 1:v 0:a for video track';

document.getElementById('mysub').value=newv;
} else if (newv == 'Extract a frame per second') {

document.getElementById('moreb').innerHTML=firstdivih.replace(' out.mp4',' ');
document.getElementById('precmds').innerHTML=' ';
document.getElementById('secondi').innerHTML='-filter:v fps=fps=1 -vsync 0';
document.getElementById('secondi').title='The 1 represents 1 per second';
document.getElementById('sswitches').innerHTML=\"<span id=sfolder contenteditable=false>newfolder_" . rand(0,784534) . str_replace("\\","\\\\",$ddn) . "out%d.png\" + '</span>';

document.getElementById('mysub').value=newv;
} else if (newv == 'Extract the frames from a video') {

document.getElementById('moreb').innerHTML=firstdivih.replace(' out.mp4',' ');
document.getElementById('precmds').innerHTML=' ';
document.getElementById('secondi').innerHTML=\"-vf \" + String.fromCharCode(34) + \"select='between(t,1,5)+between(t,11,15)'\" + String.fromCharCode(34) + \" -vsync 0\";
document.getElementById('secondi').title='To extract all frames from between 1 and 5 seconds, and also between 11 and 15 seconds';
document.getElementById('sswitches').innerHTML=\"<span id=sfolder contenteditable=false>newfolder_" . rand(0,784534) . str_replace("\\","\\\\",$ddn) . "out%d.png\" + '</span>';

document.getElementById('mysub').value=newv;
} else if (newv == 'Mute some of the audio') {

document.getElementById('moreb').innerHTML=firstdivih;
document.getElementById('secondi').innerHTML='';
document.getElementById('precmds').innerHTML=' ';

document.getElementById('sswitches').innerHTML=\"-vcodec copy -af \" + String.fromCharCode(34) + \"volume=enable='between(t,80,90)'<span id=svolume contenteditable=false>:volume=0\" + String.fromCharCode(34) + \" </span>\";
document.getElementById('sswitches').title='To replace all audio between 1:20 and 1:30 with silence';

document.getElementById('mysub').value=newv;
} else if (newv == 'Create a video slideshow from images') {

document.getElementById('moreb').innerHTML=firstdivih;

document.getElementById('minusi').innerHTML='-r 1/5 -i ';
document.getElementById('minusi').title='Parameter -r marks the image framerate (inverse time of each image); -vf fps=25 marks the true framerate of the output';

document.getElementById('secondi').innerHTML='';
document.getElementById('precmds').innerHTML=' ';
document.getElementById('scbi').innerHTML='" . $vssfi . "';

document.getElementById('sswitches').innerHTML=' -c:v libx264 -vf fps=25<span id=shat contenteditable=false> -pix_fmt yuv420p </span>';

document.getElementById('mysub').value=newv;
} else if (newv == 'Extract one frame') {

document.getElementById('moreb').innerHTML=firstdivih.replace(' out.mp4',' out.jpg');
document.getElementById('secondi').innerHTML='';
document.getElementById('precmds').innerHTML=' ';

document.getElementById('sswitches').innerHTML='-ss 00:00:10.000<span id=svframes contenteditable=false> -vframes 1 </span>';
document.getElementById('sswitches').title='Extract one frame at 10 second mark';

document.getElementById('mysub').value=newv;
}

“; ?>

ffmpeg media functionality talents for you to try yourself, today, in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Linear Gradient Tutorial is shown below.

Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Linear Gradient Tutorial

Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Linear Gradient Tutorial

There were two weakness with the logic in yesterday’s Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Hover Swipe Tutorial, we reckon, those being …

  1. it is hard to “hover swipe” with no linework to show where one option starts and another ends, in Y (or top) co-ordinates … and …
  2. the user has trouble knowing whether their swipe attempt worked

… for which we supply ideas …

  1. linear-gradient background, in the form of a colourful “underlay” div element under (now transparent backgrounded) select (ie. dropdown) element (and associated “overlay” div) … and …
  2. emoji for swipe left ⬅ (&#11013;) and for swipe right ➡ (&#10145;) shown briefly

… featuring relevant code snippets …

  1. <?php echo ”

    function overlay() {
    origval=document.getElementById('schoices').value;
    var rect=document.getElementById('fcommand').getBoundingClientRect();
    document.getElementById('moreb').style.position='absolute';
    document.getElementById('moreb').style.left='' + rect.left + 'px';
    document.getElementById('moreb').style.top='' + rect.top + 'px';
    document.getElementById('moreb').style.width='96%'; //' + rect.width + 'px';
    document.getElementById('moreb').style.height='' + rect.height + 'px';


    document.getElementById('moreb').style.border='1px solid black';
    document.getElementById('moreb').style.paddingLeft='20px';
    document.getElementById('moreb').style.backgroundColor='#f9f9f9';
    document.getElementById('fcommand').style.opacity='0.0';
    document.getElementById('fcommand').style.cursor='pointer';


    document.getElementById('moreb').innerHTML='<span id=precmds></span><span id=verb>ffmpeg" . $ffmpegsuf . "</span> <span id=prescbi></span><span id=minusi> -i </span><span id=scbi><iframe onload=checkif(this,\"inv.mp4\"); scrolling=no frameborder=0 id=cbi data-type=file data-value=inv.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:92px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=69075964842271&left=y\"></iframe></span> <span id=betweenis></span> <span id=secondi>-i <span id=scbix><iframe onload=checkiftwo(this,\"inva.mp4\"); scrolling=no frameborder=0 id=cbix data-type=file data-value=inva.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:106px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=69075964842271&right=y\"></iframe></span></span> <span id=sswitches>-c copy -map 0:v:0 -map 1:a:0 -shortest</span> out.mp4 > <a target=_blank title=ffimpdf.bad onclick=getvb(); style=cursor:pointer;text-decoration:underline; data-href=./ffimpdf.bad>ffimpdf.bad</a>';
    if (firstdivih == '') { firstdivih=document.getElementById('moreb').innerHTML; }
    if (firstbutval == '') { firstbutval=document.getElementById('mysub').value; }
    document.getElementById('schoices').style.display='inline-block';


    rect=document.getElementById('schoices').getBoundingClientRect();


    if (eval('' + rect.height) > 100 || 1 == 1) {


    document.getElementById('schoices').style.backgroundColor='transparent';
    document.getElementById('tf').style.position='absolute'; // using new <div id=tf></div>
    document.getElementById('tf').style.left='' + rect.left + 'px';
    document.getElementById('tf').style.top='' + rect.top + 'px';
    document.getElementById('tf').style.width='' + rect.width + 'px';
    document.getElementById('tf').style.height='' + rect.height + 'px';
    // Thanks to https://stackoverflow.com/questions/49660659/css-gradients-inside-gradients
    document.getElementById('tf').style.background='linear-gradient(0deg, #ffffff 10%, rgba(255,255,0,0.6) 20%, rgba(192,192,192,0.6) 31%, rgba(255,215,0,0.6) 42%, rgba(211,211,211,0.6) 53%, rgba(255,165,0,0.6) 63%, rgba(224,255,255,0.6) 74%, rgba(254,254,254,0.6) 85%, #CC7722 100%), linear-gradient( to right, yellow, pink )'; // #fcfafc #f9f6f8 #f8f1f3
    document.getElementById('tf').style.zIndex='-1';


    document.getElementById('doverlay').style.position='absolute';
    document.getElementById('doverlay').style.left='' + rect.left + 'px';
    document.getElementById('doverlay').style.top='' + rect.top + 'px';
    document.getElementById('doverlay').style.width='' + rect.width + 'px';
    if (eval('' + rect.height) < 30) {
    document.getElementById('doverlay').style.height='' + rect.height + 'px';
    } else {
    document.getElementById('doverlay').style.height='' + eval(eval('' + rect.height) / eval('' + document.getElementById('schoices').size)) + 'px';
    }
    document.getElementById('doverlay').style.zIndex='96';
    document.getElementById('doverlay').style.textAlign='center';
    document.getElementById('doverlay').style.display='block';
    document.getElementById('doverlay').title=document.getElementById('mydefopt').title;
    //document.getElementById('mydefopt').style.fontColor='transparent';
    document.getElementById('mydefopt').innerHTML='';


    document.getElementById('doverlaytwo').style.position='absolute';
    document.getElementById('doverlaytwo').style.left='' + rect.left + 'px';
    //document.getElementById('doverlaytwo').style.top='' + eval(eval('' + rect.height) - eval(2 * eval('' + rect.height) / eval('' + document.getElementById('schoices').size))) + 'px';
    document.getElementById('doverlaytwo').style.top='' + eval(eval('' + rect.height) - eval(0.5 * eval('' + rect.height) / eval('' + document.getElementById('schoices').size))) + 'px';
    //document.getElementById('doverlaytwo').style.bottom='' + rect.bottom + 'px';
    document.getElementById('doverlaytwo').style.width='' + rect.width + 'px';
    if (eval('' + rect.height) < 30) {
    if (1 == 2) { document.getElementById('doverlaytwo').style.height='' + rect.height + 'px'; }
    } else {
    document.getElementById('doverlaytwo').style.height='' + eval(eval('' + rect.height) / eval('' + document.getElementById('schoices').size)) + 'px';
    }
    document.getElementById('doverlaytwo').style.zIndex='96';
    document.getElementById('doverlaytwo').style.textAlign='center';
    document.getElementById('doverlaytwo').style.display='block';
    document.getElementById('mydefopttwo').innerHTML='';

    rect=document.getElementById('mysub').getBoundingClientRect();
    document.getElementById('mysub').style.position='absolute';
    document.getElementById('mysub').style.left='' + rect.left + 'px';
    document.getElementById('mysub').style.top='' + rect.top + 'px';

    setInterval(fhoc, 1000);
    }


    }

    “; ?>
    … using a multiple linear-gradient element style background for the first time we can remember
  2. <?php echo ”

    var swipel='', swipelcp='', swiper='', swipercp='';

    var ra='&#10145;', racp=String.fromCodePoint(10145);
    var la='&#11013;', lacp=String.fromCodePoint(11013);


    function isplace(thiso, e) {
    var kkk=0;
    e = e || window.event;
    e.preventDefault();
    if (e.touches) {
    if (e.touches[0].pageX) {
    pos3 = e.touches[0].pageX;
    pos4 = e.touches[0].pageY;
    } else {
    pos3 = e.touches[0].clientX;
    pos4 = e.touches[0].clientY;
    }
    //console.log('pos3=' + pos3 + ',pos4=' + pos4);
    } else if (e.clientX || e.clientY) {
    pos3 = e.clientX;
    pos4 = e.clientY;
    } else {
    pos3 = e.pageX;
    pos4 = e.pageY;
    }
    if (lasto == e.target) {
    if (Math.abs(pos1 - pos3) >= 70) {
    if (pos3 > pos1) { // swipe right
    swiper=ra;
    swipercp=racp;

    if (e.target == opastr) {
    kkk=eval(1 + eval('' + kpastr));
    if (kkk >= eval('' + apastr.length)) {
    kpastr=eval('' + kpastr);
    } else {
    kpastr=kkk;
    }
    } else if (e.target == opdstr) {
    kkk=eval(1 + eval('' + kpdstr));
    if (kkk >= eval('' + apdstr.length)) {
    kpdstr=eval('' + kpdstr);
    } else {
    kpdstr=kkk;
    }
    } else if (e.target == oimstr) {
    kkk=eval(1 + eval('' + kimstr));
    if (kkk >= eval('' + aimstr.length)) {
    kimstr-=eval('' + kimstr);
    } else {
    kimstr=kkk;
    }
    } else if (e.target == offstr) {
    kkk=eval(1 + eval('' + kffstr));
    if (kkk >= eval('' + affstr.length)) {
    kffstr-=eval('' + kffstr);
    } else {
    kffstr=kkk;
    }
    }
    } else { // swipe left
    swipel=la;
    swipelcp=lacp;

    if (e.target == opastr) {
    kkk=eval(-1 + eval('' + kpastr));
    if (kkk < 0) {
    kpastr=eval(-1 + eval('' + apastr.length));
    } else {
    kpastr=kkk;
    }
    } else if (e.target == opdstr) {
    kkk=eval(-1 + eval('' + kpdstr));
    if (kkk < 0) {
    kpdstr=eval(-1 + eval('' + apdstr.length));
    } else {
    kpdstr=kkk;
    }
    } else if (e.target == oimstr) {
    kkk=eval(-1 + eval('' + kimstr));
    if (kkk < 0) {
    kimstr=eval(-1 + eval('' + aimstr.length));
    } else {
    kimstr=kkk;
    }
    } else if (e.target == offstr) {
    kkk=eval(-1 + eval('' + kffstr));
    if (kkk < 0) {
    kffstr=eval(-1 + eval('' + affstr.length));
    } else {
    kffstr=kkk;
    }
    }
    }
    }
    //alert('swipe distance = ' + Math.abs(pos1 - pos3));
    }
    lasto=e.target;
    }

    function betweeneatatjoes() {
    var origt='', origrest='', kkprefix=swipelcp + '...', kksuffix='...' + swipercp;
    var origkkprefix='', origkksuffix='', origkprefix='', origksuffix='';
    if (kprefix == '' && ksuffix == '') {
    kprefix=swipel + '&#128309;..';
    kkprefix=swipelcp + String.fromCodePoint(128309) + '..';
    ksuffix='...' + swiper;
    //document.getElementById('doverlaytwo').style.marginTop='20px';
    } else if (kprefix == swipel + '&#128309;..') {
    kprefix=swipel + '.&#128309;.';
    kkprefix=swipelcp +'.' + String.fromCodePoint(128309) + '.';
    ksuffix='...' + swiper;
    } else if (kprefix == swipel + '.&#128309;.') {
    kprefix=swipel + '..&#128309;';
    kkprefix=swipelcp + '..' + String.fromCodePoint(128309) + '';
    ksuffix='...' + swiper;
    } else if (kprefix == swipel + '..&#128309;') {
    ksuffix='&#128309;..' + swiper;
    kksuffix=String.fromCodePoint(128309) + '..' + swipercp;
    kprefix=swipel + '...' + swiper;
    } else if (ksuffix == '&#128309;..' + swiper) {
    ksuffix='.&#128308;.' + swiper;
    kksuffix='.' + String.fromCodePoint(128308) + '.' + swipercp;
    kprefix=swipel + '...';
    } else if (ksuffix == '.&#128308;.' + swiper) {
    ksuffix='..&#128308;' + swiper;
    kksuffix='..' + String.fromCodePoint(128308) + '' + swipercp;
    kprefix=swipel + '...';
    } else {
    kprefix=swipel + '&#917536;..';
    kkprefix=swipelcp + '..' + String.fromCodePoint(917536) + '..';
    ksuffix='...' + swiper;
    //document.getElementById('doverlaytwo').style.marginTop='0px';
    }


    origkkprefix=kkprefix;
    origkksuffix=kksuffix;
    origkprefix=kprefix;
    origksuffix=ksuffix;



    if (oimstr) {
    origt=oimstr.getAttribute('data-title');
    if (lasto == oimstr) {
    kkprefix=origkkprefix;
    kksuffix=origkksuffix;
    kprefix=origkprefix;
    ksuffix=origksuffix;
    } else if (swipel + swiper != '') {
    kkprefix=origkkprefix.replace(swipelcp,'');
    kksuffix=origkksuffix.replace(swipercp,'');
    kprefix=origkprefix.replace(swipel,'');
    ksuffix=origksuffix.replace(swiper,'');
    }

    if (kimstr == 0) {
    oimstr.innerHTML=' ' + kprefix + aimstr[kimstr] + ksuffix;
    origrest=(origt.split('' + aimstr[kimstr])[1] + ',' + origt.split('' + aimstr[kimstr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    oimstr.title=kkprefix + aimstr[kimstr] + kksuffix + origrest;
    } else {
    oimstr.innerHTML=' ' + kprefix + aimstr[eval(-1 + kimstr)] + ksuffix;
    origrest=(origt.split('' + aimstr[eval(-1 + kimstr)])[1] + ',' + origt.split('' + aimstr[eval(-1 + kimstr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    oimstr.title=kkprefix + aimstr[eval(-1 + kimstr)] + kksuffix + origrest;
    }
    }
    if (opdstr) {
    origt=opdstr.getAttribute('data-title');
    if (lasto == opdstr) {
    kkprefix=origkkprefix;
    kksuffix=origkksuffix;
    kprefix=origkprefix;
    ksuffix=origksuffix;
    } else if (swipel + swiper != '') {
    kkprefix=origkkprefix.replace(swipelcp,'');
    kksuffix=origkksuffix.replace(swipercp,'');
    kprefix=origkprefix.replace(swipel,'');
    ksuffix=origksuffix.replace(swiper,'');
    }

    if (kpdstr == 0) {
    opdstr.innerHTML=' ' + kprefix + apdstr[kpdstr] + ksuffix;
    origrest=(origt.split('' + apdstr[kpdstr])[1] + ',' + origt.split('' + apdstr[kpdstr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    opdstr.title=kkprefix + apdstr[kpdstr] + kksuffix + origrest;
    } else {
    opdstr.innerHTML=' ' + kprefix + apdstr[eval(-1 + kpdstr)] + ksuffix;
    origrest=(origt.split('' + apdstr[eval(-1 + kpdstr)])[1] + ',' + origt.split('' + apdstr[eval(-1 + kpdstr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    opdstr.title=kkprefix + apdstr[eval(-1 + kpdstr)] + kksuffix + origrest;
    }
    }
    if (opastr) {
    origt=opastr.getAttribute('data-title');
    if (lasto == opastr) {
    kkprefix=origkkprefix;
    kksuffix=origkksuffix;
    kprefix=origkprefix;
    ksuffix=origksuffix;
    } else if (swipel + swiper != '') {
    kkprefix=origkkprefix.replace(swipelcp,'');
    kksuffix=origkksuffix.replace(swipercp,'');
    kprefix=origkprefix.replace(swipel,'');
    ksuffix=origksuffix.replace(swiper,'');
    }

    if (kpastr == 0) {
    opastr.innerHTML=' ' + kprefix + apastr[kpastr] + ksuffix;
    origrest=(origt.split('' + apastr[kpastr])[1] + ',' + origt.split('' + apastr[kpastr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    opastr.title=kkprefix + apastr[kpastr] + kksuffix + origrest;
    } else {
    opastr.innerHTML=' ' + kprefix + apastr[eval(-1 + kpastr)] + ksuffix;
    origrest=(origt.split('' + apastr[eval(-1 + kpastr)])[1] + ',' + origt.split('' + apastr[eval(-1 + kpastr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    opastr.title=kkprefix + apastr[eval(-1 + kpastr)] + kksuffix + origrest;
    }
    }
    if (offstr) {
    origt=offstr.getAttribute('data-title');
    if (lasto == offstr) {
    kkprefix=origkkprefix;
    kksuffix=origkksuffix;
    kprefix=origkprefix;
    ksuffix=origksuffix;
    } else if (swipel + swiper != '') {
    kkprefix=origkkprefix.replace(swipelcp,'');
    kksuffix=origkksuffix.replace(swipercp,'');
    kprefix=origkprefix.replace(swipel,'');
    ksuffix=origksuffix.replace(swiper,'');
    }

    if (kffstr == 0) {
    offstr.innerHTML=' ' + kprefix + affstr[kffstr] + ksuffix;
    origrest=(origt.split('' + affstr[kffstr])[1] + ',' + origt.split('' + affstr[kffstr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    offstr.title=kkprefix + affstr[kffstr] + kksuffix + origrest;
    } else {
    offstr.innerHTML=' ' + kprefix + affstr[eval(-1 + kffstr)] + ksuffix;
    origrest=(origt.split('' + affstr[eval(-1 + kffstr)])[1] + ',' + origt.split('' + affstr[eval(-1 + kffstr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
    offstr.title=kkprefix + affstr[eval(-1 + kffstr)] + kksuffix + origrest;
    }
    }
    kcnt++;
    swipel='';
    swipelcp='';
    swiper='';
    swipercp='';

    if (kcnt < 7) { setTimeout(betweeneatatjoes, 1000); }
    }

    “; ?>

… in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Hover Swipe Tutorial is shown below.

Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Hover Swipe Tutorial

Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Hover Swipe Tutorial

Some users are impatient, we grant you. Maybe some don’t want to wait the whole time of an 8 second “Eat at Joes” rotation. Well, we thought about this, and got an idea to extend yesterday’s Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Onhover Marquee Tutorial‘s non-mobile functionality via …

  • dropdown option (with animation) element onmouseover (hover swipe (maybe) in x,y) … call such as oimstr.onmouseover=function(event) { wasplace(oimstr, event); }; … uses …
    <?php echo ”

    var pos1=0, pos2=0, pos3=0, pos4=0, lasto=null;

    function wasplace(thiso, e) {
    e = e || window.event;
    e.preventDefault();
    if (e.touches) {
    if (e.touches[0].pageX) {
    pos1 = e.touches[0].pageX;
    pos2 = e.touches[0].pageY;
    } else {
    pos1 = e.touches[0].clientX;
    pos2 = e.touches[0].clientY;
    }
    //console.log('pos3=' + pos3 + ',pos4=' + pos4);
    } else if (e.clientX || e.clientY) {
    pos1 = e.clientX;
    pos2 = e.clientY;
    } else {
    pos1 = e.pageX;
    pos2 = e.pageY;
    }
    lasto=e.target;
    }

    “; ?>
    …and onmouseout (hover swipe out x,y) events … if deltax >= 70 … call such as oimstr.onmouseout=function(event) { isplace(oimstr, event); }; … uses …
    <?php echo ”

    function isplace(thiso, e) {
    var kkk=0;
    e = e || window.event;
    e.preventDefault();
    if (e.touches) {
    if (e.touches[0].pageX) {
    pos3 = e.touches[0].pageX;
    pos4 = e.touches[0].pageY;
    } else {
    pos3 = e.touches[0].clientX;
    pos4 = e.touches[0].clientY;
    }
    //console.log('pos3=' + pos3 + ',pos4=' + pos4);
    } else if (e.clientX || e.clientY) {
    pos3 = e.clientX;
    pos4 = e.clientY;
    } else {
    pos3 = e.pageX;
    pos4 = e.pageY;
    }
    if (lasto == e.target) {
    if (Math.abs(pos1 - pos3) >= 70) {
    if (pos3 > pos1) { // swipe right
    if (e.target == opastr) {
    kkk=eval(1 + eval('' + kpastr));
    if (kkk >= eval('' + apastr.length)) {
    kpastr=0;
    } else {
    kpastr=kkk;
    }
    } else if (e.target == opdstr) {
    kkk=eval(1 + eval('' + kpdstr));
    if (kkk >= eval('' + apdstr.length)) {
    kpdstr=0;
    } else {
    kpdstr=kkk;
    }
    } else if (e.target == oimstr) {
    kkk=eval(1 + eval('' + kimstr));
    if (kkk >= eval('' + aimstr.length)) {
    kimstr=0;
    } else {
    kimstr=kkk;
    }
    } else if (e.target == offstr) {
    kkk=eval(1 + eval('' + kffstr));
    if (kkk >= eval('' + affstr.length)) {
    kffstr=0;
    } else {
    kffstr=kkk;
    }
    }
    } else { // swipe left
    if (e.target == opastr) {
    kkk=eval(-1 + eval('' + kpastr));
    if (kkk < 0) {
    kpastr=eval(-1 + eval('' + apastr.length));
    } else {
    kpastr=kkk;
    }
    } else if (e.target == opdstr) {
    kkk=eval(-1 + eval('' + kpdstr));
    if (kkk < 0) {
    kpdstr=eval(-1 + eval('' + apdstr.length));
    } else {
    kpdstr=kkk;
    }
    } else if (e.target == oimstr) {
    kkk=eval(-1 + eval('' + kimstr));
    if (kkk < 0) {
    kimstr=eval(-1 + eval('' + aimstr.length));
    } else {
    kimstr=kkk;
    }
    } else if (e.target == offstr) {
    kkk=eval(-1 + eval('' + kffstr));
    if (kkk < 0) {
    kffstr=eval(-1 + eval('' + affstr.length));
    } else {
    kffstr=kkk;
    }
    }
    }
    }
    //alert('swipe distance = ' + Math.abs(pos1 - pos3));
    }
    lasto=e.target;
    }

    “; ?>
  • class a swipe right (if deltax > 0) else swipe left … resulting in …
  • immediately show next option innerText if swipe right and show previous option innerText if swipe left

… for you to try for yourself

Media and document action items … please note you can hover swipe right or left, accurately, and with panache, regarding animated options to speed up transitions between option values

… in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Onhover Marquee Tutorial is shown below.

Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Onhover Marquee Tutorial

Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Onhover Marquee Tutorial

The non-mobile platforms have that useful wooooorrrrllllddd, the “onhover wooooorrrrllllddd” (to be precise) that can be a great partner for Javascript Ajax methodologies. This onhover (actually the “onmouseover”) event is also useful whereby as a user hovers over an HTML element, and that element’s title attribute has a value, then the user can see that value displayed.

And though, with yesterday’s Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Emoji Tutorial work …

though we’re not going “full marquee Eat at Joes”

… regarding the dropdown option innerText “look”, there is, for non-mobile, this “onhover wooooorrrrllllddd” we can use to try a form of marquee “look” there, as per

<?php echo ”

function betweeneatatjoes() {
var origt='', origrest='', kkprefix='...', kksuffix='...';
if (kprefix == '' && ksuffix == '') {
kprefix='&#128309;..';
kkprefix=String.fromCodePoint(128309) + '..';
ksuffix='...';
//document.getElementById('doverlaytwo').style.marginTop='20px';
} else if (kprefix == '&#128309;..') {
kprefix='.&#128309;.';
kkprefix='.' + String.fromCodePoint(128309) + '.';
ksuffix='...';
} else if (kprefix == '.&#128309;.') {
kprefix='..&#128309;';
kkprefix='..' + String.fromCodePoint(128309) + '';
ksuffix='...';
} else if (kprefix == '..&#128309;') {
ksuffix='&#128309;..';
kksuffix=String.fromCodePoint(128309) + '..';
kprefix='...';
} else if (ksuffix == '&#128309;..') {
ksuffix='.&#128308;.';
kksuffix='.' + String.fromCodePoint(128308) + '.';
kprefix='...';
} else if (ksuffix == '.&#128308;.') {
ksuffix='..&#128308;';
kksuffix='..' + String.fromCodePoint(128308) + '';
kprefix='...';
} else {
kprefix='&#917536;..';
kkprefix='..' + String.fromCodePoint(917536) + '..';
ksuffix='...';
//document.getElementById('doverlaytwo').style.marginTop='0px';
}
if (oimstr) {
origt=oimstr.getAttribute('data-title');
if (kimstr == 0) {
oimstr.innerHTML=' ' + kprefix + aimstr[kimstr] + ksuffix;
origrest=(origt.split('' + aimstr[kimstr])[1] + ',' + origt.split('' + aimstr[kimstr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
oimstr.title=kkprefix + aimstr[kimstr] + kksuffix + origrest;

} else {
oimstr.innerHTML=' ' + kprefix + aimstr[eval(-1 + kimstr)] + ksuffix;
origrest=(origt.split('' + aimstr[eval(-1 + kimstr)])[1] + ',' + origt.split('' + aimstr[eval(-1 + kimstr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
oimstr.title=kkprefix + aimstr[eval(-1 + kimstr)] + kksuffix + origrest;

}
}
if (opdstr) {
origt=opdstr.getAttribute('data-title');
if (kpdstr == 0) {
opdstr.innerHTML=' ' + kprefix + apdstr[kpdstr] + ksuffix;
origrest=(origt.split('' + apdstr[kpdstr])[1] + ',' + origt.split('' + apdstr[kpdstr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
opdstr.title=kkprefix + apdstr[kpdstr] + kksuffix + origrest;

} else {
opdstr.innerHTML=' ' + kprefix + apdstr[eval(-1 + kpdstr)] + ksuffix;
origrest=(origt.split('' + apdstr[eval(-1 + kpdstr)])[1] + ',' + origt.split('' + apdstr[eval(-1 + kpdstr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
opdstr.title=kkprefix + apdstr[eval(-1 + kpdstr)] + kksuffix + origrest;

}
}
if (opastr) {
origt=opastr.getAttribute('data-title');
if (kpastr == 0) {
opastr.innerHTML=' ' + kprefix + apastr[kpastr] + ksuffix;
origrest=(origt.split('' + apastr[kpastr])[1] + ',' + origt.split('' + apastr[kpastr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
opastr.title=kkprefix + apastr[kpastr] + kksuffix + origrest;

} else {
opastr.innerHTML=' ' + kprefix + apastr[eval(-1 + kpastr)] + ksuffix;
origrest=(origt.split('' + apastr[eval(-1 + kpastr)])[1] + ',' + origt.split('' + apastr[eval(-1 + kpastr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
opastr.title=kkprefix + apastr[eval(-1 + kpastr)] + kksuffix + origrest;

}
}
if (offstr) {
origt=offstr.getAttribute('data-title');
if (kffstr == 0) {
offstr.innerHTML=' ' + kprefix + affstr[kffstr] + ksuffix;
origrest=(origt.split('' + affstr[kffstr])[1] + ',' + origt.split('' + affstr[kffstr])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
offstr.title=kkprefix + affstr[kffstr] + kksuffix + origrest;

} else {
offstr.innerHTML=' ' + kprefix + affstr[eval(-1 + kffstr)] + ksuffix;
origrest=(origt.split('' + affstr[eval(-1 + kffstr)])[1] + ',' + origt.split('' + affstr[eval(-1 + kffstr)])[0]).trim().replace(/\,\,/g,'').replace('undefined','');
offstr.title=kkprefix + affstr[eval(-1 + kffstr)] + kksuffix + origrest;

}
}
kcnt++;
if (kcnt < 7) { setTimeout(betweeneatatjoes, 1000); }
}

“; ?>

Proof positive that emojis are text, and can help provide a graphic display interest for a webpage. As well, as a CSS means by which we stop “dropdown Y jitteriness”, we introduce the use of an emoji ⚪ (&#9898; or &#x26aa;) for most option element Clayton innerText parts, always …


<style>
option:not(.nonwhite)::before {
content: '\0026aa';
}


#doverlay {
background-color: #FFE7E9;
}


#doverlaytwo {
background-color: #FFE7E9;
}


body {
background-color: #FFFFEF;
}
</style>

“; ?>

… with one more media functionality

<?php

var mlook=false, kcnt=0, kprefix='', ksuffix='';
var imstr=' Images to PDF, Images to GIF,', oimstr=null, kimstr=0, aimstr=[];
var pdstr=' PDF to Images, PDF to HTML, PDF to XML,', opdstr=null, kpdstr=0, apdstr=[];
var pastr=' Text to HTML, Text to Rich Text, Text to Word,', opastr=null, kpastr=0, apastr=[];
var ffstr=' Concat demuxer, Display the frame number on each frame,', offstr=null, kffstr=0, affstr=[];

?>

… in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Emoji Tutorial is shown below.

Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Emoji Tutorial

Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Emoji Tutorial

The “dropdown animations” introduced into yesterday’s Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Dropdown Tutorial were a tad subtle, it only involving …

  • the wording of option elements within the dropdown … and though we’re not going “full marquee Eat at Joes” we are accentuating “midway”, today, by …
  • adding emoji 🔵 (&#128309;) movement to the animation for interest sake, as well as being informative (in that the user can anticipate when the new innerText text will arrive, as the emoji moves from left to right)

… that we team with more instances of multiple animation settings …

<?php echo ”

var mlook=false, kcnt=0, kprefix='', ksuffix='';
var imstr=' Images to PDF, Images to GIF,', oimstr=null, kimstr=0, aimstr=[];
var pdstr=' PDF to Images, PDF to HTML, PDF to XML,', opdstr=null, kpdstr=0, apdstr=[];
var pastr=' Text to HTML, Text to Rich Text, Text to Word,', opastr=null, kpastr=0, apastr=[];
var ffstr=' Concat demuxer, ', offstr=null, kffstr=0, affstr=[];

“; ?>

… and a new “between the 8 second setInterval wording refreshes” Javascript function

<?php echo ”

function betweeneatatjoes() {
if (kprefix == '' && ksuffix == '') {
kprefix='&#128309;..';
ksuffix='...';
document.getElementById('doverlaytwo').style.marginTop='20px';
} else if (kprefix == '&#128309;..') {
kprefix='.&#128309;.';
ksuffix='...';
} else if (kprefix == '.&#128309;.') {
kprefix='..&#128309;';
ksuffix='...';
} else if (kprefix == '..&#128309;') {
ksuffix='&#128309;..';
kprefix='...';
} else if (ksuffix == '&#128309;..') {
ksuffix='.&#128309;.';
kprefix='...';
} else if (ksuffix == '.&#128309;.') {
ksuffix='..&#128309;';
kprefix='...';
} else {
kprefix='...';
ksuffix='...';
document.getElementById('doverlaytwo').style.marginTop='0px';
}
if (oimstr) {
if (kimstr == 0) {
oimstr.innerHTML=' ' + kprefix + aimstr[kimstr] + ksuffix;
} else {
oimstr.innerHTML=' ' + kprefix + aimstr[eval(-1 + kimstr)] + ksuffix;
}
}
if (opdstr) {
if (kpdstr == 0) {
opdstr.innerHTML=' ' + kprefix + apdstr[kpdstr] + ksuffix;
} else {
opdstr.innerHTML=' ' + kprefix + apdstr[eval(-1 + kpdstr)] + ksuffix;
}
}
if (opastr) {
if (kpastr == 0) {
opastr.innerHTML=' ' + kprefix + apastr[kpastr] + ksuffix;
} else {
opastr.innerHTML=' ' + kprefix + apastr[eval(-1 + kpastr)] + ksuffix;
}
}
if (offstr) {
if (kffstr == 0) {
offstr.innerHTML=' ' + kprefix + affstr[kffstr] + ksuffix;
} else {
offstr.innerHTML=' ' + kprefix + affstr[kffstr] + ksuffix;
}
}
kcnt++;
if (kcnt < 7) { setTimeout(betweeneatatjoes, 1000); }
}



function eatatjoes() {
kcnt=0;
kprefix='';
ksuffix='';
document.getElementById('doverlaytwo').style.marginTop='0px';

if (oimstr) {
if (kimstr >= eval('' + aimstr.length)) {
kimstr=0;
oimstr.innerHTML=' ' + aimstr[kimstr];
} else {
oimstr.innerHTML=' ' + aimstr[kimstr];
kimstr++;
}
}
if (opdstr) {
if (kpdstr >= eval('' + apdstr.length)) {
kpdstr=0;
opdstr.innerHTML=' ' + apdstr[kpdstr];
} else {
opdstr.innerHTML=' ' + apdstr[kpdstr];
kpdstr++;
}
}
if (opastr) {
//alert(apastr.length);
if (kpastr >= eval('' + apastr.length)) {
kpastr=0;
opastr.innerHTML=' ' + apastr[kpastr];
} else {
opastr.innerHTML=' ' + apastr[kpastr];
kpastr++;
}
}
if (offstr) {
if (kffstr >= eval('' + affstr.length)) {
kffstr=0;
offstr.innerHTML=' ' + affstr[kffstr];
} else {
offstr.innerHTML=' ' + affstr[kffstr];
kffstr++;
}
}
setTimeout(betweeneatatjoes, 1000);
}


function andthen(iidea) {
var outidea=iidea;
var fndpos=-1;
var optsare=document.getElementsByTagName('option'), ioptsare=0;
var iimstr=(imstr.indexOf(',') == -1 ? -1 : outidea.indexOf(imstr.split(',')[0].trim() + ','));
mlook=false;
if (iimstr != -1) {
if ((imstr.split(',')[0].trim() + ',') != imstr.trim()) {
if (document.getElementById('oimagemagick')) {
oimstr=document.getElementById('oimagemagick');
mlook=true;
aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == imstr.split(',')[0].trim()) {
oimstr=optsare[ioptsare];
mlook=true;
aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(imstr.split(',')[0].trim(), imstr.split(',')[0].trim() + '' + (imstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var ipdstr=(pdstr.indexOf(',') == -1 ? -1 : outidea.indexOf(pdstr.split(',')[0].trim() + ','));
if (ipdstr != -1) {
if ((pdstr.split(',')[0].trim() + ',') != pdstr.trim()) {
if (document.getElementById('opdfimages')) {
opdstr=document.getElementById('opdfimages');
mlook=true;
apdstr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == pdstr.split(',')[0].trim()) {
opdstr=optsare[ioptsare];
mlook=true;
apdstr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(pdstr.split(',')[0].trim(), pdstr.split(',')[0].trim() + '' + (pdstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var ipastr=(pastr.indexOf(',') == -1 ? -1 : outidea.indexOf(pastr.split(',')[0].trim() + ','));
if (ipastr != -1) {
if ((pastr.split(',')[0].trim() + ',') != pastr.trim()) {
if (document.getElementById('opandoc')) {
opastr=document.getElementById('opandoc');
mlook=true;
apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == pastr.split(',')[0].trim()) {
opastr=optsare[ioptsare];
mlook=true;
apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(pastr.split(',')[0].trim(), pastr.split(',')[0].trim() + '' + (pastr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var iffstr=(ffstr.indexOf(',') == -1 ? -1 : outidea.indexOf(ffstr.split(',')[0].trim() + ','));
if (iffstr != -1) {
if ((ffstr.split(',')[0].trim() + ',') != ffstr.trim()) {
if (document.getElementById('offmpeg')) {
offstr=document.getElementById('offmpeg');
mlook=true;
affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == ffstr.split(',')[0].trim()) {
offstr=optsare[ioptsare];
mlook=true;
affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(ffstr.split(',')[0].trim(), ffstr.split(',')[0].trim() + '' + (ffstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
if (mlook) { setInterval(eatatjoes, 8000); }
return outidea;
}

“; ?>

… helped out via the original setInterval Javascript “eatatjoes” function (all kicked off via modified document.body onload logic
document.getElementById(‘mainspan’).title = andthen(document.getElementById(‘schoices’).innerText.replace(/\&nbsp\;/g,’ ‘).replace(/\ \ /g,’, ‘));
), as modified, above.

You can see this in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Dropdown Tutorial is shown below.

Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Dropdown Tutorial

Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Dropdown Tutorial

Lemon curry?! Animated dropdown?! What gives? Well, it’s not “shelling peas”, yet!

Yes, there is another “framework” step forward we wanted to implement before the peas. And yes, no surprises there, the “framework” work relates to adding functionality to our main dropdown. We’re adding a layer of functionality we’re going to refer to as “animated dropdown”. It amounts to …

  • dropdown (ie. select element) … for non-mobile …
  • has size attribute equal to the number of option elements it contains
  • logic wise, because our non-nothing option innerTexts have equalled option values (if you Javascript trim() the option innerText, that is), we have the opportunity to start taking more notice of the …
    <?php echo ”

    function process(tv, tvo) {
    var newval='';
    var ourtv=tvo.value;
    if (tv != '') {
    ourtv=tvo.options[tvo.selectedIndex].innerText.trim();
    }

    if (origval == '') { origval=document.getElementById('mydefopt').title; }
    if (tv == '') {
    document.getElementById('mainspan').innerHTML=document.getElementById('mydefopt').title;
    } else {
    document.getElementById('mydefopt').title=ourtv; //tv;
    document.getElementById('mainspan').innerHTML=document.getElementById('mydefopt').title;
    document.getElementById('schoices').value='';
    }
    newval=document.getElementById('mydefopt').title;
    //alert('origval,newval=' + origval + ' ' + newval);
    if (newval != origval) {
    origval=newval;
    wentfrom(origval, newval);
    } else {
    origval=newval;
    }
    }

    “; ?>
    … option innerHTML as above, meaning …
  • we can set up Javascript code facilitating the animated feel of some option innerHTML looks that are taken notice of as selected via …
    Global variables arranged via each “verb” involved … for today’s “proof of concept” we add one extra Pandoc “Text to Rich Text” option, for now, before the flood of peas arrives …
    <?php echo ”

    var mlook=false;
    var imstr=' Images to PDF, ', oimstr=null, kimstr=0, aimstr=[];
    var pdstr=' PDF to Images, ', opdstr=null, kpdstr=0, apdstr=[];
    var pastr=' Text to HTML, Text to Rich Text,', opastr=null, kpastr=0, apastr=[];
    var ffstr=' Concat demuxer, ', offstr=null, kffstr=0, affstr=[];

    “; ?>
    As heading title is determined at document.body onload document.getElementById(‘mainspan’).title=andthen(document.getElementById(‘schoices’).innerText.replace(/\&nbsp\;/g,’ ‘).replace(/\ \ /g,’, ‘));
    <?php echo ”

    function andthen(iidea) {
    var outidea=iidea;
    var fndpos=-1;
    var optsare=document.getElementsByTagName('option'), ioptsare=0;
    var iimstr=(imstr.indexOf(',') == -1 ? -1 : outidea.indexOf(imstr.split(',')[0].trim() + ','));
    mlook=false;
    if (iimstr != -1) {
    if ((imstr.split(',')[0].trim() + ',') != imstr.trim()) {
    if (document.getElementById('oimagemagick')) {
    oimstr=document.getElementById('oimagemagick');
    mlook=true;
    aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    } else {
    for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
    if (optsare[ioptsare].value == imstr.split(',')[0].trim()) {
    oimstr=optsare[ioptsare];
    mlook=true;
    aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    }
    }
    }
    outidea=outidea.replace(imstr.split(',')[0].trim(), imstr.split(',')[0].trim() + '' + (imstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
    }
    }
    var ipdstr=(pdstr.indexOf(',') == -1 ? -1 : outidea.indexOf(pdstr.split(',')[0].trim() + ','));
    if (ipdstr != -1) {
    if ((pdstr.split(',')[0].trim() + ',') != pdstr.trim()) {
    if (document.getElementById('opdfimages')) {
    opdstr=document.getElementById('opdfimages');
    mlook=true;
    aipdtr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    } else {
    for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
    if (optsare[ioptsare].value == pdstr.split(',')[0].trim()) {
    opdstr=optsare[ioptsare];
    mlook=true;
    apdstr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    }
    }
    }
    outidea=outidea.replace(pdstr.split(',')[0].trim(), pdstr.split(',')[0].trim() + '' + (pdstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
    }
    }
    var ipastr=(pastr.indexOf(',') == -1 ? -1 : outidea.indexOf(pastr.split(',')[0].trim() + ','));
    if (ipastr != -1) {
    if ((pastr.split(',')[0].trim() + ',') != pastr.trim()) {
    if (document.getElementById('opandoc')) {
    opastr=document.getElementById('opandoc');
    mlook=true;
    apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    } else {
    for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
    if (optsare[ioptsare].value == pastr.split(',')[0].trim()) {
    opastr=optsare[ioptsare];
    mlook=true;
    apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    }
    }
    }
    outidea=outidea.replace(pastr.split(',')[0].trim(), pastr.split(',')[0].trim() + '' + (pastr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
    }
    }
    var iffstr=(ffstr.indexOf(',') == -1 ? -1 : outidea.indexOf(ffstr.split(',')[0].trim() + ','));
    if (iffstr != -1) {
    if ((ffstr.split(',')[0].trim() + ',') != ffstr.trim()) {
    if (document.getElementById('offmpeg')) {
    offstr=document.getElementById('offmpeg');
    mlook=true;
    affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    } else {
    for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
    if (optsare[ioptsare].value == ffstr.split(',')[0].trim()) {
    offstr=optsare[ioptsare];
    mlook=true;
    affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
    }
    }
    }
    outidea=outidea.replace(ffstr.split(',')[0].trim(), ffstr.split(',')[0].trim() + '' + (ffstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
    }
    }
    if (mlook) { setInterval(eatatjoes, 8000); }
    return outidea;
    }

    “; ?>
    … the appeal of all this being that the dropdown height can be controlled by swapping animation for height extension (and user experience downgrades)
    Animated dropdown setInterval Javascript function (bit like marquee Eat at Joes type of animation (we’ll see if it gets more like it into the future, perhaps?)) …
    <?php echo ”

    function eatatjoes() {
    if (oimstr) {
    if (kimstr >= eval('' + aimstr.length)) {
    kimstr=0;
    oimstr.innerHTML=' ' + aimstr[kimstr];
    } else {
    oimstr.innerHTML=' ' + aimstr[kimstr];
    kimstr++;
    }
    }
    if (opdstr) {
    if (kpdstr >= eval('' + apdstr.length)) {
    kpdstr=0;
    opdstr.innerHTML=' ' + apdstr[kpdstr];
    } else {
    opdstr.innerHTML=' ' + apdstr[kpdstr];
    kpdstr++;
    }
    }
    if (opastr) {
    if (kpastr >= eval('' + apastr.length)) {
    kpastr=0;
    opastr.innerHTML=' ' + apastr[kpastr];
    } else {
    opastr.innerHTML=' ' + apastr[kpastr];
    kpastr++;
    }
    }
    if (offstr) {
    if (kffstr >= eval('' + affstr.length)) {
    kffstr=0;
    offstr.innerHTML=' ' + affstr[kffstr];
    } else {
    offstr.innerHTML=' ' + affstr[kffstr];
    kffstr++;
    }
    }
    }

    “; ?>

… onto yesterday’s Ffmpeg and Pandoc and ImageMagick and Pdfimages Media Tutorial in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg and Pandoc and ImageMagick and Pdfimages Media Tutorial is shown below.

Ffmpeg and Pandoc and ImageMagick and Pdfimages Media Tutorial

Ffmpeg and Pandoc and ImageMagick and Pdfimages Media Tutorial

Onto yesterday’s Ffmpeg and ImageMagick and Pdfimages Media Tutorial

  • ffmpeg … two more media manipulation “verb” stars today …
  • ImageMagick (can help us with new “Images to PDF” option)
  • pdfimages (can help us with new “PDF to Images” option) … “verb” collection, today, we wanted to add …
  • pandoc (can help us with new “Text to HTML” option) …

    If you need to convert files from one markup format into another, pandoc is your swiss-army knife.

… to help improve the “one stop shop” aspects, especially regarding “documents”, to our current Intranet feeling web application in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg and ImageMagick and Pdfimages Media Tutorial is shown below.

Ffmpeg and ImageMagick and Pdfimages Media Tutorial

Ffmpeg and ImageMagick and Pdfimages Media Tutorial

Yesterday’s Ffmpeg Rotate Video Tutorial left you with …

We now present those four in “an expanded out” (at least on non-mobile) dropdown HTML element. Maybe you can guess why?

… and today we are deploying the framework parts and two new media manipulation options regarding PDF that add to our PHP web application’s functionality.

Operating system commands can be thought of to start with …

  • an action item (to be precise a desktop software file specification) … and, what we often think is, like …
  • the command’s “verb” part (as funny as that is to think of a “noun” sounding desktop software file specification being like a “verb”) … verbs being action items in a sentence … down to being essential in any sentence … to the point a “verb” can be the whole sentence

We want to add functionality by adding to our first “verb” …

  • ffmpeg … two more media manipulation “verb” stars today …
  • ImageMagick (can help us with new “Images to PDF” option)
  • pdfimages (can help us with new “PDF to Images” option)

… and to help the “framework” ahead of “shelling peas” we lean on the experience we got from the Animated GIF Creation on Windows MAMP via PDF Tutorial thread of blog postings to deal with …

  • software paths
  • presenting two new “verb” ideas … and us being so fond of dropdowns, we decided to try, for our first time …
    1. start to use three HTML option CSS text-align style choices being left (for ffmpeg), center (for ImageMagick) and right (for pdfimages) … as in …

      … within …

      Add Voiceover Audio to Video via ffmpeg  pdfimages



      <select size=7 onchange=process(this.value,this); style=display:inline-block;font-size:8px; id=schoices><option style=text-align:center; id=mydefopt title='Add Voiceover Audio to Video' value=''>&#10549; Image&#11015;Magick &#10550;</option><option value='Add Voiceover Audio to Video'> Add Voiceover Audio to Video </option><option style='text-align:center;' value='Images to PDF'> Images to PDF</option><option style='text-align:right;' value='PDF to Images'> PDF to Images</option><option value='Burn subtitles'> Burn subtitles</option><option value='Concat demuxer'> Concat demuxer</option><option value='Rotate a video'> Rotate a video</option></select>

      … and then in order to offer the “center” ImageMagick be a link back to the product we introduce some new overlay code
      <?php echo ”

      function overlay() {
      origval=document.getElementById('schoices').value;
      var rect=document.getElementById('fcommand').getBoundingClientRect();
      document.getElementById('moreb').style.position='absolute';
      document.getElementById('moreb').style.left='' + rect.left + 'px';
      document.getElementById('moreb').style.top='' + rect.top + 'px';
      document.getElementById('moreb').style.width='96%'; //' + rect.width + 'px';
      document.getElementById('moreb').style.height='' + rect.height + 'px';
      document.getElementById('moreb').style.border='1px solid black';
      document.getElementById('moreb').style.paddingLeft='20px';
      document.getElementById('moreb').style.backgroundColor='#f9f9f9';
      document.getElementById('fcommand').style.opacity='0.0';
      document.getElementById('fcommand').style.cursor='pointer';
      document.getElementById('moreb').innerHTML='<span id=precmds></span><span id=verb>ffmpeg" . $ffmpegsuf . "</span> <span id=prescbi></span><span id=minusi> -i </span><span id=scbi><iframe onload=checkif(this,\"inv.mp4\"); scrolling=no frameborder=0 id=cbi data-type=file data-value=inv.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:92px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=69075964842271&left=y\"></iframe></span> <span id=betweenis></span> <span id=secondi>-i <span id=scbix><iframe onload=checkiftwo(this,\"inva.mp4\"); scrolling=no frameborder=0 id=cbix data-type=file data-value=inva.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:106px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=69075964842271&right=y\"></iframe></span></span> <span id=sswitches>-c copy -map 0:v:0 -map 1:a:0 -shortest</span> out.mp4 > <a target=_blank title=ffimpdf.bad onclick=getvb(); style=cursor:pointer;text-decoration:underline; data-href=./ffimpdf.bad>ffimpdf.bad</a>';
      if (firstdivih == '') { firstdivih=document.getElementById('moreb').innerHTML; }
      if (firstbutval == '') { firstbutval=document.getElementById('mysub').value; }
      document.getElementById('schoices').style.display='inline-block';


      rect=document.getElementById('schoices').getBoundingClientRect();


      if (eval('' + rect.height) > 100 || 1 == 1) {
      document.getElementById('doverlay').style.position='absolute';
      document.getElementById('doverlay').style.left='' + rect.left + 'px';
      document.getElementById('doverlay').style.top='' + rect.top + 'px';
      document.getElementById('doverlay').style.width='' + rect.width + 'px';
      if (eval('' + rect.height) < 30) {
      document.getElementById('doverlay').style.height='' + rect.height + 'px';
      } else {
      document.getElementById('doverlay').style.height='' + eval(eval('' + rect.height) / eval('' + document.getElementById('schoices').size)) + 'px';
      }
      document.getElementById('doverlay').style.zIndex='96';
      document.getElementById('doverlay').style.textAlign='center';
      document.getElementById('doverlay').style.display='block';
      document.getElementById('doverlay').title=document.getElementById('mydefopt').title;
      //document.getElementById('mydefopt').style.fontColor='transparent';
      document.getElementById('mydefopt').innerHTML='';
      setInterval(fhoc, 1000);
      }



      }


      function fhoc() {
      var rectx=document.getElementById('schoices').getBoundingClientRect();
      document.getElementById('doverlay').style.left='' + rectx.left + 'px';
      document.getElementById('doverlay').title=document.getElementById('mydefopt').title;
      if (document.getElementById('scbi')) {
      if (document.getElementById('scbi').innerHTML.indexOf('<') == -1) {
      if (document.getElementById('scbi').innerHTML.trim().indexOf(' ') != -1) {
      if (document.getElementById('scbi').innerHTML.trim().indexOf(String.fromCharCode(34)) == -1) {
      document.getElementById('scbi').innerHTML=String.fromCharCode(34) + document.getElementById('scbi').innerHTML.trim() + String.fromCharCode(34);
      }
      }
      }
      }
      if (document.getElementById('scbix')) {
      if (document.getElementById('scbix').innerHTML.indexOf('<') == -1) {
      if (document.getElementById('scbix').innerHTML.trim().indexOf(' ') != -1) {
      if (document.getElementById('scbix').innerHTML.trim().indexOf(String.fromCharCode(34)) == -1) {
      document.getElementById('scbix').innerHTML=String.fromCharCode(34) + document.getElementById('scbix').innerHTML.trim() + String.fromCharCode(34);
      }
      }
      }
      }
      }


      “; ?>

  • Javascript to set up the HTML div contenteditable=true look for these two new options …
    <?php echo ”

    if (newv == 'PDF to Images') {
    document.getElementById('moreb').innerHTML=firstdivih.replace(' out.mp4',' " . $minuspng . "');
    document.getElementById('secondi').innerHTML='';
    document.getElementById('sswitches').innerHTML=\"<span id=sfolder contenteditable=false>newfolder_" . rand(0,784534) . str_replace("\\","\\\\",$ddn) . "\" + '</span>ideas';

    document.getElementById('precmds').innerHTML=' ';
    document.getElementById('verb').innerHTML='" . $pdfimages . $pdfimagessuf . "';
    document.getElementById('scbi').innerHTML=document.getElementById('scbi').innerHTML.replace(/inv\.mp4/g,'inv.pdf ');
    document.getElementById('minusi').innerHTML=' -j ';

    document.getElementById('mysub').value=newv;
    } else if (newv == 'Images to PDF') {
    document.getElementById('moreb').innerHTML=firstdivih.replace('out.mp4','out.pdf');

    document.getElementById('precmds').innerHTML=' ';
    document.getElementById('secondi').innerHTML='';
    document.getElementById('verb').innerHTML='" . $magickverb . $magicksuf . "';
    document.getElementById('sswitches').innerHTML='-auto-orient';
    document.getElementById('sswitches').title='To perform a folder of images (only, we suggest) right click or two finger guesture to left and enter the folder name only';
    document.getElementById('scbi').innerHTML=document.getElementById('scbi').innerHTML.replace(/inv\.mp4/g,'inv.jpg ');
    document.getElementById('minusi').innerHTML='';
    document.getElementById('scbi').setAttribute('contenteditable', true);
    document.getElementById('scbi').onblur=function(event) { if (document.getElementById('mydefopt').title == 'Images to PDF') { if (event.target.innerHTML.replace(/\ \;/g,' ').trim() == '') { event.target.innerHTML='folder' + \"" . str_replace("\\","\\\\",$ddn) . "*\"; } if (event.target.innerHTML.toLowerCase().indexOf('.txt') == -1) { if (event.target.innerHTML.indexOf('.') != -1) { document.getElementById('ifs').innerHTML+='<iframe id=voaskfor' + ifile + ' style=display:none; src=\"./voiceover.php?infilegetsize=' + encodeURIComponent(listtxt + ';' + event.target.innerHTML) + '\"></iframe>'; ifile++; if (document.getElementById('moreb').title.indexOf(\"file '\" + event.target.innerHTML.replace(String.fromCharCode(34),'').replace(String.fromCharCode(34),'') + \"'\") == -1) { document.getElementById('moreb').title+=String.fromCharCode(10) + \"file '\" + event.target.innerHTML.replace(String.fromCharCode(34),'').replace(String.fromCharCode(34),'') + \"'\"; } } } event.target.innerHTML=listtxt; if (document.getElementById('minusi')) { document.getElementById('minusi').innerHTML=''; } } };
    document.getElementById('moreb').onblur=function(event) { if (document.getElementById('mydefopt').title == 'Images to PDF') { if (document.getElementById('minusi')) { var thingos=document.getElementById('minusi').innerHTML.replace(/\ \;/g,' ').trim().split('-i '); if (thingos.length > 1) { if (thingos[1].trim() != '' && (thingos[1] + '~').toLowerCase().indexOf('.txt~') == -1) { spanfill(thingos[1]); } } document.getElementById('minusi').innerHTML=''; } if (!document.getElementById('scbi')) { event.target.innerHTML=event.target.innerHTML.replace('<span id=\"between', '<span id=scbi contenteditable=true>' + listtxt + '</span> <span id=\"between'); putbackonblur(); if (event.target.innerHTML.indexOf('> -i </span><span id=\"scbi\"') == -1) { event.target.innerHTML=event.target.innerHTML.replace('</span>' + event.target.innerHTML.split('<span id=\"scbi\"')[0].split('</span>')[-1 + eval(event.target.innerHTML.split('<span id=\"scbi\"')[0].split('</span>').length)],'</span>'); } } } };
    document.getElementById('moreb').oncontextmenu=function(event) { document.getElementById('scbi').innerHTML='folder' + \"" . str_replace("\\","\\\\",$ddn) . "*\"; };


    document.getElementById('mysub').value=newv;
    }

    “; ?>
  • the performing of those two new “verb” ideas …
    <?php

    $pfolder='';
    $ppdf='';

    // ... later ...
    $cmdis=str_replace('+',' ',urldecode($_GET['fcommand']));
    if (PHP_OS =='WINNT' || PHP_OS =='WIN32' || PHP_OS =='Windows') {
    if ($ffmpegpre != '' && strpos($cmdis, 'ffmpeg.') !== false && strpos($cmdis, $ffmpegpre) === false) {
    $cmdis=str_replace('ffmpeg.', $ffmpegpre . 'ffmpeg.', $cmdis);
    }
    if ($magickpre != '' && strpos($cmdis, $magickverb . '.') !== false && strpos($cmdis, $magickpre) === false) {
    $cmdis=str_replace($magickverb . '.', $magickpre . $magickverb . '.', $cmdis);
    }
    if ($pdfimagespre != '' && strpos($cmdis, 'pdfimages.') !== false && strpos($cmdis, $pdfimagespre) === false) {
    $cmdis=str_replace('pdfimages.', $pdfimagespre . 'pdfimages.', $cmdis);
    }
    }

    $precmd=explode('>', $cmdis);
    if (strpos($cmdis, 'pdfimages') !== false && strpos($cmdis, 'newfolder_') !== false) {
    $pfolder='newfolder_' . explode(DIRECTORY_SEPARATOR, explode('newfolder_', $cmdis)[1])[0];
    $beforep=explode($pfolder, $cmdis)[0];
    $afterp=explode($pfolder, $cmdis)[1];
    while (file_exists($pfolder)) {
    $pfolder='newfolder' . '_' . explode('newfolder', $pfolder)[1];
    $cmdis=$beforep . $pfolder . $afterp;
    }
    if (!file_exists($pfolder)) { mkdir($pfolder); }
    }

    // ... later ...
    $outf=$subcmd[1];
    // ... later ...
    if (strpos(strtolower(trim($outf) . '~'), '.pdf~') !== false) {
    $ppdf=trim($outf);
    }

    // ... later ...
    $rs=shell_exec($cmdis);

    // ... later ...
    if ($pfolder != '') {
    $rs.="<br><br>";
    foreach (glob($pfolder . DIRECTORY_SEPARATOR . '*.*') as $ifilename) {
    $rs.='<img title="' . $ifilename . '" src="' . $ifilename . '?rand=' . rand(0,7654532) . '"></img>';
    }
    }
    if ($ppdf != '') {
    $outf='';
    $rs.="<br><br><iframe style='width:98%;height:800px;' src='" . $ppdf . "?rand=" . rand(0,7654532) . "' title='" . $ppdf . "'></iframe>";
    }

    ?>

… in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg Rotate Video Tutorial is shown below.

Ffmpeg Rotate Video Tutorial

Ffmpeg Rotate Video Tutorial

It’s getting closer to “shelling peas”, are today’s “Rotate a video via ffmpeg” changes, but we are not there yet. Yes, most programmers want to be “shelling peas” adding functionality to web applications, once they have set up a framework in which they are happy to work. Yesterday’s Ffmpeg Concat Demuxer Tutorial “defence talk” is getting us closer to that “shelling peas” “homeostasis feel” (with an “Intranet” pike, no doubt?!) as you can see from a Javascript “Rotate a video” code snippet below …

<?php echo ”

if (newv == 'Rotate a video') {
document.getElementById('moreb').innerHTML=firstdivih;

document.getElementById('precmds').innerHTML=' ';
document.getElementById('secondi').innerHTML='';


document.getElementById('sswitches').innerHTML='<span id=notranspose contenteditable=false>-vf \"transpose=</span><span id=transpose contenteditable=true>1</span><span id=nottranspose contenteditable=false>\" </span>';
document.getElementById('sswitches').title='" . str_replace("\n", "' + String.fromCharCode(10) + '",$rotateadvice) . "';
document.getElementById('sswitches').oncontextmenu=function(event) { alert(event.target.title); };

document.getElementById('mysub').value=newv;
}

“; ?>

… effectively straightjacketing the crucial …


-vf "transpose=1"

… ffmpeg switch definition, by the user, to changing that 1 above as per the hover over advice, to help the user, straight from Mux Video and Audio from another Video, thanks, to advise …

<?php

$rotateadvice="Rotate a video

Rotate 90 clockwise:

ffmpeg -i in.mov -vf \"transpose=1\" out.mov
For the transpose parameter you can pass:

0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip

Use -vf \"transpose=2,transpose=2\" for 180 degrees.";

?>

Yes, the user can still put a bad entry there, but at least the web application has attempted to point them in the right direction, here.

If you examine the changes the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there), am sure that you will concur

  • Concat demuxer concatenation of videos ffmpeg functionality, onto the “as of yesterday” …
  • Voiceovers … and …
  • Burn subtitles
  • Rotate a video

… was the simplest functionality component, yet, of the four. We now present those four in “an expanded out” (at least on non-mobile) dropdown HTML element. Maybe you can guess why?


Previous relevant Ffmpeg Concat Demuxer Tutorial is shown below.

Ffmpeg Concat Demuxer Tutorial

Ffmpeg Concat Demuxer Tutorial

Onto yesterday’s Ffmpeg Burn Subtitles Tutorial work we’re still not up to “shelling any peas” adding in …

  • Concat demuxer concatenation of videos ffmpeg functionality, onto the “as of yesterday” …
  • Voiceovers … and …
  • Burn subtitles

… progress.

What’s different this time? Well, ffmpeg works the command, we again thank Mux Video and Audio from another Video for (regarding “the plan”), using an interim file …

Concat demuxer

First, make a text file.

file ‘in1.mp4’
file ‘in2.mp4’
file ‘in3.mp4’
file ‘in4.mp4’

Then, run ffmpeg :

ffmpeg -f concat -i list.txt -c copy out.mp4

… and for File API browsing (with our, once again, tweaked inhouse client_browsing.htm) there will be a delay, deriving the file path in “second call PHP”. We handle this by writing two new Javascript functions …

<?php echo ”

var ifile=0, ibfile=0;

function takeoffone() {
ibfile--;
if (ibfile <= 0) {
document.getElementById('mysub').style.cursor='pointer';
} else {
document.getElementById('mysub').style.cursor='progress';
}
}

function organizefilenamesize(fn, fs) {
document.getElementById('ifs').innerHTML+='<iframe id=voaskfor' + ifile + ' style=display:none; src=\"./voiceover.php?concat=' + encodeURIComponent('list.txt') + '&filename=' + encodeURIComponent(fn) + '&haveasleep=' + eval(3 * eval('' + ifile)) + '&filesize=' + fs + '\"></iframe>';
if (ibfile == 0) {
document.getElementById('mysub').style.cursor='progress';
}
ifile++;
ibfile++;
if (document.getElementById('moreb').title.indexOf(\"file '\" + fn.replace(String.fromCharCode(34),'').replace(String.fromCharCode(34),'') + \"'\") == -1) {
document.getElementById('moreb').title+=String.fromCharCode(10) + \"file '\" + fn.replace(String.fromCharCode(34),'').replace(String.fromCharCode(34),'') + \"'\";
}
}

“; ?>

… available to call from child iframes via parent.takeoneoff(); (from voiceover.php second PHP call) and parent.organizefilenamesize(files[ij].name, files[ij].size); (from client_browsing.htm) respectively, to facilitate a progress cursor on the submit button to remind the user we’d like more time. Along the way, too, we found


ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp4

… thanks to the excellent advice we found at this webpage.

You can see this work in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).

Did you know?

Just like the use of …

… are the SpongeBob, Patrick, and Squidward of the online woooorrrrllllddd, in an “offence” line of “piecing together an operating system command” thinking, thinking “defence” regarding this we added one (we were pleasantly surprised to discover worked, so as) to have …

  • div contenteditable=true
  • spanizing within that div
  • innerText
  • mask off parts the programmer wants left untouched via span contenteditable=false

… being like the Hall and Oates meets Everything But the Girl (on a yacht, of course) step back into the ’80s!

Take a look at some tweaks


if (newv == 'Burn subtitles') {
document.getElementById('moreb').innerHTML=firstdivih;
//document.getElementById('precmds').innerHTML=document.getElementById('verb').innerHTML + ' ' + document.getElementById('secondi').innerHTML.replace(/inva\.mp4/g,'sub.srt ') + ' sub.ass; ';
document.getElementById('precmds').innerHTML=document.getElementById('verb').innerHTML + ' ' + document.getElementById('secondi').innerHTML.replace(/inva\.mp4/g,'sub.srt ') + ' <span id=subass contenteditable=false>sub.ass;</span> ';
document.getElementById('secondi').innerHTML='';
//document.getElementById('sswitches').innerHTML='-vf ass=sub.ass';
document.getElementById('sswitches').innerHTML='-vf<span id=asssubass contenteditable=false> ass=sub.ass </span>';
document.getElementById('mysub').value=newv;
}

… in a “Burn subtitles” relevant Javascript code snippet.


Previous relevant Ffmpeg Burn Subtitles Tutorial is shown below.

Ffmpeg Burn Subtitles Tutorial

Ffmpeg Burn Subtitles Tutorial

The initial inspiration for this current ffmpeg themed series of blog posting was, and still is, Mux Video and Audio from another Video, thanks. So many great ideas, we found, that today we add onto the …

  • first idea of Voiceovers we’ve established to work with MAMP in macOS and Windows over the previous days, allowing us to now think to add a first suboption idea of …
  • Burn subtitles … as per our link’s …

    Burn subtitles
    Use the libass library (make sure your ffmpeg install has the library in the configuration –enable-libass).

    First convert the subtitles to .ass format:

    ffmpeg -i sub.srt sub.ass
    Then add them using a video filter:

    ffmpeg -i in.mp4 -vf ass=sub.ass out.mp4

… as a useful video piece of functionality we’d say.

To get this going, easily (from a programming perspective) …

  • our textarea element remains as the form conduit to the ffmpeg command via the onsubmit event final analysis of the …
  • underlying div contenteditable=true is “spanned” up a lot more as per …
    <?php echo ”

    document.getElementById('moreb').innerHTML='<span id=precmds></span><span id=verb>ffmpeg" . $ffmpegsuf . "</span> -i <span id=scbi><iframe onload=checkif(this,\"inv.mp4\"); scrolling=no frameborder=0 id=cbi data-type=file data-value=inv.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:92px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=9075964842271&left=y\"></iframe></span> <span id=betweenis></span> <span id=secondi>-i <span id=scbix><iframe onload=checkiftwo(this,\"inva.mp4\"); scrolling=no frameborder=0 id=cbix data-type=file data-value=inva.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:106px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=9075964842271&right=y\"></iframe></span></span> <span id=sswitches>-c copy -map 0:v:0 -map 1:a:0 -shortest</span> out.mp4 > <a target=_blank title=ffm.bad onclick=getvb(); style=cursor:pointer;text-decoration:underline; data-href=./ffm.bad>ffm.bad</a>';

    “; ?>
    … and at the onsubmit event Javascript the innerText attribute usage makes it fairly easy to say
    <?php echo ”

    function mergechanges() {
    if (document.getElementById('scbi').innerHTML.indexOf('<') == -1) {
    if (document.getElementById('precmds').innerHTML != '') {
    document.getElementById('fcommand').value=document.getElementById('moreb').innerText;
    } else {

    document.getElementById('fcommand').value=document.getElementById('fcommand').value.replace(' inv.mp4 ', ' ' + document.getElementById('scbi').innerHTML + ' ');
    }
    //alert('not oops ' + document.getElementById('fcommand').value);
    } //else {
    //alert('oops');
    //}
    if (document.getElementById('scbix').innerHTML.indexOf('<') == -1) {
    //alert('zoops');
    document.getElementById('fcommand').value=document.getElementById('fcommand').value.replace(' inva.mp4 ', ' ' + document.getElementById('scbix').innerHTML + ' ');
    }
    if (document.getElementById('moreb').innerText.indexOf(' -c ') != -1 && document.getElementById('fcommand').value.indexOf(' -c ') != -1) {
    //alert('azoops');
    if (document.getElementById('moreb').innerText.split(' -c ')[1] != document.getElementById('fcommand').value.split(' -c ')[1]) {
    //alert('bzoops');
    document.getElementById('fcommand').value=document.getElementById('fcommand').value.split(' -c ')[0] + ' -c ' + document.getElementById('moreb').innerText.split(' -c ')[1];
    }
    }
    return true;
    }

    “; ?>
    … to slice through that “span” complexity like margarine (or butter that’s been left out on a hot day for approximately 7 hours 17 minutes 23 seconds)

And so, onto yesterday’s Ffmpeg Improved Windows Media Browsing Tutorial feel free to see this in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).


Previous relevant Ffmpeg Improved Windows Media Browsing Tutorial is shown below.

Ffmpeg Improved Windows Media Browsing Tutorial

Ffmpeg Improved Windows Media Browsing Tutorial

Yesterday’s Ffmpeg Mux Video and Audio Windows Media Browsing Tutorial taught us a lesson, as a side issue, that what we said when we presented Animated GIF Creation on Windows MAMP via PDF Tutorial

No matter how we tried, we could not get a Windows command line command like …


forfiles /P "[PathToFileBestGuess]" /S /M "[FileBaseName]" /C "cmd /c echo @path@fsize" | find "[FileSizeInBytes]"

… to work out a file path when supplied a file base name and a file size and you call as above with starting folders. That works well (for deriverability (if that is a word!)) in the “cmd” window but not when called under the auspices of PHP exec or shell_exec. It could be that you lose a lot of a Windows user environment when asking PHP to do some operating system work.

… was “only partially” the story. We found out that that ” | find ” command piping could cause problems on Windows MAMP using shell_exec or exec to do some operating system functionality. But before your enthusiasm oozes over the edges, Windows “forfiles” is still very hard to get working with PHP shell_exec or exec, even using PHP to perform that ” | find ” filtering of results.

However, on revisiting the issue in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there) there were dual purpose motivations going on, for us, because our changed animated GIF creator PHP tutorial_to_animated_gif.php (that if you download to MAMP would best go to Document Root PHP/animegif folder along with the wonderful GIFEncoder.class.php … thanks) inhouse animated GIF creator web application and the changed PDF parts to animated GIF creation helper php_calls_pdfimages.php (also a standalone proposition) PHP code could be fixed up at the same time, with a new PHP ourshell_exec function interventional code snippet up at the top …

<?php

function ourshell_exec($onea, $twoa = NULL, $threea = NULL) {
$folder='';
$pattern='';
$size='';
$filesa=[];
if (PHP_OS =='WINNT' || PHP_OS =='WIN32' || PHP_OS =='Windows' || (strpos(('~@!' . $onea), '~@!forfiles /P "') !== false && strpos(('~@!' . $onea), '/M "') !== false && strpos(('~@!' . $onea), 'find "') !== false)) {
$folder=explode('"', explode('forfiles /P "', $onea)[1])[0]; // . substr(DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR, 0, 1);
if (7 == 7) {
$folder=explode('"', explode('forfiles /P "', $onea)[1])[0]; // . substr(DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR, 0, 1);
$pattern=explode('"', explode('/M "', $onea)[1])[0];
$size=explode('"', explode('find "', $onea)[1])[0];
$thiscmd=trim(explode(" | find ", $onea)[0]);
if (strpos($pattern, ' ') === false) { $thiscmd=str_replace('/M "' . $pattern . '"', '/M ' . $pattern, $thiscmd); }
if (strpos($folder, ' ') === false) { $thiscmd=str_replace('/P "' . $folder . '"', '/P ' . $folder, $thiscmd); }
if (strpos($thiscmd, '"cmd /c ') !== false && substr($thiscmd,-1,1) != '"') { $thiscmd.='"'; }
if (strpos($thiscmd, "/P C:\\ ") !== false) {
if (strpos($thiscmd, "/P C:\\ ") !== false) {
if (strpos($pattern, " ") === false) {
$thiscmd="DIR C:\\" . $pattern . " /S /-C";
} else {
$thiscmd="DIR \"C:\\" . $pattern . "\" /S /-C";
}
}
}
//file_put_contents('xxx.xxx',file_get_contents('xxx.xxx'). "\n" . '' . $size . ' ' . $thiscmd);
$nofind=shell_exec($thiscmd . ' 2> nul');

//file_put_contents('xxxx.xxxx',file_get_contents('xxxx.xxxx'). "\n" . '' . $size . ' ' . $nofind);
//exit;
$findings=explode("\n", $nofind);
$bitbefore='';
for ($ifindgs=0; $ifindgs<sizeof($findings); $ifindgs++) {
if (strpos(str_replace("\r","",$findings[$ifindgs]), 'Directory of ') !== false) {
$bitbefore=explode('Directory of ', str_replace("\r","",$findings[$ifindgs]))[1] . "\\";
}
if (strpos((str_replace("\r","",$findings[$ifindgs]) . '~'), $size . '~') !== false) {
return str_replace('~','',str_replace($size . '~', '', (str_replace("\r","",$findings[$ifindgs]) . '~')));
} else if (strpos((str_replace("\r","",$findings[$ifindgs]) . ''), $size . ' ') !== false) {
//file_put_contents('xxxxx.xxxxx',$bitbefore . explode($size . ' ', (str_replace("\r","",$findings[$ifindgs]) . ''))[1]);
return $bitbefore . explode($size . ' ', (str_replace("\r","",$findings[$ifindgs]) . ''))[1];
}
}
if ($folder == "C:\\") { return ''; }
}

// more code
// as per usual
// stays here ...
}
return shell_exec($onea, $twoa, $threea);
}

?>

… where we substitute in Windows DIR C:\ /S /-C thinking in place of forfiles (via shell_exec minus the ” | find ” piping, that is).


Previous relevant Ffmpeg Mux Video and Audio Windows Media Browsing Tutorial is shown below.

Ffmpeg Mux Video and Audio Windows Media Browsing Tutorial

Ffmpeg Mux Video and Audio Windows Media Browsing Tutorial

You know it’s “Intranet feely land”?

You look out the train window (tee hee) and see macOS racing through their usual routine.

Of course you’ll pick the buffet car containing the rice bubbles ahead of the vegemite corn flakes?!

But do we need to reiterate that in “Intranet feely land” you’ve got your macOS typose of work not suiting “arch Windows” methodologies? Take the case of …

At least, with macOS MAMP there is the excellent command line “file” we can use to show information about some potential input files you could use in this, so far, user unfriendly, “first draft” version of the PHP.

… to the beach, would be nice … but we digress. Well, in any case, we asked Google (not via the “arch Window”) does windows have the equivalent of linux file command” and got to the helpful What is the equivalent to the Linux File command for windows? – Super User, thanks, and then ended up at the really useful third party “file.exe” for (non-arch) Windows usage and proceeded with it, working off Ffmpeg Mux Video and Audio Media Browsing Tutorial, to start being able to develop this “reveal” details/summary arrangement in either macOS or Windows MAMP environments, that “ffmpeg” voiceover command, which normally works a lot better than …

I command thee mux, hey you, with audible you, over yonder, by dale and meadow be, yea!

… when it occurred to us we could turn the base filename parts of those “file.exe” reports into links that when clicked mapped those clicked files into place into the “ffmpeg” command being developed above (as alternative input file designator idea to browsing or div contenteditable=true typing ways), in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder) and which you can run that PHP there.

And so, we reckon the work day got worth it!


Previous relevant Ffmpeg Mux Video and Audio Media Browsing Tutorial is shown below.

Ffmpeg Mux Video and Audio Media Browsing Tutorial

Ffmpeg Mux Video and Audio Media Browsing Tutorial

Onto yesterday’s Ffmpeg Mux Video and Audio Primer Tutorial

There be a flowerin’ of inner warmth and glo’ towards all our readers, youngins and oldins alike … like!

Yes, we’re involving good ol’ HTML5 File API Object Javascript logic, so our “Intranet” savvy downloaders out there …

Full o’ inner warmth and glo’ towards each other … like!

… can easily browse for their two media input files, and for the first time ever integrating our ever tweaked inhouse client_browsing.htm (also a standalone proposition) (we’d like you to download to MAMP Document Root’s HTMLCSS subfolder) we add “oncontextmenu” event changes to its input type=file browser hosting parent iframe element onload event Javascript function as per

<?php echo ”

var voaf='', voaftwo='';

function checkif(iois, ival) {
if (iois.src.indexOf('?d=') != -1) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.getElementById('files')) {
if (voaf == '') {
voaf=iois.src;
iois.setAttribute('data-parentspan', 's' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix'));
document.getElementById('myh1').title='s' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix');
document.getElementById('myh1').setAttribute('data-url', iois.src);
setInterval(voaff, 1000);
} else if (voaftwo == '') {
voaftwo=iois.src;
iois.setAttribute('data-parentspan', 's' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix'));
document.getElementById('myh3').title='s' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix');
document.getElementById('myh3').setAttribute('data-url', iois.src);
//alert(iois.id + ' data-parentspan=' + iois.getAttribute('data-parentspan'));
}
//alert(iois.id + ' data-parentspan=' + iois.getAttribute('data-parentspan'));
aconto.getElementsByTagName('h1')[0].style.opacity='0.0';
//alert('here');
aconto.getElementById('files').style.position='absolute';
aconto.getElementById('files').style.left='0px';
aconto.getElementById('files').style.top='0px';
aconto.getElementById('files').style.zIndex='99';
aconto.getElementById('files').style.marginLeft='10px';
aconto.getElementById('files').style.marginTop='8px';
aconto.getElementById('files').style.visibility='visible';
aconto.getElementById('files').style.display='block';
aconto.getElementById('files').style.backgroundColor='#eeeeee';
aconto.getElementById('files').setAttribute('data-hostcont', ival);
aconto.getElementById('files').setAttribute('data-hostspan', 's' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix'));
aconto.getElementById('files').oncontextmenu = function(event) { var suf=event.target.getAttribute('data-hostspan'); parent.document.getElementById(suf).innerHTML=\"" . str_replace("\\","\\\\",dirname(__FILE__) . DIRECTORY_SEPARATOR) . "\" + event.target.getAttribute('data-hostcont'); }
if (ival == 'inv.mp4') {
aconto.getElementById('files').accept='video/*';
aconto.getElementById('files').title='Click to browse for video else right click or two finger gesture to make disappear.';
} else {
aconto.getElementById('files').accept='video/*,audio/*';
aconto.getElementById('files').title='Click to browse for video or audio else right click or two finger gesture to make disappear.';
}
//alert('there');
aconto.getElementById('dwstyle').innerHTML+=\"<style> #files::before { content: '\" + ival + \"'; } </style>\";
}
}
}
}

“; ?>

… to allow a user who prefers the overlayed div contenteditable=true alternative (which speaks back to the HTML form textarea conduit when that form’s “onsubmit” event is called) onto yesterday’s exclusively textarea methodology

<?php echo ”

function overlay() {
var rect=document.getElementById('fcommand').getBoundingClientRect();
document.getElementById('moreb').style.position='absolute';
document.getElementById('moreb').style.left='' + rect.left + 'px';
document.getElementById('moreb').style.top='' + rect.top + 'px';
document.getElementById('moreb').style.width='96%'; //' + rect.width + 'px';
document.getElementById('moreb').style.height='' + rect.height + 'px';
document.getElementById('moreb').style.border='1px solid black';
document.getElementById('moreb').style.paddingLeft='20px';
document.getElementById('moreb').style.backgroundColor='#f9f9f9';
document.getElementById('fcommand').style.opacity='0.0';
document.getElementById('moreb').innerHTML='ffmpeg" . $ffmpegsuf . " -i <span id=scbi><iframe onload=checkif(this,\"inv.mp4\"); scrolling=no frameborder=0 id=cbi data-type=file data-value=inv.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:92px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=975964842271&left=y\"></iframe></span> -i <span id=scbix><iframe onload=checkiftwo(this,\"inva.mp4\"); scrolling=no frameborder=0 id=cbix data-type=file data-value=inva.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:106px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=975964842271&right=y\"></iframe></span> -c copy -map 0:v:0 -map 1:a:0 -shortest out.mp4 > voiceover.bad';
}

function mergechanges() {
if (document.getElementById('scbi').innerHTML.indexOf('<') == -1) {
document.getElementById('fcommand').value=document.getElementById('fcommand').value.replace(' inv.mp4 ', ' ' + document.getElementById('scbi').innerHTML + ' ');
//alert('not oops ' + document.getElementById('fcommand').value);
} //else {
//alert('oops');
//}
if (document.getElementById('scbix').innerHTML.indexOf('<') == -1) {
document.getElementById('fcommand').value=document.getElementById('fcommand').value.replace(' inva.mp4 ', ' ' + document.getElementById('scbix').innerHTML + ' ');
}
if (document.getElementById('moreb').innerText.indexOf(' -c ') != -1 && document.getElementById('fcommand').value.indexOf(' -c ') != -1) {
if (document.getElementById('moreb').innerText.split(' -c ')[1] != document.getElementById('fcommand').value.split(' -c ')[1]) {
document.getElementById('fcommand').value=document.getElementById('fcommand').value.split(' -c ')[0] + ' -c ' + document.getElementById('moreb').innerText.split(' -c ')[1];
}
}
return true;
}


“; ?>

… reign supreme collecting their media file specification information in the changed voiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder) and which you can run that PHP there.

The previous work of Animated GIF Creation Install Paths Tutorial‘s thread of blog postings has been a great help with this ffmpeg “Intranet feeling” integration work we use, around here, in conjunction with macOS or Windows operating system MAMP Apache local web server environments.


Previous relevant Ffmpeg Mux Video and Audio Primer Tutorial is shown below.

Ffmpeg Mux Video and Audio Primer Tutorial

Ffmpeg Mux Video and Audio Primer Tutorial

We’ve got another “Intranet feeling” PHP web application “first draft” for you today. The reason we’re opting for “Intranet feeling” (ie. we’re asking you to download the voiceover.php PHP to a local MAMP Apache web server and run the PHP there from its Document Root folder) is that we want to further explore the brilliant …


ffmpeg -i inv.mp4 -i inva.mp4 -c copy -map 0:v:0 -map 1:a:0 -shortest out.mp4

… we got inspired to try via Mux Video and Audio from another Video and FFMPEG mux video and audio (from another video) – mapping issue … thanks and thanks … to add audio to a video stream from two different sources.

At least, with macOS MAMP there is the excellent command line “file” we can use to show information about some potential input files you could use in this, so far, user unfriendly, “first draft” version of the PHP.

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

Ball Game Canvas Animation Primer Tutorial

Ball Game Canvas Animation Primer Tutorial

Ball Game Canvas Animation Primer Tutorial

In the 70’s (ie. 1970’s), around and in Australian squash court complexes, people would get excited by the squash, and the “coffee table” style computer games based on balls and bats and walls. Well, today, we were reminded of those “heady days” … cough, cough … when we chanced upon this excellent website using …

… “animation friends”.

We thought to “value add” via …

  • https://stackoverflow.com/questions/39563033/how-to-resize-the-canvas-using-javascript‘s “heads up” regarding a window resizing means by which we might allow a canvas resize … as well as the method below, in amongst …
  • allow user control of …
    1. ball radius
    2. ball colour
    3. ball delta-X movement
    4. ball delta-Y movement
    5. ball “field” width
    6. ball “field” height
  • style a brick wall the ball could bounce off (alas, not as unpredictable as the besser block wall we used to practice tennis reactions against)

… in today’s proof of concept Ball Game you can also try below …

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

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

Google Chart Geo Chart Quiz Time Tutorial

Google Chart Geo Chart Quiz Time Tutorial

Google Chart Geo Chart Quiz Time Tutorial

Yesterday’s Google Chart Geo Chart Quiz Overlay Tutorial ideas worked fine on non-mobile, and was mostly okay on iPhone but not on iPad, very well, and we thought what we should do for the greater good was to …

  • change iframe overlay ideas … that were also not so good, without a lot more work, regarding horizontal scrolling … in favour of …
    1. still call the URL of that iframe … and in it’s onload event …
    2. scour its SVG for the country green shading and add it back into the parent SVG, appending these SVG path elements onto the last “g” element found (that way, helping with positioning)
      <?php echo ”

      function realign(iois) {
      var aconto = (iois.contentWindow || iois.contentDocument);
      if (aconto != null) {
      if (aconto.document) { aconto = aconto.document; }
      if (aconto.body != null) {
      if (aconto.getElementById('chart_div')) {
      if (document.getElementById('chart_div')) {
      var cdrect=document.getElementById('chart_div').getBoundingClientRect();
      aconto.getElementById('chart_div').style.position='absolute';
      aconto.getElementById('chart_div').style.left='' + cdrect.left + 'px';
      aconto.getElementById('chart_div').style.top='' + cdrect.top + 'px';
      aconto.getElementById('chart_div').style.width='' + cdrect.width + 'px';
      aconto.getElementById('chart_div').style.height='' + cdrect.height + 'px';
      if (aconto.getElementById('myh')) {
      if (aconto.getElementById('myh').innerHTML.indexOf('Quiz Zoom Out Answer') != -1) {
      aconto.getElementById('myh').style.visibility='hidden';
      }
      }
      " . ($doverlayscr == "" ? ("
      var dopvsvg=document.getElementsByTagName('g');
      var dovsvg=aconto.getElementsByTagName('svg');
      var dovs=dovsvg[0].innerHTML.split(' fill=\"#109618\"');

      for (var iyu=1; iyu < dovs.length; iyu++) {
      if (dovs[iyu].indexOf('</path>') != -1) {
      dopvsvg[eval(-1 + dopvsvg.length)].innerHTML+='<' + dovs[eval(-1 + iyu)].split('<')[eval(-1 + dovs[eval(-1 + iyu)].split('<').length)] + ' fill=\"#109618\"' + dovs[iyu].split('</path>')[0] + '</path>';
      }
      }

      setTimeout(function(){
      var doptsvg=document.getElementsByTagName('text');
      for (var jyu=0; jyu < doptsvg.length; jyu++) {
      doptsvg[jyu].setAttribute('fill-opacity','0.7'); //.style.opacity='0.7';
      }
      }, 8000);
      if (eval('' + dovs.length) > 1) {
      document.getElementById('doverlay').innerHTML='';
      } else if (navigator.userAgent.match(/iPad/i)) {
      var acdx=aconto.getElementById('chart_div').innerHTML;
      if (1 == 1) {
      document.getElementById('chart_div').innerHTML+='<details><summary>Country shaded below ...</summary>' + acdx + '</details>';
      document.getElementById('doverlay').innerHTML='';
      } else {
      document.getElementById('doverlay').innerHTML=''; //location.href=iois.src;
      }
      }
      ") : $doverlayscr) . "
      }
      }
      }
      }
      }

      “; ?>
    3. and then “call off” that iframe display

Also we add another hint, a Current Time one, calling on that recent PHP intl “Internationalization Functions” extension work, so that …

  • a tweaked
    <?php

    if ((isset($_GET['ccode']) || isset($_GET['timezone'])) && !isset($_GET['locale'])) {
    $passedtz='';
    $tzideas=[];
    if (isset($_GET['timezone'])) {
    $passedtz=str_replace('+',' ',urldecode($_GET['timezone']));
    // value='Australia/Sydney' data-geo='-33.86667,151.21666,AEST,AU,+11
    if (strlen($_GET['ccode']) != 2 || strtoupper($_GET['ccode']) != $_GET['ccode']) {
    $tzideas=explode('' . $passedtz . '', $yourtzlist);
    if (sizeof($tzideas) > 1) {
    if (sizeof(explode(',', $tzideas[1])) > 3) {
    $_GET['ccode']=explode(',', $tzideas[1])[3];
    }
    }
    }
    }
    if (strlen($_GET['ccode']) == 2 && strtoupper($_GET['ccode']) == $_GET['ccode']) {
    if (strpos($yourtzlist, ',' . $_GET['ccode'] . ',') !== false) {
    $tzideas=explode(',' . $_GET['ccode'] . ',', $yourtzlist);
    $itz=sizeof($tzideas);
    if ($itz > 2) {
    if (($itz % 2) == 1) {
    $itz=(($itz + 1) / 2);
    } else {
    $itz/=2;
    }
    } else {
    $itz-=1;
    }
    if (sizeof($tzideas) > 1 || $passedtz != '') {
    if ($passedtz == '') {
    $passedtz=explode('<', explode('>', $tzideas[$itz])[1])[0];
    }
    $okayidea='';
    $reallygoodidea='';
    $bestidea='';
    $arrl=ResourceBundle::getLocales('');
    for ($df=0; $df<sizeof($arrl); $df++) {
    if (!isset($_GET['langidea'])) {
    if (strpos(str_replace('-','_',$arrl[$df] . '_'), '_' . $_GET['ccode'] . '_') !== false) {
    if (strlen($arrl[$df]) <= 6) { if ($reallygoodidea == '') { $reallygoodidea=$arrl[$df]; } else { if ($okayidea == '') { $okayidea=$arrl[$df]; } } } else if ($okayidea == '') { $okayidea=$arrl[$df]; }
    }
    } else {
    if (strpos(str_replace('-','_',$arrl[$df] . '_'), '_' . $_GET['ccode'] . '_') !== false) {
    if (strpos('~' . str_replace('-','_',$arrl[$df] . '_'), '~' . $_GET['langidea'] . '_') !== false) {
    if (strlen($arrl[$df]) <= 6) { if ($bestidea == '') { $bestidea=$arrl[$df]; } else { if ($reallygoodidea == '') { $reallygoodidea=$arrl[$df]; } } } else if ($okayidea == '') { $okayidea=$arrl[$df]; }
    } else if (strlen($arrl[$df]) <= 6) {
    if ($reallygoodidea == '') { $reallygoodidea=$arrl[$df]; } else { if ($okayidea == '') { $okayidea=$arrl[$df]; } } } else if ($okayidea == '') { $okayidea=$arrl[$df]; }
    }
    }
    }
    if (!isset($_GET['langidea'])) {
    $_GET['langidea']='en';
    }
    if (!isset($_GET['parid'])) {
    $_GET['parid']='curtime';
    }

    if ($bestidea != '') {
    $fmt = datefmt_create(
    $bestidea,
    IntlDateFormatter::FULL,
    IntlDateFormatter::FULL,
    $passedtz,
    IntlDateFormatter::GREGORIAN
    );
    echo '<html><body onload="if (!parent.document.getElementById(' . "'" . urldecode($_GET['parid']) . "'" . ')) { alert(' . "'" . datefmt_format($fmt, time()) . "'" . '); } else { parent.document.getElementById(' . "'" . urldecode($_GET['parid']) . "'" . ').value=' . "'" . datefmt_format($fmt, time()) . "'" . '; }"></iframe>';
    } else if ($reallygoodidea != '') {
    $fmt = datefmt_create(
    $reallygoodidea,
    IntlDateFormatter::FULL,
    IntlDateFormatter::FULL,
    $passedtz,
    IntlDateFormatter::GREGORIAN
    );
    echo '<html><body onload="if (!parent.document.getElementById(' . "'" . urldecode($_GET['parid']) . "'" . ')) { alert(' . "'" . datefmt_format($fmt, time()) . "'" . '); } else { parent.document.getElementById(' . "'" . urldecode($_GET['parid']) . "'" . ').value=' . "'" . datefmt_format($fmt, time()) . "'" . '; }"></iframe>';
    } else if ($okayidea != '') {
    $fmt = datefmt_create(
    $okayidea,
    IntlDateFormatter::FULL,
    IntlDateFormatter::FULL,
    $passedtz,
    IntlDateFormatter::GREGORIAN
    );
    echo '<html><body onload="if (!parent.document.getElementById(' . "'" . urldecode($_GET['parid']) . "'" . ')) { alert(' . "'" . datefmt_format($fmt, time()) . "'" . '); } else { parent.document.getElementById(' . "'" . urldecode($_GET['parid']) . "'" . ').value=' . "'" . datefmt_format($fmt, time()) . "'" . '; }"></iframe>';
    }


    }
    }
    }
    exit;
    }

    ?>
    i_eg.php Datetime Internationalization web application … helps out …
  • our changed geochart.html My World Zoom In Quiz web application … using …
  • our changed geo_chart.php Google Chart Geo Chart interfacer


Previous relevant Google Chart Geo Chart Quiz Overlay Tutorial is shown below.

Google Chart Geo Chart Quiz Overlay Tutorial

Google Chart Geo Chart Quiz Overlay Tutorial

Regarding the recent “beep work” of Google Chart Geo Chart Quiz Beep Tutorial we saw that that right hand iframe “explanation of a wrong answer” could do with some tweaking, it as of then was …

  • only showing a green dot of the relevant country’s relevant TimeZone place position on a Google Chart Geo Chart world map … but then we thought …
  • Wouldn’t it be good to transition from the green dot to the country emoji flag?

    … and then the next day we thought …

  • Wouldn’t it be good to transition from the green dot to the country emoji flag at the same time as overlaying a shaded country view as well?

    … and then the next day was tomorrow … so …

… we wrote this blog post, after doing the coding changes, featuring a new “overlay iframe onload event”

<?php

$doverlayih='';

if (isset($_GET['title']) && isset($_GET['data']) && strpos(urldecode($_GET['title']), 'Quiz Zoom Out Answer') !== false) {
if (isset($_GET['peninfo']) && isset($_GET['data'])) {
if (strpos($_GET['peninfo'], '|') === false && strpos($_GET['peninfo'], urlencode('|')) === false && strpos(urldecode($_GET['data']), '|~') !== false) {
$cplace=str_replace('_',' ',str_replace('+',' ',explode('~', explode('|~', urldecode($_GET['data']))[1])[0]));
for ($ij=1; $ij < sizeof($iso_country_codes); $ij+=2) {
if ($cplace == $iso_country_codes[$ij]) {
$cplaceiso=strtoupper($iso_country_codes[-1 + $ij]);
$newpeninfo=str_replace('%20[','',explode(urlencode('~'), explode('~', $_GET['data'])[0])[0]);
$uretv='';
$xlri=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
$xdri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];
for ($jjm=0; $jjm<strlen($cplaceiso); $jjm++) {
for ($jm=0; $jm<sizeof($xlri); $jm++) {
if (strtoupper(substr(substr($cplaceiso,$jjm),0,1)) == $xlri[$jm]) {
if ($jjm == 0) {
$newpeninfo.=$xdri[$jm];
} else {
$newpeninfo.='.' . $xdri[$jm];
}
}
}
}
$newpeninfo.='_' . str_replace(' ','_',$cplace);
$_GET['peninfo']=$newpeninfo;

//$_GET['overlay']='y';
$doverlayih='<iframe onload="realign(this);" style="position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:2222;opacity:0.58;text-shadow:-1px 1px 1px #ff2d95;" src="//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' . (isset($_GET['title']) ? $_GET['title'] : '') . '&width=' . (isset($_GET['width']) ? $_GET['width'] : '') . '&height=' . (isset($_GET['height']) ? $_GET['height'] : '') . '&country=' . (isset($_GET['country']) ? $_GET['country'] : '') . '&popularity=' . (isset($_GET['popularity']) ? $_GET['popularity'] : '') . '&data=%20[~' . $cplaceiso . '~,2]"></iframe><style> #chart_div { text-shadow:-1px 1px 1px #ff2d95; } </style>';
}
}
}
}
}

?>

… used, later, via …


<div id="doverlay"><?php echo $doverlayih; ?></div>

… using new “overlay iframe onload event function” …

<?php echo ”

function realign(iois) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
if (aconto.getElementById('chart_div')) {
if (document.getElementById('chart_div')) {
var cdrect=document.getElementById('chart_div').getBoundingClientRect();
aconto.getElementById('chart_div').style.position='absolute';
aconto.getElementById('chart_div').style.left='' + cdrect.left + 'px';
aconto.getElementById('chart_div').style.top='' + cdrect.top + 'px';
aconto.getElementById('chart_div').style.width='' + cdrect.width + 'px';
aconto.getElementById('chart_div').style.height='' + cdrect.height + 'px';
if (aconto.getElementById('myh')) {
if (aconto.getElementById('myh').innerHTML.indexOf('Quiz Zoom Out Answer') != -1) {
aconto.getElementById('myh').style.visibility='hidden';
}
}
}
}
}
}
}

“; ?>

… you may notice tries to improve “the display dynamism” that little bit by applying a CSS text-shadow property Santa claws clause in our changed geo_chart.php Google Chart Geo Chart interfacer for our Geography Zoom In Quiz.


Previous relevant Google Chart Geo Chart Quiz Beep Tutorial is shown below.

Google Chart Geo Chart Quiz Beep Tutorial

Google Chart Geo Chart Quiz Beep Tutorial

We’ve long had on our minds a wish to incorporate a beep sound into quiz scenarios, and we’re revisiting this, again, for us, trying to get this going using the Geographical Quiz featuring in Google Chart Image Chart Map Chart Quiz Tutorial.

Why we feel a beep would be good here is that a user can use the beep while multitasking, and be told when to focus back on the quiz, while doing other things, perhaps, and the beep patterns can tell them …

  1. whether they are correct
  2. when the next question’s left hand map hint has been loaded

… while they are doing those other things, perhaps.

A beep is no big deal, right?! No, it is not such a big deal on non-mobile, true, but on mobile, it is a nightmare! Because …

  1. ever since this web browser approach on mobile, of only allowing audio (and/or video) play operations off a real user click “origin”, the task for mere non-Spotify mortals (and even they click, really, at least once) is more tortuous … and less of a pain, but a tad annoying, is that …
  2. Safari (web browser) not playing audio/wav files, so we looked around and came upon this excellent link, thanks, to get an MP3 beep

… all hold us up.

To get a kludgy solution on mobile we opted to …

  • overlay a dropdown (select) element the user uses to answer (which we later improved by overlaying a new “Beep” checkbox initially hidden from view, which we’re calling “non kludgy”), in the quiz … with an …
  • audio element positioned so that …
    1. mobile user can’t help but see it … and …
    2. they choose whether or not to involve audio beeps by clicking the audio element at a time of their choosing, or not, knowing …

    … there are still ways to get to the underlayed dropdown to answer the quiz question …

    function overselceqwq() {
    if (document.getElementById('divselcq').innerHTML.indexOf('<audio') == -1) {
    //document.getElementById('divselcq').innerHTML+='1:' + navigator.userAgent + '<br>';
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i) && 1 == 1) {
    //document.getElementById('divselcq').innerHTML+='01:' + navigator.userAgent + '<br>';
    rectisa=document.getElementById('selceqwq').getBoundingClientRect();
    //document.getElementById('divselcq').innerHTML+='11:' + navigator.userAgent + '<br>';
    if (1 == 11) {
    document.getElementById('divselcq').innerHTML+='<audio id=aselwq style="visibility:' + hidden + ';opacity:0.4;z-index:876;position:absolute;top:' + eval(-95 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(0.55 * eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(0.10 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/mp3 onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); hidden=' + "'hidden'" + '; document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; document.getElementById(' + "'aselwq'" + ').style.visibility=' + "'hidden'" + '; },2000);" onmousedown="if (event.currentTarget == this) { this.muted=!this.muted; }" ontouchstart="if (event.currentTarget == this) { this.muted=!this.muted; }" onclick="if (event.currentTarget == this) { this.muted=!this.muted; setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; }, 2000); }" controls muted><source type=audio/mp3 src="/beep.mp3"></source></audio>';
    } else if (1 == 1) {
    setTimeout(function(){
    rectisa=document.getElementById('audios').getBoundingClientRect();
    document.getElementById('divselcq').innerHTML+='<audio id=aselwq style="visibility:' + hidden + ';opacity:0.4;z-index:876;position:absolute;top:' + eval(-20 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(10 + eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(1.0 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/mp3 onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); hidden=' + "'hidden'" + '; document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; document.getElementById(' + "'aselwq'" + ').style.visibility=' + "'hidden'" + '; },2000);" onmousedown="if (event.currentTarget == this) { this.muted=!this.muted; }" ontouchstart="if (event.currentTarget == this) { this.muted=!this.muted; }" onclick="if (event.currentTarget == this) { this.muted=!this.muted; setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; }, 2000); }" controls muted><source type=audio/mp3 src="/beep.mp3"></source></audio>';
    }, 3000);
    } else {
    document.getElementById('divselcq').innerHTML+='<audio onload=this.muted(true); id=aselwq style="visibility:hidXden;opacity:0.2;z-index:876;position:absolute;top:' + eval(4 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(0.80 * eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(0.10 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/wav onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); },2000);" onmousedown="this.muted(false);" ontouchdown="this.muted(false); " onclick="setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); }, 2000);" controls><source type=audio/wav src="data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU="></source></audio>';
    }
    //document.getElementById('divselcq').innerHTML+='111:' + document.getElementById('aselwq').outerHTML.replace(/\</g,'<').replace(/\>/g,'>') + '<br>';
    //document.getElementById('divselcq').innerHTML+='<button id=bselwq style="background-color:transparent;z-index:1876;position:absolute;top:' + rectisa.top + 'px;left:' + rectisa.left + 'px;width:' + rectisa.width + 'px;height:' + rectisa.height + 'px;' + '" type=audio/wav onclick="beep(); document.getElementById(' + "'selceqwq'" + ').click();"></button>';
    }
    }
    }

    function mbeep() {
    if (useaudios) {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i)) {
    if (top.document.getElementById('aselwq')) {
    top.document.getElementById('aselwq').play();
    } else {
    //var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    var snd = new Audio("/beep.mp3"); // "data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    snd.play();
    setTimeout(beep, 5000);
    }
    }
    }
    }

    function beep() {
    if (useaudios) {
    if (top.document.getElementById('aselwq')) {
    top.document.getElementById('aselwq').play();
    } else {
    var snd = new Audio("/beep.mp3"); // "data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    snd.play();
    }
    }
    }

    function beeptwo() {
    beep();
    setTimeout(function(){
    beep();
    }, 100);
    }

    function beepthree() {
    beep();
    setTimeout(function(){
    beep();
    }, 100);
    setTimeout(function(){
    beep();
    }, 200);
    setTimeout(function(){
    beep();
    }, 300);
    }

    function beepDoubleThree() {
    beepthree();
    setTimeout(function(){
    beepthree()
    }, 500);
    }

Codewise …

… you might want to revisit, yourself!


Previous relevant Google Chart Image Chart Map Chart Quiz Tutorial is shown below.

Google Chart Image Chart Map Chart Quiz Tutorial

Google Chart Image Chart Map Chart Quiz Tutorial

There is an expression so apt for today’s situation. But we hate it, so … no … we’ll say instead …

Our fault mainly, not Google’s fault only

… regarding yesterday’s …

However, this last one both needs more “wading through data” and “consideration” because it seems to be at Google Charts that not even the national boundary is shown when this regional data is not recognized.

We discovered today, that fallback colours directed towards an overall country code at the end of the URL regional colour entry list, is the way around some of the issue, that some meaning now we can get a country boundary showing, but still, for some countries, Google Charts, with its Image Chart Map Chart, will not show regional boundaries as you might see defined at Wikipedia for some ISO 3166-2 regional codes they have recorded.

So, what’s that got to do with quizzes? Well, the quiz got us interested in these colour mappings, and discovering how those mappings worked led us to this discovery. We hope colour blind people don’t suffer because our Country Regional Quiz functionality could easily be called …

Name the Red Region Quiz

Yes, if the user chooses the new “Quiz” input submit button modus operandi we arrange …

  • to leave out any legends
  • randomly pick a region which is coloured red … and now blue represents unaccounted for country parts not assigned a region and green represents the rest of the world and the oceans are as they ever were … and …
  • after a while we ask the user for their guess as to what this red region’s name is

Good ol’ “colour coding”! What did we do when the world was not colourful? Oops … [expression we hate, again, fits here] … my mistake. We wouldn’t have been around. But we digress.

Simple premise, building on yesterday’s Google Chart Image Chart Map Chart Context Tutorial, but surprisingly involved in our changed third draft image_chart.php PHP web application for you to try, below, perhaps


Previous relevant Google Chart Image Chart Map Chart Context Tutorial is shown below.

Google Chart Image Chart Map Chart Context Tutorial

Google Chart Image Chart Map Chart Context Tutorial

Onto yesterday’s Google Chart Image Chart Map Chart Primer Tutorial start with Google Charts Image Chart Map Chart interfacing, today we’ve come at it from two subcategories relating to fallback positions and “context” …

  • add Geo Chart and Map Chart optionally viewed details/summary iframes showing country TimeZone position data
  • add a mechanism that if we can determine a country’s ideal range of latitude,longitude “box” view, as we found GADM could help us with, thanks, we can flag that

    $ourtzlist=" ...<option value=\"Asia/Shanghai\" title=\"17,82,55,133\" data-geo=\"31.23333,121.46666,CST,CN,+8\">Asia/Shanghai</option><option value=\"Asia/Singapore\" data-geo=\"1.28333,103.85,+08,SG,+8\">Asia/Singapore</option> ...";

    … in the data

However, this last one both needs more “wading through data” and “consideration” because it seems to be at Google Charts that not even the national boundary is shown when this regional data is not recognized.

The first one, though, is useful in our changed second draft image_chart.php PHP web application for you to try, below, perhaps


Previous relevant Google Chart Image Chart Map Chart Primer Tutorial is shown below.

Google Chart Image Chart Map Chart Primer Tutorial

Google Chart Image Chart Map Chart Primer Tutorial

We hope today’s work does not confuse terms, because we’re exploring a new area of Google Charts functionality today they refer to as …

  • Google Charts Image Charts … and you’ll see there lots of suboptions we’ll explain a bit more about later, and all this is separate functionality to …
  • Google Charts Map Chart … and …
  • Google Charts Geo Chart

… and, as of today, we interface to all three categories of Google Charts above, with three separate PHP web applications.

So, what’s the potential confusion? Well, we start out today interfacing to an Image Chart suboption called “Map Chart”, but not the one above, because its look is more in keeping with what the “Geo Chart” above achieves. We’ve written a web application, here, to show regional places within a country (via its 2 letter code) if this has been catered for by Google Charts, and for the most part, that is the case.

And so, on the same theme as yesterday’s Google Chart Geo Chart Zoom In Quiz Translate Tutorial, and thanks to Wikipedia for regional code lookups, we would welcome you to try out our “proof of concept” first draft image_chart.php PHP web application for you to try, below, perhaps …


Previous relevant Google Chart Geo Chart Zoom In Quiz Translate Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Translate Tutorial

Google Chart Geo Chart Zoom In Quiz Translate Tutorial

You could say the way we navigate to our recent …

World Quiz

… from our …

Geo Chart Interfacer

… in the web application as of yesterday’s Google Chart Geo Chart Zoom In Quiz Hints Tutorial was a bit cryptic, or convoluted, the way at a first prompt window we’d change an entry from the default My World Survey to My World Quiz or even to click that button that we’d arranged in this blog posting thread. Nevertheless, we were a bit loathe to change the arrangements, until we ran into problems involving today’s work of …

Adding a Google Translate layer on top of the World Quiz

… to facilitate some Internationalization (ie. language translation from English to non-English) into the mix. Yes, our PHP caused problems interfacing to Google Translate. So, what was our approach? We took a snapshot (ie. web browser View -> Page Source) at a point after the convolutions above, and worked off that to introduce a new code file member. Welcome …

… via our proof of concept geochart.html clientside only web application version (or the old access approach in all these changes to geo_chart.php PHP web application still works). Any downside doing this? A little, in that within a Google Translate “bubble” we could not work the Wikipedia images hint part of the logic. Also, you may run into problems with SVG image backgrounds using an svg+xml protocol, or we may just have been having a bad day?! So sad.


Previous relevant Google Chart Geo Chart Zoom In Quiz Hints Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Hints Tutorial

Google Chart Geo Chart Zoom In Quiz Hints Tutorial

Yesterday’s Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial showed us …

  • using a web inspector to dynamically change CSS styling in place preparatory to making a permanent change … well, today, we’re here to reiterate …
  • using a web inspector can help with a myriad of Javascript logic errors or debugging, as well

… and we do that today adding hints to all these changes to geo_chart.php Geo Chart interfacer at this live run World Quiz web application link or click a button down below.

Do the hints look familiar? Take a read of Javascript Lazy Evaluation Country Game Hints Tutorial and it all might come back to you!


Previous relevant Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial

Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial

We recently revisited the PHP web application we call …

Google Chart Geo Chart Zoom In Quiz

… last talked about at Google Chart Geo Chart Zoom In Quiz Sharing Tutorial, and noticed a bit of ugliness regarding its CSS styling, specifically related to the “too large” border-radius values we’d applied to the twin iframes cutting off wording in their bottom left corner.

This issue is an …

  • aesthetics, only …
  • CSS styling

… one … queue the Web Inspector! How come? Well, web inspectors, such as Google Chrome web browser’s one, allow you to …

  • in place … on our macOS MAMP local Apache/PHP/MySql web server system …
  • dynamically tweak …
  • CSS styling … especially good with inline CSS style syntax, that we happen to be very fond of too … so as to be able to …
  • make the changes for you to optionally re-tweak … ephemerally

… on a test system (ours being a macOS MAMP local Apache/PHP/MySql web server one) ahead of uploading and committing to a permanent change up at the live and public RJM Programming web server domain.

Take a look at how we went about what went into the aesthetically tweaked geo_chart.php Geo Chart interfacer at this live run link, where we remind you again, a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” in a new window or click a button down below.


Previous relevant Google Chart Geo Chart Zoom In Quiz Sharing Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Sharing Tutorial

Google Chart Geo Chart Zoom In Quiz Sharing Tutorial

Adding functionality to yesterday’s Google Chart Geo Chart Zoom In Quiz Tutorial we see an opportunity to …

  • add an element of “when” functionality onto the “where” strengths of the Google Chart Geo Chart recent work, via PHP TimeZones and interfacing to the work of the recent Looks Nice Nearby Speech to Text Game Video Tutorial … as well as …
  • means by which to share or collaborate with the “My World Zoom In Quiz” … via …
    1. email 📧 (via inline HTML PHP mail) … or …
    2. SMS 📟 (via “a” tag href=sms: link)

… and that last SMS methodology brought into focus our wish not to allow, yet, a URL approach to get directly to this new “My World Zoom In Quiz” (although we may change this strategy into the future). So, how to apply security over the use of a URL such as …

https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?wqperspective=Monday+10+Feb+2020+17:57:15.7182

… not linked, above, because there is no point. We have already clicked it in an SMS we got sent, and that nullifies its use from then on? Huh?! Yes, we use the PHP itself, as we are fond of doing, storing (a form of) that “Monday+10+Feb+2020+17:57:15.7182” away as a comment in amongst the PHP code and, hence, “file_get_contents” checkable by its or some other PHP code for its existence (as well as the “file_put_contents” based clean up removal of said comment after the SMSee’s (body) link is ever clicked), as the security check for whether we navigate to the “My World Zoom In Quiz” (bringing up that last correct answer) via an SMS body URL link, clicked by an SMSee. And that collaborator can do the same thing back to the original sender for the next wrong answer’s similar 📟 emoji button press instigation of this sharing and collaboration Javascript logic …


function smswho() {
if (smsorig == '') { smsorig=document.getElementById('smssend').href.split('0000')[0]; }
if (smsdateorig == '') { smsdateorig=document.getElementById('smsdate').value; }
var smsto=prompt('SMS to?', document.getElementById('smssend').href.split('sms:')[1].split('?')[0]);
if (smsto == null) { smsto = ''; }
if (smsto.trim() != '') {
document.getElementById('smsdate').value=smsdateorig + '.' + gsv.substring(0,1).charCodeAt(0) + gsv.substring(1).substring(0,1).charCodeAt(0);
document.getElementById('smsbut').click();
document.getElementById('smssend').href=(smsorig + '' + gsv.substring(0,1).charCodeAt(0) + gsv.substring(1).substring(0,1).charCodeAt(0)).replace('sms:?','sms:' + smsto + '?');
document.getElementById('smssend').click();
}
}


function emailwho() {
var emto=prompt('Email to?', document.getElementById('emailto').value);
if (emto == null) { emto = ''; }
if (emto.indexOf('@') != -1) {
document.getElementById('emailto').value=emto;
document.getElementById('hcont').value='<html><body><form action=' + document.URL + ' method=POST><input type=hidden value=' + gsv + ' name=wqperspective></input><input type=submit value=\"My World Zoom In Quiz\" style=\"background-color:yellow;\"></input></form></body></html>';
document.getElementById('iemail').click();
}
}

… in the context of all these changes to geo_chart.php Geo Chart interfacer at this live run link, where we remind you again, a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” in a new window.


Previous relevant Google Chart Geo Chart Zoom In Quiz Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Tutorial

Google Chart Geo Chart Zoom In Quiz Tutorial

Today we’re combining …

… to create another form of quiz (we think of as “My World Zoom In Quiz”) the user can navigate to via the way they answer that first title prompt (substituting “Survey” with “Quiz”). You might prefer to think of it as the “Geographical Perspective Quiz” with a degree of difficulty, often, because to see a “Zoomed In” display of a country or region can be disorienting and challenging to recognize. And so, for incorrect dropdown answers, we provide a “zoomed out” world view of where that “zoomed in” view sits (like an inset).

In order to show you this below please click

Again, a bit of a different tack to yesterday with the reworked geo_chart.php Geo Chart interfacer at this live run link, where a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” (like above) in a new window.


Previous relevant Google Chart Geo Chart Small Region Tutorial is shown below.

Google Chart Geo Chart Small Region Tutorial

Google Chart Geo Chart Small Region Tutorial

Meanwhile, resuming our dreams of Andorra, there must be hundreds of readers there a bit sick of us going on and on and on and on and on about our Google Chart Geo Chart interfacing Quizzes and the use of complex “width” (and “height”) prompt user interactions. After all, we came onto this topic more to do with “small countries”. Well, let’s go back to that and let’s say …

  • as well as the “markers” mode (geographicals) latitude and longitude (helped out by PHP TimeZone places) way of signifying the position of a small country on a world or continent map … always, there behind the scenes, set up ages ago, was the interfacing we had set up to …
  • connect with the Google Chart “smarts” regarding “region” mapping to be able to hone in on a “region” (which can mean a whole country too) of interest

… and that means, today, we revisit our imaginary jaunts in Andorra setting out from the big smoke of …


Andorra la Vella

… to the border tranquillity of …


Pas de la Casa

… in the scenario of today’s tutorial picture … honing in on the user interaction before the width one (yayyyyyy!) with that title prompt. At this prompt we make use of two extensions to default behaviour with our PHP web application, those being …

  1. prefix of “region code” + “;” ( in the case of Andorra an ISO 2 Character Country Code “AD” + “;” = porkAD; )
  2. suffix of “heads up” placename list (making it so you will probably not need to fish around for any latitude and longitude geographicals yourself) via &areplaces=[comma (and + if you want lines joining) separated placename list] … eg. &areplaces=Andorra la Vella,+Pas de la Casa

… to end up with a user title data item user interaction entry of …


AD;My World Survey&areplaces=Andorra la Vella,+Pas de la Casa

… as the lead in to “not much thinking” (and as long as you are not Pinocchio, “follow your nose” ease) required for the other non-quiz-based prompts (ie. no need for width or height mantissae …

… in this scenario).

Quite a bit of a different tack to yesterday’s Google Chart Geo Chart Quiz Tooltip Flag Tutorial that you can see how we needed to tweak geo_chart.php Geo Chart interfacer at this live run link, showing the versatility and usefulness of Google Chart Geo Charts.


Previous relevant Google Chart Geo Chart Quiz Tooltip Flag Tutorial is shown below.

Google Chart Geo Chart Quiz Tooltip Flag Tutorial

Google Chart Geo Chart Quiz Tooltip Flag Tutorial

Yesterday’s Google Chart Geo Chart Quiz on Mobile Tutorial‘s Google Chart Geo Chart interfacing uses …

  • onmouseover event tooltip functionality for non-mobile platforms … and, better something than nothing, we guess …
  • first onclick event tooltip functionality for mobile platforms

… a blessing, in our view, that an onmouseover (ie. on hover) piece of functionality thinking survives into the mobile platform wooooooooorrrrrlllddd in some way shape or form. We generally find tooltips an optimistic and useful webpage functionality tool.

And with this in mind, it was worth our mind’s attention to ask … “what about if the Geo Chart Quiz functionality can, optionally, help out the user a bit without giving the game away?” … in the sense that ISO 2 character country codes can be baffling, yet help to make the quiz a challenge, on occasions, though enough of a turn off for some users, we’re sure. But to place an Emoji Flag could be a feature some quizzers will like and appreciate.

Rather than add to the navigational data we’d rather “add” an Emoji Flag on being “flagged” (tee hee) to do so, that “flagging” being to add argument “&flag=y” into the mix, at the width value prompt, which is the same prompt whereby a user decides to create a quiz in the first place. And because Emojis represent text data (albeit multibyte ones) we won’t even need to change data structures, just data content involving the one string structure member of …


['Latitude','Longitude','Country','Countdown']

… which we’ve been sending as that country’s ISO 2 character code (to leave some challenge to the quizzer, where the user has been seeing that ISO code only “on hover” up to today) … but if the user has “flagged” &flag=y this code below swings into play appending text data onto that ISO Code text data (of PHP variable (and argument) “$instuff” below) via String.fromCodePoint() function, as per …

<?php

$lri=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
$dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];

function maybequizflag($instuff) {
global $GETdata, $iso_country_codes, $flagentity, $lri, $dri;
if (isset($_GET['quiz']) || isset($_POST['quiz'])) {
if (isset($_GET['flag']) || isset($_POST['flag'])) {
if (strpos($instuff, "['Lat','Long',") !== false) {
return $instuff; //str_replace("'Country',", "'Country','Flag',", $instuff);
} else {
$outstuff=$instuff;
$cbits=explode("'", $instuff);
$outstuff=$cbits[0];
$uretv=" ' + '";
for ($iol=1; $iol<sizeof($cbits); $iol++) {
if (($iol % 2) == 1) {
if (strlen($cbits[$iol]) == 2) {
for ($jjm=0; $jjm<strlen($cbits[$iol]); $jjm++) {
for ($jm=0; $jm<sizeof($lri); $jm++) {
if (strtoupper(substr($cbits[$iol],$jjm,1)) == $lri[$jm]) {
$uretv=str_replace(" + '", " + String.fromCodePoint(" . $dri[$jm] . ") + '", $uretv); //uvaltosfcp($dri[$jm]);
}
}
}
$outstuff.="'" . $cbits[$iol] . $uretv;
$uretv="' + '";
} else {
$uretv=" ' + '";
for ($im=1; $im<sizeof($iso_country_codes); $im+=2) {
if ($uretv == " ' + '" && strpos(strtolower($iso_country_codes[$im]), strtolower(str_replace("%20"," ",str_replace("%E2%80%99","",str_replace("%2C",",",$cbits[$iol]))))) !== false) {
for ($jjm=0; $jjm<strlen($iso_country_codes[-1 + $im]); $jjm++) {
for ($jm=0; $jm<sizeof($lri); $jm++) {
if (strtoupper(substr($iso_country_codes[-1 + $im],$jjm,1)) == $lri[$jm]) {
$uretv=str_replace(" + '", " + String.fromCodePoint(" . $dri[$jm] . ") + '", $uretv); //uvaltosfcp($dri[$jm]);
}
}
}
}
}
$outstuff.="'" . $cbits[$iol] . $uretv;
$uretv="' + '";
}
} else {
$outstuff.="'" . $cbits[$iol];
}
}
return $outstuff; //str_replace("',9", "','x',9", str_replace("',8", "','x',8", str_replace("',7", "','x',7", str_replace("',6", "','x',6", str_replace("',5", "','x',5", str_replace("',4", "','x',4", str_replace("',3", "','x',3", str_replace("',2", "','x',2", str_replace("',1", "','x',1", str_replace("',0", "','x',0", $instuff))))))))));
}
}
}
return $instuff;
}

?>

Again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Quiz on Mobile Tutorial is shown below.

Google Chart Geo Chart Quiz on Mobile Tutorial

Google Chart Geo Chart Quiz on Mobile Tutorial

We wanted to improve on the recent Google Chart Geo Chart More Quizzes Tutorial‘s “World Quiz” functionality approach of displaying window.open popups for mobile platforms. The reason for the concern on mobile platforms, and not such a concern on non-mobile platforms (though there is a concern about popup window web browser disabling settings), because the chance to “overlay” a popup window (via the use of a third argument to window.open calls) is ignored on mobile platforms, instead opening a new browser tab (at best). This can be disconcerting, akin to telling a room of students doing an important examination, to look out the window at an interesting magpie (warbling about Collingwood’s last triumph, no doubt).

Well, after extensive research, and first trying to position “anything new” down the bottom of the webpage we …

  • rejected idea of whole display of a relevant Wikipedia page content at the bottom (of a mobile user’s Geo Chart “quiz” webpage) … associated with a …
  • rejected “a” hashtag link down the bottom (but above proposed content above) to navigate back up to the quiz … to, instead …
  • start thinking that it is up to the mobile user to act themselves to ever navigate away from the quiz webpage, so, instead, initially condense the Wikipedia content down to an image that is …
    1. if HTTPS:// protocol being used, use the Google Page Insights screenshotting “smarts” you can see being used at PDF Slideshow and Form Creation Data URI Contents Tutorial
    2. if HTTP:// protocol being used, use the (thumbnail version of) the first image of the relevant Wikipedia webpage

    … encased by an “a” tag that the click of navigates the user to the relevant Wikipedia content in a new tab (at best), all positioned at the left hand side of the Geo Chart webpage’s H1 or H2 tag heading as a 70px width42px height thumbnail

The conduit here are Ajax Javascript techniques as per …


var myxhr = false;
var oursrc = '';
var woourl='';


function ajit(wourl) {
woourl=wourl;
var xurl = '';
if (document.URL.toLowerCase().indexOf('https') == 0) {
xurl='https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=' + encodeURIComponent(wourl) + '&screenshot=true';
} else {
xurl=document.URL.split('/GeoChart')[0] + '/fgc/?tdinto=&inurl=' + encodeURIComponent(wourl);
}
if (window.XMLHttpRequest) {
myxhr = new window.XMLHttpRequest;
}
else {
try {
myxhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (othermicrosoft) {
try {
myxhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (failed) {
myxhr = false;
}
}
}
if (myxhr) {
myxhr.onreadystatechange = backin;
myxhr.open('GET', xurl, true);
myxhr.send(null);
}
}


function backin() {
if (myxhr.readyState == 4) {
if (myxhr.status == 200) {
if (myxhr.responseText) {
var dbits = myxhr.responseText.split('\"data\":');
if (dbits.length > 1) {
oursrc='data:image/jpeg;base64,' + dbits[1].split('\"')[1].split('\"')[0].replace(/\_/g,'/').replace(/\-/g,'+');
ism='nm';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ism='';
document.getElementById(ism + 'dwoalttwo').style.position='absolute';
document.getElementById(ism + 'dwoalttwo').style.left='20px';
document.getElementById(ism + 'dwoalttwo').style.top='0px';
document.getElementById(ism + 'dwoalttwo').style.opacity='0.95';
document.getElementById(ism + 'dwoalttwo').style.zIndex='51';
} else {
document.getElementById(ism + 'dwoalt').innerHTML='<br><a id=btta href=#myh title=Top>Back to top</a>';
}
document.getElementById(ism + 'dwoalttwo').innerHTML='<a target=_blank id=adw title=Wikipedia style=z-index:52; href=' + woourl + '><img title=Wikipedia style=width:80px;z-index:52; src=' + oursrc + '></img></a>';
document.getElementById('myh').onclick=function() { document.getElementById('adw').click(); }
if (ism != '') { location.href='#btta'; }
} else if (myxhr.responseText.indexOf('<img') != -1) {
dbits = myxhr.responseText.split('<img');
dbits=dbits[1].split(' src=');
ism='nm';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ism='';
document.getElementById(ism + 'dwoalttwo').style.position='absolute';
document.getElementById(ism + 'dwoalttwo').style.left='20px';
document.getElementById(ism + 'dwoalttwo').style.top='0px';
document.getElementById(ism + 'dwoalttwo').style.opacity='0.95';
document.getElementById(ism + 'dwoalttwo').style.zIndex='51';
} else {
document.getElementById(ism + 'dwoalt').innerHTML='<br><a id=btta href=#myh title=Top>Back to top</a>';
}
document.getElementById(ism + 'dwoalttwo').innerHTML='<a target=_blank id=adw title=Wikipedia style=z-index:52; href=' + woourl + '><img title=Wikipedia style=width:80px;z-index:52; src=' + dbits[1].split(' ')[0].split('>')[0] + '></img></a>';
document.getElementById('myh').onclick=function() { document.getElementById('adw').click(); }
if (ism != '') { location.href='#btta'; }
}
}
}
}
}

… with the effect, for a mobile user, of not being interrupted from their quiz, unless this thumbnail (Wikipedia content) appears at the top left, that they can “long click” to open in a “New Tab” (or, perhaps, a “Split View”) as required, at least on the iPad we tried this with.

And so, you can try the changed geo_chart.php Geo Chart interfacer at this live run link, we hope representing an improvement for the Quizzing User Experience for our mobile user readers.


Previous relevant Google Chart Geo Chart More Quizzes Tutorial is shown below.

Google Chart Geo Chart More Quizzes Tutorial

Google Chart Geo Chart More Quizzes Tutorial

In allowing the World Quiz web applications of yesterday’s Google Chart Geo Chart World Quizzes Tutorial work accept more than about …

  • the 10 places (per continent Geo Chart) fitting into a $_GET arguments URL (of about 850 characters, for rjmprogramming.com.au domain) … the first cab off the rank allowing for …
  • a lot more than 10 can be accepted via $_POST in an HTML form method=POST action=./geo_chart.php

You may wonder why “first cab off the rank” here. Well, we’re not sure we won’t involve window.sessionStorage or window.localStorage in future plans. It being PHP we’re writing though, we will need a compelling reason to try this.

We allow you to ask the web application to try more places by (optionally) appending space characters onto the height values they enter.

You can try the changed (and note “function iftoobig()” in particular, here) geo_chart.php Geo Chart interfacer at this live run link, and try it with a few right space appended “heights” to try out this new functionality.


Previous relevant Google Chart Geo Chart World Quizzes Tutorial is shown below.

Google Chart Geo Chart World Quizzes Tutorial

Google Chart Geo Chart World Quizzes Tutorial

We’re heading towards “prove it for n” on top of the recent Google Chart Geo Chart Oceania Quiz Tutorial (“prove it for 2”) progress, making quizzes for …

  • Europe
  • South East Asia and Oceania
  • Africa
  • South America
  • North and Central America
  • Asia

… but feel we need more testing to bed it down, as far as reliability issues go, and we’ll keep you posted on that.

We found clutter issue with ISO 2 character Country Codes …

ISO Code 1 Country TZ Place 1 (Lat,Long) Too Close To Country TZ Place 2 (Lat,Long) ISO Code 2
VA Vatican City
(41.90222,
12.45305)
(-0.02,
+0.03)
Rome, Italy
(41.9,
12.48333)
IT
BJ Porto-Novo, Benin
(6.48333,
2.61666)
(-0.03,
+0.78)
Lagos, Nigeria
(6.45,
3.4)
NG

… and so “fashioned” this into a numerical basis for a “declutter” algorithm


function setsixteenquiz() {
var sixteen=16;
var allcontinents=['Europe','South East Asia and Oceania', 'Africa', 'South America', 'North and Central America', 'Asia'];
var thiscontinent=isquiz;
var cisq=-1;
var exclusions=',';
var sofarq=',-1,';
var ourselceqih=selceqih.replace(/\ data\-alt\-/g, ' data-');
if (thiscontinent == 'South East Asia and Oceania') {
sixteen=10;
} else if (thiscontinent == 'Africa') {
sixteen=17;
} else if (thiscontinent == 'South America') {
sixteen=10;
} else if (thiscontinent == 'North and Central America') {
sixteen=10;
}
for (var isqis=0; isqis<allcontinents.length; isqis++) {
if (allcontinents[isqis] != thiscontinent) {
while (ourselceqih.indexOf(' data-continent=\"' + allcontinents[isqis] + '\"') != -1) {
ourselceqih=ourselceqih.replace(' data-continent=\"' + allcontinents[isqis] + '\"','');
}
}
}
var sqws=ourselceqih.split(' data-continent=\"' + thiscontinent + '\" value=\"');
document.body.title='Awaiting quiz clickable circle symbols to score ...';
document.body.style.cursor=pcur;
if (document.getElementById('chart')) {
document.getElementById('chart').title='Awaiting quiz clickable circle symbols to score ... ';
document.getElementById('chart').style.cursor=pcur;
}
var latsofar=[], longsofar=[], thislats=0.0, thislongs=0.0;
var valid=true, ivalid=0, difflatlong=0.0;

while (quizisos.length < sixteen) {
cisq=-1;
while (sofarq.indexOf(',' + cisq + ',') != -1 || exclusions.indexOf(',' + cisq + ',') != -1) {
cisq=Math.floor(Math.random() * eval(-1 + sqws.length));
cisq++;
if (ourtzlist.indexOf(',' + sqws[cisq].split('\"')[0] + ',') != -1) {
thislats=(eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[0]));
thislongs=(eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]));
}

if (thiscontinent == 'South East Asia and Oceania') {
if (ourtzlist.indexOf(',' + sqws[cisq].split('\"')[0] + ',') != -1) {
if (eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]) < 73.0) { // || eval(ourtzlist.split(',' + ourselceqih[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + ourselceqih[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]) >= 169.0) {
cisq=-1;
}
} else {
cisq=-1;
}
}
}
sofarq+='' + cisq + ',';
if (cisq != -1) {
if (sqws[cisq].split('\"')[0] == 'IT') { exclusions+='VA,'; } else if (sqws[cisq].split('\"')[0] == 'VA') { exclusions+='IT,'; }
if (sqws[cisq].split('\"')[0] == 'BJ') { exclusions+='NG,'; } else if (sqws[cisq].split('\"')[0] == 'NG') { exclusions+='BJ,'; }
difflatlong=0.0;
if (quizisos.length > 0) {
for (ivalid=0; ivalid<quizisos.length; ivalid++) {
difflatlong=Math.abs(eval('' + latsofar[ivalid]) - eval('' + thislats)) + Math.abs(eval('' + longsofar[ivalid]) - eval('' + thislongs));
}
}
if (difflatlong >= 2.0 || quizisos.length == 0) {
latsofar.push(thislats);
longsofar.push(thislongs);
quizisos.push(sqws[cisq].split('\"')[0]);
}

}
}
quizisos.push(\"\");
}

Here’s your chance to try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter Africa, South America, North and Central America and Asia Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Oceania Quiz Tutorial is shown below.

Google Chart Geo Chart Oceania Quiz Tutorial

Google Chart Geo Chart Oceania Quiz Tutorial

Regular readers will know about our penchant for “mathematical induction” theory, in the way you …

  • prove it for 1
  • prove it for 2
  • prove it for n

… and earlier this morning “too proud” moi thought we’d be at “n”, skipping “2” by now getting our Geo Chart interfacing new “Quiz” functionality to have covered user interactions for all the major continents of greater than 10 (of category) places, looking towards the “10 is a bit lame” thinking, to follow. Oh, well! But maybe that’s the point of the “2” in the “mathematical induction” proof “game”. A lot might be discovered, and so it was for us, trying to open the door to … come in …


South East Asia and Oceania ...

… spinner! In broad brush concepts, we discovered …

  • we needed to start to worry about places with an ISO 2 code but no TimeZone …
  • we needed to start to worry about places off to the left, right, and top limits of the Geo Chart limits we establish via those weird width and height values you enter … and on this am sure many will have tweaked that the value integer parts are like a “scalar” measure and the mantissae are a “left zero padded percentage offset into the entire Geo Chart on which to lob” measure
  • we needed to rearrange the scoring system’s denominator as a “seconds timer” rather than a “number of goes”
  • we needed to, at least at the start, mention name of Quiz
  • we needed to start closing previous Wikipedia windows on opening a new one, as applicable
  • we needed to start to worry about clutter (eg. Vatican City and Rome geographicals for two different countries)
  • we needed to start to worry about “skewed representations” (going back to Europe Quiz) whereby the first mention of a country ISO 2 Code within the TimeZone list is a position of a colony or dominion

… whereas we optimistically imagined all we might need to worry about was just …

  • converting (boolean binary decision) variable isquiz=false/true (Javascript code logic) into (string ternary and more decision) variable isquiz=”/’Europe’/’South East Asia and Oceania’ (with more to come … until “n” (for) nirvana) … and associated …
  • adding data-continent=”South East Asia and Oceania” global data attributes into dropdown id=’selceq’ linking ISO 2 codes with Country names
  • trying to add a bit of cursor=’progress’ flagging of web application “thinking time”

Never mind! And so, onto yesterday’s Google Chart Geo Chart Europe Quiz Tutorial progress there is not that much difference user interaction wise, just the offer of another weird “width” value choice (on which to blow your mind) but behind the scenes a “hard working mathematical induction middlemanperson” can now offer you the chance to try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter South East Asia and Oceania Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Europe Quiz Tutorial is shown below.

Google Chart Geo Chart Europe Quiz Tutorial

Google Chart Geo Chart Europe Quiz Tutorial

Up to yesterday’s Google Chart Geo Chart Sorted Small Countries Tutorial, as with interfacings to other Google Charts, we had a two phase aspect to the web application structures …

  1. ask for user interaction via the keyboard
  2. display the resultant Google Chart taking notice of that user interaction

… but today’s extension of Geo Chart interfacing functionality opens the door to the new

  • display the resultant Google Chart taking notice of that user interaction and allowing click/touch continuing interaction in the form of a quiz … first cab off the rank … Europe Quiz

The work recently has helped because …


function gck(igck) {
var ansis='';
if (document.getElementById('attachedImage' + ('' + igck).replace('-1',''))) {
var xxx=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).getAttribute('title');
if (xxx.indexOf('#') != -1) {
if (isquiz) {
maybe_bad=false;
if (xxx.split('#')[1].indexOf('/') != -1) {
ansis=xxx.split('#')[1].split('/')[eval(-1 + xxx.split('#')[1].split('/').length)].toLowerCase();
} else {
ansis=xxx.split('#')[1];
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(xxx.split('#')[1],'_blank', 'top=50,left=50,width=500,height=500');
} else if (xxx == '') {
if (isquiz) {
maybe_bad=false;
if (document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title.indexOf('/') != -1) {
ansis=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title.split('/')[eval(-1 + xxx.split('#')[1].split('/').length)].toLowerCase();
} else {
ansis=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title;
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title,'_blank', 'top=50,left=50,width=500,height=500');
} else {
if (isquiz) {
maybe_bad=false;
if (xxx.indexOf('/') != -1) {
ansis=xxx.split('/')[eval(-1 + xxx.split('/').length)].toLowerCase();
} else {
ansis=xxx;
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(xxx,'_blank', 'top=50,left=50,width=500,height=500');
}
}
}

… is an onclick place we’ve set aside for our SVG intervention work. Keep it to no keyboard for this Europe Quiz, and we are happy (with this new idea, reminiscent of recent tweaking at Google Chart Annotated Timeline Whitespace Delimitation Tutorial).

So, again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter Europe Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Sorted Small Countries Tutorial is shown below.

Google Chart Geo Chart Sorted Small Countries Tutorial

Google Chart Geo Chart Sorted Small Countries Tutorial

Yesterday’s Google Chart Geo Chart Small Countries Overlay Tutorial‘s workings potentially using the geographicals (or marker) mode of use actually involve intervention logic within what Google provide SVG-wise for the Geo Chart content.

And so, for some time, the order in which we entered …

Country Surface Area (sq km)
Australia 7692024
New Zealand 269190
Andorra 468

… we entered, interactively by us, like, personally, like, in that order above, like. But for a day or two we were covering up a gap in the “wall of logic” plaster we had created for Google Chart select event logic (actually non-existant for the Geo Chart, but we code for onclick logic to navigate a user to a relevant Wikipedia page). The good news is we have fixed it now, not tying the user down to entering data in any particular order.

Fixed what, now? (I thought I heard you ask?!) Well, the alignment of &aregeographical= data to the symbology presented at the geographical positions on the Geo Map asks that the order we present corresponds to the relevant order of relevant Google SVG elements, and Google orders these from the largest numerical value down to the smallest, as you notice as far as Surface Area (sq km) suits an order of Australia, New Zealand, Andorra …

First non-overlay URL version goes https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-34.91667|138.58333|~Australia~,7692024]%20,%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
Second overlay URL version goes https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-34.91667|138.58333|~Australia~,7692024]%20,%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20&overlay=y&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
But the recent work means overlay URL version created interactively with order New Zealand, Andorra, Australia https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20,%20[-34.91667|138.58333|~Australia~,7692024]%20&overlay=y&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
also works

… and the changes necessary to ensure this go


// var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;
function assess_small(indatar) {
var ipl=0, jpl=0, kpl=0, pushxx=[];
var outsuffix='';
var outdatar=indatar;
if (pushfrom.length > 0 && !oneisnotapplicable && oneistoosmall) {
for (jpl=0; jpl<pushfrom.length; jpl++) { // for (var ipl=0; ipl<pushfrom.length; ipl++) {
if (jpl == 0) {
var huhdatas=indatar.split('~');
for (var ihuhdatas=2; ihuhdatas<huhdatas.length; ihuhdatas+=2) {
if (huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0].replace('%20',' ').indexOf(' ') != -1) {
pushxx.push(('00000000000000000000000' + huhdatas[ihuhdatas].split(',')[1].split(']')[0]).slice(-22) + ' ... ' + huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0]);
}
pushxx.push(('00000000000000000000000' + huhdatas[ihuhdatas].split(',')[1].split(']')[0]).slice(-22) + ' ... ' + encodeURIComponent(huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0]));
}
pushxx.sort();
pushxx.reverse();
}
ipl=jpl;
for (kpl=0; kpl<pushfrom.length; kpl++) {
if (ipl == jpl && pushxx[jpl].split(' ... ')[1] == pushfrom[kpl].split('~')[1].split('~')[0]) {
ipl=kpl;
pushxx[jpl]=pushxx[jpl].split(' ... ')[0] + ' ... ';
}
}

if (outdatar.indexOf(pushfrom[ipl]) != -1) {
if (outsuffix == '') {
outsuffix='&aregeographicals=' + pushag[ipl];
} else {
outsuffix+='%2C' + pushag[ipl];
}
while (outdatar.indexOf(pushfrom[ipl]) != -1) {
outdatar=outdatar.replace(pushfrom[ipl], pushto[ipl]);
}
}
}
}


return outdatar + outsuffix;
}

Yet again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Small Countries Overlay Tutorial is shown below.

Google Chart Geo Chart Small Countries Overlay Tutorial

Google Chart Geo Chart Small Countries Overlay Tutorial

With “overlay” techniques available in life it might be tempting to say “never say never” because you don’t have to compromise a weak solution for a less weak solution. Yesterday’s Google Chart Geo Chart Small Countries Tutorial‘s Google Chart Geo Chart‘s homegrown interfacer tactics for Small Countries is a case in point.

You may recall from yesterday how we dynamically reverted to “geographicals mode” display (Google call it “Markers” mode) when the shading for a Small Country would lead to “data loss”. But what if we …

  • continue what we were doing yesterday “overlayed”

    … onto …

  • what we changed from URL-wise with “function assess_small()” (with the one codeline change

    outsuffix='&overlay=y&aregeographicals=' + pushag[ipl];

    ) … in the form of two new HTML iframe code below …
    <?php

    if (isset($_GET['overlay']) || isset($_POST['overlay'])) {
    echo "<script> function overlayit() {
    var ourls=documentURL.split('&overlay=')[0].split('[');
    var ourl=ourls[0];
    for (var iouris=1; iouris<ourls.length; iouris++) {
    if (ourls[iouris].substring(0,1) == '~') {
    ourl+='[' + ourls[iouris];
    } else {
    ourl+='[' + ourls[iouris].replace(ourls[iouris].split('~')[0],'');
    }
    }
    document.body.style.zIndex='-12';
    document.getElementById('doverlay').innerHTML='<iframe style=\"position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:2;opacity:0.95;\" src=\"' + ourl + '\"></iframe>';
    document.getElementById('doverlaytwo').innerHTML='<iframe style=\"position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:22;opacity:0.9;\" src=\"' + documentURL.replace('&overlay=','&qw=') + '&guess=' + '\"></iframe>';
    }
    setTimeout(overlayit, 2000);
    </script>
    ";
    }

    ?>

Again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Small Countries Tutorial is shown below.

Google Chart Geo Chart Small Countries Tutorial

Google Chart Geo Chart Small Countries Tutorial

We last used the excellent Google Chart Geo Chart tool with the work of Window LocalStorage Client Versus Server Map Tutorial, and it was this project that alerted us to both a weakness and a strength of that chart …

  • a weakness being its inability to get the resolution to shade a small country (eg. today’s tutorial picture‘s Andorra) … but, the good news, as used with this integration work above …
  • a strength is the alternative display mechanism via geographical entries

… and so, what if …

  • as the user enters in their Country (or Geographical) data …
  • if we can determine it as being a Country being entered … and…
  • you have only ever been entering Countries … and …
  • any one Country so defined has a surface area less than 10000 square kilometers … then …
  • we navigate to a Geographical data version of this “only Countries entered” data set … so that …
  • even small such Countries will be displayed …
  • as they would not if still in the default “only Countries entered” mode of display

We introduce three new sources of data in order to piece together the (Javascript via PHP coding) logic for this …

  1. TimeZone and Geographicals and ISO 2 Letter Code information …

    var ourtzlist='<option value="Africa/Abidjan" data-geo="5.31666,-4.03334,GMT,CI,+0">Africa/Abidjan</option><option value="Africa/Accra" data-geo="5.55,-0.21667,GMT,GH,+0">Africa/Accra</option>'; // etcetera etcetera etcetera
  2. Country Name and ISO 2 Letter Code information (etcetera etcetera etcetera) …

    <div id=dlookups>
    <select id='selceq' style='display:none;'>
    <option value='AF'>Afghanistan</option>
    <option value='AX'>Aland Islands</option>
    <option value='AL'>Albania</option>
    </select></div>
  3. Surface Areas of Countries thanks to Wikipedia (etcetera etcetera etcetera) …

    <table style='display:none;' id='surface_area' border='1' cellpadding='2' cellspacing='0'>
    <tbody><tr bgcolor='#efefef'>
    <th>Pos
    </th><th>Country
    </th>
    <th>Area (km²)
    </th></tr>
    <tr>
    <td>1</td>
    <td><a data-href='/wiki/Russia' title='Russia'>Russia</a></td>
    <td>17098246
    </td></tr>
    <tr>
    <td>2</td>
    <td><a data-href='/wiki/Canada' title='Canada'>Canada</a></td>
    <td>9984670
    </td></tr>
    <tr>
    <td>3</td>
    <td><a data-href='/wiki/People%27s_Republic_of_China' title='People's Republic of China'>China</a></td>
    <td>9572900
    </td></tr>
    </tbody></table>

… used where we process a user Country (or Geographical) interaction Javascript code snippet where variable thisris is that user interaction result …


var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;

if (ourtzlist.indexOf(',' + thisris.toUpperCase() + ',') != -1 && thisris.length == 2) {
if (selceqih == '') { selceqih=document.getElementById('selceq').innerHTML; }
if (saih == '') { saih=document.getElementById('surface_area').innerHTML; }
pushfrom.push('[~' + thisris + '~');
pushto.push('[' + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + thisris.toUpperCase() + '~');
if (selceqih.indexOf(' value=\"' + thisris.toUpperCase() + '\">') != -1) {
pushag.push('http.' + encodeURIComponent(selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0]));
} else {
pushag.push('');
}
if (saih.indexOf('>' + selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0]) != -1) {
thissa=saih.split('>' + selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0])[1].split('<td>')[1].split('<')[0].split(String.fromCharCode(10))[0];
if (eval('' + thissa) < 10000) {
oneistoosmall=true;
}
}
} else if (('' + thisris).trim() != '' && selceqih.toUpperCase().indexOf('>' + thisris.toUpperCase()) != -1) {
thisisocc=selceqih.toUpperCase().split('>' + thisris.toUpperCase())[0].split(' VALUE=\"')[eval(-1 + selceqih.toUpperCase().split('>' + thisris.toUpperCase())[0].split(' VALUE=\"').length)].split('\"')[0];
pushfrom.push('[~' + encodeURIComponent(thisris) + '~');
pushto.push('[' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + encodeURIComponent(thisris) + '~');
pushag.push('http.' + encodeURIComponent(thisris));
if (thisris.indexOf(' ') != -1) {
pushfrom.push('[~' + thisris + '~');
pushto.push('[' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + encodeURIComponent(thisris) + '~');
pushag.push('http.' + encodeURIComponent(thisris));
}
if (saih.toUpperCase().indexOf('>' + thisris.toUpperCase()) != -1) {
thissa=saih.toUpperCase().split('>' + thisris.toUpperCase())[1];
thissa=thissa.split('<TD>')[1].split('<')[0].split(String.fromCharCode(10))[0];
if (eval('' + thissa) < 10000) {
oneistoosmall=true;
}
}
}

… and if remaining relevant just before the next navigation happens, where variable indatar represents the default “only Countries entered” mode of display value …


// var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;
function assess_small(indatar) {
var outsuffix='';
var outdatar=indatar;
if (pushfrom.length > 0 && !oneisnotapplicable && oneistoosmall) {
for (var ipl=0; ipl<pushfrom.length; ipl++) {
if (outdatar.indexOf(pushfrom[ipl]) != -1) {
if (outsuffix == '') {
outsuffix='&aregeographicals=' + pushag[ipl];
} else {
outsuffix+='%2C' + pushag[ipl];
}
while (outdatar.indexOf(pushfrom[ipl]) != -1) {
outdatar=outdatar.replace(pushfrom[ipl], pushto[ipl]);
}
}
}
}


return outdatar + outsuffix;
}

You can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Window LocalStorage Client Versus Server Map Tutorial is shown below.

Window LocalStorage Client Versus Server Map Tutorial

Window LocalStorage Client Versus Server Map Tutorial

Get a good map, and a goodly number of times you’ll want a map of smaller or larger scale than the one you have. Murphy’s Law? This is probably why in the wonderful woooooooorrrrrrrrlllllld of Google Charts they have included …

  • Geo Chart topographic map of the world or of regions
  • Map Chart terrestrial/satellite map of your group of markers at a zoom level of your choosing

… and hope you can see that the latter can save the day for a Short Distance Trip (corner shop, anyone?!).

So we’ve added onto yesterday’s Window LocalStorage Client Versus Server Timeline Tutorial progress a new toggling button to view a scenario in either Google Chart scenario above.

You can see this integration work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link supervising a tweaked geo_chart.php Geo Chart interfacer.


Previous relevant Window LocalStorage Client Versus Server Timeline Tutorial is shown below.

Window LocalStorage Client Versus Server Timeline Tutorial

Window LocalStorage Client Versus Server Timeline Tutorial

Up to yesterday’s Window LocalStorage Client Versus Server User Tutorial‘s progress, our Capital City Find Matching Country Report web application project was all about …

  • where (and capital of “what”) … but we often seek out a way to add into the mix that 4th dimension …
  • when (ie. time)

… and regarding the current project, a …

  • where “map” … can interface with a …
  • when “Trip Plan Itinerary”

… and for this purpose, we’re going to interface to the excellent Google Charts Annotated Timeline Chart, thanks, because it combines links of “time” to “user annotations” in a timeline way, that similar way you might describe the qualities of a Trip, even before you’ve gone on that trip. We’ve also added it so that an unordered places list can be turned into a Trip Plan Itinerary at the click/touch of a new map 🗺 &#128506; emoji button.

Again, see how these timeline amendments were achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link and annotatedtimeline_chart.php which changed quite a lot.


Previous relevant Window LocalStorage Client Versus Server User Tutorial is shown below.

Window LocalStorage Client Versus Server User Tutorial

Window LocalStorage Client Versus Server User Tutorial

The inherent weakness with our current Capital City Find Matching Country Report web application project, to our minds, was that places of interest are not restricted to the Capital Cities of Countries, especially when “Trip Planning”. On the other hand, it would be impossible to cater for every “place” in the world. That is far too subjective for good web application applicability. What would be good though, is to allow in user defined …


Place name, Country name

… terms, the definitions of interest to a user. We can ask this …

  • flagged by the click/touch of an emoji button … and …
  • the interactive entry presented via a Javascript prompt window

. When thinking of data applicable to an individual, then that can be catered for by recording it in localStorage where it will be recalled on the next execution of that web application in the same web browser.

This, along with a Colour Wheel of the “nearest TimeZone place” onto the existing logic of yesterday’s Window SessionStorage Client Versus Server Order Tutorial progress could make for a more useful and practical tool for those Trip Planners out there!

See how this was achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Did you know?

To click/touch one of those Google Chart Geo Chart lines between Emoji Flag Markers will show a new Google Maps directions web page with transport times and detail, as well as an inhouse crow fly distance of that trip leg, as shown up the top right of today’s tutorial picture.


Previous relevant Window SessionStorage Client Versus Server Order Tutorial is shown below.

Window SessionStorage Client Versus Server Order Tutorial

Window SessionStorage Client Versus Server Order Tutorial

If we are to honour our thoughts of being able to use our current Capital City Find Matching Country Report web application as a Trip Planner …

Our primary integration today is to (software) integrate the great Weather Underground and its great API service for autocomplete name searches for weather (and hurricane) information. Why bother? Well, can you not envisage a user using that Ajax functionality of yesterday’s Window SessionStorage Client Versus Server Ajax Tutorial as a trip planner, perhaps, or as a “checking up on relatives overseas” tool, perhaps? And not all the capital cities are timezone places, and so for some of those we can use Weather integration to still show apt online information when click/touching a Countries Report row. Speaking of this “row”, we make an improvement whereby on a first click of a right hand (Country) row cell, that cell is not initially a contenteditable=”true” one (that may frustrate showing the keyboard on mobile, when most likely it was the row touch intended), but then becomes a contenteditable=”true” cell henceforth.

… then yesterday’s Window SessionStorage Client Versus Server Flags Tutorial “progress to now” needs to take notice of a user’s order of multiple select (dropdown) element click/touching of Capital City option (sub)elements, just as we did with the recent User Controlled Dynamic Javascript YouTube Embedded API Ordered Tutorial‘s web application project to allow for a user ordered YouTube video playlist.

Because what is a Trip Planner without an ordered trip? Well, that is debatable, but what isn’t (debatable), is that there will be people in the world who appreciate the “mapping out” of a proposed Trip Planning Itinerary. What could we call on here? We can think of the Google Chart Geo Chart work around about the time of Google Geo Chart Co-ordinate Emojis Tutorial, when we started using …

  • a world map … with …
  • emoji markers … and optionally …
  • joined up by straight lines

… an idea for a Trip Plan itinerary synopsis, perhaps?!

If you examined closely yesterday’s code changes you will have noticed our collecting of TimeZone Place geographical latitude and longitude information. Today, we start making use of that preparatory work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Stop Press

The “emoji markers” above (as of 2 January 2020) will be “country flags” (as per Window SessionStorage Client Versus Server Flags Tutorial ideas), as defined.


Previous relevant Window SessionStorage Client Versus Server Flags Tutorial is shown below.

Window SessionStorage Client Versus Server Flags Tutorial

Window SessionStorage Client Versus Server Flags Tutorial

Yes, there’s more to do onto yesterday’s Window SessionStorage Client Versus Server CSS Tutorial‘s Capital City Find Matching Country Report web application project, in our eyes. We have not even mentioned “Internationalization” as a concept up to now. In this line of thinking …

Did you know?

Emoji flags via ISO 2 character country codes are dead easy via Regional Indicator Symbol characters …


var lri="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];

var thiscc='AU'; // ISO 2 character countrycode for Australia
var ccsuff='', ccchar=' ';
for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
ccsuff+='&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
}
document.getElementById('lastflag').innerHTML=ccsuff;

… to result in (via <span style=font-size:64px;>&#127462;&#127482;</span>) …


🇦🇺

… providing interest and general translatability to the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.


Previous relevant Window SessionStorage Client Versus Server CSS Tutorial is shown below.

Window SessionStorage Client Versus Server CSS Tutorial

Window SessionStorage Client Versus Server CSS Tutorial

Further to yesterday’s Window SessionStorage Client Versus Server Integration Tutorial we have a two pronged improvements set for you today with our current Capital City Find Matching Country Report web application project …

  • CSS styling changes … and …
  • additional functionality for Email and SMS links back to our current Capital City Find Matching Country Report web application project (to complete the cycle)

We use several modes of CSS application (the first and last of particular relevance to today’s “highlighting of workflow” improvements) …

… the “static” measures often helping to highlight the web application’s main workflow of user interaction and the “dynamic” measures helping to alert the user as to where to proceed with their “workflow”.

In terms of CSS styling work …

  1. for non-mobile platforms we allow for more columns to be applied to our Capitals select (dropdown) element (in order to reduce some user scrolling, as does our new additional A-Z letter basis sorting functionality) as per … the “dynamic” Javascript DOM “class” modifications

    if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    document.getElementById('lefttd').className='lefttd';
    }

    … dovetailing with the “static” internal CSS coding

    <style>
    .lefttd {
    column-count: 4;
    max-height: 35%;
    vertical-align: top;
    max-width: 70%;
    font-size: 8px;
    background-color: rgba(205,205,205,0.5);
    background-image: -webkit-gradient(
    linear,
    right bottom,
    left top,
    color-stop(0, rgba(205, 205, 205, 0.8)),
    color-stop(0.50, rgba(255, 255, 0, 0.2))
    );
    background-image: -o-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -moz-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -webkit-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -ms-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: linear-gradient(to left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);

    }
    </style>

    … and please note that around here at RJM Programming we have a “far from hard and fast rule” (but a rule regardless) regarding HTML element ID and class attributes that they concern (and (usually) be compartmentalised into) Javascript (DOM) manipulations and CSS styling issues respectively … and add a linear-gradient background to the table cell when expecting the initial user interaction on non-mobile platforms
  2. a “dynamic” Javascript DOM “class” modification … document.getElementById(‘myrepsb’).className=’dglow’; … is made to the “Report…” button at the Capitals select (dropdown) onfocusout event so as to highlight (with “glow” inspired styling) where user interaction may flow to

As far as links go, you may expect to need serverside means to construct these in online Email and SMS message interfacing, but email (client program) products like Gmail parse your ascii text and convert http: or https: protocol URLs in your Email body to hyperlinks, as does the Messages SMS application here on this MacBook Pro using macOS Mojave. Cute, huh?! So to close the circle back from remote thar’ parts back to our web application is a simple matter of, in broad brush terms …

  • adding two new buttons called “Email Columns and Links …” and “SMS Columns and Links …” that …
  • set a global variable andlinkto = true; … setting in play, within the report writing code (that likes monospaced fonts) …
  • add a new links column to the right with URLs like …
    https://www.rjmprogramming.com.au/HTMLCSS/wls_vs_php.htm?andgo=y&countries=Belize&capitals=Belmopan
    … to tell your client programs to form the hyperlinks for us (if they are “of the mood”, that is!)

To improve user experience we use “dynamic” Javascript DOM HTML “style” attribute change means to easier close the “Colour Wheel” helper web application “above the fold” by changing the CSS z-index (Javascript DOM [element].style.zIndex) of elements accordingly, when the user clicks other elements. You can see all this with the first “the changed” link above, where all “glow” CSS styling will also feature prominently.


Previous relevant Window SessionStorage Client Versus Server Integration Tutorial is shown below.

Window SessionStorage Client Versus Server Integration Tutorial

Window SessionStorage Client Versus Server Integration Tutorial

We hope, when performing a “software integration” task, that the two or more components of that integration work with each other’s talents, rather than a big tussle like reinventing the wheel. This ideal makes the work …

  • sometimes difficult but rewarding because …
  • the differences between two independent software components can be quite large and daunting … and the programmer has to see that …
  • care is applied so as not to wreck previous functionality and integrations in making the current integration work

… and that is why we’ve made corollaries to “building from scratch” (when planning and design is a huge component) can be a lot simpler than a software integration “renovation”, in the past, here at this blog.

Our primary integration today is to (software) integrate the great Weather Underground and its great API service for autocomplete name searches for weather (and hurricane) information. Why bother? Well, can you not envisage a user using that Ajax functionality of yesterday’s Window SessionStorage Client Versus Server Ajax Tutorial as a trip planner, perhaps, or as a “checking up on relatives overseas” tool, perhaps? And not all the capital cities are timezone places, and so for some of those we can use Weather integration to still show apt online information when click/touching a Countries Report row. Speaking of this “row”, we make an improvement whereby on a first click of a right hand (Country) row cell, that cell is not initially a contenteditable=”true” one (that may frustrate showing the keyboard on mobile, when most likely it was the row touch intended), but then becomes a contenteditable=”true” cell henceforth.

As a user experience improvement for “trip planners” perhaps, we allow the user to alphabetically sort the presented select (dropdown) element entries …


var firstopt='';
var wasopts='';
var restopts='';

function readyitforsort(iselid) {
var optsare=[];
var huhisel=document.getElementById(iselid).innerHTML;
var huhsopts=huhisel.split('</option>');
for (var ihuh=0; ihuh<huhsopts.length; ihuh++) {
if (huhsopts[ihuh].trim() != '') {
if (firstopt == '') {
firstopt=huhsopts[ihuh] + '</option>';
} else {
wasopts+=huhsopts[ihuh].replace('option ','option data-ih="' + (huhsopts[ihuh].split('>')[eval(-1 + huhsopts[ihuh].split('>').length)] + '" ')) + '</option>';
optsare.push(huhsopts[ihuh].replace('option ','option data-ih="' + (huhsopts[ihuh].split('>')[eval(-1 + huhsopts[ihuh].split('>').length)] + '" ')) + '</option>');
}
}
}
optsare.sort();
for (var jhuh=0; jhuh<optsare.length; jhuh++) {
restopts+=optsare[jhuh];
}
}

… controlled by a new dropdown in the left hand column header cell.

We also allow the user to move the iframe element with some positioning emoji buttons near the “Close” button one (of yesterday’s work).

Into the future, too, we’ll have more to say regarding the germination of an idea “to allow a mobile onmouseover simulator (of sorts)” be to allow the user to perform a swipe across an individual HTML element of interest on mobile platforms (ie. harness ontouchmove event) as per (so far) … kicked off by “<body onload=” setTimeout(athn, 5000); “>” …


var last24='';
var rectdc;

function nodivalert() {
document.getElementById('divalert').style.display='none';
document.getElementById('divalert').style.zIndex='-456';
document.getElementById('divalert').style.left=('-' + rectdc.left).replace('px','') + 'px';
document.getElementById('divalert').style.top=('-' + rectdc.top).replace('px','') + 'px';
}

function ourdivalert(inmsg) {
document.getElementById('divalert').style.position='absolute';
document.getElementById('divalert').style.left=('' + rectdc.left).replace('px','') + 'px';
document.getElementById('divalert').style.top='' + eval(-80 + eval(('' + rectdc.top).replace('px',''))) + 'px';
document.getElementById('divalert').style.backgroundColor='#e0e0e0';
document.getElementById('divalert').style.display='block';
document.getElementById('divalert').style.zIndex='456';
document.getElementById('divalert').style.opacity='0.8';
document.getElementById('divalert').style.padding='5px 5px 5px 5px';
document.getElementById('divalert').innerHTML=inmsg + '<br><br><input type=button value=Close onclick=nodivalert();></input>';
setTimeout(nodivalert,9000);
}

function athn() {
rectdc=document.getElementById('dc').getBoundingClientRect();
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('dc').ontouchmove=function(event) { if (last24.substring(0,eval(-1 + last24.length)) == event.target.title.substring(0,eval(-1 + event.target.title.length))) { last24=last24; } else { last24=event.target.title; ourdivalert(event.target.title); } }
} else {
document.getElementById('dc').onmousemove=function(event) { if (last24.substring(0,eval(-1 + last24.length)) == event.target.title.substring(0,eval(-1 + event.target.title.length))) { last24=last24; } else { last24=event.target.title; ourdivalert(event.target.title); } }
}
}

… working with the new HTML …


<div id=divalert></div>
</body>
</html>

… to try to allow the “explainer of an element” advantages non-mobile platforms have for hovering over an HTML element with a title attribute filled in.

And so, yet again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new Weather integration functionality. It caused the changed colour_wheel.html‘s colour wheel (at this live run link) to be affected (by integrations “up”).


Previous relevant Window SessionStorage Client Versus Server Ajax Tutorial is shown below.

Window SessionStorage Client Versus Server Ajax Tutorial

Window SessionStorage Client Versus Server Ajax Tutorial

We have a few “clientside chestnuts” to use with our current Capital City Find Matching Country Report web application project today, those being …

  • Ajax functionality, kicked off by an “onclick” event set of logic, allowing mobile platforms to also have a look in (the look in that they miss when the event logic is off the “onmouseover” event)
  • iframe and its …
    1. srcdoc attribute (“content” alternative to src “url” attribute) … along with, and crucially needing (because srcdoc ignores its own document.body onload goings on, that we need the “Iframe Client Pre-Emptive” methods below to circumvent) the …
    2. onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)

… adding onto yesterday’s Window SessionStorage Client Versus Server Canvas Tutorial.

It’s not that involved with the Ajax work today, given that there are no cross-domain issues, though there are cross-protocol (SSL https: versus non-SSL http:) issues to be careful about. Those can be addressed because the web application is recalled to present its “Country Report” and that is the opportunity to check on protocol navigation requirements.

Along the way, we also make this happen for the user on …

  • click/touching a table row … it sets off new “tr” (table row) element logic calling our (inhouse) Timezone and Wikipedia Place Information helper (HTML) via Ajax (so not leaving the webpage) … and because of place name oddities we allow for …
  • “td” (table cell) element user amendments by setting their contenteditable attributes to “true” (since fixed, but we found the Timezone Europe/Tirane pointing at Tirane in Albania used to be spelt “Tirana”)

… that latter methodology normally a technique we apply to “div” elements (so, there you are!)

Also used are “overlay” techniques, two of the “usual suspects” here coming into play, to present to the “Ajax content to srcdoc iframe arrangements” …

Yet again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new “Ajax” functionality.


Previous relevant Window SessionStorage Client Versus Server Canvas Tutorial is shown below.

Window SessionStorage Client Versus Server Canvas Tutorial

Window SessionStorage Client Versus Server Canvas Tutorial

Yesterday’s Window SessionStorage Client Versus Server Share Tutorial dealt with ascii text clipboard copy assisted sharing options with our current Capital City Find Matching Country Report web application project. This suited both Email and SMS share options we coded for, but today’s extension of functionality from “ascii text” data to “graphical data” only suits Email sharing. The other caveat with our work is that no serverside (for us, PHP) help is allowed, so no PHP mail here.

What comes into play with a “graphical data” clientside (only) sharing approach? It will not surprise many readers that, for us, it involves …

  • canvas element … converting HTML table outerHTML “ascii text” data … via …
  • canvas drawing methods “[canvasContext].strokeRect()” and “[canvasContext].strokeText()” via “[cellElement].getBoundingClientRect()” … to convert that canvas element content via …
  • [canvasElement].toDataURL() … to an …
  • img element nested in a div contenteditable=true element … so as to hook in with today’s very useful helper link, thanks … use …

  • function tabletoclipboard(canvas) { // thanks to https://stackoverflow.com/questions/27863617/is-it-possible-to-copy-a-canvas-image-to-the-clipboard
    var img = document.createElement('img');
    img.src = canvas.toDataURL();

    var div = document.createElement('div');
    div.contentEditable = true;
    div.appendChild(img);
    document.body.appendChild(div);

    // do copy
    SelectText(div);
    document.execCommand('Copy');
    document.body.removeChild(div);
    }

    function SelectText(element) { // thanks to https://stackoverflow.com/questions/27863617/is-it-possible-to-copy-a-canvas-image-to-the-clipboard
    var doc = document;
    if (doc.body.createTextRange) {
    var range = document.body.createTextRange();
    range.moveToElementText(element);
    range.select();
    } else if (window.getSelection) {
    var selection = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(element);
    selection.removeAllRanges();
    selection.addRange(range);
    }
    }
  • to leave the user’s device’s clipboard containing a useful table (with linework) … ready to …
  • paste into an email body section

… sharing off to an emailee collaborator.

Again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new “Email Table” button functionality.


Previous relevant Window SessionStorage Client Versus Server Share Tutorial is shown below.

Window SessionStorage Client Versus Server Share Tutorial

Window SessionStorage Client Versus Server Share Tutorial

Yesterday’s Window SessionStorage Client Versus Server Tutorial has been amended today for two new sharing and collaboration options, those being …

  • email
  • SMS

… but you may well be familiar with the restrictions on email and SMS client (program) approaches to this, coming from HTML “a” link “mailto:” and “sms:” href property prefixes respectively. We’re going to need help with the 800 odd character (length) restrictions with the (resultant) web address (bar) URL, but what? How about working off the great advice of this wonderful link, thanks, to copy what we’d have assembled into an ascii text Report into the characters contained by the user’s device’s clipboard?


function copytoclipboard(str) { // thanks to https://hackernoon.com/copying-text-to-clipboard-with-javascript-df4d4988697f
var el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
}

An issue that springs up here using such clipboard ascii text content, whenever you get the Font choice given to you, pick a monospaced Font like Courier New or “Fixed Width”.

See the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new sharing functionality.


Previous relevant Window SessionStorage Client Versus Server Tutorial is shown below.

Window SessionStorage Client Versus Server Tutorial

Window SessionStorage Client Versus Server Tutorial

Sometimes it’s the case at this blog that we’d like to introduce a new topic, but do not do so, because we cannot show any real world (or real application) use of that concept. So it has been, up until now, with the concept of (web browser) window (object) sessionStorage property. But yesterday’s Window LocalStorage Client Versus Server Primer Tutorial represented an opportunity akin to when Haley’s Comet gets at its closest to the Earth … while you see a chance, take it … chance because of that nuance whereby we were not trying to store data for any other purpose than passing data onto …

  1. a known entity … ie. same web application … at …
  2. a known time … ie. immediately

… two conditions that make the code design “marginally” more ideal for the window object property concept of sessionStorage rather than localStorage, in that any …


localStorage.removeItem([knownLocalStorageName]);

… becomes superfluous as with sessionStorage data will disappear between web browser sessions, anyway.

We offer this new concept as a non-default option of a select (dropdown) element replacement to the h1 element hardcoding “localStorage” with the changed wls_vs_php.htm Capital City Find Matching Country Report live run. The other nuance of difference with sessionStorage usage is that in the document.body onload event logic, we may as well (as part of other changes) pre-emptively look for, and if there, respond to, any found sessionStorage data points, even without the user having flagged it specifically


var datamode='localStorage';

function checkforreport() {
var divcont='';
var dcaps, dctys, idis;
if (getcapitals == 'localStorage') {
if (window.localStorage) {
getcapitals=decodeURIComponent(localStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
localStorage.removeItem('wls_vs_php_capitals');
} else {
getcapitals='';
}
} else if (getcapitals == 'sessionStorage') {
document.getElementById('smode').value=getcapitals;
datamode=getcapitals;
if (window.sessionStorage) {
getcapitals=decodeURIComponent(sessionStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
} else {
getcapitals='';
}
}
else if (getcapitals == '' && window.sessionStorage) {
getcapitals=decodeURIComponent(('' + sessionStorage.getItem('wls_vs_php_capitals')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (getcapitals != '') {
document.getElementById('smode').value='sessionStorage';
datamode='sessionStorage';
}
}

if (getcountries == 'localStorage') {
if (window.localStorage) {
getcountries=decodeURIComponent(localStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
if (getcapitals.replace('localStorage','') != '' && getcountries.replace('localStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
localStorage.removeItem('wls_vs_php_countries');
} else {
getcountries='';
}
} else if (getcountries == 'sessionStorage') {
if (window.sessionStorage) {
getcountries=decodeURIComponent(sessionStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
if (getcapitals.replace('sessionStorage','') != '' && getcountries.replace('sessionStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
} else {
getcountries='';
}
}
else if (getcountries == '' && document.getElementById('smode').value == 'sessionStorage' && window.sessionStorage) {
getcountries=decodeURIComponent(('' + sessionStorage.getItem('wls_vs_php_countries')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (getcountries != '') {
document.getElementById('smode').value='sessionStorage';
datamode='sessionStorage';
}
}

if (getcapitals != '' && getcountries != '') {
divcont='<table border=5 style="width:95%;vertical-align:top;background-color:white;"><tr style=background-color:#f0f0f0;"><th>Capital</th><th>Country</th></tr></table>';
dcaps=getcapitals.split('|');
dctys=getcountries.split('|');
for (idis=0; idis<dcaps.length; idis++) {
divcont=divcont.replace('</table>', '<tr><td>' + dcaps[idis] + '</td><td>' + dctys[idis] + '</td></tr></table>');
}
document.getElementById('dreport').innerHTML=divcont;
}
document.getElementById('smode').value=datamode;
}

Which beggars the question “What are the differences between sessionStorage and localStorage?” A quick reading might surmise that “the latter has an expiration date”. We leave you with an open ended Google search so that you may extend your readings on this.


Previous relevant Window LocalStorage Client Versus Server Primer Tutorial is shown below.

Window LocalStorage Client Versus Server Primer Tutorial

Window LocalStorage Client Versus Server Primer Tutorial

Even though we rave on a lot about serverside PHP and its $_POST method=POST (versus HTML/Javascript recipient via ? and & argument $_GET method=GET scenario) data length advantages as the recipient of an HTML form method=POST set of data that could be sizeable, we’ve just realized that there is a client Javascript and window.localStorage methodology that may help alleviate the need to involve PHP (and any other serverside intervention) on occasions.

Hint: Yes, we’ve raved on about this too?! Does the blog posting title give it away? Okay, yes, it should read “localStorage”, but thought we’d gone past such juvenile finickiness since the Whac-A-Mole controversy of 1st December 2019 (or even The Great Tea Trolley Disaster of ’67, we daresay).

It can even use a “self-destruct” approach to the use of this “localStorage” on having used it because …

  • the web application knows who is using it (localStorage) … and on having accessed and read it …
  • the web application knows it (localStorage) is of no use to any other user (in this web application’s case, at least)

… which is very pleasing for a Land Surveyor who likes to leave cow paddocks as they’ve seen them so to speak. Except it’s like having a ten tonne truck worth of data access in amongst the cow pats when having access to “localStorage” (or PHP), rather than a little piddle of calf wee (wee Metcalfes know a thing or two about these things!) data access of ? and & HTML/Javascript URL arguments (or even if we were to use HTTP Cookies).

It’s not as if we all have access to serverside language usage, though we do, because we really like PHP and MAMP and Apache/PHP/MySql web servers (and have arranged our development environment accordingly), but what if you are starting out in web development, and still want to allow for sizeable chunks of data with your web applications? Huh? Huh?! See the possibilities? Try our proof of concept wls_vs_php.html Capital City Find Matching Country Report live run, and highlight a whole swathe of (multiple mode) dropdown option Capital Cities holding down the shift key before pressing the yellow “Report” button. If the URL ends up as …

https://rjmprogramming.com.au/HTMLCSS/wls_vs_php.html?capitals=localStorage&countries=localStorage

that’s because the web application’s …


function analyze() {
var purl=document.URL.split('#')[0].split('?')[0] + '?capitals=' + encodeURIComponent(document.getElementById('capitals').value) + '&countries=' + encodeURIComponent(document.getElementById('countries').value);
if (purl.length > 800) {
if (phpexists) {
document.getElementById('myform').method='POST';
document.getElementById('myform').action='./wls_vs_php.php';
} else if (window.localStorage) {
localStorage.setItem('wls_vs_php_countries', encodeURIComponent(document.getElementById('countries').value));
localStorage.setItem('wls_vs_php_capitals', encodeURIComponent(document.getElementById('capitals').value));
document.getElementById('capitals').value='localStorage';
document.getElementById('countries').value='localStorage';
location.href=document.URL.split('#')[0].split('?')[0] + '?capitals=' + encodeURIComponent(document.getElementById('capitals').value) + '&countries=' + encodeURIComponent(document.getElementById('countries').value);

return false;
}
}
return true;
}

… HTML form onsubmit event logic …

  1. discovered no PHP web application existant (via Client Pre-emptive Iframe techniques) … and …
  2. discovered (in a sanity check feeling way) that to go down the proposed HTML form method=GET approach was risking a …

    HTTP 414 "Request URI too long"

    … web browser error … and that …
  3. localStorage was a known web browser piece of functionality
  4. … and so as per our localStorage logic we …

  5. back out of the default HTML form method=GET navigation setup of the web application in favour of …
    • storing that data into localStorage
    • substituting into the URL ? and & arguments the hardcoding “localStorage” (and in so doing, getting back under the HTTP 414 “Request URI too long” limitation, piecing together (what amounts to) …
      location.href=document.URL.split(‘#’)[0].split(‘?’)[0] + ‘?capitals=localStorage&countries=localStorage’;)
      … that on a recall to this same web application a …
    • document.body onload event piece of Javascript logic checks the localStorage for its incoming Capital City Country Report data, as per …

      var phpexists=false;
      var getcapitals=location.search.split('capitals=')[1] ? decodeURIComponent(location.search.split('capitals=')[1].split('&')[0]).replace(/\+/g,' ') : '';
      var getcountries=location.search.split('countries=')[1] ? decodeURIComponent(location.search.split('countries=')[1].split('&')[0]).replace(/\+/g,' ') : '';

      function checkforreport() {
      var divcont='';
      var dcaps, dctys, idis;
      if (getcapitals == 'localStorage') {
      if (window.localStorage) {
      getcapitals=decodeURIComponent(localStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
      localStorage.removeItem('wls_vs_php_capitals');
      } else {
      getcapitals='';
      }
      }
      if (getcountries == 'localStorage') {
      if (window.localStorage) {
      getcountries=decodeURIComponent(localStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
      if (getcapitals.replace('localStorage','') != '' && getcountries.replace('localStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
      localStorage.removeItem('wls_vs_php_countries');
      } else {
      getcountries='';
      }
      }

      if (getcapitals != '' && getcountries != '') {
      divcont='<table border=5 style="width:95%;vertical-align:top;background-color:white;"><tr style=background-color:#f0f0f0;"><th>Capital</th><th>Country</th></tr></table>';
      dcaps=getcapitals.split('|');
      dctys=getcountries.split('|');
      for (idis=0; idis<dcaps.length; idis++) {
      divcont=divcont.replace('</table>', '<tr><td>' + dcaps[idis] + '</td><td>' + dctys[idis] + '</td></tr></table>');
      }
      document.getElementById('dreport').innerHTML=divcont;
      }
      }

      … the localStorage.removeItem() representing that “self-destruct” nuance we were talking about before

We may well use this methodology in future projects, and hope it has been of some little interest to you as well?!

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

Google Chart Geo Chart Quiz Overlay Tutorial

Google Chart Geo Chart Quiz Overlay Tutorial

Google Chart Geo Chart Quiz Overlay Tutorial

Regarding the recent “beep work” of Google Chart Geo Chart Quiz Beep Tutorial we saw that that right hand iframe “explanation of a wrong answer” could do with some tweaking, it as of then was …

  • only showing a green dot of the relevant country’s relevant TimeZone place position on a Google Chart Geo Chart world map … but then we thought …
  • Wouldn’t it be good to transition from the green dot to the country emoji flag?

    … and then the next day we thought …

  • Wouldn’t it be good to transition from the green dot to the country emoji flag at the same time as overlaying a shaded country view as well?

    … and then the next day was tomorrow … so …

… we wrote this blog post, after doing the coding changes, featuring a new “overlay iframe onload event”

<?php

$doverlayih='';

if (isset($_GET['title']) && isset($_GET['data']) && strpos(urldecode($_GET['title']), 'Quiz Zoom Out Answer') !== false) {
if (isset($_GET['peninfo']) && isset($_GET['data'])) {
if (strpos($_GET['peninfo'], '|') === false && strpos($_GET['peninfo'], urlencode('|')) === false && strpos(urldecode($_GET['data']), '|~') !== false) {
$cplace=str_replace('_',' ',str_replace('+',' ',explode('~', explode('|~', urldecode($_GET['data']))[1])[0]));
for ($ij=1; $ij < sizeof($iso_country_codes); $ij+=2) {
if ($cplace == $iso_country_codes[$ij]) {
$cplaceiso=strtoupper($iso_country_codes[-1 + $ij]);
$newpeninfo=str_replace('%20[','',explode(urlencode('~'), explode('~', $_GET['data'])[0])[0]);
$uretv='';
$xlri=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
$xdri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];
for ($jjm=0; $jjm<strlen($cplaceiso); $jjm++) {
for ($jm=0; $jm<sizeof($xlri); $jm++) {
if (strtoupper(substr(substr($cplaceiso,$jjm),0,1)) == $xlri[$jm]) {
if ($jjm == 0) {
$newpeninfo.=$xdri[$jm];
} else {
$newpeninfo.='.' . $xdri[$jm];
}
}
}
}
$newpeninfo.='_' . str_replace(' ','_',$cplace);
$_GET['peninfo']=$newpeninfo;

//$_GET['overlay']='y';
$doverlayih='<iframe onload="realign(this);" style="position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:2222;opacity:0.58;text-shadow:-1px 1px 1px #ff2d95;" src="//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' . (isset($_GET['title']) ? $_GET['title'] : '') . '&width=' . (isset($_GET['width']) ? $_GET['width'] : '') . '&height=' . (isset($_GET['height']) ? $_GET['height'] : '') . '&country=' . (isset($_GET['country']) ? $_GET['country'] : '') . '&popularity=' . (isset($_GET['popularity']) ? $_GET['popularity'] : '') . '&data=%20[~' . $cplaceiso . '~,2]"></iframe><style> #chart_div { text-shadow:-1px 1px 1px #ff2d95; } </style>';
}
}
}
}
}

?>

… used, later, via …


<div id="doverlay"><?php echo $doverlayih; ?></div>

… using new “overlay iframe onload event function” …

<?php echo ”

function realign(iois) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
if (aconto.getElementById('chart_div')) {
if (document.getElementById('chart_div')) {
var cdrect=document.getElementById('chart_div').getBoundingClientRect();
aconto.getElementById('chart_div').style.position='absolute';
aconto.getElementById('chart_div').style.left='' + cdrect.left + 'px';
aconto.getElementById('chart_div').style.top='' + cdrect.top + 'px';
aconto.getElementById('chart_div').style.width='' + cdrect.width + 'px';
aconto.getElementById('chart_div').style.height='' + cdrect.height + 'px';
if (aconto.getElementById('myh')) {
if (aconto.getElementById('myh').innerHTML.indexOf('Quiz Zoom Out Answer') != -1) {
aconto.getElementById('myh').style.visibility='hidden';
}
}
}
}
}
}
}

“; ?>

… you may notice tries to improve “the display dynamism” that little bit by applying a CSS text-shadow property Santa claws clause in our changed geo_chart.php Google Chart Geo Chart interfacer for our Geography Zoom In Quiz.


Previous relevant Google Chart Geo Chart Quiz Beep Tutorial is shown below.

Google Chart Geo Chart Quiz Beep Tutorial

Google Chart Geo Chart Quiz Beep Tutorial

We’ve long had on our minds a wish to incorporate a beep sound into quiz scenarios, and we’re revisiting this, again, for us, trying to get this going using the Geographical Quiz featuring in Google Chart Image Chart Map Chart Quiz Tutorial.

Why we feel a beep would be good here is that a user can use the beep while multitasking, and be told when to focus back on the quiz, while doing other things, perhaps, and the beep patterns can tell them …

  1. whether they are correct
  2. when the next question’s left hand map hint has been loaded

… while they are doing those other things, perhaps.

A beep is no big deal, right?! No, it is not such a big deal on non-mobile, true, but on mobile, it is a nightmare! Because …

  1. ever since this web browser approach on mobile, of only allowing audio (and/or video) play operations off a real user click “origin”, the task for mere non-Spotify mortals (and even they click, really, at least once) is more tortuous … and less of a pain, but a tad annoying, is that …
  2. Safari (web browser) not playing audio/wav files, so we looked around and came upon this excellent link, thanks, to get an MP3 beep

… all hold us up.

To get a kludgy solution on mobile we opted to …

  • overlay a dropdown (select) element the user uses to answer (which we later improved by overlaying a new “Beep” checkbox initially hidden from view, which we’re calling “non kludgy”), in the quiz … with an …
  • audio element positioned so that …
    1. mobile user can’t help but see it … and …
    2. they choose whether or not to involve audio beeps by clicking the audio element at a time of their choosing, or not, knowing …

    … there are still ways to get to the underlayed dropdown to answer the quiz question …

    function overselceqwq() {
    if (document.getElementById('divselcq').innerHTML.indexOf('<audio') == -1) {
    //document.getElementById('divselcq').innerHTML+='1:' + navigator.userAgent + '<br>';
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i) && 1 == 1) {
    //document.getElementById('divselcq').innerHTML+='01:' + navigator.userAgent + '<br>';
    rectisa=document.getElementById('selceqwq').getBoundingClientRect();
    //document.getElementById('divselcq').innerHTML+='11:' + navigator.userAgent + '<br>';
    if (1 == 11) {
    document.getElementById('divselcq').innerHTML+='<audio id=aselwq style="visibility:' + hidden + ';opacity:0.4;z-index:876;position:absolute;top:' + eval(-95 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(0.55 * eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(0.10 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/mp3 onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); hidden=' + "'hidden'" + '; document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; document.getElementById(' + "'aselwq'" + ').style.visibility=' + "'hidden'" + '; },2000);" onmousedown="if (event.currentTarget == this) { this.muted=!this.muted; }" ontouchstart="if (event.currentTarget == this) { this.muted=!this.muted; }" onclick="if (event.currentTarget == this) { this.muted=!this.muted; setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; }, 2000); }" controls muted><source type=audio/mp3 src="/beep.mp3"></source></audio>';
    } else if (1 == 1) {
    setTimeout(function(){
    rectisa=document.getElementById('audios').getBoundingClientRect();
    document.getElementById('divselcq').innerHTML+='<audio id=aselwq style="visibility:' + hidden + ';opacity:0.4;z-index:876;position:absolute;top:' + eval(-20 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(10 + eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(1.0 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/mp3 onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); hidden=' + "'hidden'" + '; document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; document.getElementById(' + "'aselwq'" + ').style.visibility=' + "'hidden'" + '; },2000);" onmousedown="if (event.currentTarget == this) { this.muted=!this.muted; }" ontouchstart="if (event.currentTarget == this) { this.muted=!this.muted; }" onclick="if (event.currentTarget == this) { this.muted=!this.muted; setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; }, 2000); }" controls muted><source type=audio/mp3 src="/beep.mp3"></source></audio>';
    }, 3000);
    } else {
    document.getElementById('divselcq').innerHTML+='<audio onload=this.muted(true); id=aselwq style="visibility:hidXden;opacity:0.2;z-index:876;position:absolute;top:' + eval(4 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(0.80 * eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(0.10 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/wav onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); },2000);" onmousedown="this.muted(false);" ontouchdown="this.muted(false); " onclick="setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); }, 2000);" controls><source type=audio/wav src="data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU="></source></audio>';
    }
    //document.getElementById('divselcq').innerHTML+='111:' + document.getElementById('aselwq').outerHTML.replace(/\</g,'<').replace(/\>/g,'>') + '<br>';
    //document.getElementById('divselcq').innerHTML+='<button id=bselwq style="background-color:transparent;z-index:1876;position:absolute;top:' + rectisa.top + 'px;left:' + rectisa.left + 'px;width:' + rectisa.width + 'px;height:' + rectisa.height + 'px;' + '" type=audio/wav onclick="beep(); document.getElementById(' + "'selceqwq'" + ').click();"></button>';
    }
    }
    }

    function mbeep() {
    if (useaudios) {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i)) {
    if (top.document.getElementById('aselwq')) {
    top.document.getElementById('aselwq').play();
    } else {
    //var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    var snd = new Audio("/beep.mp3"); // "data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    snd.play();
    setTimeout(beep, 5000);
    }
    }
    }
    }

    function beep() {
    if (useaudios) {
    if (top.document.getElementById('aselwq')) {
    top.document.getElementById('aselwq').play();
    } else {
    var snd = new Audio("/beep.mp3"); // "data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    snd.play();
    }
    }
    }

    function beeptwo() {
    beep();
    setTimeout(function(){
    beep();
    }, 100);
    }

    function beepthree() {
    beep();
    setTimeout(function(){
    beep();
    }, 100);
    setTimeout(function(){
    beep();
    }, 200);
    setTimeout(function(){
    beep();
    }, 300);
    }

    function beepDoubleThree() {
    beepthree();
    setTimeout(function(){
    beepthree()
    }, 500);
    }

Codewise …

… you might want to revisit, yourself!


Previous relevant Google Chart Image Chart Map Chart Quiz Tutorial is shown below.

Google Chart Image Chart Map Chart Quiz Tutorial

Google Chart Image Chart Map Chart Quiz Tutorial

There is an expression so apt for today’s situation. But we hate it, so … no … we’ll say instead …

Our fault mainly, not Google’s fault only

… regarding yesterday’s …

However, this last one both needs more “wading through data” and “consideration” because it seems to be at Google Charts that not even the national boundary is shown when this regional data is not recognized.

We discovered today, that fallback colours directed towards an overall country code at the end of the URL regional colour entry list, is the way around some of the issue, that some meaning now we can get a country boundary showing, but still, for some countries, Google Charts, with its Image Chart Map Chart, will not show regional boundaries as you might see defined at Wikipedia for some ISO 3166-2 regional codes they have recorded.

So, what’s that got to do with quizzes? Well, the quiz got us interested in these colour mappings, and discovering how those mappings worked led us to this discovery. We hope colour blind people don’t suffer because our Country Regional Quiz functionality could easily be called …

Name the Red Region Quiz

Yes, if the user chooses the new “Quiz” input submit button modus operandi we arrange …

  • to leave out any legends
  • randomly pick a region which is coloured red … and now blue represents unaccounted for country parts not assigned a region and green represents the rest of the world and the oceans are as they ever were … and …
  • after a while we ask the user for their guess as to what this red region’s name is

Good ol’ “colour coding”! What did we do when the world was not colourful? Oops … [expression we hate, again, fits here] … my mistake. We wouldn’t have been around. But we digress.

Simple premise, building on yesterday’s Google Chart Image Chart Map Chart Context Tutorial, but surprisingly involved in our changed third draft image_chart.php PHP web application for you to try, below, perhaps


Previous relevant Google Chart Image Chart Map Chart Context Tutorial is shown below.

Google Chart Image Chart Map Chart Context Tutorial

Google Chart Image Chart Map Chart Context Tutorial

Onto yesterday’s Google Chart Image Chart Map Chart Primer Tutorial start with Google Charts Image Chart Map Chart interfacing, today we’ve come at it from two subcategories relating to fallback positions and “context” …

  • add Geo Chart and Map Chart optionally viewed details/summary iframes showing country TimeZone position data
  • add a mechanism that if we can determine a country’s ideal range of latitude,longitude “box” view, as we found GADM could help us with, thanks, we can flag that

    $ourtzlist=" ...<option value=\"Asia/Shanghai\" title=\"17,82,55,133\" data-geo=\"31.23333,121.46666,CST,CN,+8\">Asia/Shanghai</option><option value=\"Asia/Singapore\" data-geo=\"1.28333,103.85,+08,SG,+8\">Asia/Singapore</option> ...";

    … in the data

However, this last one both needs more “wading through data” and “consideration” because it seems to be at Google Charts that not even the national boundary is shown when this regional data is not recognized.

The first one, though, is useful in our changed second draft image_chart.php PHP web application for you to try, below, perhaps


Previous relevant Google Chart Image Chart Map Chart Primer Tutorial is shown below.

Google Chart Image Chart Map Chart Primer Tutorial

Google Chart Image Chart Map Chart Primer Tutorial

We hope today’s work does not confuse terms, because we’re exploring a new area of Google Charts functionality today they refer to as …

  • Google Charts Image Charts … and you’ll see there lots of suboptions we’ll explain a bit more about later, and all this is separate functionality to …
  • Google Charts Map Chart … and …
  • Google Charts Geo Chart

… and, as of today, we interface to all three categories of Google Charts above, with three separate PHP web applications.

So, what’s the potential confusion? Well, we start out today interfacing to an Image Chart suboption called “Map Chart”, but not the one above, because its look is more in keeping with what the “Geo Chart” above achieves. We’ve written a web application, here, to show regional places within a country (via its 2 letter code) if this has been catered for by Google Charts, and for the most part, that is the case.

And so, on the same theme as yesterday’s Google Chart Geo Chart Zoom In Quiz Translate Tutorial, and thanks to Wikipedia for regional code lookups, we would welcome you to try out our “proof of concept” first draft image_chart.php PHP web application for you to try, below, perhaps …


Previous relevant Google Chart Geo Chart Zoom In Quiz Translate Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Translate Tutorial

Google Chart Geo Chart Zoom In Quiz Translate Tutorial

You could say the way we navigate to our recent …

World Quiz

… from our …

Geo Chart Interfacer

… in the web application as of yesterday’s Google Chart Geo Chart Zoom In Quiz Hints Tutorial was a bit cryptic, or convoluted, the way at a first prompt window we’d change an entry from the default My World Survey to My World Quiz or even to click that button that we’d arranged in this blog posting thread. Nevertheless, we were a bit loathe to change the arrangements, until we ran into problems involving today’s work of …

Adding a Google Translate layer on top of the World Quiz

… to facilitate some Internationalization (ie. language translation from English to non-English) into the mix. Yes, our PHP caused problems interfacing to Google Translate. So, what was our approach? We took a snapshot (ie. web browser View -> Page Source) at a point after the convolutions above, and worked off that to introduce a new code file member. Welcome …

… via our proof of concept geochart.html clientside only web application version (or the old access approach in all these changes to geo_chart.php PHP web application still works). Any downside doing this? A little, in that within a Google Translate “bubble” we could not work the Wikipedia images hint part of the logic. Also, you may run into problems with SVG image backgrounds using an svg+xml protocol, or we may just have been having a bad day?! So sad.


Previous relevant Google Chart Geo Chart Zoom In Quiz Hints Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Hints Tutorial

Google Chart Geo Chart Zoom In Quiz Hints Tutorial

Yesterday’s Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial showed us …

  • using a web inspector to dynamically change CSS styling in place preparatory to making a permanent change … well, today, we’re here to reiterate …
  • using a web inspector can help with a myriad of Javascript logic errors or debugging, as well

… and we do that today adding hints to all these changes to geo_chart.php Geo Chart interfacer at this live run World Quiz web application link or click a button down below.

Do the hints look familiar? Take a read of Javascript Lazy Evaluation Country Game Hints Tutorial and it all might come back to you!


Previous relevant Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial

Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial

We recently revisited the PHP web application we call …

Google Chart Geo Chart Zoom In Quiz

… last talked about at Google Chart Geo Chart Zoom In Quiz Sharing Tutorial, and noticed a bit of ugliness regarding its CSS styling, specifically related to the “too large” border-radius values we’d applied to the twin iframes cutting off wording in their bottom left corner.

This issue is an …

  • aesthetics, only …
  • CSS styling

… one … queue the Web Inspector! How come? Well, web inspectors, such as Google Chrome web browser’s one, allow you to …

  • in place … on our macOS MAMP local Apache/PHP/MySql web server system …
  • dynamically tweak …
  • CSS styling … especially good with inline CSS style syntax, that we happen to be very fond of too … so as to be able to …
  • make the changes for you to optionally re-tweak … ephemerally

… on a test system (ours being a macOS MAMP local Apache/PHP/MySql web server one) ahead of uploading and committing to a permanent change up at the live and public RJM Programming web server domain.

Take a look at how we went about what went into the aesthetically tweaked geo_chart.php Geo Chart interfacer at this live run link, where we remind you again, a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” in a new window or click a button down below.


Previous relevant Google Chart Geo Chart Zoom In Quiz Sharing Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Sharing Tutorial

Google Chart Geo Chart Zoom In Quiz Sharing Tutorial

Adding functionality to yesterday’s Google Chart Geo Chart Zoom In Quiz Tutorial we see an opportunity to …

  • add an element of “when” functionality onto the “where” strengths of the Google Chart Geo Chart recent work, via PHP TimeZones and interfacing to the work of the recent Looks Nice Nearby Speech to Text Game Video Tutorial … as well as …
  • means by which to share or collaborate with the “My World Zoom In Quiz” … via …
    1. email 📧 (via inline HTML PHP mail) … or …
    2. SMS 📟 (via “a” tag href=sms: link)

… and that last SMS methodology brought into focus our wish not to allow, yet, a URL approach to get directly to this new “My World Zoom In Quiz” (although we may change this strategy into the future). So, how to apply security over the use of a URL such as …

https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?wqperspective=Monday+10+Feb+2020+17:57:15.7182

… not linked, above, because there is no point. We have already clicked it in an SMS we got sent, and that nullifies its use from then on? Huh?! Yes, we use the PHP itself, as we are fond of doing, storing (a form of) that “Monday+10+Feb+2020+17:57:15.7182” away as a comment in amongst the PHP code and, hence, “file_get_contents” checkable by its or some other PHP code for its existence (as well as the “file_put_contents” based clean up removal of said comment after the SMSee’s (body) link is ever clicked), as the security check for whether we navigate to the “My World Zoom In Quiz” (bringing up that last correct answer) via an SMS body URL link, clicked by an SMSee. And that collaborator can do the same thing back to the original sender for the next wrong answer’s similar 📟 emoji button press instigation of this sharing and collaboration Javascript logic …


function smswho() {
if (smsorig == '') { smsorig=document.getElementById('smssend').href.split('0000')[0]; }
if (smsdateorig == '') { smsdateorig=document.getElementById('smsdate').value; }
var smsto=prompt('SMS to?', document.getElementById('smssend').href.split('sms:')[1].split('?')[0]);
if (smsto == null) { smsto = ''; }
if (smsto.trim() != '') {
document.getElementById('smsdate').value=smsdateorig + '.' + gsv.substring(0,1).charCodeAt(0) + gsv.substring(1).substring(0,1).charCodeAt(0);
document.getElementById('smsbut').click();
document.getElementById('smssend').href=(smsorig + '' + gsv.substring(0,1).charCodeAt(0) + gsv.substring(1).substring(0,1).charCodeAt(0)).replace('sms:?','sms:' + smsto + '?');
document.getElementById('smssend').click();
}
}


function emailwho() {
var emto=prompt('Email to?', document.getElementById('emailto').value);
if (emto == null) { emto = ''; }
if (emto.indexOf('@') != -1) {
document.getElementById('emailto').value=emto;
document.getElementById('hcont').value='<html><body><form action=' + document.URL + ' method=POST><input type=hidden value=' + gsv + ' name=wqperspective></input><input type=submit value=\"My World Zoom In Quiz\" style=\"background-color:yellow;\"></input></form></body></html>';
document.getElementById('iemail').click();
}
}

… in the context of all these changes to geo_chart.php Geo Chart interfacer at this live run link, where we remind you again, a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” in a new window.


Previous relevant Google Chart Geo Chart Zoom In Quiz Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Tutorial

Google Chart Geo Chart Zoom In Quiz Tutorial

Today we’re combining …

… to create another form of quiz (we think of as “My World Zoom In Quiz”) the user can navigate to via the way they answer that first title prompt (substituting “Survey” with “Quiz”). You might prefer to think of it as the “Geographical Perspective Quiz” with a degree of difficulty, often, because to see a “Zoomed In” display of a country or region can be disorienting and challenging to recognize. And so, for incorrect dropdown answers, we provide a “zoomed out” world view of where that “zoomed in” view sits (like an inset).

In order to show you this below please click

Again, a bit of a different tack to yesterday with the reworked geo_chart.php Geo Chart interfacer at this live run link, where a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” (like above) in a new window.


Previous relevant Google Chart Geo Chart Small Region Tutorial is shown below.

Google Chart Geo Chart Small Region Tutorial

Google Chart Geo Chart Small Region Tutorial

Meanwhile, resuming our dreams of Andorra, there must be hundreds of readers there a bit sick of us going on and on and on and on and on about our Google Chart Geo Chart interfacing Quizzes and the use of complex “width” (and “height”) prompt user interactions. After all, we came onto this topic more to do with “small countries”. Well, let’s go back to that and let’s say …

  • as well as the “markers” mode (geographicals) latitude and longitude (helped out by PHP TimeZone places) way of signifying the position of a small country on a world or continent map … always, there behind the scenes, set up ages ago, was the interfacing we had set up to …
  • connect with the Google Chart “smarts” regarding “region” mapping to be able to hone in on a “region” (which can mean a whole country too) of interest

… and that means, today, we revisit our imaginary jaunts in Andorra setting out from the big smoke of …


Andorra la Vella

… to the border tranquillity of …


Pas de la Casa

… in the scenario of today’s tutorial picture … honing in on the user interaction before the width one (yayyyyyy!) with that title prompt. At this prompt we make use of two extensions to default behaviour with our PHP web application, those being …

  1. prefix of “region code” + “;” ( in the case of Andorra an ISO 2 Character Country Code “AD” + “;” = porkAD; )
  2. suffix of “heads up” placename list (making it so you will probably not need to fish around for any latitude and longitude geographicals yourself) via &areplaces=[comma (and + if you want lines joining) separated placename list] … eg. &areplaces=Andorra la Vella,+Pas de la Casa

… to end up with a user title data item user interaction entry of …


AD;My World Survey&areplaces=Andorra la Vella,+Pas de la Casa

… as the lead in to “not much thinking” (and as long as you are not Pinocchio, “follow your nose” ease) required for the other non-quiz-based prompts (ie. no need for width or height mantissae …

… in this scenario).

Quite a bit of a different tack to yesterday’s Google Chart Geo Chart Quiz Tooltip Flag Tutorial that you can see how we needed to tweak geo_chart.php Geo Chart interfacer at this live run link, showing the versatility and usefulness of Google Chart Geo Charts.


Previous relevant Google Chart Geo Chart Quiz Tooltip Flag Tutorial is shown below.

Google Chart Geo Chart Quiz Tooltip Flag Tutorial

Google Chart Geo Chart Quiz Tooltip Flag Tutorial

Yesterday’s Google Chart Geo Chart Quiz on Mobile Tutorial‘s Google Chart Geo Chart interfacing uses …

  • onmouseover event tooltip functionality for non-mobile platforms … and, better something than nothing, we guess …
  • first onclick event tooltip functionality for mobile platforms

… a blessing, in our view, that an onmouseover (ie. on hover) piece of functionality thinking survives into the mobile platform wooooooooorrrrrlllddd in some way shape or form. We generally find tooltips an optimistic and useful webpage functionality tool.

And with this in mind, it was worth our mind’s attention to ask … “what about if the Geo Chart Quiz functionality can, optionally, help out the user a bit without giving the game away?” … in the sense that ISO 2 character country codes can be baffling, yet help to make the quiz a challenge, on occasions, though enough of a turn off for some users, we’re sure. But to place an Emoji Flag could be a feature some quizzers will like and appreciate.

Rather than add to the navigational data we’d rather “add” an Emoji Flag on being “flagged” (tee hee) to do so, that “flagging” being to add argument “&flag=y” into the mix, at the width value prompt, which is the same prompt whereby a user decides to create a quiz in the first place. And because Emojis represent text data (albeit multibyte ones) we won’t even need to change data structures, just data content involving the one string structure member of …


['Latitude','Longitude','Country','Countdown']

… which we’ve been sending as that country’s ISO 2 character code (to leave some challenge to the quizzer, where the user has been seeing that ISO code only “on hover” up to today) … but if the user has “flagged” &flag=y this code below swings into play appending text data onto that ISO Code text data (of PHP variable (and argument) “$instuff” below) via String.fromCodePoint() function, as per …

<?php

$lri=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
$dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];

function maybequizflag($instuff) {
global $GETdata, $iso_country_codes, $flagentity, $lri, $dri;
if (isset($_GET['quiz']) || isset($_POST['quiz'])) {
if (isset($_GET['flag']) || isset($_POST['flag'])) {
if (strpos($instuff, "['Lat','Long',") !== false) {
return $instuff; //str_replace("'Country',", "'Country','Flag',", $instuff);
} else {
$outstuff=$instuff;
$cbits=explode("'", $instuff);
$outstuff=$cbits[0];
$uretv=" ' + '";
for ($iol=1; $iol<sizeof($cbits); $iol++) {
if (($iol % 2) == 1) {
if (strlen($cbits[$iol]) == 2) {
for ($jjm=0; $jjm<strlen($cbits[$iol]); $jjm++) {
for ($jm=0; $jm<sizeof($lri); $jm++) {
if (strtoupper(substr($cbits[$iol],$jjm,1)) == $lri[$jm]) {
$uretv=str_replace(" + '", " + String.fromCodePoint(" . $dri[$jm] . ") + '", $uretv); //uvaltosfcp($dri[$jm]);
}
}
}
$outstuff.="'" . $cbits[$iol] . $uretv;
$uretv="' + '";
} else {
$uretv=" ' + '";
for ($im=1; $im<sizeof($iso_country_codes); $im+=2) {
if ($uretv == " ' + '" && strpos(strtolower($iso_country_codes[$im]), strtolower(str_replace("%20"," ",str_replace("%E2%80%99","",str_replace("%2C",",",$cbits[$iol]))))) !== false) {
for ($jjm=0; $jjm<strlen($iso_country_codes[-1 + $im]); $jjm++) {
for ($jm=0; $jm<sizeof($lri); $jm++) {
if (strtoupper(substr($iso_country_codes[-1 + $im],$jjm,1)) == $lri[$jm]) {
$uretv=str_replace(" + '", " + String.fromCodePoint(" . $dri[$jm] . ") + '", $uretv); //uvaltosfcp($dri[$jm]);
}
}
}
}
}
$outstuff.="'" . $cbits[$iol] . $uretv;
$uretv="' + '";
}
} else {
$outstuff.="'" . $cbits[$iol];
}
}
return $outstuff; //str_replace("',9", "','x',9", str_replace("',8", "','x',8", str_replace("',7", "','x',7", str_replace("',6", "','x',6", str_replace("',5", "','x',5", str_replace("',4", "','x',4", str_replace("',3", "','x',3", str_replace("',2", "','x',2", str_replace("',1", "','x',1", str_replace("',0", "','x',0", $instuff))))))))));
}
}
}
return $instuff;
}

?>

Again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Quiz on Mobile Tutorial is shown below.

Google Chart Geo Chart Quiz on Mobile Tutorial

Google Chart Geo Chart Quiz on Mobile Tutorial

We wanted to improve on the recent Google Chart Geo Chart More Quizzes Tutorial‘s “World Quiz” functionality approach of displaying window.open popups for mobile platforms. The reason for the concern on mobile platforms, and not such a concern on non-mobile platforms (though there is a concern about popup window web browser disabling settings), because the chance to “overlay” a popup window (via the use of a third argument to window.open calls) is ignored on mobile platforms, instead opening a new browser tab (at best). This can be disconcerting, akin to telling a room of students doing an important examination, to look out the window at an interesting magpie (warbling about Collingwood’s last triumph, no doubt).

Well, after extensive research, and first trying to position “anything new” down the bottom of the webpage we …

  • rejected idea of whole display of a relevant Wikipedia page content at the bottom (of a mobile user’s Geo Chart “quiz” webpage) … associated with a …
  • rejected “a” hashtag link down the bottom (but above proposed content above) to navigate back up to the quiz … to, instead …
  • start thinking that it is up to the mobile user to act themselves to ever navigate away from the quiz webpage, so, instead, initially condense the Wikipedia content down to an image that is …
    1. if HTTPS:// protocol being used, use the Google Page Insights screenshotting “smarts” you can see being used at PDF Slideshow and Form Creation Data URI Contents Tutorial
    2. if HTTP:// protocol being used, use the (thumbnail version of) the first image of the relevant Wikipedia webpage

    … encased by an “a” tag that the click of navigates the user to the relevant Wikipedia content in a new tab (at best), all positioned at the left hand side of the Geo Chart webpage’s H1 or H2 tag heading as a 70px width42px height thumbnail

The conduit here are Ajax Javascript techniques as per …


var myxhr = false;
var oursrc = '';
var woourl='';


function ajit(wourl) {
woourl=wourl;
var xurl = '';
if (document.URL.toLowerCase().indexOf('https') == 0) {
xurl='https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=' + encodeURIComponent(wourl) + '&screenshot=true';
} else {
xurl=document.URL.split('/GeoChart')[0] + '/fgc/?tdinto=&inurl=' + encodeURIComponent(wourl);
}
if (window.XMLHttpRequest) {
myxhr = new window.XMLHttpRequest;
}
else {
try {
myxhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (othermicrosoft) {
try {
myxhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (failed) {
myxhr = false;
}
}
}
if (myxhr) {
myxhr.onreadystatechange = backin;
myxhr.open('GET', xurl, true);
myxhr.send(null);
}
}


function backin() {
if (myxhr.readyState == 4) {
if (myxhr.status == 200) {
if (myxhr.responseText) {
var dbits = myxhr.responseText.split('\"data\":');
if (dbits.length > 1) {
oursrc='data:image/jpeg;base64,' + dbits[1].split('\"')[1].split('\"')[0].replace(/\_/g,'/').replace(/\-/g,'+');
ism='nm';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ism='';
document.getElementById(ism + 'dwoalttwo').style.position='absolute';
document.getElementById(ism + 'dwoalttwo').style.left='20px';
document.getElementById(ism + 'dwoalttwo').style.top='0px';
document.getElementById(ism + 'dwoalttwo').style.opacity='0.95';
document.getElementById(ism + 'dwoalttwo').style.zIndex='51';
} else {
document.getElementById(ism + 'dwoalt').innerHTML='<br><a id=btta href=#myh title=Top>Back to top</a>';
}
document.getElementById(ism + 'dwoalttwo').innerHTML='<a target=_blank id=adw title=Wikipedia style=z-index:52; href=' + woourl + '><img title=Wikipedia style=width:80px;z-index:52; src=' + oursrc + '></img></a>';
document.getElementById('myh').onclick=function() { document.getElementById('adw').click(); }
if (ism != '') { location.href='#btta'; }
} else if (myxhr.responseText.indexOf('<img') != -1) {
dbits = myxhr.responseText.split('<img');
dbits=dbits[1].split(' src=');
ism='nm';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ism='';
document.getElementById(ism + 'dwoalttwo').style.position='absolute';
document.getElementById(ism + 'dwoalttwo').style.left='20px';
document.getElementById(ism + 'dwoalttwo').style.top='0px';
document.getElementById(ism + 'dwoalttwo').style.opacity='0.95';
document.getElementById(ism + 'dwoalttwo').style.zIndex='51';
} else {
document.getElementById(ism + 'dwoalt').innerHTML='<br><a id=btta href=#myh title=Top>Back to top</a>';
}
document.getElementById(ism + 'dwoalttwo').innerHTML='<a target=_blank id=adw title=Wikipedia style=z-index:52; href=' + woourl + '><img title=Wikipedia style=width:80px;z-index:52; src=' + dbits[1].split(' ')[0].split('>')[0] + '></img></a>';
document.getElementById('myh').onclick=function() { document.getElementById('adw').click(); }
if (ism != '') { location.href='#btta'; }
}
}
}
}
}

… with the effect, for a mobile user, of not being interrupted from their quiz, unless this thumbnail (Wikipedia content) appears at the top left, that they can “long click” to open in a “New Tab” (or, perhaps, a “Split View”) as required, at least on the iPad we tried this with.

And so, you can try the changed geo_chart.php Geo Chart interfacer at this live run link, we hope representing an improvement for the Quizzing User Experience for our mobile user readers.


Previous relevant Google Chart Geo Chart More Quizzes Tutorial is shown below.

Google Chart Geo Chart More Quizzes Tutorial

Google Chart Geo Chart More Quizzes Tutorial

In allowing the World Quiz web applications of yesterday’s Google Chart Geo Chart World Quizzes Tutorial work accept more than about …

  • the 10 places (per continent Geo Chart) fitting into a $_GET arguments URL (of about 850 characters, for rjmprogramming.com.au domain) … the first cab off the rank allowing for …
  • a lot more than 10 can be accepted via $_POST in an HTML form method=POST action=./geo_chart.php

You may wonder why “first cab off the rank” here. Well, we’re not sure we won’t involve window.sessionStorage or window.localStorage in future plans. It being PHP we’re writing though, we will need a compelling reason to try this.

We allow you to ask the web application to try more places by (optionally) appending space characters onto the height values they enter.

You can try the changed (and note “function iftoobig()” in particular, here) geo_chart.php Geo Chart interfacer at this live run link, and try it with a few right space appended “heights” to try out this new functionality.


Previous relevant Google Chart Geo Chart World Quizzes Tutorial is shown below.

Google Chart Geo Chart World Quizzes Tutorial

Google Chart Geo Chart World Quizzes Tutorial

We’re heading towards “prove it for n” on top of the recent Google Chart Geo Chart Oceania Quiz Tutorial (“prove it for 2”) progress, making quizzes for …

  • Europe
  • South East Asia and Oceania
  • Africa
  • South America
  • North and Central America
  • Asia

… but feel we need more testing to bed it down, as far as reliability issues go, and we’ll keep you posted on that.

We found clutter issue with ISO 2 character Country Codes …

ISO Code 1 Country TZ Place 1 (Lat,Long) Too Close To Country TZ Place 2 (Lat,Long) ISO Code 2
VA Vatican City
(41.90222,
12.45305)
(-0.02,
+0.03)
Rome, Italy
(41.9,
12.48333)
IT
BJ Porto-Novo, Benin
(6.48333,
2.61666)
(-0.03,
+0.78)
Lagos, Nigeria
(6.45,
3.4)
NG

… and so “fashioned” this into a numerical basis for a “declutter” algorithm


function setsixteenquiz() {
var sixteen=16;
var allcontinents=['Europe','South East Asia and Oceania', 'Africa', 'South America', 'North and Central America', 'Asia'];
var thiscontinent=isquiz;
var cisq=-1;
var exclusions=',';
var sofarq=',-1,';
var ourselceqih=selceqih.replace(/\ data\-alt\-/g, ' data-');
if (thiscontinent == 'South East Asia and Oceania') {
sixteen=10;
} else if (thiscontinent == 'Africa') {
sixteen=17;
} else if (thiscontinent == 'South America') {
sixteen=10;
} else if (thiscontinent == 'North and Central America') {
sixteen=10;
}
for (var isqis=0; isqis<allcontinents.length; isqis++) {
if (allcontinents[isqis] != thiscontinent) {
while (ourselceqih.indexOf(' data-continent=\"' + allcontinents[isqis] + '\"') != -1) {
ourselceqih=ourselceqih.replace(' data-continent=\"' + allcontinents[isqis] + '\"','');
}
}
}
var sqws=ourselceqih.split(' data-continent=\"' + thiscontinent + '\" value=\"');
document.body.title='Awaiting quiz clickable circle symbols to score ...';
document.body.style.cursor=pcur;
if (document.getElementById('chart')) {
document.getElementById('chart').title='Awaiting quiz clickable circle symbols to score ... ';
document.getElementById('chart').style.cursor=pcur;
}
var latsofar=[], longsofar=[], thislats=0.0, thislongs=0.0;
var valid=true, ivalid=0, difflatlong=0.0;

while (quizisos.length < sixteen) {
cisq=-1;
while (sofarq.indexOf(',' + cisq + ',') != -1 || exclusions.indexOf(',' + cisq + ',') != -1) {
cisq=Math.floor(Math.random() * eval(-1 + sqws.length));
cisq++;
if (ourtzlist.indexOf(',' + sqws[cisq].split('\"')[0] + ',') != -1) {
thislats=(eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[0]));
thislongs=(eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]));
}

if (thiscontinent == 'South East Asia and Oceania') {
if (ourtzlist.indexOf(',' + sqws[cisq].split('\"')[0] + ',') != -1) {
if (eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]) < 73.0) { // || eval(ourtzlist.split(',' + ourselceqih[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + ourselceqih[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]) >= 169.0) {
cisq=-1;
}
} else {
cisq=-1;
}
}
}
sofarq+='' + cisq + ',';
if (cisq != -1) {
if (sqws[cisq].split('\"')[0] == 'IT') { exclusions+='VA,'; } else if (sqws[cisq].split('\"')[0] == 'VA') { exclusions+='IT,'; }
if (sqws[cisq].split('\"')[0] == 'BJ') { exclusions+='NG,'; } else if (sqws[cisq].split('\"')[0] == 'NG') { exclusions+='BJ,'; }
difflatlong=0.0;
if (quizisos.length > 0) {
for (ivalid=0; ivalid<quizisos.length; ivalid++) {
difflatlong=Math.abs(eval('' + latsofar[ivalid]) - eval('' + thislats)) + Math.abs(eval('' + longsofar[ivalid]) - eval('' + thislongs));
}
}
if (difflatlong >= 2.0 || quizisos.length == 0) {
latsofar.push(thislats);
longsofar.push(thislongs);
quizisos.push(sqws[cisq].split('\"')[0]);
}

}
}
quizisos.push(\"\");
}

Here’s your chance to try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter Africa, South America, North and Central America and Asia Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Oceania Quiz Tutorial is shown below.

Google Chart Geo Chart Oceania Quiz Tutorial

Google Chart Geo Chart Oceania Quiz Tutorial

Regular readers will know about our penchant for “mathematical induction” theory, in the way you …

  • prove it for 1
  • prove it for 2
  • prove it for n

… and earlier this morning “too proud” moi thought we’d be at “n”, skipping “2” by now getting our Geo Chart interfacing new “Quiz” functionality to have covered user interactions for all the major continents of greater than 10 (of category) places, looking towards the “10 is a bit lame” thinking, to follow. Oh, well! But maybe that’s the point of the “2” in the “mathematical induction” proof “game”. A lot might be discovered, and so it was for us, trying to open the door to … come in …


South East Asia and Oceania ...

… spinner! In broad brush concepts, we discovered …

  • we needed to start to worry about places with an ISO 2 code but no TimeZone …
  • we needed to start to worry about places off to the left, right, and top limits of the Geo Chart limits we establish via those weird width and height values you enter … and on this am sure many will have tweaked that the value integer parts are like a “scalar” measure and the mantissae are a “left zero padded percentage offset into the entire Geo Chart on which to lob” measure
  • we needed to rearrange the scoring system’s denominator as a “seconds timer” rather than a “number of goes”
  • we needed to, at least at the start, mention name of Quiz
  • we needed to start closing previous Wikipedia windows on opening a new one, as applicable
  • we needed to start to worry about clutter (eg. Vatican City and Rome geographicals for two different countries)
  • we needed to start to worry about “skewed representations” (going back to Europe Quiz) whereby the first mention of a country ISO 2 Code within the TimeZone list is a position of a colony or dominion

… whereas we optimistically imagined all we might need to worry about was just …

  • converting (boolean binary decision) variable isquiz=false/true (Javascript code logic) into (string ternary and more decision) variable isquiz=”/’Europe’/’South East Asia and Oceania’ (with more to come … until “n” (for) nirvana) … and associated …
  • adding data-continent=”South East Asia and Oceania” global data attributes into dropdown id=’selceq’ linking ISO 2 codes with Country names
  • trying to add a bit of cursor=’progress’ flagging of web application “thinking time”

Never mind! And so, onto yesterday’s Google Chart Geo Chart Europe Quiz Tutorial progress there is not that much difference user interaction wise, just the offer of another weird “width” value choice (on which to blow your mind) but behind the scenes a “hard working mathematical induction middlemanperson” can now offer you the chance to try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter South East Asia and Oceania Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Europe Quiz Tutorial is shown below.

Google Chart Geo Chart Europe Quiz Tutorial

Google Chart Geo Chart Europe Quiz Tutorial

Up to yesterday’s Google Chart Geo Chart Sorted Small Countries Tutorial, as with interfacings to other Google Charts, we had a two phase aspect to the web application structures …

  1. ask for user interaction via the keyboard
  2. display the resultant Google Chart taking notice of that user interaction

… but today’s extension of Geo Chart interfacing functionality opens the door to the new

  • display the resultant Google Chart taking notice of that user interaction and allowing click/touch continuing interaction in the form of a quiz … first cab off the rank … Europe Quiz

The work recently has helped because …


function gck(igck) {
var ansis='';
if (document.getElementById('attachedImage' + ('' + igck).replace('-1',''))) {
var xxx=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).getAttribute('title');
if (xxx.indexOf('#') != -1) {
if (isquiz) {
maybe_bad=false;
if (xxx.split('#')[1].indexOf('/') != -1) {
ansis=xxx.split('#')[1].split('/')[eval(-1 + xxx.split('#')[1].split('/').length)].toLowerCase();
} else {
ansis=xxx.split('#')[1];
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(xxx.split('#')[1],'_blank', 'top=50,left=50,width=500,height=500');
} else if (xxx == '') {
if (isquiz) {
maybe_bad=false;
if (document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title.indexOf('/') != -1) {
ansis=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title.split('/')[eval(-1 + xxx.split('#')[1].split('/').length)].toLowerCase();
} else {
ansis=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title;
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title,'_blank', 'top=50,left=50,width=500,height=500');
} else {
if (isquiz) {
maybe_bad=false;
if (xxx.indexOf('/') != -1) {
ansis=xxx.split('/')[eval(-1 + xxx.split('/').length)].toLowerCase();
} else {
ansis=xxx;
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(xxx,'_blank', 'top=50,left=50,width=500,height=500');
}
}
}

… is an onclick place we’ve set aside for our SVG intervention work. Keep it to no keyboard for this Europe Quiz, and we are happy (with this new idea, reminiscent of recent tweaking at Google Chart Annotated Timeline Whitespace Delimitation Tutorial).

So, again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter Europe Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Sorted Small Countries Tutorial is shown below.

Google Chart Geo Chart Sorted Small Countries Tutorial

Google Chart Geo Chart Sorted Small Countries Tutorial

Yesterday’s Google Chart Geo Chart Small Countries Overlay Tutorial‘s workings potentially using the geographicals (or marker) mode of use actually involve intervention logic within what Google provide SVG-wise for the Geo Chart content.

And so, for some time, the order in which we entered …

Country Surface Area (sq km)
Australia 7692024
New Zealand 269190
Andorra 468

… we entered, interactively by us, like, personally, like, in that order above, like. But for a day or two we were covering up a gap in the “wall of logic” plaster we had created for Google Chart select event logic (actually non-existant for the Geo Chart, but we code for onclick logic to navigate a user to a relevant Wikipedia page). The good news is we have fixed it now, not tying the user down to entering data in any particular order.

Fixed what, now? (I thought I heard you ask?!) Well, the alignment of &aregeographical= data to the symbology presented at the geographical positions on the Geo Map asks that the order we present corresponds to the relevant order of relevant Google SVG elements, and Google orders these from the largest numerical value down to the smallest, as you notice as far as Surface Area (sq km) suits an order of Australia, New Zealand, Andorra …

First non-overlay URL version goes https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-34.91667|138.58333|~Australia~,7692024]%20,%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
Second overlay URL version goes https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-34.91667|138.58333|~Australia~,7692024]%20,%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20&overlay=y&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
But the recent work means overlay URL version created interactively with order New Zealand, Andorra, Australia https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20,%20[-34.91667|138.58333|~Australia~,7692024]%20&overlay=y&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
also works

… and the changes necessary to ensure this go


// var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;
function assess_small(indatar) {
var ipl=0, jpl=0, kpl=0, pushxx=[];
var outsuffix='';
var outdatar=indatar;
if (pushfrom.length > 0 && !oneisnotapplicable && oneistoosmall) {
for (jpl=0; jpl<pushfrom.length; jpl++) { // for (var ipl=0; ipl<pushfrom.length; ipl++) {
if (jpl == 0) {
var huhdatas=indatar.split('~');
for (var ihuhdatas=2; ihuhdatas<huhdatas.length; ihuhdatas+=2) {
if (huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0].replace('%20',' ').indexOf(' ') != -1) {
pushxx.push(('00000000000000000000000' + huhdatas[ihuhdatas].split(',')[1].split(']')[0]).slice(-22) + ' ... ' + huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0]);
}
pushxx.push(('00000000000000000000000' + huhdatas[ihuhdatas].split(',')[1].split(']')[0]).slice(-22) + ' ... ' + encodeURIComponent(huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0]));
}
pushxx.sort();
pushxx.reverse();
}
ipl=jpl;
for (kpl=0; kpl<pushfrom.length; kpl++) {
if (ipl == jpl && pushxx[jpl].split(' ... ')[1] == pushfrom[kpl].split('~')[1].split('~')[0]) {
ipl=kpl;
pushxx[jpl]=pushxx[jpl].split(' ... ')[0] + ' ... ';
}
}

if (outdatar.indexOf(pushfrom[ipl]) != -1) {
if (outsuffix == '') {
outsuffix='&aregeographicals=' + pushag[ipl];
} else {
outsuffix+='%2C' + pushag[ipl];
}
while (outdatar.indexOf(pushfrom[ipl]) != -1) {
outdatar=outdatar.replace(pushfrom[ipl], pushto[ipl]);
}
}
}
}


return outdatar + outsuffix;
}

Yet again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Small Countries Overlay Tutorial is shown below.

Google Chart Geo Chart Small Countries Overlay Tutorial

Google Chart Geo Chart Small Countries Overlay Tutorial

With “overlay” techniques available in life it might be tempting to say “never say never” because you don’t have to compromise a weak solution for a less weak solution. Yesterday’s Google Chart Geo Chart Small Countries Tutorial‘s Google Chart Geo Chart‘s homegrown interfacer tactics for Small Countries is a case in point.

You may recall from yesterday how we dynamically reverted to “geographicals mode” display (Google call it “Markers” mode) when the shading for a Small Country would lead to “data loss”. But what if we …

  • continue what we were doing yesterday “overlayed”

    … onto …

  • what we changed from URL-wise with “function assess_small()” (with the one codeline change

    outsuffix='&overlay=y&aregeographicals=' + pushag[ipl];

    ) … in the form of two new HTML iframe code below …
    <?php

    if (isset($_GET['overlay']) || isset($_POST['overlay'])) {
    echo "<script> function overlayit() {
    var ourls=documentURL.split('&overlay=')[0].split('[');
    var ourl=ourls[0];
    for (var iouris=1; iouris<ourls.length; iouris++) {
    if (ourls[iouris].substring(0,1) == '~') {
    ourl+='[' + ourls[iouris];
    } else {
    ourl+='[' + ourls[iouris].replace(ourls[iouris].split('~')[0],'');
    }
    }
    document.body.style.zIndex='-12';
    document.getElementById('doverlay').innerHTML='<iframe style=\"position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:2;opacity:0.95;\" src=\"' + ourl + '\"></iframe>';
    document.getElementById('doverlaytwo').innerHTML='<iframe style=\"position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:22;opacity:0.9;\" src=\"' + documentURL.replace('&overlay=','&qw=') + '&guess=' + '\"></iframe>';
    }
    setTimeout(overlayit, 2000);
    </script>
    ";
    }

    ?>

Again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Small Countries Tutorial is shown below.

Google Chart Geo Chart Small Countries Tutorial

Google Chart Geo Chart Small Countries Tutorial

We last used the excellent Google Chart Geo Chart tool with the work of Window LocalStorage Client Versus Server Map Tutorial, and it was this project that alerted us to both a weakness and a strength of that chart …

  • a weakness being its inability to get the resolution to shade a small country (eg. today’s tutorial picture‘s Andorra) … but, the good news, as used with this integration work above …
  • a strength is the alternative display mechanism via geographical entries

… and so, what if …

  • as the user enters in their Country (or Geographical) data …
  • if we can determine it as being a Country being entered … and…
  • you have only ever been entering Countries … and …
  • any one Country so defined has a surface area less than 10000 square kilometers … then …
  • we navigate to a Geographical data version of this “only Countries entered” data set … so that …
  • even small such Countries will be displayed …
  • as they would not if still in the default “only Countries entered” mode of display

We introduce three new sources of data in order to piece together the (Javascript via PHP coding) logic for this …

  1. TimeZone and Geographicals and ISO 2 Letter Code information …

    var ourtzlist='<option value="Africa/Abidjan" data-geo="5.31666,-4.03334,GMT,CI,+0">Africa/Abidjan</option><option value="Africa/Accra" data-geo="5.55,-0.21667,GMT,GH,+0">Africa/Accra</option>'; // etcetera etcetera etcetera
  2. Country Name and ISO 2 Letter Code information (etcetera etcetera etcetera) …

    <div id=dlookups>
    <select id='selceq' style='display:none;'>
    <option value='AF'>Afghanistan</option>
    <option value='AX'>Aland Islands</option>
    <option value='AL'>Albania</option>
    </select></div>
  3. Surface Areas of Countries thanks to Wikipedia (etcetera etcetera etcetera) …

    <table style='display:none;' id='surface_area' border='1' cellpadding='2' cellspacing='0'>
    <tbody><tr bgcolor='#efefef'>
    <th>Pos
    </th><th>Country
    </th>
    <th>Area (km²)
    </th></tr>
    <tr>
    <td>1</td>
    <td><a data-href='/wiki/Russia' title='Russia'>Russia</a></td>
    <td>17098246
    </td></tr>
    <tr>
    <td>2</td>
    <td><a data-href='/wiki/Canada' title='Canada'>Canada</a></td>
    <td>9984670
    </td></tr>
    <tr>
    <td>3</td>
    <td><a data-href='/wiki/People%27s_Republic_of_China' title='People's Republic of China'>China</a></td>
    <td>9572900
    </td></tr>
    </tbody></table>

… used where we process a user Country (or Geographical) interaction Javascript code snippet where variable thisris is that user interaction result …


var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;

if (ourtzlist.indexOf(',' + thisris.toUpperCase() + ',') != -1 && thisris.length == 2) {
if (selceqih == '') { selceqih=document.getElementById('selceq').innerHTML; }
if (saih == '') { saih=document.getElementById('surface_area').innerHTML; }
pushfrom.push('[~' + thisris + '~');
pushto.push('[' + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + thisris.toUpperCase() + '~');
if (selceqih.indexOf(' value=\"' + thisris.toUpperCase() + '\">') != -1) {
pushag.push('http.' + encodeURIComponent(selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0]));
} else {
pushag.push('');
}
if (saih.indexOf('>' + selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0]) != -1) {
thissa=saih.split('>' + selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0])[1].split('<td>')[1].split('<')[0].split(String.fromCharCode(10))[0];
if (eval('' + thissa) < 10000) {
oneistoosmall=true;
}
}
} else if (('' + thisris).trim() != '' && selceqih.toUpperCase().indexOf('>' + thisris.toUpperCase()) != -1) {
thisisocc=selceqih.toUpperCase().split('>' + thisris.toUpperCase())[0].split(' VALUE=\"')[eval(-1 + selceqih.toUpperCase().split('>' + thisris.toUpperCase())[0].split(' VALUE=\"').length)].split('\"')[0];
pushfrom.push('[~' + encodeURIComponent(thisris) + '~');
pushto.push('[' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + encodeURIComponent(thisris) + '~');
pushag.push('http.' + encodeURIComponent(thisris));
if (thisris.indexOf(' ') != -1) {
pushfrom.push('[~' + thisris + '~');
pushto.push('[' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + encodeURIComponent(thisris) + '~');
pushag.push('http.' + encodeURIComponent(thisris));
}
if (saih.toUpperCase().indexOf('>' + thisris.toUpperCase()) != -1) {
thissa=saih.toUpperCase().split('>' + thisris.toUpperCase())[1];
thissa=thissa.split('<TD>')[1].split('<')[0].split(String.fromCharCode(10))[0];
if (eval('' + thissa) < 10000) {
oneistoosmall=true;
}
}
}

… and if remaining relevant just before the next navigation happens, where variable indatar represents the default “only Countries entered” mode of display value …


// var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;
function assess_small(indatar) {
var outsuffix='';
var outdatar=indatar;
if (pushfrom.length > 0 && !oneisnotapplicable && oneistoosmall) {
for (var ipl=0; ipl<pushfrom.length; ipl++) {
if (outdatar.indexOf(pushfrom[ipl]) != -1) {
if (outsuffix == '') {
outsuffix='&aregeographicals=' + pushag[ipl];
} else {
outsuffix+='%2C' + pushag[ipl];
}
while (outdatar.indexOf(pushfrom[ipl]) != -1) {
outdatar=outdatar.replace(pushfrom[ipl], pushto[ipl]);
}
}
}
}


return outdatar + outsuffix;
}

You can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Window LocalStorage Client Versus Server Map Tutorial is shown below.

Window LocalStorage Client Versus Server Map Tutorial

Window LocalStorage Client Versus Server Map Tutorial

Get a good map, and a goodly number of times you’ll want a map of smaller or larger scale than the one you have. Murphy’s Law? This is probably why in the wonderful woooooooorrrrrrrrlllllld of Google Charts they have included …

  • Geo Chart topographic map of the world or of regions
  • Map Chart terrestrial/satellite map of your group of markers at a zoom level of your choosing

… and hope you can see that the latter can save the day for a Short Distance Trip (corner shop, anyone?!).

So we’ve added onto yesterday’s Window LocalStorage Client Versus Server Timeline Tutorial progress a new toggling button to view a scenario in either Google Chart scenario above.

You can see this integration work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link supervising a tweaked geo_chart.php Geo Chart interfacer.


Previous relevant Window LocalStorage Client Versus Server Timeline Tutorial is shown below.

Window LocalStorage Client Versus Server Timeline Tutorial

Window LocalStorage Client Versus Server Timeline Tutorial

Up to yesterday’s Window LocalStorage Client Versus Server User Tutorial‘s progress, our Capital City Find Matching Country Report web application project was all about …

  • where (and capital of “what”) … but we often seek out a way to add into the mix that 4th dimension …
  • when (ie. time)

… and regarding the current project, a …

  • where “map” … can interface with a …
  • when “Trip Plan Itinerary”

… and for this purpose, we’re going to interface to the excellent Google Charts Annotated Timeline Chart, thanks, because it combines links of “time” to “user annotations” in a timeline way, that similar way you might describe the qualities of a Trip, even before you’ve gone on that trip. We’ve also added it so that an unordered places list can be turned into a Trip Plan Itinerary at the click/touch of a new map 🗺 &#128506; emoji button.

Again, see how these timeline amendments were achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link and annotatedtimeline_chart.php which changed quite a lot.


Previous relevant Window LocalStorage Client Versus Server User Tutorial is shown below.

Window LocalStorage Client Versus Server User Tutorial

Window LocalStorage Client Versus Server User Tutorial

The inherent weakness with our current Capital City Find Matching Country Report web application project, to our minds, was that places of interest are not restricted to the Capital Cities of Countries, especially when “Trip Planning”. On the other hand, it would be impossible to cater for every “place” in the world. That is far too subjective for good web application applicability. What would be good though, is to allow in user defined …


Place name, Country name

… terms, the definitions of interest to a user. We can ask this …

  • flagged by the click/touch of an emoji button … and …
  • the interactive entry presented via a Javascript prompt window

. When thinking of data applicable to an individual, then that can be catered for by recording it in localStorage where it will be recalled on the next execution of that web application in the same web browser.

This, along with a Colour Wheel of the “nearest TimeZone place” onto the existing logic of yesterday’s Window SessionStorage Client Versus Server Order Tutorial progress could make for a more useful and practical tool for those Trip Planners out there!

See how this was achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Did you know?

To click/touch one of those Google Chart Geo Chart lines between Emoji Flag Markers will show a new Google Maps directions web page with transport times and detail, as well as an inhouse crow fly distance of that trip leg, as shown up the top right of today’s tutorial picture.


Previous relevant Window SessionStorage Client Versus Server Order Tutorial is shown below.

Window SessionStorage Client Versus Server Order Tutorial

Window SessionStorage Client Versus Server Order Tutorial

If we are to honour our thoughts of being able to use our current Capital City Find Matching Country Report web application as a Trip Planner …

Our primary integration today is to (software) integrate the great Weather Underground and its great API service for autocomplete name searches for weather (and hurricane) information. Why bother? Well, can you not envisage a user using that Ajax functionality of yesterday’s Window SessionStorage Client Versus Server Ajax Tutorial as a trip planner, perhaps, or as a “checking up on relatives overseas” tool, perhaps? And not all the capital cities are timezone places, and so for some of those we can use Weather integration to still show apt online information when click/touching a Countries Report row. Speaking of this “row”, we make an improvement whereby on a first click of a right hand (Country) row cell, that cell is not initially a contenteditable=”true” one (that may frustrate showing the keyboard on mobile, when most likely it was the row touch intended), but then becomes a contenteditable=”true” cell henceforth.

… then yesterday’s Window SessionStorage Client Versus Server Flags Tutorial “progress to now” needs to take notice of a user’s order of multiple select (dropdown) element click/touching of Capital City option (sub)elements, just as we did with the recent User Controlled Dynamic Javascript YouTube Embedded API Ordered Tutorial‘s web application project to allow for a user ordered YouTube video playlist.

Because what is a Trip Planner without an ordered trip? Well, that is debatable, but what isn’t (debatable), is that there will be people in the world who appreciate the “mapping out” of a proposed Trip Planning Itinerary. What could we call on here? We can think of the Google Chart Geo Chart work around about the time of Google Geo Chart Co-ordinate Emojis Tutorial, when we started using …

  • a world map … with …
  • emoji markers … and optionally …
  • joined up by straight lines

… an idea for a Trip Plan itinerary synopsis, perhaps?!

If you examined closely yesterday’s code changes you will have noticed our collecting of TimeZone Place geographical latitude and longitude information. Today, we start making use of that preparatory work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Stop Press

The “emoji markers” above (as of 2 January 2020) will be “country flags” (as per Window SessionStorage Client Versus Server Flags Tutorial ideas), as defined.


Previous relevant Window SessionStorage Client Versus Server Flags Tutorial is shown below.

Window SessionStorage Client Versus Server Flags Tutorial

Window SessionStorage Client Versus Server Flags Tutorial

Yes, there’s more to do onto yesterday’s Window SessionStorage Client Versus Server CSS Tutorial‘s Capital City Find Matching Country Report web application project, in our eyes. We have not even mentioned “Internationalization” as a concept up to now. In this line of thinking …

Did you know?

Emoji flags via ISO 2 character country codes are dead easy via Regional Indicator Symbol characters …


var lri="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];

var thiscc='AU'; // ISO 2 character countrycode for Australia
var ccsuff='', ccchar=' ';
for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
ccsuff+='&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
}
document.getElementById('lastflag').innerHTML=ccsuff;

… to result in (via <span style=font-size:64px;>&#127462;&#127482;</span>) …


🇦🇺

… providing interest and general translatability to the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.


Previous relevant Window SessionStorage Client Versus Server CSS Tutorial is shown below.

Window SessionStorage Client Versus Server CSS Tutorial

Window SessionStorage Client Versus Server CSS Tutorial

Further to yesterday’s Window SessionStorage Client Versus Server Integration Tutorial we have a two pronged improvements set for you today with our current Capital City Find Matching Country Report web application project …

  • CSS styling changes … and …
  • additional functionality for Email and SMS links back to our current Capital City Find Matching Country Report web application project (to complete the cycle)

We use several modes of CSS application (the first and last of particular relevance to today’s “highlighting of workflow” improvements) …

… the “static” measures often helping to highlight the web application’s main workflow of user interaction and the “dynamic” measures helping to alert the user as to where to proceed with their “workflow”.

In terms of CSS styling work …

  1. for non-mobile platforms we allow for more columns to be applied to our Capitals select (dropdown) element (in order to reduce some user scrolling, as does our new additional A-Z letter basis sorting functionality) as per … the “dynamic” Javascript DOM “class” modifications

    if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    document.getElementById('lefttd').className='lefttd';
    }

    … dovetailing with the “static” internal CSS coding

    <style>
    .lefttd {
    column-count: 4;
    max-height: 35%;
    vertical-align: top;
    max-width: 70%;
    font-size: 8px;
    background-color: rgba(205,205,205,0.5);
    background-image: -webkit-gradient(
    linear,
    right bottom,
    left top,
    color-stop(0, rgba(205, 205, 205, 0.8)),
    color-stop(0.50, rgba(255, 255, 0, 0.2))
    );
    background-image: -o-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -moz-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -webkit-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -ms-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: linear-gradient(to left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);

    }
    </style>

    … and please note that around here at RJM Programming we have a “far from hard and fast rule” (but a rule regardless) regarding HTML element ID and class attributes that they concern (and (usually) be compartmentalised into) Javascript (DOM) manipulations and CSS styling issues respectively … and add a linear-gradient background to the table cell when expecting the initial user interaction on non-mobile platforms
  2. a “dynamic” Javascript DOM “class” modification … document.getElementById(‘myrepsb’).className=’dglow’; … is made to the “Report…” button at the Capitals select (dropdown) onfocusout event so as to highlight (with “glow” inspired styling) where user interaction may flow to

As far as links go, you may expect to need serverside means to construct these in online Email and SMS message interfacing, but email (client program) products like Gmail parse your ascii text and convert http: or https: protocol URLs in your Email body to hyperlinks, as does the Messages SMS application here on this MacBook Pro using macOS Mojave. Cute, huh?! So to close the circle back from remote thar’ parts back to our web application is a simple matter of, in broad brush terms …

  • adding two new buttons called “Email Columns and Links …” and “SMS Columns and Links …” that …
  • set a global variable andlinkto = true; … setting in play, within the report writing code (that likes monospaced fonts) …
  • add a new links column to the right with URLs like …
    https://www.rjmprogramming.com.au/HTMLCSS/wls_vs_php.htm?andgo=y&countries=Belize&capitals=Belmopan
    … to tell your client programs to form the hyperlinks for us (if they are “of the mood”, that is!)

To improve user experience we use “dynamic” Javascript DOM HTML “style” attribute change means to easier close the “Colour Wheel” helper web application “above the fold” by changing the CSS z-index (Javascript DOM [element].style.zIndex) of elements accordingly, when the user clicks other elements. You can see all this with the first “the changed” link above, where all “glow” CSS styling will also feature prominently.


Previous relevant Window SessionStorage Client Versus Server Integration Tutorial is shown below.

Window SessionStorage Client Versus Server Integration Tutorial

Window SessionStorage Client Versus Server Integration Tutorial

We hope, when performing a “software integration” task, that the two or more components of that integration work with each other’s talents, rather than a big tussle like reinventing the wheel. This ideal makes the work …

  • sometimes difficult but rewarding because …
  • the differences between two independent software components can be quite large and daunting … and the programmer has to see that …
  • care is applied so as not to wreck previous functionality and integrations in making the current integration work

… and that is why we’ve made corollaries to “building from scratch” (when planning and design is a huge component) can be a lot simpler than a software integration “renovation”, in the past, here at this blog.

Our primary integration today is to (software) integrate the great Weather Underground and its great API service for autocomplete name searches for weather (and hurricane) information. Why bother? Well, can you not envisage a user using that Ajax functionality of yesterday’s Window SessionStorage Client Versus Server Ajax Tutorial as a trip planner, perhaps, or as a “checking up on relatives overseas” tool, perhaps? And not all the capital cities are timezone places, and so for some of those we can use Weather integration to still show apt online information when click/touching a Countries Report row. Speaking of this “row”, we make an improvement whereby on a first click of a right hand (Country) row cell, that cell is not initially a contenteditable=”true” one (that may frustrate showing the keyboard on mobile, when most likely it was the row touch intended), but then becomes a contenteditable=”true” cell henceforth.

As a user experience improvement for “trip planners” perhaps, we allow the user to alphabetically sort the presented select (dropdown) element entries …


var firstopt='';
var wasopts='';
var restopts='';

function readyitforsort(iselid) {
var optsare=[];
var huhisel=document.getElementById(iselid).innerHTML;
var huhsopts=huhisel.split('</option>');
for (var ihuh=0; ihuh<huhsopts.length; ihuh++) {
if (huhsopts[ihuh].trim() != '') {
if (firstopt == '') {
firstopt=huhsopts[ihuh] + '</option>';
} else {
wasopts+=huhsopts[ihuh].replace('option ','option data-ih="' + (huhsopts[ihuh].split('>')[eval(-1 + huhsopts[ihuh].split('>').length)] + '" ')) + '</option>';
optsare.push(huhsopts[ihuh].replace('option ','option data-ih="' + (huhsopts[ihuh].split('>')[eval(-1 + huhsopts[ihuh].split('>').length)] + '" ')) + '</option>');
}
}
}
optsare.sort();
for (var jhuh=0; jhuh<optsare.length; jhuh++) {
restopts+=optsare[jhuh];
}
}

… controlled by a new dropdown in the left hand column header cell.

We also allow the user to move the iframe element with some positioning emoji buttons near the “Close” button one (of yesterday’s work).

Into the future, too, we’ll have more to say regarding the germination of an idea “to allow a mobile onmouseover simulator (of sorts)” be to allow the user to perform a swipe across an individual HTML element of interest on mobile platforms (ie. harness ontouchmove event) as per (so far) … kicked off by “<body onload=” setTimeout(athn, 5000); “>” …


var last24='';
var rectdc;

function nodivalert() {
document.getElementById('divalert').style.display='none';
document.getElementById('divalert').style.zIndex='-456';
document.getElementById('divalert').style.left=('-' + rectdc.left).replace('px','') + 'px';
document.getElementById('divalert').style.top=('-' + rectdc.top).replace('px','') + 'px';
}

function ourdivalert(inmsg) {
document.getElementById('divalert').style.position='absolute';
document.getElementById('divalert').style.left=('' + rectdc.left).replace('px','') + 'px';
document.getElementById('divalert').style.top='' + eval(-80 + eval(('' + rectdc.top).replace('px',''))) + 'px';
document.getElementById('divalert').style.backgroundColor='#e0e0e0';
document.getElementById('divalert').style.display='block';
document.getElementById('divalert').style.zIndex='456';
document.getElementById('divalert').style.opacity='0.8';
document.getElementById('divalert').style.padding='5px 5px 5px 5px';
document.getElementById('divalert').innerHTML=inmsg + '<br><br><input type=button value=Close onclick=nodivalert();></input>';
setTimeout(nodivalert,9000);
}

function athn() {
rectdc=document.getElementById('dc').getBoundingClientRect();
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('dc').ontouchmove=function(event) { if (last24.substring(0,eval(-1 + last24.length)) == event.target.title.substring(0,eval(-1 + event.target.title.length))) { last24=last24; } else { last24=event.target.title; ourdivalert(event.target.title); } }
} else {
document.getElementById('dc').onmousemove=function(event) { if (last24.substring(0,eval(-1 + last24.length)) == event.target.title.substring(0,eval(-1 + event.target.title.length))) { last24=last24; } else { last24=event.target.title; ourdivalert(event.target.title); } }
}
}

… working with the new HTML …


<div id=divalert></div>
</body>
</html>

… to try to allow the “explainer of an element” advantages non-mobile platforms have for hovering over an HTML element with a title attribute filled in.

And so, yet again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new Weather integration functionality. It caused the changed colour_wheel.html‘s colour wheel (at this live run link) to be affected (by integrations “up”).


Previous relevant Window SessionStorage Client Versus Server Ajax Tutorial is shown below.

Window SessionStorage Client Versus Server Ajax Tutorial

Window SessionStorage Client Versus Server Ajax Tutorial

We have a few “clientside chestnuts” to use with our current Capital City Find Matching Country Report web application project today, those being …

  • Ajax functionality, kicked off by an “onclick” event set of logic, allowing mobile platforms to also have a look in (the look in that they miss when the event logic is off the “onmouseover” event)
  • iframe and its …
    1. srcdoc attribute (“content” alternative to src “url” attribute) … along with, and crucially needing (because srcdoc ignores its own document.body onload goings on, that we need the “Iframe Client Pre-Emptive” methods below to circumvent) the …
    2. onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)

… adding onto yesterday’s Window SessionStorage Client Versus Server Canvas Tutorial.

It’s not that involved with the Ajax work today, given that there are no cross-domain issues, though there are cross-protocol (SSL https: versus non-SSL http:) issues to be careful about. Those can be addressed because the web application is recalled to present its “Country Report” and that is the opportunity to check on protocol navigation requirements.

Along the way, we also make this happen for the user on …

  • click/touching a table row … it sets off new “tr” (table row) element logic calling our (inhouse) Timezone and Wikipedia Place Information helper (HTML) via Ajax (so not leaving the webpage) … and because of place name oddities we allow for …
  • “td” (table cell) element user amendments by setting their contenteditable attributes to “true” (since fixed, but we found the Timezone Europe/Tirane pointing at Tirane in Albania used to be spelt “Tirana”)

… that latter methodology normally a technique we apply to “div” elements (so, there you are!)

Also used are “overlay” techniques, two of the “usual suspects” here coming into play, to present to the “Ajax content to srcdoc iframe arrangements” …

Yet again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new “Ajax” functionality.


Previous relevant Window SessionStorage Client Versus Server Canvas Tutorial is shown below.

Window SessionStorage Client Versus Server Canvas Tutorial

Window SessionStorage Client Versus Server Canvas Tutorial

Yesterday’s Window SessionStorage Client Versus Server Share Tutorial dealt with ascii text clipboard copy assisted sharing options with our current Capital City Find Matching Country Report web application project. This suited both Email and SMS share options we coded for, but today’s extension of functionality from “ascii text” data to “graphical data” only suits Email sharing. The other caveat with our work is that no serverside (for us, PHP) help is allowed, so no PHP mail here.

What comes into play with a “graphical data” clientside (only) sharing approach? It will not surprise many readers that, for us, it involves …

  • canvas element … converting HTML table outerHTML “ascii text” data … via …
  • canvas drawing methods “[canvasContext].strokeRect()” and “[canvasContext].strokeText()” via “[cellElement].getBoundingClientRect()” … to convert that canvas element content via …
  • [canvasElement].toDataURL() … to an …
  • img element nested in a div contenteditable=true element … so as to hook in with today’s very useful helper link, thanks … use …

  • function tabletoclipboard(canvas) { // thanks to https://stackoverflow.com/questions/27863617/is-it-possible-to-copy-a-canvas-image-to-the-clipboard
    var img = document.createElement('img');
    img.src = canvas.toDataURL();

    var div = document.createElement('div');
    div.contentEditable = true;
    div.appendChild(img);
    document.body.appendChild(div);

    // do copy
    SelectText(div);
    document.execCommand('Copy');
    document.body.removeChild(div);
    }

    function SelectText(element) { // thanks to https://stackoverflow.com/questions/27863617/is-it-possible-to-copy-a-canvas-image-to-the-clipboard
    var doc = document;
    if (doc.body.createTextRange) {
    var range = document.body.createTextRange();
    range.moveToElementText(element);
    range.select();
    } else if (window.getSelection) {
    var selection = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(element);
    selection.removeAllRanges();
    selection.addRange(range);
    }
    }
  • to leave the user’s device’s clipboard containing a useful table (with linework) … ready to …
  • paste into an email body section

… sharing off to an emailee collaborator.

Again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new “Email Table” button functionality.


Previous relevant Window SessionStorage Client Versus Server Share Tutorial is shown below.

Window SessionStorage Client Versus Server Share Tutorial

Window SessionStorage Client Versus Server Share Tutorial

Yesterday’s Window SessionStorage Client Versus Server Tutorial has been amended today for two new sharing and collaboration options, those being …

  • email
  • SMS

… but you may well be familiar with the restrictions on email and SMS client (program) approaches to this, coming from HTML “a” link “mailto:” and “sms:” href property prefixes respectively. We’re going to need help with the 800 odd character (length) restrictions with the (resultant) web address (bar) URL, but what? How about working off the great advice of this wonderful link, thanks, to copy what we’d have assembled into an ascii text Report into the characters contained by the user’s device’s clipboard?


function copytoclipboard(str) { // thanks to https://hackernoon.com/copying-text-to-clipboard-with-javascript-df4d4988697f
var el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
}

An issue that springs up here using such clipboard ascii text content, whenever you get the Font choice given to you, pick a monospaced Font like Courier New or “Fixed Width”.

See the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new sharing functionality.


Previous relevant Window SessionStorage Client Versus Server Tutorial is shown below.

Window SessionStorage Client Versus Server Tutorial

Window SessionStorage Client Versus Server Tutorial

Sometimes it’s the case at this blog that we’d like to introduce a new topic, but do not do so, because we cannot show any real world (or real application) use of that concept. So it has been, up until now, with the concept of (web browser) window (object) sessionStorage property. But yesterday’s Window LocalStorage Client Versus Server Primer Tutorial represented an opportunity akin to when Haley’s Comet gets at its closest to the Earth … while you see a chance, take it … chance because of that nuance whereby we were not trying to store data for any other purpose than passing data onto …

  1. a known entity … ie. same web application … at …
  2. a known time … ie. immediately

… two conditions that make the code design “marginally” more ideal for the window object property concept of sessionStorage rather than localStorage, in that any …


localStorage.removeItem([knownLocalStorageName]);

… becomes superfluous as with sessionStorage data will disappear between web browser sessions, anyway.

We offer this new concept as a non-default option of a select (dropdown) element replacement to the h1 element hardcoding “localStorage” with the changed wls_vs_php.htm Capital City Find Matching Country Report live run. The other nuance of difference with sessionStorage usage is that in the document.body onload event logic, we may as well (as part of other changes) pre-emptively look for, and if there, respond to, any found sessionStorage data points, even without the user having flagged it specifically


var datamode='localStorage';

function checkforreport() {
var divcont='';
var dcaps, dctys, idis;
if (getcapitals == 'localStorage') {
if (window.localStorage) {
getcapitals=decodeURIComponent(localStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
localStorage.removeItem('wls_vs_php_capitals');
} else {
getcapitals='';
}
} else if (getcapitals == 'sessionStorage') {
document.getElementById('smode').value=getcapitals;
datamode=getcapitals;
if (window.sessionStorage) {
getcapitals=decodeURIComponent(sessionStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
} else {
getcapitals='';
}
}
else if (getcapitals == '' && window.sessionStorage) {
getcapitals=decodeURIComponent(('' + sessionStorage.getItem('wls_vs_php_capitals')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (getcapitals != '') {
document.getElementById('smode').value='sessionStorage';
datamode='sessionStorage';
}
}

if (getcountries == 'localStorage') {
if (window.localStorage) {
getcountries=decodeURIComponent(localStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
if (getcapitals.replace('localStorage','') != '' && getcountries.replace('localStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
localStorage.removeItem('wls_vs_php_countries');
} else {
getcountries='';
}
} else if (getcountries == 'sessionStorage') {
if (window.sessionStorage) {
getcountries=decodeURIComponent(sessionStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
if (getcapitals.replace('sessionStorage','') != '' && getcountries.replace('sessionStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
} else {
getcountries='';
}
}
else if (getcountries == '' && document.getElementById('smode').value == 'sessionStorage' && window.sessionStorage) {
getcountries=decodeURIComponent(('' + sessionStorage.getItem('wls_vs_php_countries')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (getcountries != '') {
document.getElementById('smode').value='sessionStorage';
datamode='sessionStorage';
}
}

if (getcapitals != '' && getcountries != '') {
divcont='<table border=5 style="width:95%;vertical-align:top;background-color:white;"><tr style=background-color:#f0f0f0;"><th>Capital</th><th>Country</th></tr></table>';
dcaps=getcapitals.split('|');
dctys=getcountries.split('|');
for (idis=0; idis<dcaps.length; idis++) {
divcont=divcont.replace('</table>', '<tr><td>' + dcaps[idis] + '</td><td>' + dctys[idis] + '</td></tr></table>');
}
document.getElementById('dreport').innerHTML=divcont;
}
document.getElementById('smode').value=datamode;
}

Which beggars the question “What are the differences between sessionStorage and localStorage?” A quick reading might surmise that “the latter has an expiration date”. We leave you with an open ended Google search so that you may extend your readings on this.


Previous relevant Window LocalStorage Client Versus Server Primer Tutorial is shown below.

Window LocalStorage Client Versus Server Primer Tutorial

Window LocalStorage Client Versus Server Primer Tutorial

Even though we rave on a lot about serverside PHP and its $_POST method=POST (versus HTML/Javascript recipient via ? and & argument $_GET method=GET scenario) data length advantages as the recipient of an HTML form method=POST set of data that could be sizeable, we’ve just realized that there is a client Javascript and window.localStorage methodology that may help alleviate the need to involve PHP (and any other serverside intervention) on occasions.

Hint: Yes, we’ve raved on about this too?! Does the blog posting title give it away? Okay, yes, it should read “localStorage”, but thought we’d gone past such juvenile finickiness since the Whac-A-Mole controversy of 1st December 2019 (or even The Great Tea Trolley Disaster of ’67, we daresay).

It can even use a “self-destruct” approach to the use of this “localStorage” on having used it because …

  • the web application knows who is using it (localStorage) … and on having accessed and read it …
  • the web application knows it (localStorage) is of no use to any other user (in this web application’s case, at least)

… which is very pleasing for a Land Surveyor who likes to leave cow paddocks as they’ve seen them so to speak. Except it’s like having a ten tonne truck worth of data access in amongst the cow pats when having access to “localStorage” (or PHP), rather than a little piddle of calf wee (wee Metcalfes know a thing or two about these things!) data access of ? and & HTML/Javascript URL arguments (or even if we were to use HTTP Cookies).

It’s not as if we all have access to serverside language usage, though we do, because we really like PHP and MAMP and Apache/PHP/MySql web servers (and have arranged our development environment accordingly), but what if you are starting out in web development, and still want to allow for sizeable chunks of data with your web applications? Huh? Huh?! See the possibilities? Try our proof of concept wls_vs_php.html Capital City Find Matching Country Report live run, and highlight a whole swathe of (multiple mode) dropdown option Capital Cities holding down the shift key before pressing the yellow “Report” button. If the URL ends up as …

https://rjmprogramming.com.au/HTMLCSS/wls_vs_php.html?capitals=localStorage&countries=localStorage

that’s because the web application’s …


function analyze() {
var purl=document.URL.split('#')[0].split('?')[0] + '?capitals=' + encodeURIComponent(document.getElementById('capitals').value) + '&countries=' + encodeURIComponent(document.getElementById('countries').value);
if (purl.length > 800) {
if (phpexists) {
document.getElementById('myform').method='POST';
document.getElementById('myform').action='./wls_vs_php.php';
} else if (window.localStorage) {
localStorage.setItem('wls_vs_php_countries', encodeURIComponent(document.getElementById('countries').value));
localStorage.setItem('wls_vs_php_capitals', encodeURIComponent(document.getElementById('capitals').value));
document.getElementById('capitals').value='localStorage';
document.getElementById('countries').value='localStorage';
location.href=document.URL.split('#')[0].split('?')[0] + '?capitals=' + encodeURIComponent(document.getElementById('capitals').value) + '&countries=' + encodeURIComponent(document.getElementById('countries').value);

return false;
}
}
return true;
}

… HTML form onsubmit event logic …

  1. discovered no PHP web application existant (via Client Pre-emptive Iframe techniques) … and …
  2. discovered (in a sanity check feeling way) that to go down the proposed HTML form method=GET approach was risking a …

    HTTP 414 "Request URI too long"

    … web browser error … and that …
  3. localStorage was a known web browser piece of functionality
  4. … and so as per our localStorage logic we …

  5. back out of the default HTML form method=GET navigation setup of the web application in favour of …
    • storing that data into localStorage
    • substituting into the URL ? and & arguments the hardcoding “localStorage” (and in so doing, getting back under the HTTP 414 “Request URI too long” limitation, piecing together (what amounts to) …
      location.href=document.URL.split(‘#’)[0].split(‘?’)[0] + ‘?capitals=localStorage&countries=localStorage’;)
      … that on a recall to this same web application a …
    • document.body onload event piece of Javascript logic checks the localStorage for its incoming Capital City Country Report data, as per …

      var phpexists=false;
      var getcapitals=location.search.split('capitals=')[1] ? decodeURIComponent(location.search.split('capitals=')[1].split('&')[0]).replace(/\+/g,' ') : '';
      var getcountries=location.search.split('countries=')[1] ? decodeURIComponent(location.search.split('countries=')[1].split('&')[0]).replace(/\+/g,' ') : '';

      function checkforreport() {
      var divcont='';
      var dcaps, dctys, idis;
      if (getcapitals == 'localStorage') {
      if (window.localStorage) {
      getcapitals=decodeURIComponent(localStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
      localStorage.removeItem('wls_vs_php_capitals');
      } else {
      getcapitals='';
      }
      }
      if (getcountries == 'localStorage') {
      if (window.localStorage) {
      getcountries=decodeURIComponent(localStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
      if (getcapitals.replace('localStorage','') != '' && getcountries.replace('localStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
      localStorage.removeItem('wls_vs_php_countries');
      } else {
      getcountries='';
      }
      }

      if (getcapitals != '' && getcountries != '') {
      divcont='<table border=5 style="width:95%;vertical-align:top;background-color:white;"><tr style=background-color:#f0f0f0;"><th>Capital</th><th>Country</th></tr></table>';
      dcaps=getcapitals.split('|');
      dctys=getcountries.split('|');
      for (idis=0; idis<dcaps.length; idis++) {
      divcont=divcont.replace('</table>', '<tr><td>' + dcaps[idis] + '</td><td>' + dctys[idis] + '</td></tr></table>');
      }
      document.getElementById('dreport').innerHTML=divcont;
      }
      }

      … the localStorage.removeItem() representing that “self-destruct” nuance we were talking about before

We may well use this methodology in future projects, and hope it has been of some little interest to you as well?!

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

Country Quizzes Beep Tutorial

Country Quizzes Beep Tutorial

Country Quizzes Beep Tutorial

One of the great things about …

  • peer to peer thinking … grouping …
  • web applications into a suite of software … to form a more powerful “tool” … is that it …
  • lends itself to thinking, as far as logic goes, to either/both …
    1. external Javascript … on the clientside … and perhaps …
    2. include/require serverside (eg. PHP) thinking … and so it is the case that the good thing …

… is that all this infers “modularization” … an aspirational word for us, creating “order” in the minds of those “who don’t mind mess” … cough, cough.

And so, further to the “beep logic” of yesterday’s Google Chart Geo Chart Quiz Beep Tutorial we’re happy regarding the order of play here, because …

  • yesterday’s Google Chart Geo Chart Quiz Beep Tutorial scenario(s) had aspects crueling many thoughts regarding “genericization” because of that delay needed to set up any new quiz question (the situation regarding would be too different for every scenario, whereas today’s “peer to peer” target had a “score paradigm” where there was potential for genericization in a useful external Javascript scenario) … and yet …
  • taught us lots about “beep logic”

… and that, along with the recent “peer to peer” ideas of PHP Intl Class Peer To Peer Locale Variants World Map Tutorial meant that a revisit of the Country Quiz “peer to peer” web applications of Country Quizzes Mobile Makeover Tutorial, below, led us to think …

Could we develop a beep.js … could we?

… whose influence is …

  • optional
  • improving the user experience … for some (hence the “optional” here)
  • encourage user interactivity

Would we?

Codewise …

Did you know?

A consideration in external Javascript development is, if a user on another domain, puts into their “head” (element code)


<script type="text/javascript" src="//www.rjmprogramming.com.au/beep.js" defer></script>

… does it have a chance of success, and being a tool outside the domain it was written on? Or was it too specific to be of use in that way, having a set of assumptions only, in our case, apply to the RJM Programming domain scenarios? Well, of course, our aim is the former, and any feedback, any which way on this, is available through this blog’s comment facilities.


Previous relevant Country Quizzes Mobile Makeover Tutorial is shown below.

Country Quizzes Mobile Makeover Tutorial

Country Quizzes Mobile Makeover Tutorial

It’s interesting, when making a web application like the Country Quiz ones of yesterday’s Country Quizzes Makeover Tutorial how when making it better for mobile platforms, with their smaller device widths, you often end up wanting to increase font sizes. Go Figure!

Well, we figure … personally … it revolves around how the mobile platform keyboards take up about a third of a iPhone sized device screen.

You can fight it, or get flexible, and we’ve decided on the latter, and taken inspiration from this scene of Hitch … keep it small, keep it simple, and don’t think you can just programmatically scroll everywhere you might want to on any given webpage using mobile platforms.

And this thought pattern set us at our ease. Why have we fought these fundamentals, so often in the past? It pans out, due to keyboard usage, the crux of the quizzes in “mobile land” can be traced down to a very small area of the “starting out” onload event screen content, and we just need to enhance what is shown in that area which is the “tweeners area” in among where …

  • table header cells “th” (2x) meet … and also meet …
  • top part of where table data cells “td” (2x) meet

… because of that zooming in to focussed input type=text textboxes that goes on with mobile platforms. And in this scenario …


<table>
<tr><th>Country</th><th>X[Modes of Use Dropdown]</th></tr>
<tr><td>[Country Dropdown]</td><td>[Text Box]</td></tr>
</table>

X marks the spot where the score and wrong answer explanations could be temporarily (for 20 seconds at a time) copied to, to allow the most important information to the user regarding the quiz be “above the fold” for the user, perhaps doing away with any need for the mobile user to scroll anywhere, for the running of their basic quiz incarnation. This “zooming” replaces the need, we are often feeling, on mobile platforms, for larger font size usage.

Take a look at our external Javascript function to cover the checking of answers made at the Country Currency Quiz, and map into your mind X with <span id=container style=font-size:8px;></span> as you analyze


function currencycheck(inv) {
if (inv.value != '') {
var suffix='';
goes++;
if (ourcomp(inv.value,document.getElementById('country').value)) {
score++;
} else if (document.getElementById(countryids[choice]).outerHTML.indexOf('<p') == 0 || document.getElementById(countryids[choice]).outerHTML.indexOf('<span') == 0) {
suffix=' The country ' + document.getElementById(countryids[choice]).id.replace(/_/g,' ') + ' (' + countrycodes[choice] + ') <BR>represented by <span>' + document.getElementById(countryids[choice]).innerHTML + '</span> <BR>has the currency ' + document.getElementById(countryids[choice]).title;
} else {
suffix=' The country ' + document.getElementById(countryids[choice]).id.replace(/_/g,' ') + ' (' + countrycodes[choice] + ') <BR>represented by <img src=' + document.getElementById(countryids[choice]).src + '></img> <BR>has the currency ' + document.getElementById(countryids[choice]).title;
}
if (document.getElementById('ssuffix')) {
document.gteElementById('ssuffix').innerHTML=suffix; suffix='';
}
document.getElementById('score').innerHTML='Score: ' + score + ' Goes: ' + goes + suffix; choose();
if (suffix != '' && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//document.body.style.zoom='1';
//window.scrollTo(0,0);
if (document.getElementById('container')) {
document.getElementById('country').scrollIntoView();
if (document.getElementById('ssuffix')) {
document.getElementById('container').innerHTML=(document.getElementById('score').innerHTML + '&nbsp;&nbsp;').replace('The country ', '<br>The country ').replace('has the currency ', 'has the currency <br>');
} else {
document.getElementById('container').innerHTML=(document.getElementById('score').innerHTML + '&nbsp;&nbsp;').replace('The country ', '<br>The country ').replace('has the currency ', 'has the currency <br>');
}
if (document.getElementById('thleft')) {
document.getElementById('thleft').scrollIntoView();
} else {
document.getElementById('container').scrollIntoView();
}
setTimeout(nocontainer, 20000);
} else {
document.getElementById('myh1').scrollIntoView();
}
}

}
}

function nocontainer() {
document.getElementById('container').innerHTML='';
}

Again, with this “peer to peer” web application suite they share the use of …


Previous relevant Country Quizzes Makeover Tutorial is shown below.

Country Quizzes Makeover Tutorial

Country Quizzes Makeover Tutorial

It’s been more than a year since a visit to the Country Quiz web applications of Country Quizzes Wikipedia Image Integration Tutorial, involving “the we are fam-il-y” style

  • Country Capitals Quiz
  • Country Currency Quiz
  • Country Flags Quiz

… and some of us agree that it can be the sure case that

moss grows fat on a rolling stone

… and so, we’re back!

Since then, on a revisit, we thought the optional quiz “informing options” could be expanded upon from the existant …

  • YouTube Video
  • Wikipedia Images … to also include, as of today …
  • GeoJson World Map
  • TimeZone Places … and …
  • Google Image Chart Map Chart

Data wise we started collecting Country ISO-3166 2 character Codes …

<?php

$foundcc=''; // global

// later used ...

$postbits=explode("<", str_replace('<span>','',str_replace('</span>','',$ctysarr[$ihj])));
if (yourflag($postbits[0]) != '') {
// blah blah ...
$scriptis=str_replace("</scr" . "ipt>", " countries.push(\"" . str_replace("_", " ", $postbits[0]) . "\"); countryids.push(\"" . $idis . "\"); countryccs.push(\"" . $foundcc . "\"); num++; \n</scr" . "ipt>", $scriptis);
// blah blah ...
}

function yourflag($incn) {
global $iso_country_codes, $foundcc;
for ($jk=1; $jk<sizeof($iso_country_codes); $jk+=2) {
if (strtoupper($iso_country_codes[$jk]) == strtoupper($incn)) {
$foundcc=strtoupper($iso_country_codes[-1 + $jk]);
return orflag(strtoupper($iso_country_codes[-1 + $jk]));
}
}
return '';
}

function orflag($incc) {
global $foundcc;
$uretv='';
$lri=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
$dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];
for ($jjm=0; $jjm<strlen($incc); $jjm++) {
for ($jm=0; $jm<sizeof($lri); $jm++) {
if (strtoupper(substr(substr($incc,$jjm),0,1)) == $lri[$jm]) {
$uretv.='&#' . $dri[$jm] . ";";
$foundcc=$incc;
}
}
}
return $uretv;
}


?>

… and found this to be a wise move, not just to do with linking to some of these new “informational helpers” above, but also with ideas into the future, we reckon, the main reason being that you can rely on the ISO-3166 2 character codes, while there are a wide and varied set of Country Names out there.

With this “peer to peer” web application suite they share the use of …


Previous relevant Country Quizzes Wikipedia Image Integration Tutorial is shown below.

Country Quizzes Wikipedia Image Integration Tutorial

Country Quizzes Wikipedia Image Integration Tutorial

We wanted to offer some optional Wikipedia Image lookup functionality as an alternative to the optional existent YouTube Video lookup functionality in the …

… peer to peer linked (via dropdown selection) web applications we’ve talked about in the past with Country via Capital Placeholder Quiz Game Tutorial.

Before this idea came to us, the way functionality was optional led us to use an input type=checkbox to represent this idea. Even with the new Wikipedia Image choice, to us, this does not change, as it’s optional.

But the choice between the two optionals is a choice, and so … we have to choose among …

… usage for this second-tier user choice. Well, the checkbox buttons are definitely inferior to the others in that we only want to present one optional lookup type of content, as well as the awkwardness of two checkboxes, horizontally, in a row, presentation and UX-wise. Now that leaves dropdowns versus radio buttons. Most of the time we prefer the former by a long way, but because there are only two choices and we’d prefer a horizontal display that is “all seen” (even on mobile), today, we’ve plumped for radio buttons, but not used, perhaps, the way you might be more familiar with, within a form and using a shared name attribute passed along with a value through to the “called”. No, we use the onclick event of each radio button to glean the choice without any HTML form help. See relevant changed code from the peer to peer shared and modified country_quiz.js external Javascript …

<script type=’text/javascript’>

function check(inv) {
var ourcis="";
if (inv.value != "") {
if (document.URL.indexOf('_flag_') != -1) {
if (document.getElementById('fav_opt').value == 'wi') {
ourcis="//www.rjmprogramming.com.au/PHP/fgc/?tzexact=" + encodeURIComponent(document.getElementById(countryids[choice]).title.replace(/\ /g,'_')) + "&tznickname=" + encodeURIComponent(document.getElementById(countryids[choice]).title.replace(/\ /g,'_'));
} else {

ourcis="//www.rjmprogramming.com.au/HTMLCSS/karaoke_youtube_api.htm?emoji=on&nokaraoke=y&youtubeid=" + encodeURIComponent(" flag of " + document.getElementById(countryids[choice]).title);
}
flagcheck(inv);
} else if (document.URL.indexOf('_capital_') != -1) {
if (document.getElementById('fav_opt').value == 'wi') {
ourcis="//www.rjmprogramming.com.au/PHP/fgc/?tzexact=" + encodeURIComponent(document.getElementById(countryids[choice]).id.replace(/\ /g,'_')) + "&tznickname=" + encodeURIComponent(document.getElementById(countryids[choice]).id.replace(/\ /g,'_'));
} else {

ourcis="//www.rjmprogramming.com.au/HTMLCSS/karaoke_youtube_api.htm?emoji=on&nokaraoke=y&youtubeid=" + encodeURIComponent(" capital of " + document.getElementById(countryids[choice]).id.replace(/_/g,' '));
}
capitalcheck(inv);
} else if (document.URL.indexOf('_currency_') != -1) {
if (document.getElementById('fav_opt').value == 'wi') {
ourcis="//www.rjmprogramming.com.au/PHP/fgc/?tzexact=" + encodeURIComponent(document.getElementById(countryids[choice]).id.replace(/\ /g,'_')) + "&tznickname=" + encodeURIComponent(document.getElementById(countryids[choice]).id.replace(/\ /g,'_'));
} else {

ourcis="//www.rjmprogramming.com.au/HTMLCSS/karaoke_youtube_api.htm?emoji=on&nokaraoke=y&youtubeid=" + encodeURIComponent(" currency of " + document.getElementById(countryids[choice]).id.replace(/_/g,' '));
}
currencycheck(inv);
}
if (trjm != null) {
document.getElementById('iback').src=ourcis;
document.getElementById('iback').style.display='block';
}
}
}

function ronclk(cv) {
var wasv=document.getElementById('fav_opt').value;
if (wasv == 'yv' && cv != 'yv') {
document.getElementById('fav_opt').value='wi';
} else if (wasv == 'wi' && cv != 'wi') {
document.getElementById('fav_opt').value='yv';
}
}


function andquizthen() {
// xpreandquizthen();
if (trjm == null) {
trjm=document.getElementsByTagName('h3')[0];
if (trjm != null) {
trjm.innerHTML+=' <input onchange=" if (trjm == null) { trjm=this; } else { trjm=null; } ifon(); " type="checkbox" name="youtube" id="youtube" value="Optional YouTube Video lookups" checked>Optional <input type=hidden id=fav_opt value=yv></input><input onclick=ronclk("yv"); type="radio" id="yv" name="fav_opt" value="YouTube Video" checked><label for="yv">YouTube <font size=1>Video</font></label><!--br--><input onclick=ronclk("wi"); type="radio" id="wi" name="fav_opt" value="Wikipedia Images"><label for="wi">Wikipedia <font size=1>Images</font></label>';
document.body.innerHTML+="<div id=ourcanvas><iframe id='iback' style='height:700px;width:100%;display:none;background-color:transparent;border:7px solid lightblue;' src='//www.rjmprogramming.com.au'></iframe></div><div id=dstyle style=display:none;></div><div id=stz style=display:none;></div><input id=addthis type=hidden value=''></input>";
choose();
}
}
}

</script>


Previous relevant Country via Capital Placeholder Quiz Game Tutorial is shown below.

Country via Capital Placeholder Quiz Game Tutorial

Country via Capital Placeholder Quiz Game Tutorial

Our latest favourite HTML styling feature is the HTML placeholder attribute. We like its …

  • ability to be a replacement for a label or caption, especially when designing an HTML form, and hence, saving space
  • similar ability to be able to direct a user via a default suggestion
  • use that we apply with it today, is to dynamically reveal an input type=text box value, and gradually, with an effect a bit like an HTML marquee element

… its transparency a great advantage that we are just starting out on a quest to realize how using it can help.

Today, we add a “Country via (a placeholder revealed) Capital” block of functionality onto what we’d already coded for when we presented Country Quiz Game Suite Google Geo Chart Javascript Tutorial.

There’s no rocket science here, and no need for anything new with content, just a rearrangement of display features, but we do quite like this slightly typewriterish effect that may remind you of when we presented HTML/Javascript Multiple Choice Quiz Reveal Tutorial. In practical terms, imagine (some of) the (relevant) innards of a Javascript function fit


var anal=0, capis='';
function fit() {
if (eval(-1 + anal) < capis.length) {
document.getElementById('icapital').placeholder+=capis.substring(anal,eval(1 + anal)).replace('_',' ');
anal++;
setTimeout(fit,1500);
}
}

If you want to try this new bit of functionality, try this live run with underlying PHP country_capital_quiz.php code that changed in this way.


Previous relevant Country Quiz Game Suite Google Geo Chart Javascript Tutorial is shown below.

Country Quiz Game Suite Google Geo Chart Javascript Tutorial

Country Quiz Game Suite Google Geo Chart Javascript Tutorial

Our blog posting titles lately (most recently Country Quiz Game Suite Google Geo Chart Post Tutorial) have used the word “suite” for describing some “peer to peer” web applications that can navigate from one to the other with our Country Quiz game regarding …

  • Capitals
  • Flags
  • Currencies

… and we used that first “Capitals” web application of the “suite” (as the guinea pig) to iron out issues related to our additional contextual Google Chart Geo Chart HTML iframe “helper”. We had it in our mind, in order of preference, we’d like to present this last “bringing it all together” blog posting showing the whole “suite” with this new functionality, that we would …

  • change the common country_quiz.js featuring these changes external Javascript that is shared throughout the suite of web applications, taking what was involved with changes to country_capital_quiz.php as the basis for this (to the point where country_capital_quiz.php could look “pared back” almost to the way it looked a long time ago) … or …
  • for each of the other two web applications piece equivalent bits of code into those two country_flag_quiz.php and country_currency_quiz.php to make them work along with the original country_capital_quiz.php

Alas, trying that first option, we believe we ran into timing issues related to when the external Javascript is “pulled in” and we couldn’t get that method to work, and so … boo, hoo … we settled for the second solution. Not bad, but not as aesthetically pleasing or generic as the way some generic external Javascript could be modelled to do, like, 95% of what is needed to make that Google Chart Geo Chart functionality work. Anyway, we may end up revisiting that external Javascript which has the intended code (but prefixed by an “x” and/or commented out) still there for a future “Eureka” moment, we’re hoping. Perhaps it relates to the defer method of calling this external Javascript.

So, less generic, but instructive, in any case, crystallizing commonalities (or not … eg. the flags web application should not have an active onchange event Geo Chart bit of logic attached) and so that leaves us with our changed country_capital_quiz.php Capitals (Quiz) “guinea pig” (with this live run link, featuring these changes inspired by making …

… fit into this similar “suite” mode of thinking regarding Country Quiz additional (contextual) Google Chart Geo Chart functionality.

Recapping (why we’ve been referring to “suite”), these “peer to peer” web applications navigate to each other by the changing value to an HTML select element “dropdown” (and kicking off the onchange event navigation logic) the look of which, they all share.


Previous relevant Country Quiz Game Suite Google Geo Chart Post Tutorial is shown below.

Country Quiz Game Suite Google Geo Chart Post Tutorial

Country Quiz Game Suite Google Geo Chart Post Tutorial

If you read yesterday’s Country Quiz Game Suite Google Geo Chart Tutorial as shown below, why, right there and then, didn’t we apply these changes (to the “Capital” web application) onto the whole suite of Country Quizzes, those being …

  • Capital
  • Flag
  • Currency

? Well, there’s another matter to attend to. What do you think would happen if you quizzed away for, say, ten minutes? We think our additional Google Chart Geo Chart bit would “fall over” … that’s what programmer’s say when there is a weakness (and/or a bug) to do with “not catering for” untoward scenarios. The reason it would “fall over”, we believe, is that, eventually, the number of countries you string along adding to the length of the URL you push into that Google Chart Geo Chart’s HTML iframe element would push it over the length limit for (form method=) “GET” URLs, and then this, albeit optional, functionality would become unstable. Even though the functionality is optional, if you keep ignoring such issues at the sidelines of your plans, you are likely to get lazy and produce results that disappoint your more adventurous users.

So here is what we are going to do. You see how we said ‘(form method=) “GET” URLs’ above?

  1. we don’t have an HTML form … but you could … and to simulate the stringing together of a URL and placing it, Javascript DOM-wise, into the src property of the HTML iframe, is to have an HTML form with input elements whose name properties point at the ?/&[name]=[value] and value properties … doh … point at ?/&[name]=[value] and have a method=”GET” action=http://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php target=[nameOfRelevantIframe] … or …
  2. do everything the same as above except that method=”POST” and in this way there are much less stringent data length restrictions … you’ll be quizzing until dinner time … hey, why aren’t you making dinner?!

We’re going to go from the stringing a URL together to passing that “stringed together URL” as a parameter into a pretty generic Javascript function as per …


function checkforpost(insg, owhere) {
var outs=insg, fbits='<form style=display:none; target=\"myipost\" method=\"POST\" action=\"http://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php\"><input type=submit id=myspost value=Submit></input><input name=wellinever value=y type=hidden></input></form>';
if (insg.length > 950) {
var outarr=insg.split('#')[0].split('?');
if (outarr.length > 1) {
var outarrtwo=outarr[1].split('&'), oath;
for (var im=0; im<outarrtwo.length; im++) {
oath=outarrtwo[im].split('=');
fbits=fbits.replace('</form>','<input type=hidden name=' + oath[0] + ' value=\"' + (oath[1]) + '\"></input></form>');
}
}
if (owhere == null) {
owhere=document.getElementById('mydpost');
if (owhere == null) {
if (document.getElementById('mydpost')) {
document.getElementById('mydpost').innerHTML=fbits;
setTimeout(andlater,1500);
outs=\"#\";
} else {
document.body.innerHTML+='<div id=mydpost>' + fbits + '</div>';
setTimeout(andlater,1500);
outs=\"#\";
}
} else {
owhere.innerHTML=fbits;
setTimeout(andlater,1500);
outs=\"#\";
}
} else {
owhere.innerHTML=fbits;
setTimeout(andlater,1500);
outs=\"#\";
}
}
return outs;
}
function andlater() {
document.getElementById('myspost').click();
}

… to cater for lots of quizzing.

And so that leaves us with our changed country_capital_quiz.php (with this live run link), featuring these changes.


Previous relevant Country Quiz Game Suite Google Geo Chart Tutorial is shown below.

Country Quiz Game Suite Google Geo Chart Tutorial

Country Quiz Game Suite Google Geo Chart Tutorial

We think there are several interesting thing about Charts …

  • they are a way to visualise mathematical ideas, which is not always easy
  • they interface really well with spreadsheets
  • in the case of Google Charts, especially with their Geo Chart and Map Chart, there is a great link to geography
  • they can simplify complex data
  • they can put trends into an easily digestible graphical form
  • they can show the distribution of data

… and we want to use that third point above today to make use of the brilliant Google Chart Geo Chart to add context to our Flags and Currency and Capital Country Quiz game we created when we last presented Country Quiz Game Suite Google Geo Chart Tutorial, as shown below.

The point here is that many of us struggle to locate all the countries of the world you can think of, but isn’t it of interest for us all to get better at this, if the dream of the Internet as the “Superhighway” of Knowledge and Information can improve as a force for good. Can we all get back that idea from those earlier times, and get back to tackling problems in an International framework, where every good idea has a chance to be expressed, and heard?

Anyway, that last change to Geo Chart interfacing got us to this point where we can highlight one or several countries (or regions), and not display that (default) legend, as we set up when we presented Country Quiz Game Suite Google Geo Chart Tutorial. We’ll buy into that today with our changed country_capital_quiz.php (with this live run link), featuring these changes.


Previous relevant Country Quiz Game Suite Google Geo Chart Tutorial is shown below.

Country Quiz Game Suite YouTube Tutorial

Country Quiz Game Suite YouTube Tutorial

Today we are adding optional functionality to our previous web application from Country Quiz Game Suite Tutorial as shown below, and so it seems apt that we add one word for the title of today’s tutorial called “Country Quiz Game Suite YouTube Tutorial”, and that added word is “YouTube”, the biggest repository of videos in the online world.

So we are trying to spice up the “dry” look of the “Country Quiz Game Suite” of web applications by adding optional lookups of YouTube so that the user can choose to watch a video about the last question that was asked about in the quiz. Is there a reason to use a “YouTube” search for this, rather than a search engine search? For us, yes, and this can be put down to the wonders of the YouTube API designed for embedding in HTML iframe elements, which you can read a thread of blog posts about from Karaoke via YouTube API in Iframe Email Tutorial down. This ability is a huge UX positive for use of these web applications, on mobile platforms in particular, because the YouTube video “interface” parts of the webpage can be placed on the webpage the user is currently using, rather than having to open any new windows, and have the user be in danger of “losing the plot”.

Added to that advantage is the way the user can do research and development on topics that may interest them. To us, the most important point here.

So far we’ve talked about what the changes involve, and now we’ll turn our attention to how these changes were achieved. In broad brush terms …

  • we introduce new external Javascript you could call country_quiz.js called by the parent …

    … using a call like …

  • <script type='text/javascript' src='country_quiz.js' defer='defer'></script>
  • the defer HTML script tag attribute used to delay its loading to the end of loading, and also placed so that …
  • the call of the external Javascript is placed after local Javascript script tag client logic, because …
  • we “overload” the local Javascript “function check()” with a version from the external Javascript country_quiz.js, and we’ve discussed this Javascript style of overloading, before, when we presented Javascript Function Overload Primer Tutorial (where we overloaded the “encodeURIComponent” method) … and in that …
  • external Javascript country_quiz.js “function check()” potentially loads YouTube API functionality to an HTML iframe element which was first created via …
  • a one off setTimeout piece of logic is called by the external Javascript country_quiz.js to …
    • append the HTML for that YouTube API HTML iframe “container” element to document.body
    • append to the first HTML h3 element an HTML input type=checkbox, initially checked, toggling the use of that option YouTube API (to HTML iframe element) functionality

    … this setTimeout methodology remaining as independent from any potential logic clashes with parent HTML Javascript onload event logic

    Nothing changes about the peer to peer nature of this “Country Quiz Game Suite” of web applications, so we encourage you to try any/all of them … let’s try … flags.


    Previous relevant Country Quiz Game Suite Tutorial is shown below.

    Country Quiz Game Suite Tutorial

    Country Quiz Game Suite Tutorial

    Think we may have done a (web application software) set before, but honestly cannot locate it, but in any case we are here today to tell you about one of the joys of server side programming, in our case PHP.

    That joy, for us, is when you get into a pattern of completely peer to peer software components, in our case PHP serverside web applications. What do we mean by peer to peer in the way we feel about the thought? It means that several, usually small, completely independent web applications can …

    • as such, be easily unit tested within themselves … but …
    • they each have a similar, and really easy, approach to, just right at the end of coding … ie. when they are all individually coded … link them to be pointable at each other “peer to peer” … guess the difference here, unlike our penchant for “parent/child” (which we are also very fond of), each web application component is independent and of “equal” status in our tiny little woooorrrrrrlllld!

    … and this really appeals to us. Sometimes such an arrangement can be thought of as a “suite” of web applications (or programs).

    So what is that really simple mechanism of linking …

    ? We just have a rearranged HTML select (dropdown) element as below (exemplified below for the “Country Capital Quiz”) …


    <select onchange=' location.href="http://www.rjmprogramming.com.au/PHP/country_" + this.value.toLowerCase() + "_quiz.php"; '><option value=Capital>Capital</option><option value=Currency>Currency</option><option value=Flag>Flag</option></select>

    … but just arrange for the “home” top HTML option element to point at the quiz theme of interest for that piece of web application PHP software.

    And the placement of such a dropdown? Well, we often annoy our HTML h1 elements with such dropdowns, but we’ve been a little more UXy today, by replacing an otherwise less dynamic (HTML (table) th element) heading (single word), with something dynamic, and perhaps useful, to some quizzer users out there in “net” land!

    And this is what we like to think of as “clobbering” (but we encourage you to think of a less aggressive word perhaps) something not very dynamic with something dynamic, but optionally so, in that it is up to the user whether they make use of the added functionality, or not, is another way “some of us we like to roll”.

    Now, perhaps you are thinking it rather cheeky to say that this is so peer to peer with the quiz concepts being so different, and yes, that is so, but what does bring things together is the generosity of the “net” and its data resources to find out information, so, we’d like to thank …

    • Country Flag Quiz … thanks to Tiki Wiki CMS … effectively giving up a country list to work with … and …
    • Country Currency Quiz … thanks to this link links countries to currencies (and (3 letter) country codes and (3 letter) currency codes) … and …
    • Country Capital Quiz … thanks to this link links countries to capitals

    If you don’t have an interest in a server side language like PHP to glean such information, please consider Ajax programming techniques to be able to (just) stick with HTML and Javascript and CSS (client side) coding. But if you do … your PHP homework for today is to read about the file_get_contents method.


    Previous relevant Country Flag Quiz Game Primer Tutorial is shown below.

    Country Flag Quiz Game Primer Tutorial

    Country Flag Quiz Game Primer Tutorial

    Often, the simpler you make the working of a web application, the more appealing it is. Not always, but often. Lots of us like to test our knowledge with a quiz, and lots of us have our specialty subjects. So, today’s “Country Flag Quiz” web application, that we also talk about at WordPress 4.1.1’s Country Flag Quiz Game Primer Tutorial, will be right up the alley of some people. Got to say that it felt like a huge challenge to get a decent score in this game, speaking personally, and found myself resorting to … but we digress … to come up with a pass mark for the game.

    Today’s game we wrote in PHP (that you could call country_flag_quiz.php and which you can try with today’s live run link) and used its Supercalifragilisticexpialidocious glob method … we’ve spoken about (quite a bit) here.

    We need to thank the excellent Tiki Wiki CMS product (which you can try for yourself at this test website) for the help with the country flag imagery, as well, today.

    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

Google Chart Geo Chart Quiz Beep Tutorial

Google Chart Geo Chart Quiz Beep Tutorial

Google Chart Geo Chart Quiz Beep Tutorial

We’ve long had on our minds a wish to incorporate a beep sound into quiz scenarios, and we’re revisiting this, again, for us, trying to get this going using the Geographical Quiz featuring in Google Chart Image Chart Map Chart Quiz Tutorial.

Why we feel a beep would be good here is that a user can use the beep while multitasking, and be told when to focus back on the quiz, while doing other things, perhaps, and the beep patterns can tell them …

  1. whether they are correct
  2. when the next question’s left hand map hint has been loaded

… while they are doing those other things, perhaps.

A beep is no big deal, right?! No, it is not such a big deal on non-mobile, true, but on mobile, it is a nightmare! Because …

  1. ever since this web browser approach on mobile, of only allowing audio (and/or video) play operations off a real user click “origin”, the task for mere non-Spotify mortals (and even they click, really, at least once) is more tortuous … and less of a pain, but a tad annoying, is that …
  2. Safari (web browser) not playing audio/wav files, so we looked around and came upon this excellent link, thanks, to get an MP3 beep

… all hold us up.

To get a kludgy solution on mobile we opted to …

  • overlay a dropdown (select) element the user uses to answer (which we later improved by overlaying a new “Beep” checkbox initially hidden from view, which we’re calling “non kludgy”), in the quiz … with an …
  • audio element positioned so that …
    1. mobile user can’t help but see it … and …
    2. they choose whether or not to involve audio beeps by clicking the audio element at a time of their choosing, or not, knowing …

    … there are still ways to get to the underlayed dropdown to answer the quiz question …

    function overselceqwq() {
    if (document.getElementById('divselcq').innerHTML.indexOf('<audio') == -1) {
    //document.getElementById('divselcq').innerHTML+='1:' + navigator.userAgent + '<br>';
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i) && 1 == 1) {
    //document.getElementById('divselcq').innerHTML+='01:' + navigator.userAgent + '<br>';
    rectisa=document.getElementById('selceqwq').getBoundingClientRect();
    //document.getElementById('divselcq').innerHTML+='11:' + navigator.userAgent + '<br>';
    if (1 == 11) {
    document.getElementById('divselcq').innerHTML+='<audio id=aselwq style="visibility:' + hidden + ';opacity:0.4;z-index:876;position:absolute;top:' + eval(-95 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(0.55 * eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(0.10 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/mp3 onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); hidden=' + "'hidden'" + '; document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; document.getElementById(' + "'aselwq'" + ').style.visibility=' + "'hidden'" + '; },2000);" onmousedown="if (event.currentTarget == this) { this.muted=!this.muted; }" ontouchstart="if (event.currentTarget == this) { this.muted=!this.muted; }" onclick="if (event.currentTarget == this) { this.muted=!this.muted; setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; }, 2000); }" controls muted><source type=audio/mp3 src="/beep.mp3"></source></audio>';
    } else if (1 == 1) {
    setTimeout(function(){
    rectisa=document.getElementById('audios').getBoundingClientRect();
    document.getElementById('divselcq').innerHTML+='<audio id=aselwq style="visibility:' + hidden + ';opacity:0.4;z-index:876;position:absolute;top:' + eval(-20 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(10 + eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(1.0 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/mp3 onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); hidden=' + "'hidden'" + '; document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; document.getElementById(' + "'aselwq'" + ').style.visibility=' + "'hidden'" + '; },2000);" onmousedown="if (event.currentTarget == this) { this.muted=!this.muted; }" ontouchstart="if (event.currentTarget == this) { this.muted=!this.muted; }" onclick="if (event.currentTarget == this) { this.muted=!this.muted; setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); document.getElementById(' + "'audios'" + ').style.visibility=' + "'visible'" + '; document.getElementById(' + "'aselwq'" + ').style.display=' + "'none'" + '; }, 2000); }" controls muted><source type=audio/mp3 src="/beep.mp3"></source></audio>';
    }, 3000);
    } else {
    document.getElementById('divselcq').innerHTML+='<audio onload=this.muted(true); id=aselwq style="visibility:hidXden;opacity:0.2;z-index:876;position:absolute;top:' + eval(4 + eval('' + rectisa.top)) + ('px;left:' + eval(eval(0.80 * eval('' + rectisa.width)) + eval('' + rectisa.left))).replace('NaN','') + ('px;width:' + eval(0.10 * eval('' + rectisa.width))).replace('NaN','') + 'px;height:' + rectisa.height + 'px;' + '" type=audio/wav onplay="this.muted(false); setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); },2000);" onmousedown="this.muted(false);" ontouchdown="this.muted(false); " onclick="setTimeout(function(){ document.getElementById(' + "'selceqwq'" + ').click(); }, 2000);" controls><source type=audio/wav src="data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU="></source></audio>';
    }
    //document.getElementById('divselcq').innerHTML+='111:' + document.getElementById('aselwq').outerHTML.replace(/\</g,'<').replace(/\>/g,'>') + '<br>';
    //document.getElementById('divselcq').innerHTML+='<button id=bselwq style="background-color:transparent;z-index:1876;position:absolute;top:' + rectisa.top + 'px;left:' + rectisa.left + 'px;width:' + rectisa.width + 'px;height:' + rectisa.height + 'px;' + '" type=audio/wav onclick="beep(); document.getElementById(' + "'selceqwq'" + ').click();"></button>';
    }
    }
    }

    function mbeep() {
    if (useaudios) {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i)) {
    if (top.document.getElementById('aselwq')) {
    top.document.getElementById('aselwq').play();
    } else {
    //var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    var snd = new Audio("/beep.mp3"); // "data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    snd.play();
    setTimeout(beep, 5000);
    }
    }
    }
    }

    function beep() {
    if (useaudios) {
    if (top.document.getElementById('aselwq')) {
    top.document.getElementById('aselwq').play();
    } else {
    var snd = new Audio("/beep.mp3"); // "data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    snd.play();
    }
    }
    }

    function beeptwo() {
    beep();
    setTimeout(function(){
    beep();
    }, 100);
    }

    function beepthree() {
    beep();
    setTimeout(function(){
    beep();
    }, 100);
    setTimeout(function(){
    beep();
    }, 200);
    setTimeout(function(){
    beep();
    }, 300);
    }

    function beepDoubleThree() {
    beepthree();
    setTimeout(function(){
    beepthree()
    }, 500);
    }

Codewise …

… you might want to revisit, yourself!


Previous relevant Google Chart Image Chart Map Chart Quiz Tutorial is shown below.

Google Chart Image Chart Map Chart Quiz Tutorial

Google Chart Image Chart Map Chart Quiz Tutorial

There is an expression so apt for today’s situation. But we hate it, so … no … we’ll say instead …

Our fault mainly, not Google’s fault only

… regarding yesterday’s …

However, this last one both needs more “wading through data” and “consideration” because it seems to be at Google Charts that not even the national boundary is shown when this regional data is not recognized.

We discovered today, that fallback colours directed towards an overall country code at the end of the URL regional colour entry list, is the way around some of the issue, that some meaning now we can get a country boundary showing, but still, for some countries, Google Charts, with its Image Chart Map Chart, will not show regional boundaries as you might see defined at Wikipedia for some ISO 3166-2 regional codes they have recorded.

So, what’s that got to do with quizzes? Well, the quiz got us interested in these colour mappings, and discovering how those mappings worked led us to this discovery. We hope colour blind people don’t suffer because our Country Regional Quiz functionality could easily be called …

Name the Red Region Quiz

Yes, if the user chooses the new “Quiz” input submit button modus operandi we arrange …

  • to leave out any legends
  • randomly pick a region which is coloured red … and now blue represents unaccounted for country parts not assigned a region and green represents the rest of the world and the oceans are as they ever were … and …
  • after a while we ask the user for their guess as to what this red region’s name is

Good ol’ “colour coding”! What did we do when the world was not colourful? Oops … [expression we hate, again, fits here] … my mistake. We wouldn’t have been around. But we digress.

Simple premise, building on yesterday’s Google Chart Image Chart Map Chart Context Tutorial, but surprisingly involved in our changed third draft image_chart.php PHP web application for you to try, below, perhaps


Previous relevant Google Chart Image Chart Map Chart Context Tutorial is shown below.

Google Chart Image Chart Map Chart Context Tutorial

Google Chart Image Chart Map Chart Context Tutorial

Onto yesterday’s Google Chart Image Chart Map Chart Primer Tutorial start with Google Charts Image Chart Map Chart interfacing, today we’ve come at it from two subcategories relating to fallback positions and “context” …

  • add Geo Chart and Map Chart optionally viewed details/summary iframes showing country TimeZone position data
  • add a mechanism that if we can determine a country’s ideal range of latitude,longitude “box” view, as we found GADM could help us with, thanks, we can flag that

    $ourtzlist=" ...<option value=\"Asia/Shanghai\" title=\"17,82,55,133\" data-geo=\"31.23333,121.46666,CST,CN,+8\">Asia/Shanghai</option><option value=\"Asia/Singapore\" data-geo=\"1.28333,103.85,+08,SG,+8\">Asia/Singapore</option> ...";

    … in the data

However, this last one both needs more “wading through data” and “consideration” because it seems to be at Google Charts that not even the national boundary is shown when this regional data is not recognized.

The first one, though, is useful in our changed second draft image_chart.php PHP web application for you to try, below, perhaps


Previous relevant Google Chart Image Chart Map Chart Primer Tutorial is shown below.

Google Chart Image Chart Map Chart Primer Tutorial

Google Chart Image Chart Map Chart Primer Tutorial

We hope today’s work does not confuse terms, because we’re exploring a new area of Google Charts functionality today they refer to as …

  • Google Charts Image Charts … and you’ll see there lots of suboptions we’ll explain a bit more about later, and all this is separate functionality to …
  • Google Charts Map Chart … and …
  • Google Charts Geo Chart

… and, as of today, we interface to all three categories of Google Charts above, with three separate PHP web applications.

So, what’s the potential confusion? Well, we start out today interfacing to an Image Chart suboption called “Map Chart”, but not the one above, because its look is more in keeping with what the “Geo Chart” above achieves. We’ve written a web application, here, to show regional places within a country (via its 2 letter code) if this has been catered for by Google Charts, and for the most part, that is the case.

And so, on the same theme as yesterday’s Google Chart Geo Chart Zoom In Quiz Translate Tutorial, and thanks to Wikipedia for regional code lookups, we would welcome you to try out our “proof of concept” first draft image_chart.php PHP web application for you to try, below, perhaps …


Previous relevant Google Chart Geo Chart Zoom In Quiz Translate Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Translate Tutorial

Google Chart Geo Chart Zoom In Quiz Translate Tutorial

You could say the way we navigate to our recent …

World Quiz

… from our …

Geo Chart Interfacer

… in the web application as of yesterday’s Google Chart Geo Chart Zoom In Quiz Hints Tutorial was a bit cryptic, or convoluted, the way at a first prompt window we’d change an entry from the default My World Survey to My World Quiz or even to click that button that we’d arranged in this blog posting thread. Nevertheless, we were a bit loathe to change the arrangements, until we ran into problems involving today’s work of …

Adding a Google Translate layer on top of the World Quiz

… to facilitate some Internationalization (ie. language translation from English to non-English) into the mix. Yes, our PHP caused problems interfacing to Google Translate. So, what was our approach? We took a snapshot (ie. web browser View -> Page Source) at a point after the convolutions above, and worked off that to introduce a new code file member. Welcome …

… via our proof of concept geochart.html clientside only web application version (or the old access approach in all these changes to geo_chart.php PHP web application still works). Any downside doing this? A little, in that within a Google Translate “bubble” we could not work the Wikipedia images hint part of the logic. Also, you may run into problems with SVG image backgrounds using an svg+xml protocol, or we may just have been having a bad day?! So sad.


Previous relevant Google Chart Geo Chart Zoom In Quiz Hints Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Hints Tutorial

Google Chart Geo Chart Zoom In Quiz Hints Tutorial

Yesterday’s Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial showed us …

  • using a web inspector to dynamically change CSS styling in place preparatory to making a permanent change … well, today, we’re here to reiterate …
  • using a web inspector can help with a myriad of Javascript logic errors or debugging, as well

… and we do that today adding hints to all these changes to geo_chart.php Geo Chart interfacer at this live run World Quiz web application link or click a button down below.

Do the hints look familiar? Take a read of Javascript Lazy Evaluation Country Game Hints Tutorial and it all might come back to you!


Previous relevant Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial

Google Chart Geo Chart Zoom In Quiz Aesthetics Tutorial

We recently revisited the PHP web application we call …

Google Chart Geo Chart Zoom In Quiz

… last talked about at Google Chart Geo Chart Zoom In Quiz Sharing Tutorial, and noticed a bit of ugliness regarding its CSS styling, specifically related to the “too large” border-radius values we’d applied to the twin iframes cutting off wording in their bottom left corner.

This issue is an …

  • aesthetics, only …
  • CSS styling

… one … queue the Web Inspector! How come? Well, web inspectors, such as Google Chrome web browser’s one, allow you to …

  • in place … on our macOS MAMP local Apache/PHP/MySql web server system …
  • dynamically tweak …
  • CSS styling … especially good with inline CSS style syntax, that we happen to be very fond of too … so as to be able to …
  • make the changes for you to optionally re-tweak … ephemerally

… on a test system (ours being a macOS MAMP local Apache/PHP/MySql web server one) ahead of uploading and committing to a permanent change up at the live and public RJM Programming web server domain.

Take a look at how we went about what went into the aesthetically tweaked geo_chart.php Geo Chart interfacer at this live run link, where we remind you again, a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” in a new window or click a button down below.


Previous relevant Google Chart Geo Chart Zoom In Quiz Sharing Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Sharing Tutorial

Google Chart Geo Chart Zoom In Quiz Sharing Tutorial

Adding functionality to yesterday’s Google Chart Geo Chart Zoom In Quiz Tutorial we see an opportunity to …

  • add an element of “when” functionality onto the “where” strengths of the Google Chart Geo Chart recent work, via PHP TimeZones and interfacing to the work of the recent Looks Nice Nearby Speech to Text Game Video Tutorial … as well as …
  • means by which to share or collaborate with the “My World Zoom In Quiz” … via …
    1. email 📧 (via inline HTML PHP mail) … or …
    2. SMS 📟 (via “a” tag href=sms: link)

… and that last SMS methodology brought into focus our wish not to allow, yet, a URL approach to get directly to this new “My World Zoom In Quiz” (although we may change this strategy into the future). So, how to apply security over the use of a URL such as …

https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?wqperspective=Monday+10+Feb+2020+17:57:15.7182

… not linked, above, because there is no point. We have already clicked it in an SMS we got sent, and that nullifies its use from then on? Huh?! Yes, we use the PHP itself, as we are fond of doing, storing (a form of) that “Monday+10+Feb+2020+17:57:15.7182” away as a comment in amongst the PHP code and, hence, “file_get_contents” checkable by its or some other PHP code for its existence (as well as the “file_put_contents” based clean up removal of said comment after the SMSee’s (body) link is ever clicked), as the security check for whether we navigate to the “My World Zoom In Quiz” (bringing up that last correct answer) via an SMS body URL link, clicked by an SMSee. And that collaborator can do the same thing back to the original sender for the next wrong answer’s similar 📟 emoji button press instigation of this sharing and collaboration Javascript logic …


function smswho() {
if (smsorig == '') { smsorig=document.getElementById('smssend').href.split('0000')[0]; }
if (smsdateorig == '') { smsdateorig=document.getElementById('smsdate').value; }
var smsto=prompt('SMS to?', document.getElementById('smssend').href.split('sms:')[1].split('?')[0]);
if (smsto == null) { smsto = ''; }
if (smsto.trim() != '') {
document.getElementById('smsdate').value=smsdateorig + '.' + gsv.substring(0,1).charCodeAt(0) + gsv.substring(1).substring(0,1).charCodeAt(0);
document.getElementById('smsbut').click();
document.getElementById('smssend').href=(smsorig + '' + gsv.substring(0,1).charCodeAt(0) + gsv.substring(1).substring(0,1).charCodeAt(0)).replace('sms:?','sms:' + smsto + '?');
document.getElementById('smssend').click();
}
}


function emailwho() {
var emto=prompt('Email to?', document.getElementById('emailto').value);
if (emto == null) { emto = ''; }
if (emto.indexOf('@') != -1) {
document.getElementById('emailto').value=emto;
document.getElementById('hcont').value='<html><body><form action=' + document.URL + ' method=POST><input type=hidden value=' + gsv + ' name=wqperspective></input><input type=submit value=\"My World Zoom In Quiz\" style=\"background-color:yellow;\"></input></form></body></html>';
document.getElementById('iemail').click();
}
}

… in the context of all these changes to geo_chart.php Geo Chart interfacer at this live run link, where we remind you again, a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” in a new window.


Previous relevant Google Chart Geo Chart Zoom In Quiz Tutorial is shown below.

Google Chart Geo Chart Zoom In Quiz Tutorial

Google Chart Geo Chart Zoom In Quiz Tutorial

Today we’re combining …

… to create another form of quiz (we think of as “My World Zoom In Quiz”) the user can navigate to via the way they answer that first title prompt (substituting “Survey” with “Quiz”). You might prefer to think of it as the “Geographical Perspective Quiz” with a degree of difficulty, often, because to see a “Zoomed In” display of a country or region can be disorienting and challenging to recognize. And so, for incorrect dropdown answers, we provide a “zoomed out” world view of where that “zoomed in” view sits (like an inset).

In order to show you this below please click

Again, a bit of a different tack to yesterday with the reworked geo_chart.php Geo Chart interfacer at this live run link, where a substitution of “Survey” by “Quiz” at the first title prompt can show the “My World Zoom In Quiz” (like above) in a new window.


Previous relevant Google Chart Geo Chart Small Region Tutorial is shown below.

Google Chart Geo Chart Small Region Tutorial

Google Chart Geo Chart Small Region Tutorial

Meanwhile, resuming our dreams of Andorra, there must be hundreds of readers there a bit sick of us going on and on and on and on and on about our Google Chart Geo Chart interfacing Quizzes and the use of complex “width” (and “height”) prompt user interactions. After all, we came onto this topic more to do with “small countries”. Well, let’s go back to that and let’s say …

  • as well as the “markers” mode (geographicals) latitude and longitude (helped out by PHP TimeZone places) way of signifying the position of a small country on a world or continent map … always, there behind the scenes, set up ages ago, was the interfacing we had set up to …
  • connect with the Google Chart “smarts” regarding “region” mapping to be able to hone in on a “region” (which can mean a whole country too) of interest

… and that means, today, we revisit our imaginary jaunts in Andorra setting out from the big smoke of …


Andorra la Vella

… to the border tranquillity of …


Pas de la Casa

… in the scenario of today’s tutorial picture … honing in on the user interaction before the width one (yayyyyyy!) with that title prompt. At this prompt we make use of two extensions to default behaviour with our PHP web application, those being …

  1. prefix of “region code” + “;” ( in the case of Andorra an ISO 2 Character Country Code “AD” + “;” = porkAD; )
  2. suffix of “heads up” placename list (making it so you will probably not need to fish around for any latitude and longitude geographicals yourself) via &areplaces=[comma (and + if you want lines joining) separated placename list] … eg. &areplaces=Andorra la Vella,+Pas de la Casa

… to end up with a user title data item user interaction entry of …


AD;My World Survey&areplaces=Andorra la Vella,+Pas de la Casa

… as the lead in to “not much thinking” (and as long as you are not Pinocchio, “follow your nose” ease) required for the other non-quiz-based prompts (ie. no need for width or height mantissae …

… in this scenario).

Quite a bit of a different tack to yesterday’s Google Chart Geo Chart Quiz Tooltip Flag Tutorial that you can see how we needed to tweak geo_chart.php Geo Chart interfacer at this live run link, showing the versatility and usefulness of Google Chart Geo Charts.


Previous relevant Google Chart Geo Chart Quiz Tooltip Flag Tutorial is shown below.

Google Chart Geo Chart Quiz Tooltip Flag Tutorial

Google Chart Geo Chart Quiz Tooltip Flag Tutorial

Yesterday’s Google Chart Geo Chart Quiz on Mobile Tutorial‘s Google Chart Geo Chart interfacing uses …

  • onmouseover event tooltip functionality for non-mobile platforms … and, better something than nothing, we guess …
  • first onclick event tooltip functionality for mobile platforms

… a blessing, in our view, that an onmouseover (ie. on hover) piece of functionality thinking survives into the mobile platform wooooooooorrrrrlllddd in some way shape or form. We generally find tooltips an optimistic and useful webpage functionality tool.

And with this in mind, it was worth our mind’s attention to ask … “what about if the Geo Chart Quiz functionality can, optionally, help out the user a bit without giving the game away?” … in the sense that ISO 2 character country codes can be baffling, yet help to make the quiz a challenge, on occasions, though enough of a turn off for some users, we’re sure. But to place an Emoji Flag could be a feature some quizzers will like and appreciate.

Rather than add to the navigational data we’d rather “add” an Emoji Flag on being “flagged” (tee hee) to do so, that “flagging” being to add argument “&flag=y” into the mix, at the width value prompt, which is the same prompt whereby a user decides to create a quiz in the first place. And because Emojis represent text data (albeit multibyte ones) we won’t even need to change data structures, just data content involving the one string structure member of …


['Latitude','Longitude','Country','Countdown']

… which we’ve been sending as that country’s ISO 2 character code (to leave some challenge to the quizzer, where the user has been seeing that ISO code only “on hover” up to today) … but if the user has “flagged” &flag=y this code below swings into play appending text data onto that ISO Code text data (of PHP variable (and argument) “$instuff” below) via String.fromCodePoint() function, as per …

<?php

$lri=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
$dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];

function maybequizflag($instuff) {
global $GETdata, $iso_country_codes, $flagentity, $lri, $dri;
if (isset($_GET['quiz']) || isset($_POST['quiz'])) {
if (isset($_GET['flag']) || isset($_POST['flag'])) {
if (strpos($instuff, "['Lat','Long',") !== false) {
return $instuff; //str_replace("'Country',", "'Country','Flag',", $instuff);
} else {
$outstuff=$instuff;
$cbits=explode("'", $instuff);
$outstuff=$cbits[0];
$uretv=" ' + '";
for ($iol=1; $iol<sizeof($cbits); $iol++) {
if (($iol % 2) == 1) {
if (strlen($cbits[$iol]) == 2) {
for ($jjm=0; $jjm<strlen($cbits[$iol]); $jjm++) {
for ($jm=0; $jm<sizeof($lri); $jm++) {
if (strtoupper(substr($cbits[$iol],$jjm,1)) == $lri[$jm]) {
$uretv=str_replace(" + '", " + String.fromCodePoint(" . $dri[$jm] . ") + '", $uretv); //uvaltosfcp($dri[$jm]);
}
}
}
$outstuff.="'" . $cbits[$iol] . $uretv;
$uretv="' + '";
} else {
$uretv=" ' + '";
for ($im=1; $im<sizeof($iso_country_codes); $im+=2) {
if ($uretv == " ' + '" && strpos(strtolower($iso_country_codes[$im]), strtolower(str_replace("%20"," ",str_replace("%E2%80%99","",str_replace("%2C",",",$cbits[$iol]))))) !== false) {
for ($jjm=0; $jjm<strlen($iso_country_codes[-1 + $im]); $jjm++) {
for ($jm=0; $jm<sizeof($lri); $jm++) {
if (strtoupper(substr($iso_country_codes[-1 + $im],$jjm,1)) == $lri[$jm]) {
$uretv=str_replace(" + '", " + String.fromCodePoint(" . $dri[$jm] . ") + '", $uretv); //uvaltosfcp($dri[$jm]);
}
}
}
}
}
$outstuff.="'" . $cbits[$iol] . $uretv;
$uretv="' + '";
}
} else {
$outstuff.="'" . $cbits[$iol];
}
}
return $outstuff; //str_replace("',9", "','x',9", str_replace("',8", "','x',8", str_replace("',7", "','x',7", str_replace("',6", "','x',6", str_replace("',5", "','x',5", str_replace("',4", "','x',4", str_replace("',3", "','x',3", str_replace("',2", "','x',2", str_replace("',1", "','x',1", str_replace("',0", "','x',0", $instuff))))))))));
}
}
}
return $instuff;
}

?>

Again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Quiz on Mobile Tutorial is shown below.

Google Chart Geo Chart Quiz on Mobile Tutorial

Google Chart Geo Chart Quiz on Mobile Tutorial

We wanted to improve on the recent Google Chart Geo Chart More Quizzes Tutorial‘s “World Quiz” functionality approach of displaying window.open popups for mobile platforms. The reason for the concern on mobile platforms, and not such a concern on non-mobile platforms (though there is a concern about popup window web browser disabling settings), because the chance to “overlay” a popup window (via the use of a third argument to window.open calls) is ignored on mobile platforms, instead opening a new browser tab (at best). This can be disconcerting, akin to telling a room of students doing an important examination, to look out the window at an interesting magpie (warbling about Collingwood’s last triumph, no doubt).

Well, after extensive research, and first trying to position “anything new” down the bottom of the webpage we …

  • rejected idea of whole display of a relevant Wikipedia page content at the bottom (of a mobile user’s Geo Chart “quiz” webpage) … associated with a …
  • rejected “a” hashtag link down the bottom (but above proposed content above) to navigate back up to the quiz … to, instead …
  • start thinking that it is up to the mobile user to act themselves to ever navigate away from the quiz webpage, so, instead, initially condense the Wikipedia content down to an image that is …
    1. if HTTPS:// protocol being used, use the Google Page Insights screenshotting “smarts” you can see being used at PDF Slideshow and Form Creation Data URI Contents Tutorial
    2. if HTTP:// protocol being used, use the (thumbnail version of) the first image of the relevant Wikipedia webpage

    … encased by an “a” tag that the click of navigates the user to the relevant Wikipedia content in a new tab (at best), all positioned at the left hand side of the Geo Chart webpage’s H1 or H2 tag heading as a 70px width42px height thumbnail

The conduit here are Ajax Javascript techniques as per …


var myxhr = false;
var oursrc = '';
var woourl='';


function ajit(wourl) {
woourl=wourl;
var xurl = '';
if (document.URL.toLowerCase().indexOf('https') == 0) {
xurl='https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=' + encodeURIComponent(wourl) + '&screenshot=true';
} else {
xurl=document.URL.split('/GeoChart')[0] + '/fgc/?tdinto=&inurl=' + encodeURIComponent(wourl);
}
if (window.XMLHttpRequest) {
myxhr = new window.XMLHttpRequest;
}
else {
try {
myxhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (othermicrosoft) {
try {
myxhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (failed) {
myxhr = false;
}
}
}
if (myxhr) {
myxhr.onreadystatechange = backin;
myxhr.open('GET', xurl, true);
myxhr.send(null);
}
}


function backin() {
if (myxhr.readyState == 4) {
if (myxhr.status == 200) {
if (myxhr.responseText) {
var dbits = myxhr.responseText.split('\"data\":');
if (dbits.length > 1) {
oursrc='data:image/jpeg;base64,' + dbits[1].split('\"')[1].split('\"')[0].replace(/\_/g,'/').replace(/\-/g,'+');
ism='nm';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ism='';
document.getElementById(ism + 'dwoalttwo').style.position='absolute';
document.getElementById(ism + 'dwoalttwo').style.left='20px';
document.getElementById(ism + 'dwoalttwo').style.top='0px';
document.getElementById(ism + 'dwoalttwo').style.opacity='0.95';
document.getElementById(ism + 'dwoalttwo').style.zIndex='51';
} else {
document.getElementById(ism + 'dwoalt').innerHTML='<br><a id=btta href=#myh title=Top>Back to top</a>';
}
document.getElementById(ism + 'dwoalttwo').innerHTML='<a target=_blank id=adw title=Wikipedia style=z-index:52; href=' + woourl + '><img title=Wikipedia style=width:80px;z-index:52; src=' + oursrc + '></img></a>';
document.getElementById('myh').onclick=function() { document.getElementById('adw').click(); }
if (ism != '') { location.href='#btta'; }
} else if (myxhr.responseText.indexOf('<img') != -1) {
dbits = myxhr.responseText.split('<img');
dbits=dbits[1].split(' src=');
ism='nm';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ism='';
document.getElementById(ism + 'dwoalttwo').style.position='absolute';
document.getElementById(ism + 'dwoalttwo').style.left='20px';
document.getElementById(ism + 'dwoalttwo').style.top='0px';
document.getElementById(ism + 'dwoalttwo').style.opacity='0.95';
document.getElementById(ism + 'dwoalttwo').style.zIndex='51';
} else {
document.getElementById(ism + 'dwoalt').innerHTML='<br><a id=btta href=#myh title=Top>Back to top</a>';
}
document.getElementById(ism + 'dwoalttwo').innerHTML='<a target=_blank id=adw title=Wikipedia style=z-index:52; href=' + woourl + '><img title=Wikipedia style=width:80px;z-index:52; src=' + dbits[1].split(' ')[0].split('>')[0] + '></img></a>';
document.getElementById('myh').onclick=function() { document.getElementById('adw').click(); }
if (ism != '') { location.href='#btta'; }
}
}
}
}
}

… with the effect, for a mobile user, of not being interrupted from their quiz, unless this thumbnail (Wikipedia content) appears at the top left, that they can “long click” to open in a “New Tab” (or, perhaps, a “Split View”) as required, at least on the iPad we tried this with.

And so, you can try the changed geo_chart.php Geo Chart interfacer at this live run link, we hope representing an improvement for the Quizzing User Experience for our mobile user readers.


Previous relevant Google Chart Geo Chart More Quizzes Tutorial is shown below.

Google Chart Geo Chart More Quizzes Tutorial

Google Chart Geo Chart More Quizzes Tutorial

In allowing the World Quiz web applications of yesterday’s Google Chart Geo Chart World Quizzes Tutorial work accept more than about …

  • the 10 places (per continent Geo Chart) fitting into a $_GET arguments URL (of about 850 characters, for rjmprogramming.com.au domain) … the first cab off the rank allowing for …
  • a lot more than 10 can be accepted via $_POST in an HTML form method=POST action=./geo_chart.php

You may wonder why “first cab off the rank” here. Well, we’re not sure we won’t involve window.sessionStorage or window.localStorage in future plans. It being PHP we’re writing though, we will need a compelling reason to try this.

We allow you to ask the web application to try more places by (optionally) appending space characters onto the height values they enter.

You can try the changed (and note “function iftoobig()” in particular, here) geo_chart.php Geo Chart interfacer at this live run link, and try it with a few right space appended “heights” to try out this new functionality.


Previous relevant Google Chart Geo Chart World Quizzes Tutorial is shown below.

Google Chart Geo Chart World Quizzes Tutorial

Google Chart Geo Chart World Quizzes Tutorial

We’re heading towards “prove it for n” on top of the recent Google Chart Geo Chart Oceania Quiz Tutorial (“prove it for 2”) progress, making quizzes for …

  • Europe
  • South East Asia and Oceania
  • Africa
  • South America
  • North and Central America
  • Asia

… but feel we need more testing to bed it down, as far as reliability issues go, and we’ll keep you posted on that.

We found clutter issue with ISO 2 character Country Codes …

ISO Code 1 Country TZ Place 1 (Lat,Long) Too Close To Country TZ Place 2 (Lat,Long) ISO Code 2
VA Vatican City
(41.90222,
12.45305)
(-0.02,
+0.03)
Rome, Italy
(41.9,
12.48333)
IT
BJ Porto-Novo, Benin
(6.48333,
2.61666)
(-0.03,
+0.78)
Lagos, Nigeria
(6.45,
3.4)
NG

… and so “fashioned” this into a numerical basis for a “declutter” algorithm


function setsixteenquiz() {
var sixteen=16;
var allcontinents=['Europe','South East Asia and Oceania', 'Africa', 'South America', 'North and Central America', 'Asia'];
var thiscontinent=isquiz;
var cisq=-1;
var exclusions=',';
var sofarq=',-1,';
var ourselceqih=selceqih.replace(/\ data\-alt\-/g, ' data-');
if (thiscontinent == 'South East Asia and Oceania') {
sixteen=10;
} else if (thiscontinent == 'Africa') {
sixteen=17;
} else if (thiscontinent == 'South America') {
sixteen=10;
} else if (thiscontinent == 'North and Central America') {
sixteen=10;
}
for (var isqis=0; isqis<allcontinents.length; isqis++) {
if (allcontinents[isqis] != thiscontinent) {
while (ourselceqih.indexOf(' data-continent=\"' + allcontinents[isqis] + '\"') != -1) {
ourselceqih=ourselceqih.replace(' data-continent=\"' + allcontinents[isqis] + '\"','');
}
}
}
var sqws=ourselceqih.split(' data-continent=\"' + thiscontinent + '\" value=\"');
document.body.title='Awaiting quiz clickable circle symbols to score ...';
document.body.style.cursor=pcur;
if (document.getElementById('chart')) {
document.getElementById('chart').title='Awaiting quiz clickable circle symbols to score ... ';
document.getElementById('chart').style.cursor=pcur;
}
var latsofar=[], longsofar=[], thislats=0.0, thislongs=0.0;
var valid=true, ivalid=0, difflatlong=0.0;

while (quizisos.length < sixteen) {
cisq=-1;
while (sofarq.indexOf(',' + cisq + ',') != -1 || exclusions.indexOf(',' + cisq + ',') != -1) {
cisq=Math.floor(Math.random() * eval(-1 + sqws.length));
cisq++;
if (ourtzlist.indexOf(',' + sqws[cisq].split('\"')[0] + ',') != -1) {
thislats=(eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[0]));
thislongs=(eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]));
}

if (thiscontinent == 'South East Asia and Oceania') {
if (ourtzlist.indexOf(',' + sqws[cisq].split('\"')[0] + ',') != -1) {
if (eval(ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + sqws[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]) < 73.0) { // || eval(ourtzlist.split(',' + ourselceqih[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + ourselceqih[cisq].split('\"')[0] + ',')[0].split(' data-geo=\"').length)].split(',')[1]) >= 169.0) {
cisq=-1;
}
} else {
cisq=-1;
}
}
}
sofarq+='' + cisq + ',';
if (cisq != -1) {
if (sqws[cisq].split('\"')[0] == 'IT') { exclusions+='VA,'; } else if (sqws[cisq].split('\"')[0] == 'VA') { exclusions+='IT,'; }
if (sqws[cisq].split('\"')[0] == 'BJ') { exclusions+='NG,'; } else if (sqws[cisq].split('\"')[0] == 'NG') { exclusions+='BJ,'; }
difflatlong=0.0;
if (quizisos.length > 0) {
for (ivalid=0; ivalid<quizisos.length; ivalid++) {
difflatlong=Math.abs(eval('' + latsofar[ivalid]) - eval('' + thislats)) + Math.abs(eval('' + longsofar[ivalid]) - eval('' + thislongs));
}
}
if (difflatlong >= 2.0 || quizisos.length == 0) {
latsofar.push(thislats);
longsofar.push(thislongs);
quizisos.push(sqws[cisq].split('\"')[0]);
}

}
}
quizisos.push(\"\");
}

Here’s your chance to try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter Africa, South America, North and Central America and Asia Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Oceania Quiz Tutorial is shown below.

Google Chart Geo Chart Oceania Quiz Tutorial

Google Chart Geo Chart Oceania Quiz Tutorial

Regular readers will know about our penchant for “mathematical induction” theory, in the way you …

  • prove it for 1
  • prove it for 2
  • prove it for n

… and earlier this morning “too proud” moi thought we’d be at “n”, skipping “2” by now getting our Geo Chart interfacing new “Quiz” functionality to have covered user interactions for all the major continents of greater than 10 (of category) places, looking towards the “10 is a bit lame” thinking, to follow. Oh, well! But maybe that’s the point of the “2” in the “mathematical induction” proof “game”. A lot might be discovered, and so it was for us, trying to open the door to … come in …


South East Asia and Oceania ...

… spinner! In broad brush concepts, we discovered …

  • we needed to start to worry about places with an ISO 2 code but no TimeZone …
  • we needed to start to worry about places off to the left, right, and top limits of the Geo Chart limits we establish via those weird width and height values you enter … and on this am sure many will have tweaked that the value integer parts are like a “scalar” measure and the mantissae are a “left zero padded percentage offset into the entire Geo Chart on which to lob” measure
  • we needed to rearrange the scoring system’s denominator as a “seconds timer” rather than a “number of goes”
  • we needed to, at least at the start, mention name of Quiz
  • we needed to start closing previous Wikipedia windows on opening a new one, as applicable
  • we needed to start to worry about clutter (eg. Vatican City and Rome geographicals for two different countries)
  • we needed to start to worry about “skewed representations” (going back to Europe Quiz) whereby the first mention of a country ISO 2 Code within the TimeZone list is a position of a colony or dominion

… whereas we optimistically imagined all we might need to worry about was just …

  • converting (boolean binary decision) variable isquiz=false/true (Javascript code logic) into (string ternary and more decision) variable isquiz=”/’Europe’/’South East Asia and Oceania’ (with more to come … until “n” (for) nirvana) … and associated …
  • adding data-continent=”South East Asia and Oceania” global data attributes into dropdown id=’selceq’ linking ISO 2 codes with Country names
  • trying to add a bit of cursor=’progress’ flagging of web application “thinking time”

Never mind! And so, onto yesterday’s Google Chart Geo Chart Europe Quiz Tutorial progress there is not that much difference user interaction wise, just the offer of another weird “width” value choice (on which to blow your mind) but behind the scenes a “hard working mathematical induction middlemanperson” can now offer you the chance to try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter South East Asia and Oceania Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Europe Quiz Tutorial is shown below.

Google Chart Geo Chart Europe Quiz Tutorial

Google Chart Geo Chart Europe Quiz Tutorial

Up to yesterday’s Google Chart Geo Chart Sorted Small Countries Tutorial, as with interfacings to other Google Charts, we had a two phase aspect to the web application structures …

  1. ask for user interaction via the keyboard
  2. display the resultant Google Chart taking notice of that user interaction

… but today’s extension of Geo Chart interfacing functionality opens the door to the new

  • display the resultant Google Chart taking notice of that user interaction and allowing click/touch continuing interaction in the form of a quiz … first cab off the rank … Europe Quiz

The work recently has helped because …


function gck(igck) {
var ansis='';
if (document.getElementById('attachedImage' + ('' + igck).replace('-1',''))) {
var xxx=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).getAttribute('title');
if (xxx.indexOf('#') != -1) {
if (isquiz) {
maybe_bad=false;
if (xxx.split('#')[1].indexOf('/') != -1) {
ansis=xxx.split('#')[1].split('/')[eval(-1 + xxx.split('#')[1].split('/').length)].toLowerCase();
} else {
ansis=xxx.split('#')[1];
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(xxx.split('#')[1],'_blank', 'top=50,left=50,width=500,height=500');
} else if (xxx == '') {
if (isquiz) {
maybe_bad=false;
if (document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title.indexOf('/') != -1) {
ansis=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title.split('/')[eval(-1 + xxx.split('#')[1].split('/').length)].toLowerCase();
} else {
ansis=document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title;
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(document.getElementById('attachedImage' + ('' + igck).replace('-1','')).title,'_blank', 'top=50,left=50,width=500,height=500');
} else {
if (isquiz) {
maybe_bad=false;
if (xxx.indexOf('/') != -1) {
ansis=xxx.split('/')[eval(-1 + xxx.split('/').length)].toLowerCase();
} else {
ansis=xxx;
}
if (document.getElementById('sans').getAttribute('data-title').toLowerCase().replace(/\ /g,'_') == ansis.toLowerCase().replace(/\ /g,'_')) {
score++;
goes++;
} else {
goes++;
}
document.getElementById('sans').innerHTML='? ' + score + '/' + goes;
}

window.open(xxx,'_blank', 'top=50,left=50,width=500,height=500');
}
}
}

… is an onclick place we’ve set aside for our SVG intervention work. Keep it to no keyboard for this Europe Quiz, and we are happy (with this new idea, reminiscent of recent tweaking at Google Chart Annotated Timeline Whitespace Delimitation Tutorial).

So, again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link, and enter Europe Quiz territory by following pointers at the “width” interactive entry (Javascript) prompt window.


Previous relevant Google Chart Geo Chart Sorted Small Countries Tutorial is shown below.

Google Chart Geo Chart Sorted Small Countries Tutorial

Google Chart Geo Chart Sorted Small Countries Tutorial

Yesterday’s Google Chart Geo Chart Small Countries Overlay Tutorial‘s workings potentially using the geographicals (or marker) mode of use actually involve intervention logic within what Google provide SVG-wise for the Geo Chart content.

And so, for some time, the order in which we entered …

Country Surface Area (sq km)
Australia 7692024
New Zealand 269190
Andorra 468

… we entered, interactively by us, like, personally, like, in that order above, like. But for a day or two we were covering up a gap in the “wall of logic” plaster we had created for Google Chart select event logic (actually non-existant for the Geo Chart, but we code for onclick logic to navigate a user to a relevant Wikipedia page). The good news is we have fixed it now, not tying the user down to entering data in any particular order.

Fixed what, now? (I thought I heard you ask?!) Well, the alignment of &aregeographical= data to the symbology presented at the geographical positions on the Geo Map asks that the order we present corresponds to the relevant order of relevant Google SVG elements, and Google orders these from the largest numerical value down to the smallest, as you notice as far as Surface Area (sq km) suits an order of Australia, New Zealand, Andorra …

First non-overlay URL version goes https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-34.91667|138.58333|~Australia~,7692024]%20,%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
Second overlay URL version goes https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-34.91667|138.58333|~Australia~,7692024]%20,%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20&overlay=y&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
But the recent work means overlay URL version created interactively with order New Zealand, Andorra, Australia https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Surface%20Areas%20(sq%20km)&width=1112&height=694&country=Country&popularity=Surface%20Area%20(sq%20km)&data=%20[-36.86667|174.76666|~New%20Zealand~,269190]%20,%20[42.5|1.51666|~Andorra~,468]%20,%20[-34.91667|138.58333|~Australia~,7692024]%20&overlay=y&aregeographicals=http.Australia%2Chttp.New%20Zealand%2Chttp.Andorra
also works

… and the changes necessary to ensure this go


// var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;
function assess_small(indatar) {
var ipl=0, jpl=0, kpl=0, pushxx=[];
var outsuffix='';
var outdatar=indatar;
if (pushfrom.length > 0 && !oneisnotapplicable && oneistoosmall) {
for (jpl=0; jpl<pushfrom.length; jpl++) { // for (var ipl=0; ipl<pushfrom.length; ipl++) {
if (jpl == 0) {
var huhdatas=indatar.split('~');
for (var ihuhdatas=2; ihuhdatas<huhdatas.length; ihuhdatas+=2) {
if (huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0].replace('%20',' ').indexOf(' ') != -1) {
pushxx.push(('00000000000000000000000' + huhdatas[ihuhdatas].split(',')[1].split(']')[0]).slice(-22) + ' ... ' + huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0]);
}
pushxx.push(('00000000000000000000000' + huhdatas[ihuhdatas].split(',')[1].split(']')[0]).slice(-22) + ' ... ' + encodeURIComponent(huhdatas[eval(-1 + eval('' + ihuhdatas))].split('~')[0]));
}
pushxx.sort();
pushxx.reverse();
}
ipl=jpl;
for (kpl=0; kpl<pushfrom.length; kpl++) {
if (ipl == jpl && pushxx[jpl].split(' ... ')[1] == pushfrom[kpl].split('~')[1].split('~')[0]) {
ipl=kpl;
pushxx[jpl]=pushxx[jpl].split(' ... ')[0] + ' ... ';
}
}

if (outdatar.indexOf(pushfrom[ipl]) != -1) {
if (outsuffix == '') {
outsuffix='&aregeographicals=' + pushag[ipl];
} else {
outsuffix+='%2C' + pushag[ipl];
}
while (outdatar.indexOf(pushfrom[ipl]) != -1) {
outdatar=outdatar.replace(pushfrom[ipl], pushto[ipl]);
}
}
}
}


return outdatar + outsuffix;
}

Yet again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Small Countries Overlay Tutorial is shown below.

Google Chart Geo Chart Small Countries Overlay Tutorial

Google Chart Geo Chart Small Countries Overlay Tutorial

With “overlay” techniques available in life it might be tempting to say “never say never” because you don’t have to compromise a weak solution for a less weak solution. Yesterday’s Google Chart Geo Chart Small Countries Tutorial‘s Google Chart Geo Chart‘s homegrown interfacer tactics for Small Countries is a case in point.

You may recall from yesterday how we dynamically reverted to “geographicals mode” display (Google call it “Markers” mode) when the shading for a Small Country would lead to “data loss”. But what if we …

  • continue what we were doing yesterday “overlayed”

    … onto …

  • what we changed from URL-wise with “function assess_small()” (with the one codeline change

    outsuffix='&overlay=y&aregeographicals=' + pushag[ipl];

    ) … in the form of two new HTML iframe code below …
    <?php

    if (isset($_GET['overlay']) || isset($_POST['overlay'])) {
    echo "<script> function overlayit() {
    var ourls=documentURL.split('&overlay=')[0].split('[');
    var ourl=ourls[0];
    for (var iouris=1; iouris<ourls.length; iouris++) {
    if (ourls[iouris].substring(0,1) == '~') {
    ourl+='[' + ourls[iouris];
    } else {
    ourl+='[' + ourls[iouris].replace(ourls[iouris].split('~')[0],'');
    }
    }
    document.body.style.zIndex='-12';
    document.getElementById('doverlay').innerHTML='<iframe style=\"position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:2;opacity:0.95;\" src=\"' + ourl + '\"></iframe>';
    document.getElementById('doverlaytwo').innerHTML='<iframe style=\"position:absolute;top:0px;left:0px;width:100%;height:100vh;z-index:22;opacity:0.9;\" src=\"' + documentURL.replace('&overlay=','&qw=') + '&guess=' + '\"></iframe>';
    }
    setTimeout(overlayit, 2000);
    </script>
    ";
    }

    ?>

Again, you can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Google Chart Geo Chart Small Countries Tutorial is shown below.

Google Chart Geo Chart Small Countries Tutorial

Google Chart Geo Chart Small Countries Tutorial

We last used the excellent Google Chart Geo Chart tool with the work of Window LocalStorage Client Versus Server Map Tutorial, and it was this project that alerted us to both a weakness and a strength of that chart …

  • a weakness being its inability to get the resolution to shade a small country (eg. today’s tutorial picture‘s Andorra) … but, the good news, as used with this integration work above …
  • a strength is the alternative display mechanism via geographical entries

… and so, what if …

  • as the user enters in their Country (or Geographical) data …
  • if we can determine it as being a Country being entered … and…
  • you have only ever been entering Countries … and …
  • any one Country so defined has a surface area less than 10000 square kilometers … then …
  • we navigate to a Geographical data version of this “only Countries entered” data set … so that …
  • even small such Countries will be displayed …
  • as they would not if still in the default “only Countries entered” mode of display

We introduce three new sources of data in order to piece together the (Javascript via PHP coding) logic for this …

  1. TimeZone and Geographicals and ISO 2 Letter Code information …

    var ourtzlist='<option value="Africa/Abidjan" data-geo="5.31666,-4.03334,GMT,CI,+0">Africa/Abidjan</option><option value="Africa/Accra" data-geo="5.55,-0.21667,GMT,GH,+0">Africa/Accra</option>'; // etcetera etcetera etcetera
  2. Country Name and ISO 2 Letter Code information (etcetera etcetera etcetera) …

    <div id=dlookups>
    <select id='selceq' style='display:none;'>
    <option value='AF'>Afghanistan</option>
    <option value='AX'>Aland Islands</option>
    <option value='AL'>Albania</option>
    </select></div>
  3. Surface Areas of Countries thanks to Wikipedia (etcetera etcetera etcetera) …

    <table style='display:none;' id='surface_area' border='1' cellpadding='2' cellspacing='0'>
    <tbody><tr bgcolor='#efefef'>
    <th>Pos
    </th><th>Country
    </th>
    <th>Area (km²)
    </th></tr>
    <tr>
    <td>1</td>
    <td><a data-href='/wiki/Russia' title='Russia'>Russia</a></td>
    <td>17098246
    </td></tr>
    <tr>
    <td>2</td>
    <td><a data-href='/wiki/Canada' title='Canada'>Canada</a></td>
    <td>9984670
    </td></tr>
    <tr>
    <td>3</td>
    <td><a data-href='/wiki/People%27s_Republic_of_China' title='People's Republic of China'>China</a></td>
    <td>9572900
    </td></tr>
    </tbody></table>

… used where we process a user Country (or Geographical) interaction Javascript code snippet where variable thisris is that user interaction result …


var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;

if (ourtzlist.indexOf(',' + thisris.toUpperCase() + ',') != -1 && thisris.length == 2) {
if (selceqih == '') { selceqih=document.getElementById('selceq').innerHTML; }
if (saih == '') { saih=document.getElementById('surface_area').innerHTML; }
pushfrom.push('[~' + thisris + '~');
pushto.push('[' + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisris.toUpperCase() + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + thisris.toUpperCase() + '~');
if (selceqih.indexOf(' value=\"' + thisris.toUpperCase() + '\">') != -1) {
pushag.push('http.' + encodeURIComponent(selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0]));
} else {
pushag.push('');
}
if (saih.indexOf('>' + selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0]) != -1) {
thissa=saih.split('>' + selceqih.split(' value=\"' + thisris.toUpperCase() + '\">')[1].split('<')[0])[1].split('<td>')[1].split('<')[0].split(String.fromCharCode(10))[0];
if (eval('' + thissa) < 10000) {
oneistoosmall=true;
}
}
} else if (('' + thisris).trim() != '' && selceqih.toUpperCase().indexOf('>' + thisris.toUpperCase()) != -1) {
thisisocc=selceqih.toUpperCase().split('>' + thisris.toUpperCase())[0].split(' VALUE=\"')[eval(-1 + selceqih.toUpperCase().split('>' + thisris.toUpperCase())[0].split(' VALUE=\"').length)].split('\"')[0];
pushfrom.push('[~' + encodeURIComponent(thisris) + '~');
pushto.push('[' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + encodeURIComponent(thisris) + '~');
pushag.push('http.' + encodeURIComponent(thisris));
if (thisris.indexOf(' ') != -1) {
pushfrom.push('[~' + thisris + '~');
pushto.push('[' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[0] + '|' + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"')[eval(-1 + ourtzlist.split(',' + thisisocc + ',')[0].split(' data-geo=\"').length)].split(',')[1] + '|~' + encodeURIComponent(thisris) + '~');
pushag.push('http.' + encodeURIComponent(thisris));
}
if (saih.toUpperCase().indexOf('>' + thisris.toUpperCase()) != -1) {
thissa=saih.toUpperCase().split('>' + thisris.toUpperCase())[1];
thissa=thissa.split('<TD>')[1].split('<')[0].split(String.fromCharCode(10))[0];
if (eval('' + thissa) < 10000) {
oneistoosmall=true;
}
}
}

… and if remaining relevant just before the next navigation happens, where variable indatar represents the default “only Countries entered” mode of display value …


// var pushfrom=[], pushto=[], pushag=[], selceqih='', saih='', oneistoosmall=false, oneisnotapplicable=false;
function assess_small(indatar) {
var outsuffix='';
var outdatar=indatar;
if (pushfrom.length > 0 && !oneisnotapplicable && oneistoosmall) {
for (var ipl=0; ipl<pushfrom.length; ipl++) {
if (outdatar.indexOf(pushfrom[ipl]) != -1) {
if (outsuffix == '') {
outsuffix='&aregeographicals=' + pushag[ipl];
} else {
outsuffix+='%2C' + pushag[ipl];
}
while (outdatar.indexOf(pushfrom[ipl]) != -1) {
outdatar=outdatar.replace(pushfrom[ipl], pushto[ipl]);
}
}
}
}


return outdatar + outsuffix;
}

You can try the changed geo_chart.php Geo Chart interfacer at this live run link.


Previous relevant Window LocalStorage Client Versus Server Map Tutorial is shown below.

Window LocalStorage Client Versus Server Map Tutorial

Window LocalStorage Client Versus Server Map Tutorial

Get a good map, and a goodly number of times you’ll want a map of smaller or larger scale than the one you have. Murphy’s Law? This is probably why in the wonderful woooooooorrrrrrrrlllllld of Google Charts they have included …

  • Geo Chart topographic map of the world or of regions
  • Map Chart terrestrial/satellite map of your group of markers at a zoom level of your choosing

… and hope you can see that the latter can save the day for a Short Distance Trip (corner shop, anyone?!).

So we’ve added onto yesterday’s Window LocalStorage Client Versus Server Timeline Tutorial progress a new toggling button to view a scenario in either Google Chart scenario above.

You can see this integration work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link supervising a tweaked geo_chart.php Geo Chart interfacer.


Previous relevant Window LocalStorage Client Versus Server Timeline Tutorial is shown below.

Window LocalStorage Client Versus Server Timeline Tutorial

Window LocalStorage Client Versus Server Timeline Tutorial

Up to yesterday’s Window LocalStorage Client Versus Server User Tutorial‘s progress, our Capital City Find Matching Country Report web application project was all about …

  • where (and capital of “what”) … but we often seek out a way to add into the mix that 4th dimension …
  • when (ie. time)

… and regarding the current project, a …

  • where “map” … can interface with a …
  • when “Trip Plan Itinerary”

… and for this purpose, we’re going to interface to the excellent Google Charts Annotated Timeline Chart, thanks, because it combines links of “time” to “user annotations” in a timeline way, that similar way you might describe the qualities of a Trip, even before you’ve gone on that trip. We’ve also added it so that an unordered places list can be turned into a Trip Plan Itinerary at the click/touch of a new map 🗺 &#128506; emoji button.

Again, see how these timeline amendments were achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link and annotatedtimeline_chart.php which changed quite a lot.


Previous relevant Window LocalStorage Client Versus Server User Tutorial is shown below.

Window LocalStorage Client Versus Server User Tutorial

Window LocalStorage Client Versus Server User Tutorial

The inherent weakness with our current Capital City Find Matching Country Report web application project, to our minds, was that places of interest are not restricted to the Capital Cities of Countries, especially when “Trip Planning”. On the other hand, it would be impossible to cater for every “place” in the world. That is far too subjective for good web application applicability. What would be good though, is to allow in user defined …


Place name, Country name

… terms, the definitions of interest to a user. We can ask this …

  • flagged by the click/touch of an emoji button … and …
  • the interactive entry presented via a Javascript prompt window

. When thinking of data applicable to an individual, then that can be catered for by recording it in localStorage where it will be recalled on the next execution of that web application in the same web browser.

This, along with a Colour Wheel of the “nearest TimeZone place” onto the existing logic of yesterday’s Window SessionStorage Client Versus Server Order Tutorial progress could make for a more useful and practical tool for those Trip Planners out there!

See how this was achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Did you know?

To click/touch one of those Google Chart Geo Chart lines between Emoji Flag Markers will show a new Google Maps directions web page with transport times and detail, as well as an inhouse crow fly distance of that trip leg, as shown up the top right of today’s tutorial picture.


Previous relevant Window SessionStorage Client Versus Server Order Tutorial is shown below.

Window SessionStorage Client Versus Server Order Tutorial

Window SessionStorage Client Versus Server Order Tutorial

If we are to honour our thoughts of being able to use our current Capital City Find Matching Country Report web application as a Trip Planner …

Our primary integration today is to (software) integrate the great Weather Underground and its great API service for autocomplete name searches for weather (and hurricane) information. Why bother? Well, can you not envisage a user using that Ajax functionality of yesterday’s Window SessionStorage Client Versus Server Ajax Tutorial as a trip planner, perhaps, or as a “checking up on relatives overseas” tool, perhaps? And not all the capital cities are timezone places, and so for some of those we can use Weather integration to still show apt online information when click/touching a Countries Report row. Speaking of this “row”, we make an improvement whereby on a first click of a right hand (Country) row cell, that cell is not initially a contenteditable=”true” one (that may frustrate showing the keyboard on mobile, when most likely it was the row touch intended), but then becomes a contenteditable=”true” cell henceforth.

… then yesterday’s Window SessionStorage Client Versus Server Flags Tutorial “progress to now” needs to take notice of a user’s order of multiple select (dropdown) element click/touching of Capital City option (sub)elements, just as we did with the recent User Controlled Dynamic Javascript YouTube Embedded API Ordered Tutorial‘s web application project to allow for a user ordered YouTube video playlist.

Because what is a Trip Planner without an ordered trip? Well, that is debatable, but what isn’t (debatable), is that there will be people in the world who appreciate the “mapping out” of a proposed Trip Planning Itinerary. What could we call on here? We can think of the Google Chart Geo Chart work around about the time of Google Geo Chart Co-ordinate Emojis Tutorial, when we started using …

  • a world map … with …
  • emoji markers … and optionally …
  • joined up by straight lines

… an idea for a Trip Plan itinerary synopsis, perhaps?!

If you examined closely yesterday’s code changes you will have noticed our collecting of TimeZone Place geographical latitude and longitude information. Today, we start making use of that preparatory work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Stop Press

The “emoji markers” above (as of 2 January 2020) will be “country flags” (as per Window SessionStorage Client Versus Server Flags Tutorial ideas), as defined.


Previous relevant Window SessionStorage Client Versus Server Flags Tutorial is shown below.

Window SessionStorage Client Versus Server Flags Tutorial

Window SessionStorage Client Versus Server Flags Tutorial

Yes, there’s more to do onto yesterday’s Window SessionStorage Client Versus Server CSS Tutorial‘s Capital City Find Matching Country Report web application project, in our eyes. We have not even mentioned “Internationalization” as a concept up to now. In this line of thinking …

Did you know?

Emoji flags via ISO 2 character country codes are dead easy via Regional Indicator Symbol characters …


var lri="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];

var thiscc='AU'; // ISO 2 character countrycode for Australia
var ccsuff='', ccchar=' ';
for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
ccsuff+='&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
}
document.getElementById('lastflag').innerHTML=ccsuff;

… to result in (via <span style=font-size:64px;>&#127462;&#127482;</span>) …


🇦🇺

… providing interest and general translatability to the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.


Previous relevant Window SessionStorage Client Versus Server CSS Tutorial is shown below.

Window SessionStorage Client Versus Server CSS Tutorial

Window SessionStorage Client Versus Server CSS Tutorial

Further to yesterday’s Window SessionStorage Client Versus Server Integration Tutorial we have a two pronged improvements set for you today with our current Capital City Find Matching Country Report web application project …

  • CSS styling changes … and …
  • additional functionality for Email and SMS links back to our current Capital City Find Matching Country Report web application project (to complete the cycle)

We use several modes of CSS application (the first and last of particular relevance to today’s “highlighting of workflow” improvements) …

… the “static” measures often helping to highlight the web application’s main workflow of user interaction and the “dynamic” measures helping to alert the user as to where to proceed with their “workflow”.

In terms of CSS styling work …

  1. for non-mobile platforms we allow for more columns to be applied to our Capitals select (dropdown) element (in order to reduce some user scrolling, as does our new additional A-Z letter basis sorting functionality) as per … the “dynamic” Javascript DOM “class” modifications

    if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    document.getElementById('lefttd').className='lefttd';
    }

    … dovetailing with the “static” internal CSS coding

    <style>
    .lefttd {
    column-count: 4;
    max-height: 35%;
    vertical-align: top;
    max-width: 70%;
    font-size: 8px;
    background-color: rgba(205,205,205,0.5);
    background-image: -webkit-gradient(
    linear,
    right bottom,
    left top,
    color-stop(0, rgba(205, 205, 205, 0.8)),
    color-stop(0.50, rgba(255, 255, 0, 0.2))
    );
    background-image: -o-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -moz-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -webkit-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: -ms-linear-gradient(left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);
    background-image: linear-gradient(to left top, rgba(205, 205, 205, 1) 0%, rgba(255, 255, 0, 0.2) 50%);

    }
    </style>

    … and please note that around here at RJM Programming we have a “far from hard and fast rule” (but a rule regardless) regarding HTML element ID and class attributes that they concern (and (usually) be compartmentalised into) Javascript (DOM) manipulations and CSS styling issues respectively … and add a linear-gradient background to the table cell when expecting the initial user interaction on non-mobile platforms
  2. a “dynamic” Javascript DOM “class” modification … document.getElementById(‘myrepsb’).className=’dglow’; … is made to the “Report…” button at the Capitals select (dropdown) onfocusout event so as to highlight (with “glow” inspired styling) where user interaction may flow to

As far as links go, you may expect to need serverside means to construct these in online Email and SMS message interfacing, but email (client program) products like Gmail parse your ascii text and convert http: or https: protocol URLs in your Email body to hyperlinks, as does the Messages SMS application here on this MacBook Pro using macOS Mojave. Cute, huh?! So to close the circle back from remote thar’ parts back to our web application is a simple matter of, in broad brush terms …

  • adding two new buttons called “Email Columns and Links …” and “SMS Columns and Links …” that …
  • set a global variable andlinkto = true; … setting in play, within the report writing code (that likes monospaced fonts) …
  • add a new links column to the right with URLs like …
    https://www.rjmprogramming.com.au/HTMLCSS/wls_vs_php.htm?andgo=y&countries=Belize&capitals=Belmopan
    … to tell your client programs to form the hyperlinks for us (if they are “of the mood”, that is!)

To improve user experience we use “dynamic” Javascript DOM HTML “style” attribute change means to easier close the “Colour Wheel” helper web application “above the fold” by changing the CSS z-index (Javascript DOM [element].style.zIndex) of elements accordingly, when the user clicks other elements. You can see all this with the first “the changed” link above, where all “glow” CSS styling will also feature prominently.


Previous relevant Window SessionStorage Client Versus Server Integration Tutorial is shown below.

Window SessionStorage Client Versus Server Integration Tutorial

Window SessionStorage Client Versus Server Integration Tutorial

We hope, when performing a “software integration” task, that the two or more components of that integration work with each other’s talents, rather than a big tussle like reinventing the wheel. This ideal makes the work …

  • sometimes difficult but rewarding because …
  • the differences between two independent software components can be quite large and daunting … and the programmer has to see that …
  • care is applied so as not to wreck previous functionality and integrations in making the current integration work

… and that is why we’ve made corollaries to “building from scratch” (when planning and design is a huge component) can be a lot simpler than a software integration “renovation”, in the past, here at this blog.

Our primary integration today is to (software) integrate the great Weather Underground and its great API service for autocomplete name searches for weather (and hurricane) information. Why bother? Well, can you not envisage a user using that Ajax functionality of yesterday’s Window SessionStorage Client Versus Server Ajax Tutorial as a trip planner, perhaps, or as a “checking up on relatives overseas” tool, perhaps? And not all the capital cities are timezone places, and so for some of those we can use Weather integration to still show apt online information when click/touching a Countries Report row. Speaking of this “row”, we make an improvement whereby on a first click of a right hand (Country) row cell, that cell is not initially a contenteditable=”true” one (that may frustrate showing the keyboard on mobile, when most likely it was the row touch intended), but then becomes a contenteditable=”true” cell henceforth.

As a user experience improvement for “trip planners” perhaps, we allow the user to alphabetically sort the presented select (dropdown) element entries …


var firstopt='';
var wasopts='';
var restopts='';

function readyitforsort(iselid) {
var optsare=[];
var huhisel=document.getElementById(iselid).innerHTML;
var huhsopts=huhisel.split('</option>');
for (var ihuh=0; ihuh<huhsopts.length; ihuh++) {
if (huhsopts[ihuh].trim() != '') {
if (firstopt == '') {
firstopt=huhsopts[ihuh] + '</option>';
} else {
wasopts+=huhsopts[ihuh].replace('option ','option data-ih="' + (huhsopts[ihuh].split('>')[eval(-1 + huhsopts[ihuh].split('>').length)] + '" ')) + '</option>';
optsare.push(huhsopts[ihuh].replace('option ','option data-ih="' + (huhsopts[ihuh].split('>')[eval(-1 + huhsopts[ihuh].split('>').length)] + '" ')) + '</option>');
}
}
}
optsare.sort();
for (var jhuh=0; jhuh<optsare.length; jhuh++) {
restopts+=optsare[jhuh];
}
}

… controlled by a new dropdown in the left hand column header cell.

We also allow the user to move the iframe element with some positioning emoji buttons near the “Close” button one (of yesterday’s work).

Into the future, too, we’ll have more to say regarding the germination of an idea “to allow a mobile onmouseover simulator (of sorts)” be to allow the user to perform a swipe across an individual HTML element of interest on mobile platforms (ie. harness ontouchmove event) as per (so far) … kicked off by “<body onload=” setTimeout(athn, 5000); “>” …


var last24='';
var rectdc;

function nodivalert() {
document.getElementById('divalert').style.display='none';
document.getElementById('divalert').style.zIndex='-456';
document.getElementById('divalert').style.left=('-' + rectdc.left).replace('px','') + 'px';
document.getElementById('divalert').style.top=('-' + rectdc.top).replace('px','') + 'px';
}

function ourdivalert(inmsg) {
document.getElementById('divalert').style.position='absolute';
document.getElementById('divalert').style.left=('' + rectdc.left).replace('px','') + 'px';
document.getElementById('divalert').style.top='' + eval(-80 + eval(('' + rectdc.top).replace('px',''))) + 'px';
document.getElementById('divalert').style.backgroundColor='#e0e0e0';
document.getElementById('divalert').style.display='block';
document.getElementById('divalert').style.zIndex='456';
document.getElementById('divalert').style.opacity='0.8';
document.getElementById('divalert').style.padding='5px 5px 5px 5px';
document.getElementById('divalert').innerHTML=inmsg + '<br><br><input type=button value=Close onclick=nodivalert();></input>';
setTimeout(nodivalert,9000);
}

function athn() {
rectdc=document.getElementById('dc').getBoundingClientRect();
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('dc').ontouchmove=function(event) { if (last24.substring(0,eval(-1 + last24.length)) == event.target.title.substring(0,eval(-1 + event.target.title.length))) { last24=last24; } else { last24=event.target.title; ourdivalert(event.target.title); } }
} else {
document.getElementById('dc').onmousemove=function(event) { if (last24.substring(0,eval(-1 + last24.length)) == event.target.title.substring(0,eval(-1 + event.target.title.length))) { last24=last24; } else { last24=event.target.title; ourdivalert(event.target.title); } }
}
}

… working with the new HTML …


<div id=divalert></div>
</body>
</html>

… to try to allow the “explainer of an element” advantages non-mobile platforms have for hovering over an HTML element with a title attribute filled in.

And so, yet again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new Weather integration functionality. It caused the changed colour_wheel.html‘s colour wheel (at this live run link) to be affected (by integrations “up”).


Previous relevant Window SessionStorage Client Versus Server Ajax Tutorial is shown below.

Window SessionStorage Client Versus Server Ajax Tutorial

Window SessionStorage Client Versus Server Ajax Tutorial

We have a few “clientside chestnuts” to use with our current Capital City Find Matching Country Report web application project today, those being …

  • Ajax functionality, kicked off by an “onclick” event set of logic, allowing mobile platforms to also have a look in (the look in that they miss when the event logic is off the “onmouseover” event)
  • iframe and its …
    1. srcdoc attribute (“content” alternative to src “url” attribute) … along with, and crucially needing (because srcdoc ignores its own document.body onload goings on, that we need the “Iframe Client Pre-Emptive” methods below to circumvent) the …
    2. onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)

… adding onto yesterday’s Window SessionStorage Client Versus Server Canvas Tutorial.

It’s not that involved with the Ajax work today, given that there are no cross-domain issues, though there are cross-protocol (SSL https: versus non-SSL http:) issues to be careful about. Those can be addressed because the web application is recalled to present its “Country Report” and that is the opportunity to check on protocol navigation requirements.

Along the way, we also make this happen for the user on …

  • click/touching a table row … it sets off new “tr” (table row) element logic calling our (inhouse) Timezone and Wikipedia Place Information helper (HTML) via Ajax (so not leaving the webpage) … and because of place name oddities we allow for …
  • “td” (table cell) element user amendments by setting their contenteditable attributes to “true” (since fixed, but we found the Timezone Europe/Tirane pointing at Tirane in Albania used to be spelt “Tirana”)

… that latter methodology normally a technique we apply to “div” elements (so, there you are!)

Also used are “overlay” techniques, two of the “usual suspects” here coming into play, to present to the “Ajax content to srcdoc iframe arrangements” …

Yet again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new “Ajax” functionality.


Previous relevant Window SessionStorage Client Versus Server Canvas Tutorial is shown below.

Window SessionStorage Client Versus Server Canvas Tutorial

Window SessionStorage Client Versus Server Canvas Tutorial

Yesterday’s Window SessionStorage Client Versus Server Share Tutorial dealt with ascii text clipboard copy assisted sharing options with our current Capital City Find Matching Country Report web application project. This suited both Email and SMS share options we coded for, but today’s extension of functionality from “ascii text” data to “graphical data” only suits Email sharing. The other caveat with our work is that no serverside (for us, PHP) help is allowed, so no PHP mail here.

What comes into play with a “graphical data” clientside (only) sharing approach? It will not surprise many readers that, for us, it involves …

  • canvas element … converting HTML table outerHTML “ascii text” data … via …
  • canvas drawing methods “[canvasContext].strokeRect()” and “[canvasContext].strokeText()” via “[cellElement].getBoundingClientRect()” … to convert that canvas element content via …
  • [canvasElement].toDataURL() … to an …
  • img element nested in a div contenteditable=true element … so as to hook in with today’s very useful helper link, thanks … use …

  • function tabletoclipboard(canvas) { // thanks to https://stackoverflow.com/questions/27863617/is-it-possible-to-copy-a-canvas-image-to-the-clipboard
    var img = document.createElement('img');
    img.src = canvas.toDataURL();

    var div = document.createElement('div');
    div.contentEditable = true;
    div.appendChild(img);
    document.body.appendChild(div);

    // do copy
    SelectText(div);
    document.execCommand('Copy');
    document.body.removeChild(div);
    }

    function SelectText(element) { // thanks to https://stackoverflow.com/questions/27863617/is-it-possible-to-copy-a-canvas-image-to-the-clipboard
    var doc = document;
    if (doc.body.createTextRange) {
    var range = document.body.createTextRange();
    range.moveToElementText(element);
    range.select();
    } else if (window.getSelection) {
    var selection = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(element);
    selection.removeAllRanges();
    selection.addRange(range);
    }
    }
  • to leave the user’s device’s clipboard containing a useful table (with linework) … ready to …
  • paste into an email body section

… sharing off to an emailee collaborator.

Again, see the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new “Email Table” button functionality.


Previous relevant Window SessionStorage Client Versus Server Share Tutorial is shown below.

Window SessionStorage Client Versus Server Share Tutorial

Window SessionStorage Client Versus Server Share Tutorial

Yesterday’s Window SessionStorage Client Versus Server Tutorial has been amended today for two new sharing and collaboration options, those being …

  • email
  • SMS

… but you may well be familiar with the restrictions on email and SMS client (program) approaches to this, coming from HTML “a” link “mailto:” and “sms:” href property prefixes respectively. We’re going to need help with the 800 odd character (length) restrictions with the (resultant) web address (bar) URL, but what? How about working off the great advice of this wonderful link, thanks, to copy what we’d have assembled into an ascii text Report into the characters contained by the user’s device’s clipboard?


function copytoclipboard(str) { // thanks to https://hackernoon.com/copying-text-to-clipboard-with-javascript-df4d4988697f
var el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
}

An issue that springs up here using such clipboard ascii text content, whenever you get the Font choice given to you, pick a monospaced Font like Courier New or “Fixed Width”.

See the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link’s new sharing functionality.


Previous relevant Window SessionStorage Client Versus Server Tutorial is shown below.

Window SessionStorage Client Versus Server Tutorial

Window SessionStorage Client Versus Server Tutorial

Sometimes it’s the case at this blog that we’d like to introduce a new topic, but do not do so, because we cannot show any real world (or real application) use of that concept. So it has been, up until now, with the concept of (web browser) window (object) sessionStorage property. But yesterday’s Window LocalStorage Client Versus Server Primer Tutorial represented an opportunity akin to when Haley’s Comet gets at its closest to the Earth … while you see a chance, take it … chance because of that nuance whereby we were not trying to store data for any other purpose than passing data onto …

  1. a known entity … ie. same web application … at …
  2. a known time … ie. immediately

… two conditions that make the code design “marginally” more ideal for the window object property concept of sessionStorage rather than localStorage, in that any …


localStorage.removeItem([knownLocalStorageName]);

… becomes superfluous as with sessionStorage data will disappear between web browser sessions, anyway.

We offer this new concept as a non-default option of a select (dropdown) element replacement to the h1 element hardcoding “localStorage” with the changed wls_vs_php.htm Capital City Find Matching Country Report live run. The other nuance of difference with sessionStorage usage is that in the document.body onload event logic, we may as well (as part of other changes) pre-emptively look for, and if there, respond to, any found sessionStorage data points, even without the user having flagged it specifically


var datamode='localStorage';

function checkforreport() {
var divcont='';
var dcaps, dctys, idis;
if (getcapitals == 'localStorage') {
if (window.localStorage) {
getcapitals=decodeURIComponent(localStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
localStorage.removeItem('wls_vs_php_capitals');
} else {
getcapitals='';
}
} else if (getcapitals == 'sessionStorage') {
document.getElementById('smode').value=getcapitals;
datamode=getcapitals;
if (window.sessionStorage) {
getcapitals=decodeURIComponent(sessionStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
} else {
getcapitals='';
}
}
else if (getcapitals == '' && window.sessionStorage) {
getcapitals=decodeURIComponent(('' + sessionStorage.getItem('wls_vs_php_capitals')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (getcapitals != '') {
document.getElementById('smode').value='sessionStorage';
datamode='sessionStorage';
}
}

if (getcountries == 'localStorage') {
if (window.localStorage) {
getcountries=decodeURIComponent(localStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
if (getcapitals.replace('localStorage','') != '' && getcountries.replace('localStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
localStorage.removeItem('wls_vs_php_countries');
} else {
getcountries='';
}
} else if (getcountries == 'sessionStorage') {
if (window.sessionStorage) {
getcountries=decodeURIComponent(sessionStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
if (getcapitals.replace('sessionStorage','') != '' && getcountries.replace('sessionStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
} else {
getcountries='';
}
}
else if (getcountries == '' && document.getElementById('smode').value == 'sessionStorage' && window.sessionStorage) {
getcountries=decodeURIComponent(('' + sessionStorage.getItem('wls_vs_php_countries')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (getcountries != '') {
document.getElementById('smode').value='sessionStorage';
datamode='sessionStorage';
}
}

if (getcapitals != '' && getcountries != '') {
divcont='<table border=5 style="width:95%;vertical-align:top;background-color:white;"><tr style=background-color:#f0f0f0;"><th>Capital</th><th>Country</th></tr></table>';
dcaps=getcapitals.split('|');
dctys=getcountries.split('|');
for (idis=0; idis<dcaps.length; idis++) {
divcont=divcont.replace('</table>', '<tr><td>' + dcaps[idis] + '</td><td>' + dctys[idis] + '</td></tr></table>');
}
document.getElementById('dreport').innerHTML=divcont;
}
document.getElementById('smode').value=datamode;
}

Which beggars the question “What are the differences between sessionStorage and localStorage?” A quick reading might surmise that “the latter has an expiration date”. We leave you with an open ended Google search so that you may extend your readings on this.


Previous relevant Window LocalStorage Client Versus Server Primer Tutorial is shown below.

Window LocalStorage Client Versus Server Primer Tutorial

Window LocalStorage Client Versus Server Primer Tutorial

Even though we rave on a lot about serverside PHP and its $_POST method=POST (versus HTML/Javascript recipient via ? and & argument $_GET method=GET scenario) data length advantages as the recipient of an HTML form method=POST set of data that could be sizeable, we’ve just realized that there is a client Javascript and window.localStorage methodology that may help alleviate the need to involve PHP (and any other serverside intervention) on occasions.

Hint: Yes, we’ve raved on about this too?! Does the blog posting title give it away? Okay, yes, it should read “localStorage”, but thought we’d gone past such juvenile finickiness since the Whac-A-Mole controversy of 1st December 2019 (or even The Great Tea Trolley Disaster of ’67, we daresay).

It can even use a “self-destruct” approach to the use of this “localStorage” on having used it because …

  • the web application knows who is using it (localStorage) … and on having accessed and read it …
  • the web application knows it (localStorage) is of no use to any other user (in this web application’s case, at least)

… which is very pleasing for a Land Surveyor who likes to leave cow paddocks as they’ve seen them so to speak. Except it’s like having a ten tonne truck worth of data access in amongst the cow pats when having access to “localStorage” (or PHP), rather than a little piddle of calf wee (wee Metcalfes know a thing or two about these things!) data access of ? and & HTML/Javascript URL arguments (or even if we were to use HTTP Cookies).

It’s not as if we all have access to serverside language usage, though we do, because we really like PHP and MAMP and Apache/PHP/MySql web servers (and have arranged our development environment accordingly), but what if you are starting out in web development, and still want to allow for sizeable chunks of data with your web applications? Huh? Huh?! See the possibilities? Try our proof of concept wls_vs_php.html Capital City Find Matching Country Report live run, and highlight a whole swathe of (multiple mode) dropdown option Capital Cities holding down the shift key before pressing the yellow “Report” button. If the URL ends up as …

https://rjmprogramming.com.au/HTMLCSS/wls_vs_php.html?capitals=localStorage&countries=localStorage

that’s because the web application’s …


function analyze() {
var purl=document.URL.split('#')[0].split('?')[0] + '?capitals=' + encodeURIComponent(document.getElementById('capitals').value) + '&countries=' + encodeURIComponent(document.getElementById('countries').value);
if (purl.length > 800) {
if (phpexists) {
document.getElementById('myform').method='POST';
document.getElementById('myform').action='./wls_vs_php.php';
} else if (window.localStorage) {
localStorage.setItem('wls_vs_php_countries', encodeURIComponent(document.getElementById('countries').value));
localStorage.setItem('wls_vs_php_capitals', encodeURIComponent(document.getElementById('capitals').value));
document.getElementById('capitals').value='localStorage';
document.getElementById('countries').value='localStorage';
location.href=document.URL.split('#')[0].split('?')[0] + '?capitals=' + encodeURIComponent(document.getElementById('capitals').value) + '&countries=' + encodeURIComponent(document.getElementById('countries').value);

return false;
}
}
return true;
}

… HTML form onsubmit event logic …

  1. discovered no PHP web application existant (via Client Pre-emptive Iframe techniques) … and …
  2. discovered (in a sanity check feeling way) that to go down the proposed HTML form method=GET approach was risking a …

    HTTP 414 "Request URI too long"

    … web browser error … and that …
  3. localStorage was a known web browser piece of functionality
  4. … and so as per our localStorage logic we …

  5. back out of the default HTML form method=GET navigation setup of the web application in favour of …
    • storing that data into localStorage
    • substituting into the URL ? and & arguments the hardcoding “localStorage” (and in so doing, getting back under the HTTP 414 “Request URI too long” limitation, piecing together (what amounts to) …
      location.href=document.URL.split(‘#’)[0].split(‘?’)[0] + ‘?capitals=localStorage&countries=localStorage’;)
      … that on a recall to this same web application a …
    • document.body onload event piece of Javascript logic checks the localStorage for its incoming Capital City Country Report data, as per …

      var phpexists=false;
      var getcapitals=location.search.split('capitals=')[1] ? decodeURIComponent(location.search.split('capitals=')[1].split('&')[0]).replace(/\+/g,' ') : '';
      var getcountries=location.search.split('countries=')[1] ? decodeURIComponent(location.search.split('countries=')[1].split('&')[0]).replace(/\+/g,' ') : '';

      function checkforreport() {
      var divcont='';
      var dcaps, dctys, idis;
      if (getcapitals == 'localStorage') {
      if (window.localStorage) {
      getcapitals=decodeURIComponent(localStorage.getItem('wls_vs_php_capitals')).replace(/\+/g,' ');
      localStorage.removeItem('wls_vs_php_capitals');
      } else {
      getcapitals='';
      }
      }
      if (getcountries == 'localStorage') {
      if (window.localStorage) {
      getcountries=decodeURIComponent(localStorage.getItem('wls_vs_php_countries')).replace(/\+/g,' ');
      if (getcapitals.replace('localStorage','') != '' && getcountries.replace('localStorage','') != '') { document.getElementById('myh1').innerHTML+=' <font size=1>... yes, it was needed</font>'; }
      localStorage.removeItem('wls_vs_php_countries');
      } else {
      getcountries='';
      }
      }

      if (getcapitals != '' && getcountries != '') {
      divcont='<table border=5 style="width:95%;vertical-align:top;background-color:white;"><tr style=background-color:#f0f0f0;"><th>Capital</th><th>Country</th></tr></table>';
      dcaps=getcapitals.split('|');
      dctys=getcountries.split('|');
      for (idis=0; idis<dcaps.length; idis++) {
      divcont=divcont.replace('</table>', '<tr><td>' + dcaps[idis] + '</td><td>' + dctys[idis] + '</td></tr></table>');
      }
      document.getElementById('dreport').innerHTML=divcont;
      }
      }

      … the localStorage.removeItem() representing that “self-destruct” nuance we were talking about before

We may well use this methodology in future projects, and hope it has been of some little interest to you as well?!

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

PHP Tokeniser Primer Tutorial

PHP Tokeniser Primer Tutorial

PHP Tokeniser Primer Tutorial

Validation is a big subject area for programmers (we last discussed with XML Lint Validation Tutorial), and “when in a real pickle” I’ve turned to online HTML validators such as this one, but more often the web browser’s web inspector can help.

Here, changing from CentOS to AlmaLinux as the hosting Apache/PHP/MySql environment, we’ve been surprised by, even with PHP issues, the web browser web inspectors are by and large doing the job helping us debug issues. Nonetheless, we want to explore the Tokeniser PHP extension as a …

… best understood, we reckon, by trying it yourself …

Did you know?

For the first time we can remember we got over the perennial problem of form programming language code content encoding whereby a + equates to a space (on decoding) where we’d rather have %20 be used, as encodeURIComponent uses to encode the space character, by …

  1. on the way out, use (a form onsubmit event function incorporating) window.btoa
    <?php echo ”

    function btoait() {
    orig=document.getElementById('html').value;
    document.getElementById('html').value=window.btoa(orig);
    return true;
    }

    “; ?>

  2. teamed with, on the way in, incorporating base64_decode
    <?php

    $html_fragment=base64_decode($_POST['html']);

    ?>

… to get around that + character being misinterpreted. We find, though, that window.btoa can fail when there is a lot of data or complex data (or, it could have been a bad hair day?!)


Previous relevant XML Lint Validation Tutorial is shown below.

XML Lint Validation Tutorial

XML Lint Validation Tutorial

Do you remember when we discussed the Sanitizer API, talked about at Sanitizer API Primer Tutorial, regarding it as a web application HTML (and more) validation tool?

Well, we’ve based a new “validator” of HTML or XML using the XML Lint web application on what we did then, but this code needing to be …

  • under the auspices of a serverside scenario … ie. PHP … for us … calling on …
  • underlying operating system call such as (for HTML qsall.htm incoming data file) …

    xmllint --html --valid --noout ./qsall.htm

    … via …
  • shell_exec

… there’s not much left of the original HTML and Javascript!

We had a fun time with HTML textarea elements and scrolling with the resultant “first draft” xmllint_validation.php you might want to try for yourself supplying an HTML or XML URL of intetest. Why, in particular? Well, it was the first time that we remember trying to make practically useful …

  • a table cell (ie. td element) (the left of two) hosted …
  • two textarea element arrangement whereby, ideally. they view …
    1. side by side
    2. if one is scrolled the two identically scroll the same amount … (document.body outerHTML) HTML …
      <?php echo ”

      <body onload="s1 = document.getElementById('preincoming'); s2 = document.getElementById('incoming'); s1.addEventListener('scroll', select_scroll_1, false); s2.addEventListener('scroll', select_scroll_2, false);" data-onload='onl();'>
      <h1>XML Lint Validation <!--button onclick='trythis();' title='Try your own'>Usage</button--></h1>
      <h3>RJM Programming - June, 2024</h3>
      <form action=./xmllint_validation.php method=POST target=_self>
      <table style=width:95%; border=5>
      <tr><th colspan=2 style=text-align:center;>XML Lint validation of <input style=width:70%; onblur="if (this.value.length > 0) { document.getElementById('mysub').click(); }" name=htmlfile id=myhxfile placeholder='Please enter either HTML or XML file to validate ...' value="<?php echo str_replace('>','>',str_replace('<','<',$prefn)); ?>"></input></th></tr>
      <tr><th>Data to validate</th><th>XML Lint results</th></tr>
      <tr><td style=vertical-align:top;><textarea style=font-size:8px;display:inline-block;overflow-x:clip;text-wrap:nowrap;text-align:right; id=preincoming><?php echo str_replace('>','>',str_replace('<','<',$precontents)); ?></textarea><textarea onblur="if (this.value.length > 0 && '<?echo $fn; ?>' == '') { document.getElementById('mysub').click(); }" style=font-size:8px;display:inline-block;overflow-x:clip;text-wrap:nowrap; name=content id=incoming><?php echo str_replace('>','>',str_replace('<','<',$contents)); ?></textarea></td><td style=vertical-align:top;><textarea id=outgoing><?php echo str_replace('>','>',str_replace('<','<',$results)); ?></textarea></td></tr>
      <tr><td></td><td><input type=submit id=mysub style=display:<?php echo $vsnone; ?> value=Validate></input></td></tr>
      </table>
      </form>
      </body>

      “; ?>
      … uses Javascript …
      <?php echo ”

      var s1=null, s2=null;

      // Thanks to https://stackoverflow.com/questions/7108270/scrolling-2-different-elements-in-same-time
      function select_scroll_1(e) { s2.scrollTop = s1.scrollTop; }
      function select_scroll_2(e) { s1.scrollTop = s2.scrollTop; }

      “; ?>
      … so that …
    3. the left hand textarea contains code line numbers right aligned … to sidle up next to …
    4. the right hand textarea contains the code (HTML or XML) being validated by xmllint

    … while …

  • the right hand table cell contains the xmllint validation (of HTML or XML) results

… had us, in practice, thanking our lucky stars that …

  1. textarea elements are resizeable
  2. you can simulate “some cockpit action” aligning them vertically … Jim?!


Previous relevant Sanitizer API Primer Tutorial is shown below.

Sanitizer API Primer Tutorial

Sanitizer API Primer Tutorial

Today we’re roadtesting the Sanitizer API

The HTML Sanitizer API allow developers to take untrusted strings of HTML and Document or DocumentFragment objects, and sanitize them for safe insertion into a document’s DOM.

… as another validation idea for HTML to add to our previous HTML Online Validation Tidy Errors Tutorial efforts.

Perhaps you’d like to try the “Usage” button of the proof of concept web application below …

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

PHP Intl Class Peer to Peer Locale Variants World Map Tutorial

PHP Intl Class Peer to Peer Locale Variants World Map Tutorial

PHP Intl Class Peer to Peer Locale Variants World Map Tutorial

Today, further to yesterday’s PHP Intl Class Peer to Peer Locale Variants Tutorial, we seek to answer questions such as …

Which countries in the world speak Arabic?

… and with a changed i_eg.js supporting a changed i_variant_eg.php and with the inhouse PHP intl class web application such questions are easier to answer on a Google Chart Geo Chart world map we start presenting.

And regarding “too thin” table cells hosting iframe hosting variant Current Datetimes, we also now offer onclick or oncontextmenu right click ways to show a “blow up view” of that same data in a table row below the top table row cells, which you can see and try for yourself below.

Now, in a data display sense, you might ask (via entering into yellow Locale textbox)

For a given Language can you show me Current Datetime in all the Countries of relevance using it?

Example below is for de German

For a given Script type can you show me Current Datetime in all the Countries of relevance using it?

Example below is for Latn script type

For a given Country can you show me Current Datetime in all the Languages of relevance to it?

Example below is for CY Cyprus


Previous relevant PHP Intl Class Peer to Peer Locale Variants Tutorial is shown below.

PHP Intl Class Peer to Peer Locale Variants Tutorial

PHP Intl Class Peer to Peer Locale Variants Tutorial

We’ve written a new member of “the peerage”, in other words, our inhouse PHP intl class web applications. It gathers variants of an entered Locale into a group we display Current Datetimes for in a series of HTML iframe hosting elements.

And if you’ve been keeping up with the goings on here, from yesterday’s PHP Intl Class Peer to Peer World Map Tutorial, you’ll know that we have code for the external Javascript to automatically change when a new member of “the peerage” is created, and we upload GETME files such as today’s i_variant_eg.php_GETME into place up at the RJM Programming domain as a web application

… with an updated peer to peer dropdown easily able to navigate the user to other web applications of its ilk.


Previous relevant PHP Intl Class Peer to Peer World Map Tutorial is shown below.

PHP Intl Class Peer to Peer World Map Tutorial

PHP Intl Class Peer to Peer World Map Tutorial

All the web applications in the suite of PHP intl class using web applications were capable of making a connection between …

Country Name and ISO-3166 2 letter Country Code suffixing a Locale … and … Emoji Flag

… setting our mind to an “across the board” improvement chance on top of progress up until yesterday’s PHP Intl Class Peer to Peer Serverside Tutorial.

And so, rather than change five members of “the peerage” …

  1. Sorting Words PHP code changed today this way only to reorder the external script call to be placed below the web application Javascript
  2. Language Name PHP code changed today this way only to reorder the external script call to be placed below the web application Javascript
  3. Region Name PHP code changed today this way only to reorder the external script call to be placed below the web application Javascript
  4. Currency PHP code changed today this way only to reorder the external script call to be placed below the web application Javascript
  5. Current Datetime PHP code changed today this way only to reorder the external script call to be placed below the web application Javascript

… in any major way, rather we significantly changed the one i_eg.js as per


// i_eg.js
// RJM Programming - December, 2024
// Allow for peer to peer access amongst i_eg.php i_cur_eg.php i_region_eg.php i_language_eg.php i_sort_eg.php

var thisflagiso='', thisfemoji='';
var candidates="i_eg.php i_cur_eg.php i_region_eg.php i_language_eg.php i_sort_eg.php";
var candidatesd=candidates;
var candidatesdesc="Current_Datetime Currency Region_Name Language_Name Sort_Words";
var candidatesdarr=candidates.replace(/\,/g,' ').split(' ');

var herel=location.search.split('locale=')[1] ? decodeURIComponent(location.search.split('locale=')[1].split('&')[0]) : '';

if (document.head.innerHTML.indexOf('/i_eg.js?') != -1) {
var qs=document.head.innerHTML.split('/i_eg.js?')[1].split('"')[0].split("'")[0].split(' ')[0].split('>')[0];
if (qs.replace(/^rand\=/g,'').indexOf('=') != -1) {
candidates=decodeURIComponent(document.head.innerHTML.split('/i_eg.js?')[1].split('=')[1].split('&')[0].split('#')[0].split('"')[0].split("'")[0]).replace(/\+/g,' ');
}
}

var candidatesarr=candidates.replace(/\,/g,' ').split(' ');

function jorflag(thiscc) {
var lri='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var dri=['127462','127463','127464','127465','127466','127467','127468','127469','127470','127471','127472','127473','127474','127475','127476','127477','127478','127479','127480','127481','127482','127483','127484','127485','127486','127487'];
var ccsuff='', ccchar=' ', cde='';
for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
ccsuff+=String.fromCodePoint(dri[eval('' + lri.indexOf(ccchar))]); //'&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
cde='.';
}
if ((document.URL.split('#')[0] + '&').indexOf(encodeURIComponent('_') + thiscc.toUpperCase() + '&') != -1 && herel != '') {
if (thisfemoji == '' && thisflagiso != '') {
ccsuff=ccsuff;
} else {
thisflagiso=thiscc.toUpperCase();
thisfemoji=ccsuff;
setTimeout(geochartit, 20000);
}
}
return ccsuff;
}

function geochartit() {
var hostelt='', bighostelt='', resthostelt='', prefb='', ctynameisnow='';
//alert('0ccsuff');
if (thisfemoji == '' && thisflagiso != '') {
thisfemoji=jorflag(thisflagiso);
}
if (thisfemoji != '' && thisflagiso != '') {
//alert('1ccsuff');
if (!document.getElementById('ageoc') && document.getElementsByTagName('h1')[0].innerHTML.indexOf(thisfemoji) != -1) {
//alert('2ccsuff');
if (document.getElementsByTagName('h1')[0].innerHTML.split(thisfemoji)[0].indexOf('<') != -1) {
prefb=document.getElementsByTagName('h1')[0].innerHTML.split(thisfemoji)[0];
ctynameisnow='%20in%20' + prefb.split('>')[eval(-1 + prefb.split('>').length)].trim() + '%20' + encodeURIComponent(thisfemoji);
//alert('ccsuff');
//bighostelt=document.getElementsByTagName('h1')[0].innerHTML.split('</')[0].split(thisfemoji)[0].split('<')[eval(-1 + document.getElementsByTagName('h1')[0].innerHTML.split('</')[0].split(thisfemoji)[0].split('<').length)];
bighostelt=document.getElementsByTagName('h1')[0].innerHTML.split(thisfemoji)[0].split('<')[eval(-1 + document.getElementsByTagName('h1')[0].innerHTML.split('</')[0].split(thisfemoji)[0].split('<').length)];
hostelt=bighostelt.split(' ')[0].split('>')[0];
resthostelt=document.getElementsByTagName('h1')[0].innerHTML.split(thisfemoji)[1].replace('</' + hostelt + '>', '').split('<')[0];
//alert('Resthostelt=' + resthostelt + ' and hostelt=' + hostelt + ' and bighostelt=' + bighostelt);
}
if (hostelt != '' && document.getElementsByTagName('h1')[0].innerHTML.split(thisfemoji)[0].indexOf('</') == -1) {
//alert('resthostelt=' + resthostelt + ' and hostelt=' + hostelt + ' and bighostelt=' + bighostelt);
if (resthostelt.trim() != '') {
document.getElementsByTagName('h1')[0].innerHTML=prefb + "</" + hostelt + "><a id=ageoc style=cursor:pointer;text-decoration:none; title=GeoChart onclick=\"window.open('//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Where%20Locale%20" + encodeURIComponent(herel) + "%20Lives" + ctynameisnow + "&width=556&height=347&country=Country&popularity=Popularity&data=%20[~" + thisflagiso + '~,2]' + "','_blank','top=200,left=200,width=630,height=600');\">" + thisfemoji + '</a><' + bighostelt.split('>')[0] + '>' + resthostelt + '</' + hostelt + '>';
} else {
//alert(prefb + "</" + hostelt + "><a id=ageoc style=cursor:pointer;text-decoration:none; title=GeoChart onclick=\"window.open('//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Where%20Locale%20" + encodeURIComponent(herel) + "%20Lives&width=556&height=347&country=Country&popularity=Popularity&data=%20[~" + thisflagiso + '~,2]' + "','_blank','top=100,left=100,width=600,height=600');\">" + thisfemoji + '</a>');
document.getElementsByTagName('h1')[0].innerHTML=prefb + "</" + hostelt + "><a id=ageoc style=cursor:pointer;text-decoration:none; title=GeoChart onclick=\"window.open('//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Where%20Locale%20" + encodeURIComponent(herel) + "%20Lives" + ctynameisnow + "&width=556&height=347&country=Country&popularity=Popularity&data=%20[~" + thisflagiso + '~,2]' + "','_blank','top=200,left=200,width=630,height=600');\">" + thisfemoji + '</a>';
}
//alert('0:' + resthostelt + ' ... ' + document.getElementsByTagName('h1')[0].innerHTML);
} else {
document.getElementsByTagName('h1')[0].innerHTML=document.getElementsByTagName('h1')[0].innerHTML.replace(thisfemoji, "<a style=cursor:pointer;text-decoration:none; title=GeoChart onclick=\"window.open('//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=Where%20Locale%20" + encodeURIComponent(herel) + "%20Lives&width=556&height=347&country=Country&popularity=Popularity&data=%20[~" + thisflagiso + '~,2]' + "','_blank','top=100,left=100,width=600,height=600');\">" + thisfemoji + '</a>');
thisfemoji='';
thisflagiso='';
//alert('1:' + document.getElementsByTagName('h1')[0].innerHTML);
}
}
}
}


function hthreesel() {
var icv=0, hthreesuffix='', curone='', curdesc='', compone=document.URL.split('?')[0].split('#')[0].split('/')[eval(-1 + document.URL.split('?')[0].split('#')[0].split('/').length)];
var hthreearr=document.getElementsByTagName('h3');

if (herel != '') {
var piso=herel.split('_')[eval(-1 + herel.split('_').length)];
piso=piso.split('-')[eval(-1 + piso.split('-').length)];
if (eval('' + piso.length) == 2 && piso == piso.toUpperCase()) {
thisflagiso=piso;
setTimeout(geochartit, 22000);
}
}


if (eval('' + hthreearr.length) > 0) {
if (hthreearr[0].outerHTML.indexOf('</select>') == -1 && candidates.trim() != '' && eval('' + candidatesarr.length) > 0) {
if ((' ' + candidatesd.replace(/\+/g,' ') + ' ').indexOf(' ' + compone + ' ') != -1) {
curone=compone;
//alert('1:' + compone + ' found at ' + candidatesdarr.indexOf(curone));
curdesc=candidatesdesc.split(' ')[candidatesdarr.indexOf(curone)].replace(/\_/g, ' ');
//alert(curdesc);
}
if (curone == '') {
if ((' ' + candidates.replace(/\+/g,' ') + ' ').indexOf(' ' + compone + ' ') != -1) {
curone=compone;
//alert('11:' + compone);
if (curone.indexOf('i_') == 0 && curone.indexOf('_eg.') != -1) {
curdesc=curone.split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(0,1).toUpperCase() + curone.split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(1).toLowerCase();
}
}
}

hthreesuffix='<select onchange="location.href=this.value;"><option value="' + document.URL.split('?')[0].split('#')[0] + '">Optionally select peer ' + ('to ' + curdesc).replace(/^to\ $/g, '') + ' web application below ...</option></select>';
for (icv=0; icv<candidatesarr.length; icv++) {
if (candidatesdarr.indexOf(candidatesarr[icv]) != -1) {
hthreesuffix=hthreesuffix.replace('</select>', '<option value="/' + candidatesarr[icv] + '">' + ('' + candidatesdesc.split(' ')[candidatesdarr.indexOf(candidatesarr[icv])]).replace(/\_/g,' ') + '</option></select>');
} else if (candidatesarr[icv].indexOf('i_') == 0 && curone.indexOf('_eg.') != -1) {
hthreesuffix=hthreesuffix.replace('</select>', '<option value="/' + candidatesarr[icv] + '">' + ('' + candidatesarr[icv].split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(0,1).toUpperCase() + candidatesarr[icv].split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(1).toLowerCase()).replace(/\_/g,' ') + '</option></select>');
} else {
hthreesuffix=hthreesuffix.replace('</select>', '<option value="/' + candidatesarr[icv] + '">' + candidatesarr[icv] + '</option></select>');
}
}

if (hthreesuffix != '') {
if (curone != '' && curdesc != '') {
hthreearr[0].innerHTML+='  ' + hthreesuffix.replace('</select>', '<option value="/' + curone + '">' + curdesc + '</option></select>');
} else {
hthreearr[0].innerHTML+='  ' + hthreesuffix;
}
}
}
}
}

setTimeout(hthreesel, 2000);

… featuring an overridden function jorflag which explains our reordering of script tags we’ve talked about above.

And the benefits are that wherever you see an emoji flag in a heading tag of one of “the peerage” after a while the emoji flag can be clicked to create a popup window that shows the country relevant to the Locale involved shaded on a Google Chart Geo Chart world map.


Previous relevant PHP Intl Class Peer to Peer Serverside Tutorial is shown below.

PHP Intl Class Peer to Peer Serverside Tutorial

PHP Intl Class Peer to Peer Serverside Tutorial

Sometimes, in programming …

  • you’re stringent … especially regarding security matters, but most of the time, when we organize the programming rules, so to speak, we prefer it when …
  • you’re flexible

… and so, back with GraphViz via PHP on AlmaLinux Require Once Tutorial when we used a …

  • require_once … PHP calling paradigm (we’re not going to change it, because it is still fine) … we’re wondering now, why we didn’t use an …
  • include … paradigm, because the arrangement was optional

as per

The include (or require) statement takes all the text/code/markup that exists in the specified file and copies it into the file that uses the include statement.

Including files is very useful when you want to include the same PHP, HTML, or text on multiple pages of a website.

… as with the optional nature of today’s PHP include paradigm call of a new i_eg_js.php piece of PHP we’ve decided should …

Can’t “when the need arises” be contentious?

… we hear you ask. Good question! We could jump the gun, before code is properly ready using PHP glob to look for files existant under the ./i_*eg.php file specification, and match them to what we have in the i_eg.js external Javascript, adding new entries when a mismatch is found. But that is where “local knowledge” can come into play (and the other aspect to “local knowledge” here is that the suite of PHP intl class using web applications all have a file specification suiting /i_*eg.php here). Genericity has it’s limits sometimes, in other words. Take a look at what we do to time this PHP rewrites external Javascript serverside intervention safely …

<?php

<?php
// i_eg_js.php
// RJM Programming - December, 2024
// Rewrite i_eg.js as needed

$iscand=false;
$pcont='';
$jscont='';
$phplistcomp='';
$desclistcomp='';
if (file_exists('./i_eg.js')) {
$jscont=file_get_contents('./i_eg.js');
$bitsphpa=explode(' candidates="', $jscont);
$bitsdesca=explode(' candidatesdesc="', $jscont);
if (sizeof($bitsphpa) > 1 && sizeof($bitsdesca) > 1) {
foreach (glob('./i_*eg.php') as $pfile) {
$iscand=false;
$pcont='';
if (strpos(' ' . explode('"', $bitsphpa[1])[0] . ' ', ' ' . basename($pfile) . ' ') === false) {
foreach (glob('./' . basename($pfile) . '*GETME') as $ppfile) {
$iscand=true;
}

}
if ($iscand) {
$pcont=file_get_contents('./' . basename($pfile));
if (strpos($pcont, '>Show ') === false) { $iscand=false; }
}
if ($iscand) {
$jscont=str_replace(' candidates="' . explode('"', $bitsphpa[1])[0] . '"', ' candidates="' . explode('"', $bitsphpa[1])[0] . ' ' . basename($pfile) . '"', $jscont);
$jscont=str_replace(' candidatesdesc="' . explode('"', $bitsdesca[1])[0] . '"', ' candidatesdesc="' . explode('"', $bitsdesca[1])[0] . ' ' . str_replace(' ','_',explode('"',explode('<', explode('>Show ', $pcont)[1])[0])[0]) . '"', $jscont);
file_put_contents('./i_eg.js', $jscont);
$bitsphpa=explode(' candidates="', $jscont);
$bitsdesca=explode(' candidatesdesc="', $jscont);
}
}
}
}

?>

Yes, we share via a GETME filename suffixing set of rules here at RJM Programming, and we only do that, and upload codefiles and GETME files to the RJM Programming web server via sftp means, when we’ve tested the code.

How is this new include paradigm PHP called in each PHP web application of …

  1. Sorting Words PHP code changed today this way and changed this way yesterday
  2. Language Name PHP code changed today this way and changed this way yesterday
  3. Region Name PHP code changed today this way and changed this way yesterday
  4. Currency PHP code changed today this way and changed this way yesterday
  5. Current Datetime PHP code changed today this way and changed this way yesterday

? As simple as now having …

<?php

include "i_eg_js.php";

?>

… up near the top of the PHP code and, unlike require_once these PHP suite web applications will not fall over should they not find i_eg_js.php in their same web server folder, and meaning the use of any of “the peerage” can look for new members without constantly having to update that external Javascript list, it flowing through to that dropdown, created via that external Javascript, updated, as required, by this new PHP include paradigm intervention.

Did you know?

If we’re not introducing any new PHP members of “the peerage” today, how did we test this thinking above, to our satisfaction? Simulating the scenario on our test Apache/PHP/MySql MAMP web server is how we tested it. We went, at the local macOS command line …


cp i_eg.php i_new_eg.php

… and tested, to be satisfied that the external Javascript remained unchanged, and then went …


cp i_eg.php i_new_eg.php_GETME

… to see that the external Javascript was appropriately changed, as you can see occurring in today’s tutorial picture. When happy, we undid all these changes, ready for when a new member of “the peerage” is really added, and then we’ll test further.


Previous relevant PHP Intl Class Peer to Peer Tutorial is shown below.

PHP Intl Class Peer to Peer Tutorial

PHP Intl Class Peer to Peer Tutorial

Today we’re implementing, on top of the progress of yesterday’s PHP Intl Class Word Sorting Primer Tutorial

  • a clientside (external Javascript called by the PHP) approach to gathering this PHP intl “Internationalization” class work into a suite of peer to peer web applications so that they can easily access each other rather than worrying about any web browser address bar (or bookmark) recalling of URLs in that group (once you get one under your belt, that is) … as maybe, another day, we’ll develop …
  • a serverside (PHP require/include) approach (helping out that clientside approach more generically and scientifically)

… meaning i_eg.js external Javascript …


// i_eg.js
// RJM Programming - December, 2024
// Allow for peer to peer access amongst i_eg.php i_cur_eg.php i_region_eg.php i_language_eg.php i_sort_eg.php
<>br>
var candidates="i_eg.php i_cur_eg.php i_region_eg.php i_language_eg.php i_sort_eg.php";
var candidatesd=candidates;
var candidatesdesc="Current_Datetime Currency Region_Name Language_Name Sort_Words";
var candidatesdarr=candidates.replace(/\,/g,' ').split(' ');

var candidatesarr=candidates.replace(/\,/g,' ').split(' ');

function hthreesel() {
var icv=0, hthreesuffix='', curone='', curdesc='', compone=document.URL.split('?')[0].split('#')[0].split('/')[eval(-1 + document.URL.split('?')[0].split('#')[0].split('/').length)];
var hthreearr=document.getElementsByTagName('h3');
if (eval('' + hthreearr.length) > 0) {
if (hthreearr[0].outerHTML.indexOf('</select>') == -1 && candidates.trim() != '' && eval('' + candidatesarr.length) > 0) {
if ((' ' + candidatesd.replace(/\+/g,' ') + ' ').indexOf(' ' + compone + ' ') != -1) {
curone=compone;
//alert('1:' + compone + ' found at ' + candidatesdarr.indexOf(curone));
curdesc=candidatesdesc.split(' ')[candidatesdarr.indexOf(curone)].replace(/\_/g, ' ');
//alert(curdesc);
}
if (curone == '') {
if ((' ' + candidates.replace(/\+/g,' ') + ' ').indexOf(' ' + compone + ' ') != -1) {
curone=compone;
//alert('11:' + compone);
if (curone.indexOf('i_') == 0 && curone.indexOf('_eg.') != -1) {
curdesc=curone.split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(0,1).toUpperCase() + curone.split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(1).toLowerCase();
}
}
}


hthreesuffix='<select onchange="location.href=this.value;"><option value="' + document.URL.split('?')[0].split('#')[0] + '">Optionally select peer ' + ('to ' + curdesc).replace(/^to\ $/g, '') + ' web application below ...</option></select>';
for (icv=0; icv<candidatesarr.length; icv++) {
if (candidatesdarr.indexOf(candidatesarr[icv]) != -1) {
hthreesuffix=hthreesuffix.replace('</select>', '<option value="/' + candidatesarr[icv] + '">' + ('' + candidatesdesc.split(' ')[candidatesdarr.indexOf(candidatesarr[icv])]).replace(/\_/g,' ') + '</option></select>');
} else if (candidatesarr[icv].indexOf('i_') == 0 && curone.indexOf('_eg.') != -1) {
hthreesuffix=hthreesuffix.replace('</select>', '<option value="/' + candidatesarr[icv] + '">' + ('' + candidatesarr[icv].split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(0,1).toUpperCase() + candidatesarr[icv].split('i_')[1].split('_eg.')[0].replace(/\_/g,' ').substring(1).toLowerCase()).replace(/\_/g,' ') + '</option></select>');
} else {
hthreesuffix=hthreesuffix.replace('</select>', '<option value="/' + candidatesarr[icv] + '">' + candidatesarr[icv] + '</option></select>');
}
}

if (hthreesuffix != '') {
if (curone != '' && curdesc != '') {
hthreearr[0].innerHTML+='  ' + hthreesuffix.replace('</select>', '<option value="/' + curone + '">' + curdesc + '</option></select>');
} else {
hthreearr[0].innerHTML+='  ' + hthreesuffix;
}
}
}
}
}

setTimeout(hthreesel, 2000);

… is overseeing “the peerage” …

  1. Sorting Words
  2. Language Name
  3. Region Name
  4. Currency
  5. Current Datetime

… by constructing a new dropdown means of navigating into each …


<script type=text/javascript src=/i_eg.js></script>

… of the above PHP web applications.


Previous relevant PHP Intl Class Word Sorting Primer Tutorial is shown below.

PHP Intl Class Word Sorting Primer Tutorial

PHP Intl Class Word Sorting Primer Tutorial

The PHP intl “Internationalization” class can help with an issue that has haunted me for many years. When you sort words in my English biased way, will they be sorted the same way in other languages, given alphabets and diacritics (with thanks to this excellent link regarding an example we’re defaulting to in the web application) and emojis and non-ascii characters, in various keyboard configurations, which might happen with words expressing the human condition? Luckily, the PHP intl class has

<?php

function sortit($arr, $thisloc) {
global $dias, $dia, $tabis;
$coll = collator_create( $thisloc );
//$arr = array( 'at', 'às', 'as' );
//var_export( $arr );
if (!isset($_GET['sorttype']) && !isset($_POST['sorttype'])) {
collator_sort( $coll, $arr );
} else if (isset($_GET['sorttype'])) {
if (strpos($_GET['sorttype'], 'REGULAR') !== false) {
collator_sort( $coll, $arr, Collator::SORT_REGULAR );
} else if (strpos($_GET['sorttype'], 'NUMERIC') !== false) {
collator_sort( $coll, $arr, Collator::SORT_NUMERIC );
} else if (strpos($_GET['sorttype'], 'STRING') !== false) {
collator_sort( $coll, $arr, Collator::SORT_STRING );
} else {
collator_sort( $coll, $arr );
}
} else if (isset($_POST['sorttype'])) {
if (strpos($_POST['sorttype'], 'REGULAR') !== false) {
collator_sort( $coll, $arr, Collator::SORT_REGULAR );
} else if (strpos($_POST['sorttype'], 'NUMERIC') !== false) {
collator_sort( $coll, $arr, Collator::SORT_NUMERIC );
} else if (strpos($_POST['sorttype'], 'STRING') !== false) {
collator_sort( $coll, $arr, Collator::SORT_STRING );
} else {
collator_sort( $coll, $arr );
}
}
//var_export( $arr );
for ($ij=(-1 + sizeof($arr)); $ij>=0; $ij--) {
$tabis=str_replace('<td id="sorttd">', '<td id="sorttd">' . $arr[$ij] . '<br>', $tabis);
}
echo $tabis;
}

?>

… to verify, one way or the other, and thanks to a heads up from this useful link here, further to yesterday’s PHP Intl Class Language Names Primer Tutorial.

Again, feel free to try a new “proof of concept” i_sort_eg.php Word Sorting Internationalization web application, where you can test out these concepts yourself, using your own word lists, you can enter into textarea elements.


Previous relevant PHP Intl Class Language Names Primer Tutorial is shown below.

PHP Intl Class Language Names Primer Tutorial

PHP Intl Class Language Names Primer Tutorial

You might have noticed over the last week (further to yesterday’s PHP Intl Class Region Names Primer Tutorial) or so, how useful …

Locales

… are as a data item involved with PHP intl “Internationalization” class programming work.

As an example Locale …


pt_BR

… we’ve been making quite a lot out of the “BR” ISO-3166 2 letter Country Code as the suffix of such a Locale. But what about the prefix of Locales? That prefix maps to an ISO-639 Language Code, meaning any derivable (ie. via our keyboard onkeydown and oninput logics) set of Locales could tell us (at the very least) two types of information, exemplifying the case above …

List of Countries using pt Portuguese List of Languages used in BR Brazil
pt pt_AO pt_BR pt_CH pt_CV pt_GQ pt_GW pt_LU pt_MO pt_MZ pt_PT pt_ST pt_TL es_BR pt_BR

All “code talk” above, but what about some Language Names, because you are not likely to ask down at Copacabana Beach …

Ei, cara! Você falar es?

That’s where we thank https://www.php.net/manual/en/locale.getprimarylanguage.php for the “heads up” to use code as per the followup to $lochelper and $lochelpertwo data flows to help with these Language Name determinations …

<?php

$locsel='';
$altinlang='';
$locit=user_agent();
$arrl=ResourceBundle::getLocales('');
for ($df=0; $df<sizeof($arrl); $df++) {
$endih='';
$lastword=explode('_',$arrl[$df])[-1 + sizeof(explode('_',$arrl[$df]))];
$isalt=false;
if (isset($_GET['languagecode'])) {
if (strlen($_GET['languagecode']) > 0) {
if ($lastword == $_GET['languagecode']) { $isalt=true; }
}
} else if (isset($_POST['languagecode'])) {
if (strlen($_POST['languagecode']) > 0) {
if ($lastword == $_POST['languagecode']) { $isalt=true; }
}
}
$ends=explode("['" . explode('-',explode('_',$arrl[$df])[0])[0] . '-', $lochelper);
if (sizeof($ends) > 1) {
$endih.=' ' . explode("'", explode("['", $ends[0])[-1 + sizeof(explode("['", $ends[0]))])[0];
if (explode("'", explode("['", $ends[0])[-1 + sizeof(explode("['", $ends[0]))])[0] != '') {
$inlang=' is ' . explode("'", explode("['", $ends[0])[-1 + sizeof(explode("['", $ends[0]))])[0];
if ($isalt) { $altinlang=' is ' . explode("'", explode("['", $ends[0])[-1 + sizeof(explode("['", $ends[0]))])[0]; }
}
}
if (strpos($lochelpertwo, '>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>') !== false) {
//echo "yes " . explode('-',explode('_',$arrl[$df])[0])[0] . "\n<br>";
//echo substr(explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0], -250,250);
$interim=explode('</a>', explode('<tr', explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0])[-1 + sizeof(explode('<tr', explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0]))])[0]; //)[-1 + sizeof(explode('>', explode('</td>', explode('<tr', explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0];
//exit;
//if ($isalt) { echo $interim; exit; }
$aintm=explode('>', str_replace('</a>','',$interim))[-1 + sizeof(explode('>', str_replace('</a>','',$interim) ))];
//if ($isalt) { echo $interim . '<br>' . $aintm . '<br>' . $endih; exit; }
if (strpos($endih, ' ' . $aintm) === false) {
if ($endih != '') {
$endih.=' (' . $aintm . ')';
$inlang=' is ' . $aintm;
if ($isalt) {
//echo "yes " . explode('-',explode('_',$arrl[$df])[0])[0] . "\n<br>";
if ($altinlang != '') {
$altinlang.=' (' . $aintm . ')';
} else {
$altinlang=' is ' . $aintm;
}
}
} else {
$endih.=' ' . $aintm;
if ($isalt) {
//echo "Yes " . explode('-',explode('_',$arrl[$df])[0])[0] . "\n<br>";
if ($altinlang != '') {
$altinlang.=' (' . $aintm . ')';
} else {
$altinlang=' is ' . $aintm;
}
}
}
}
}
if ($lastword == strtoupper($lastword) && strlen($lastword) == 2) {
$endih.=' ' . orflag($lastword);
}
if ($endih != '') {
$endih="\t" . $endih . '';
}
if (strpos(($arrl[$df] . '_'), '_') !== false) { //} && strpos($arrl[$df], '0') === false) {
if ($locsel == '') {
$locsel="<select ontouchdown=ots(event); onchange=\"if (this.value.trim().length != 0) { document.getElementById('locale').value=(this.value); document.getElementById('justincase').src=document.URL.split('?')[0].split('#')[0] + '?ccode=' + this.value.split('_')[0].split('-')[0]; }\" id=locsel>
<option id=\"loptone\" value=''>Optionally select a Locale below ...</option></select>";
}
if ($locit != 'pc' && 1 == 1) {
$locsel=str_replace("</select>", "
<option value='" . $arrl[$df] . "' translate=\"no\" data-ontouchstart=ots(event); title=\"" . $endih . "\">" . $arrl[$df] . ' ' . $endih . "</option></select>", $locsel);
} else {
$locsel=str_replace("</select>", "
<option value='" . $arrl[$df] . "' translate=\"no\" data-ontouchstart=ots(event); title=\"" . $endih . "\">" . $arrl[$df] . "</option></select>", $locsel);
}
}
}

?>

So, feel free to try a new “proof of concept” i_language_eg.php Language Names Internationalization web application.


Previous relevant PHP Intl Class Region Names Primer Tutorial is shown below.

PHP Intl Class Region Names Primer Tutorial

PHP Intl Class Region Names Primer Tutorial

Apart from Ghostbusters who do you turn to when you want to know what a resident of a region calls their region?

Still, Ghostbusters, you must be pulling my leg?!

Anyway, further to yesterday’s PHP Intl Class Currency Primer Tutorial, we’ve turned to good ol’ PHP.net, as usual (when it comes to many matters PHP).

In amongst all the ISO code usage we seek when interfacing to the PHP intl “Internationalization” class, because they are definitive, even so, we feel we need to allow users to enter Country Names, as one concept, especially as Country Names have been there before any ISO codes even started. The trouble with Country Names is twofold …

  • it is not a reliable indexer, if you get my drift, because there are lots of forms, in any language you pick, for what a Country Name is
  • at least for an English representation of a Country Name we’d like consistency, and, happily, the PHP intl “Internationalization” class can provide it

… via PHP code of the ilk …

<?php

echo "<p id=pdfmt>" . locale_get_display_region(urldecode($_GET['locale']), urldecode($_GET['displaylocale'])) . "</p><br>";

?>

As you might imagine, this discovery can have mildly wide ranging implications … well, you had to be there … on …

…PHP intl class suite of web applications we’re not letting Ghostbusters anywhere near!


Previous relevant PHP Intl Class Currency Primer Tutorial is shown below.

PHP Intl Class Currency Primer Tutorial

PHP Intl Class Currency Primer Tutorial

We’re back with the PHP intl “Internationalization” class, today, last talked about with the recent PHP Intl Class Datetime Keyboard Events Tutorial, this time discussing …

Currency Internationalization

… topics. Again, we found the Locale data item, as with Datetimes, the main data item of interest. But, any one Country can use more than one Currency (defined by an ISO-4217 3 letter Currency Code) in this new PHP Intl using Currency web application we’ve started developing today, and on a Locale selection we choose the first such one, and leave it open to the user to be able to type in their own ISO-4217 three letter Currency Code, as required.

We got great help from https://stackoverflow.com/questions/76825595/php-format-currency-issue with codeline ideas, such as …

<?php

$formatter = new NumberFormatter(urldecode($_GET['locale']), NumberFormatter::CURRENCY);
if (isset($_GET['amount'])) {
echo "<p id=pdfmt>" . $formatter->formatCurrency(urldecode($_GET['amount']), urldecode($_GET['currency'])) . "</p><br>";
} else {
echo "<p id=pdfmt>" . $formatter->formatCurrency(76543.210, urldecode($_GET['currency'])) . "</p><br>";
}

?>

The work of Datetimes, ahead of all this, has meant it is easier to get “further down the track” for today’s “proof of concept” i_cur_eg.php PHP code start, that has keyboard event and dropdown logics all in there, and which you can try below …


Previous relevant PHP Intl Class Datetime Keyboard Events Tutorial is shown below.

PHP Intl Class Datetime Keyboard Events Tutorial

PHP Intl Class Datetime Keyboard Events Tutorial

As far as “user interaction” goes with our Current Datetime PHP web application of PHP Intl Class Datetime Google Translate Tutorial we’ve been thinking …

  • the user would be more likely to use the dropdown element selection methods … but supposing …
  • the user uses the keyboard to enter Locale and/or Timezone

… and, as of yesterday’s logic, that would have been quite unwieldy, especially regarding timezone entries.

And so, today, we’ve added keyboard onkeydown and oninput event logics to cater for several scenarios we can “shortcut” those user requirements, often down to the entry of a couple or a few characters, and from there click appropriate created links in …

<?php echo ”

var morechanges=true;
var lastwo='';
var woi=null;
var oko=null;
var nlastokn='';
var xokn='';
var xlastconto=[];
var xmorechanges=true;
var xlastwo='';
var xwoi=null;
var xoko=null;

function precval(iois) {
//okn=iois.value;
oko=iois;
lastokn=okn;
}

function xprecval(iois) {
//okn=iois.value;
xoko=iois;
xlastokn=xokn;
}

function cval(eiois) {
//if (document.URL.indexOf('i0=') == -1) {
//if (eiois.which != 16) { alert('2:' + eiois.which); }
//okn+=String.fromCharCode(eiois.which || eiois.keyCode);
if ((eiois.which || eiois.keyCode) == 8) {
okn='';
} else if ((eiois.which || eiois.keyCode) == 186 || (eiois.which || eiois.keyCode) == 900000016) {
okn=okn.replace(':','') + ':';
//document.title=okn + ' ' + (eiois.which || eiois.keyCode);
var cvi=okn.split(':');
if (cvi.length > 1) {
var scs=0.0, factor=1.0;
for (var ij=eval(-1 + cvi.length); ij>=0; ij--) {
if (cvi[ij] == '') cvi[ij]='00';
scs+=eval(factor * eval(cvi[ij]));
factor*=60.0;
}
//alert(scs + ' ' + okn);
okn='' + scs;
oko.value=okn;
lastokn=okn.replace(':','');
//document.title=okn + ' ' + (eiois.which || eiois.keyCode) + ' ' + oko.value;
//setTimeout(fixval,30);
}
} else if ((eiois.which || eiois.keyCode) == 191) {
if (!eiois.shiftKey) {
okn+=String.fromCharCode(47);
//document.title='=1:' + okn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
}
if (eval('' + okn.length) > 1) { expandokn(); }
} else if ((eiois.which || eiois.keyCode) == 189) {
if (eiois.shiftKey) {
okn+=String.fromCharCode(95);
} else {
okn+=String.fromCharCode(45);
}
if (eval('' + okn.length) > 1) { expandokn(); }
//document.title='=1:' + okn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
} else if (eiois.keyCode == 189 || (eiois.which || eiois.keyCode) >= 65 && (eiois.which || eiois.keyCode) <= 90) {
if (eiois.shiftKey) {
okn+=String.fromCharCode(eiois.which || eiois.keyCode);
} else {
okn+=String.fromCharCode(eval(32 + eval(eiois.which || eiois.keyCode)));
}
//document.title='=1:' + okn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
if (eval('' + okn.length) > 1) { expandokn(); }
} else if ((eiois.which || eiois.keyCode) < 46 || (eiois.which || eiois.keyCode) > 58) {
okn=okn;
} else if (1 == 3) {
okn+=String.fromCharCode(eiois.which || eiois.keyCode);
document.title+='=1:' + okn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
}
//}
}

function xcval(eiois) {
//if (document.URL.indexOf('i0=') == -1) {
//if (eiois.which != 16) { alert('1:' + eiois.which); }
//xokn+=String.fromCharCode(eiois.which || eiois.keyCode);
if ((eiois.which || eiois.keyCode) == 8) {
xokn='';
} else if ((eiois.which || eiois.keyCode) == 186 || (eiois.which || eiois.keyCode) == 900000016) {
xokn=xokn.replace(':','') + ':';
//document.title=okn + ' ' + (eiois.which || eiois.keyCode);
var cvi=xokn.split(':');
if (cvi.length > 1) {
var scs=0.0, factor=1.0;
for (var ij=eval(-1 + cvi.length); ij>=0; ij--) {
if (cvi[ij] == '') cvi[ij]='00';
scs+=eval(factor * eval(cvi[ij]));
factor*=60.0;
}
//alert(scs + ' ' + okn);
xokn='' + scs;
xoko.value=xokn;
xlastokn=xokn.replace(':','');
//document.title=okn + ' ' + (eiois.which || eiois.keyCode) + ' ' + oko.value;
//setTimeout(fixval,30);
}
} else if ((eiois.which || eiois.keyCode) == 191) {
if (!eiois.shiftKey) {
xokn+=String.fromCharCode(47);
//document.title='=2:' + xokn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
}
if (eval('' + xokn.length) > 1) { expandxokn(); }
} else if ((eiois.which || eiois.keyCode) == 189) {
if (eiois.shiftKey) {
xokn+=String.fromCharCode(95);
} else {
xokn+=String.fromCharCode(45);
}
if (eval('' + xokn.length) > 1) { expandxokn(); }
//document.title='=2:' + xokn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
} else if (eiois.keyCode == 189 || (eiois.which || eiois.keyCode) >= 65 && (eiois.which || eiois.keyCode) <= 90) {
if (eiois.shiftKey) {
xokn+=String.fromCharCode(eiois.which || eiois.keyCode);
} else {
xokn+=String.fromCharCode(eval(32 + eval(eiois.which || eiois.keyCode)));
}
if (eval('' + xokn.length) > 1) { expandxokn(); }
//document.title='=2:' + xokn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
} else if ((eiois.which || eiois.keyCode) < 46 || (eiois.which || eiois.keyCode) > 58) {
xokn=xokn;
} else if (1 == 3) {
xokn+=String.fromCharCode(eiois.which || eiois.keyCode);
document.title+='=' + xokn + '+' + eiois.which + ' ' + eiois.keyCode + ' ... ';
}
//}
}

function expandokn() {
var iut=0, pls=[],firsttz='',tzsih='',xtzsih='',thatloc='', wds=[];
if (okn.substring(0,1) == okn.substring(0,1).toUpperCase() && okn != okn.toUpperCase()) {
document.getElementById('das').innerHTML='Country Name<br>';
pls=ctynames.split('>' + okn);
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut++) {
document.getElementById('das').innerHTML+=' <a onclick=analp(this,0); title=' + pls[eval(-1 + iut)].slice(-4) + ' style=cursor:pointer;text-decoration:underline;>' + okn + pls[iut].split('<')[0] + ' ' + jorflag(pls[eval(-1 + iut)].slice(-3).substring(0,2)) + '</a>';
}
}
} else if (okn.substring(0,1) == okn.substring(0,1).toLowerCase() && okn == okn.toLowerCase()) {
xtzsih=document.getElementById('tzsel').innerHTML;
document.getElementById('das').innerHTML+='<br><br>Locale<br>';
tzsih=document.getElementById('locsel').innerHTML;
//alert(tzsih.length);
pls=tzsih.split( value='\"' + okn);
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut++) {
thatloc=pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0];
wds=thatloc.split('_');
if (eval('' + wds[eval(-1 + wds.length)].length) == 2 && wds[eval(-1 + wds.length)] == wds[eval(-1 + wds.length)].toUpperCase() && eval('' + wds.length) > 1) {
//alert('1:' + wds[eval(-1 + wds.length)]);
firsttz='';
if (xtzsih.indexOf(',' + wds[eval(-1 + wds.length)] + ',') != -1) {
firsttz=xtzsih.split(',' + wds[eval(-1 + wds.length)] + ',')[1].split('>')[1].split('<')[0].split(' ')[0];
//alert('2:' + firsttz);
}
document.getElementById('das').innerHTML+=' <a onclick=analr(this,\"' + firsttz + '\"); style=cursor:pointer;text-decoration:underline;>' + thatloc + ' ' + jorflag(wds[eval(-1 + wds.length)]) + '</a>';
} else {
document.getElementById('das').innerHTML+=' <a onclick=analr(this,\"\"); style=cursor:pointer;text-decoration:underline;>' + thatloc + '</a>';
}
}
}

} else if (okn.substring(0,1) == okn.substring(0,1).toUpperCase() && okn == okn.toUpperCase() && eval('' + okn.length) == 2) {
document.getElementById('das').innerHTML='Country Name<br>';
pls=ctynames.split(\"'\" + okn + \"'>\");
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut++) {
document.getElementById('das').innerHTML+=' <a onclick=analp(this,0); title=' + okn + ' style=cursor:pointer;text-decoration:underline;>' + pls[iut].split('<')[0] + ' ' + jorflag(okn) + '</a>';
}
}

tzsih=document.getElementById('tzsel').innerHTML;
if (tzsih.indexOf(',' + okn + ',') != -1) {
firsttz=tzsih.split(',' + okn + ',')[1].split('>')[1].split('<')[0].split(' ')[0];
}
document.getElementById('das').innerHTML+='<br><br>Locale<br>';
tzsih=document.getElementById('locsel').innerHTML;
//alert(tzsih.length);
pls=tzsih.split('_' + okn + '\"');
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut++) {
document.getElementById('das').innerHTML+=' <a onclick=analr(this,\"' + firsttz + '\"); style=cursor:pointer;text-decoration:underline;>' + pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0] + ' ' + jorflag(okn) + '</a>';
}
}

}
}

function expandxokn() {
var iut=0, pls=[], tzsih='', thattz='';
if (xokn.substring(0,1) == xokn.substring(0,1).toUpperCase() && xokn != xokn.toUpperCase()) {
document.getElementById('das').innerHTML='TimeZone Place Name<br>';
tzsih=document.getElementById('tzsel').innerHTML;
//alert(tzsih.length);
pls=tzsih.split('/' + xokn);
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut+=2) {
if (pls[iut].split('\"')[0].indexOf('/') == -1) {
thattz=pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0].split('/' + xokn)[0] + '/' + xokn + pls[iut].split('\"')[0];
if (eval('' + tzsih.split(thattz)[1].split(' data-geo=')[1].split(',').length) > 3) {
document.getElementById('das').innerHTML+=' <a onclick=analo(this); style=cursor:pointer;text-decoration:underline;>' + pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0].split('/' + xokn)[0] + '/' + xokn + pls[iut].split('\"')[0] + ' ' + jorflag(tzsih.split(thattz)[1].split(' data-geo=')[1].split(',')[3]) + '</a>';
} else {
document.getElementById('das').innerHTML+=' <a onclick=analo(this); style=cursor:pointer;text-decoration:underline;>' + pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0].split('/' + xokn)[0] + '/' + xokn + pls[iut].split('\"')[0] + '</a>';
}
}
}
}
document.getElementById('das').innerHTML+='<br><br>Country Name<br>';
pls=ctynames.split('>' + xokn);
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut++) {
document.getElementById('das').innerHTML+=' <a onclick=analp(this,1); title=' + pls[eval(-1 + iut)].slice(-4) + ' style=cursor:pointer;text-decoration:underline;>' + xokn + pls[iut].split('<')[0] + ' ' + jorflag(pls[eval(-1 + iut)].slice(-3).substring(0,2)) + '</a>';
}
}
}
}

function analr(ao,tzi) { // locale
if (ao.innerHTML.indexOf('_') != -1) {
document.getElementById('locsel').value=ao.innerHTML.split(' ')[0];
document.getElementById('locale').value=ao.innerHTML.split(' ')[0];
document.getElementById('timezone').value=tzi.split(' ')[0];
document.getElementById('das').innerHTML='';
okn='';
}
}

function analq(ao,tzi) { // locale
if (ao.innerHTML.indexOf('_') != -1) {
document.getElementById('locsel').value=ao.innerHTML.split(' ')[0];
document.getElementById('locale').value=ao.innerHTML.split(' ')[0];
document.getElementById('timezone').value=tzi.split(' ')[0];
document.getElementById('das').innerHTML='';
xokn='';
okn='';
}
}

function analo(ao) { // timezone places
if (ao.innerHTML.indexOf('/') != -1) {
document.getElementById('tzsel').value=ao.innerHTML.split(' ')[0];
document.getElementById('timezone').value=ao.innerHTML.split(' ')[0];
document.getElementById('das').innerHTML='';
xokn='';
}
}

function analp(ao,isxokn) { // country names
var tzsih='',pls=[],iut=0, firsttz='', thattz='';
if (ao.innerHTML.indexOf('/') != -1) {
document.getElementById('tzsel').value=ao.innerHTML.split(' ')[0];
document.getElementById('timezone').value=ao.innerHTML.split(' ')[0];
document.getElementById('das').innerHTML='';
if (isxokn != 0) {
xokn='';
} else {
okn='';
}
} else {
document.getElementById('das').innerHTML+='<br><br>TimeZone Place Name<br>';
tzsih=document.getElementById('tzsel').innerHTML;
//alert(tzsih.length);
pls=tzsih.split(',' + ao.title.split(' ')[0] + ',');
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut++) {
if (firsttz == '') { firsttz=pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0]; }
document.getElementById('das').innerHTML+=' <a onclick=analo(this); style=cursor:pointer;text-decoration:underline;>' + pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0] + ' ' + jorflag(ao.title.split(' ')[0]) + '</a>';
}
}

document.getElementById('das').innerHTML+='<br><br>Locale<br>';
tzsih=document.getElementById('locsel').innerHTML;
//alert(tzsih.length);
pls=tzsih.split('_' + ao.title.split(' ')[0] + '\"');
if (eval('' + pls.length) > 1) {
//alert('here');
for (iut=1; iut<pls.length; iut++) {
document.getElementById('das').innerHTML+=' <a onclick=analq(this,\"' + firsttz + '\"); style=cursor:pointer;text-decoration:underline;>' + pls[iut].split('>')[1].split('<')[0].split(' ')[0].split('+')[0] + ' ' + jorflag(ao.title.split(' ')[0]) + '</a>';
}
}

xokn='';
}
}

“; ?>

… in further changed latest draft PHP code offering here, as a PHP web application, you can also try below.


Previous relevant PHP Intl Class Datetime Google Translate Tutorial is shown below.

PHP Intl Class Datetime Google Translate Tutorial

PHP Intl Class Datetime Google Translate Tutorial

The Internationalization improvements of yesterday’s PHP Intl Class Datetime Clock Tutorial get another boost today via the inclusion of some interfacing to the great …


Google Translate

… for those incidental translations regarding …

  • titles and headings
  • dropdown instructions

… while avoiding what might add confusion, that being any translation of user web application settings, as you might get … you being the user … that is!

But we ask first on this. And when it is the case for asking here, a useful mechanism can be the HTML input type=checkbox element which now feeds into the Javascript below …

<?php echo ”

function parhelp() {
" . $gone . "
}

function storeinnertexts() {
if (!document.getElementById('translate').checked) { return ''; }
if (!allowanyway) {
if (document.getElementById('locale').value == '') { return ''; }
if (document.getElementById('timezone').value == '') { return ''; }
}
var bcols=['yellow','yellow','white','#ffffff'];
var idcnt=0;
var seclet=['h translate=\"no\"','d','h translate=\"no\"','d','d translate=\"no\"','d','d','d'];
var inb='', ina='</span>';
var krow=0;
var itsare=['locale','loptone','timezone','toptone','calendar','calone','doneb','Clock'], thisrowis='';
var h1toform='<html><head><body>' + document.body.innerHTML.split('<form')[0] + '<br><table style=width:100%; border=2></table></body></html>';
for (var iuyt=0; iuyt<itsare.length; iuyt+=2) {
thisrowis='<tr style=background-color:' + bcols[krow] + ';></tr>';
thisrowis='<tr></tr>';
tdsuff='';
inb='<span>';
if (eval('' + seclet[idcnt].length) > 1) {
inb='<span' + seclet[idcnt].substring(1) + '>';
}
if (bcols[krow] == '#ffffff') {
tdsuff=' style=background-color:lightgreen;'
}
if (document.getElementById(itsare[iuyt]).value.trim() != '' || 1 == 1) {
thisrowis=thisrowis.replace('</tr>', '<t' + seclet[idcnt].substring(0,1) + '>' + inb + (inb == '<span>' ? document.getElementById(itsare[iuyt]).value : '') + ina + '</t' + seclet[idcnt].substring(0,1) + '></tr>');
} else {
thisrowis=thisrowis.replace('</tr>', '<t' + seclet[idcnt].substring(0,1) + '>' + inb + (inb == '<span>' ? document.getElementById(itsare[iuyt]).placeholder : '') + ina + '</t' + seclet[idcnt].substring(0,1) + '></tr>');
}
idcnt++;
if (bcols[krow] == '#ffffff') {
tdsuff=' style=background-color:#f0f0f0;'
}
inb='<span>';
if (eval('' + seclet[idcnt].length) > 1) {
inb='<span' + seclet[idcnt].substring(1) + '>';
}
if (itsare[eval(1 + iuyt)] == itsare[eval(1 + iuyt)].toLowerCase()) {
try {
if (document.getElementById(itsare[eval(1 + iuyt)]).innerText.trim() != '') {
//if (doseti == 1) { alert(document.getElementById(itsare[eval(1 + iuyt)]).innerText); }
thisrowis=thisrowis.replace('</tr>', '<t' + seclet[idcnt].substring(0,1) + '>' + inb + (inb == '<span>' ? document.getElementById(itsare[eval(1 + iuyt)]).innerText : '') + ina + '</t' + seclet[idcnt].substring(0,1) + '></tr>');
}
} catch(erty) { alert(itsare[eval(1 + iuyt)]); }
} else {
if (document.getElementById(itsare[eval(1 + iuyt)].toLowerCase()).value.trim() != '') {
thisrowis=thisrowis.replace('</tr>', '<t' + seclet[idcnt].substring(0,1) + '>' + inb + (inb == '<span>' ? document.getElementById(itsare[eval(1 + iuyt)].toLowerCase()).value : '') + ina + '</t' + seclet[idcnt].substring(0,1) + '></tr>');
} else {
thisrowis=thisrowis.replace('</tr>', '<t' + seclet[idcnt].substring(0,1) + '>' + inb + (inb == '<span>' ? document.getElementById(itsare[eval(1 + iuyt)].toLowerCase()).placeholder : '') + ina + '</t' + seclet[idcnt].substring(0,1) + '></tr>');
}
}
idcnt++;
krow++;
h1toform=h1toform.replace('</table>', thisrowis + '</table>');
}
//if (doseti == 1) { alert(h1toform); }
h1toform=h1toform.replace(/Optionally\ select\ /g, '*');
h1toform=h1toform.replace(/Show\ Current\ Time/g, '@');
h1toform=h1toform.replace('RJM Programming - December, 2024', '$');
h1toform=h1toform.replace('As per (white background textboxes optional) ...', '!');
h1toform=h1toform.replace(/\<br\>/g, '');
h1toform=h1toform.replace('<span translate=\"no\"></span>', '');
h1toform=h1toform.replace('<span translate=\"no\"></span>', '');
//if (doseti == 1) { var tyr=prompt('' + (documentURL.split('?')[0] + '?sra=' + encodeURIComponent(sra) + '&it=' + encodeURIComponent(h1toform) + '&rand=' + Math.floor(Math.random() * 1987865)).length + ' ' + h1toform.replace(/\<\//g, String.fromCharCode(10) + '</'), h1toform.replace(/\<\//g, String.fromCharCode(10) + '</')); }
document.getElementById('setiif').src=documentURL.split('?')[0] + '?sra=' + encodeURIComponent(sra) + '&it=' + encodeURIComponent(h1toform) + '&rand=' + Math.floor(Math.random() * 1987865);
doseti++;
return '';
}

function setitranslate() {
if (doseti == 0) {
doseti=1;
setInterval(storeinnertexts, 2000);
}
}

“; ?>

… and the PHP …

<?php

$gtwo='';
$delthis='';
$optcnt=0;

if (isset($_GET['timezone'])) {
$_GET['timezone']=explode('%20',explode('+', $_GET['timezone'])[0])[0];
} else if (isset($_POST['timezone'])) {
$_POST['timezone']=explode('%20',explode('+', $_POST['timezone'])[0])[0];
}

function user_agent() { // thanks to https://stackoverflow.com/questions/6322112/check-if-php-page-is-accessed-from-an-ios-device/6322131
$iPod = strpos($_SERVER['HTTP_USER_AGENT'],"iPod");
$iPhone = strpos($_SERVER['HTTP_USER_AGENT'],"iPhone");
$iPad = strpos($_SERVER['HTTP_USER_AGENT'],"iPad");
$android = strpos($_SERVER['HTTP_USER_AGENT'],"Android");
//file_put_contents('./public/upload/install_log/agent',$_SERVER['HTTP_USER_AGENT']);
if ($iPad||$iPhone||$iPod) {
return 'ios';
} else if ($android) {
return 'android';
} else {
return 'pc';
}
}

function server_remote_addr() {
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if (1 == 1) {
if(preg_match('/(chromium)[ \/]([\w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ \/]([\w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ \/]([\w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ \/]([\w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ \/]([\w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ \/]([\w.]+)/', $ua))
$rma = '0'.$rma;
}
return str_replace(':','_',str_replace('.','_',$rma));
}

if (isset($_GET['sra']) && isset($_GET['it'])) {
//if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_GET['sra'])) . '.html')) {
// exec('rm -f ' . $_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_GET['sra'])) . '.html');
//}
$wopenit=false;
if (!file_exists($_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_GET['sra'])) . '.html')) {
$wopenit=true;
}
$cont=str_replace('+',' ',urldecode($_GET['it']));
$cont=str_replace('*', 'Optionally select ', $cont);
$cont=str_replace('@', 'Show Current Time', $cont);
$cont=str_replace('$', 'RJM Programming - December, 2024', $cont);
$cont=str_replace('!', 'As per (white background textboxes optional) ...', $cont);
$cont=str_replace('</body>', '<style> th { background-color:yellow; } </style></body>', $cont);
file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_GET['sra'])) . '.html', $cont);
if ($wopenit) {
echo "<html><body onload=\" parent.parhelp(); \"></body></html>";
}
exit;
} else if (isset($_POST['sra']) && isset($_POST['it'])) {
//if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_POST['sra'])) . '.html')) {
// exec('rm -f ' . $_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_POST['sra'])) . '.html');
//}
$wopenit=false;
if (!file_exists($_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_POST['sra'])) . '.html')) {
$wopenit=true;
}
$cont=str_replace('+',' ',urldecode($_POST['it']));
$cont=str_replace('*', 'Optionally select ', $cont);
$cont=str_replace('@', 'Show Current Time', $cont);
$cont=str_replace('$', 'RJM Programming - December, 2024', $cont);
$cont=str_replace('!', 'As per (white background textboxes optional) ...', $cont);
$cont=str_replace('</body>', '<style> th { background-color:yellow; } </style></body>', $cont);
file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/html_intl_' . str_replace('+',' ',urldecode($_POST['sra'])) . '.html', $cont);
if ($wopenit) {
echo "<html><body onload=\" parent.parhelp(); \"></body></html>";
}
exit;
}

$gone="\n setTimeout(function(){ if ((document.getElementById('locale').value + document.getElementById('locale').placeholder).split('_')[0].split('-')[0] != 'en') { gtwoo=window.open('https://www-rjmprogramming-com-au.translate.goog/html_intl_" . server_remote_addr() . ".html?_x_tr_sch=https&_x_tr_sl=en&_x_tr_tl=' + (document.getElementById('locale').value + document.getElementById('locale').placeholder).split('_')[0].split('-')[0] + '&_x_tr_hl=en','_blank','top=200,left=' + eval(-500 + eval('' + screen.width)) + ',width=500,height=500'); } }, 7000); \n";

// https://www-rjmprogramming-com-au.translate.goog/PHP/GeoChart/image_chart.php?_x_tr_sch=https&_x_tr_sl=en&_x_tr_tl=it&_x_tr_hl=en
if (isset($_GET['translate']) && isset($_GET['locale'])) {
if (strlen($_GET['locale']) > 0) {
$delthis=$_SERVER['DOCUMENT_ROOT'] . "/html_intl_" . server_remote_addr() . ".html";
if (explode('-',explode('_',urldecode($_GET['locale']))[0])[0] != 'en') {
$gtwo="\n setTimeout(function(){ gtwoo=window.open('https://www-rjmprogramming-com-au.translate.goog/html_intl_" . server_remote_addr() . ".html?_x_tr_sch=https&_x_tr_sl=en&_x_tr_tl=" . explode('-',explode('_',urldecode($_GET['locale']))[0])[0] . "&_x_tr_hl=en','_blank','top=200,left=' + eval(-500 + eval('' + screen.width)) + ',width=500,height=500'); }, 7000); \n";
}
}
} else if (isset($_POST['translate']) && isset($_POST['locale'])) {
if (strlen($_POST['locale']) > 0) {
$delthis=$_SERVER['DOCUMENT_ROOT'] . "/html_intl_" . server_remote_addr() . ".html";
if (explode('-',explode('_',urldecode($_POST['locale']))[0])[0] != 'en') {
$gtwo="\n setTimeout(function(){ gtwoo=window.open('https://www-rjmprogramming-com-au.translate.goog/html_intl_" . server_remote_addr() . ".html?_x_tr_sch=https&_x_tr_sl=en&_x_tr_tl=" . explode('-',explode('_',urldecode($_POST['locale']))[0])[0] . "&_x_tr_hl=en','_blank','top=200,left=' + eval(-500 + eval('' + screen.width)) + ',width=500,height=500'); }, 7000); \n";
}
}
}

?>

… to make this a possibility in a changed “fourth draft” PHP code offering here, as a PHP web application, you can also try below.


Previous relevant PHP Intl Class Datetime Clock Tutorial is shown below.

PHP Intl Class Datetime Clock Tutorial

PHP Intl Class Datetime Clock Tutorial

Yesterday’s PHP Intl Class Datetime Defaults Tutorial‘s PHP web application involves …

  • timezones … and, for us, whenever that happens, our eyes light up with “possibility” because …
  • “where” meets “when” … when you have timezones involved … and to our mind …
  • “where” and “when” are the best catered for “adverbs” in the I.T. wooooorrrrlllldddd

Invariably, too, the data is “full of possibility” regarding simple ideas of “internationalization” that are easy to deploy, such as …

  • emoji flags
  • Wikipedia lookups in the form of tabulated lists

And so, though our last web application is not totally disengageable from our English bias, we can help its “Internationalization Credentials” today, via …

  • emoji flag code …
    PHP
    <?php

    function orflag($incc) {
    $uretv='';
    $lri=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P", "Q","R","S","T","U","V","W","X","Y","Z"];
    $dri=["127462","127463","127464","127465","127466","127467","127468", "127469","127470","127471","127472","127473","127474","127475", "127476","127477","127478","127479","127480","127481", "127482","127483","127484","127485","127486","127487"];
    for ($jjm=0; $jjm<strlen($incc); $jjm++) {
    for ($jm=0; $jm<sizeof($lri); $jm++) {
    if (strtoupper(substr(substr($incc,$jjm),0,1)) == $lri[$jm]) {
    $uretv.='&#' . $dri[$jm] . ";";
    }
    }
    }
    return $uretv;
    }

    ?>
    Javascript
    <?php echo ”

    function jorflag(thiscc) {
    var lri='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var dri=['127462','127463','127464','127465','127466','127467','127468', '127469','127470','127471','127472','127473','127474', '127475','127476','127477','127478','127479','127480', '127481','127482','127483','127484','127485','127486','127487'];
    var ccsuff='', ccchar=' ', cde='';
    for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
    ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
    ccsuff+=String.fromCodePoint(dri[eval('' + lri.indexOf(ccchar))]); //'&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
    cde='.';
    }
    return ccsuff;
    }

    “; ?>
  • new clock functionality (using an Internationalization emoji usage regarding an SVG based button background image) and known timezone reasons to tabulate …
    <?php

    $tabp='';
    $tabs='';
    if (isset($_GET['timezone'])) {
    $tabp='<table style=width:100%;><tr><td style=vertical-align:top;>';
    $tabs='</td><td style=vertical-align:top;width:50%;><iframe src="/HTMLCSS/colour_wheel.html?mode=' . $_GET['timezone'] . '" style=width:100%;height:800px;></iframe></td></tr></table>';
    } else if (isset($_POST['timezone'])) {
    $tabp='<table style=width:100%;><tr><td style=vertical-align:top;>';
    $tabs='</td><td style=vertical-align:top;width:50%;><iframe src="/HTMLCSS/colour_wheel.html?mode=' . $_POST['timezone'] . '" style=width:100%;height:800px;></iframe></td></tr></table>';
    }
    $revealp='';
    $reveals='';
    $clockcss='';
    $clocksvg="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewport='0 0 100 100' style='font-family:Verdana;font-size:10px;'><text y='50%'>\\0023f0</text></svg>";

    if (isset($_GET['clock']) || isset($_POST['clock'])) {
    $revealp='<details title="Form you can use to display different time or different clock"><summary title="Form you can use to display different time or different clock"></summary>' . $tabp;
    $reveals=$tabs . '</details>';
    $clockcss="\n #pdfmt { border-radius: 50px; } \n";
    } else {
    $revealp=$tabp;
    $reveals=$tabs;
    }

    ?>

  • document.body onload emoji flag application (via Javascript) …
    <?php echo ”

    function onlit() {
    txils=parent.document.getElementById('tzsel').innerHTML.split(' value=\"' + thistz + '\"');
    if (eval('' + txils.length) > 1) {
    isov=txils[1].split('>')[0].split(',')[3];
    cnb='';
    if (ctynames.indexOf(\" value='\" + isov + \"'>\") != -1) {
    cnb=' in ' + ctynames.split(\" value='\" + isov + \"'>\")[1].split('<')[0];
    document.getElementById('tzsel').title='Default is a Timezone in ' + ctynames.split(\" value='\" + isov + \"'>\")[1].split('<')[0];
    document.getElementById('myh1').innerHTML+=' for ' + (thistz + '/').replace(thistz.split('/')[0] + '/', '').split('/')[1].replace(/\_/g,' ') + ' ' + (thistz + '/').replace(thistz.split('/')[0] + '/', '').split('/')[0].replace(/\_/g,' ').trim().replace('Argentina','');
    document.getElementById('myh1').innerHTML+=cnb + ' ' + jorflag(isov);
    }
    }
    }

    “; ?>
  • clock button styling …
    <?php

    $clockcss='';
    $clocksvg="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewport='0 0 100 100' style='font-family:Verdana;font-size:10px;'><text y='50%'>\\0023f0</svg>";

    ?>
    <?php echo ”

    <style>
    " . $clockcss . "
    input[type=\"text\"] { width: 250px; }
    #clock { border-radius: 50px; color:pink; text-shadow:-1px 1px 1px yellow; background-image: url('" . str_replace("'",'"',$clocksvg) . "'); }
    </style>

    “; ?>

  • clock recursive style functionality via an iframe onload event paradigm (with function clockif below) …
    <?php echo ”

    var documentURL=document.URL;
    var repcnt=0, cnb='', isov='', txils=[];
    var thistz=(location.search.split('timezone=')[1] ? (decodeURIComponent(location.search.split('timezone=')[1].split('&')[0]) + '') : '');

    function clockif(iois) {
    if (iois.src.indexOf('About_Us.') == -1) {
    repcnt++;
    setTimeout(function(){ iois.src=iois.src.split('&rand=')[0] + '&rand=' + repcnt; }, 1000);
    var aconto = (iois.contentWindow || iois.contentDocument);
    if (aconto != null) {
    if (aconto.document) { aconto = aconto.document; }
    if (aconto.body != null) {
    if (aconto.getElementById('pdfmt') && parent.document.getElementById('pdfmt')) {
    parent.document.getElementById('pdfmt').innerHTML=aconto.getElementById('pdfmt').innerHTML;
    if (repcnt == 1) {
    parent.document.getElementById('pdfmt').style.border='5px dotted pink';
    parent.document.getElementById('pdfmt').style.padding='5 5 5 5';
    if (eval('' + txils.length) > 1) {
    parent.document.getElementById('pdfmt').title='Timestamp for ' + documentURL.split('?')[1].split('&cl')[0].replace(/\&/g,' ').replace(/\=/g,' ').replace(/\%2F/g,'/').replace(/\%2f/g,'/') + txils[1].split('>')[0] + cnb;
    } else {
    parent.document.getElementById('pdfmt').title='Timestamp for ' + documentURL.split('?')[1].split('&cl')[0].replace(/\&/g,' ').replace(/\=/g,' ').replace(/\%2F/g,'/').replace(/\%2f/g,'/');
    }
    }
    }
    }
    }
    }
    }

    “; ?>
    … called into play via document.body onload Javascript …
    <?php echo ”

    <body onload="onlit(); if (documentURL.indexOf('clock=') != -1) { setTimeout(function(){ document.getElementById('justincase').src=documentURL=documentURL.replace('clock=','cloNOWAYck=') + '&rand=' + repcnt; }, 1000); } ">

    “; ?>
    … along with a new form submit button choice …
    <?php echo ”

    <input style=background-color:#f0f0f0; title=Clock type=submit id=clock name=clock value=Clock></input>

    “; ?>

  • dropdown option (subelement) emoji flag title …
    Locale
    <?php

    $locsel='';
    $arrl=ResourceBundle::getLocales('');
    for ($df=0; $df<sizeof($arrl); $df++) {
    $endih='';
    $lastword=explode('_',$arrl[$df])[-1 + sizeof(explode('_',$arrl[$df]))];
    $ends=explode("['" . explode('-',explode('_',$arrl[$df])[0])[0] . '-', $lochelper);
    if (sizeof($ends) > 1) {
    $endih.=' ' . explode("'", explode("['", $ends[0])[-1 + sizeof(explode("['", $ends[0]))])[0];
    }
    if (strpos($lochelpertwo, '>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>') !== false) {
    //echo "yes " . explode('-',explode('_',$arrl[$df])[0])[0] . "\n<br>";
    //echo substr(explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0], -250,250);
    $interim=explode('</a>', explode('<tr', explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0])[-1 + sizeof(explode('<tr', explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0]))])[0]; //)[-1 + sizeof(explode('>', explode('</td>', explode('<tr', explode('>' . explode('-',explode('_',$arrl[$df])[0])[0] . '</a>', $lochelpertwo)[0];
    //exit;
    $aintm=explode('>', $interim)[-1 + sizeof(explode('>', $interim))];
    if (strpos($endih, ' ' . $aintm) === false) {
    if ($endih != '') {
    $endih.=' (' . $aintm . ')';
    } else {
    $endih.=' ' . $aintm;
    }
    }
    }
    if ($lastword == strtoupper($lastword) && strlen($lastword) == 2) {
    $endih.=' ' . orflag($lastword);
    }
    if ($endih != '') {
    $endih="\t" . $endih . '';
    }

    if (strpos(($arrl[$df] . '_'), '_') !== false) { //} && strpos($arrl[$df], '0') === false) {
    if ($locsel == '') {
    $locsel="<select onchange=\"if (this.value.trim().length != 0) { document.getElementById('locale').value=tzdef(this.value); }\" id=locsel><option id=\"loptone\" value=''>Optionally select a Locale below ...</option></select>";
    }
    $locsel=str_replace("</select>", "<option value='" . $arrl[$df] . "' translate=\"no\" title=\"" . $endih . "\">" . $arrl[$df] . "</option></select>", $locsel);
    }
    }

    ?>
    TimeZone
    <?php

    $yourtzlist="<select onchange=\"if (this.value.trim().length != 0) { document.getElementById('timezone').value=this.value; }\" id=tzsel><option id=\"toptone\" value=''>Optionally select a TimeZone below ...</option><option value='Africa/Abidjan' data-geo='5.31666,-4.03334,GMT,CI,+0'>Africa/Abidjan</option><option value='Africa/Accra' data-geo='5.55,-0.21667,GMT,GH,+0'>Africa/Accra</option><option value='Africa/Addis_Ababa' data-geo='9.03333,38.7,EAT,ET,+3'>Africa/Addis_Ababa</option><option value='Africa/Algiers' data-geo='36.78333,3.05,CET,DZ,+1'>Africa/Algiers</option> ... blah ... blah ... blah ... </select>";

    $yls=explode(" data-geo='", $yourtzlist);
    for ($iy=(-1 + sizeof($yls)); $iy>=1; $iy--) {
    if (sizeof(explode(',', $yls[$iy])) > 3) {
    $icp=explode(',', $yls[$iy])[3];
    //echo $icp;
    if ($icp == strtoupper($icp) && strlen($icp) == 2 && strpos($icp, '?') === false) {
    //echo $icp . ' data-geo="' . $yls[$iy] . ' becomes ' . ' title="' . orflag($icp) . '" data-geo="' . $yls[$iy];
    //exit;
    $yourtzlist=str_replace(" data-geo='" . $yls[$iy], ' title=' . "'" . orflag($icp) . "'" . " data-geo='" . $yls[$iy], $yourtzlist);
    }
    }
    }


    ?>

… in a changed “third draft” PHP code offering here, as a PHP web application, you can also try below.


Previous relevant PHP Intl Class Datetime Defaults Tutorial is shown below.

PHP Intl Class Datetime Defaults Tutorial

PHP Intl Class Datetime Defaults Tutorial

Onto the recent PHP Intl Class Datetime Tutorial start to a PHP Current Datetime Intl Using Internationalization web application we see a way forward improving …

  • default Locale and TimeZone presented …
    Locale
    <?php

    $defloc=Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);

    ?>
    Timezone
    <?php

    $deficc=explode('_', str_replace('_posix','',$defloc))[-1 + sizeof(explode('_', str_replace('_posix','',$defloc)))];
    $yourtzlist="<select onchange=\"if (this.value.trim().length != 0) { document.getElementById('timezone').value=this.value; }\" id=tzsel><option id=\"toptone\" value=''>Optionally select a TimeZone below ...</option><option value='Africa/Abidjan' data-geo='5.31666,-4.03334,GMT,CI,+0'>Africa/Abidjan</option><option value='Africa/Accra' data-geo='5.55,-0.21667,GMT,GH,+0'>Africa/Accra</option><option value='Africa/Addis_Ababa' data-geo='9.03333,38.7,EAT,ET,+3'>Africa/Addis_Ababa</option><option value='Africa/Algiers' data-geo='36.78333,3.05,CET,DZ,+1'>Africa/Algiers</option> ... blah ... blah ... blah ... </select>";

    if (strpos($yourtzlist, ',' . $deficc . ',') !== false) {
    $ourtz=explode('<', explode('>', explode(',' . $deficc . ',', $yourtzlist)[1])[1])[0];
    } else {
    $ourtz="''"; //date.timezone; // ($_SERVER['TZ'] ?? (file_get_contents('/etc/timezone') ?: file_get_contents('/etc/localtime')))
    }

    ?>

  • add accompanying dropdown ways to select values from a list of what is available on Locale and TimeZone (as above) and Calendar …
    <?php

    $calsel='';
    if (1 == 1) {
    $bundle=new ResourceBundle('','ICUDATA');
    $cnames=[];
    $calendars=$bundle->get('calendar');
    foreach ($calendars as $n=>$v) {
    if ($calsel == '') {
    $calsel="<select onchange=\"if (this.value.trim().length != 0) { document.getElementById('calendar').value=this.value; }\" id=calsel><option value=''>Optionally select a Calendar system below ...</option></select>";
    }
    $calsel=str_replace("</select>", "<option value='" . $n . "'>" . $n . "</option></select>", $calsel);
    $cnames[]=$n;
    }
    }

    $locsel='';
    $arrl=ResourceBundle::getLocales('');
    for ($df=0; $df<sizeof($arrl); $df++) {
    if (strpos(($arrl[$df] . '_'), '_') !== false) { //} && strpos($arrl[$df], '0') === false) {
    if ($locsel == '') {
    $locsel="<select onchange=\"if (this.value.trim().length != 0) { document.getElementById('locale').value=tzdef(this.value); }\" id=locsel><option id=\"loptone\" value=''>Optionally select a Locale below ...</option></select>";
    }
    $locsel=str_replace("</select>", "<option value='" . $arrl[$df] . "'>" . $arrl[$df] . "</option></select>", $locsel);
    }
    }

    ?>

  • change input type=text placeholder reflect any previously selected Locale and TimeZone and/or Calendar …
    <?php echo ”

    echo "<h1>Show Current Time</h1><br><h3>RJM Programming - December, 2024</h3><br><h4>As per (white background textboxes optional) ...</h4><br><br><form method=GET onsubmit=\"if (document.getElementById('calendar').value.trim() != '') { document.getElementById('calendar').name='calendar'; } if (document.getElementById('locale').value.trim() == '' || document.getElementById('timezone').value.trim() == '') { return false; } return true;\" action=\"./i_eg.php\">
    <br><input type=text ondblclick=this.value=this.placeholder; style=background-color:yellow; id=locale name=locale placeholder=" . (isset($_GET['locale']) ? urldecode($_GET['locale']) : (isset($_POST['locale']) ? urldecode($_POST['locale']) : $defloc)) . " value='' title=Locale></input> " . $locsel . "
    <br><input type=text ondblclick=this.value=this.placeholder; style=background-color:yellow; id=timezone name=timezone placeholder=" . (isset($_GET['timezone']) ? urldecode($_GET['timezone']) : (isset($_POST['timezone']) ? urldecode($_POST['timezone']) : $ourtz)) . " value='' title=TimeZone></input> " . $yourtzlist . "
    <br><input type=text ondblclick=this.value=this.placeholder; style=background-color:white; id=calendar placeholder=" . (isset($_GET['calendar']) ? urldecode($_GET['calendar']) : (isset($_POST['calendar']) ? urldecode($_POST['calendar']) : "gregorian")) . " value='' title=Calendar></input> " . $calsel . "
    <br><br><input style=background-color:lightgreen; type=submit value=Display></input>
    </form>
    ";

    “; ?>

… and regarding Locale selections take the opportunity to gather up to the top of Locale and TimeZone dropdowns any options relevant to any Locale first selected …

<?php echo ”

<scri" . "pt type=text/javascript>
var ctynames=\"" . str_replace("\n","",$ctynames) . "\";
var canmakenothing=false, firstloc='';

function tzdef(inloc) { // wrapper around Locale dropdown selected value
var inicc=inloc.replace(/\-/g,'_').split('_')[eval(-1 + inloc.replace(/\-/g,'_').split('_').length)];
var jnicc=inicc;
var newtstuff='', newlstuff='', newts=0, newls=0, tvalis='';
if (ctynames.indexOf(\" value='\" + inicc + \"'>\") != -1) {
jnicc=ctynames.split(\" value='\" + inicc + \"'>\")[1].split('<')[0];
}
if (document.getElementById('timezone').value == '' && inicc.trim() != '' && inicc == inicc.toUpperCase() && eval('' + inicc.length) == 2) {
var tzoh=document.getElementById('tzsel').innerHTML;
var aftertopt=document.getElementById('toptone').outerHTML;
var tzloh=document.getElementById('locsel').innerHTML;
var afterlopt=document.getElementById('loptone').outerHTML;
var tzs=tzoh.split(',' + inicc + ',');
if (eval('' + tzs.length) > 1) {
//document.getElementById('timezone').value=tzs[1].split('>')[1].split('<')[0];
tvalis=tzs[1].split('>')[1].split('<')[0];
newtstuff+='<option value=\"' + tvalis + '\">' + tvalis + '</option>';
for (newts=1; newts<eval('' + tzs.length); newts++) {
if (tzs[newts].split('>')[1].split('<')[0] != tvalis) {
newtstuff+='<option value=\"' + tzs[newts].split('>')[1].split('<')[0] + '\">' + tzs[newts].split('>')[1].split('<')[0] + '</option>';
}
}
tzs=tzloh.split('_' + inicc + '\"');
if (eval('' + tzs.length) > 1) {
newlstuff+='<option value=\"' + inloc + '\">' + inloc + '</option>';
for (newls=1; newls<eval('' + tzs.length); newls++) {
if (tzs[newls].split('>')[1].split('<')[0] != inloc) {
newlstuff+='<option value=\"' + tzs[newls].split('>')[1].split('<')[0] + '\">' + tzs[newls].split('>')[1].split('<')[0] + '</option>';
}
}
}
}
if (tzoh.indexOf(aftertopt) != -1 && newtstuff != '') {
document.getElementById('tzsel').innerHTML=aftertopt.replace(' id=', ' data-id=').replace(' value=\"', ' value=\" ').replace(' a Time', ' ' + jnicc + ' Time') + newtstuff + aftertopt + tzoh.split(aftertopt)[1];
}
if (tzloh.indexOf(afterlopt) != -1 && newlstuff != '') {
document.getElementById('locsel').innerHTML=afterlopt.replace(' id=', ' data-id=').replace(' value=\"', ' value=\" ').replace(' a Locale', ' ' + jnicc + ' Locale') + newlstuff + afterlopt + tzloh.split(afterlopt)[1];
}
if (tvalis != '') { document.getElementById('timezone').value=tvalis; }
document.getElementById('locsel').value=inloc;
firstloc=inicc;
canmakenothing=true;
}
if (document.getElementById('tzsel').value == ' ' && canmakenothing) {
if (inicc != firstloc) {
document.getElementById('tzsel').value='';
}
}
return inloc.replace(/\-/g,'_');
}
</scr" . "ipt>

“; ?>

… containing an ISO-3166 2 letter Country Code at it’s end, mentioning that country’s name in that first option of the TimeZone dropdown, so that some users will see a Country Name in the mix, adding to relatability, perhaps.

We feel this considerably improves the User Experience using a changed “second draft” PHP code offering here, as a PHP web application, you can also try below.


Previous relevant PHP Intl Class Datetime Tutorial is shown below.

PHP Intl Class Datetime Tutorial

PHP Intl Class Datetime Tutorial

We’re back revisiting the PHP intl “Internationalization” class mentioned in “the AlmaLinux install feeling” PHP Mbstring Multibyte String and Intl Class Tutorial

Reading a bit, we cottoned onto three data items being central to Datetime PHP intl usage being …

  1. locale
  2. timezone
  3. calendar … optional

… and, so, we’re starting our “learning curve” (we got great help from this excellent website developing …

<?php

if (isset($_GET['locale']) && isset($_GET['timezone']) && isset($_GET['calendar'])) {
$DateTime = new DateTime();
$IntlDateFormatter = new IntlDateFormatter(
urldecode($_GET['locale']) . '@calendar=' . urldecode($_GET['calendar']),
IntlDateFormatter::FULL,
IntlDateFormatter::FULL,
urldecode($_GET['timezone']),
IntlDateFormatter::TRADITIONAL);

echo '<p>' . $IntlDateFormatter->format($DateTime) . '</p><br><br>';
}

?>

…) in today’s “first draft” “proof of concept” offering here, as a PHP web application, you can also try below …


Previous relevant PHP Mbstring Multibyte String and Intl Class Tutorial is shown below.

PHP Mbstring Multibyte String and Intl Class Tutorial

PHP Mbstring Multibyte String and Intl Class Tutorial

We’re revisiting the PHP Mbstring Multibyte String Primer Tutorial of the past to see where we stand now with PHP 8 and …

  • mbstring “Multibyte String” extension … and …
  • intl “Internationalization Functions” extension

… and discovered that we can happily now have a chance incorporating these functionalities into PHP serverside logic into the future. We tested this with a tweaked mbstring_test.php “old way” live run and “new way” live run via the writing of a couple of “proof of concepts” …


Previous relevant PHP Mbstring Multibyte String Primer Tutorial is shown below.

PHP Mbstring Multibyte String Primer Tutorial

PHP Mbstring Multibyte String Primer Tutorial

Our (Mac OS X laptop) local MAMP web server is an Apache/PHP/MySql web server. In this environment you can find out a lot with some PHP code as per …

<?php phpinfo(); ?>

… and if, in doing this, you find a reference to the “mbstring” Multibyte String Information functionality existing, you are a lucky candidate to introduce some internationalization code into your PHP code, for those occasions where the destination language uses a UTF-8 character set where individual characters can not be described by the ascii character set from decimal 0 to decimal 255. In other words, it takes more than one byte to describe each character of the language. There are many languages like this, a few being the Chinese languages, Japanese and Korean.

We followed a lot of the advice of the very useful link (thanks) to create some PHP called …

… where we show what we always suspected but were too shy to ask, and didn’t flesh it out before … doh! … you can’t split a Chinese phrase’s characters into their individual characters and expect those characters individually translated bring you back to the sense of the Chinese phrase to start with.

So we take the Chinese phrase 火车票 (which translates into English as “Train tickets” … and we thank Google Translate for help with all this) and use PHP mbstring’s mb_str_split to properly split the Chinese into its constituent multibyte (UTF-8) characters (and along the way, show that PHP str_split messes up this same task, as you’d probably guess would happen), and then translate all these into English using Google Translate, as an intellectual exercise.

If this exercise makes you …

  • a) fall on the floor laughing
  • b) hit a gong with a huge hammer
  • c) cook up some deep fried dumplings
  • d) put the left chopstick in the right ear and the right chopstick in the left ear (please ask for adult supervision) … translation: do not do this
  • e) while reading you sweep the cat under the rug (no animals were harmed in the making of this blog posting)

… then we’re here to tell you that you need to take a Bex and have a lie down.

We are just showing in PHP that if the mbstring functionality is available to you, that the mbstring library of functionality can help with some Internationalization issues you may be grappling with and that this PHP code you could try via this live run link.

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


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


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


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


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


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


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


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


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


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


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