Clickaround Maps Google Chart Geo Chart Mobile Integration Tutorial

Clickaround Maps Google Chart Geo Chart Mobile Integration Tutorial

Clickaround Maps Google Chart Geo Chart Mobile Integration Tutorial

As Felix pointed out in The Odd Couple (cough, cough … cough, cough, cough, splutter, cough … well, you had to be there)

When you assume, you make an ‘ass’ out of ‘u’ and ‘me’.

Yes, with yesterday’s Clickarounds work of Clickaround Maps Google Chart Geo Chart Integration Tutorial, we hadn’t tested on mobile!
Oops, that’s allsorry, folks.

Did you pick up a potential ‘ass’ out of ‘u’ and ‘me’ assumption in yesterday’s new function divcheck code? Hint is, you need more care around if statements with a particular quality of HTML structure tested for. Yes …


if (divsare[idivs].outerHTML.split('>')[0].indexOf('ltr') != -1 && divsare[idivs].outerHTML.split('>')[0].indexOf(' id=') == -1) {
// is that candidate for suspicion, and extra care, to test on all platforms
}

Even writing the logic of the code, we should have been wary, because we arrived at this …

  1. being on the MacBook Air
  2. in a Google Chrome web browser
  3. web inspector
  4. playing around with scaling div elements dynamically just outside the SVG of the Geo Chart Google produced chart elements
  5. making something look interesting dynamically
  6. then working out that if logic, reverse engineering, if you will, to assemble the logic …
  7. Make the div two down from id=chart_div be id=theonetoscale

  8. … the idea of this being to offer another scaling of Geo Chart approach we might develop further and talk about into the future

Reasonable logic, except that we didn’t test that assumption on any mobile platforms, and that logic was relying on a certain pattern to a structure of HTML … 🔔🔔

Our new function divcheck, with slightly less assumptiveness (cough, cough … cough, cough, cough, splutter, cough … well, you had to be there) goes …

<?php echo ”

function divcheck() {
var ctylistis=['india_', 'india', 'ireland', 'brazil', 'australia', 'china', 'nigeria', 'australia', 'germany', 'united_states', 'welcometonation'];
var ctylistcd=['IN', 'IN', 'IE', 'BR', 'AU', 'CN', 'NG', 'AU', 'DE', 'US', 'AU'];
var tstris='';
var divltrcnt=0, divsare=document.getElementsByTagName('div');
var thingois='MinxMaxy';
console.log('divcheck here');


for (var idivs=0; idivs<divsare.length; idivs++) {
if (('' + divsare[idivs].id) == 'chart_div') {
divltrcnt=-0.5;
} else if (divltrcnt < 0 || (divltrcnt > 0 && divltrcnt < 1)) {
divltrcnt+=1.0;
if (divltrcnt > 1 && divltrcnt < 2) {
console.log(divsare[idivs].outerHTML.split('>')[0]);
if (divsare[idivs].outerHTML.split('>')[0].replace('thedivemail','ltr').indexOf('ltr') != -1 && divsare[idivs].outerHTML.split('>')[0].replace(' id=\"thedivemail\"','').indexOf(' id=') == -1) {
if (divsare[idivs].outerHTML.split('>')[0].indexOf(' id=') == -1) {
divsare[idivs].id='theonetoscale';
}
for (var iuh=0; iuh<ctylistis.length; iuh++) {
if (('' + document.URL).indexOf('title=') != -1) {
tstris='title=' + ('' + document.URL).split('title=')[1].split('&')[0].split('#')[0];
}
if (('' + parent.document.URL).indexOf('/' + ctylistis[iuh]) != -1 && (('' + document.URL).indexOf('title=') != -1 && ('' + document.URL).indexOf('title=' + ctylistcd[iuh]) == -1)) {
if (('' + document.URL).indexOf('?title=') != -1) {
console.log('1:' + tstris + String.fromCharCode(10) + document.URL.split('&onclick=')[0] + String.fromCharCode(10) + document.URL.replace('?' + tstris, '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + ctylistcd[iuh]));
if (iuh > 0) { thingois='Your%20Place'; if (document.URL.indexOf('Your%20Place') == -1 && document.URL.indexOf('|~') != -1) { thingois=document.URL.split('|~')[1].split('~')[0]; } } else if (document.URL.indexOf(thingois) == -1) { thingois=tstris; }
concole.log('11:' + document.URL.replace('?' + tstris, '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&'));
location.href=document.URL.replace('?' + tstris, '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&');
} else if (('' + document.URL).indexOf('&title=') != -1) {
console.log('2:' + tstris + String.fromCharCode(10) + document.URL.split('&onclick=')[0] + String.fromCharCode(10) + document.URL.replace('&' + tstris,'').replace('?', '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + ctylistcd[iuh]));
if (iuh > 0) { thingois='Your%20Place'; if (document.URL.indexOf('Your%20Place') == -1 && document.URL.indexOf('|~') != -1) { thingois=document.URL.split('|~')[1].split('~')[0]; } } else if (document.URL.indexOf(thingois) == -1) { thingois=tstris; }
console.log('22:' + document.URL.replace('&' + tstris,'').replace('?', '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&'));
location.href=document.URL.replace('&' + tstris,'').replace('?', '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&');
} else if (('' + document.URL).indexOf('#title=') != -1) {
location.href=document.URL.replace('#title=', '#title=' + ctylistcd[iuh] + ';');
}
}
}
}
} else {
console.log('but no:' + divsare[idivs].outerHTML.split('>')[0]);
}
}
}
}

“; ?>

… to fix the issue in a tweaked geo_chart.php Google Chart Geo Chart interfacer.

Did you know?

Do you have …

FOTIMPIVAWLBIAMASWBWISTV

? … ie. Fear of Testing iOS Mobile Platform issues via Apple White lead between iPhone and MacBook and Safari web browser Web Inspectors sensitive to versioning ?

We think we developed it ( ie. FOTIMPIVAWLBIAMASWBWIS (we Australians can’t help but give stuff a nickname) ) a little, over some time, because of intransigence, putting up with a dodgy Apple White lead letting us down so often. My advice … don’t always ‘ass’ out of ‘u’ and ‘me’ hardware never fails, and ditch the lead to get a new one. Aaaaaaaaah!


Previous relevant Clickaround Maps Google Chart Geo Chart Integration Tutorial is shown below.

Clickaround Maps Google Chart Geo Chart Integration Tutorial

Clickaround Maps Google Chart Geo Chart Integration Tutorial

The word “integration” usually refers to two or more parts to an issue or concept combining to work together better … at least to us.

In our case, we’re often “integrating”, better, a parent and child “part”. We find it more elegant to only have to change one component here, but, of course, this is …

  • not always possible
  • not always desirable … especially if it becomes too cryptic by half doing the “integration” this way

With our Clickaround Maps suite of web applications our admittedly just mildly annoying issue concerned the “World View” any interfacing to the inhouse Google Chart Geo Chart interfacer, last talked about at Google Chart Geo Chart Quiz Time Tutorial, would lob you onto. After all, each Clickaround Map web application (except the “World” one) has associated with it a home country of interest, and a regular reader will know, in amongst the URL arguments (exemplified) …


https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=BR;Brazil&iso=BR&shade=Your%20Place&aregeographicals=y&width=556&height=347&country=Places&popularity=Popularity&data=%20[-8,-48.5,~Your%20Place%20%F0%9F%8F%A0%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7~,2],[-7.2,-48.2,~America%2FAraguaina%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7%20is%2094.902km%20(-3%20%F0%9F%95%91%20am%2C%20Monday)%20~,2],[-1.45,-48.48334,~America%2FBelem%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7%20is%20728.329km%20(-3%20%F0%9F%95%91%20am%2C%20Monday)%20~,2],[-2.43334,-54.86667,~America%2FSantarem%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7%20is%20937.963km%20(-3%20%F0%9F%95%91%20am%2C%20Monday)%20~,2]

… we were not, up until today …

  1. using that [ISO-Country-Code]; means of making the Geo Chart view honed in on the country of interest
  2. using that &iso=BR to indicate we want to shade the map SVG polygon of interest, as found
  3. using that &shade=Your%20Place to indicate we want to shade the map SVG polygon of interest via the one containing the SVG text or circle element containing the wording Your Place

… and so, we worked it from the child Geo Chart interfacer back up, in preference, because that is where the “action item” sits, and in complex cases, this is usually the best decision as to where most of the “integration” work should occur, the Javascript arranger of better arguments happening just after the document onload event …

<?php echo ”

function divcheck() {
var ctylistis=['india_', 'india', 'ireland', 'brazil', 'australia', 'china', 'nigeria', 'australia', 'germany', 'united_states', 'welcometonation'];
var ctylistcd=['IN', 'IN', 'IE', 'BR', 'AU', 'CN', 'NG', 'AU', 'DE', 'US', 'AU'];
var tstris='';
var divltrcnt=0, divsare=document.getElementsByTagName('div');
var thingois='MinxMaxy';

for (var idivs=0; idivs<divsare.length; idivs++) {
if (('' + divsare[idivs].id) == 'chart_div') {
divltrcnt=-0.5;
} else if (divltrcnt < 0 || (divltrcnt > 0 && divltrcnt < 1)) {
divltrcnt+=1.0;
if (divltrcnt > 1 && divltrcnt < 2) {
if (divsare[idivs].outerHTML.split('>')[0].indexOf('ltr') != -1 && divsare[idivs].outerHTML.split('>')[0].indexOf(' id=') == -1) {
divsare[idivs].id='theonetoscale';
for (var iuh=0; iuh<ctylistis.length; iuh++) {
if (('' + document.URL).indexOf('title=') != -1) {
tstris='title=' + ('' + document.URL).split('title=')[1].split('&')[0].split('#')[0];
}
if (('' + parent.document.URL).indexOf('/' + ctylistis[iuh]) != -1 && (('' + document.URL).indexOf('title=') != -1 && ('' + document.URL).indexOf('title=' + ctylistcd[iuh]) == -1)) {
if (('' + document.URL).indexOf('?title=') != -1) {
if (iuh > 0) { thingois='Your%20Place'; if (document.URL.indexOf('Your%20Place') == -1 && document.URL.indexOf('|~') != -1) { thingois=document.URL.split('|~')[1].split('~')[0]; } } else if (document.URL.indexOf(thingois) == -1) { thingois=tstris; }
location.href=document.URL.replace('?' + tstris, '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&');
} else if (('' + document.URL).indexOf('&title=') != -1) {
if (iuh > 0) { thingois='Your%20Place'; if (document.URL.indexOf('Your%20Place') == -1 && document.URL.indexOf('|~') != -1) { thingois=document.URL.split('|~')[1].split('~')[0]; } } else if (document.URL.indexOf(thingois) == -1) { thingois=tstris; }
location.href=document.URL.replace('&' + tstris,'').replace('?', '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&');
} else if (('' + document.URL).indexOf('#title=') != -1) {
location.href=document.URL.replace('#title=', '#title=' + ctylistcd[iuh] + ';');
}
}
}
}
}
}
}
}

“; ?>

… to result in initially shaded Country View Geo Chart interfacing with Clickaround Suite of web applications below …

… all capable of calling the improved more integral changed geo_chart.php Google Chart Geo Chart interfacer.


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

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,//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="></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,//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=");
    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,//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();
    }
    }
    }

    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.


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


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

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

Clickaround Maps Google Chart Geo Chart Integration Tutorial

Clickaround Maps Google Chart Geo Chart Integration Tutorial

Clickaround Maps Google Chart Geo Chart Integration Tutorial

The word “integration” usually refers to two or more parts to an issue or concept combining to work together better … at least to us.

In our case, we’re often “integrating”, better, a parent and child “part”. We find it more elegant to only have to change one component here, but, of course, this is …

  • not always possible
  • not always desirable … especially if it becomes too cryptic by half doing the “integration” this way

With our Clickaround Maps suite of web applications our admittedly just mildly annoying issue concerned the “World View” any interfacing to the inhouse Google Chart Geo Chart interfacer, last talked about at Google Chart Geo Chart Quiz Time Tutorial, would lob you onto. After all, each Clickaround Map web application (except the “World” one) has associated with it a home country of interest, and a regular reader will know, in amongst the URL arguments (exemplified) …


https://www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=BR;Brazil&iso=BR&shade=Your%20Place&aregeographicals=y&width=556&height=347&country=Places&popularity=Popularity&data=%20[-8,-48.5,~Your%20Place%20%F0%9F%8F%A0%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7~,2],[-7.2,-48.2,~America%2FAraguaina%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7%20is%2094.902km%20(-3%20%F0%9F%95%91%20am%2C%20Monday)%20~,2],[-1.45,-48.48334,~America%2FBelem%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7%20is%20728.329km%20(-3%20%F0%9F%95%91%20am%2C%20Monday)%20~,2],[-2.43334,-54.86667,~America%2FSantarem%20in%20Brazil%20%F0%9F%87%A7%F0%9F%87%B7%20is%20937.963km%20(-3%20%F0%9F%95%91%20am%2C%20Monday)%20~,2]

… we were not, up until today …

  1. using that [ISO-Country-Code]; means of making the Geo Chart view honed in on the country of interest
  2. using that &iso=[ISO-Country-Code] ( ie. &iso=BR ) to indicate we want to shade the map SVG polygon of interest, as found
  3. using that &shade=Your%20Place to indicate we want to shade the map SVG polygon of interest via the one containing the SVG text or circle element containing the wording Your Place

… and so, we worked it from the child Geo Chart interfacer back up, in preference, because that is where the “action item” sits, and in complex cases, this is usually the best decision as to where most of the “integration” work should occur, the Javascript arranger of better arguments happening just after the document onload event …

<?php echo ”

function divcheck() {
var ctylistis=['india_', 'india', 'ireland', 'brazil', 'australia', 'china', 'nigeria', 'australia', 'germany', 'united_states', 'welcometonation'];
var ctylistcd=['IN', 'IN', 'IE', 'BR', 'AU', 'CN', 'NG', 'AU', 'DE', 'US', 'AU'];
var tstris='';
var divltrcnt=0, divsare=document.getElementsByTagName('div');
var thingois='MinxMaxy';

for (var idivs=0; idivs<divsare.length; idivs++) {
if (('' + divsare[idivs].id) == 'chart_div') {
divltrcnt=-0.5;
} else if (divltrcnt < 0 || (divltrcnt > 0 && divltrcnt < 1)) {
divltrcnt+=1.0;
if (divltrcnt > 1 && divltrcnt < 2) {
if (divsare[idivs].outerHTML.split('>')[0].indexOf('ltr') != -1 && divsare[idivs].outerHTML.split('>')[0].indexOf(' id=') == -1) {
divsare[idivs].id='theonetoscale';
for (var iuh=0; iuh<ctylistis.length; iuh++) {
if (('' + document.URL).indexOf('title=') != -1) {
tstris='title=' + ('' + document.URL).split('title=')[1].split('&')[0].split('#')[0];
}
if (('' + parent.document.URL).indexOf('/' + ctylistis[iuh]) != -1 && (('' + document.URL).indexOf('title=') != -1 && ('' + document.URL).indexOf('title=' + ctylistcd[iuh]) == -1)) {
if (('' + document.URL).indexOf('?title=') != -1) {
if (iuh > 0) { thingois='Your%20Place'; if (document.URL.indexOf('Your%20Place') == -1 && document.URL.indexOf('|~') != -1) { thingois=document.URL.split('|~')[1].split('~')[0]; } } else if (document.URL.indexOf(thingois) == -1) { thingois=tstris; }
location.href=document.URL.replace('?' + tstris, '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&');
} else if (('' + document.URL).indexOf('&title=') != -1) {
if (iuh > 0) { thingois='Your%20Place'; if (document.URL.indexOf('Your%20Place') == -1 && document.URL.indexOf('|~') != -1) { thingois=document.URL.split('|~')[1].split('~')[0]; } } else if (document.URL.indexOf(thingois) == -1) { thingois=tstris; }
location.href=document.URL.replace('&' + tstris,'').replace('?', '?' + tstris.replace('=','=' + ctylistcd[iuh] + ';') + '&shade=' + thingois + '&iso=' + ctylistcd[iuh] + '&');
} else if (('' + document.URL).indexOf('#title=') != -1) {
location.href=document.URL.replace('#title=', '#title=' + ctylistcd[iuh] + ';');
}
}
}
}
}
}
}
}

“; ?>

… to result in initially shaded Country View Geo Chart interfacing with Clickaround Suite of web applications below …

… all capable of calling the improved more integral changed geo_chart.php Google Chart Geo Chart interfacer.


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

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,//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="></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,//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=");
    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,//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();
    }
    }
    }

    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.


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

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

WordPress Blog Image Editing Media Tutorial

WordPress Blog Image Editing Media Tutorial

WordPress Blog Image Editing Media Tutorial

We’re happy to be revisiting …

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

  • Video
  • Animated GIF

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

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

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

  1. lots of data
  2. but understood everywhere

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

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


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

… to look like …

    

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

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


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

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

… creating those popup window “Video” and/or “Animated GIF” presentations we’ve been talking about above.

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

<?php echo ”

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

“; ?>

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


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

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

Yesterday’s …

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

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

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

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

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


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

}
};
}, 4000);
}

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

<?php

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

?>

… calling new Javascript function …

<?php echo ”

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

“; ?>

Other than header.php WordPress PHP code we changed …


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

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

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

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

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

And then there was “the unknown factor” …

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

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


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

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

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

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

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

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

… talking about the three appended spaces needed.


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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

Did you know?

All this begs the question …

What about mobile?

Well, at least for iOS we think …


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per

index.htm …


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday’s One Image Website iOS Radio Music One Less Tutorial set us on an “off to the side, but eventually forward” project that intertwines …

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday’s One Image Website iOS Radio Music Tutorial “Stop Press” promised …

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    … to arrive at the calling window

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said …

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

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

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

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

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

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

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

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

<?php echo ”

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

“; ?>

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

<?php echo ”

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

}

“; ?>

… to call on that new PHP …

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo ”

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

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

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

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


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

“; ?>

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

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

… we all excluded from new functionality Image Map potential “dark green area clicking” access to photography themed “One Image Websites” …

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

<?php echo ”

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

“; ?>

57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of “responsive web design”

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

… coming at it from the idea “Can a responsive shell webpage host a non-responsive iframe?”

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

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

    … as food for (your) thought …


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

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


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


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


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


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


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


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


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


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


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


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


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

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

Google Charts Debugging via Web Inspector and View Page Source Tutorial

Google Charts Debugging via Web Inspector and View Page Source Tutorial

Google Charts Debugging via Web Inspector and View Page Source Tutorial

The combination of (showing Google Chrome web browser wording)

  • PHP
  • web browser Web Inspector(s) … via … View -> Developer -> Developer Tools …
  • web browser View Source … via … View Page Source right click option … or … View -> Developer -> View Source

… are a great out of the web browser box (ie. free) debugging toolset, especially for issues related to an upgrade of PHP to version starting with an 8 (as an upgrade to AlmaLinux we did here from a CentOS PHP version starting with a 5).

What can you expect in the nature of the symptoms of PHP upgrade to 8 problems? We’d say …

  • blank web content … as for today … you might need the web browser Web Inspector (and perhaps onto View Page Source) or some third party PHP Debugger
  • PHP warning messages
  • PHP deprecation messages
  • PHP (fatal) error messages
  • Web Inspector syntax errors etcetera … at a level where you might drill down to an actual clientside codeline (but clientside codeline number is unlikely to be problematic PHP codeline number with the issue)

Today’s debugging fix session (of non declared PHP $GETdesc variable and one $_GET[‘desc2’] or one $_POST[‘desc2’]) to the changed annotatedtimeline_chart.php Google Chart Annotated Timeline Chart inhouse interfacer illustrated builds on the recent Google Charts Interfacing Date Picker Tutorial work fixing the Timeline Chart button for our inhouse India Map

… web application below (showing India Map with the picking of state Madhya Pradesh to show the TimeChart Chart button) …


Previous relevant Google Calendar Chart Revisit Tutorial is shown below.

Google Calendar Chart Revisit Tutorial

Google Calendar Chart Revisit Tutorial

It pays to revisit your web applications, especially when they involve API or third party calls, as much as anything because your inhouse calls can take on different meanings should Google, in our case, change the usage syntax. We were surprised by errors we received when revisiting the Google Chart Calendar Chart interfacing live run‘s calendar_chart.php‘s functionality (changes), building on Google Calendar Chart Difference Report Planning Tutorial from days past.

What tool can you use to suss out the issue? A web browser’s Web Inspector will often help, because the problems will appear at a client level, and error messages will be “true to their word”.

Am sure you can see from the differences report below, when your work involves third parties, it is good to be checking that third party information on a regular basis, or via feeds and/or blogs …

63d62
< <script type=”text/javascript” src=”//www.gstatic.com/charts/loader.js”></script>
67c66
< <!–script type=”text/javascript” src=”https://www.google.com/jsapi?autoload={‘modules’:[{‘name’:’visualisation’,’version’:’1.1′,’packages’:[‘calendar’]}]}”></script–>

> <script type=”text/javascript” src=”https://www.google.com/jsapi?autoload={‘modules’:[{‘name’:’visualization’,’version’:’1.1′,’packages’:[‘calendar’]}]}”></script>
586,587c585
< echo ‘ google.charts.load(“current”, {packages:[“calendar”]}); ‘ . “\n”;
< echo ‘ google.setOnLoadCallback(drawChart); ‘ . “\n”; // old

> echo ‘ google.setOnLoadCallback(drawChart); ‘ . “\n”;
591,592c589
< echo ” chart = new google.visualization.Calendar(document.getElementById(‘chart_div’)); \n”;
< //echo ” chart = new google.visualization.DataTable(); \n”;

> echo ” chart = new google.visualization.Calendar(container); \n”;
625,629c622
< echo ” var options = { \n”;
< echo ” title:’Red Sox Attendance’, \n”;
< echo ” height: 350 \n”;
< echo ” }; \n”;
< echo ” chart.draw(dataTable,options); \n”;

> echo ” chart.draw(dataTable); \n”;
894c887
< //setTimeout(onl,1000);

>


Previous relevant Google Calendar Chart Difference Report Planning Tutorial is shown below.

Google Calendar Chart Difference Report Planning Tutorial

Google Calendar Chart Difference Report Planning Tutorial

Yesterday, with Google Timeline Chart Clipboard Tutorial, we had another (“when”) sub-guinea pig situation like the Area Chart was a “where” sub-guinea pig. Now, you may be sick of our “guinea pig” business … nga, nga, nga nga, ngaaaaair keeps legs smooth and hairfree … but we digress … you didn’t get to read this sophisticated riposte! … but there is “a method” (as my Dad used to say) in the madness. And today is a good day to show you the benefits of the “guinea pig” or sub-guinea pig. Do you remember the “(changes)” link from yesterday? To us, as a snapshot in time, it is “a gem” (my Dad would have said, “a peach”). Why? It sums up progress, and banishes chaos from the manyfold Google Chart related changes …

  • Background Multimedia (to Google Chart interfacings)
  • Email as Attachment
  • Big Data Length Management
  • Clipboard and/or URL based data inputs
  • Code for differentiation of web browser versus mobile UIWebView “hosted” environment “logics” … more on this later

… we want to propagate through all our interfacings … even-tu-al-ly … and so, this “differences” report is worth hiving off for future reference as a “things to do” link and as shown below …

… serving as a dampener of chaos and a “line in the sand”, things you need on big projects as far as organization goes.

So what do we apply these “planning via difference reporting” ideas to today? We apply it to a “when” Google Chart interfacing to the Timeline Chart, the Calendar Chart. Its data form is just “[date,number]” (array within an array), so is easier to slide into the csv.php “changed logic”, that is supervised by Calendar Chart live run‘s calendar_chart.php‘s functionality (changes) can, again, work large amounts of data as shown in today’s tutorial picture, and which you can simulate yourself at this Sydney Observatory Hill March 2018 Minimum Celcius Temperature Calendar Chart link, thanks to this great Australian Bureau of Meteorology link.

. Because it is only demanding (Javascript) Date object data and numeric data “sets”, we scan for all data items delimited that satisfy being a Date, and work the “numeric” around that, which had already been started on with yesterday’s work.

Along the way, we again make the line feed … in Javascript thoughts …


String.fromCharCode(10)

… delimiter a “friend” for data such as is required by a Timeline Chart by treating each “record” as a separate “entity” to “Date scan” within. We’ll see further down the track, this will, no doubt, be advantageous when we get to some of the more complex “when” Date object Google Chart interfacings we have not talked about yet.

The result of these “planning via difference reporting” is that you can …

  • work quicker
  • work with more surety
  • tick off “tasks” (you can start with a difference report, and “Cut” away at it, if you like)
  • unit test in a more savvy fashion
  • isolate problems easier

Aaaaaaaarrrrh! Here, “sub-guinea pig two”, time for sub-dinner!


Previous relevant Google Timeline Chart Clipboard Tutorial is shown below.

Google Timeline Chart Clipboard Tutorial

Google Timeline Chart Clipboard Tutorial

Today’s Google Charts Timeline Chart interface changes bring into play for the first time thoughts regarding (the Javascript) …


Date

… (object and) data type. We wanted to start down this “road” so that our “when” Google Charts such as the Timeline Chart, can be improved to allow for either of …

  • data off a web URL
  • data from the computer (or device’s) clipboard

… to eventually suit the “[label,dateFrom,dateTo]” (array within an array) data requirements of the Google Chart Timeline Chart. This work may sound familiar, and that would be because you have been following our recent progress with work of this ilk we last talked about with the recent Google Geo Intensity Map Chart Multimedia Background Tutorial.

What is different (but “modelable”), and requiring new PHP functions in our csv.php generic helper is that a Date (as an “object” or concept) is comprised of a …

  1. Year
  2. Month
  3. Date

… which, as you can probably imagine, could be represented in the “big wide world of data” in a huge variety of formats. We try allowing for the more popular Date formats.

What are we on about with “modelable” above? Well, if you’ve been following closely, you’d have seen us grapple with URL and clipboard issues with two other charts with 3 data items, namely …

  1. Intensity Chart uses “CountryCode,number1,number2”
  2. Map Chart uses “latitude,longitude,Place”

… and we like to follow “glimpses” of synergies rather than starting again. After all, we spent some time working the PHP functions for this, and the column ordering and delimitation logic of the Map Chart represent a great start to what we need to achieve, so that what is most of the work today becomes how we …

  • change the references to PHP function latlongmassage … and write a new …
  • datemassage … as the place to worry about all that Date representation thoughts we referred to above

… so that the calling live run‘s timeline_chart.php‘s functionality (changes) can work large amounts of data as shown in today’s tutorial picture, and which you can simulate yourself at this link, thanks to this great link.


Previous relevant Google Geo Intensity Map Chart Multimedia Background Tutorial is shown below.

Google Geo Intensity Map Chart Multimedia Background Tutorial

Google Geo Intensity Map Chart Multimedia Background Tutorial

To ease the burden of our usual Google Chart “guinea pig” Pie Chart interfacing web application, we’ve introduced today our interim “sub guinea pig” candidate, the Area Chart, who wants to grow up to be … you guessed it … a very big guinea pig, indeed!

The recent Google Line Area Bar Column Chart Multimedia Background Tutorial had us adding code to analyze semicolon delimited title prompt multimedia entries, similar code in a couple of places depending on whether the HTML form navigation is method=GET or method=POST. This is where a call of a shared PHP function would be good, and we did that by adding …


function titlebits(&$burl, &$GETtitle, &$cdivc, &$bdivstart, &$bdivend, &$nondefs) {

$gtypes = ["audio/wav","audio/x-wav","audio/x-pn-realaudio","audio/x-mpegurl","audio/x-aiff","audio/x-aifc","audio/mpeg","audio/mid",
"audio/basic","audio/ogg","video/x-sgi-movie","video/x-msvideo","video/quicktime","audio/mp3","video/mp4","video/mpeg",
"video/x-la-asf","video/ogg","video/webm","audio/mp4", "image/jpeg", "image/jpeg", "image/png", "image/gif", "image/bmp", "image/tif",
"text/html", "text/html", "text/html", "text/javascript", "text/css", "text/plain", "text/xml", "text/csv",
"application/vnd.ms-word", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/x-php", "application/pdf",
"application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.ms-powerpoint",
"application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"];
$gexts = [".wav",".wav",".ram",".m3u",".aiff",".aifc",".mp3",".rmi",
".snd",".ogg",".movie",".avi",".mov",".mp3",".m4v",".mpeg",
".lsx",".ogv",".webm",".m4a", ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tif",
".htm", ".html", ".htmls", ".js", ".css", ".txt", ".xml", ".csv",
".doc", ".docx", ".php", ".pdf",
".pptx", ".ppt",
".xls", ".xlsx"];

$ourtitles=explode(";", str_replace(";base64","|base64",urldecode($GETtitle)));
for ($ipa=0; $ipa<sizeof($ourtitles); $ipa++) {
$ourtitles[$ipa]=str_replace("|base64",";base64",$ourtitles[$ipa]);
}
$GETtitle = str_replace("\\'", "'", $ourtitles[sizeof($ourtitles) - 1]);
if (sizeof($ourtitles) > 1 && strlen($ourtitles[0]) > 3 && (strpos(strtolower($ourtitles[0]), "//") !== false || strpos(strtolower($ourtitles[0]), "data:") !== false)) {
while (sizeof($ourtitles) > 1 && strlen($ourtitles[0]) > 3 && (strpos(strtolower($ourtitles[0]), "//") !== false || strpos(strtolower($ourtitles[0]), "data:") !== false)) {
$burl="";
// Thanks to https://stackoverflow.com/questions/8828076/how-can-i-hack-a-background-image-into-google-chart-tools-dynamic-javascript-s
if (strpos($ourtitles[0], "data:") !== false) {
$burl=str_replace("%2b","+","data:" . explode(" ", explode("data:", substr($ourtitles[0],0,20) . explode(";",substr($ourtitles[0],20))[0] . " " )[1])[0]);
} else if (strpos($ourtitles[0], "DATA:") !== false) {
$burl=str_replace("%2b","+","data:" . explode(" ", explode("DATA:", substr($ourtitles[0],0,20) . explode(";",substr($ourtitles[0],20))[0] . " " )[1])[0]);
} else if (strpos($ourtitles[0], "Data:") !== false) {
$burl=str_replace("%2b","+","data:" . explode(" ", explode("Data:", substr($ourtitles[0],0,20) . explode(";",substr($ourtitles[0],20))[0] . " " )[1])[0]);
} else if (strpos($ourtitles[0], "https://") !== false) {
$burl="https://" . explode(" ", explode("https://", $ourtitles[0])[1])[0];
} else if (strpos($ourtitles[0], "Https://") !== false) {
$burl="Https://" . explode(" ", explode("Https://", $ourtitles[0])[1])[0];
} else if (strpos($ourtitles[0], "HTTPS://") !== false) {
$burl="HTTPS://" . explode(" ", explode("HTTPS://", $ourtitles[0])[1])[0];
} else if (strpos($ourtitles[0], "http://") !== false) {
$burl="http://" . explode(" ", explode("http://", $ourtitles[0])[1])[0];
} else if (strpos($ourtitles[0], "Http://") !== false) {
$burl="Http://" . explode(" ", explode("Http://", $ourtitles[0])[1])[0];
} else if (strpos($ourtitles[0], "HTTP://") !== false) {
$burl="HTTP://" . explode(" ", explode("HTTP://", $ourtitles[0])[1])[0];
} else {
$burl="//" . explode(" ", explode("//", $ourtitles[0])[1])[0];
}
if ($burl != "") {
$ourmimetype="";
if (strpos($burl, "data:") === false) {
$ourext=explode(".", $burl)[-1 + sizeof(explode(".", $burl))];
for ($im=0; $im<sizeof($gexts); $im++) {
if (strtolower("." . $ourext) == strtolower($gexts[$im])) $ourmimetype=$gtypes[$im] . ";";
}
}
if (strpos($burl, "audio/") !== false || strpos($ourmimetype, "audio/") !== false) {
if ($bdivstart == "") $bdivstart="<div id='bkcol'>";
if ($bdivend == "") {
$bdivend="</div><audio type='audio/" . explode(';', explode('audio/', $ourmimetype . $burl)[1])[0] . "' controls autoplay><source src=" . $burl . "></source></audio>";
} else {
$bdivend=str_replace("</div>", "</div><audio type='audio/" . explode(';', explode('audio/', $ourmimetype . $burl)[1])[0] . "' controls autoplay><source src=" . $burl . "></source></audio>", $bdivend);
}
} else if (strpos($burl, "video/") !== false || strpos($ourmimetype, "video/") !== false) {
if ($bdivstart == "") $bdivstart="<div id='bkcol'>";
if ($bdivend == "") {
$bdivend="</div><video type='video/" . explode(';', explode('video/', $ourmimetype . $burl)[1])[0] . "' controls autoplay><source src=" . $burl . "></source></video>";
} else {
$bdivend=str_replace("</div>", "</div><video type='video/" . explode(';', explode('video/', $ourmimetype . $burl)[1])[0] . "' controls autoplay><source src=" . $burl . "></source></video>", $bdivend);
}
} else if (strpos($burl, "youtube.com/embed/") !== false) {
if ($bdivstart == "") $bdivstart="<div id='bkcol'>";
if ($bdivend == "") {
$bdivend="</div><iframe width='560' height='315' src='" . $burl . "' frameborder='0' allow='autoplay; encrypted-media' allowfullscreen></iframe>";
} else {
$bdivend=str_replace("</div>", "</div><iframe width='560' height='315' src='" . $burl . "' frameborder='0' allow='autoplay; encrypted-media' allowfullscreen></iframe>", $bdivend);
}
} else if ($burl != "") {
$bdivstart="<div id='bkcol' style=\"background: linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url('" . $burl . "'); background-repeat: repeat;\">";
if ($bdivend == "") $bdivend="</div>";
}
}
$cdivc="background-color: none; opacity:1.0; ";
array_shift($ourtitles);
}
if ($burl != "") {
if (substr(trim("x" . $nondefs),-1) == ',') {
$nondefs.="backgroundColor: 'none',";
} else {
$nondefs.=", backgroundColor: 'none' ";
}
$ourtitles=explode(";", urldecode($GETtitle));
if (sizeof($ourtitles) == 1) {
$GETtitle=$ourtitles[0];
} else if (sizeof($ourtitles) == 2 && strlen($ourtitles[0]) <= 3) {
$GETtitle=$ourtitles[0] . ";" . $ourtitles[1];
}
} else {
$nondefs=$nondefs;
}
}
}

… into csv.php changed this way for today’s work. You may note here how PHP can use references in its function parameters so that any value changes performed to those parameter values with the function are reflected (actually “copied”) back at the caller code. Can PHP use pointerspointers, like C++ and C? Alas, no, but references can help, but are not as fast as pointers, given that pointers perform (operating system) kernel operations.

You can see an example of this usage at https://www.rjmprogramming.com.au/PHP/Map/map.php?title=https://www.youtube.com/embed/uzmtNSKf_JQ;http://www.rjmprogramming.com.au/frog/Welcome_files/shapeimage_1e.jpg;Places&onclick=y&emailto=rmetcalfe15@gmail.com&emailsubject=M%20h&label=[%27Lat%27,&value=%27Lon%27,%20%27Name%27]&data=%2C%20%5B-33.86667%2C151.21666%2C~Sydney~%5D%20%2C%20%5B-27.46667%2C153.07333%2C~Brisbane~%5D and answer the prompts of today’s live run like below …

https://www.youtube.com/embed/uzmtNSKf_JQ;HTTP://www.rjmprogramming.com.au/frog/Welcome_files/shapeimage_1e.jpg;Places&onclick=y&emailto=rmetcalfe15@gmail.com&emailsubject=M h
Sydney
Brisbane

You can see changes, today, via the report HTTP://www.rjmprogramming.com.au/PHP/Geographicals/prediff.php?dpath=HTTP://www.rjmprogramming.com.au/&dfilespec=PHP/*/*.*GETME&dmdates=2018-05-10&dmdateb=2018-05-11

Did you know?

The YouTube video access used in the example execution above is based on a YouTube -> Share -> Embed URL that the code looks for to know to embed a YouTube video “embed” URL into an HTML iframe element.


Previous relevant Google Line Area Bar Column Chart Multimedia Background Tutorial is shown below.

Google Line Area Bar Column Chart Multimedia Background Tutorial

The recent Google Pie Chart Multimedia Background Tutorial “guinea pig” approach to multimedia background functionality behind our Google Chart interfacings not only introduced us to bigger guinea pigs but helped build up some code intervention points for those bigger guinea pigs … down, Nala! … us, to extend that functionality to “the awesome foursome” …

  • Line Chart
  • Area Chart
  • Bar Chart
  • Column Chart

As we’d have mentioned before, these four Google Chart types ask for a similar data structure that is behind their workings, and so it is reasonably easy to convert from one to another as per the Google Chart (&onclick=y) select event prompt window options for all these that allow for conversions to the others. By their very nature, depending on the look of your data, that dataset may present better in one of these Google Chart types than the rest.

We take that multimedia data from the Pie Chart case and use the wonderful data from the Australian Bureau of Meteorology (with webpages like Sydney in winter 2016: A warm, wet winter for Sydney) to show in today’s Area Chart tutorial picture using the user prompt window entries …

https://www.rjmprogramming.com.au/PHP/PieChart/qrtr.aifc;https://www.rjmprogramming.com.au/PHP/PieChart/IMG_0631.JPG;https://www.rjmprogramming.com.au/PHP/PieChart/IMG_0018.MOV;The Seasons Explained&onclick=y&emailto=rmetcalfe15@gmail.com&emailsubject=The Seasons Explained via Area Chart
Sydney Season by Year Hottest Days in C
Summer,Autumn,Winter,Spring
2013
46.5,34.9,29.3,39.3
2014
41.9,31.6,25.8,45.3
2015
37.7,37.9,28.9,42.8
2016
42.2,36.6,27.0,37.4
2017
47.0,35.2,29.3,37.3

… to create a Google Chart Area Chart “Sydney Season by Year Hottest Days in C” for the years from 2013 to 2017.

You can see changes, today, via the report HTTP://www.rjmprogramming.com.au/PHP/Geographicals/prediff.php?dpath=HTTP://www.rjmprogramming.com.au/&dfilespec=PHP/*/*.*GETME&dmdates=2018-05-08&dmdateb=2018-05-09′>HTTP://www.rjmprogramming.com.au/PHP/Geographicals/prediff.php?dpath=HTTP://www.rjmprogramming.com.au/&dfilespec=PHP/*/*.*GETME&dmdates=2018-05-08&dmdateb=2018-05-09 below …


Previous relevant Google Pie Chart Multimedia Background Tutorial is shown below.

Google Pie Chart Multimedia Background Tutorial

It’s back to “guinea pig” Google Chart Pie Chart web application interface work today, moving on from yesterday’s Google Map Chart Email Attachment Reply Tutorial Map Chart specifics. Today we want to return to the background image functionality we added a little time ago with Google Chart Pie Chart Background Image Tutorial, so that by the end of today combinations of any/all of …

  • image
  • video
  • audio

… will be possible as background media sources, because, after all, the HTML audio and video are totally flexible “helperer outerers” here given either …

  • URL of a suitable audio or video (or image) media file that we map the file extension to a mime type for … and/or …
  • data URI which will have this mime type defined in all likelihood within its data

… and we want all this to still work emailing your “Pie Chart presentation” off to a recipient.

We made a YouTube video of some QuickTime Player Screen Presentation we did explaining this work …

… which involved, device wise …

  • iPad (Camera app in Video mode) videoing a sheet of paper mostly showing the “Seasons Explained” (moral of the story is 1/4 is same as 25%) presentation … video (s)ftp’ed to rjmprogramming.com.au (and you might want to read Email iPad Image Conduit Tutorial with respect to this, as email cannot “cut the mustard” with anything but the smallest of videos) … we just also …
  • take an overall photo of the setup with an iPhone (Camera app in Photo mode) … image (s)ftp’ed to rjmprogramming.com.au … and is today’s tutorial picture … while …
  • QuickTime Player Audio Capture on MacBook Pro … audio (s)ftp’ed to rjmprogramming.com.au … and …
  • QuickTime Player Screen Capture on MacBook Pro … helped make the YouTube video upload above

The PHP code changes to pie_chart.php … can be tried here, in a generic sense, or to simulate what you see up above today, the prompt window entries required after clicking that last link, are, respectively …

https://www.rjmprogramming.com.au/PHP/PieChart/qrtr.aifc;https://www.rjmprogramming.com.au/PHP/PieChart/IMG_0631.JPG;https://www.rjmprogramming.com.au/PHP/PieChart/IMG_0018.MOV;The Seasons Explained&onclick=y&emailto=rmetcalfe15@gmail.com&emailsubject=The Seasons Explained via a Pie Chart
Season
Percentage
Summer
25
Autumn
25
Winter
25
Spring
25

Previous relevant Google Map Chart Email Attachment Reply Tutorial is shown below

Google Map Chart Email Attachment Reply Tutorial

Yesterday’s Google Chart Email Attachment Reply Tutorial helped in some ways with today’s parallel email attachment reply logic we apply to the Google Chart Map Chart interface today.

This Map Chart interface is a whole independent story, because we cannot use the external Javascript we normally use.

Along the way we realized that it could be good not to restrict the user to only appending …

  • &emailto=[emailee] … as well as …
  • &emailsubject=[EmailSubject]
  • &emailcc=[EmailCC]
  • &emailbcc=[EmailBCC]

… when replying to emails, but also allow then to add this between data set array members. Why is that? Well, our experience with the Dams of the USA web application for example, it will be too hard to reach the end of the data easily within the prompt window textbox.

We also tee up “latitude,longitude” fillins when the user chooses to follow the prompt advice and enter something like …


Sydney|Australia/Sydney|+11|12:32

It already fills in for an entry such as …


Sydney

… for instance, teeing up with a place found within the PHP TimeZone information list.

Feel free to take a look at the PHP map.php‘s changes today, and compare to the live run experience of establishing an emailee to communicate with, and to see what their download experience is.


Previous relevant Google Chart Email Attachment Reply Tutorial is shown below.

Google Chart Email Attachment Reply Tutorial

Today’s work did not pan out as planned, but that can almost be par for the course, when you “go interfacing”. You spend time nutting things out, then they interest, and that could be you for the day. The more gifted of us, half the day, perhaps. So today started in thought as a Google Chart Map Chart interface day, but that is for the future, as we ended up (on the same theme as yesterday’s Google Chart Email Attachment Mobile Tutorial) picking on our “guinea pig” Google Chart Pie Chart interface because we started the day testing this scenario …


Pie Chart &onclick=y &emailto=rmetcalfe15@gmail.com method=POST to location.protocol = file: scenario email attachment Pie Chart select event (click) menu "what shows as the prompt window default answer" test

… hoping, and expecting to see the &data= data … sad to say “no” though … earlier in the day that is … now you can … but actually, what the test showed was worse than that, it showed no &data= data even for the location.protocol = http: and https: scenarios … we hadn’t nailed that down yet, even on the “guinea pig” … no “guinea pigs” nor “guinea fowl” were injured in the making of this blog post …. In our defence, this is in no way trivial. Huh?! You might say … you don’t say?. Well, even for the location.protocol = http: and https: scenarios what you are asking for here is …

  • user selects &onclick=y &emailto=rmetcalfe15@gmail.com within answer to their Pie Chart title … no problems … can do … but …
  • should they supply a huge &data= data set answer (and we cheat with unit testing today setting the limit small) that our Javascript (function) “toolong” needs to wrap around any …

    location.href=toolong([PieChartURL]);

    … checking for [PieChartURL] lengths over this limit we talk about above (which when live reflects a URL length limit for the rjmprogramming.com.au web server (to avoid error 414)) and switching to the non-default method=POST HTML form navigation Javascript DOM’ed “on the fly” … which …
  • sends email with (location.protocol = file: scenario version of) HTML attachment in an email to rmetcalfe15@gmail.com (ie. moi) … the emailee (ie. moooiii) …
  • opens the email in a web browser webmail URL access way to access emails for that emailee (on whatever device we are considering, which is just straight MacBook Pro today) … clicks the attachment to …
  • open email attachment HTML to be presented with a very similar Pie Chart look as left off in location.protocol = http: or https: scenario “land” … then …
  • click a Pie Chart sector calling on our inhouse select event (click) menu logic … closing eyes because …
  • damn! … the default Javascript prompt window answer is not the &data= data (ie. if it was we could just alter this default answer and shoot off another Pie Chart with that altered &data= data set)

So why wouldn’t that default prompt window answer not show? We knew. We’d forgotten to cater for the method=POST way of navigation, which in basic terms consists of …

  1. URL in web browser address bar (just like at the beginning of a session, and like location.protocol = file: email attachment download and open scenarios) that has no ? nor & arguments … the difference from a beginning URL being …
  2. behind the scenes, invisible to a client-only “solution” like for HTML/Javascript/CSS (and invisible to location.protocol = file: email attachment download and open scenarios, also), where (server side) PHP (can see the) $_POST array filled in with data (that normally is too long to be suited to the PHP $_GET[] array equivalent of the client side use of URLs with ? and & arguments)

Where can these two worlds meet? In Javascript client side “land” they can meet, with no length issues, in a Javascript (global) variable … that’s where. PHP …


var documentURL = document.URL , locationhref='', etodi='emailee', etodicc='EmailCC', etodibcc='EmailBCC', etodisubject='EmailSubject';
documentURL=documentURL.split('#')[0];

<?php
if (isset($_POST[‘data’])) {
$appval=””;
$appvald=”?”;
if (strlen($_SERVER[‘QUERY_STRING’]) > 1) $appvald=”&”;
foreach ($_POST as $name => $val) {
$appval.=$appvald . htmlspecialchars($name) . “=” . str_replace(“+”,”%20″,urlencode(htmlspecialchars($val)));
$appvald=”&”;
}
echo “\n documentURL=document.URL.split(‘#’)[0] + \”” . $appval . “\”; \n”;
}

… can help derive this (global) variable “documentURL” and “locationhref” useful in the location.protocol = http: or https: scenarios but needing more to do within the realms of location.protocol = file: scenario version of the logics, just before the email attachment HTML is formed, that HTML’s document.body.outerHTML is now wrapped as per makeright(document.body.outerHTML)


function makeright(inbo) {
if (typeof documentURL === "undefined") {
inbo=inbo;
} else {
if (documentURL.indexOf('&') != -1 && inbo.indexOf('<bo' + 'dy') != -1) {
if (inbo.indexOf('</bo' + 'dy>') != -1) {
inbo=inbo.replace('</bo' + 'dy>', + '<scr' + 'ipt type="text/javascript"> function dub() { ' + " documentURL=\"" + documentURL + "\"; if (documentURL.indexOf(\"&data=\") != -1) { paramdata=(documentURL + \"&\").split(\"&data=\")[1].split(\"&\")[0]; pardata=encodeURIComponent(paramdata); } } " + ' </scr' + 'ipt></bo' + 'dy>');
} else {
inbo+='<scr' + 'ipt type="text/javascript"> function dub() { ' + " documentURL=\"" + documentURL + "\"; if (documentURL.indexOf(\"&data=\") != -1) { paramdata=(documentURL + \"&\").split(\"&data=\")[1].split(\"&\")[0]; pardata=encodeURIComponent(paramdata); } } " + ' </scr' + 'ipt>';
}
if (inbo.split('<bo' + 'dy')[1].split('>')[0].indexOf(' onload=') == -1) {
return inbo.replace('<bo' + 'dy', '<bo' + 'dy onl' + "oad=' setTimeout(dub,300); ' ");
} else if (inbo.indexOf('<bo' + 'dy onl' + 'oad="') != -1) {
return inbo.replace('<bo' + 'dy onl' + 'oad="', '<bo' + 'dy onl' + 'oad=" setTimeout(dub,300); ');
}
}
}
return inbo;
}

… so that as the emailee downloads and opens their email attachment HTML it populates that same (global) variable “documentURL” which is used in a new fashion in new Javascript prompt window answer analysis Javascript code as per (that used to use “document.URL” and “location.href” and we used not to have “toolong() wrapping”) …


if (documentURL.indexOf(pardata) != -1 && ans.indexOf('&') == -1) {
locationhref=toolong(documentURL.replace(pardata, ourencodeURIComponent(ans)));
if (locationhref != '#') { location.href=locationhref; } locationhref='';
} else if (documentURL.indexOf('data=') != -1 && ans.indexOf('&') != -1) {
var vbn=documentURL.split('&data=')[0] + ans.replace(ans.split('&')[0],'').replace(/\'/g,'`') + '&data=' + documentURL.split('&data=')[1];
locationhref=toolong(vbn.replace(vbn.split('data=')[1].split('&')[0], ourencodeURIComponent(('' + ans.split('&')[0]))));
if (locationhref != '#') { location.href=locationhref; } locationhref='';
} else if (documentURL.indexOf(pardata) != -1) {
locationhref=toolong(documentURL.replace(pardata, ourencodeURIComponent(ans)));
if (locationhref != '#') { location.href=locationhref; } locationhref='';
} else if (documentURL.indexOf('data=') != -1) {
locationhref=toolong(documentURL.replace(documentURL.split('data=')[1].split('&')[0], ourencodeURIComponent(('' + ans))));
if (locationhref != '#') { location.href=locationhref; } locationhref='';
}

… we hope ensuring that variable “paramdata” is populated by the &data= data ready to be the default select event (click) menu logic’s prompt window’s default answer. But it is not just that “getting back to square one” for our “guinea pig”. Moving forward, the implication of having this in place is very good, because we can now go forward allowing the user to append their own …

  • &emailto=[emailee] … as well as …
  • &emailsubject=[EmailSubject]
  • &emailcc=[EmailCC]
  • &emailbcc=[EmailBCC]

… to user answers (as we show you a bit of with today’s tutorial picture), meaning that the emailee could reply to the emailer with a new email subject and a new emailto (more than likely), perhaps with an adjusted Pie Chart data set as well, back to the emailer (or someone else) in a conversational web application capability (for any of location.protocol file: or http: or https: scenarios).

PHP and Javascript code wise …

From little guinea pigs, bigger guinea pigs grow?!


Previous relevant Google Chart Email Attachment Mobile Tutorial is shown below.

Google Chart Email Attachment Mobile Tutorial

We’re working towards trying to make the HTML coming off an email attachment (of a mobile device’s web browser’s webmail URL such as https://gmail.com on Safari on an iPad) be of some comparability in terms of its functionality as the original webpage, continuing on from yesterday’s Google Chart Email Attachment Post Tutorial. There are issues. Things to consider are …

  • iOS devices do not regard an HTML form target=_blank (and it seems, other target values) … when in a …
  • location.protocol = file: (ie. a local file system access) scenario to be wise, shall we say … and …
  • the “pins” of our Google Chart Map Chart interface don’t show in this scenario either

For this goal we have, we needed to break large data sets up into subsets whose URL length would be alright with the limits up at the rjmprogramming.com.au domain web server.

Funnily enough, using Google Chrome web browser on an iPad did not change the issues above.

Take a look at the PHP map.php‘s changes today, and compare to the live run experience of establishing an emailee to communicate with, and to see what their download experience is.


Previous relevant Google Chart Email Attachment Post Tutorial is shown below.

Google Chart Email Attachment Post Tutorial

Yesterday’s Google Chart Email Attachment Tutorial intimated …

For the $_POST[] scenario, we’ll need to chip away at each parent Google Chart interface PHP web application code. Home and hosed?! Not yet, still fixing the leaks!

… and so that was a lot of today’s work for Google Chart interfacings, here …

  • Pie Chart
  • Line Chart
  • Area Chart
  • Bar Chart
  • Column Chart
  • Geo Chart
  • Intensity Chart
  • Map Chart

… in general terms revolving around the addition of the following Javascript (via PHP as well) code placed before a </script> tag …


function preclickforemail() {
<?php
if (isset($_POST['emailto'])) {
if (strpos(urldecode($_POST['emailto']), '@') !== false) {
if (isset($_POST['emailto'])) echo "\n if (document.getElementById('theto') && yesgo) { document.getElementById('theto').value='" . urldecode($_POST['emailto']) . "'; } \n";
if (isset($_POST['emailsubject'])) echo "\n if (document.getElementById('thesubject') && yesgo) { document.getElementById('thesubject').innerHTML=\"" . urldecode($_POST['emailsubject']) . "\"; } \n";
if (isset($_POST['emailcc'])) echo "\n if (document.getElementById('thecc') && yesgo) { document.getElementById('thecc').value='" . urldecode($_POST['emailcc']) . "'; } \n";
if (isset($_POST['emailbcc'])) echo "\n if (document.getElementById('thebcc') && yesgo) { document.getElementById('thebcc').value='" . urldecode($_POST['emailbcc']) . "'; } \n";
echo "\n
if (yesgo) {
yesgo3='MAILTO:" . urldecode($_POST['emailto']) . "';
nogo3='MAILTO:fillin.email@address';
yesgo2='\"' + document.URL.split('#')[0].split('?')[0].substring(0,10) + document.URL.split('#')[0].split('?')[0].substring(10).split('/')[0] + '/PHP/butsel.php';
nogo2='\"//www.rjmprogramming.com.au/PHP/butsel.php';
if (document.getElementById('another')) {
yesgo=document.getElementById('another').href=document.URL.split('#')[0].split('?')[0];
nogo='./' + document.URL.split('#')[0].split('?')[0].split('/')[eval(-1 + document.URL.split('#')[0].split('?')[0].split('/').length)];
}
}
\n ";
echo "\n if (clickforemail) { clickforemail(); } else if (document.getElementById('thesemail')) { document.getElementById('thesemail').click(); } \n";
}
}
?>
}

<?php
if (isset($_POST[’emailto’])) {
if (strpos(urldecode($_POST[’emailto’]), ‘@’) !== false) {
echo “\n setTimeout(preclickforemail,4000); \n”;
}
}
?>

You can see changes for via the report HTTP://www.rjmprogramming.com.au/PHP/Geographicals/prediff.php?dpath=HTTP://www.rjmprogramming.com.au/&dfilespec=PHP/*/*.*GETME&dmdates=2018-04-28&dmdateb=2018-04-29′>HTTP://www.rjmprogramming.com.au/PHP/Geographicals/prediff.php?dpath=HTTP://www.rjmprogramming.com.au/&dfilespec=PHP/*/*.*GETME&dmdates=2018-04-28&dmdateb=2018-04-29 below …

… and it was with the last of these that the implications for additional “sharing email” possibilities opens up, so we not only changed the PHP “parent” of the interfacings above but quite a few applications using that Map Chart, above, for lots of posted data. Think (the web applications of) …

… where a combination of HTML select element new options and new HTML input type=button elements helps with the email (via HTML attachment) interfacing. The real practical use, though, we would contend, is to use these tools to aid with map presentations and explanations via a series of emails to and from
your emailee.

You can see changes for via the report HTTP://www.rjmprogramming.com.au/PHP/Geographicals/prediff.php?dpath=HTTP://www.rjmprogramming.com.au/&dfilespec=[HP][TH][MP]*/*.*GETME&dmdates=2018-04-28&dmdateb=2018-04-29 below …


Previous relevant Google Chart Email Attachment Tutorial is shown below.

Google Chart Email Attachment Tutorial

Google Chart chart data is worth sharing, and we share with email using our interfacing PHP web applications. There are a few reasons for today’s additional email “attachment” design functionality today (augmenting yesterday’s Google Chart Pie Chart Background Image Tutorial), that we think are improvements to the existing “link in an email (to the RJM Programming domain URL)” email arrangements …

  • an attachment in an email can snapshot the scenario of the emailer in a more direct way … and …
  • downloading it provides the snapshot on the emailee’s local system, and/or on their local web browser, potentially stored locally for as long as the emailee requires …
  • is a more dynamic sharing response …
  • can be used to handle the larger data sets, coming up more often now, with clipboard and image and CSV data ideas lately

We arrange these changes at the …

  • generic external Javascript gchartgen.js which changed for this work, in this way … for those PHP web applications that don’t call gchartgen.js they make their own parallel coding arrangements … and …
  • generic helper (for emailing) PHP webviewemail.php which changed for this work, in this way

In the simplest scenario, we have a very simple arrangement to make in the “parent” code of each Google Chart interfacing, that being the verification that it is ready by having exist before </body> …


<div id="thedivemail"></div>

The email, with HTML attachment, navigation, as required, is placed into the innerHTML of this HTML div element …

  • method=POST … to handle large or small data sets …
  • target=theiemail … which is a reference to …

    <iframe name=theiemail id=theiemail style='display:none;' src='../webviewemail.php'></iframe>
  • onsubmit=”

    if (document.getElementById('theto').value.indexOf('@') == -1) {
    return false;
    } else {
    fixanother();
    if (document.getElementById('thesubject').value == '' || document.getElementById('thesubject').innerHTML == '') {
    document.getElementById('thesubject').value='Google Chart Interfacing via RJM Programming';
    }
    var hcis='<!DOCTYPE HTML PUBLIC ' + String.fromCharCode(34) + '-//W3C//DTD HTML 4.0 Transitional//EN' + String.fromCharCode(34) + '><html></head>' + document.head.innerHTML + document.body.outerHTML.split('<div id=' + String.fromCharCode(34) + 'thedi' + 'vemail' + String.fromCharCode(34) + '>')[0] + '</body></html>';
    document.getElementById('thehtml').value=hcis.replace(/\+/g,'%2b').replace(nogo,yesgo).replace(emailtitle,'');
    return true;
    }

… and the timing of populating that HTML textarea ‘thehtml’ value is after the client document.body onload event of the complete Google Chart, and this is automatic when gchartgen.js is getting URL ? and & parameters in a $_GET[] scenario. For the $_POST[] scenario, we’ll need to chip away at each parent Google Chart interface PHP web application code. Home and hosed?! Not yet, still fixing the leaks!


Previous relevant Google Chart Pie Chart Background Image Tutorial is shown below.

Google Chart Pie Chart Background Image Tutorial

We have another potential use for the clipboard, adding onto the recent Google Pie Chart via Clipboard Co-ordinates Tutorial data set usage, today. We allow the user to change the default white background to the Google Chart Pie Chart be tailored to be either …

  • image URL … or …
  • image data URI (most likely entered via the clipboard)

… as a prefixing option when they enter in the Title of their Pie Chart.

In order to achieve this, we were helped enormously by …

  • this very useful link, thanks … the crux of it being to get to put …

    backgroundColor: 'none'

    … into the Pie Chart options … and some previous help we got when we presented …
  • Column Intelligence Primer Tutorial‘s “Did you know?” section reference to incredibly useful link‘s advice on our …

    wish to apply opacity just to background image, but not the corresponding textual data (or other types) that is the primary content of that HTML element

You can see a video of some of the practicalities to usage on an iPad mobile app version in the YouTube video below …

Because data URIs are an option here, too, you will see in the code changes to pie_chart.php the need, now, to cater for the switch of HTML form navigation from …

  • method=GET (the default) … to …
  • method=POST (when the URL becomes too long)

… and that new bit of logic is slated home to the generic external Javascript we have set aside for Google Charts work called gchartgen.js which changed for this work, in this way.

Maybe you can see how to use this feature yourself, and if that is the case you can try this live run link.


Previous relevant Google Pie Chart via Clipboard Co-ordinates Tutorial is shown below.

Google Pie Chart via Clipboard Co-ordinates Tutorial

Yesterday’s Google Map Chart via Clipboard Co-ordinates Tutorial was a good precursor to today’s work interfacing this time to the Google Chart Pie Chart.

With this work, we’ve started refining the clipboard “smarts” by looking for linefeeds … in Javascript thoughts …


String.fromCharCode(10)

… and as the data exits the Javascript prompt window on its way, before navigating back to the PHP itself, we can check for too many fields to the right of the data, and truncate the clipboard data, as necessary. Along the way, we may be able to reject any header records with this same approach. We can check for no numerical fields here. Business specific logic can be applied here too. With a Pie Chart, the original data, or the user, may be tempted to place “%” after the numerical data, and we can take the opportunity to weed these out. Also, with the character data, it may be delimited by a double quote (ie. within “”), and with this knowledge in mind, we may be able to weed out confusing additional commas that could confuse us with the clipboard comma separated value format of the data.

The lesson here, is to “validate early” and it could be good to “validate often” as well. Real data can be strange indeed.


function dlp(thisris) {
if (thisris != null) {
var commacount=thisris.toLowerCase().replace(/\<\/td\>/g,' , ').indexOf(',');
if (thisris.toLowerCase().replace('https:','http:').indexOf('http:') == 0) {
fti=true;
allowed=true;
datac=thisris;
} else if (commacount >= 0) {
var thatris=thisris.replace(/\ \"/g,String.fromCharCode(10) + '"').replace(/\<tr\>/g,'').replace(/\<\/td\>\<td\>/g,',').replace(/\<\/tr\>/g,String.fromCharCode(10)).replace(/\<\/td\>/g,',').replace(/\,\,/g,',').replace(/\,\,/g,',').replace(',' + String.fromCharCode(10),String.fromCharCode(10));
var zisok=true, fldq=thatris.split(',');
var pielines=thatris.split(String.fromCharCode(10));
if ((fldq[0].replace('"','').trim() + ' ').substring(0,1) < '0' || (fldq[0].replace('"','').trim() + ' ').substring(0,1) > '9') {
if ((fldq[eval(-1 + fldq.length)].replace('"','').trim() + ' ').substring(0,1) < '0' || (fldq[eval(-1 + fldq.length)].replace('"','').trim() + ' ').substring(0,1) > '9') {
zisok=false;
}
}
if (!zisok && pielines.length > 1) {
fldq=pielines[1].split(',');
zisok=true;
if ((fldq[0].replace('"','').trim() + ' ').substring(0,1) < '0' || (fldq[0].replace('"','').trim() + ' ').substring(0,1) > '9') {
if ((fldq[eval(-1 + fldq.length)].replace('"','').trim() + ' ').substring(0,1) < '0' || (fldq[eval(-1 + fldq.length)].replace('"','').trim() + ' ').substring(0,1) > '9') {
zisok=false;
}
}
}
if (zisok) {
while (thatris.indexOf(String.fromCharCode(10)) != -1) {
var inpies, pied='';
thatris='';
var sthatris='';
for (var ipie=0; ipie<pielines.length; ipie++) {
inpies=pielines[ipie].split(',');
if (inpies.length > 1) {
if ((inpies[0].trim() + " ").substring(0,1) == '"' && (inpies[1].trim() + " ").substring(0,1) == '"') {
sthatris=pied + inpies[0].trim().substring(1).split('"')[0].trim().replace('%','').replace(',','').replace(',','') + ',' + inpies[1].trim().substring(1).split('"')[0].trim().replace('%','').replace(',','').replace(',','');
} else if ((inpies[0].trim() + " ").substring(0,1) == '"') {
sthatris=pied + inpies[0].trim().substring(1).split('"')[0].trim().replace('%','').replace(',','').replace(',','') + ',' + inpies[1].trim().replace('%','').replace('"','');
} else if ((inpies[1].trim() + " ").substring(0,1) == '"') {
sthatris=pied + inpies[0].trim().replace('%','') + ',' + inpies[1].trim().substring(1).split('"')[0].trim().replace('%','').replace(',','').replace(',','');
} else {
sthatris=pied + inpies[0].trim().replace('%','') + ',' + inpies[1].trim().replace('%','').replace('"','');
}
inpies=sthatris.replace(pied,'').split(',');
if (((inpies[0].trim() + " ").substring(0,1) >= '0' && (inpies[0].trim() + " ").substring(0,1) <= '9') || ((inpies[1].trim() + " ").substring(0,1) >= '0' && (inpies[1].trim() + " ").substring(0,1) <= '9')) {
thatris+=sthatris;
pied=',';
}
}
}
}
thatris=thatris.replace(/\,\,/g,',');
fti=true;
allowed=true;
datac='http;' + thatris;
thisris='http;' + thatris;
}
}
}
return thisris;
}

Our PHP Google Chart Pie Chart interface is pie_chart.php changed this way for today’s work, that you can try yourself at this live run link.

Our PHP helper csv.php changed this way for today’s work.

If you want to recreate the conditions as shown in today’s tutorial picture

  1. copy the contents below …

  2. and paste into the 4th prompt (window’s text) box of the Google Charts Pie Chart interfacing live run link
  3. click OK button … P.S. On first prompt, appending &onclick=y to what you want as a Pie Chart title will work the Pie Chart’s select event logic we harness with this interfacing
  4. … or, if you are feeling lazy …
    https://www.rjmprogramming.com.au/PHP/PieChart/pie_chart.php?title=Country%20Populations&onclick=y&task=Country&desc=Populations&data=,%20[~https;China,1347000000,India,1241000000,United%20States,312000000,Indonesia,238000000,Brazil,197000000,Pakistan,177000000,Nigeria,162000000,Bangladesh,151000000,Russia,143000000,Japan,128000000,Mexico,115000000,Philippines,96000000,Vietnam,88000000,Ethiopia,87000000,Germany,81800000,Egypt,82600000,Iran,78000000,Turkey,74000000,Thailand,69500000,Congo,67800000,France,63300000,United%20Kingdom,62700000,Italy,60800000~,100]

Previous relevant Google Map Chart via Clipboard Co-ordinates Tutorial is shown below.

Google Map Chart via Clipboard Co-ordinates Tutorial

Yesterday’s Google Map Chart via URL Co-ordinates Tutorial added functionality directed towards a …

  • secondary data source, that you access … but today we are going to extend that functionality to support a …
  • primary data source that you enter a comma separated values list for the [place,lat,long] data sets (yourself, via the computer keyboard) … as well as a …
  • “subset” of a secondary data source, that you access, more than likely, using you computer device’s clipboard

The invention of the clipboard was a brilliant step. Before it, we were so beholden to programmers to get tailored work done, and though it’s sad that so many of you get on without us (cough, cough) … well … we were being overworked anyway … and there was that project to “make the morning breakfast coffee before you even know you wanted it” to get onto … finally.

Perhaps we all forget now what the clipboard has meant, for so many of us. It is the freedom of “copy and paste”, the individualism tool of content creation.

Yesterday’s functionality idea is a case in point. “Secondary data sources” are, by definition, out of your control, as to what the content of a web page is. Notice how, yesterday, we made some content that was (s)ftp transferred over to the rjmprogramming.com.au domain via … yes, you guessed it …

  1. me copying (off the mapbox.com website, thanks, as part of the contents of a webpage) … then …
  2. pasting that content into a csv text file on the MacBook Pro computer we’re using (locally) … and then …
  3. (s)ftp transferred over to rjmprogramming.com.au domain to represent a …
  4. URL usable within the functionality of our Google Chart Map Chart interface we host here as the PHP map.php‘s live run link

But there you are, an intelligent human, able to determine for yourself the data you are interested in (quite often not the entire contents of a webpage, as yesterday’s work is ideally asking for), so that being the case, the map.php modifications to PHP code we’ve made today, make it possible for (the much simpler) …

  1. me copying (off the mapbox.com website, thanks, as part of the contents of a webpage) … then …
  2. pasting that content within the functionality of our Google Chart Map Chart interface we host here as the PHP map.php‘s live run link

If you have the clipboard as your friend, your time around computers becomes so much more enjoyable, and flexible, and within your control. We, as programmers, need to think, on occasions, or encourage, on occasions, how the user is likely to use the clipboard, in conjunction with our applications. As you might surmise, that can be a pretty unpredictable “artform”.

Our PHP helper csv.php changed this way for today’s work.


Previous relevant Google Map Chart via URL Co-ordinates Tutorial is shown below.

Google Map Chart via URL Co-ordinates Tutorial

The last blog posting referring to the Google Chart Map Chart interface we host here was with Emoji Name Search Map Chart Weather Tutorial, but today we are presenting a major functionality addition with implications for other Google Chart interfacing PHP codesets here. We are allowing the user at the second prompt to take the data from a URL data source containing CSV (comma separated values) place,latitude,longitude data or those three fields in an HTML table element contents perhaps.

We’ve added the ability to “map” (tee hee) …


HTTP://www.rjmprogramming.com.au/PHP/Map/map.php?title=Where%20We%20Are&onclick=y&label=['Lat',&value='Lon',%20'Name']&data=,%20[-33.90743410270099,151.17646964910696,~Parent1~]%20,%20[-33.907440603083124,151.1764659419197,~Parent2~]

… from a CSV data URL look with contents …


-33.907434102700991,151.17646964910696,Parent1
-33.907440603083124,151.17646594191973,Parent2

… that if placed at rjmprogramming.com.au’s Document Root and called parent.csv then a URL of …


HTTP://www.rjmprogramming.com.au/PHP/Map/map.php?title=Where%20We%20Are&onclick=y&label=['Lat',&value='Lon',%20'Name']&data=,%20[0.00000001,0.0000000,~HTTP://rjmprogramming.com.au/parent.csv~]

… could be a shortcut to that first URL same look. You can see another example using data from mapbox.com, thanks, show the scenario our tutorial picture illustrates.

The way this “mapping” (tee hee, tee hee) of URLs can happen is that the PHP supervisor map.php (changed this way and which you can try with this live run link) “includes” (ie. calls) …


include "../csv.php";

… a (now bigger, and more functional) csv.php (changed this way) does its best to handle a few looks to the CSV or tabular data, with code to allow for …

  • CSV data ordered place,latitude(decimal),longitude(decimal) or latitude(decimal),longitude(decimal),place or place,longitude(decimal),latitude(decimal) or longitude(decimal),latitude(decimal),place
  • CSV data ordered place,latitude(W/S/E/N_deg_min_secs),longitude(W/S/E/N_deg_min_secs) or latitude(W/S/E/N_deg_min_secs),longitude(W/S/E/N_deg_min_secs),place or place,longitude(W/S/E/N_deg_min_secs),latitude(W/S/E/N_deg_min_secs) or longitude(W/S/E/N_deg_min_secs),latitude(W/S/E/N_deg_min_secs),place
  • HTML tabular data ordered place,latitude(decimal),longitude(decimal) or latitude(decimal),longitude(decimal),place or place,longitude(decimal),latitude(decimal) or longitude(decimal),latitude(decimal),place
  • HTML tabular data ordered place,latitude(W/S/E/N_deg_min_secs),longitude(W/S/E/N_deg_min_secs) or latitude(W/S/E/N_deg_min_secs),longitude(W/S/E/N_deg_min_secs),place or place,longitude(W/S/E/N_deg_min_secs),latitude(W/S/E/N_deg_min_secs) or longitude(W/S/E/N_deg_min_secs),latitude(W/S/E/N_deg_min_secs),place

Previous relevant Emoji Name Search Map Chart Weather Tutorial is shown below.

Emoji Name Search Map Chart Weather Tutorial

If you’ve been studying the code of our hierarchy for our Emoji Flags of the World web application …

… am sure you’ll have noticed how bottom heavy it is on the “child” as far as functionality goes. What we like to call “the hard working duck syndrome”. Partly, that is because we see the Google Charts Map Chart interface we have as being a very useful “meeting point” with interfacing web applications tending towards the “where” of life.

Today’s job, extending yesterday’s Emoji Name Search Map Chart Tutorial is to add Map Chart interfacing to the great Weather Underground and its great API service for autocomplete name searches for weather (and hurricane) information … thanks.

The changes are again just to that “hard working duck” Map Chart interface “child” web application, as for yesterday’s work. We were very keen to do this, especially because …

  • Weather Underground database works most succinctly with Placename, Country identification pairs, better than for the …
  • Continent/Placename setup of (PHP) Timezones

… and so, while we are going to so much trouble scouring Timezone places for their associated Countries, it is a really good opportunity to slot in some Weather API interfacing to our Emoji World Flags web application, which is starting to be looking better and better as a trip planning aid.


Previous relevant Emoji Name Search Map Chart Tutorial is shown below.

Emoji Name Search Map Chart Tutorial

We now have a three tier functionality hierarchy for our Emoji Flags of the World web application …

… all made so very possible when web applications sit in the same domain and you utilize the HTML iframe element.

We wanted to enhance its integration by …

  • adding in “locality pins” for all PHP Timezone places in the country of interest
  • involving Emoji flags in the Map Chart title (rather than as a pin) because Emojis, after all, are like textual data, not HTML (but can use HTML Entity representations in both)

To work the latter of these we called on recent experience with the “Fifth Beatle” discussion in Emoji Name Search Primer Tutorial

We got quite excited recently with Rainbow Games PHP Emoji Tutorial when we added a (fourth Beatle) emoji helper, called Emoji Terra, into the mix of tools to gather emoji information. Today, we’ve got a new Emoji Search web application that introduces a new (fifth Beatle(?)) emoji helper tool to add into the “how we see it” mix …

We found that Emoji Terra could be used in our map Chart interfacing PHP to look up the HTML Decimal Entity for a flag of a country via the URL pattern …


HTTP://www.emojiterra.com/flag-for-[CountryNameSpacesMakeMinusSignsLowerCase]

So even though Google Chart Map Charts do not allow HTML in their titles there is nothing stopping you putting in an HTML Entity Emoji coding.

As far as the former goes, we again called on the PHP DateTimeZone class to scrutinize the first Timezone in the Map Chart title, derive its ISO 2 letter Country Code, and look through the array list of (PHP) Timezones to garner latitude and longitude, time now, and GMT offset information necessary to improve the “where” and “when” aspects of our Google Chart Map Chart interfacing.


Previous relevant Emoji Name Search Timezone Tutorial is shown below.

Emoji Name Search Timezone Tutorial

Yesterday’s Emoji Name Search Map Tutorial was a step in the direction of “where” functionality, but because PHP teams up with the supervisory HTML “Emoji World Flags” web application, to make all this happen, there is the opportunity to add interest by adding a “when” aspect to how it works.

As we’ve said many times now, should you have access to PHP, you also have access to its DateTimeZone class where Timezones can be linked to ISO 2 letter Country Codes, useful as an integration point as of recent times when we introduced ISO 2 letter Country Codes to today’s (supervisory) live run‘s world_flags.html HTML and Javascript code.

But it is not HTML code that changes today. It is its PHP partner emoticon_keyboard_shortcuts.php changed in this way, that arranges that its call of Google Charts Map Chart passes across a new URL …


&ccode=[ISO 2 letter Country Code]

… argument that uses a new PHP function as below (arrays shortened for practicality purposes) …


<?php
function inctycodecheck($incd, $sofar) {
$nearname=["Africa/Abidjan","Africa/Accra", ... ]; // array of Timezone names
$retv="";
$retd="";
$otz = new DateTimeZone("UTC");
$jj=0;
$origin_dt = new DateTime("now", $otz);
for ($best1=0; $best1<sizeof($nearname); $best1++) {
try {
$tz = new DateTimeZone($nearname[$best1]);
$cloc = $tz->getLocation();
$ctrycode = $cloc['country_code'];
if (strtoupper($incd) == strtoupper($ctrycode)) {
$remote_dt = new DateTime("now", $tz);
$offset = ($tz->getOffset($remote_dt) - $otz->getOffset($origin_dt)) / 3600;
$newp=$retd . $nearname[$best1] . "/" . $remote_dt->format('Y-m-d_H:i:s') . " (GMT" . $offset . ")";
$huhs=explode(" (GMT" . $offset . ")", $retv);
if (sizeof($huhs) == 2) {
if (explode("/", $newp)[0] != explode("/", explode(",", $huhs[0])[-1 + sizeof(explode(",", $huhs[0]))])[0]) {
$huhs=explode("youwillneverfindthis", $retv);
}
}
if (($sofar + strlen(urlencode(($retv . $newp)))) < 950 && $jj < 10 && sizeof($huhs) == 1) {
$retv.=$newp;
$retd=",";
$jj++;
}
}
} catch (Exception $exc) { }
}
return $retv;
}
?>

… called later in the code with the new block of code as per …


<?php
$urlis=urldecode($_GET['gmc']); // URL to point at template Google Chart Map Chart call for Country of interest
if (strpos($urlis, ',,') !== false) {
$urlis=str_replace(",,", urlencode($latis . "," . $longis . ","), $urlis);
} else {
$urlis=str_replace(urlencode(",,"), urlencode($latis . "," . $longis . ","), $urlis);
}
if (isset($_GET['ccode'])) {
$urlis=str_replace("&onclick=", "%20" . urlencode(inctycodecheck(urldecode($_GET['ccode']), (strlen($urlis) + 3))) . "&onclick=", $urlis); // appends to the title argument
}

if (isset($_SERVER['HTTPS'])) {
if ($_SERVER['HTTPS'] == "on") {
header("Location: https:" . $urlis);
} else {
header("Location: http:" . $urlis);
}
} else {
header("Location: http:" . $urlis);
}
exit;
?>


Previous relevant Emoji Name Search Map Tutorial is shown below.

Emoji Name Search Map Tutorial

Yesterday’s posted data Emoji Name Search Posting Tutorial functionality opened the door to “where” web application (software) integration, because the wonderful Wikipedia has compiled Latitude,Longitude co-ordinate pairs for those countries, and that is our foot in the door to place an HTML a link under the Emoji flags, that points to our favourite “where” interfacing tool, the Google Charts Map Chart.

Because the Map Chart and Emoji Flag web application share the same domain we can keep this functionality on this same Emoji Flag webpage in an …

  • HTML iframe element name=gcmi id=gcmi initially invisible … “populated by” …
  • HTML a element target=gcmi href=[URL to Map Chart for Country of Interest] onclick=aoc();

    function aoc() {
    document.getElementById('gmci').style.width='450px';
    document.getElementById('gmci').style.height='450px';
    document.getElementById('gmci').style.display='inline-block';
    }

Another way to zoom around the world online!

You can try the Emoji Flags live run (with underlying world_flags.html changed this way) or the other Emoji functionalities that have this live run and/or its PHP source code emoticon_keyboard_shortcuts.php changed in this way to extend its software integration capabilities.


Previous relevant Emoji Name Search Posting Tutorial is shown below.

Emoji Name Search Posting Tutorial

Yesterday’s Emoji Name Search Tailoring Tutorial was suitable for data sets of that smaller size able to be handled by the web server limit of URL length. But what if there are too many data items in your data set to be handled by PHP’s $_GET[] array URL ? and & delimited URLs? We, having PHP serverside code at our disposal, can turn to $_POST[] (HTML) method=POST form action=[here’sLookingAtYouKid] scenarios, to get around this issue. The unfortunate side effect of this is that the HTML mailto: a link (email client) method of sharing your Emoji web application relies on that $_GET[] approach, that is, unless you wrote a whole “bespoke” web application to help out, like we do today for our new Emoji “World Flags” web application with this live run, with this HTML and Javascript world_flags.html source code.

That new “supervisor” being a guinea pig idea into the $_POST[] thinking, we add some HTML form element input type=text additions to allow for, out of …

  • Emoji look class … and …
  • Wording next to Emoji … and …
  • URL of Wording’s link, be that substituted or appended

mapped values, optionally, off a newly offered HTML form element input type=text for this mapped comma or blank separated word list.

Perhaps, now, you “long data set thinkers” want to try the live run and/or its PHP source code emoticon_keyboard_shortcuts.php changed in this way to extend its data set size capabilities.


Previous relevant Emoji Name Search Tailoring Tutorial is shown below.

Emoji Name Search Tailoring Tutorial

Information Technology is full of “buzz words”, and am sure you wince at some to all of them yourselves. That’s a bit why am using “Tailoring” rather than …

 

  • sharing
  • personalization

 

… to give you a slumberrest from having to look under struck throughdeleted wording to look for hidden “buzz words”terminology that makes your harehair sit upstand watchingon Bugs Bunnyend.

We think, perhaps, that emojis can be important for young “would be” programmers to launch into. Personally wonder how many “would be” programmers give the game up far too soon just because they don’t have those graphics skills, well, with emojis, a lot of that hard work, in miniature, has been done for you by some pretty creative people, so why not enjoy the fruits (chortle, in context, chortle) of their labour and start developing your own web applications to use them. Daily, their use is increasing, as are the sharing of access methods.

In today’s extension to the functionality started with yesterday’s Emoji Name Search Primer Tutorial we separate the Emoji Terra aspects to how it works and allow the user to …

  • supply an Emoji Word List of interest
  • perhaps supply a heading and subheading to describe the “concept” of that list
  • supply either a …
    1. URL prefix … or …
    2. URL with the ~ (tilde) character where you want, substituted, your emoji name

    … to be a navigation destination in that similar new window navigation we used to access Emoji Terra

  • presenting all this in an HTML form action=[here’sLookingAtYouKid] method=GET …
  • that method=GET opening the door to be able to offer an email client engine method to “share”email somebody the link to a screen that looks like the one you’re seeing

Of course, we’d like you to find some of your own such Emoji Display Dynamically Created Web Applications yourself, but to encourage, we, in the web application, today, identified two ideas, namely …

  • Fruit and Vegetables via Wikipedia at https://en.wikipedia.org/wiki/ as a prefix … and …
  • Astrology via Cafe Astrology at https://cafeastrology.com/~dailyhoroscope.html via ~ (tilde) character substitution

… each of which (and any you make will also) feature a link to the HTML mailto: a link out through the email client and to your recipient who can click the email link to “share”compare notes.

Perhaps, now, you want to try the live run and/or its PHP source code emoticon_keyboard_shortcuts.php changed in this way to extend its functionality, involving a reveal favourite of ours, the use of HTML(5)’s details (and summary) element.

You can also see this play out at WordPress 4.1.1’s Emoji Name Search Tailoring Tutorial.


Previous relevant Emoji Name Search Primer Tutorial is shown below.

Emoji Name Search Primer Tutorial

We got quite excited recently with Rainbow Games PHP Emoji Tutorial when we added a (fourth Beatle) emoji helper, called Emoji Terra, into the mix of tools to gather emoji information. Today, we’ve got a new Emoji Search web application that introduces a new (fifth Beatle(?)) emoji helper tool to add into the “how we see it” mix below …

  • Emojipedia is good for looking up Emoji names or concepts in words
  • FileFormat Information is great for HTML Entity determinations for your less complex Emojis
  • Iemoji is great for HTML Entity determinations for Emojis of all complexities
  • Emoji Terra performs similar functionality as Iemoji but has a permalink organization more friendly to an “emoji search via emoji title” query, and that has suited our purposes today, and before, so, thanks a lot
  • Emoji CSS performs similar functionality to Emojipedia, but has a pictorial view of Emoji names as well, right from the word go, thanks

With these emoji tools in mind we wrote a new PHP web application combining those last two to show Emojis pictorially (with their short name) initially and allow the user to search for an Emoji (match) list via their HTML input type=text (textbox) entry, which results in …

  • the Emoji (match) list look (as an Emoji “display”) … and …
  • an HTML a link which is that Emoji’s short name … linking to …
  • an Emoji Terra webpage with more detail, including HTML Entity information if “short name” is unique, or one extra click away, if not

Maybe you need to try the live run and/or its PHP source code emoticon_keyboard_shortcuts.php to download, perhaps?


Previous relevant Rainbow Games PHP Emoji Tutorial is shown below.

Rainbow Games PHP Emoji Tutorial

In order to take that further genericization step onto the achievements of yesterday’s Rainbow Games Genericization Tutorial to get onto (the mathematics Induction principle inspired) …

  • prove for the first case
  • prove for the second case
  • prove for the nth case

… we had a choice of …

  • continue on (with) the HTML code creation of new “hardcoded” arrays (managed by Javascript eval abstractional approach) … or “bite the bullet” and …
  • try to work out a generic “emoji lookerer upperer” arrangement

Guess you can tell we opted for the latter, huh?! We started the investigation of this by examining our three favourite emoji informational websites, namely …

  1. Emojipedia
  2. FileFormat Information
  3. Iemoji

… and were a bit surprised that we could not quite swing a generic method to glean the information, so don’t know whether our new “player” is “Ringo Starr” or not, but can tell you this, “its beat is much better than its bite” … chortle, chortle

Emoji Terra performs similar functionality as Iemoji but has a permalink organization more friendly to an “emoji search via emoji title” query, and that suits our purposes today, so, thanks a lot. Without this query by “emoji title” possibility we’d have been forced to adopt more of those “hardcoded” arrays, which would have been alright, but this second approach opens the door to “sport” events in “The Rainbow Games” web application using emojis of the future (ie. they haven’t been invented yet).

How to work the interfacing to Emoji Terra?

This new PHP emoji_lookup.php treats the “prove for the nth case” sports as ones to …

  • look up the emoji information for (in the order “PHP Source File as the Database Source” then try file_get_contents of Emoji Terra lookup), and …
  • read the HTML partner source code live run‘s underlying HTML and Javascript and CSS emoji_walk_animation.htm (which changed in this way)
  • amend that HTML source to supplant the “Sprint” default sport for this new nominated sport … trying not to fall over laughing at some of the new sports we present (inspired by a visit to Emoji Terra search)
  • write out that amended HTML code as the web page (the beauty of a serverside language like PHP)

The more detailed specifics of the file_get_contents of Emoji Terra lookup above are …

  • build up a URL starting with HTTP://emojiterra.com/ … then …
  • in emojiland arrangements there are two genders (as our prefixes if you will) … woman- and man-
  • then add on a “middle” sport descriptor (eg. biking)
  • in emojiland emoticonland arrangements there are five descriptors (as our suffixes if you will) … -dark-skin-tone, -medium-dark-skin-tone, -medium-skin-tone, -medium-light-skin-tone, -light-skin-tone
  • for that set of 2x1x5=10 URLs glean what “HTML dec” (HTML Entity) information you can glean via the file_get_contents call of the Emoji Terra URLs described above (eg. Emoji: Woman Biking: Dark Skin Tone) … built into a Javascript array string to “plug into” the previously read HTML partner source code, and amended to output as the web page the user sees

Sports of the future in emojiland? Just ask for the equivalent of biking (above) off the user via a Javascript prompt window (on the proviso you read Conditional Alternative to Javascript Popup Windows in iOS Tutorial first please).


Previous relevant Rainbow Games Genericization Tutorial is shown below.

Rainbow Games Genericization Tutorial

What would help genericize the recent Rainbow Games Double Transformation Tutorial “Rainbow Games” web application? How about introducing another sport?

Again, in honour of “onions of the 4th dimension” approaches, we mainly, turn to the power of Javascript’s eval methodology to achieve this abstracted feeling to our web application. Today, with this, we go two thirds of the way along the “Mathematical Induction” approach …

  • prove for the first case
  • prove for the second case
  • prove for the nth case

How does this use of Javascript eval manifest itself in this way?

  • there are two arrays that work with the “content” of our “Rainbow Games” sport(s) (well, at least, the first “sprint running” sport) called emoticons[] and choices[]
  • wherever we find references in the code to either of these two arrays we start to involve the global variable verbsuffix

    var verb='Sprint';
    var verbs=['Sprint','Row'];
    var anotherverb='run';
    var verbsuffix='';

    … in altered ways like …

    function plus(ih,ihep) {
    var outihep=ihep;
    if (eval("emoticons" + verbsuffix + "[" + ih + "]").indexOf('<p>') != -1) {
    outihep += ' (' + eval("emoticons" + verbsuffix + "[" + ih + "]").split('<p>')[1].split('<')[0] + ')';
    }
    return outihep;
    }

    … in that abstracted way … noting that sometimes you don’t need the “eval()” encasings …
  • and so, working through the code this way it just falls to the coder to define new members for all the arrays for all the new sports (ours is “rowing” today), some of those new arrays (like for rowing are emoticonsrowing[] and choicesrowing[]) to involve …
  • looking up emoji definitions from …
    1. Emojipedia
    2. FileFormat Information
    3. Iemoji

    … not forgetting to …

  • make sure the event logics work for multiple sport scenarios … but mostly they do by sticking to the principles above … especially for the …
  • new HTML select (dropdown) element allows the user to pick a sport

Remaining a work in progress, you can try out our live run link that has underlying HTML and Javascript and CSS emoji_walk_animation.htm, and which changed in this way regarding today’s genericization work. We hope it gives you food for thought.


Previous relevant Rainbow Games Double Transformation Tutorial is shown below.

Rainbow Games Double Transformation Tutorial

We were on the “road to personalization” for the web application game we started with yesterday’s Rainbow Games Primer Tutorial when “an old chestnut” came up again. It’s happened before, the desire to “double transform” in CSS came about from our emoji …

‍♀️

… table cell mirroring styling as per …


<style>
* { overflow-x: visible; }

select { font-size: 36px; }

td.runner { width: 50px; word-wrap: break-word; font-size: 36px;
transform: scale(-1, 1); -o-transform: scale(-1, 1); -moz-transform: scale(-1, 1); -ms-transform: scale(-1, 1); -webkit-transform: scale(-1, 1);
} //

‍♀️

tr { max-height: 40px; }
</style>

… necessary to make our running emojis run from left to right (that, alas, also transformed any accompanying …

‍♀️

Florence

… name), was added to in this double transformational clause to prove what this wonderful web page advice had to say. In other words, a “double transform” CSS styling scenario like the one below …


<style>
* { overflow-x: visible; }

select { font-size: 36px; }

td.runner { width: 50px; word-wrap: break-word; font-size: 36px;
transform: scale(-1, 1); -o-transform: scale(-1, 1); -moz-transform: scale(-1, 1); -ms-transform: scale(-1, 1); -webkit-transform: scale(-1, 1);
}
tr { max-height: 40px; }

p {
display: block;
font-size: 12px;
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-moz-transform: matrix(-1, 0, 0, 1, 0, 0);
-o-transform: matrix(-1, 0, 0, 1, 0, 0);
transform: matrix(-1, 0, 0, 1, 0, 0);
}
//

‍♀️

Florence

</style>

… works as a “double transform” to first …

  • mirror (image) flip the table cell (td) emoji data … but us appending some “Runner Name” textual data underneath also, annoyingly, got flipped until …
  • within that (same) table cell (td) element and after the emoji data we append an HTML p(aragraph) element to both …
    1. introduce a new HTML element type into the (CSS styling) mix … and to …
    2. introduce a new CSS transformation type, the matrix … perhaps either or both new parts to the problem critical to its success when, believe me, lots of other approaches don’t work

… to personalize the “runners” and “users”, optionally, “into the game”, by allowing the “user” to name their “runners” and allow for a “runner energy” setting be a bit randomized, to add for some other interest “variety” to the game’s workings. So, still a work in progress that you can try out at our live run link that has underlying HTML and Javascript and CSS emoji_walk_animation.html, and which changed in this way regarding today’s work.


Previous relevant Rainbow Games Primer Tutorial is shown below.

Interesting Places Primer Tutorial

It’s been a while since we’ve written any conventional HTML and Javascript and CSS game. Today’s game uses the “emoticon” section of the Emoji character set, defaulting so far, to the “running woman” emoji featuring in Compound Emoji WordPress Usage Tutorial.

It’s the early days of our “Rainbow Games” web application, and we’re starting with the animation featuring horizontal hashtag navigation techniques for a running race start to our game. Where it finishes? Hard to say! Today, we’ve looked at “splits” and a finish line.

You can try out our burgeoning live run game concept link that has underlying HTML and Javascript and CSS emoji_walk_animation.html.

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


If this was interesting you may be interested in 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

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

Yesterday’s …

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

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

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

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

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


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

}
};
}, 4000);
}

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

<?php

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

?>

… calling new Javascript function …

<?php echo ”

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

“; ?>

Other than header.php WordPress PHP code we changed …


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

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

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

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

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

And then there was “the unknown factor” …

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

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


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

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

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

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

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

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

… talking about the three appended spaces needed.


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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

Did you know?

All this begs the question …

What about mobile?

Well, at least for iOS we think …


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per

index.htm …


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday’s One Image Website iOS Radio Music One Less Tutorial set us on an “off to the side, but eventually forward” project that intertwines …

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday’s One Image Website iOS Radio Music Tutorial “Stop Press” promised …

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    … to arrive at the calling window

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said …

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

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

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

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

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

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

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

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

<?php echo ”

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

“; ?>

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

<?php echo ”

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

}

“; ?>

… to call on that new PHP …

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo ”

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

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

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

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


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

“; ?>

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

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

… we all excluded from new functionality Image Map potential “dark green area clicking” access to photography themed “One Image Websites” …

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

<?php echo ”

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

“; ?>

57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of “responsive web design”

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

… coming at it from the idea “Can a responsive shell webpage host a non-responsive iframe?”

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

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

    … as food for (your) thought …


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

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


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


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


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


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


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


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


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


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


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


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

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

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

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

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

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

And then there was “the unknown factor” …

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

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


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

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

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

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

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

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

… talking about the three appended spaces needed.


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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

Did you know?

All this begs the question …

What about mobile?

Well, at least for iOS we think …


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per

index.htm …


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday’s One Image Website iOS Radio Music One Less Tutorial set us on an “off to the side, but eventually forward” project that intertwines …

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday’s One Image Website iOS Radio Music Tutorial “Stop Press” promised …

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    … to arrive at the calling window

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said …

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

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

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

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

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

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

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

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

<?php echo ”

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

“; ?>

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

<?php echo ”

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

}

“; ?>

… to call on that new PHP …

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo ”

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

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

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

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


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

“; ?>

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

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

… we all excluded from new functionality Image Map potential “dark green area clicking” access to photography themed “One Image Websites” …

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

<?php echo ”

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

“; ?>

57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of “responsive web design”

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

… coming at it from the idea “Can a responsive shell webpage host a non-responsive iframe?”

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

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

    … as food for (your) thought …


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

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


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


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


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


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


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


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


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


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


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

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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

Did you know?

All this begs the question …

What about mobile?

Well, at least for iOS we think …


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per

index.htm …


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday’s One Image Website iOS Radio Music One Less Tutorial set us on an “off to the side, but eventually forward” project that intertwines …

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday’s One Image Website iOS Radio Music Tutorial “Stop Press” promised …

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    … to arrive at the calling window

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said …

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

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

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

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

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

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

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

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

<?php echo ”

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

“; ?>

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

<?php echo ”

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

}

“; ?>

… to call on that new PHP …

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo ”

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

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

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

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


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

“; ?>

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

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

… we all excluded from new functionality Image Map potential “dark green area clicking” access to photography themed “One Image Websites” …

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

<?php echo ”

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

“; ?>

57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of “responsive web design”

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

… coming at it from the idea “Can a responsive shell webpage host a non-responsive iframe?”

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

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

    … as food for (your) thought …


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

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


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


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


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


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


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


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


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


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

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

Dice Games Peer to Peer Emoji Tutorial

Dice Games Peer to Peer Emoji Tutorial

Dice Games Peer to Peer Emoji Tutorial

The recent Knockout Dice Game Emoji Tutorial got us a little peeved. We do like fairness, even for your humble web application, and when The Knockout Dice Game got an “emoji makeover” a few days ago … well … we’re telling you … around here there were stares and whispers … or was that 🖕👇stairs and wise purrs.

And so, regarding The Three Amigos

… all demanded “emoji ⚖ equality” … and who are we to argue?!

Each demanded nuanced modification differences, but we were glad regarding the “code cloning” that got us arriving at a fairly consistent starting point even before the Knockout Dice Game changes of Knockout Dice Game Emoji Tutorial and the day before that. Cloning should take place whenever you as the programmer have achieved functioning milestones.

And then we come to …

If you (Dice Game web applications) all want consistency you’ll want to easily see that grouping reflected in a peer to peer dropdown navigation arrangement?

Rhetorical question alert!!

Yes, dropdown (ie. select) elements are great for these peer to peer concept ideas, but the default CSS styling grates here. So how can a select element look more like an h1 element? Glad we asked! Have a look at this …


// Make the dropdown look like the nesting h1
var divelem=document.getElementById('gamemode');
var output=document.getElementById('myh1');
divelem.style.fontFamily = window.getComputedStyle(output,null).fontFamily || output.style.fontFamily || output.currentStyle.getCurrentProperty('font-family');
divelem.style.fontSize = window.getComputedStyle(output,null).fontSize || output.style.fontSize || output.currentStyle.getCurrentProperty('font-size');
divelem.style.fontWeight = window.getComputedStyle(output,null).fontWeight || output.style.fontWeight || output.currentStyle.getCurrentProperty('font-weight');
divelem.style.border = window.getComputedStyle(output,null).border || output.style.border || output.currentStyle.getCurrentProperty('border');
divelem.style.padding = window.getComputedStyle(output,null).padding || output.style.padding || output.currentStyle.getCurrentProperty('padding');
divelem.style.margin = window.getComputedStyle(output,null).margin || output.style.margin || output.currentStyle.getCurrentProperty('margin');
divelem.style.overflow = window.getComputedStyle(output,null).overflow || output.style.overflow || output.currentStyle.getCurrentProperty('overflow');
divelem.style.padding = window.getComputedStyle(output,null).padding || output.style.padding || output.currentStyle.getCurrentProperty('padding');
divelem.style.color = window.getComputedStyle(output,null).color || output.style.color || output.currentStyle.getCurrentProperty('color');

… Javascript code snippet. Isn’t Javascript wonderful!? Rhetorical question alert!!

Stop Press

Are you looking for a cross-browser means of right justifying the option text of a select (ie. dropdown) element? This very useful link, thanks, got us to try, successfully …


<select dir="rtl" style="text-align:right;" onchange="location.href='/HTMLCSS/' + this.value + '_dice_game.html?rand=' + Math.floor(Math.random() * 19878654);" id=gamemode><option value=knockout>Knockout</option><option value=runforit>Run for It &#127939;&#8205;&#9792;&#65039;</option><option value=threeormore>Three or More &#128338;<sup>&#10133;&#10133;</option></select>

… to look like …


Previous relevant Knockout Dice Game Emoji Tutorial is shown below.

Knockout Dice Game Emoji Tutorial

Knockout Dice Game Emoji Tutorial

To our mind, the invention of emojis has been a really positive part of the online world. Maybe we’re that extra bit fond of them because it can go somewhere on the way to …

  • covering up image media deficiencies (cough, cough) with this text/image hybrid alternative where the artistry has already been done, just asking for your coding intervention to use (where our favourite emoji coding access means, (using example of “dice” here) is to …
    1. type … [search strings] emojipedia ( ie. dice emojipedia ) … into the web browser address bar …
    2. click/tap relevant Google search Emojipedia link
    3. click/tap Technical Information tab link
    4. copy the U+1F3B2 style of Codepoint presented to paste into the web browser address bar …
    5. click/tap the relevant link (our preferred being, for single entities, the FileFormat.info) link
    6. copy the relevant HTML Entity (decimal) ( ie. &#127922; ) into the buffer

    ) … ready to paste at the relevant place ( or use String.fromCodePoint(127922) … 🎲 ) of the HTML or Javascript code … as well as the emoji talents of …

  • emojis are a help with Internationalization of your web application … as well as …
  • adding colour into the webpage aesthetics look
  • adding interest into the webpage aesthetics look … and because they are that hybrid between image and text …
  • adding interest into the webpage content
  • With this in mind, we spent some time, onto yesterday’s Knockout Dice Game Checkbox Tutorial progress for that Knockout Dice Game making it …

    Knockout 👊 Dice 🎲🎲 Game

    … even there in the web browser tab’s title.

    For the first time we can remember we needed to get ahead of the curve picking a suitable CSS font-family property for all text with this work because we found that some of the dice guise emojis were really new and not found in all the font families out there, so …


    <style>
    * { font-family: 'DejaVu Sans'; }

    .xone:before { font-family: 'DejaVu Sans'; content: '\002680'; color:blue; }
    .xtwo:before { font-family: 'DejaVu Sans'; content: '\002681'; color:blue; }
    .xthree:before { font-family: 'DejaVu Sans'; content: '\002682'; color:blue; }
    .xfour:before { font-family: 'DejaVu Sans'; content: '\002683'; color:blue; }
    .xfive:before { font-family: 'DejaVu Sans'; content: '\002684'; color:blue; }
    .xsix:before { font-family: 'DejaVu Sans'; content: '\002685'; color:blue; }
    .zone:after { font-family: 'DejaVu Sans'; content: '\002680'; color:blue; }
    .ztwo:after { font-family: 'DejaVu Sans'; content: '\002681'; color:blue; }
    .zthree:after { font-family: 'DejaVu Sans'; content: '\002682'; color:blue; }
    .zfour:after { font-family: 'DejaVu Sans'; content: '\002683'; color:blue; }
    .zfive:after { font-family: 'DejaVu Sans'; content: '\002684'; color:blue; }
    .zsix:after { font-family: 'DejaVu Sans'; content: '\002685'; color:blue; }

    .kout:after { content: '\01f44A'; }

    #snum { background-color: yellow; }

    #header { background-color: #f0f0f0; }

    select { white-space:pre-wrap; border-radius: 6px; }

    button { border-radius: 12px; }

    </style>

    … solved some issues for us, here. And in researching totally CSS ways to style via content, again, we got a leave pass to not look again. CSS (style) and HTML (substance) have been separated by the W3C powers that be, for a reason, and we see that CSS selectors based on “content starts with” will never happen, though you can probably use jQuery library calls to achieve this.

    Okay, with that in mind, we abandoned a CSS only “cute” way to display die values either side of a numerical dice roll total in the header table cell which updates dynamically, instead using this Javascript …


    function diceemojis(totv, secv) {
    var hprefix='', hsuffix='', classbit='';
    var firstv=eval(totv - secv);
    if (1 == 1) {
    var sels=document.getElementsByTagName('select');
    for (var isels=0; isels<sels.length; isels++) {
    if (('' + sels[isels].value.replace(/^0/g,'')) == ('' + totv)) { classbit=' class="kout"'; }
    }
    hprefix=('' + secv).replace(/1/g, '<sup class=xone></sup>').replace(/2/g, '<sup class=xtwo></sup>').replace(/3/g, '<sup class=xthree></sup>').replace(/4/g, '<sup class=xfour></sup>').replace(/5/g, '<sup class=xfive></sup>').replace(/6/g, '<sup class=xsix></sup>')
    hsuffix=('' + firstv).replace(/1/g, '<sub class=zone></sub>').replace(/2/g, '<sub class=ztwo></sub>').replace(/3/g, '<sub class=zthree></sub>').replace(/4/g, '<sub class=zfour></sub>').replace(/5/g, '<sub class=zfive></sub>').replace(/6/g, '<sub class=zsix></sub>')
    return hprefix + '<span' + classbit + ' id="span' + rollno + '">' + totv + '</span>' + hsuffix;
    }
    return (' <span class="' + firstv + ' ' + secv + '">' + totv + '</span>').replace(/\ 1\"/g, ' zone"').replace(/\ 2\"/g, ' ztwo"').replace(/\ 3\"/g, ' zthree"').replace(/\ 4\"/g, ' zfour"').replace(/\ 5\"/g, ' zfive"').replace(/\ 6\"/g, ' zsix"').replace(/\"1\ /g, '"xone ').replace(/\"2\ /g, '"xtwo ').replace(/\"3\ /g, '"xthree ').replace(/\"4\ /g, '"xfour ').replace(/\"5\ /g, '"xfive ').replace(/\"6\ /g, '"xsix ');
    }

    … to start making this happen in the changed knockout_dice_game.html Knockout Dice Game you can also try below.


    Previous relevant Knockout Dice Game Checkbox Tutorial is shown below.

    Knockout Dice Game Checkbox Tutorial

    Knockout Dice Game Checkbox Tutorial

    Around here, we’re often moving on in a project via …

    • the changing of hardcodings into “dropdown” select elements (especially within h1 header elements) … but today, to move on, we arrange for …
    • the nested insertion of a checkbox (initially checked) within an h1 header element

    … which for the first time we can remember, we adjust “opacity aesthetics” to add a useful dynamic setting adjustment to the Knockout Dice Game created when we presented Knockout Dice Game Primer Tutorial some time ago now …


    <h1><div id=divword style=display:inline-block;>Knockout</div> Dice Game for <div id='dnum' style='display:inline-block;'><select style='display:inline-block;' onchange='fixinstone(this.value);' id='snum'><option value=2>2</option><option value=3>3</option><option value=4>4</option><option value=5>5</option><option value=6>6</option><option value=7>7</option><option value=8>8</option><option value=9>9</option></select></div> <span id=sgwta style=opacity:1.0;><input onchange="document.getElementById('sgwta').style.opacity='' + eval(1.1 - eval('' + document.getElementById('sgwta').style.opacity));" style=display:inline-block;opacity:1.0; type=checkbox id=gwta checked></input>Winner Take All</span> Players</h1>

    This “Winner Takes All” checkbox controlled mode of use defaults to being set (which is unusual for us, when we add a new form of methodology like this) because we discovered, revisiting this game, that “passivity” was, sort of, being rewarded and so we felt like we needed to add in the idea (and the concept of “No Winner” needed to be added), into the game, where it is really user participation encouraged here, to make the game interesting. Adding to that interest is that in a “Winner Takes All” mode of use, if a player can be the lone player to survive “Knockouts” they score a point for every roll of the two dice to get to this “lone winner” scenario.

    The other issue we noticed were the right hand overflows of our tabulated dropdowns when a lot of players are asked for. We started rearranging content justifications (to now be left justified) so it did not matter if we reduced the (now a better Responsive Design friendly table cell percentage) widths of those dropdowns, so as to fit more fields into the webpage …


    tg+="<td><select style=width:100%;background-color:cyan; id='gplayer" + jhow + "'><option value='06'>[6] Knockout value ...</option><option value='6'>6</option><option value='7'>7</option><option value='8'>8</option><option value='9'>9</option></select></td><td><div id='score" + jhow + "'>Score: 0/0</div></td>";

    … in the changed knockout_dice_game.html Knockout Dice Game you can also try below …


    Previous relevant Knockout Dice Game Primer Tutorial is shown below.

    Knockout Dice Game Primer Tutorial

    Knockout Dice Game Primer Tutorial

    Further to the previous Dice Guessing Game Primer Tutorial, today, we have for you another Dice Game, this time …

    • a dice game for 2 to 9 players … which you should establish, as necessary, straight up …
    • then rename any player names you don’t want to be the default Player1 up to Player9 values, again, making use of the contenteditable=”true” global HTML attribute and the HTML div element’s onchange event to achieve this
    • then in each round of competition the players choose a two dice roll value between 6 to 9 as the value they don’t want to see turn up, because if it does, they score nothing for that round of competition, else the players last not rejected when there is one or no players left, score a point in that round of competition … and …
    • the web application randomly throws the dice the necessary number of times to find winner(s) once the “Roll the Dice for Each Player” button is pressed

    We’d like to thank the very useful webpage for ideas for how (for the most part) this Knockout Dice Game design, execution and rules should go.

    And again, we’d welcome your try out of this new Knockout Dice Guessing Game, and please feel free to tell us what you think. Its HTML and Javascript and CSS underpinning its functionality can be perused by downloading the knockout_dice_game.html link.


    Previous relevant Dice Guessing Game Primer Tutorial is shown below.

    Dice Guessing Game Primer Tutorial

    Dice Guessing Game Primer Tutorial

    There are many HTML Entities based around punctuation that can add to the means by which you communicate ideas with your web applications.

    In today’s new (up to two player) Dice Game, we use some of these to represent the numbers from 1 to 6 on the faces of the dice, similar to how you may have seen this happen with dice in various games you play, or hanging from your car’s front visor perhaps?

    We’d welcome your try out of this Dice Guessing Game, and feel free to tell us what you think (or if its two of you “tell us what you think” … huh?!). Its HTML and Javascript and CSS underpinning its functionality can be perused by downloading the dice_game.html link. If you do, you’ll see the mildly interesting scoring system, that can be explained via the equation …


    [CorrectAnswerScoreIncrement] = 7 - (NumberOfPossibilitiesInFull36PossibilitiesSet)

    … allowing for the incorporation of this Javascript array initialization …


    var probabilities=[0,0,1,2,3,4,5,6,5,4,3,2,1]; // score will be 7-guessValue

    … that we were capable of working out ourselves but were reassured by the mathematics of this very useful link, thanks.

    Another game thought unique to how we do things that has been introduced today, is that a user can change the default player names, those being Player1 and Player2 via an HTML div element utilizing the contenteditable=”true” global HTML attribute to make it look readable, but be also “quietly” editable.

    You can also see this play out at WordPress 4.1.1’s Dice Guessing Game Primer Tutorial.

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


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


    If this was interesting you may be interested in 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, Games, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment