AlmaLinux TimeZone Places Associative Array Tutorial

AlmaLinux TimeZone Places Associative Array Tutorial

AlmaLinux TimeZone Places Associative Array Tutorial

Have you been waiting for more “heads up” regarding issues we’ll have moving from a PHP (of a version starting with a 5) to a PHP (of a version starting with an 8)? Join the crowd?! But so far, it hasn’t been that bad. That is, until we started into looking at the PHP TimeZone functionalities. Going back to a previous time of referencing this, at the recent Google Charts Geo Chart Region Picker Conditional Positioning Tutorial, associative array based codelines like

<?php

$ourtz=new DateTimeZone($zzbit);
$ourtzgl=$ourtz->getLocation();
$versus=str_replace('"' . '' . '"];', '"' . $zzbit . '","' . '' . '"];', $versus);
$yourgl=explode(',',('' . implode(',',$ourtzgl)));
//$versus=str_replace('"' . ' ' . '"];', '"' . $ourtzgl[latitude] . '","' . ' ' . '"];', $versus);
//$versus=str_replace('"' . ' ' . '"];', '"' . $ourtzgl[longitude] . '","' . ' ' . '"];', $versus);
$versus=str_replace('"' . ' ' . '"];', '"' . $yourgl[1] . '","' . ' ' . '"];', $versus);
$versus=str_replace('"' . ' ' . '"];', '"' . $yourgl[2] . '","' . ' ' . '"];', $versus);


?>

… worked and meant codelines avoiding associative array logic, in favour of numerically indexed array thinking, like above (thanks to implode) were not needed then, on CentOS, but are needed now, in a redesign, on AlmaLinux, in the changed TimeZone Places (the old way) (and TimeZone Places (the new way)) tz_places.php PHP code.


Previous relevant Google Charts Geo Chart Region Picker Conditional Positioning Tutorial is shown below.

Google Charts Geo Chart Region Picker Conditional Positioning Tutorial

Google Charts Geo Chart Region Picker Conditional Positioning Tutorial

Because of the work at Curl HTTP Request Methods Tool Tutorial we can now …

  • conditionally (depending on the existence of the Google Charts Image Charts API) …
  • determine the positioning of Region Picker functionality elements

… further to yesterday’s Google Charts Geo Chart Region Picker Alignment Tutorial.

We start with non-mobile improving the positioning for the “letter breadcrumbs” and “middle dropdown” elements …


var imagechartthere=true;

function checkimagechart(iois) {
var eaconto = (iois.contentWindow || iois.contentDocument);
if (eaconto != null) {
if (eaconto.document) { eaconto = eaconto.document; }

if (eaconto.body.innerHTML.replace('Not Found','Error 404').replace(/^\<br\>\<\/p\>/g, 'Error 404').indexOf('Error 404') != -1) {
imagechartthere=false;
document.getElementById('myh3').style.left='' + eval(eval('' + screen.width) * 7 / 10) + 'px';
document.getElementById('myh3').style.top='' + eval('' + document.getElementById('myh3').getBoundingClientRect().bottom) + 'px';
setTimeout(function(){
document.getElementById('tdleft').style.backgroundPosition="right center";
}, 60000);
}

}
}
//
// and then later ...
//
setTimeout(function(){
if (!imagechartthere && document.getElementById('myh3')) {
document.getElementById('more').style.left='' + eval(-170 + eval(('' + document.getElementById('myh3').style.left).replace('px',''))) + 'px';
} else {
document.getElementById('more').style.left='' + eval(eval(360 * lastiizoom / 2) + eval('' + document.getElementById('more').style.left.replace('px',''))) + 'px';
}
}, 3000);

… working via the “client pre-emptive iframe” feeling …


<iframe style="display:none;" src="/PHP/http_methods.php?url=https%3A%2F%2Fchart.googleapis.com%2Fchart" onload="checkimagechart(this);"></iframe>

… along with making the opacity toggling of the country background SVG slightly more pronounced in the changed regions_via_countries.html Region Picker.

Did you know?

Ignoring the kludginess of codelines …


ipbit=ipbit.trim();
setTimeout(function(){ ipbit=ipbit.trim(); }, 5000);

… how do you think we arrived at the need to write the second line of code for our Region Picker? Goo … anyone, anyone?guffaw

Sir, could you repeat the question?

Goo … guffaw

Sir, could you repeat the question?

Goo … guffaw

Sir, could you repeat the question?

Goo … guffaw

Sir, could you repeat the question?

… Goo … well, anyone, anyone? … Google Chrome web inspector. Rings any bells?!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
… Okay, see you tomorrow. But catch up on the debugging and “watch” of variables dynamically before tomorrow’s lesson …


Previous relevant Google Charts Geo Chart Region Picker Alignment Tutorial is shown below.

Google Charts Geo Chart Region Picker Alignment Tutorial

Google Charts Geo Chart Region Picker Alignment Tutorial

In our inhouse Region Picker we like the way the right hand webpage side involved some useful …


position: sticky;

… positioning, useful within the realms of what is going on on the right hand side.

But now we’re wanting some horizontal integration, linking commonalities of left and right regarding the country of interest, as a user’s eyes scan across the webpage, at pivotal times.

Our new Javascript functions to help, today, further to the recent Google Charts Geo Chart Region Picker Shading Tutorial


var glincode='';

function prebrize() {
if (glincode != '') {
document.getElementById('a' + glincode).scrollIntoView();
}
}

function brizetwo(pb, lincode) {
if (eval('' + lincode.length) == 2) {
glincode=lincode;
document.getElementById('a' + lincode).scrollIntoView();
setTimeout(function(){ document.getElementById('a' + lincode).scrollIntoView(); document.getElementById('mychart').style.paddingTop='' + document.body.scrollTop + 'px'; }, 6000);
}
return brize(pb);
}

function brize(pb) {
var torectx=null, vsrectx=null, aidis='';
var torectxtop=0;
if (eval('' + andynft.length) == 8) {
aidis='a' + andynft.split('title=')[1];
if (pb == '') {
torectx=document.getElementById(aidis).getBoundingClientRect();
if (document.getElementById('pspacer')) {
document.getElementById('pspacer').height='' + torectx.top + 'px';
} else if (document.getElementById('language')) {
document.getElementById('language').style.paddingTop='' + eval(eval('' + torectx.top) + eval('' + document.body.scrollTop)) + 'px';
} else if (document.getElementById(aidis) && document.getElementById('mychart')) {
document.getElementById('mychart').style.paddingTop='' + eval(eval('' + torectx.top) + eval('' + document.body.scrollTop)) + 'px';
}
} else {
if (document.getElementById(aidis) && document.getElementById('mychart')) {
torectx=document.getElementById(aidis).getBoundingClientRect();
vsrectx=document.getElementById('mychart').getBoundingClientRect();
document.getElementById('mychart').style.paddingTop='' + eval(eval('' + torectx.top) + eval('' + document.body.scrollTop) - eval('' + vsrectx.top)) + 'px';
return pb;
} else if (document.getElementById(aidis) && document.getElementById('language')) {
torectx=document.getElementById(aidis).getBoundingClientRect();
vsrectx=document.getElementById('language').getBoundingClientRect();
document.getElementById('language').style.paddingTop='' + eval(eval('' + torectx.top) + eval('' + document.body.scrollTop) - eval('' + vsrectx.top)) + 'px';
}
}
}
return pb;
}

… all feature the great [element].scrollIntoView() way to programmatically scroll, rather than use (the sometimes ignored) window.scrollTo([left],[top]); or location.href=’#[elementID]’; approaches. It has the advantage of not altering location.hash (if you see that as a plus). We’d rather not add complexity, so, yes, we prefer the [aCountryElement].scrollIntoView(); call approach, at those pivotal times. This accounts for the left hand side of the webpage agreeing to the right hand side’s vertical scroll position. But what about the other way around? There, we started applying a CSS padding-top property to relevant right hand side elements (via DOM [element].style.paddingTop=[pixelsToExtendDown]px;), at pivotal points in the programming flow.

And on double clicking a right hand side button to start creating those background Geo Chart SVG based “images” we turn on a progress cursor, at least for non-mobile platforms, because the user needs patience here, in the changed regions_via_countries.html Region Picker.


Previous relevant Google Charts Geo Chart Region Picker Shading Tutorial is shown below.

Google Charts Geo Chart Region Picker Shading Tutorial

Google Charts Geo Chart Region Picker Shading Tutorial

We have a few major improvements onto yesterday’s Google Charts Geo Chart Region Picker Nesting Tutorial‘s work …

  • shading of country in the Google Charts Geo Chart
  • addition of event logic for the “overlay/underlay/arriba” Google Charts Geo Chart incarnation … via Javascript DOM dynamic manipulation of Geo Chart z-index via …

    function reposition() {
    document.getElementById(gaid).style.display='block';
    var nrect=document.getElementById(gaid).getBoundingClientRect();
    document.getElementById(gulid).style.top='' + eval(eval('' + nrect.top) + eval('' + document.body.scrollTop)) + 'px';
    document.getElementById(gulid).style.left='' + eval(eval('' + nrect.left) + eval('' + document.body.scrollLeft)) + 'px';
    document.getElementById(gulid).style.width='' + nrect.width + 'px';
    document.getElementById(gulid).style.height='' + nrect.height + 'px';
    if (('' + document.getElementById(gulid).style.zIndex).indexOf('-') != -1) {
    document.getElementById(gulid).style.zIndex='' + ('' + document.getElementById(gulid).style.zIndex).replace('-','');
    } else {
    document.getElementById(gulid).style.zIndex='-' + ('' + document.getElementById(gulid).style.zIndex).replace('-','');
    }

    }

    … effectively toggling between “overlay” and “underlay” … arriba
  • oncontextmenu (ie. right click) means by which any clashing region name text can be “unclashed”

Codewise, this needed ..

… with WordPress blog 404.php helper changes as per …

<?php

function yourfile_get_contents($wone) { //, $ucc, $ctname) {
global $geomapurl, $getmapdata, $iso_country_codes; // <a href="/wiki/Autonomous_Republic_of_Crimea" title="Autonomous Republic of Crimea">Avtonomna Respublika Krym</a>
// %20[51.4769|-0.0005|~From~,2]%20,%20[51.4769|-0.0005|~To~,2]%20,
// <img style="z-index:25;" onload=" return true; " id="ici" data-onmouseout="this.title=origtitle;" onmousemove=" if (isclear || 1 == 1) { document.getElementById('moimode').value='mouseover'; filloutform(event,0); }" src="//www.rjmprogramming.com.au/ITblog/455/350/?cht=map&chld=AF|AF-BDG|AF-BGL|AF-BAL|AF-BAM|AF-DAY|AF-FRA|AF-FYB|AF-GHA|AF-GHO|AF-HEL|AF-HER|AF-JOW|AF-KAB|AF-KAN|AF-KAP|AF-KHO|AF-KNR|AF-KDZ|AF-LAG|AF-LOG|AF-NAN|AF-NIM|AF-NUR|AF-PKA|AF-PIA|AF-PAN|AF-PAR|AF-SAM|AF-SAR|AF-TAK|AF-URU|AF-WAR|AF-ZAB|&chco=B3BCC0|5781AE|FF0000|FFC726|885E80|518274|A3BCC0|4781AE|EF0000|EFC726|785E80|418274|7ccdef|e65814|477b73|87f592|ed75f2|09526e|27a51c|58c662|4b4840|7d01b5|f6a557|b69f63|cac10b|f3e9ab|26192c|ad7629|3b21b4|7238ab|aa1e07|23f0d7|d8dfb3|8c07c2|7a5bbf|b0ee12&screenheight=900" title="Optionally click in relevant region for menu">
if (file_exists('../HTMLCSS/rvc_' . my_s_s_server_remote_addr() . '.html')) {
sleep(5);
unlink('../HTMLCSS/rvc_' . my_s_s_server_remote_addr() . '.html');
}
$iso_underscore=false;
$ucc='';
$ctname='';
$okwone='';
$ones=[];
if (strpos($wone, 'chld=') === false) {
return @file_get_contents($wone);
} else if (1 == 1 || strpos($wone, 'screenheight=') !== false) {
$ucc=strtoupper(trim(explode('_', explode('|', explode('chld=', $wone)[1])[0])[0]));
for ($ire=0; $ire<sizeof($iso_country_codes); $ire+=2) {
if ($ucc == strtoupper($iso_country_codes[$ire])) {
$ctname=$iso_country_codes[1 + $ire];
}
}
$okwone=file_get_contents($wone);
$wone='http://en.wikipedia.org/wiki/ISO_3166-2:' . $ucc;
}
if (strlen($ucc) != 2) {
return @file_get_contents($wone);
}
$tbit=$ucc . ';' . $ctname;
$geomapurl='';
$wpg='';
$ones=[];
$preurl='';
$saveducc=@file_get_contents('saveducc.txt');
$linfnd=explode($ucc . '=', $saveducc);
if (sizeof($linfnd) > 1) {
$geomapurl=explode("\n", $linfnd[1])[0];
}
file_put_contents('xcc.xcc', $tbit . ' ' . $wone);
if (strpos($wone, '/wiki/') !== false && strpos($wone, 'http') !== false) {
$preurl='http' . explode('/wiki/', explode('http', $wone)[-1 + sizeof(explode('http', $wone))])[0];
}
$one=file_get_contents($wone);
if ($geomapurl != '') {
sleep(9);
} else {
file_put_contents('xccone.xcc', $preurl . ' ... ' . $one);
if (strpos($one, ' sortable"') !== false && $preurl != '') {
$ones=explode('<a href="/wiki/', explode(' sortable"', explode("See also ", $one)[0])[1]);
} else if ($preurl != '') {
$ones=explode('<a href="/wiki/', explode("See also ", $one)[0]);
}

for ($ii=1; $ii<sizeof($ones); $ii++) {
if (!$iso_underscore) {
$rname=explode('<', explode('>', $ones[$ii])[1])[0];
if (substr(($rname . ' '),0,3) == 'ISO') { $iso_underscore=true; }
if ($ii == 1) {
file_put_contents('xccuccit.xcc', $ucc . ' - ' . $rname . "\n");
}
if (trim($rname) != '') {
file_put_contents('xccu.xcc', $preurl . '/wiki/' . explode('"', $ones[$ii])[0]);
$wpg=file_get_contents($preurl . '/wiki/' . explode('"', $ones[$ii])[0]);
$rname=str_replace('_',' ',explode('"', $ones[$ii])[0]);
file_put_contents('xccuc.xcc', $wpg);
$wpgs=explode(' class="geo">', $wpg);
if (sizeof($wpgs) > 1) {
file_put_contents('xccuu.xcc', $preurl . '/wiki/' . explode('"', $ones[$ii])[0]);
$ltlg=str_replace(' ','',str_replace(';',',',explode('<', $wpgs[1])[0]));
file_put_contents('xccuuu.xcc', $ltlg);
if ($geomapurl != '') { $geomapurl.=','; }
$geomapurl.=str_replace("%27","+","%20[" . str_replace(',','|',$ltlg) . '|~' . str_replace("%27","+",str_replace('%27~','~',urlencode($rname) . '~')) . ',2]%20');
file_put_contents('xcz.xc', $geomapurl);
file_put_contents('xccuccit.xcc', file_get_contents('xccuccit.xcc') . $ii . ' : ' . str_replace("%27","+","%20[" . str_replace(',','|',$ltlg) . '|~' . str_replace("%27","+",str_replace('%27~','~',urlencode($rname) . '~')) . ',2]%20') . "\n");
} else {
file_put_contents('xccuccit.xcc', file_get_contents('xccuccit.xcc') . $ii . ' ; ' . explode('"', $ones[$ii])[0] . "\n");
}
}
}
}
}

if ($geomapurl != '') {
if (sizeof($linfnd) <= 1) {
file_put_contents('saveducc.txt', $saveducc . $ucc . '=' . $geomapurl . "\n");
}
file_put_contents('xc.xc', $geomapurl);
if (strlen('/PHP/GeoChart/geo_chart.php#onclick=y&retsvg=y&overlay=a' . $ucc . '&text=text&wouldlikeyoutoseekpermission=y&width=834&height=520&country=Places&popularity=&aregeographicals=y&title=' . urlencode($tbit) . '&data=' . $geomapurl) < 850) {
file_put_contents('../HTMLCSS/rvc_' . my_s_s_server_remote_addr() . '.html', '<html><head><scri' . 'pt type=text/javascript> var aconto=null; function flowthrough(iois) { aconto = (iois.contentWindow || iois.contentDocument); if (aconto != null) { if (aconto.document) { aconto = aconto.document; } } if (window.opener) { if (window.opener.setifrmoreacontochild) { window.opener.setifrmoreacontochild(aconto); } } } </scr' . 'ipt></head><body><iframe onload=flowthrough(this); style=width:98%;height:98%; src="/PHP/GeoChart/geo_chart.php#onclick=y&retsvg=y&overlay=a' . $ucc . '&shade=' . $ucc . '&iso=' . $ucc . '&text=text&wouldlikeyoutoseekpermission=y&width=834&height=520&country=Places&popularity=&aregeographicals=y&title=' . urlencode($tbit) . '&data=' . unduplicate($geomapurl) . '"></iframe></body></html>');
} else {
file_put_contents('../HTMLCSS/rvc_' . my_s_s_server_remote_addr() . '.html', '<html><head><scri' . 'pt type=text/javascript> var aconto=null; function flowthrough(iois) { aconto = (iois.contentWindow || iois.contentDocument); if (aconto != null) { if (aconto.document) { aconto = aconto.document; } } if (window.opener) { if (window.opener.setifrmoreacontochild) { window.opener.setifrmoreacontochild(aconto); } } } </scr' . 'ipt></head><body><iframe onload=flowthrough(this); style=width:98%;height:98%; src="/PHP/GeoChart/geo_chart.php#onclick=y&retsvg=y&overlay=a' . $ucc . '&shade=' . $ucc . '&iso=' . $ucc . '&text=text&wouldlikeyoutoseekpermission=y&width=834&height=520&country=Places&popularity=&aregeographicals=y&title=' . urlencode($tbit) . '&data=' . unduplicate($geomapurl) . '"></iframe></body></html>');
}

// '<html><body><iframe style=width:98%;height:98%; src="/PHP/GeoChart/geo_chart.php#onclick=y&text=text&wouldlikeyoutoseekpermission=y&width=834&height=520&country=Places&popularity=&aregeographicals=y&title=' . urlencode($tbit) . '&data=' . $geomapurl . '"></iframe></body></html>');
//if (file_exists('../rvc_' . my_s_s_server_remote_addr() . '.html')) {
// sleep(35);
// unlink('../rvc_' . my_s_s_server_remote_addr() . '.html');
//}
}

return $okwone;
}

function unduplicate($inbn) {
$outbn=$inbn;
$thiso='';
$sofarfound=';';
$outbs=explode('|~', $inbn);
for ($iout=1; $iout<sizeof($outbs); $iout++) {
$thiso=explode('~', $outbs[$iout])[0];
if (strpos($sofarfound, ';' . $thiso . ';') !== false) {
$youtbs=explode('|~' . $thiso . '~', $outbn);
for ($jout=2; $iout<sizeof($youtbs); $jout++) {
$outbn=str_replace('~' . $thiso . '~' . $youtbs[$jout], '~' . '~' . $youtbs[$jout], $outbn);
}
} else {
$sofarfound.=$thiso . ';';
}
}
return $outbn;
}

?>


Previous relevant Google Charts Geo Chart Region Picker Nesting Tutorial is shown below.

Google Charts Geo Chart Region Picker Nesting Tutorial

Google Charts Geo Chart Region Picker Nesting Tutorial

It was really our inhouse Region Picker web application we had in mind behind the “create a map background” motivations of yesterday’s Google Charts Geo Chart Nesting Tutorial.

We found trying the …

  • background-image:url(‘data:image/svg+xml;utf8, blahde blah ‘); nor background-image:url(‘data:image/svg+xml;base64, blahde blah ‘); ideas were not working for us … but today, we started to try …
  • overlay HTML div position:absolute; opacity:0.5; z-index:-4; …
    the changed geo_chart.php Geo Chart creating the new “as if background image” Google Charts Geo Chart …
    <?php echo ”

    function ovmap(winobj, goodid, goodrect, thesvg) {
    // contain svg opacity z-index ul next to aXX display property of that ul determines pre-click
    var jgeo='doverlay';
    //alert(987);
    if (winobj.document.getElementById(jgeo)) {
    winobj.document.getElementById(jgeo).style.position='absolute';
    winobj.document.getElementById(jgeo).style.top='' + goodrect.top + 'px';
    winobj.document.getElementById(jgeo).style.left='' + goodrect.left + 'px';
    winobj.document.getElementById(jgeo).style.width='' + goodrect.width + 'px';
    winobj.document.getElementById(jgeo).style.height='' + goodrect.height + 'px';
    winobj.document.getElementById(jgeo).style.opacity='0.5';
    winobj.document.getElementById(jgeo).style.zIndex='-4';
    winobj.document.getElementById(jgeo).style.display='block';
    //winobj.document.getElementById(jgeo).innerHTML=thesvg.replace(/\#ffffff/g,'transparent').replace(/white/g,'transparent');
    winobj.document.getElementById(jgeo).innerHTML=winobj.bsvg(jgeo, goodid, window.self, thesvg.replace(/\#ffffff/g,'transparent').replace(/white/g,'transparent'));
    }
    }

    “; ?>
    … used by the changed regions_via_countries.html Region Picker

    var gulid='', gchildwin=null, gulbsvg='', gaid='';

    var gulid='', gchildwin=null, gulbsvg='', gaid='';

    function setifrmoreacontochild(what) {
    ifrmoreacontochild=what;
    }

    function getifrmoreacontochild() {
    return ifrmoreacontochild;
    }

    function reposition() {
    document.getElementById(gaid).style.display='block';
    var nrect=document.getElementById(gaid).getBoundingClientRect();
    document.getElementById(gulid).style.top='' + nrect.top + 'px';
    document.getElementById(gulid).style.left='' + nrect.left + 'px';
    document.getElementById(gulid).style.width='' + nrect.width + 'px';
    document.getElementById(gulid).style.height='' + nrect.height + 'px';
    }

    function bsvg(ulid, aid, childwin, ulbsvg) {
    gulid=ulid;
    gchildwin=childwin;
    gulbsvg=ulbsvg;
    if (gaid == '') {
    setInterval(reposition, 3000);
    }
    gaid=aid;
    //alert('svg is ' + ulbsvg);
    //alert(ifrmoreaconto.body.innerHTML);
    if (ifrmoreacontochild) {
    //alert('child there');
    if (ifrmoreacontochild.getElementById('chart_div')) {
    //alert('child svg there');
    //alert('will apply ' + '')[0].split('')[0].split('');
    setTimeout(function(){ document.getElementById(gulid).innerHTML='')[0].split('')[0].split(''; }, 9000);
    }
    }
    return ulbsvg;
    }
    … helped out by an improved this WordPress blog 404.php”not found” processor
    <?php

    if (strlen('/PHP/GeoChart/geo_chart.php#onclick=y&retsvg=y&overlay=a' . $ucc . '&text=text&wouldlikeyoutoseekpermission=y&width=834&height=520&country=Places&popularity=&aregeographicals=y&title=' . urlencode($tbit) . '&data=' . $geomapurl) < 850) {
    file_put_contents('../HTMLCSS/rvc_' . my_s_s_server_remote_addr() . '.html', '<html><head><scri' . 'pt type=text/javascript> var aconto=null; function flowthrough(iois) { aconto = (iois.contentWindow || iois.contentDocument); if (aconto != null) { if (aconto.document) { aconto = aconto.document; } } if (window.opener) { if (window.opener.setifrmoreacontochild) { window.opener.setifrmoreacontochild(aconto); } } } </scr' . 'ipt></head><body><iframe onload=flowthrough(this); style=width:98%;height:98%; src="/PHP/GeoChart/geo_chart.php#onclick=y&retsvg=y&overlay=a' . $ucc . '&text=text&wouldlikeyoutoseekpermission=y&width=834&height=520&country=Places&popularity=&aregeographicals=y&title=' . urlencode($tbit) . '&data=' . $geomapurl . '"></iframe></body></html>');
    } else {
    file_put_contents('../HTMLCSS/rvc_' . my_s_s_server_remote_addr() . '.html', '<html><head><scri' . 'pt type=text/javascript> var aconto=null; function flowthrough(iois) { aconto = (iois.contentWindow || iois.contentDocument); if (aconto != null) { if (aconto.document) { aconto = aconto.document; } } if (window.opener) { if (window.opener.setifrmoreacontochild) { window.opener.setifrmoreacontochild(aconto); } } } </scr' . 'ipt></head><body><iframe onload=flowthrough(this); style=width:98%;height:98%; src="/PHP/GeoChart/geo_chart.php#onclick=y&retsvg=y&overlay=a' . $ucc . '&text=text&wouldlikeyoutoseekpermission=y&width=834&height=520&country=Places&popularity=&aregeographicals=y&title=' . urlencode($tbit) . '&data=' . $geomapurl . '"></iframe></body></html>');
    }

    ?>

… with more success.

We can’t remember a “foreground overlay” scenario so resembling a “background image feeling” end result, the transparent colour introduced into the Google Charts Geo Chart SVG being crucial to help make this all work.


Previous relevant Google Charts Geo Chart Nesting Tutorial is shown below.

Google Charts Geo Chart Nesting Tutorial

Google Charts Geo Chart Nesting Tutorial

Today we’re working on more Google Charts Geo Chart inhouse web application interfacer functionality other web applications might be able to make use of … “tool” functionality, if you will.

We want to be able to control the way a Google Charts Geo Chart can be nested within an HTML div element, for instance. We started the day wanting to be able to make …

  • a Google Charts Geo Chart be a background image to a div element … alas, on this first draft we couldn’t get there (but will continue with the research here) … whereas we succeeded …
  • adding the Google Charts Geo Chart interfacer’s resultant SVG data as the innerHTML (ie. content) …
    <?php echo ”

    function newbackin() {
    if (dmyxhr.readyState == 4) {
    if (dmyxhr.status == 200) {
    if (dmyxhr.responseText) {
    var m_t='image/jpeg';
    var h_t='179';
    var w_t='320';
    var dbits = dmyxhr.responseText.split('\"height\": ');
    if (dbits.length > 1) {
    h_t=dbits[1].split(',')[0].split(String.fromCharCode(10))[0].split('}')[0].trim();
    }
    dbits = dmyxhr.responseText.split('\"mime_type\": \"');
    if (dbits.length > 1) {
    m_t=dbits[1].split('\"')[0];
    }
    dbits = dmyxhr.responseText.split('\"width\": ');
    if (dbits.length > 1) {
    w_t=dbits[1].split(',')[0].split(String.fromCharCode(10))[0].split('}')[0].trim();
    }
    dbits = dmyxhr.responseText.split('\"data\":');
    dbits = dmyxhr.responseText.split('\"data\":');
    if (dbits.length > 1) {
    // replace all '_' with '/' and all '-' with '+' thanks to https://stackoverflow.com/questions/757675/website-screenshots
    dgsbi='<img alt=\"Blog Posting Image\" style=\"width:' + w_t + 'px;height:' + h_t + 'px;\" width=' + w_t + ' height=' + h_t + ' src=\"data:' + m_t + ';base64,' + dbits[1].split('\"')[1].split('\"')[0].replace(/\_/g,'/').replace(/\-/g,'+') + '\"></img>';
    //alert('dgsbi=' + dgsbi);
    }
    }
    }
    }
    }

    function ajaxit(urlin) {
    if (urlin.length > 0) {
    aurl=urlin;
    if (window.XMLHttpRequest) {
    dmyxhr = new window.XMLHttpRequest;
    }
    else {
    try {
    dmyxhr = new ActiveXObject('Msxml2.XMLHTTP');
    } catch (othermicrosoft) {
    try {
    dmyxhr = new ActiveXObject('Microsoft.XMLHTTP');
    } catch (failed) {
    dmyxhr = false;
    }
    }
    }
    var xurl = 'https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=' + encodeURIComponent(urlin) + '&screenshot=true';
    if (dmyxhr) {
    dmyxhr.onreadystatechange = newbackin;
    dmyxhr.open('GET', xurl, true);
    dmyxhr.send(null);
    }
    }
    }

    function wbtoa(instris) {
    var outstris=instris;
    while (outstris.indexOf(String.fromCharCode(10)) != -1) {
    outstris=outstris.replace(String.fromCharCode(10),'');
    }
    var xzs=prompt(outstris, outstris);
    return outstris.replace(/\\\"/g, \"'\");
    }


    function svgret(swhat) {
    var igeo='georeceiver', aspfactor=1.0, swis=-1, shis=-1, whrect=null;
    var newswis=-1, newshis=-1, cswis=' ', cshis=' ', newcswis=' ', newcshis=' ', whdelim='';
    var newercswis=' width=' + whdelim + '100%' + whdelim;
    var newercshis=' height=' + whdelim + '100%' + whdelim;
    var cswistwo=' ', cshistwo=' ', newcswistwo=' ', newcshistwo=' ';
    var retsvg=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('retsvg=')[1] ? (decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('retsvg=')[1].split('&')[0])) : ' ';
    if (retsvg != ' ') {
    if (swhat.indexOf('<svg') != -1 && swhat.indexOf('</s' + 'vg>') != -1) {
    var candidate=false;
    if (swhat.indexOf(' width=') != -1 && swhat.indexOf(' height=') != -1) {
    if (swhat.split(' width=')[1].substring(0,1) < '0') {
    whdelim=swhat.split(' width=')[1].substring(0,1);
    cswis=' width=' + swhat.split(' width=')[1].split(' ')[0].split('>')[0];
    cshis=' height=' + swhat.split(' height=')[1].split(' ')[0].split('>')[0];
    newcswis=cswis;
    newcshis=cshis;
    swis=eval('' + swhat.split(' width=')[1].substring(1).split(swhat.split(' width=')[1].substring(0,1))[0]);
    shis=eval('' + swhat.split(' height=')[1].substring(1).split(swhat.split(' height=')[1].substring(0,1))[0]);
    } else {
    cswis=' width=' + swhat.split(' width=')[1].split(' ')[0].split('>')[0];
    cshis=' height=' + swhat.split(' width=')[1].split(' ')[0].split('>')[0];
    newcswis=cswis;
    newcshis=cshis;
    swis=eval('' + swhat.split(' width=')[1].split(' ')[0].split('>')[0]);
    shis=eval('' + swhat.split(' height=')[1].split(' ')[0].split('>')[0]);
    }
    }
    if (window.opener && !candidate) {
    if (window.opener.document.getElementById(igeo)) {
    candidate=true;
    if (('' + window.opener.document.getElementById(igeo).value).replace('undefined','').replace('null','') != '') {
    igeo=window.opener.document.getElementById(igeo).value;
    }
    if (cswis.trim() != '') {
    whrect=window.opener.document.getElementById(igeo).getBoundingClientRect();
    // 2000 x 2500 to fit into 800 x 654
    if (eval(swis / eval('' + whrect.width)) < eval(shis / eval('' + whrect.height))) {
    aspfactor=eval(eval('' + whrect.width) / swis);
    cswistwo='&width=' + ('' + swis).split('.')[0];
    cshistwo='&height=' + ('' + shis).split('.')[0];
    newcswistwo='&width=' + Math.floor(eval(swis * aspfactor));
    newcshistwo='&height=' + Math.floor(eval(shis * aspfactor));
    newcswis=' width=' + whdelim + eval(swis * aspfactor) + whdelim;
    newcshis=' height=' + whdelim + eval(shis * aspfactor) + whdelim;
    } else {
    aspfactor=eval(eval('' + whrect.height) / shis);
    cswistwo='&width=' + ('' + swis).split('.')[0];
    cshistwo='&height=' + ('' + shis).split('.')[0];
    newcswistwo='&width=' + Math.floor(eval(swis * aspfactor));
    newcshistwo='&height=' + Math.floor(eval(shis * aspfactor));
    newcswis=' width=' + whdelim + eval(swis * aspfactor) + whdelim;
    newcshis=' height=' + whdelim + eval(shis * aspfactor) + whdelim;
    }
    }
    if (('' + window.opener.document.getElementById(igeo).outerHTML).indexOf('background') != -1) {
    window.opener.document.getElementById(igeo).style.backgroundSize='cover';
    window.opener.document.getElementById(igeo).style.backgroundRepeat='no-repeat';

    window.opener.document.getElementById(igeo).style.backgroundImage='URL(`data:image/svg+xml;utf8,' + wbtoa('<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo) + '</s' + 'vg>') + '`)';
    if (('' + window.opener.document.getElementById(igeo).outerHTML).indexOf('none;') != -1) {
    window.opener.document.getElementById(igeo).style.display='block';
    }
    } else if (('' + window.opener.document.getElementById(igeo).innerHTML) == '' || ('' + window.opener.document.getElementById(igeo).innerHTML).indexOf('<svg') == 0) {
    //window.opener.document.getElementById(igeo).innerHTML='<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo).replace(cswis,newercswis).replace(cshis,newercshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis) + '</s' + 'vg>';
    window.opener.document.getElementById(igeo).innerHTML='<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'#ffffff').replace(/\#000000/g,'#000000').replace(/\#cccccc/g,'#cccccc').replace(/\#dddddd/g,'#cccccc').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'#_ABSTRACT_RENDERER_ID_2').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'#_ABSTRACT_RENDERER_ID_1').replace(/\#109618/g,'#109618').replace(/\<text/g,'<!--text').replace(/\<\/text\>/g,'</text-->').replace(/\#f5f5f5/g,'#e5e5e5').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo).replace(cswis,newercswis).replace(cshis,newercshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis) + '</s' + 'vg>';
    if (('' + window.opener.document.getElementById(igeo).outerHTML).indexOf('none;') != -1) {
    window.opener.document.getElementById(igeo).style.display='block';
    }
    }
    }
    }

    if (window.parent && !candidate) {
    if (window.parent.document.getElementById(igeo)) {
    candidate=true;
    if (('' + window.parent.document.getElementById(igeo).value).replace('undefined','').replace('null','') != '') {
    igeo=window.parent.document.getElementById(igeo).value;
    }
    if (cswis.trim() != '') {
    whrect=window.parent.document.getElementById(igeo).getBoundingClientRect();
    // 2000 x 2500 to fit into 800 x 654
    if (eval(swis / eval('' + whrect.width)) < eval(shis / eval('' + whrect.height))) {
    aspfactor=eval(eval('' + whrect.width) / swis);
    cswistwo='width=' + ('' + swis).split('.')[0];
    cshistwo='height=' + ('' + shis).split('.')[0];
    newcswistwo='width=' + Math.floor(eval(swis * aspfactor));
    newcshistwo='height=' + Math.floor(eval(shis * aspfactor));
    //alert('cswistwo=' + cswistwo + ' and newcswistwo=' + newcswistwo);
    //if (swhat.indexOf(' clip-path=') != -1) {
    // alert(swhat.split(' clip-path=')[1].substring(0,400));
    //}
    newcswis=' width=' + whdelim + eval(swis * aspfactor) + whdelim;
    newcshis=' height=' + whdelim + eval(shis * aspfactor) + whdelim;
    } else {
    aspfactor=eval(eval('' + whrect.height) / shis);
    cswistwo='width=' + ('' + swis).split('.')[0];
    cshistwo='height=' + ('' + shis).split('.')[0];
    newcswistwo='width=' + Math.floor(eval(swis * aspfactor));
    newcshistwo='height=' + Math.floor(eval(shis * aspfactor));
    //alert('Cswistwo=' + cswistwo + ' and newcswistwo=' + newcswistwo);
    //if (swhat.indexOf(' clip-path=') != -1) {
    // alert(swhat.split(' clip-path=')[1].substring(0,400));
    //}
    newcswis=' width=' + whdelim + eval(swis * aspfactor) + whdelim;
    newcshis=' height=' + whdelim + eval(shis * aspfactor) + whdelim;
    }
    }
    if (('' + window.parent.document.getElementById(igeo).outerHTML).indexOf('background') != -1) {
    //ajaxit(document.URL);
    window.parent.document.getElementById(igeo).style.backgroundSize='cover';
    window.parent.document.getElementById(igeo).style.backgroundRepeat='no-repeat';


    //window.parent.document.getElementById(igeo).style.backgroundImage='URL(`data:image/svg+xml;utf8,' + wbtoa('<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo) + '</s' + 'vg>') + '`)';
    //alert('URL(\"data:image/svg+xml;utf8,' + (wbtoa('<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo) + '</s' + 'vg>')) + '\")');
    window.parent.document.getElementById(igeo).style.backgroundImage='URL(\"data:image/svg+xml;utf8,' + (wbtoa('<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo) + '</s' + 'vg>')) + '\")';
    if (('' + window.parent.document.getElementById(igeo).outerHTML).indexOf('none;') != -1) {
    window.parent.document.getElementById(igeo).style.display='block';
    }
    //window.parent.document.getElementById('rest').innerHTML='<img src=\"' + 'data:image/svg+xml;base64,' + window.btoa(wbtoa('<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo) + '</s' + 'vg>')) + '\"></img>';
    } else if (('' + window.parent.document.getElementById(igeo).innerHTML) == '' || ('' + window.parent.document.getElementById(igeo).innerHTML).indexOf('<svg') == 0) {
    window.parent.document.getElementById(igeo).innerHTML='<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'#ffffff').replace(/\#000000/g,'#000000').replace(/\#cccccc/g,'#cccccc').replace(/\#dddddd/g,'#cccccc').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'#_ABSTRACT_RENDERER_ID_2').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'#_ABSTRACT_RENDERER_ID_1').replace(/\#109618/g,'#109618').replace(/\<text/g,'<!--text').replace(/\<\/text\>/g,'</text-->').replace(/\#f5f5f5/g,'#e5e5e5').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo).replace(cswis,newercswis).replace(cshis,newercshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis) + '</s' + 'vg>';
    if (('' + window.parent.document.getElementById(igeo).outerHTML).indexOf('none;') != -1) {
    window.parent.document.getElementById(igeo).style.display='block';
    }
    }
    }
    }

    if (window.top && !candidate) {
    if (window.top.document.getElementById(igeo)) {
    candidate=true;
    if (('' + window.top.document.getElementById(igeo).value).replace('undefined','').replace('null','') != '') {
    igeo=window.top.document.getElementById(igeo).value;
    }
    if (cswis.trim() != '') {
    whrect=window.top.document.getElementById(igeo).getBoundingClientRect();
    // 2000 x 2500 to fit into 800 x 654
    if (eval(swis / eval('' + whrect.width)) < eval(shis / eval('' + whrect.height))) {
    aspfactor=eval(eval('' + whrect.width) / swis);
    cswistwo='&width=' + ('' + swis).split('.')[0];
    cshistwo='&height=' + ('' + shis).split('.')[0];
    newcswistwo='&width=' + Math.floor(eval(swis * aspfactor));
    newcshistwo='&height=' + Math.floor(eval(shis * aspfactor));
    newcswis=' width=' + whdelim + eval(swis * aspfactor) + whdelim;
    newcshis=' height=' + whdelim + eval(shis * aspfactor) + whdelim;
    } else {
    aspfactor=eval(eval('' + whrect.height) / shis);
    cswistwo='&width=' + ('' + swis).split('.')[0];
    cshistwo='&height=' + ('' + shis).split('.')[0];
    newcswistwo='&width=' + Math.floor(eval(swis * aspfactor));
    newcshistwo='&height=' + Math.floor(eval(shis * aspfactor));
    newcswis=' width=' + whdelim + eval(swis * aspfactor) + whdelim;
    newcshis=' height=' + whdelim + eval(shis * aspfactor) + whdelim;
    }
    }
    if (('' + window.top.document.getElementById(igeo).outerHTML).indexOf('background') != -1) {
    window.top.document.getElementById(igeo).style.backgroundSize='cover';
    window.top.document.getElementById(igeo).style.backgroundRepeat='no-repeat';
    window.top.document.getElementById(igeo).style.backgroundImage='URL(`data:image/svg+xml;utf8,' + wbtoa('<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo) + '</s' + 'vg>') + '`)';
    if (('' + window.top.document.getElementById(igeo).outerHTML).indexOf('none;') != -1) {
    window.top.document.getElementById(igeo).style.display='block';
    }
    } else if (('' + window.top.document.getElementById(igeo).innerHTML) == '' || ('' + window.top.document.getElementById(igeo).innerHTML).indexOf('<svg') == 0) {
    //window.top.document.getElementById(igeo).innerHTML='<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'white').replace(/\#000000/g,'black').replace(/\#cccccc/g,'gray').replace(/\#dddddd/g,'silver').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'').replace(/\#109618/g,'green').replace(/\#f5f5f5/g,'lightgray').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo).replace(cswis,newercswis).replace(cshis,newercshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis) + '</s' + 'vg>';
    window.top.document.getElementById(igeo).innerHTML='<svg viewBox=\"0 0 ' + Math.floor(eval(swis * aspfactor)) + ' ' + Math.floor(eval(shis * aspfactor)) + '\" ' + swhat.split('</s' + 'vg>')[0].split('<svg')[eval(-1 + swhat.split('</s' + 'vg>')[0].split('<svg').length)].replace(/\#ffffff/g,'#ffffff').replace(/\#000000/g,'#000000').replace(/\#cccccc/g,'#cccccc').replace(/\#dddddd/g,'#cccccc').replace(/\#_ABSTRACT_RENDERER_ID_2/g,'#_ABSTRACT_RENDERER_ID_2').replace(/\#_ABSTRACT_RENDERER_ID_1/g,'#_ABSTRACT_RENDERER_ID_1').replace(/\#109618/g,'#109618').replace(/\<text/g,'<!--text').replace(/\<\/text\>/g,'</text-->').replace(/\#f5f5f5/g,'#e5e5e5').replace('hidden;','visible;').replace(cswistwo,newcswistwo).replace(cshistwo,newcshistwo).replace(cswis,newercswis).replace(cshis,newercshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis).replace(cswis,newcswis).replace(cshis,newcshis) + '</s' + 'vg>';
    if (('' + window.top.document.getElementById(igeo).outerHTML).indexOf('none;') != -1) {
    window.top.document.getElementById(igeo).style.display='block';
    }
    }
    }
    }

    }
    }
    return swhat;
    }


    setTimeout(function(){ svgret(document.body.innerHTML); }, 5000);

    “; ?>
    … in >the changed geo_chart.php Geo Chart
  • interfacer of the div element …

… and offering user control over the resultant Google Charts Geo Chart …

  1. width
  2. height
  3. latitude
  4. longitude
  5. place(s)

… further to the previous progress regarding Google Charts Geo Charts when we presented TimeZone Places Nearest Places Tweak Tutorial.

Our first draft geotest.html “proof of concept” tests of this are available here.


Previous relevant TimeZone Places Nearest Places Tweak Tutorial is shown below.

TimeZone Places Nearest Places Tweak Tutorial

TimeZone Places Nearest Places Tweak Tutorial

When we presented GeoJson World Countries Drag and Drop Makeover Nuance Tutorial we tweaked our inhouse TimeZone Places PHP web application. But it needs a “re-tweak”.

In that Nearest Places form part of the TimeZone places webpage, we noticed that even when shaping to enter a TimeZone Placename in the first textbox we made no attempt to fill in …

  • latitude
  • longitude

… when we have the information to do so, and even if we’re misunderstanding a placename designation, that should not stop us from trying, because those two numerical fields above can be corrected, and the form resubmitted, in these scenarios.

Apart from making a PHP derived Javascript variable be made available to the code, we “wrap”

<?php

$otherform="<br><br><iframe id=nearestif name=nearestif style=display:none; src=about:none></iframe><div id=nearest></div><form target=nearestif action=./tz_places.php method=GET style=background-color:#f0f0f0;>Place: <input onblur=\" if (this.value.length > 0) { document.getElementById('nearestif').src=perhapsfillin('./tz_places.php?latitude=&longitude=&place=' + encodeURIComponent(this.value)); } \" type=text id=nplace name=place value=></input> Latitude: <input type=number id=latitude name=latitude value=0.0000 max=90.0000 min=-90.0000 step=0.0001></input> Longitude: <input type=number id=longitude name=longitude value=0.0000 max=180.0000 min=-180.0000 step=0.0001></input><br><input style=background-color:orange; type=submit id=inearest value='Nearest TimeZone Places'></input></form>";

?>

… the “a” link content call via …

<?php echo ”

function perhapsfillin(inidea) {
// './tz_places.php?latitude=&longitude=&place=' + encodeURIComponent(this.value))
var outidea=inidea;
if (inidea.indexOf('place=') != -1) {
var inplaceis=decodeURIComponent(inidea.split('place=')[1].split('&')[0].split('#')[0]);
// +07'>Asia/Tomsk</option><option value='Europe/London' data-geo='51.5074,-0.1278,BST,GB,+0'>Europe/London</
if (yourtzlist.toLowerCase().indexOf('/' + inplaceis.toLowerCase().replace(/\ /g,'_') + '<') != -1) {
document.getElementById('latitude').value='' + eval('' + yourtzlist.toLowerCase().split('/' + inplaceis.toLowerCase().replace(/\ /g,'_') + '<')[0].split(' data-geo=')[eval(-1 + yourtzlist.toLowerCase().split('/' + inplaceis.toLowerCase().replace(/\ /g,'_') + '<')[0].split(' data-geo=').length)].substring(1).split(',')[0]).toPrecision(6);
document.getElementById('longitude').value='' + eval('' + yourtzlist.toLowerCase().split('/' + inplaceis.toLowerCase().replace(/\ /g,'_') + '<')[0].split(' data-geo=')[eval(-1 + yourtzlist.toLowerCase().split('/' + inplaceis.toLowerCase().replace(/\ /g,'_') + '<')[0].split(' data-geo=').length)].substring(1).split(',')[1]).toPrecision(6);
outidea=outidea.replace('latitude=' + inidea.split('latitude=')[1].split('&')[0].split('#')[0], 'latitude=' + document.getElementById('latitude').value);
outidea=outidea.replace('longitude=' + inidea.split('longitude=')[1].split('&')[0].split('#')[0], 'longitude=' + document.getElementById('longitude').value);
}
}
return outidea;
}

“; ?>

… in the changed TimeZone Places tz_places.php


Previous relevant GeoJson World Countries Drag and Drop Makeover Nuance Tutorial is shown below.

GeoJson World Countries Drag and Drop Makeover Nuance Tutorial

GeoJson World Countries Drag and Drop Makeover Nuance Tutorial

Nuance alert! We’re not sure if you noticed, but if you tried out the Drag and Drop functionality in the World Countries web application of yesterday’s GeoJson World Countries Drag and Drop Makeover Tutorial you may have noticed …

  • for a country with lots of TimeZone places, like Brazil, you could get a decent Google Chart Geo Chart map up … but if you were to click the “Map?” link down the bottom of that iframe …
  • it would fail to show a Google Chart Map Chart for that country’s TimeZone places

This fix, believe it or not, is interesting, perhaps only in an “internal use only” sense, we grant you. But our solution got us delving even more into hashtagging data, so that the solution we came up with was a hybrid whereby …

  • stayed with PHP $_GET[] (ie. address bar ? and & argumented) data (versus using PHP $_POST[] methodologies) … but …
  • where it came to the &data=[most of the data] part, other than its first character, we hashtagged the rest

… so that the logic flows as per usual, but we intervene at places and flesh it out via location.hash (client side only) means. We won’t bore you too much with all the places of intervention except the receiving map.php’s “easiest to get” intervention

<?php

$gtw="";

if (isset($_POST['title'])) {
foreach ($_POST as $name => $val) {
if (strpos($val, 'data:') !== false) {
$fval=urlencode($val); //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
} else {
$fval=str_replace('+','%20',urlencode(str_replace(' ',' + ',str_replace('+',' ',$val)))); //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
}
if ($shto == "") {
$shto="#" . $name . "=" . $fval; //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
} else {
$shto.="&" . $name . "=" . $fval; //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
}
}
}

if (isset($_GET['data'])) {
foreach ($_GET as $name => $val) {
if (strpos($val, 'data:') !== false) {
$fval=urlencode($val); //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
} else {
//$fval=str_replace('+','%20',urlencode($val)); //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
$fval=str_replace('+','%20',urlencode(str_replace(' ',' + ',str_replace('+',' ',$val)))); //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
}
if ($shto == "") {
$gshto="#" . $name . "=" . $fval; //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
} else {
$gshto.="&" . $name . "=" . $fval; //str_replace(" ", "%20", str_replace("'", urlencode("'"), str_replace('"', urlencode('"'), str_replace('=', urlencode('='), str_replace('>', urlencode('>'), str_replace('<', urlencode('<'), str_replace('?', urlencode('?'), str_replace('&', urlencode('&'), $val))))))));
}
}

if ($gshto != '' && strlen($_GET['data']) < 10) {
$gtw="\n
if (document.URL.split('#')[0].indexOf('?') != -1 && decodeURIComponent(decodeURIComponent(('' + location.hash + 'x'))).indexOf('[') == 1) {
var jformoh='<iframe name=lastfig id=lastfig style=\"position:absolute;width:100%;height:100%;z-index:897;top:0px;left:0px;\" src=></iframe><br><form style=display:none; target=_self method=POST action=\"' + document.URL.split('#')[0].split('?')[0] + '\"><input id=gjformsubis type=submit value=Submit style=display:none;></input></form>';
var iiareflds=0, areflds=(document.URL.split('#')[0] + decodeURIComponent(decodeURIComponent((',' + location.hash.substring(1))))).replace('#','&').replace('?','&').split('=');
for (var iiareflds=1; iiareflds<areflds.length; iiareflds++) {
jformoh=jformoh.replace('</form>','<input type=hidden name=\"' + areflds[eval(-1 + iiareflds)].split('&')[eval(-1 + areflds[eval(-1 + iiareflds)].split('&').length)] + '\" value=\"' + decodeURIComponent(areflds[iiareflds].split('&')[0]).replace(/^%2C/g,'').replace(/\,1\]/g,']').replace(/\|/g,',').replace(/\,\,/g,',') + '\"></input></form>');
}
setTimeout(function() {
document.body.innerHTML+=jformoh;
document.getElementById('gjformsubis').click(); }, 7000);
}
";
}

}

?>

… just a matter of concern for …

… using the World Countries GeoJson web application.


Previous relevant GeoJson World Countries Drag and Drop Makeover Tutorial is shown below.

GeoJson World Countries Drag and Drop Makeover Tutorial

GeoJson World Countries Drag and Drop Makeover Tutorial

In a similar vein to the recent GeoJson World Coastlines Drag and Drop Makeover Tutorial, today, we have got a mild makeover happening with the Drag and Drop functionality related to GeoJson World Countries web application usage.

In addition to the Wikipedia information, at the very least, presented following a successful drag and drop operation, from today, we also start presenting a new HTML iframe element containing …

Nearest TimeZone places along with Google Charts for each unique country involved

… used by that changed TimeZone Places tz_places.php helped out by the changed external Javascript countries.js external Javascript all called by our unchanged GeoJson World Countries web application.

The work from that last makeover helped, and today the changes involve …

In tz_places.php start doing what you did for regions.php now for countries.php
<?php

echo "<!doctype html><html><body onload=\"if (('' + top.document.URL).replace('/countries.','/regions.').indexOf('/regions.') != -1) { if (document.getElementById('snearest')) { document.getElementById('snearest').style.left='0px'; } }\" style='background-color:yellow;" . $backstyle . "'><h1>Nearest Timezones ... RJM Programming ... April, 2018 ... <a target=_blank title='Thanks to ...' href='//php.net/manual/en/datetimezone.getlocation.php'>//php.net/manual/en/datetimezone.getlocation.php</a></h1><br><br><br>" . $pd . $ret . "</body></html>";

?>
And in countries.js intervene in the dragover event

target.addEventListener("dragover", (ev) => {
console.log("dragOver");
if (window.parent) {
if (parent.document.URL.indexOf('/countries.') != -1) {
var ftables=parent.document.getElementsByTagName('table');
if (eval('' + ftables.length) > 0) {
if (ftables[0].innerHTML.indexOf('lastrow') == -1) {
ftables[0].innerHTML+='<tr id=lastrow><td><iframe id=lastif style=display:none;width:100%;height:900px; src="/PHP/tz_places.php"></iframe></td></tr>';
}
}
}
}

ev.preventDefault();
});
Intervene again, where applicable

if (parent.document.URL.indexOf('/regions.') != -1) {
window.open('/PHP/tz_places.php?place=&latitude=' + encodeURIComponent('' + parent.derivethislat(pos4)) + '&longitude=' + encodeURIComponent('' + parent.derivethislong(pos3)) + '&ntztontz=y','_blank','top=180,left=' + eval(-350 + screen.width) + ',width=350,height=600');
} else {
if (parent.document.getElementById('lastif')) {
parent.document.getElementById('lastif').style.display='block';
parent.document.getElementById('lastif').src='/PHP/tz_places.php?place=&latitude=' + encodeURIComponent('' + parent.derivethislat(pos4)) + '&longitude=' + encodeURIComponent('' + parent.derivethislong(pos3)) + '&ntztontz=y';
}

window.open('//wikipedia.org/wiki/' + encodeURIComponent(tdid.replace(/\ /g,'_')),'_blank','top=180,left=' + eval(-350 + screen.width) + ',width=350,height=600');
}


Previous relevant GeoJson World Coastlines Drag and Drop Makeover Tutorial is shown below.

GeoJson World Coastlines Drag and Drop Makeover Tutorial

GeoJson World Coastlines Drag and Drop Makeover Tutorial

We’ve got a mild makeover happening with the Drag and Drop functionality related to GeoJson World Coastlines Drag and Drop Tutorial today.

At first …

  • we wanted the first popup window content be aligned to the top and left … and then …
  • we thought it would be good to also, in “Drag and Drop land”, relevant countries nearby to the user’s drop point TimeZone Places be showing below that (and it panned out the best way to show this, for us, was via an iframe pointing at another incarnation of the tz_places.php webpage, because it could have GET arguments iso, iso2, iso3 etcetera to point at ISO 2 letter country codes, which we made more readily available (via a new data-cc global data attribute applied to the select option subelements presented) for the changed external Javascript countries.js we decided should get into the mix via a new Javascript function …

    function tzagain(inhtml) {
    var outhtml=inhtml, dccs=[], getarg='?', theone=1;
    if (inhtml.indexOf('left:0px;') != -1 && inhtml.indexOf(' data-cc=') != -1) {
    dccs=inhtml.split(' data-cc=');
    for (var ii=1; ii<dccs.length; ii++) {
    if (getarg == '?') {
    getarg+='iso=' + dccs[ii].substring(0,4).replace(/\'/g,'').replace(/\"/g,'').substring(0,2);
    theone++;
    } else if (getarg.indexOf('=' + dccs[ii].substring(0,4).replace(/\'/g,'').replace(/\"/g,'').substring(0,2)) == -1) {
    getarg+='&iso' + theone + '=' + dccs[ii].substring(0,4).replace(/\'/g,'').replace(/\"/g,'').substring(0,2);
    theone++;
    }
    }
    if (getarg != '?') {
    if (inhtml.indexOf('</bo' + 'ody>') != -1) {
    outhtml=inhtml.split('</bo' + 'dy>')[0] + '<iframe src="./tz_places.php' + getarg + '" style="position:absolute;left:0px;top:120px;width:100%;height:900px;"></iframe></body></html>';
    } else {
    outhtml=inhtml + '<iframe src="./tz_places.php' + getarg + '" style="position:absolute;left:0px;top:120px;width:100%;height:900px;"></iframe>';
    }
    }
    }
    return outhtml;
    }

    )

… used by that changed TimeZone Places tz_places.php as exemplified below

<?php

echo "<!doctype html><html><head><scr" . "ipt type='text/javascript' src='/HTMLCSS/countries.js?rand=" . rand(0,16756453) . "'></scr" . "ipt><scr" . "ipt type='text/javascript'> function lookoutfortop() { if (parent.document.getElementById('getmell')) { parent.document.getElementById('nearest').innerHTML=\"" . $pd . $retmore . "\"; } else if (top.document.getElementById('nearest')) { if (top.document.getElementById('getmell')) { top.document.getElementById('nearest').innerHTML=\"" . $pd . $retmore . "\"; } else { top.document.getElementById('nearest').innerHTML=\"" . $pd . $ret . "\"; } top.window.scrollTo(0,0); } else { if (top.document.getElementById('getmell')) { document.body.innerHTML=tzagain(\"" . $pd . $retmore . "\"); } else { document.body.innerHTML=tzagain(\"" . $pd . str_replace(':70px;',':0px;',str_replace(':350px;',':0px;',$ret)) . "\"); } } if (('' + top.document.URL).indexOf('/regions.') != -1) { if (document.getElementById('snearest')) { document.getElementById('snearest').style.left='0px'; } } } </scr" . "ipt></head><body onload=' lookoutfortop();'" . $backfullstyle . ">" . $pd . $ret . "</body></html>"; //$ret;

?>

… that superfluous looking ?rand=blah measure being pretty useful really regarding getting around the cache keeping old external Javascript in its mind after changes.

Curiously, the grandparent regions.php starting off all this needed no changing! We hope you like these tweaks!


Previous relevant GeoJson World Coastlines Drag and Drop Tutorial is shown below.

GeoJson World Coastlines Drag and Drop Tutorial

GeoJson World Coastlines Drag and Drop Tutorial

The primary aim of today’s work, onto yesterday’s GeoJson World Drag and Drop on iPad Tutorial iPad integration is to …

  • add similar drag and drop logic into our World Coastlines GeoJson web application … and along the way, also for the World Countries web application …
  • hold off involving the (pretty kludgy looking) vertical scrollbar of our drag and drop pin’s underlying HTML iframe …

    <iframe scrolling=no frameborder=0 name=iftr id=iftr style=display:none; srcdoc="<body style=background-color:transparent;><p id=mg title='Wikipedia country page below via drag and drop to world map' draggable='true'>📍</p><br><br><div id=myh1></div><script type='text/javascript' src='./countries.js?rand=321156747657' defer></script></body>" data-src=></iframe>

    … until the first drag operation starting, calls on …

    parent.document.getElementById('iftr').scrolling='yes';

    … proving a Javascript DOM control of the “scrolling” attribute works (as we weren’t sure, having never done this before)

It’s worth beavering away at a guinea pig web application until (just about complete) satisfaction (for now) before having a parallel set of code changes happening simultaneously, we’ve always found.

So, what happened in “external Javascript land”? No need for a “regions.js” here, as parent.document.URL can be scrutinised in that “external Javascript land” to discover which web application is the parent, and act accordingly. So changed were our changed external Javascript countries.js in …


Previous relevant GeoJson World Drag and Drop on iPad Tutorial is shown below.

GeoJson World Drag and Drop on iPad Tutorial

GeoJson World Drag and Drop on iPad Tutorial

Yesterday’s GeoJson World Drag and Drop Google Tutorial had us at a very interesting position, one that we cannot recall ever happening before, that being …

  • our GeoJson World Countries web application Drag and Drop logic worked on an iPhone … but …
  • our GeoJson World Countries web application Drag and Drop logic did not work on an iPad

They’re both iOS! And usually the smaller iPhone has the problem and the larger iPad is okay when there is an odd scenario happening. So, what gives? Well, the odd thing is, it was just rearrangements of code and iframe srcdoc usage


<iframe frameborder=0 name=iftr id=iftr style=display:none; srcdoc="<body style=background-color:transparent;><p id=mg title='Wikipedia country page below via drag and drop to world map' draggable='true'>📍</p><br><br><div id=myh1></div><script type='text/javascript' src='./countries.js?rand=321156747657' defer></script></body>" data-src=></iframe>

… that ended up helping us fix the issues. Figure this, on iPad our emoji pin could not be made visible down the bottom left of iPad screen but could be made to work in the title elements section?! Of course, we might have been having a bad day, but in our defence, even debugging in Safari via …

  • iPad Safari web browser invocation …
  • Apple white lead from iPad to MacBook Air …
  • MacBook Air Safari web browser Develop menu dropdown got us to debugging functionality

showed nothing untoward, and neither did, on the iPad’s Chrome browser …


chrome://inspect

… debugging techniques.

Changed were our changed external Javascript countries.js in our changed countries.php GeoJson World Countries PHP web application in a new window. If you have any clues yourself, the comments are there?!


Previous relevant GeoJson World Drag and Drop Google Tutorial is shown below.

GeoJson World Drag and Drop Google Tutorial

GeoJson World Drag and Drop Google Tutorial

We often turn to what we like to call …

  • “long hover” (ie. on non-mobile, wait for a long while after the onmouseover event initiation to see whether the user is still hovering) … and today, a bit like that, is the new, for us …
  • “long drag” (the user waits a long time between the drag initialization and the drop event)

… and because we found “dawdling” on a drag and drop fairly unnatural, we think this “long drag” idea “has legs”, in that it works well as a deliberate act made by a user, knowing at the end they benefit from their actions. For us, with our GeoJSON Map web application, yesterday, with GeoJson World Drag and Drop Pin Tutorial, the drag and drop led to …

  • Wikipedia country information webpage … and today, we allow a “long drag” get you to …
  • Google Maps drop position information webpage … if the “long drag” is for 10 or more seconds …
  • Google Earth drop position information webpage … if the “very long drag” is for 20 or more seconds

… arranged for via our changed external Javascript countries.js in our changed countries.php GeoJson World Countries PHP web application in a new window.


Previous relevant GeoJson World Drag and Drop Pin Tutorial is shown below.

GeoJson World Drag and Drop Pin Tutorial

GeoJson World Drag and Drop Pin Tutorial

Before today, with the GeoJson Countries web application from GeoJson World Colour Wheel Wikipedia Integration Tutorial we’ve mainly used …

  • onclick event logic … and today, we start to also include …
  • drag and drop event logic (like, but nuanced as explained below, the experimental drag and drop ideas included in the recent Planet Moon Game Tutorial) … the nuanced differences involving …
    1. the drag part of the events occurs in an iframe (populated via small amount of srcdoc HTML and Javascript) able to reference its originator via window.parent …
    2. drop part of the events occurs in that originator parent and so several Javascript function called by the child reside in the parent … and …
    3. the child “drag” event controller uses the new external Javascript countries.js

      // countries.js
      // July, 2023
      // RJM Programming
      // Help out countries.html and countries.php
      var pos3=0, pos4=0, tdid='', poligono, punto, coone='', prectis;

      // var poligono = [[2,9],[8,6],[12,10],[15,2],[10,4],[5,1]];
      // var punto = [6, 5];

      function pointInPolygon(polygon, point) { // thanks to https://community.appinventor.mit.edu/t/geofence-check-if-a-point-is-inside-a-polygon-javascript-map/57091
      var odd = false;
      for (var i = 0, j = polygon.length - 1; i < polygon.length; i++) {
      if (((polygon[i][1] > point[1]) !== (polygon[j][1] > point[1]))
      && (point[0] < ((polygon[j][0] - polygon[i][0]) * (point[1] - polygon[i][1]) / (polygon[j][1] - polygon[i][1]) + polygon[i][0]))) {
      odd = !odd;
      }
      j = i;
      }
      return odd;
      }

      function andlaterstill() {
      if (9 == 6) { // temporary
      if (tdid != '') {
      document.getElementById(tdid).innerHTML=document.getElementById(tdid).innerHTML.substring(0,1);
      } else if (document.getElementById('mytable').innerHTML.indexOf(clonedatatwo) != '') {
      document.getElementById('myh1').innerHTML=document.getElementById('myh1').innerHTML.split('</table>')[0] + '</table>';
      }
      if (document.getElementsByTagName('div')[0].innerHTML.indexOf(clonedatatwo) != -1) {
      document.getElementsByTagName('div')[0].innerHTML=document.getElementsByTagName('div')[0].innerHTML.replace(clonedatatwo,'');
      } else if (document.getElementsByTagName('div')[0].innerHTML.indexOf(clonedatatwo.replace('dragging','')) != -1) {
      document.getElementsByTagName('div')[0].innerHTML=document.getElementsByTagName('div')[0].innerHTML.replace(clonedatatwo.replace('dragging',''),'');
      } else if (document.body.innerHTML.split('<table')[0].indexOf(clonedatatwo.replace('dragging','')) != -1) {
      document.body.innerHTML=document.body.innerHTML.replace(document.body.innerHTML.split('<table')[0], document.body.innerHTML.split('<table')[0].replace(clonedatatwo.replace('dragging',''),''));
      } else if (document.body.innerHTML.split('<table')[0].indexOf(clonedatatwo) != -1) {
      document.body.innerHTML=document.body.innerHTML.replace(document.body.innerHTML.split('<table')[0], document.body.innerHTML.split('<table')[0].replace(clonedatatwo,''));
      }
      }
      tdid='';
      }

      function getprectis() {
      if (window.opener) {
      if (window.opener.document.getElementsByTagName('body')[0]) {
      return window.opener.document.body.getBoundingClientRect();
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      return parent.document.body.getBoundingClientRect();
      }
      }
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      return parent.document.body.getBoundingClientRect();
      }
      }
      return null;
      }

      function wod(ididea) {
      if (window.opener) {
      if (window.opener.document.getElementsByTagName(ididea)[0]) {
      return window.opener.document.getElementsByTagName(ididea)[0];
      } else if (window.parent) {
      if (parent.document.getElementsByTagName(ididea)[0]) {
      return parent.document.getElementsByTagName(ididea)[0];
      }
      }
      } else if (window.parent) {
      if (parent.document.getElementsByTagName(ididea)[0]) {
      return parent.document.getElementsByTagName(ididea)[0];
      }
      }
      return null;
      }

      function ccit() {
      var divs, esot=[], bodyois=null;
      if (window.opener) {
      if (window.opener.document.getElementsByTagName('body')[0]) {
      bodyois=window.opener.document.getElementsByTagName('body')[0];
      divs=window.opener.document.getElementsByTagName('div');
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      bodyois=parent.document.getElementsByTagName('body')[0];
      divs=parent.document.getElementsByTagName('div');
      }
      }
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      bodyois=parent.document.getElementsByTagName('body')[0];
      divs=parent.document.getElementsByTagName('div');
      }
      }

      for (var ii=0; ii<divs.length; ii++) {
      if (divs[ii].outerHTML.split('>')[0].indexOf(' title=' + String.fromCharCode(34) + coone) != -1) {
      divs[ii].innerHTML=divs[ii].innerHTML.replace('z-index:24;', 'z-index:123;').replace('lime;', 'rgba(200,200,200,0.3);');
      divs[ii].name='d' + tdid.replace(/\ /g, '_');
      }
      }
      }

      function andqlater() {
      //alert('HeRe');
      tdid='';
      var ppig='[]', coo='', coos=[], ip=0;
      var squares; //=window.opener.document.getElementsByTagName('area');

      if (window.opener) {
      if (window.opener.document.getElementsByTagName('body')[0]) {
      squares=window.opener.document.getElementsByTagName('area');
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      squares=parent.document.getElementsByTagName('area');
      }
      }
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      squares=parent.document.getElementsByTagName('area');
      }
      }

      for (var ii=1; ii<=squares.length; ii++) {
      ppig='[]';
      coos=squares[eval(-1 + ii)].coords.replace(/\ /g,',').split(',');
      ppig='[[' + coos[0] + ',' + coos[1] + ']]';
      for (ip=2; ip<coos.length; ip+=2) {
      ppig=ppig.replace(']]', '],[' + coos[ip] + ',' + coos[eval(1 + ip)] + ']]');
      poligono=eval(ppig);
      //alert('' + punto);
      if (pointInPolygon(poligono, punto)) {
      tdid='' + squares[eval(-1 + ii)].getAttribute('data-cname');
      coone=('' + squares[eval(-1 + ii)].coords).split(' ')[0];
      setTimeout(ccit, 2000);
      console.log('tdid=' + tdid + ' and coone=' + coone);
      if (window.opener) {
      if (window.opener.document.getElementsByTagName('body')[0]) {
      window.focus();
      document.getElementById('myh1').innerHTML='<iframe style="width:100%;height:800px;" src="//wikipedia.org/wiki/' + encodeURIComponent(tdid.replace(/\ /g,'_')) + '"></iframe>';
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      document.getElementById('myh1').innerHTML='<iframe style="width:100%;height:800px;" src="//wikipedia.org/wiki/' + encodeURIComponent(tdid.replace(/\ /g,'_')) + '"></iframe>';
      window.open('//wikipedia.org/wiki/' + encodeURIComponent(tdid.replace(/\ /g,'_')),'_blank','top=180,left=' + eval(-350 + screen.width) + ',width=350,height=600');
      }
      }
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      document.getElementById('myh1').innerHTML='<iframe style="width:100%;height:800px;" src="//wikipedia.org/wiki/' + encodeURIComponent(tdid.replace(/\ /g,'_')) + '"></iframe>';
      window.open('//wikipedia.org/wiki/' + encodeURIComponent(tdid.replace(/\ /g,'_')),'_blank','top=180,left=' + eval(-350 + screen.width) + ',width=350,height=600');
      }
      }
      return tdid;
      }
      }
      }
      console.log('tdid=' + tdid);
      //setTimeout(andlaterstill, 100);
      return '';
      }

      window.addEventListener("DOMContentLoaded", () => {
      const source = document.querySelector("#mg");
      console.log('source.id=' + source.id);
      source.addEventListener("dragstart", (ev) => {
      console.log("dragStart");
      // Change the source element's background color
      // to show that drag has started
      ev.currentTarget.classList.add("dragging");
      // Clear the drag data cache (for all formats/types)
      ev.dataTransfer.clearData();
      // Set the drag's format and data.
      // Use the event target's id for the data
      ev.dataTransfer.setData("text/plain", ev.target.id);
      //ev.dataTransfer.setData("text/html", ev.target.outerHTML);
      });
      source.addEventListener("dragend", (ev) =>
      ev.target.classList.remove("dragging")
      );

      const target = wod('body'); //window.opener.document.getElementsByTagName('body')[0];
      target.id='usemap';
      console.log('target.id=' + target.id);
      target.addEventListener("dragover", (ev) => {
      console.log("dragOver");
      ev.preventDefault();
      });
      target.addEventListener("drop", (ev) => {
      console.log("Drop");
      ev.preventDefault();
      // Get the data, which is the id of the source element
      const data = ev.dataTransfer.getData("text");
      const source = document.getElementById(data);

      var prectis=getprectis();

      console.log('' + ev.target.id);
      if (!document.getElementById('callback')) {
      if (('' + ev.target.id).substring(0,2) == 'im') {
      score+=eval(ev.target.innerHTML.substring(0,1));
      }
      } else if (1 == 1) { //document.getElementById('callback')) {
      secs++;
      if (('' + ev.target.getAttribute('data-answer')) == ('' + document.getElementById('mg').getAttribute('data-answer'))) {
      score++;
      document.getElementById('score').innerHTML='Score: ' + score + '/' + secs + '';
      } else {
      document.getElementById('score').innerHTML='Score: ' + score + '/' + secs + '';
      alert('Correct answer was ' + document.getElementById('mg').getAttribute('data-answer'));
      }
      location.href=document.getElementById('callback').value + '?score=' + score + '&secs=' + secs;
      }
      if (1 == 2) {
      //clonedatatwo=document.getElementById('source').outerHTML;
      //document.getElementById('mytable').innerHTML=document.getElementById('mytable').innerHTML.replace(clonedatatwo, '');
      //ev.target.innerHTML=ev.target.innerHTML.substring(0,1) + clonedatatwo;
      } else if ((9 == 9 || ('' + ev.target.id).substring(0,2) == 'im')) {
      //clonedatatwo=document.getElementById('source').outerHTML;
      // // andqlater();
      //document.getElementById('mytable').innerHTML=document.getElementById('mytable').innerHTML.replace(clonedatatwo, '');
      //ev.target.innerHTML=ev.target.innerHTML.substring(0,1) + clonedatatwo;
      //document.getElementById('myh1').appendChild(source);
      //if (('' + ev.target.id).substring(0,2) != 'im') {
      //document.getElementById('myh1').insertAdjacentHTML('beforeend', clonedatatwo);
      //} else {
      //ev.target.insertAdjacentHTML('beforeend', clonedatatwo);
      //}
      } else {
      ev.target.appendChild(source);
      }

      prectis=getprectis();

      if (ev.touches) {
      if (ev.touches[0].pageX) {
      pos3 = ev.touches[0].pageX;
      pos4 = ev.touches[0].pageY;
      } else {
      pos3 = ev.touches[0].clientX;
      pos4 = ev.touches[0].clientY;
      }
      console.log('pos3 = ' + pos3 + ',pos4 = ' + pos4);
      } else if (ev.clientX || ev.clientY) {
      pos3 = ev.clientX;
      pos4 = ev.clientY;
      console.log('pos3 = ' + pos3 + ' ,pos4 = ' + pos4);
      } else {
      pos3 = ev.pageX;
      pos4 = ev.pageY;
      console.log('pos3 = ' + pos3 + ', pos4 = ' + pos4);
      }
      //alert('[' + pos3 + ',' + pos4 + ']');
      var wop=0;
      if (window.opener) {
      if (window.opener.document.getElementsByTagName('body')[0]) {
      window.opener.derivethislong(pos3);
      window.opener.derivethislat(pos4);
      wop=window.opener.getzoom();
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      parent.derivethislong(pos3);
      parent.derivethislat(pos4);
      wop=parent.getzoom();
      }
      }
      } else if (window.parent) {
      if (parent.document.getElementsByTagName('body')[0]) {
      parent.derivethislong(pos3);
      parent.derivethislat(pos4);
      wop=parent.getzoom();
      }
      }

      //pos3+=eval(wop * prectis.left);
      //pos4+=eval(wop * prectis.top);
      var xwop='1';


      console.log('prectis.left/top=' + prectis.left + '/' + prectis.top);


      //punto=eval('[' + eval(eval('' + pos3) / eval('' + wop)) + ',' + eval(eval('' + pos4) / eval('' + wop)) + ']');

      punto=eval('[' + eval(eval(-prectis.left * eval('' + wop) + eval('' + pos3)) / eval('' + wop)) + ',' + eval(eval(-prectis.top * eval('' + wop) + eval('' + pos4)) / eval('' + wop)) + ']');

      console.log(punto);
      andqlater();

      });

      //const reset = document.querySelector("#reset");
      //reset.addEventListener("click", () => document.location.reload());

      });

      function dragorig() {
      if (document.getElementById('mg')) {
      document.getElementById('mg').draggable='true';
      } else {
      setTimeout(dragorig, 5000);
      }
      }

      // setTimeout(dragorig, 5000);

… to open Wikipedia Country information webpages of dropped into user drags (on a world map), in our changed countries.php GeoJson World Countries PHP web application in a new window.


Previous relevant GeoJson World Colour Wheel Wikipedia Integration Tutorial is shown below.

GeoJson World Colour Wheel Wikipedia Integration Tutorial

GeoJson World Colour Wheel Wikipedia Integration Tutorial

Further to yesterday’s GeoJson World Coastline Quiz Deployments Tutorial, with our two …

… web applications, today we want to deepen the integration with Wikipedia on two fronts …

  • GeoJson World Coastline optional quiz Wikipedia webpage navigation offerings, achieved via a Javascript override initiative …

    const confirm = (cblurb) => {
    if (cblurb.indexOf('Answer was ') != -1 && cblurb.indexOf('. ') != -1) {
    var resp=prompt(cblurb.replace(cblurb.split('Answer was ')[1].split('. ')[0] + '. ', cblurb.split('Answer was ')[1].split('. ')[0] + ' (answer W to see more information on Wikipedia). '), '');
    if (resp != null) {
    if (resp.toLowerCase() == 'w') {
    window.open('//en.wikipedia.org/wiki/' + cblurb.split('Answer was ')[1].split('. ')[0].replace(/\ /g,'_'), '_blank', 'top=70,left=70,width=650,height=650');
    return true;
    }
    return true;
    } else {
    return false;
    }
    }
    return window.confirm(cblurb);
    };
  • GeoJson World Countries and Coastline changed map.php Map Chart new onclick menu links to our Colour Wheel web application, and its Wikipedia images and TimeZone information

… in our changed regions.php GeoJson World Coastlines PHP web application in a new window, or you can also try below.


Previous relevant GeoJson World Coastline Quiz Deployments Tutorial is shown below.

GeoJson World Coastline Quiz Deployments Tutorial

GeoJson World Coastline Quiz Deployments Tutorial

The deployment follow up to yesterday’s GeoJson World Coastline Function Noun Naming Tutorial seems to concern mobile platform use of the new …

… where heap memory concerns related to the global variables memory used in our GeoJson World Coastlines webpage could cause mobile platform usage reloads of the web application, reminiscent of the external Javascript concerns we had back at GeoJson World Countries SVG Overlay Safari Error Tutorial.

There, as for here, mobile usage got better by swapping global variable usage for HTML content static PHP …

<?php echo ”

<select id=spops style=display:none;>" . $sih . "</select>
<select id=srivs style=display:none;>" . $rih . "</select>

“; ?>

… via …

<?php

$sih='';
$rih='';

function oururlencode($instuff) {
$outstuff='';
$dotbits=explode('.', $instuff);
if (sizeof($dotbits) > 1) {
$outstuff=$instuff;
for ($ii=1; $ii<sizeof($dotbits); $ii++) {
if (strlen( explode(',', explode(' ', $dotbits[$ii])[0])[0] ) > 3) {
$outstuff=str_replace('.' . explode(',', explode(' ', $dotbits[$ii])[0])[0], '.' . substr(explode(',', explode(' ', $dotbits[$ii])[0])[0],0,3), $outstuff);
}
}
return urlencode($outstuff);
}
return urlencode($instuff);
}

if (file_exists('population.geojson')) {
$rbits=explode(']}}', file_get_contents('./population.geojson'));
for ($irr=1; $irr<(-1 + sizeof($rbits)); $irr++) {
$hdrbit=explode('{"type":"Feature', $rbits[-1 + $irr])[-1 + sizeof(explode('{"type":"Feature', $rbits[-1 + $irr]))];
$hbits=explode(',"NAME":"', $hdrbit);
if (sizeof($hbits) > 1) {
if (strpos($sih, ' id=' . str_replace('+','%20',urlencode(explode('"', $hbits[1])[0])) . ' ') === false) {
$sih.='<option id=' . str_replace('+','%20',urlencode(explode('"', $hbits[1])[0])) . ' value=' . str_replace('+','%20', str_replace('[','', str_replace(']','', str_replace('],[',',' ,explode(']}', explode(':[',$hdrbit)[1])[0])))) . '></option>';
}
}
}
}

if (file_exists('rivers.geojson')) {
$rbits=explode(']]}}', file_get_contents('./rivers.geojson'));
for ($irr=1; $irr<(-1 + sizeof($rbits)); $irr++) {
$hdrbit=explode('{"type":"Feature', $rbits[-1 + $irr])[-1 + sizeof(explode('{"type":"Feature', $rbits[-1 + $irr]))];
$hbits=explode(',"name":"', $hdrbit);
if (sizeof($hbits) > 1) {
if (strpos($sih, 'id=river' . str_replace('+','%20',urlencode(explode('"', $hbits[1])[0])) . '>') === false) {
$rih.='<option value=' . str_replace('+','%20', oururlencode(str_replace('[','', str_replace(']','', str_replace('],[', ',', str_replace(']],[[', ' ', explode(']]}', explode(':[[',$hdrbit)[1])[0])))))) . ' id=river' . str_replace('+','%20',urlencode(explode('"', $hbits[1])[0])) . '></option>';
} else {
$rih=str_replace(' id=river' . str_replace('+','%20', oururlencode(explode('"', $hbits[1])[0])) . '>', str_replace('+','%20', urlencode(str_replace('[','', str_replace(']','', str_replace('],[', ',', str_replace(']],[[', ' ', explode(']]}', explode(':[[',$hdrbit)[1])[0])))))) . ' id=river' . str_replace('+','%20',urlencode(explode('"', $hbits[1])[0])) . '>', $rih);
}
}
}
}

?>

… code usage (ie. the HTML file ends up bigger, to help) in our changed regions.php GeoJson World Coastlines PHP web application in a new window, or you can also try below.


Previous relevant GeoJson World Coastline Function Noun Naming Tutorial is shown below.

GeoJson World Coastline Function Noun Naming Tutorial

GeoJson World Coastline Function Noun Naming Tutorial

We’re working on an extension to yesterday’s GeoJson World Coastline Rivers Quiz Tutorial‘s Rivers Quiz functionality within our GeoJson World Coastlines web application, and have …

  • settled on an approach … but …
  • not yet finished on deployment issues

… but it is this approach we wanted to talk about today.

Our approach borrows from Object Oriented Programming (OOP) the idea that …

  • just as with OOP thinking class names are like nouns and the methods within that class are like verbs … we, with our approach
  • help readability of our non-OOP functional code by including those nouns and verbs, as well as ideas like use of plurals to indicate array involvement, with our Javascript function naming

… we can best illustrate to you via showing you new functions and variables and modified code to show you this approach in code …


var rivers='', arivers=[], iguess=-1, isofar=' ', jscore=0, jgoes=0, elema=null, contexta=null, rectisleft=0, rectistop=0, isokto=true;
var populations='', apopulations=[], jguess=-1, jsofar=' ', both=false, jlastn='';
var idone=false;


function populaterivers() {
var found=-1, ifnd=0;
var rbits=rivers.split(']]}}');
var murraytotal=0.0;
rivers='';
var lastn='', hdrbit='', hbits=[];
for (var irr=1; irr<(-1 + rbits.length); irr++) {
hdrbit=rbits[-1 + irr].split('{' + String.fromCharCode(34) + 'type' + String.fromCharCode(34) + ':' + String.fromCharCode(34) + 'Feature')[eval(-1 + rbits[-1 + irr].split('{' + String.fromCharCode(34) + 'type' + String.fromCharCode(34) + ':' + String.fromCharCode(34) + 'Feature').length)] + '';
//alert(hdrbit);
hbits=hdrbit.split(',' + String.fromCharCode(34) + 'name' + String.fromCharCode(34) + ':' + String.fromCharCode(34));
if (hbits.length > 1) {
if ((!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval('' + arivers.length) <= 200)) {
if (lastn != hbits[1].split(String.fromCharCode(34))[0]) {
lastn=hbits[1].split(String.fromCharCode(34))[0];
found=-1;
if (arivers.length > 0) {
for (ifnd=0; ifnd<arivers.length; ifnd++) {
if (('' + arivers[ifnd]).indexOf(':') != -1 && found == -1) {
if (('' + arivers[ifnd]).split(':')[0] == lastn) { found=ifnd; }
}
}
}
if (found >= 0) {
if (lastn == 'Murray') {
console.log(hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
}
if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
arivers[found]+=' ' + lessit(hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
}
} else {
if (lastn == 'Murray') {
console.log(lastn + ':' + hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
}
arivers.push(lastn + ':' + lessit(hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')));
}
} else if (1 == 1 || !navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (lastn == 'Murray') {
console.log(hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
}
arivers[-1 + arivers.length]+=' ' + lessit(hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
}
}
}
}
rbits=[];
lastn='';
//if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
// alert(arivers.length);
//}
//return;
//plotariver(getariver());
if (!idone) { idone=true; getariver(); }
}


function lessit(maybe) {
var altmaybe='', altmaybed='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
var acsvs=maybe.split(',');
for (var ic=0; ic<acsvs.length; ic++) {
altmaybe+=altmaybed + (acsvs[ic] + '.xyz').substring(0,eval(3 + (acsvs[ic] + '.xyz').indexOf('.'))).split('.xyz')[0];
altmaybed=',';
}
acsvs=[];
return altmaybe;
}
return maybe;
}



function populatepopulations() {
var found=-1, ifnd=0;
var rbits=populations.split(']}}');
populations='';
var jlastn='', hdrbit='', hbits=[];
for (var irr=1; irr<(-1 + rbits.length); irr++) {
hdrbit=rbits[-1 + irr].split('{' + String.fromCharCode(34) + 'type' + String.fromCharCode(34) + ':' + String.fromCharCode(34) + 'Feature')[eval(-1 + rbits[-1 + irr].split('{' + String.fromCharCode(34) + 'type' + String.fromCharCode(34) + ':' + String.fromCharCode(34) + 'Feature').length)] + '';
//alert(hdrbit);
hbits=hdrbit.split(',' + String.fromCharCode(34) + 'NAME' + String.fromCharCode(34) + ':' + String.fromCharCode(34));
if (hbits.length > 1) {
if (jlastn != hbits[1].split(String.fromCharCode(34))[0]) {
jlastn=hbits[1].split(String.fromCharCode(34))[0];
found=-1;
if (apopulations.length > 0) {
for (ifnd=0; ifnd<apopulations.length; ifnd++) {
if (('' + apopulations[ifnd]).indexOf(':') != -1 && found == -1) {
if (('' + apopulations[ifnd]).split(':')[0] == jlastn) { found=ifnd; }
}
}
}
if (found >= 0) {
if (jlastn == 'Sydney') { console.log(hdrbit.split(':[')[1].replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')); }
apopulations[found]+=' ' + lessit(hdrbit.split(':[')[1].replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
} else {
if (jlastn == 'Sydney') { console.log(jlastn + ':' + hdrbit.split(':[')[1].replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')); }
apopulations.push(jlastn + ':' + lessit(hdrbit.split(':[')[1].replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')));
}
} else {
if (jlastn == 'Sydney') { console.log(hdrbit.split(':[')[1].replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')); }
apopulations[-1 + apopulations.length]+=' ' + lessit(hdrbit.split(':[')[1].replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
}
}
}
rbits=[];
jlastn='';
//return;
//plotariver(getariver());
}



function getariver() {
//for (var ih=0; ih<arivers.length; ih++) {
// if (arivers[ih].split(':')[0] == 'Murray') { return ih; }
//}
if (!idone) { document.getElementById('ifrivers').src='./rivers.geojson'; } else if (arivers.length > 0) {
iguess=Math.floor(Math.random() * arivers.length);
if (isofar.indexOf(',' + iguess + ',') != -1) {
while (isofar.indexOf(',' + iguess + ',') != -1) {
iguess=Math.floor(Math.random() * arivers.length);
}
}
isofar+=',' + iguess + ',';
lastn=arivers[iguess].split(':')[0];
plotariver(iguess);
setTimeout(askariver, 8000);
return iguess;
}
}


function askariver() {
var another=false;
var midbit='';
var origboth=both;
var thing='river';
if (!both) { midbit='Append spaces to also answer a question regarding the Populations Quiz, or P to just do Populations Quiz.'; } else { thing='population'; }
var retthis=prompt('What is the name of this new blue river plotted on the world map? ' + midbit + ' Enter ? to get given more time looking at (longitude,latitude) = (' + arivers[iguess].split(':')[1].split(',')[0] + ',' + arivers[iguess].split(':')[1].split(',')[1] + ')', '');
if (retthis == null) {
both=false;
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (retthis.toLowerCase().trim() == 'p') {
both=false;
isokto=true;
getapopulation();
return '';
} else if (retthis.trim() == '?') {
if (retthis.trim() != retthis && !origboth) { both=true; }
setTimeout(askariver, 8000);
return '';
} else if (retthis.trim() == '') {
if (retthis != '' && !origboth) { thing='population'; }
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
if (retthis != '' && !origboth) { isokto=true; both=true; getapopulation(); }
} else if (lastn.toLowerCase().indexOf(retthis.toLowerCase()) != -1 && lastn.toLowerCase() == retthis.toLowerCase() && retthis.trim().length >= 1) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='population'; }
jgoes++;
jscore++;
another=confirm('Will pay that. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (lastn.toLowerCase().indexOf(retthis.toLowerCase()) == -1) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='population'; }
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (lastn.toLowerCase() == retthis.toLowerCase()) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='population'; }
jgoes++;
jscore++;
another=confirm('Well done! Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (retthis.trim().length >= 1) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='population'; }
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else {
if (retthis.trim() != retthis && !origboth) { both=true; thing='population'; }
jgoes++;
jscore++;
another=confirm('Will pay that. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
}
if (both && !origboth) { isitok=true; getapopulation(); return ''; } else if (both) { return ''; }
if (another) { if (both) { getariver(); getapopulation(); } else { getariver(); } } else { contexta.clearRect(0,0,360,180); }
return '';
}



function plotariver(which) {
if (both) { isokto=true; }
if (isokto) { contexta.clearRect(0,0,360,180); }
if (both) { isokto=false; }
lastn=arivers[which].split(':')[0];
var rest=arivers[which].split(':')[1];
var consolelog='';
console.log(rest);
var restlonglat=[]; //rest.split(',');
var therest=rest.split(' ');
//alert(eval(180.0 + eval('' + restlonglat[0])) + ',' + eval(90.0 - eval('' + restlonglat[1])));
for (var jrrr=0; jrrr<therest.length; jrrr++) {
restlonglat=therest[jrrr].split(',');
for (var irrr=2; irrr<restlonglat.length; irrr+=2) {
if (eval(1 + irrr) < eval('' + restlonglat.length)) {
if (irrr == 2) {
contexta.strokeStyle = '#0000ff';
contexta.lineWidth = 1;
contexta.beginPath();
//console.log('context.moveTo(' + eval(180.0 + eval('' + restlonglat[0])) + ',' + eval(90.0 - eval('' + restlonglat[1])) + ');');
contexta.moveTo(eval(180.0 + eval('' + restlonglat[0])), eval(90.0 - eval('' + restlonglat[1])));
}
//alert(eval(180.0 + eval('' + restlonglat[irrr])) + ',' + eval(90.0 - eval('' + restlonglat[1 + irrr])));
consolelog=('context.lineTo(' + eval(180.0 + eval('' + restlonglat[eval(0 + eval('' + irrr))])) + ',' + eval(90.0 - eval('' + restlonglat[eval(1 + eval('' + irrr))])) + ');');
if (consolelog.indexOf('NaN') == -1) {
contexta.lineTo(eval(180.0 + eval('' + restlonglat[eval(0 + eval('' + irrr))])), eval(90.0 - eval('' + restlonglat[eval(1 + eval('' + irrr))])));
}
//if (eval(irrr + 1) >= eval('' + restlonglat.length)) { context.stroke(); }
}
}
contexta.stroke();
}
}


function getthejson(iois) {
if (iois.src.indexOf('.geojson') != -1) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
if (iois.src.indexOf('rivers.geojson') != -1) {
rivers='' + aconto.body.innerHTML;
setTimeout(populaterivers, 500);
iois.src='./population.geojson';
} else if (iois.src.indexOf('population.geojson') != -1) { // && !navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
populations='' + aconto.body.innerHTML;
setTimeout(populatepopulations, 500);
}

}
}
}
}

function getapopulation() {
//for (var ih=0; ih<apopulations.length; ih++) {
// if (apopulations[ih].split(':')[0] == 'Murray') { return ih; }
//}
jguess=Math.floor(Math.random() * apopulations.length);
if (jsofar.indexOf(',' + jguess + ',') != -1) {
while (jsofar.indexOf(',' + jguess + ',') != -1) {
jguess=Math.floor(Math.random() * apopulations.length);
}
}
jsofar+=',' + jguess + ',';
jlastn=apopulations[jguess].split(':')[0];
plotapopulation(jguess);
setTimeout(askapopulation, 9000);
return jguess;
}


function askapopulation() {
var another=false;
var origboth=both;
var midbit='';
var thing='population';
if (!both) { midbit='Append spaces to also answer a question regarding the Rivers Quiz, or R to just do Rivers Quiz.'; } else { thing='river'; }
var retthis=prompt('What is the name of this new red population area plotted on the world map? ' + midbit + ' Enter ? to get given more time looking at (longitude,latitude) = (' + apopulations[jguess].split(':')[1].split(',')[0] + ',' + apopulations[jguess].split(':')[1].split(',')[1] + ')', '');
if (retthis == null) {
both=false;
jgoes++;
another=confirm('Bad luck. Answer was ' + jlastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (retthis.toLowerCase().trim() == 'r') {
both=false;
isokto=true;
getariver();
return '';
} else if (retthis.trim() == '?') {
if (retthis.trim() != retthis && !origboth) { both=true; }
setTimeout(askapopulation, 9000);
return '';
} else if (retthis.trim() == '') {
if (retthis != '' && !origboth) { thing='river'; }
jgoes++;
another=confirm('Bad luck. Answer was ' + jlastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
if (retthis != '' && !origboth) { isokto=true; both=true; getariver(); }
} else if (jlastn.toLowerCase().indexOf(retthis.toLowerCase()) != -1 && jlastn.toLowerCase() == retthis.toLowerCase() && retthis.trim().length >= 1) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='river'; }
jgoes++;
jscore++;
another=confirm('Will pay that. Answer was ' + jlastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (jlastn.toLowerCase().indexOf(retthis.toLowerCase()) == -1) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='river'; }
jgoes++;
another=confirm('Bad luck. Answer was ' + jlastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (jlastn.toLowerCase() == retthis.toLowerCase()) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='river'; }
jgoes++;
jscore++;
another=confirm('Well done! Answer was ' + jlastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else if (retthis.trim().length >= 1) {
if (retthis.trim() != retthis && !origboth) { both=true; thing='river'; }
jgoes++;
another=confirm('Bad luck. Answer was ' + jlastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
} else {
if (retthis.trim() != retthis && !origboth) { both=true; thing='river'; }
jgoes++;
jscore++;
another=confirm('Will pay that. Answer was ' + jlastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new ' + thing + '?');
}
if (both) { contexta.clearRect(0,0,360,180); }
if (both && !origboth) { isitok=true; getariver(); return ''; }
if (another) { if (both) { getariver(); getapopulation(); } else { getapopulation(); } } else { contexta.clearRect(0,0,360,180); }
return '';
}


function plotapopulation(which) {
if (isokto) { contexta.clearRect(0,0,360,180); }
//if (both) { isokto=true; }
jlastn=apopulations[which].split(':')[0];
var rest=apopulations[which].split(':')[1];
var restlonglat=[]; //rest.split(',');
restlonglat=rest.split(',');
if (eval('' + restlonglat.length) >= 2) {
contexta.fillStyle = 'red';
contexta.fillRect(eval(180.0 + eval('' + restlonglat[0])), eval(90.0 - eval('' + restlonglat[1])),1,1);
contexta.fill();
}
}

… in our changed regions.php GeoJson World Coastlines PHP web application in a new window, or you can also try below.


Previous relevant GeoJson World Coastline Rivers Quiz Tutorial is shown below.

GeoJson World Coastline Rivers Quiz Tutorial

GeoJson World Coastline Rivers Quiz Tutorial

It’s time to turn our attention away from GeoJson World Countries, as talked about with yesterday’s GeoJson World Countries Plotted Ports Tutorial, and back to GeoJson World Coastline ideas. Why? We want to add a …


Rivers Quiz

… via the (generously provided) HTTP://geojson.xyz rivers lake centerlines GeoJSON data we download and then uploaded to become rivers.geojson data file. Now we were wondering out of …

  • use the URL to this GeoJSON file as the “src” attribute of an HTML iframe …

    <iframe id=ifrivers onload=getthejson(this); style=display:none; src=./rivers.geojson></iframe>

    … element (and then access the content via the onload event …

    var rivers='', arivers=[], iguess=-1, isofar=' ', jscore=0, jgoes=0, elema=null, contexta=null, rectisleft=0, rectistop=0;

    function getthejson(iois) {
    var aconto = (iois.contentWindow || iois.contentDocument);
    if (aconto != null) {
    if (aconto.document) { aconto = aconto.document; }
    if (aconto.body != null) {
    rivers='' + aconto.body.innerHTML;
    setTimeout(populaterivers, 500);
    }
    }
    }

    … function) would suffice, or if we would end up using …
  • Ajax call

… to access this data, and were a bit surprised the former method was all fine. Of course there are snazzy inbuilt Javascript hierarchical calls you can make to process the data, but we find, with GeoJSON data, in the client realm (where we’re keen to stay with today’s work (though PHP serverside can, of course, be purloined to do all this work, should you have that available)), of Javascript, we just need very basic string functions …

  • split (versus PHP explode)
  • index (versus PHP strpos)
  • substring (versus PHP substr)
  • replace (versus PHP str_replace)
  • push (versus PHP array_push)

… to get by processing …


var rivers='', arivers=[], iguess=-1, isofar=' ', jscore=0, jgoes=0, elema=null, contexta=null, rectisleft=0, rectistop=0;

function populaterivers() {
var found=-1, ifnd=0;
var rbits=rivers.split(']]}}');
var lastn='', hdrbit='', hbits=[];
for (var irr=1; irr<(-1 + rbits.length); irr++) {
hdrbit=rbits[-1 + irr].split('{' + String.fromCharCode(34) + 'type' + String.fromCharCode(34) + ':' + String.fromCharCode(34) + 'Feature')[eval(-1 + rbits[-1 + irr].split('{' + String.fromCharCode(34) + 'type' + String.fromCharCode(34) + ':' + String.fromCharCode(34) + 'Feature').length)] + '';
hbits=hdrbit.split(',' + String.fromCharCode(34) + 'name' + String.fromCharCode(34) + ':' + String.fromCharCode(34));
if (hbits.length > 1) {
if (lastn != hbits[1].split(String.fromCharCode(34))[0]) {
lastn=hbits[1].split(String.fromCharCode(34))[0];
found=-1;
if (arivers.length > 0) {
for (ifnd=0; ifnd<arivers.length; ifnd++) {
if (('' + arivers[ifnd]).indexOf(':') != -1 && found == -1) {
if (('' + arivers[ifnd]).split(':')[0] == lastn) { found=ifnd; }
}
}
}
if (found >= 0) {
//if (lastn == 'Murray') { console.log(hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')); }
arivers[found]+=' ' + hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'');
} else {
//if (lastn == 'Murray') { console.log(lastn + ':' + hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')); }
arivers.push(lastn + ':' + hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,''));
}
} else {
//if (lastn == 'Murray') { console.log(hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'')); }
arivers[-1 + arivers.length]+=' ' + hdrbit.split(':[[')[1].replace(/\]\]\,\[\[/g,' ').replace(/\]\,\[/g,',').replace(/\[/g,'').replace(/\]/g,'');
}
}
}
lastn='';
}

… the (ever so) consistent GeoJSON data!

The progress with GeoJson World Countries helped too. We knew to add another HTML canvas layer as per

  • document.body (now with the new onmousemove=airportplot(event); event logic) lowest level …
  • overlayed by HTML canvas element plotted with world country linework … now including …
  • overlayed by HTML canvas element dedicated to nearest airport plotting …

    <canvas id=myacanvas height='180' width='360' style='background-color:transparent;z-index:55;display:inline-block;position:absolute;top:0px;left:0px;'></canvas>
  • overlayed by HTML img (transparent image) element and its associated image map area elements … and today we add into the mix …
  • HTML div hosting SVG elements overlaying initialized with “land” parts green infilled SVG at a mid range z-index (only as well as when called upon) individual GeoJson entities overlay

… and to, at document.body onload logic …


// ... and extended document.body onload event logic has added, up near its top ...
elema = document.getElementById('myacanvas');
contexta = elema.getContext('2d');

… and supplement with another HTML sub “emoji button” ❓ ( &#10067; ) type element …


<sub style=cursor:pointer; onclick=getariver(); title='River Quiz'>&#10067;</sub>

… allowing for …


function getariver() {
//for (var ih=0; ih<arivers.length; ih++) {
// if (arivers[ih].split(':')[0] == 'Murray') { return ih; }
//}
iguess=Math.floor(Math.random() * arivers.length);
if (isofar.indexOf(',' + iguess + ',') != -1) {
while (isofar.indexOf(',' + iguess + ',') != -1) {
iguess=Math.floor(Math.random() * arivers.length);
}
}
isofar+=',' + iguess + ',';
lastn=arivers[iguess].split(':')[0];
plotariver(iguess);
setTimeout(askariver, 8000);
return iguess;
}

function askariver() {
var another=false;
var retthis=prompt('What is the name of this new blue river plotted on the world map? Enter ? to get given more time looking at (longitude,latitude) = (' + arivers[iguess].split(':')[1].split(',')[0] + ',' + arivers[iguess].split(':')[1].split(',')[1] + ')', '');
if (retthis == null) {
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new river?');
} else if (retthis.trim() == '?') {
setTimeout(askariver, 8000);
return '';
} else if (retthis.trim() == '') {
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new river?');
} else if (lastn.toLowerCase().indexOf(retthis.toLowerCase()) == -1) {
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new river?');
} else if (lastn.toLowerCase() == retthis.toLowerCase()) {
jgoes++;
jscore++;
another=confirm('Well done! Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new river?');
} else if (retthis.trim().length >= 1) {
jgoes++;
another=confirm('Bad luck. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new river?');
} else {
jgoes++;
jscore++;
another=confirm('Will pay that. Answer was ' + lastn + '. Score ' + jscore + '/' + jgoes + '. Another go with a new river?');
}
if (another) { getariver(); } else { contexta.clearRect(0,0,360,180); }
return '';
}

function plotariver(which) {
contexta.clearRect(0,0,360,180);
lastn=arivers[which].split(':')[0];
var rest=arivers[which].split(':')[1];
console.log(rest);
var restlonglat=[]; //rest.split(',');
var therest=rest.split(' ');
//alert(eval(180.0 + eval('' + restlonglat[0])) + ',' + eval(90.0 - eval('' + restlonglat[1])));
for (var jrrr=0; jrrr<therest.length; jrrr++) {
restlonglat=therest[jrrr].split(',');
for (var irrr=2; irrr<restlonglat.length; irrr+=2) {
if (irrr == 2) {
contexta.strokeStyle = '#0000ff';
contexta.lineWidth = 1;
contexta.beginPath();
console.log('context.moveTo(' + eval(180.0 + eval('' + restlonglat[0])) + ',' + eval(90.0 - eval('' + restlonglat[1])) + ');');
contexta.moveTo(eval(180.0 + eval('' + restlonglat[0])), eval(90.0 - eval('' + restlonglat[1])));
}
//alert(eval(180.0 + eval('' + restlonglat[irrr])) + ',' + eval(90.0 - eval('' + restlonglat[1 + irrr])));
console.log('context.lineTo(' + eval(180.0 + eval('' + restlonglat[eval(0 + eval('' + irrr))])) + ',' + eval(90.0 - eval('' + restlonglat[eval(1 + eval('' + irrr))])) + ');');
contexta.lineTo(eval(180.0 + eval('' + restlonglat[eval(0 + eval('' + irrr))])), eval(90.0 - eval('' + restlonglat[eval(1 + eval('' + irrr))])));
//if (eval(irrr + 1) >= eval('' + restlonglat.length)) { context.stroke(); }
}
contexta.stroke();
}
}

… to work the Rivers Quiz. Finally, though, for all good practicalities we also need those zoom logics out of GeoJson World Countries logic, via “emoji button” 🔎 ( &#128270; ) …


<a style=cursor:pointer; title='Zoom In' onclick='event.stopPropagation(); event.preventDefault(); zoomin();'>&#128270;</a>

… calling on meta name=viewport tag for mobile …


<meta id='myviewport' name='viewport' content='width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes' >

… as well as the zooming Javascript …


var jzoom=1.0, izoom=location.search.split('zoom=')[1] ? eval(decodeURIComponent(location.search.split('zoom=')[1].split('&')[0])) : 1.0;

function zoomin() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
jzoom*=2;
document.getElementById('myviewport').setAttribute('content', 'width=device-width, initial-scale=' + eval(jzoom * izoom) + ', minimum-scale=0.1, maximum-scale=8, user-scalable=yes');
window.scrollTo(0,0); //izoom*=2;
} else {
//if (1 == 1) {
// alert('Please use your web browser View Menu options Zoom In or Zoom Out');
//} else {
document.body.style.zoom=('' + eval(izoom * 200.0) + '%');
izoom*=2;
//location.href=document.URL.split('?')[0].split('#')[0] + '?zoom=' + encodeURIComponent('' + eval(2 * izoom));
//}
}
}

So feel free to try the new Rivers Quiz in our changed regions.php GeoJson World Coastlines PHP web application in a new window, or you can also try below.


Previous relevant GeoJson World Countries Plotted Ports Tutorial is shown below.

GeoJson World Countries Plotted Ports Tutorial

GeoJson World Countries Plotted Ports Tutorial

There are a few interesting aspects to today’s extension of functionality onto yesterday’s GeoJson World Countries Plotted Airports Tutorial‘s GeoJson World Countries web application …

  • where to modularise … we think “data collection” commonality is a good reason, and so we make these changes to intair.php
  • making an (“animated emoji”) button dual purpose on top of originally being a single purpose button …

    <sub title='Show Nearby Airports' onclick='doair=how(true,this); twothousand*=2; this.title=this.title.substring(0,4) + String.fromCharCode(105) + String.fromCharCode(110) + String.fromCharCode(103) + this.title.replace(this.title.split(String.fromCharCode(32))[0] + String.fromCharCode(32), String.fromCharCode(32));' data-type=9992 style=cursor:pointer; id=portsub>&#9992;</sub>

    … working with the intairsuffix global variable that could add a new GET argument where both the “port” label in &port=[value] and that [value] can affect behaviour from the intair.php PHP helper tool above …

    var intairsuffix='', zhra=null, zhrb=null, kklat=0, kklong=0, doair=false, vsll=[-999.0], answered=true;

    function how(atr, isub) {
    var curgd=isub.getAttribute('data-type');
    if (('' + curgd) == '9992') { // airport
    if (intairsuffix != '') {
    intairsuffix='&port=air';
    isub.title='Showing Nearby Airports and Ports';
    document.getElementById('title').value='Nearby Timezone Places and Airports and Ports';
    }
    } else if (('' + curgd) == '128674') { // port
    if (intairsuffix == '') {
    if (doair) {
    intairsuffix='&port=air';
    isub.title='Showing Nearby Airports and Ports';
    document.getElementById('title').value='Nearby Timezone Places and Airports and Ports';
    } else {
    intairsuffix='&port=y';
    isub.title='Showing Nearby Ports';
    document.getElementById('title').value='Nearby Timezone Places and Ports';
    }
    }
    }
    return true;
    }

    function feedhow() {
    var isub=document.getElementById('portsub');
    var curgd=isub.getAttribute('data-type');
    if (('' + curgd) == '9992') { // airport
    isub.innerHTML='&#128674;';
    isub.setAttribute('data-type', '128674');
    } else if (('' + curgd) == '128674') { // port
    isub.innerHTML='&#9992;';
    isub.setAttribute('data-type', '9992');
    }
    }

  • Ajax asynchronous usage for second half of a synchronous previous usage

    var intairsuffix='', zhra=null, zhrb=null, kklat=0, kklong=0, doair=false, vsll=[-999.0], answered=true;

    function stateChangedb() {
    if (zhrb.readyState == 4) {
    if (zhrb.status == 200) {
    var rectis=document.body.getBoundingClientRect();
    var topllong=-180.0;
    var topllat=90.0;
    var onepixelequals=izoom;
    var bts=zhrb.response.split('.src + ' + String.fromCharCode(39));
    if (eval('' + bts.length) > 1) {
    for (var ijh=1; ijh<bts.length; ijh++) {
    var vs=eval(eval(eval(eval(-topllong + eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[1])) * onepixelequals) + eval(0 * eval(rectis.left))) +
    eval(eval(eval(topllat - eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[0])) * onepixelequals) + eval(0 * eval(rectis.top))));
    if (!inarray(vs,vsll)) {
    vsll.push(vs);
    drawaac(
    eval(eval(eval(-topllong + eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[1])) * onepixelequals) + eval(0 * eval(rectis.left))),
    eval(eval(eval(topllat - eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[0])) * onepixelequals) + eval(0 * eval(rectis.top)))
    );
    }
    }
    }
    }
    }
    }


    function stateChangeda() {
    if (zhra.readyState == 4) {
    if (zhra.status == 200) {
    var rectis=document.body.getBoundingClientRect();
    var topllong=-180.0;
    var topllat=90.0;
    var onepixelequals=izoom;
    var bts=zhra.response.split('.src + ' + String.fromCharCode(39));
    if (eval('' + bts.length) > 1) {
    for (var ijh=1; ijh<bts.length; ijh++) {
    var vs=eval(eval(eval(eval(-topllong + eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[1])) * onepixelequals) + eval(0 * eval(rectis.left))) +
    eval(eval(eval(topllat - eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[0])) * onepixelequals) + eval(0 * eval(rectis.top))));
    if (!inarray(vs,vsll)) {
    vsll.push(vs);
    drawaac(
    eval(eval(eval(-topllong + eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[1])) * onepixelequals) + eval(0 * eval(rectis.left))),
    eval(eval(eval(topllat - eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[0])) * onepixelequals) + eval(0 * eval(rectis.top)))
    );
    }
    }
    }
    if (intairsuffix.indexOf('&port=air') != -1) {
    zhrb = new XMLHttpRequest();
    zhrb.onreadystatechange=stateChangedb;
    zhrb.open('get', '/HTMLCSS/intair.php?num=6&lat=' + kklat + '&long=' + kklong + '&port=y', true);
    zhrb.send(null);
    }

    answered=true;
    }
    }
    }

    function naira(klat, klong) {
    if (answered && doair) {
    answered=false;
    zhra = new XMLHttpRequest();
    zhra.onreadystatechange=stateChangeda;
    console.log('/HTMLCSS/intair.php?num=6&lat=' + klat + '&long=' + klong + intairsuffix);
    if (intairsuffix.indexOf('&port=air') != -1) {
    kklat=klat;
    kklong=klong;
    zhra.open('get', '/HTMLCSS/intair.php?num=6&lat=' + klat + '&long=' + klong, true);
    } else {

    zhra.open('get', '/HTMLCSS/intair.php?num=6&lat=' + klat + '&long=' + klong + intairsuffix, true);
    }
    zhra.send(null);
    }
    }

    … keeps a fastish synchronous call (that we enforce via that answered global variable) but truely invokes an asynchronous arrangement extracting Nearby Ports data to plot, as applicable

in adding

So far, with yesterday’s GeoJson World Countries Google Directions Trip Tutorial‘s GeoJson World Countries points of interest include …

… in our changed countries.php web application you can also try below.


Previous relevant GeoJson World Countries Plotted Airports Tutorial is shown below.

GeoJson World Countries Plotted Airports Tutorial

GeoJson World Countries Plotted Airports Tutorial

Introducing the Map Chart recognition of nearby Airports with yesterday’s GeoJson World Countries Nearest Airports Tutorial‘s progress on our latest GeoJson World Countries PHP web application, it set us to seeing …

  • the combination of Google Directions‘s talents allowing you to reposition on the fly … and …
  • the onmousemove event, at least for our non-mobile users

… could mean that if we pre-plot airports on the world map, given that the user has clicked the ✈ ( &#9992; ) “Show an Interest in Airports” emoji button, as a non-mobile user hovers over the world map, this pre-plotting might help trip planners with their travel options, should air travel be part of their interest, in the same way it is an option up at Google Directions in our changed countries.php web application you can also try below. The overlay scenario now reads

  • document.body (now with the new onmousemove=airportplot(event); event logic) lowest level …
  • overlayed by HTML canvas element plotted with world country linework … now including …
  • overlayed by HTML canvas element dedicated to nearest airport plotting …

    <canvas id=myacanvas height='180' width='360' style='background-color:transparent;z-index:55;display:inline-block;position:absolute;top:0px;left:0px;'></canvas>
  • overlayed by HTML img (transparent image) element and its associated image map area elements … and today we add into the mix …
  • HTML div hosting SVG elements overlaying initialized with “land” parts green infilled SVG at a mid range z-index (only as well as when called upon) individual GeoJson entities overlay

… worked by new (sometimes Ajax) Javascript code …


var zhra=null, elema=null, contexta=null, answered=true, vsll=[-999.0], doair=false; // clicking ✈ sets doair=true;

function drawaac(centerX, centerY) {
contexta.beginPath();
contexta.globalAlpha = 0.9;
if (1 == 1) {
contexta.fillStyle = 'black';
contexta.fillRect(centerX / izoom, centerY / izoom,1,1);
contexta.fill();
} else {
contexta.arc(centerX / izoom, centerY / izoom, 1, 0, 2 * Math.PI, false);
contexta.fillStyle = 'black';
contexta.fill();
contexta.lineWidth = 5;
contexta.lineWidth = 0.00001;
contexta.strokeStyle = '#003300';
contexta.stroke();
}
return true;
}

function inarray(needle, haystack) { // thanks to https://stackoverflow.com/questions/784012/javascript-equivalent-of-phps-in-array
var length = haystack.length;
for (var i = 0; i < length; i++) {
if (haystack[i] == needle) return true;
}
return false;
}

function stateChangeda() {
if (zhra.readyState == 4) {
if (zhra.status == 200) {
var rectis=document.body.getBoundingClientRect();
var topllong=-180.0;
var topllat=90.0;
var onepixelequals=izoom;
var bts=zhra.response.split('.src + ' + String.fromCharCode(39));
if (eval('' + bts.length) > 1) {
for (var ijh=1; ijh<bts.length; ijh++) {
var vs=eval(eval(eval(eval(-topllong + eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[1])) * onepixelequals) + eval(0 * eval(rectis.left))) +
eval(eval(eval(topllat - eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[0])) * onepixelequals) + eval(0 * eval(rectis.top))));
if (!inarray(vs,vsll)) {
vsll.push(vs);
drawaac(
eval(eval(eval(-topllong + eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[1])) * onepixelequals) + eval(0 * eval(rectis.left))),
eval(eval(eval(topllat - eval(bts[ijh].split(String.fromCharCode(39))[0].split('[')[1].split(',')[0])) * onepixelequals) + eval(0 * eval(rectis.top)))
);
}
}
}
answered=true;
}
}
}

function naira(klat, klong) {
if (answered && doair) {
answered=false;
zhra = new XMLHttpRequest();
zhra.onreadystatechange=stateChangeda;
zhra.open('get', '/HTMLCSS/intair.php?num=6&lat=' + klat + '&long=' + klong, true);
zhra.send(null);
}
}

function airportplot(e) {
if (answered) {
var rectis=null; //document.body.getBoundingClientRect();
var blat=0, blong=0;
var topllong=-180.0;
var topllat=90.0;
onepixelequals=eval(0.0 + eval(1.0 * izoom));
e = e || window.event;
e.preventDefault();
if (e.touches) {
if (e.touches[0].pageX) {
naira(eval(-rectisleft + e.touches[0].pageX), eval(-rectistop + e.touches[0].pageY)); //if (drawac(eval(-rectisleft + e.touches[0].pageX), eval(-rectistop + e.touches[0].pageY))) e = e; }
} else {
rectis=document.body.getBoundingClientRect();
naira(eval(-rectis.left + e.touches[0].clientX), eval(-rectis.top + e.touches[0].clientY)); //if (drawac(eval(-rectis.left + e.touches[0].clientX), eval(-rectis.top + e.touches[0].clientY))) { e = e; }
}
} else if (e.pageX || e.pageY) {
blat=eval(eval(eval(topllat * onepixelequals - eval(-rectistop + e.pageY) * 1)) / onepixelequals);
blong=eval(eval(eval(topllong * onepixelequals + eval(-rectisleft + e.pageX) * 1)) / onepixelequals);
if ((blat >= -90.0 && blat <= 90.0) && (blong >= -180.0 && blong <= 180.0)) {
naira(blat, blong); //if (drawac(eval(-rectisleft + e.pageX), eval(-rectistop + e.pageY))) { e = e; }
}
} else {
rectis=document.body.getBoundingClientRect();
naira(eval(-rectis.left + e.clientX), eval(-rectis.top + e.clientY)); //if (drawac(eval(-rectis.left + e.clientX), eval(-rectis.top + e.clientY))) { e = e; }
}
}
}

// ... and extended document.body onload event logic has added, up near its top ...
elema = document.getElementById('myacanvas');
contexta = elema.getContext('2d');


Previous relevant GeoJson World Countries Nearest Airports Tutorial is shown below.

GeoJson World Countries Nearest Airports Tutorial

GeoJson World Countries Nearest Airports Tutorial

So far, with yesterday’s GeoJson World Countries Google Directions Trip Tutorial‘s GeoJson World Countries points of interest include …

… being as we’re into trip planning now!


var airportstuff='', doair=false, zhr=null;

function stateChanged() {
if (zhr.readyState == 4) {
if (zhr.status == 200) {
var bts=zhr.response.split('.src + ' + String.fromCharCode(39));
if (eval('' + bts.length) > 1) {
for (var ijh=1; ijh function windowopen(p1, p2, p3) {
if (p1.length > 800) {
document.getElementById('iddata').value=(p1.split('&data=')[1].split('&')[0].split('#')[0]).replace(/\&20\;/g,' ');
document.getElementById('smapif').click();
return null;
}
return window.open(p1, p2, p3);
}

function apm(mu) {
if (airportstuff != '' && doair) {
return (mu + airportstuff).replace('&', encodeURIComponent(' and Airports') + '&');
}
return mu;
}

function nair(klat, klong) {
airportstuff='';
zhr = new XMLHttpRequest();
zhr.onreadystatechange=stateChanged;
zhr.open('get', '/HTMLCSS/intair.php?num=4&lat=' + klat + '&long=' + klong, true);
zhr.send(null);
}


function alats(inlat) {
if (inlat == 0 && lastlats.length == 0) { inlat=inlat; } else { lastlats.push(inlat); }
return inlat;
}

function alongs(inlong) {
if (inlong == 0 && lastlongs.length == 0) { inlong=inlong; } else { lastlongs.push(inlong); }
setTimeout(prenair, 200); //nair(thislat, inlong);
return inlong;
}

function prenair() {
nair(thislat, thislong);
}

… featuring Ajax Javascript code.

Try this out with our changed countries.php web application you can also try below.


Previous relevant GeoJson World Countries Google Directions Trip Tutorial is shown below.

GeoJson World Countries Google Directions Trip Tutorial

GeoJson World Countries Google Directions Trip Tutorial

Adding to the “zoom” progress of yesterday’s GeoJson World Countries Zoom Tutorial, today, we wanted to …

  • add interfacing functionality to the excellent Google Directions part of Google Maps, perhaps to help with Trip planning, or even just to associate a Placename with a latitude and longitude as clicked by the user, via the very simple URL arrangement …
    https://www.google.com/maps/dir/[decimalLatitudeDegrees]/[decimalLongitudeDegrees]
    … helped out by new Javascript functions …

    var lastlats=[], lastlongs=[], lastlat=-99.0, lastlong=-99.0, thislat=0.0, thislong=0.0;

    function preface(inblurb) {
    var extras='';
    var outblurb=inblurb;
    if (Math.abs(eval('' + lastlat)) > 0.0 || Math.abs(eval('' + lastlong)) > 0.0) {
    if (Math.abs(eval('' + lastlat)) <= 90.0 && Math.abs(eval('' + lastlong)) <= 180.0) { extras=' Add G for Google Directions between (' + lastlat + ',' + lastlong + ') to (' + thislat + ',' + thislong + ') and spaces (also more trip legs) to hashtag navigate to Google Charts later. '; } } return extras + outblurb; }
    function alats(inlat) {
    if (inlat == 0 && lastlats.length == 0) { inlat=inlat; } else { lastlats.push(inlat); }
    return inlat;
    }

    function alongs(inlong) {
    if (inlong == 0 && lastlongs.length == 0) { inlong=inlong; } else { lastlongs.push(inlong); }
    return inlong;
    }

    … and …
  • add some hashtag navigation (fairly self explanatory emoji button ) ideas now that our GeoJson world map can be zoomed in on

… in our changed countries.php web application you can also try below.


Previous relevant GeoJson World Countries Zoom Tutorial is shown below.

GeoJson World Countries Zoom Tutorial

GeoJson World Countries Zoom Tutorial

Onto yesterday’s GeoJson World Countries TimeZone Times Tutorial GeoJson World Countries web application’s capabilities we want to add zooming, that doesn’t rely on web browser functionality (which continues to work). With that in mind we create a new emoji ( &#128270; ) 🔎 link, with this onclick event code …


var jzoom=1.0, izoom=location.search.split('zoom=')[1] ? eval(decodeURIComponent(location.search.split('zoom=')[1].split('&')[0])) : 1.0;

function zoomin() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
jzoom*=2;
document.getElementById('myviewport').setAttribute('content', 'width=device-width, initial-scale=' + eval(jzoom * izoom) + ', minimum-scale=0.1, maximum-scale=8, user-scalable=yes');
window.scrollTo(0,0);
} else {
document.body.style.zoom=('' + eval(izoom * 200.0) + '%');
izoom*=2;
}
}

… to multiply the webpage zoom factor in a programmatical way. To acheive this, we have a two way approach (as you might have surmised from above) …

  • for mobile, the logic is easier by introducing a new meta name=viewport …

    <meta id="myviewport" name="viewport" content="width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes" >

    … tag … while …
  • for non-mobile we needed to realize that event.pageX and event.pageY co-ordinates grow in proportion to the zoom factor, and that better latitude and longitude determining lines of code would go

    function canvasclick(e) {
    var rectis=document.body.getBoundingClientRect();
    var topllong=-180.0;
    var topllat=90.0;
    onepixelequals=eval(0.0 + eval(1.0 * izoom));
    //document.title='canvasclick';
    e = e || window.event;
    e.preventDefault();
    if (e.touches) {
    if (e.touches[0].pageX) {
    //lastl='Longitude,Latitude coordinates are ' + eval(topllong + eval(-rectis.left + e.touches[0].pageX) * onepixelequals) + ',' + eval(topllat - eval(-rectis.top + e.touches[0].pageY) * onepixelequals);
    if (drawc(eval(-rectisleft + e.touches[0].pageX), eval(-rectistop + e.touches[0].pageY))) {
    thislat=eval(topllat - eval(-rectistop + e.touches[0].pageY) * onepixelequals);
    thislong=eval(topllong + eval(-rectisleft + e.touches[0].pageX) * onepixelequals);
    //console.log('rectistop=' + rectistop + ' and rectisleft=' + rectisleft + ' and rectisy=' + rectisy + ' and thislat=' + thislat);
    document.getElementById('nearestif').src='/PHP/tz_places.php?place=&latitude=' + encodeURIComponent('' + eval(topllat - eval(-rectistop + e.touches[0].pageY) * onepixelequals)) + '&longitude=' + encodeURIComponent('' + eval(topllong + eval(-rectisleft + e.touches[0].pageX) * onepixelequals)) + '&ntztontz=y';
    }
    } else {

    //lastl='Longitude,Latitude coordinates are ' + eval(topllong + eval(-rectis.left + e.touches[0].clientX) * onepixelequals) + ',' + eval(topllat - eval(-rectis.top + e.touches[0].clientY) * onepixelequals);
    if (drawc(eval(-rectis.left + e.touches[0].clientX), eval(-rectis.top + e.touches[0].clientY))) {
    thislat=eval(topllat - eval(-rectis.top + e.touches[0].clientY) * onepixelequals);
    thislong=eval(topllong + eval(-rectis.left + e.touches[0].clientX) * onepixelequals);
    //console.log('rectis.top=' + rectis.top + ' and rectis.left=' + rectis.left + ' and rectis.y=' + rectis.y + ' anD thislat=' + thislat);
    document.getElementById('nearestif').src='/PHP/tz_places.php?place=&latitude=' + encodeURIComponent('' + eval(topllat - eval(-rectis.top + e.touches[0].clientY) * onepixelequals)) + '&longitude=' + encodeURIComponent('' + eval(topllong + eval(-rectis.left + e.touches[0].clientX) * onepixelequals)) + '&ntztontz=y';
    }
    }
    } else if (e.pageX || e.pageY) {
    //lastl='Longitude,Latitude coordinates are ' + eval(topllong + e.clientX * onepixelequals) + ',' + eval(topllat - e.clientY * onepixelequals);
    //alert('02: ' + e.screenX + ' ' + e.pageX + ' ' + e.screenY + ' ' + e.pageY + ' ' + thislong + ' ' + thislat);
    if (drawc(eval(-rectisleft + e.pageX), eval(-rectistop + e.pageY))) {
    //thislat=eval(topllat - eval(-rectistop + e.pageY) * onepixelequals);
    //thislong=eval(topllong + eval(-rectisleft + e.pageX) * onepixelequals);
    thislat=eval(eval(eval(topllat * onepixelequals - eval(-rectistop + e.pageY) * 1)) / onepixelequals);
    thislong=eval(eval(eval(topllong * onepixelequals + eval(-rectisleft + e.pageX) * 1)) / onepixelequals);

    //alert('22: ' + e.screenX + ' ' + e.pageX + ' ' + e.screenY + ' ' + e.pageY + ' ' + thislong + ' ' + thislat);
    //console.log('rectistop=' + rectistop + ' and rectisleft=' + rectisleft + ' and rectisy=' + rectisy + ' aNd thislat=' + thislat + ' and e.pageY=' + e.pageY + ' and new plus idea=' + eval(topllat - eval(rectistop + e.pageY) * onepixelequals));
    //document.getElementById('nearestif').src='/PHP/tz_places.php?place=&latitude=' + encodeURIComponent('' + eval(topllat - eval(-rectistop + e.pageY) * onepixelequals)) + '&longitude=' + encodeURIComponent('' + eval(topllong + eval(-rectisleft + e.pageX) * onepixelequals)) + '&ntztontz=y';
    document.getElementById('nearestif').src='/PHP/tz_places.php?place=&latitude=' + encodeURIComponent('' + thislat) + '&longitude=' + encodeURIComponent('' + thislong) + '&ntztontz=y';
    }
    } else {
    //lastl='Longitude,Latitude coordinates are ' + eval(topllong + eval(-rectis.left + e.pageX) * onepixelequals) + ',' + eval(topllat - eval(-rectis.top + e.pageY) * onepixelequals);
    if (drawc(eval(-rectis.left + e.clientX), eval(-rectis.top + e.clientY))) {
    thislat=eval(topllat - eval(-rectis.top + e.clientY) * onepixelequals);
    thislong=eval(topllong + eval(-rectis.left + e.clientX) * onepixelequals);
    //console.log('rectis.top=' + rectis.top + ' and rectis.left=' + rectis.left + ' and rectis.y=' + rectis.y + ' And thislat=' + thislat);
    document.getElementById('nearestif').src='/PHP/tz_places.php?place=&latitude=' + encodeURIComponent('' + eval(topllat - eval(-rectis.top + e.clientY) * onepixelequals)) + '&longitude=' + encodeURIComponent('' + eval(topllong + eval(-rectis.left + e.clientX) * onepixelequals)) + '&ntztontz=y';
    }
    }
    }

… in our changed countries.php web application you can also try below.


Previous relevant GeoJson World Countries TimeZone Times Tutorial is shown below.

GeoJson World Countries TimeZone Times Tutorial

GeoJson World Countries TimeZone Times Tutorial

Some readers might be aware of our “theory regarding adverbs” and “web applications” on the net …

  • the most catered for adverb relates to the “where of life” … and the second banana is …
  • the “when of life”

… and, further to yesterday’s GeoJson World Countries SVG Overlay Safari Error Tutorial‘s emphasis on the “where of life”, today we add in a bit of the “when of life”, something right down the line of the remit of TimeZone talents.

Seriously though, a lot of us dream of the rest of the world on a world map, and wonder what time it is in other parts of the world. Phone call to relatives? A reminder SMS call? Email a game collaboration? It could all be part of life’s rich tapestry!

The expresion of this, for us, today, improving the communications with our current GeoJsom World Countries web application, take the form of emoji clocks from the 12 hour clock example forms such as …

  • 1 o’clock is &#128336; 🕐
  • 2 o’clock is &#128337; 🕑
  • 12 o’clock is &#128347; 🕛
  • 2:30 is &#128349; 🕝
  • 11:30 is &#128358; 🕦
  • 12:30 is &#128359; 🕧

… to show in “prompt” and “confirm” popup windows, as well as Map Chart maps … via new Javascript functions …


function clockit(hoursoffgmt) {
// 1 o'clock is 🕐
// 2 o'clock is 🕑
// 12 o'clock is 🕛
// 2:30 is 🕝
// 11:30 is 🕦
// 12:30 is 🕧
var along='Saturday,Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday';
var gmtdatetimeis='' + new Date().toUTCString();
var daybit='';
var ampm=' am';
if (gmtdatetimeis.indexOf('day') != -1) {
ampm+=', ' + gmtdatetimeis.split('day')[0].split(' ')[eval(-1 + gmtdatetimeis.split('day')[0].split(' ').length)] + 'day';
} else if (gmtdatetimeis.indexOf(',') != -1) {
ampm+=', ' + (gmtdatetimeis.split(',')[0].split(' ')[eval(-1 + gmtdatetimeis.split(',')[0].split(' ').length)] + '').replace(/^Sat$/g,'Saturday').replace(/^Sun$/g,'Sunday').replace(/^Mon$/g,'Monday').replace(/^Tue$/g,'Tuesday').replace(/^Wed$/g,'Wednesday').replace(/^Thu$/g,'Thursday').replace(/^Fri$/g,'Friday');
}
if (ampm.length > 3) { daybit=ampm.substring(5); }
var minis=eval('' + gmtdatetimeis.split(':')[1]);
var hris=eval(('' + gmtdatetimeis.split(':')[0]).split(' ')[eval(-1 + ('' + gmtdatetimeis.split(':')[0]).split(' ').length)]);
if (('' + hoursoffgmt).indexOf('-') != -1 && eval(eval('' + hoursoffgmt.replace('+','')) + hris) < 0.0) {
ampm=ampm.replace('am', 'pm');
if (daybit != '') { ampm=ampm.replace(daybit, along.split(',' + daybit)[0].split(',')[eval(-1 + along.split(',' + daybit)[0].split(',').length)]); }
} else if (('' + hoursoffgmt).indexOf('-') == -1 && eval(eval('' + hoursoffgmt.replace('+','')) + hris) >= 24) {
if (daybit != '') { ampm=ampm.replace(daybit, along.split(daybit + ',')[1].split(',')[0]); }
} else if (('' + hoursoffgmt).indexOf('-') == -1 && eval(eval('' + hoursoffgmt.replace('+','')) + hris) >= 12) {
ampm=ampm.replace('am', 'pm');
}
hris+=eval(eval(24 + eval('' + hoursoffgmt.replace('+','').split('.')[0])) % 24);
if (('' + hoursoffgmt.replace('+','')).indexOf('.5') != -1) {
if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1 && minis >= 30) {
minis-=30;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1) {
hris--;
if (hris < 24) { hris=23; ampm=ampm.replace('am', 'pm'); if (daybit != '') { ampm=ampm.replace(daybit, along.split(',' + daybit)[0].split(',')[eval(-1 + along.split(',' + daybit)[0].split(',').length)]); } }
minis+=30;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') == -1 && minis < 30) {
minis+=30;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1) {
hris++;
if (hris > 24) { hris=24; ampm=ampm.replace('pm', 'am'); if (daybit != '') { ampm=ampm.replace(daybit, along.split(daybit + ',')[1].split(',')[0]); } }
minis-=30;
}
} else if (('' + hoursoffgmt.replace('+','')).indexOf('.25') != -1) {
if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1 && minis >= 15) {
minis-=15;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1) {
hris--;
if (hris < 24) { hris=23; ampm=ampm.replace('am', 'pm'); if (daybit != '') { ampm=ampm.replace(daybit, along.split(',' + daybit)[0].split(',')[eval(-1 + along.split(',' + daybit)[0].split(',').length)]); } }
minis+=15;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') == -1 && minis < 45) {
minis+=15;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1) {
hris++;
if (hris > 24) { hris=24; ampm=ampm.replace('pm', 'am'); if (daybit != '') { ampm=ampm.replace(daybit, along.split(daybit + ',')[1].split(',')[0]); } }
minis-=15;
}
} else if (('' + hoursoffgmt.replace('+','')).indexOf('.75') != -1) {
if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1 && minis >= 45) {
minis-=45;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1) {
hris--;
if (hris < 24) { hris=23; ampm=ampm.replace('am', 'pm'); if (daybit != '') { ampm=ampm.replace(daybit, along.split(',' + daybit)[0].split(',')[eval(-1 + along.split(',' + daybit)[0].split(',').length)]); } }
minis+=45;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') == -1 && minis < 15) {
minis+=45;
} else if (('' + hoursoffgmt.replace('+','')).indexOf('-') != -1) {
hris++;
if (hris > 24) { hris=24; ampm=ampm.replace('pm', 'am'); if (daybit != '') { ampm=ampm.replace(daybit, along.split(daybit + ',')[1].split(',')[0]); } }
minis-=45;
}
}
//alert('' + hoursoffgmt + ' ' + hris + ' ' + minis + ' ' + gmtdatetimeis);


if (minis > 45 && eval(hris % 12) == 0) {
return ' ' + String.fromCodePoint(128336) + ampm;
} else if (eval(hris % 12) == 0 && minis <= 15) {
return ' ' + String.fromCodePoint(128347) + ampm;
} else if (eval(hris % 12) == 0) {
return ' ' + String.fromCodePoint(128359) + ampm;
} else if (minis >= 45) {
return ' ' + String.fromCodePoint(eval(eval(hris % 12) + 128336)) + ampm;
} else if (minis <= 15) {
return ' ' + String.fromCodePoint(eval(eval(hris % 12) + 128335)) + ampm;
} else {
return ' ' + String.fromCodePoint(eval(eval(hris % 12) + 128347)) + ampm;
}
return '';
}

function emfilter(inih) {
var bcxs=inih.split(' &#');
var bitis='', ib=0;
var outih=inih;
for (ib=1; ib<bcxs.length; ib++) {
bitis=' &#' + bcxs[ib].split(' ')[0];
outih=outih.replace(bitis, ' ' + eval('String.fromCodePoint(' + bitis.substring(3).replace(/\;\&\#/g,',').replace(/\;/g,'') + ')'));
}
bcxs=outih.split('(');
for (ib=1; ib<bcxs.length; ib++) {
if (bcxs[ib].split(')')[0].indexOf(',') == -1 && bcxs[ib].split(')')[0].indexOf(' ') == -1 && (bcxs[ib].substring(0,1) == '-' || bcxs[ib].substring(0,1) == '+' || (bcxs[ib].substring(0,1) >= '0' && bcxs[ib].substring(0,1) <= '9'))) {
outih=outih.replace('(' + bcxs[ib].split(')')[0] + ')', '(' + bcxs[ib].split(')')[0] + clockit(bcxs[ib].split(')')[0]) + ')');
}
}
return outih;
}

Also, in these same places we add in Time Place country ISO-2 character code based emoji flags, adding to information and colour pizazz in the informational parts to the workings of our changed countries.php web application you can also try below.


Previous relevant GeoJson World Countries SVG Overlay Safari Error Tutorial is shown below.

GeoJson World Countries SVG Overlay Safari Error Tutorial

GeoJson World Countries SVG Overlay Safari Error Tutorial

Mostly on smaller devices (such as an iPhone), but elsewhere as well, but less drastically, this morning, using our current Display GeoJson Countries web application we would get the Safari web browser error …

A problem repeatedly occurred with https://www.rjmprogramming.com.au/HTMLCSS/countries.php

… with web application work up to yesterday’s GeoJson World Countries SVG Overlay Colour Infill Tutorial.

On discovering our first solution theory of turning yesterday’s mapsvg.js external Javascript work into an async piece of work made no difference to this situation, we surmised that the huge amount of content held in the Javascript (ie. client side) global variable appendtoinnerHTML was causing memory issues. We couldn’t shift much to do with the overall amount of “data” needing to be handled, in order to implement country SVG colour infilling, but we could shift the data from being …

  • client side (external) Javascript held … to, instead, (have that data) be (determined on the) …
  • server side PHP filling in the contents of our (relevant) HTML div id=svgd ahead of the document.body onload event timing …
    <?php

    $icnt=0;

    function apptohtmstuff($coordsare, $origc) {
    global $icnt;
    $minl=-1;
    $mint=-1;
    $maxl=-1;
    $maxt=-1;
    $zysare=explode(',', $coordsare);
    $svgcis='';
    for ($ij=0; $ij<sizeof($zysare); $ij+=2) {
    if ($minl < 0) {
    $minl=$zysare[$ij];
    $maxl=$zysare[$ij];
    $mint=$zysare[1 + $ij];
    $maxt=$zysare[1 + $ij];
    } else {
    if ($zysare[$ij] < $minl) { $minl=$zysare[$ij]; }
    if ($zysare[$ij] > $maxl) { $maxl=$zysare[$ij]; }
    if ($zysare[1 + $ij] < $mint) { $mint=$zysare[1 + $ij]; }
    if ($zysare[1 + $ij] > $maxt) { $maxt=$zysare[1 + $ij]; }
    }
    }

    for ($ij=0; $ij<sizeof($zysare); $ij+=2) {
    if ($svgcis == '') {
    $svgcis='' . ($zysare[$ij] - $minl) . ',' . ($zysare[1 + $ij] - $mint);
    } else {
    $svgcis.=' ' . ($zysare[$ij] - $minl) . ',' . ($zysare[1 + $ij] - $mint);
    }
    }

    $icnt++;
    return '<div title="' . $coordsare . '" id="dsa' . (-1 + $icnt) . '" style="position:absolute;left:' . $minl . 'px;top:' . $mint . 'px;width:' . ($maxl - $minl) . 'px;height:' . ($maxt - $mint) . ';display:BLOCK;z-index:24;"><svg height="100%" width="100%"><polygon points="' . $svgcis . '" style="fill:lime;stroke:purple;stroke-width:1"></polygon></svg></div>';
    }

    ?>
    … meaning the web application’s underlying HTML size increased at the expense of no need for external Javascript involvement any more

… in our changed countries.php web application you can also try below.

We’re not exactly sure why, but …

  • this improved web application stability …

    …everywhere … and an idea we’d ditched yesterday of …
  • idea to pre-colour “land” parts of the world GeoJson map green (ahead of the document.body onload event) also came good (after causing problems yesterday)

… meaning now, “overlay” wise, we could say

  • document.body lowest level …
  • overlayed by HTML canvas element plotted with world country linework …
  • overlayed by HTML img (transparent image) element and its associated image map area elements … and today we add into the mix …
  • HTML div hosting SVG elements overlaying initialized with “land” parts green infilled SVG at a mid range z-index (only as well as when called upon) individual GeoJson entities overlay

… and we (reckon we’ve) improved the colour coding user experience at the same time.

We noticed that tweaks in the changed …


var lastflagged='', appendtoinnerHTML='', waitplease=false; // used to make sure "area" element onclick code precedes any document.body onmousedown or ontouchdown code

function checkdsa(ath) {
waitplease=true;
var wasih='';
var athcoords=('' + ath.coords); //.substring(0, Math.floor(eval(0.1 * ('' + ath.coords).length)));
if (document.getElementById('svgd').innerHTML.indexOf(('' + athcoords)) != -1) {
wasih='<div title=' + String.fromCharCode(34) + '' + ath.coords + document.getElementById('svgd').innerHTML.split(ath.coords)[1].split('<div ')[0];
if (lastflagged == '') {
if (wasih.indexOf(' id=' + String.fromCharCode(34)) != -1) { lastflagged=wasih.split(' id=' + String.fromCharCode(34))[1].split(String.fromCharCode(34))[0]; } else { lastflagged=''; }
} else {
document.getElementById(lastflagged).innerHTML=document.getElementById(lastflagged).innerHTML.replace(/rgba\(255\,87\,51\,0.5\)/g, 'rgba(200,200,200,0.3)');
if (wasih.indexOf(' id=' + String.fromCharCode(34)) != -1) { lastflagged=wasih.split(' id=' + String.fromCharCode(34))[1].split(String.fromCharCode(34))[0]; } else { lastflagged=''; }
}
if (lastflagged != '') {
document.getElementById(lastflagged).innerHTML=document.getElementById(lastflagged).innerHTML.replace('z-index:24;', 'z-index:123;').replace('lime;', 'rgba(255,87,51,0.5);');
document.getElementById(lastflagged).title=ath.title;
} else {
document.getElementById('svgd').innerHTML=document.getElementById('svgd').innerHTML.replace(wasih, '<div title=' + String.fromCharCode(34) + '' + ath.title + wasih.split(ath.coords)[1].split('<div ')[0].replace('none;', 'block;z-index:123;').replace('lime;', 'rgba(255,87,51,0.5);'));
}
} else if (('' + appendtoinnerHTML).indexOf(('' + athcoords)) != -1) {
if (document.getElementById('svgd').innerHTML.indexOf(' title=' + String.fromCharCode(34) + '' + ath.title + '' + String.fromCharCode(34) + '') != -1) {
document.getElementById('svgd').innerHTML=document.getElementById('svgd').innerHTML.replace(/rgba\(255\,87\,51\,0.5\)/g, 'rgba(200,200,200,0.3)');
document.getElementById('svgd').innerHTML+='<div title=' + String.fromCharCode(34) + '' + ath.title + appendtoinnerHTML.split(ath.coords)[1].split('<div ')[0].replace('none;', 'block;z-index:123;').replace(/\ id\=/g, ' data-id=').replace('lime;', 'rgba(255,87,51,0.5);');
} else {
document.getElementById('svgd').innerHTML=document.getElementById('svgd').innerHTML.replace(/rgba\(255\,87\,51\,0.5\)/g, 'rgba(200,200,200,0.3)');
document.getElementById('svgd').innerHTML+='<div title=' + String.fromCharCode(34) + '' + ath.title + appendtoinnerHTML.split(ath.coords)[1].split('<div ')[0].replace('none;', 'block;z-index:123;').replace('lime;', 'rgba(255,87,51,0.5);');
}
}
waitplease=false;
return '';
}

… also lessened the burden on the client side by only asking any Javascript DOM command operations act on single HTML element at a time, not a whole swathe of hosted ones, in any operation.


Previous relevant GeoJson World Countries Geo Chart Tutorial is shown below.

GeoJson World Countries Geo Chart Tutorial

GeoJson World Countries Geo Chart Tutorial

There are many advantages regarding today’s task to …

Integrate Google Chart Geo Chart

… as an additional “drill down” map option, functionality adding onto the work of yesterday’s GeoJson World Countries Tutorial.

What deducible data item needs to be determined for these Geo Charts to work? We need a way to deduce ISO-2 character country codes from the ISO-3 character codes existing in the GeoJson “countries.geojson” data from yesterday’s work. We happened upon the extremely generous mapping data webpage to help with these ISO-2 character deductions

<?php

$geojsonis=file_get_contents('countries.geojson');
$parts=explode("]]", $geojsonis);
$globalattr="";
$mappings=file_get_contents('http://gist.github.com/tadast/8827699'); // thanks
if (strpos($mappings, '>IN</td>') !== false) {
$mappings.='<td>IN</td><td>KAS</td><td>EH</td><td>SAH</td><td>SO</td><td>SOL</td><td>SS</td><td>SDS</td><td>XK</td><td>KOS</td><td>CY</td><td>CYN</td></body>';
}


for ($i=0; $i<(-1 + sizeof($parts)); $i++) {
if (strpos($parts[$i], '"sr_sov_a3":"') !== false) {
$globalattr=' data-iso3="' . explode('"', explode('"sr_sov_a3":"', $parts[$i])[1])[0] . '"';
if (strpos($mappings, '>' . explode('"', explode('"sr_sov_a3":"', $parts[$i])[1])[0] . '</td>') !== false) {
$iparts=explode('>' . explode('"', explode('"sr_sov_a3":"', $parts[$i])[1])[0] . '</td>', $mappings);
$globalattr.=' data-iso2="' . explode('>', explode('</td>', $iparts[0])[-2 + sizeof(explode('</td>', $iparts[0]))])[-1 + sizeof(explode('>', explode('</td>', $iparts[0])[-2 + sizeof(explode('</td>', $iparts[0]))]))] . '"';
} else if (substr(explode('"', explode('"sr_sov_a3":"', $parts[$i])[1])[0],-1,1) >= '0' && substr(explode('"', explode('"sr_sov_a3":"', $parts[$i])[1])[0],-1,1) <= '9') {
$globalattr.=' data-iso2="' . substr(explode('"', explode('"sr_sov_a3":"', $parts[$i])[1])[0],0,2) . '"';
}
}
if (strpos($parts[$i], '"sr_subunit":"') !== false) {
$globalattr.=' data-cname="' . explode('"', explode('"sr_subunit":"', $parts[$i])[1])[0] . '"';
}
$coords=str_replace('[','',str_replace(']','',explode('[[' , $parts[$i])[-1 + sizeof(explode('[[' , $parts[$i]))]));
$newcoords=$coords;
if (!$dolatlong || 1 == 1) {
$lls=explode(",", $coords);
$newcoords="";
for ($j=0; $j<sizeof($lls); $j+=2) {
$lls[$j]=($lls[$j] + $longoff) * $factor;
$lls[$j + 1]=($lls[$j + 1] + $latoff) * $factor;
if ($newcoords != "") { $newcoords.=","; $htmlis=str_replace("}", " context.lineTo(" . $lls[$j] . ',' . ((180.0 * $factor) - $lls[$j + 1]) . "); \n}", $htmlis); } else { $htmlis=str_replace("}", " context.stroke(); \n context.beginPath(); \n context.moveTo(" . $lls[$j] . ',' . ((180.0 * $factor) - $lls[$j + 1]) . "); \n}", $htmlis); }
$newcoords.='' . $lls[$j] . ',' . ((180.0 * $factor) - $lls[$j + 1]);
}
}
$abit.="<area" . $globalattr . " onclick=\"ouralert(this.getAttribute('data-cname'),this.getAttribute('data-iso3'),this.getAttribute('data-iso2'),'Longitude,Latitude coordinates are " . $coords . "');\" shape='poly' coords='" . $newcoords . "'></area>\n";
//echo "<area type='poly' coords='" . $newcoords . "'></area>\n";
}

?>

… in our image map area elements PHP creation code above. As you can see, extra “intelligence”, moving forward, is contained in area element global data attributes.

Which leaves us with why any of this helps functionality within our changed countries.php web application you can also try below?

  • Geo Chart can zoom into a country view …
  • Geo Chart can involve emoji (🏠 &127968;) or image (SVG) circle based symbology for the “User Clicked Place” and nearby TimeZone places respectively …
  • all these symbols can be clicked to open popup windows containing TimeZone Place Wikipedia webpages of relevance …
  • an emoji national flag (eg. Zambia “ZA” could be used to derive &#127487;&#127462; 🇿🇦 flag emoji) derived from those ISO-2 character codes can supplement the GeoJson (more ISO-3 character based) names presented in the underlying data, in the Geo Chart title …
  • contextualizing the accompanying Map Chart … and …
  • vice versa regarding hovering over symbology (which works on Map Chart, but not Geo Chart) …
  • within the Map Chart iframe a “Geo” link can glean a “zoomed out” world Geo Chart view of your TimeZone places

And feel free to (re-)try our tweaked “to make thinner the coastline linework” regions.php GeoJson PHP web application in a new window, or you can also try below.


Previous relevant GeoJson World Countries Tutorial is shown below.

GeoJson World Countries Tutorial

GeoJson World Countries Tutorial

Know your GeoJson! Yes, pretty obviously, any two GeoJson datasets might display the same in that “map plotting” sense, but one might have different and/or more “intelligence” than the other. Often, an XML has more “intelligence” than equivalent HTML (barring the use of global data attributes, that is), as today’s Corollacorollary.

And so, moving on from yesterday’s GeoJson World Coastline TimeZone Tutorial, today, we present a new GeoJson admin 0 countries we download, and upload as “countries.geojson” data set, again via the excellent HTTP://geojson.xyz/ repository, thanks.

From it, we do get a different JSON additional “intelligence”


{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"scalerank":1,"labelrank":1,"sr_sov_a3":"ZWE","sr_adm0_a3":"ZWE","sr_gu_a3":"ZWE","sr_su_a3":"ZWE","sr_subunit":"Zimbabwe","featureclass":"Admin-0 scale ranks"},"geometry":{"type":"Polygon","coordinates":[[[31.287890625000017,-22.40205078125001],[31.197265625,-22.34492187500001],[31.07343750000001,-22.30781250000001],[30.916113281250006,-22.29072265625001],[30.71162109375001,-22.2978515625],[30.46015625000001,-22.32900390625001],[30.1904296875,-22.291113281250006],[29.90234375,-22.184179687500006],[29.6630859375,-22.146289062500003],[29.37744140625,-22.19277343750001],[29.36484375,-22.193945312500006],[29.315234375000017,-22.15771484375],[29.237207031250023,-22.07949218750001],[29.106835937500023,-22.065722656250003],[29.07148437500001,-22.047460937500006],[29.042382812500023,-22.018359375],[29.023339843750023,-21.98125],[29.01582031250001,-21.93994140625],[29.03730468750001,-21.811328125],[29.02558593750001,-21.796875],[28.99072265625,-21.78144531250001],[28.919335937500023,-21.766015625],[28.74775390625001,-21.707617187500006],[28.532031250000017,-21.65126953125001],[28.181640625,-21.58935546875],[28.04560546875001,-21.573046875],[28.014062500000023,-21.55419921875],[27.974609375,-21.50673828125001],[27.90742187500001,-21.35908203125001],[27.844140625000023,-21.261523437500003],[27.693457031250006,-21.11103515625001],[27.66943359375,-21.064257812500003],[27.67695312500001,-20.94482421875],[27.688085937500006,-20.84833984375001],[27.70429687500001,-20.76640625],[27.69697265625001,-20.689746093750003],[27.69482421875,-20.59453125],[27.699609375000023,-20.53066406250001],[27.679296875,-20.503027343750006],[27.624609375,-20.48359375000001],[27.46894531250001,-20.47480468750001],[27.28076171875,-20.47871093750001],[27.27460937500001,-20.3818359375],[27.256738281250023,-20.23203125],[27.221484375000017,-20.145800781250003],[27.17822265625,-20.10097656250001],[27.091796875,-20.05419921875],[26.91669921875001,-19.99013671875001],[26.67822265625,-19.89277343750001],[26.474609375,-19.748632812500006],[26.241015625000017,-19.5693359375],[26.168066406250006,-19.53828125000001],[26.081933593750023,-19.369921875],[25.95068359375,-19.08173828125001],[25.95917968750001,-18.985644531250003],[25.939355468750023,-18.93867187500001],[25.811914062500023,-18.79707031250001],[25.78369140625,-18.72353515625001],[25.76123046875,-18.64921875],[25.55830078125001,-18.441796875],[25.4892578125,-18.35126953125001],[25.43671875000001,-18.234960937500006],[25.384375,-18.14199218750001],[25.340234375000023,-18.1044921875],[25.28242187500001,-18.04121093750001],[25.242285156250006,-17.969042968750003],[25.224023437500023,-17.91523437500001],[25.239062500000017,-17.843066406250003],[25.2587890625,-17.793554687500006],[25.451757812500006,-17.84511718750001],[25.55712890625,-17.84951171875001],[25.6396484375,-17.82412109375001],[25.741601562500023,-17.858203125],[25.86328125,-17.951953125],[25.995898437500017,-17.969824218750006],[26.139550781250023,-17.91171875],[26.333398437500023,-17.929296875],[26.577539062500023,-18.022558593750006],[26.779882812500006,-18.04150390625],[27.020800781250017,-17.95839843750001],[27.235742187500023,-17.728320312500003],[27.437890625000023,-17.51191406250001],[27.63671875,-17.262109375],[27.75654296875001,-17.060351562500003],[27.932226562500006,-16.89619140625001],[28.16376953125001,-16.76972656250001],[28.399804687500023,-16.66279296875001],[28.760644531250023,-16.53193359375001],[28.760546875000017,-16.53212890625001],[28.83271484375001,-16.424121093750003],[28.856738281250017,-16.30615234375],[28.856738281250017,-16.14228515625001],[28.875585937500006,-16.0361328125],[28.9130859375,-15.98779296875],[28.973046875000023,-15.950097656250009],[29.050585937500017,-15.901171875],[29.287890625000017,-15.776464843750006],[29.4873046875,-15.69677734375],[29.729589843750006,-15.644628906250006],[29.994921875000017,-15.64404296875],[30.25068359375001,-15.643457031250009],[30.39609375,-15.64306640625],[30.39814453125001,-15.80078125],[30.409375,-15.978222656250011],[30.437792968750017,-15.995312500000011],[30.630175781250017,-15.999218750000011],[30.938769531250017,-16.01171875],[31.236230468750023,-16.02363281250001],[31.426171875000023,-16.15234375],[31.48984375,-16.1796875],[31.687597656250006,-16.214160156250003],[31.939843750000023,-16.428808593750006],[32.243261718750006,-16.44873046875],[32.45195312500002,-16.515722656250006],[32.635839843750006,-16.589453125],[32.741796875,-16.67763671875001],[32.81025390625001,-16.69765625],[32.902929687500006,-16.704199218750006],[32.94804687500002,-16.71230468750001],[32.93789062500002,-16.775976562500006],[32.87626953125002,-16.88359375],[32.884375,-17.03779296875001],[32.969335937500006,-17.2515625],[32.98076171875002,-17.4375],[32.9546875,-17.765429687500003],[32.95556640625,-18.08291015625001],[32.96464843750002,-18.1962890625],[32.978515625,-18.271484375],[32.99638671875002,-18.312597656250006],[32.99306640625002,-18.35957031250001],[32.942480468750006,-18.49267578125],[32.90166015625002,-18.632910156250006],[32.90029296875002,-18.6890625],[32.88457031250002,-18.728515625],[32.8544921875,-18.763671875],[32.72197265625002,-18.828417968750003],[32.69921875,-18.868457031250003],[32.69970703125,-18.94091796875],[32.71650390625001,-19.00185546875001],[32.766210937500006,-19.02431640625001],[32.826171875,-19.05878906250001],[32.84980468750001,-19.10439453125001],[32.85,-19.152441406250006],[32.83095703125002,-19.24140625000001],[32.77763671875002,-19.388769531250006],[32.83076171875001,-19.558203125],[32.89042968750002,-19.668066406250006],[32.97265625,-19.79541015625],[33.00673828125002,-19.873828125],[33.0048828125,-19.93017578125],[32.992773437500006,-19.98486328125],[32.86962890625,-20.2171875],[32.780859375,-20.36152343750001],[32.67255859375001,-20.51611328125],[32.529296875,-20.613085937500003],[32.49238281250001,-20.659765625],[32.477636718750006,-20.712988281250006],[32.48281250000002,-20.82890625],[32.476171875,-20.95009765625001],[32.353613281250006,-21.136523437500003],[32.429785156250006,-21.29707031250001],[32.41240234375002,-21.311816406250003],[32.37109375,-21.33486328125001],[32.19472656250002,-21.515429687500003],[32.01630859375001,-21.698046875],[31.88593750000001,-21.83154296875],[31.737695312500023,-21.9833984375],[31.57148437500001,-22.15351562500001],[31.429492187500017,-22.298828125],[31.287890625000017,-22.40205078125001]]]}}

… and “mapping look” because country borders are added in, and some JSON attributes we can call on to allow for …

  • the similar Google Chart Map Chart maps introduced yesterday into the user interaction mix … as well as …
  • Wikipedia, thanks, webpage lookup possibilities calling on those new GeoJson property attributes presented within the dataset above

We enable this, as we just add in some Javascript popup window type equals “prompt” to the existant “confirm” and “alert” logic of yesterday.

Feel free to try the how we got there regions.php GeoJson PHP World Countries web application in a new window, or below …


Previous relevant GeoJson World Coastline TimeZone Tutorial is shown below.

GeoJson World Coastline TimeZone Tutorial

GeoJson World Coastline TimeZone Tutorial

Luckily for programmers all over, the organization of TimeZones has had an International flavour in its development and maintenance. As such, given the “purely coastline” GeoJson data involved in our fledgling PHP web application of yesterday’s GeoJson World Coastline Primer Tutorial a useful arrangement for improvement involves …

  • document.body onclick event co-ordinates … able to be converted to …
  • longitude, latitude (easily, only because of our simplistic map projection, of course) … onfed to …
  • our inhouse “TimeZone Places” web application PHP helper

… can have us helping out your curious web “clicking” user with the 3 nearest TimeZone places, as a reference as to where they are “clicking” in the world.

Feel free to try our improved regions.php GeoJson PHP web application in a new window, or below …

Stop Press

Our efforts in making our new tweaked regions.php GeoJson PHP web application more mobile platform user friendly reminds us about a salutary issue regarding touch gestures …

  • in a discrete click methodology of interest, you could adopt a non-mobile “onmousedown” logic set that does not get interfered with by a mobile “ontouchdown” logic set (perhaps leaving “onclick” event, which both non-mobile and mobile both recognise, for another event logic role) … and …
  • neither will interrupt the mobile gestures associated with swiping and pinching, which refer to the events “ontouchstart” and “ontouchend” at either end of their lifespan


Previous relevant GeoJson World Coastline Primer Tutorial is shown below.

GeoJson World Coastline Primer Tutorial

GeoJson World Coastline Primer Tutorial

We’re keen to further explore the possibilities of GeoJson public data sets, further to yesterday’s Swift Playgrounds on macOS Map Emoji Tutorial.

And then we remembered some of the methodologies we used with Responsive Web Design Landing Page Image Map Tutorial, talking about image maps

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 first two ideas of which, along with …

… in our “early days” “proof of concept” regions.php GeoJson PHP web application.

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


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


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


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


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


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


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


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


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


If this was interesting you may be interested in 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, Tutorials | Tagged , , , , , , , , , | Leave a comment

PHP GNU Multiple Precision Mathematics Tutorial

PHP GNU Multiple Precision Mathematics Tutorial

PHP GNU Multiple Precision Mathematics Tutorial

Maths fun “PHP style” can be had with the GNU Multiple Precision (GMP) extension with echoes of PHP mathematics work talked about with PHP Bcmath Factorial Tutorial.

Again, on this AlmaLinux PHP (starting with 8) environment, we started off with those ever fascinating …

  • factorial calculations … and then followed that up with …
  • number to the power of …
  • next greatest prime number …
  • least common multiple …
  • greatest common divisor

… functionalities the user can try for themselves …

<?php

// factorial.php
// RJM Programming - August, 2024
// Thanks to https://www.php.net/manual/en/gmp.examples.php

$whereplace=shell_exec("ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'");
if (strpos(($whereplace . ' ' . $_SERVER['SERVER_ADDR']), '65.254.92.213') !== false) {
header('Location: https://65.254.95.247/PHP/factorial.php');
exit;
}

$fstyle="";
$pstyle="";
$facttodo=1000;
$pow="1";
if (isset($_GET['facttodo'])) {
if (strlen('' . $_GET['facttodo']) > 0) {
$facttodo=str_replace('+',' ',urldecode($_GET['facttodo']));
}
} else if (isset($_POST['facttodo'])) {
if (strlen('' . $_POST['facttodo']) > 0) {
$facttodo=str_replace('+',' ',urldecode($_POST['facttodo']));
}
}
if (isset($_GET['pow'])) {
if (strlen('' . $_GET['pow']) > 0) {
$pow=str_replace('+',' ',urldecode($_GET['pow']));
}
} else if (isset($_POST['pow'])) {
if (strlen('' . $_POST['pow']) > 0) {
$pow=str_replace('+',' ',urldecode($_POST['pow']));
}
}

function fact($x) {
$return = 1;
for ($i=2; $i <= $x; $i++) {
$return = gmp_mul($return, $i);
}
return $return;
}

function thepow($x, $y) {
return gmp_pow($x, $y);
}

function thegcd($x, $y) {
return gmp_gcd($x, $y);
}

function thelcm($x, $y) {
return gmp_lcm($x, $y);
}

function nextprime($x) {
return gmp_nextprime($x);
}

echo "<html>
<head>
<style>
form {
display: inline-block;
}

textarea {
background-color: yellow;
}
</style>
</head>
<body>
<h1>Factorials via GMP</h1>
<h3>RJM Programming - August, 2024</h3>
<h4>Factorial of <form method=POST action=./factorial.php><input style=display:inline-block; onblur=\"document.getElementById('mysub').click();\" type=number step=1 name=facttodo id=facttodo value='" . $facttodo . "'></input><input type=submit style=display:none; id=mysub></input></form> is ...</h4>
<textarea style=width:95%;height:34%;>" . gmp_strval(fact($facttodo)) . "</textarea>
<h4><span>Number </span><form method=POST action=./factorial.php><input style=display:inline-block; data-onblur=\"document.getElementById('mysub').click();\" type=number step=1 name=facttodo id=facttodotwo value='" . $facttodo . "'></input><span> to the power of </span><input style=display:inline-block; onblur=\"document.getElementById('mysubpow').click();\" type=number step=1 name=pow id=pow value='" . $pow . "'></input><input type=submit style=display:none; id=mysubpow></input></form><span> is ...</span></h4>
<textarea style=width:95%;height:5%;>" . gmp_strval(thepow($facttodo, $pow)) . "</textarea>
<h4><span>Next prime greater than </span><form method=POST action=./factorial.php><input style=display:inline-block; onblur=\"document.getElementById('mysubthree').click();\" type=number step=1 name=facttodo id=facttodothree value='" . $facttodo . "'></input><input type=submit style=display:none; id=mysubthree></input></form><span> is ...</span></h4>
<textarea style=width:95%;height:3%;>" . gmp_strval(nextprime($facttodo)) . "</textarea>
<table cellpadding=15>
<tr><td>
<h4><span>Least common multiple of </span><form method=POST action=./factorial.php><input style=display:inline-block; data-onblur=\"document.getElementById('mysub').click();\" type=number step=1 name=facttodo id=facttodofive value='" . $facttodo . "'></input><span> and </span><input style=display:inline-block; onblur=\"document.getElementById('mysubfive').click();\" type=number step=1 name=pow id=powfive value='" . $pow . "'></input><input type=submit style=display:none; id=mysubfive></input></form><span> is ...</span></h4>
<textarea style=width:95%;height:3%;>" . gmp_strval(thegcd($facttodo, $pow)) . "</textarea>
</td><td>
<h4><span>Greatest common divisor of </span><form method=POST action=./factorial.php><input style=display:inline-block; data-onblur=\"document.getElementById('mysub').click();\" type=number step=1 name=facttodo id=facttodofour value='" . $facttodo . "'></input><span> and </span><input style=display:inline-block; onblur=\"document.getElementById('mysubfour').click();\" type=number step=1 name=pow id=powfour value='" . $pow . "'></input><input type=submit style=display:none; id=mysubfour></input></form><span> is ...</span></h4>
<textarea style=width:95%;height:3%;>" . gmp_strval(thelcm($facttodo, $pow)) . "</textarea>
</td></tr></table>
</body></html>";

?>

To install on AlmaLinux we ended up with a “dnf” package manager scenario looking like …


[root@65-254-95-247 ~]# dnf list *gmp*
Last metadata expiration check: 3:23:48 ago on Sat 31 Aug 2024 10:51:31 AM AWST.
Installed Packages
cpanel-perl-536-math-bigint-gmp.x86_64 1.6011-1.cp108~el9 @System
ea-php80-php-gmp.x86_64 8.0.30-4.4.8.cpanel @EA4-c9
ea-php81-php-gmp.x86_64 8.1.29-1.2.1.cpanel @EA4-c9
ea-php82-php-gmp.x86_64 8.2.22-1.2.1.cpanel @EA4-c9
gmp.x86_64 1:6.2.0-13.el9 @baseos
Available Packages
alt-php-internal-gmp.x86_64 8.2.14-2.el9 imunify360
alt-php82-gmp.x86_64 8.2.8-1.el9 imunify360
ea-php80-php-gmp-debuginfo.x86_64 8.0.28-1.1.29.cpanel EA4-c9
ea-php81-php-gmp-debuginfo.x86_64 8.1.19-2.2.1.cpanel EA4-c9
ea-php82-php-gmp-debuginfo.x86_64 8.2.6-2.2.1.cpanel EA4-c9
ea-php83-php-gmp.x86_64 8.3.10-1.2.1.cpanel EA4-c9
gmp.i686 1:6.2.0-13.el9 baseos
gmp-c++.i686 1:6.2.0-13.el9 appstream
gmp-c++.x86_64 1:6.2.0-13.el9 appstream
gmp-devel.i686 1:6.2.0-13.el9 appstream
gmp-devel.x86_64 1:6.2.0-13.el9 appstream
perl-Crypt-DH-GMP.x86_64 0.00012-24.el9 epel
perl-Math-BigInt-GMP.x86_64 1.6007-1.el9 epel
perl-Math-GMP.x86_64 2.24-1.el9 epel
python-gmpy2-doc.noarch 2.1.2-4.el9 epel
python3-gmpy2.x86_64 2.1.2-4.el9 epel
[root@65-254-95-247 ~]#

… for a functional first draft “proof of concept” GMP based mathematics web application the user can try for themselves below …


Previous relevant PHP Bcmath Factorial Tutorial is shown below.

PHP Bcmath Factorial Tutorial

PHP Bcmath Factorial Tutorial

Today we’ve had great guidance from this webpage’s contributors, thanks, writing a Factorial Calculator, using PHP and its Bcmath extension, revisiting concepts we last talked about when we presented PHP Bcmath Primer Tutorial.

Are you like me with maps and sometimes with long numbers … just staring at a long integer trying to find patterns?

Well, you need to let …

Factorials

… into your life … the bigger the better! Wonder at all those zeroes at the end? Carve a long factorial into a piece of soap? They say the Lord’s Prayer was written on a pinhead … what are you waiting for?!

Or just avail yourself of today’s use_bcmath.php first draft PHP Factorial Calculator

… therapy.


Previous relevant PHP Bcmath Primer Tutorial is shown below.

PHP Bcmath Primer Tutorial

PHP Bcmath Primer Tutorial

Today we have an unusual linkage of tutorials, where we link our tutorial here, today, called “PHP Bcmath Primer Tutorial” with one from some time back (and I.T. historically speaking, a really long way back) called Lisp Primer Tutorial as shown below.

The link is the way the languages handle some arithmetic on very large numbers, and today we present a web application that is like a calculator for some of those very large number calculations. Am not certain Lisp does the work this way, but the “bcmath” module in PHP, that we use for the purpose here today, uses “strings” to achieve the affect, so that I don’t believe there are any times during the calculations, necessarily, with the CPU register, that there are any great huge numbers being handled, but piece by piece, the CPU register is helping piece together that string that represents the answer we are after, not using any scientific notation in the process.

We throw into the mix a bit of fun and games … just imagine you are on Central (train) Station in Sydney, or loads of other train stations in the world where it is pretty obvious the station announcements are pieced together bits of audio, and today we make use of the wonderful Google Translate functionality in order for you to, optionally (and not always … no go with Firefox for instance), hear the results in those great mellifluous tones (in English, as default).

Hope you really give some curly questions out there to the live run. Here is the PHP source code using the “bcmath” module you could call got_big_numbers.php


Previous relevant Lisp Primer Tutorial is shown below.

Lisp Primer Tutorial

Lisp Primer Tutorial

Have you heard of Lisp, the programming language? Do you remember how incredible Hewlett Packard calculators were back in the 1970’s (we did as Land Surveyors … they were the bee’s knees, especially to program for those Land Surveying calculations). And do you (older users) remember the excitement regarding reverse Polish notation? Well, Lisp, the second oldest high-level language (after Fortran) uses this reverse Polish notation and thinking.

Am no expert with Lisp, as you’ll see, and we’ll defer to code available on the net and contributed by others, but have to mention its incredible mathematical scope, for instance, with its functionality for huge numbers (integers). You will notice with languages like C++ it is not at all easy doing a calculation like the factorial of 1000 … or 1000! … or 1000 x 999 x 998 x —> x 2 x 1 … but Lisp does it with considerable ease. As a matter of interest, as far as this type of big integer in Java, you may want to check on the BigO data type.

Today’s tutorial introduces you to Lisp we install using LispWorks Personal on a Mac laptop, and execute a Hello World and some large factorial calculations. Lisp, being the old language it is, is a very functional language, and although global variables are allowed, the Lisp “way” is not to resort to such approaches.

Below are some links regarding Lisp you may want to peruse:

Will leave you with some downloadable programming Lisp source code you could call helloworld.lisp and some factorial code called factorial.lisp

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


If this was interesting you may be interested in 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, Installers, Not Categorised, Tutorials | Tagged , , , , , , , , , , , , , , , , , | Leave a comment

AlmaLinux PHP Gettext Backup Translation Tutorial

AlmaLinux PHP Gettext Backup Translation Tutorial

AlmaLinux PHP Gettext Backup Translation Tutorial

As we intimated earlier, using PHP gettext is a good framework to use regarding writing your own serverside language translation functionality, but the “gruntwork” is there ahead of you maintaining those [domain].po (Poedit) files. And so, improving on yesterday’s AlmaLinux PHP Gettext Your Own Translation Tutorial

  • Why don’t we back up an “insufficient data” or “unknown” translation ask from a user, now that they can enter their own words/phrases, by presenting a popup window Google Translate window as a backup?
  • Why don’t we set up a system to follow up on moderations being attended to and accepted by administrative overseers, by adding those words/phrases accepted …
    <?php

    $lastfile="";
    if (file_exists('/tmp/get_text_moderation.txt')) {
    $lines=explode("\n", file_get_contents('/tmp/get_text_moderation.txt'));
    for ($ilines=0; $ilines<sizeof($lines); $ilines++) {
    if (strpos($lines[$ilines], DIRECTORY_SEPARATOR . 'LC_MESSAGES' . DIRECTORY_SEPARATOR) !== false) {
    $lastfile=$lines[$ilines];
    } else if (strpos($lines[$ilines], ' msgid ') !== false && strpos($lines[$ilines], '_await') !== false) {
    if (strpos(file_get_contents($lastfile), " msgid " . explode('_await', explode(' msgid ', $lines[$ilines])[1])[0] . '"' ) !== false) {
    $wordopt.="<option value='" . explode('_await', explode(' msgid "', $lines[$ilines])[1])[0] . "'>" . explode('_await', explode(' msgid "', $lines[$ilines])[1])[0] . "</option>" . "\n";
    }
    }
    }
    }

    ?>
    … through to the Words/Phrases dropdown, in the web application?

Well?! Huh?!

We think so, and you can see this in action with the changed get_text.php PHP Gettext Using web application you can also try below.

We hope you like it!


Previous relevant AlmaLinux PHP Gettext Your Own Translation Tutorial is shown below.

AlmaLinux PHP Gettext Your Own Translation Tutorial

AlmaLinux PHP Gettext Your Own Translation Tutorial

To open up yesterday’s AlmaLinux PHP Gettext Translation Tutorial‘s PHP Gettext Using web application to the possibility of …

  • user supplying a new locale into the mix … and …
  • user supplying their own English to “Their Newly Introduced Locale” word/phrase translation

… is fine and good in principle, but needs moderation, and that requires a deal of thinking. But then we thought, as far as moderation goes, why don’t we …

  • add to the [domain].po relevant [domain].po msgid entry a suffix that goes …


    _await_moderation_[IPaddressBasedStringWebBrowserBrandSpecific]

    … allowing the creator of the translation see their translation echoed back to them, but other people see no translation should they ask for the same translation conditions. That means if someone is not using the web application properly, only they, or people looking over their shoulder, see their own translation ideas happening ahead of a moderator stripping out from the msgid string any suffix like above if that moderator determines it is a genuine translation data item, in which case from then on all users see that translation suggestion come into “live play”.

    See how we did this with the changed get_text.php PHP Gettext Using web application you can also try below.


    Previous relevant AlmaLinux PHP Gettext Translation Tutorial is shown below.

    AlmaLinux PHP Gettext Translation Tutorial

    AlmaLinux PHP Gettext Translation Tutorial

    With our changeover to …

    • AlmaLinux Apache/PHP/MySql web hosting … using …
    • PHP version with an 8 starting it

    … it is time to revisit the PHP gettext (Human Language Translation) module, that had us reach an install situation which looked like …


    # dnf list *get*text*
    Last metadata expiration check: 1:51:10 ago on Wed 28 Aug 2024 11:45:24 AM AWST.
    Installed Packages
    ea-php80-php-gettext.x86_64 8.0.30-4.4.8.cpanel @EA4-c9
    ea-php80-php-gettext-debuginfo.x86_64 8.0.28-1.1.29.cpanel @EA4-c9
    ea-php81-php-gettext.x86_64 8.1.29-1.2.1.cpanel @EA4-c9
    ea-php81-php-gettext-debuginfo.x86_64 8.1.19-2.2.1.cpanel @EA4-c9
    ea-php82-php-gettext.x86_64 8.2.22-1.2.1.cpanel @EA4-c9
    ea-php82-php-gettext-debuginfo.x86_64 8.2.6-2.2.1.cpanel @EA4-c9
    ea-php83-php-gettext.x86_64 8.3.10-1.2.1.cpanel @EA4-c9
    gettext.x86_64 0.21-8.el9 @baseos
    gettext-common-devel.noarch 0.21-8.el9 @appstream
    gettext-devel.x86_64 0.21-8.el9 @appstream
    gettext-libs.x86_64 0.21-8.el9 @baseos
    Available Packages
    gettext-devel.i686 0.21-8.el9 appstream
    gettext-libs.i686 0.21-8.el9 baseos
    mingw32-gettext.noarch 0.21-5.el9 crb
    mingw32-gettext-static.noarch 0.21-5.el9 crb
    mingw64-gettext.noarch 0.21-5.el9 crb
    mingw64-gettext-static.noarch 0.21-5.el9 crb
    ocaml-gettext.x86_64 0.4.2-6.el9 crb
    ocaml-gettext-devel.x86_64 0.4.2-6.el9 crb
    perl-Locale-gettext.x86_64 1.07-21.el9 crb
    python3-setuptools-gettext.noarch 0.1.3-2.el9 epel

    … (and a …

    dnf install glibc-all-langpacks

    … to install more locales on AlmaLinux web server) … which you can see happening with today’s animated GIF tutorial presentation, as we got somewhere (albeit, after half a day of struggle (getting from years back to “getting there”, involving three “exit” code snippet struggles (only the top one working)), which ended when reading brice/axice/be’s blurb on the PHP setlocale advising webpage, thanks for the brilliance) with gettext.

    Do not think of gettext as some miracle panacea for a language translation issue. It is just a good framework to use, but you still have to do the bulk of the “hard yards” …

    1. creating [domain].po (Poedit) input files where msgid strings have translate from strings and msgstr strings have translate to strings relevant to your language locale (eg. de_DE for German) …
    2. convert these to [domain].mo via …

      msgfmt [domain].po -o [domain].mo
    3. for each relevant locale … you can check for relevance of via …

      locale -a

      … checking

    … with getting the breakthrough get_text.php PHP Gettext Using web application that harnessed some of the .po to .mo work we did when we presented the previous Yahoo YQL JSON Thesaurus Gettext Translation Tutorial, the results of which are reflected in the web application below …


    Previous relevant Yahoo YQL JSON Thesaurus Gettext Translation Tutorial is shown below.

    Yahoo YQL JSON Thesaurus Gettext Translation Tutorial

    Yahoo YQL JSON Thesaurus Gettext Translation Tutorial

    Recently we talked about PHP methods to facilitate (language) internationalization via the “gettext” Human Language and Character Encoding Support module with the PHP Gettext Internationalization Primer Tutorial.

    Yesterday’s Yahoo YQL Web Service JSON Thesaurus Tutorial as shown below, is a good candidate for “gettext” internationalization, and we show the files necessary to oversee yesterday’s HTML and Javascript with a layer of PHP to achieve it. We test this on our local MAMP local web server, where “gettext” is enabled (unfortunately, this is not the case with the rjmprogramming.com.au domain, so today, we only have source code rather than an additional live run … for that you can watch a video playing of a MAMP session using it here).

    Now this additional internationalization concerns the …

    • language of the wording on the screen, and in error messages and titles
    • starting of an execution in the same language as last used … we use PHP methods, but you could also use Cookies for this idea

    The downloadable PHP Ajax_yql_thesaurus.php (we show here the changes to it from yesterday’s HTML at Ajax_yql_thesaurus.php) calls on localization.php.

    Sessions using Poedit (for our Mac laptop) resulted in the necessary translation *.po files (compiled into *.mo) …

    … the languages of the YQL web service of the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

    Leave aside lots of time and/or manperson power for the translation work. Hope this helps you out.


    Previous relevant Yahoo YQL JSON Thesaurus and Translation Tutorial is shown below.

    Yahoo YQL JSON Thesaurus and Translation Tutorial

    Yahoo YQL JSON Thesaurus and Translation Tutorial

    Language teachers will sometimes resort to an immersion method, in the classroom, where the only language allowed to be spoken is the language being learnt, often the second language for the student who is being taught. ESL teachers face this decision sometimes. We read an interesting article on the subject here, and decided to use our Pros and Cons web application to create our own view of the importance of the excellent points talked about in that article, as you can see with our report …

    Then there are degrees of “immersion”, as well, with questions such as whether you allow the use of paper (or electronic) dictionaries and translators. Think there is a lot of agreement that the best language learning happens with some degree of context and use of realia to help the student envisage the situations in which that vocabulary might be encountered. However, with written work or independent study, and even in the classroom a (web application) tool to help the learner with a difficult word could help, and so we’ve extended the functionality of the previous Yahoo YQL Web Service JSON Thesaurus Tutorial as shown below, by offering the chance for the native language be used to translate the word, and offer a list of thesaurus word lists of the language they are learning out of the list of languages below …

    Read more about this below as well, but this tutorial uses a YQL web service into the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

    We found useful, and thank, for this extra functionality, the tremendous MyMemory API resource.

    The downloadable HTML source code for today’s tutorial you could call Ajax_yql_thesaurus.html (changed as per Ajax_yql_thesaurus.html) calls on the PHP yql_thesaurus.php (changed as per yql_thesaurus.php).

    Try a live run yourself and hope this sparks an idea or two for you.


    Previous relevant Yahoo YQL Web Service JSON Thesaurus Tutorial is shown below.

    Yahoo YQL Web Service JSON Thesaurus Tutorial

    Yahoo YQL Web Service JSON Thesaurus Tutorial

    Here is a tutorial that might be re-introducing you to the Yahoo Web Services called YQL, building on previous ones here at this blog. The name is the way it is because it simplified the API aspects of its functionality for the developer to concentrate on SQL, and I’m really supportive of this concept. You don’t have to output in JSON, as other data forms like XML are acceptable. Let’s see what Wikipedia says about YQL below.

    Yahoo! Query Language (YQL) Gumtree Advertisementusing Android Phone Photos Tutorialis an SQL-like query language created by Yahoo! as part of their Developer Network. YQL is designed to retrieve and manipulate data from APIs through a single Web interface, thus allowing mashups that enable developers to create their own applications.[1]

    Initially launched in October 2008 with access to Yahoo APIs,[2] February 2009 saw the addition of open data tables from third parties such as Google Reader, the Guardian, and The New York Times.[3] Some of these APIs still require an API key to access them. On April 29th of 2009, Yahoo introduced the capability to execute the tables of data built through YQL using JavaScript run on the company’s servers for free.[3]

    So this tutorial uses a YQL web service into the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

    And what is a thesaurus? Read what Wikipedia says here but, basically, it can be thought of as a repository of a language’s list of words of a similar meaning to the word of your interest. It is a great tool for people learning a language foreign to them, especially regarding their vocabulary.

    The two big PHP functions of use (as distinct from an Ajax approach, requiring no PHP … read on) for this are:

    • file_get_contents
    • json_decode … when there is a data structure of any complexity, this function is highly recommended, but for today’s tutorial we do not use it, and take the opportunity to show you a solution using Ajax that requires no PHP … link to some downloadable Ajax inspired HTML programming source code which you may want to rename to Ajax_yql_thesaurus.html which changes from the HTML supervising PHP approach as per Ajax_yql_thesaurus.html (and then there is an Ajax live run)

    Good links for information regarding this tutorial (thanks) are:

    Another tool you should have in your armoury for jobs like this is the online JSON validator here. A generic JSON approach to issues could be:

    1. Type the URL you were given into a web browser address bar and have a look at it
    2. Type the URL you were given into http://jsonlint.com/ and have it validated
    3. Understand in your own mind what would be different about 1. to make it suitable
    4. Incorporate findings of 3. into massaging of data between file_get_contents and json_decode

    Here is a link to some downloadable HTML programming source code which you may want to rename to yql_thesaurus.html which calls some downloadable PHP programming source code which you may want to rename to yql_thesaurus.php (and then there is a PHP live run).

    We thank the following free online dictionaries …

    Stay tuned for an interesting blog posting tomorrow which combines the new thesaurus functionality of today’s contribution, along with the functionality “smarts” of yesterday’s PHP/CSS Sentence Auxiliary Verb Game Tutorial.

    Stop Press

    As of 14th May 2015 a blog posting called HTML/Javascript Homonyms Game Tutorial inspired a “tweak” to the arrangement above such that a call of the web application above such as Sense of Humour will cause the display of a lookup during the “onload” event, as required.

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


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


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


    If this was interesting you may be interested in 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, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , | Leave a comment

AlmaLinux PHP Gettext Your Own Translation Tutorial

AlmaLinux PHP Gettext Your Own Translation Tutorial

AlmaLinux PHP Gettext Your Own Translation Tutorial

To open up yesterday’s AlmaLinux PHP Gettext Translation Tutorial‘s PHP Gettext Using web application to the possibility of …

  • user supplying a new locale into the mix … and …
  • user supplying their own English to “Their Newly Introduced Locale” word/phrase translation

… is fine and good in principle, but needs moderation, and that requires a deal of thinking. But then we thought, as far as moderation goes, why don’t we …

  • add to the [domain].po relevant [domain].po msgid entry a suffix that goes …


    _await_moderation_[IPaddressBasedStringWebBrowserBrandSpecific]

    … allowing the creator of the translation see their translation echoed back to them, but other people see no translation should they ask for the same translation conditions. That means if someone is not using the web application properly, only they, or people looking over their shoulder, see their own translation ideas happening ahead of a moderator stripping out from the msgid string any suffix like above if that moderator determines it is a genuine translation data item, in which case from then on all users see that translation suggestion come into “live play”.

    See how we did this with the changed get_text.php PHP Gettext Using web application you can also try below.


    Previous relevant AlmaLinux PHP Gettext Translation Tutorial is shown below.

    AlmaLinux PHP Gettext Translation Tutorial

    AlmaLinux PHP Gettext Translation Tutorial

    With our changeover to …

    • AlmaLinux Apache/PHP/MySql web hosting … using …
    • PHP version with an 8 starting it

    … it is time to revisit the PHP gettext (Human Language Translation) module, that had us reach an install situation which looked like …


    # dnf list *get*text*
    Last metadata expiration check: 1:51:10 ago on Wed 28 Aug 2024 11:45:24 AM AWST.
    Installed Packages
    ea-php80-php-gettext.x86_64 8.0.30-4.4.8.cpanel @EA4-c9
    ea-php80-php-gettext-debuginfo.x86_64 8.0.28-1.1.29.cpanel @EA4-c9
    ea-php81-php-gettext.x86_64 8.1.29-1.2.1.cpanel @EA4-c9
    ea-php81-php-gettext-debuginfo.x86_64 8.1.19-2.2.1.cpanel @EA4-c9
    ea-php82-php-gettext.x86_64 8.2.22-1.2.1.cpanel @EA4-c9
    ea-php82-php-gettext-debuginfo.x86_64 8.2.6-2.2.1.cpanel @EA4-c9
    ea-php83-php-gettext.x86_64 8.3.10-1.2.1.cpanel @EA4-c9
    gettext.x86_64 0.21-8.el9 @baseos
    gettext-common-devel.noarch 0.21-8.el9 @appstream
    gettext-devel.x86_64 0.21-8.el9 @appstream
    gettext-libs.x86_64 0.21-8.el9 @baseos
    Available Packages
    gettext-devel.i686 0.21-8.el9 appstream
    gettext-libs.i686 0.21-8.el9 baseos
    mingw32-gettext.noarch 0.21-5.el9 crb
    mingw32-gettext-static.noarch 0.21-5.el9 crb
    mingw64-gettext.noarch 0.21-5.el9 crb
    mingw64-gettext-static.noarch 0.21-5.el9 crb
    ocaml-gettext.x86_64 0.4.2-6.el9 crb
    ocaml-gettext-devel.x86_64 0.4.2-6.el9 crb
    perl-Locale-gettext.x86_64 1.07-21.el9 crb
    python3-setuptools-gettext.noarch 0.1.3-2.el9 epel

    … (and a …

    dnf install glibc-all-langpacks

    … to install more locales on AlmaLinux web server) … which you can see happening with today’s animated GIF tutorial presentation, as we got somewhere (albeit, after half a day of struggle (getting from years back to “getting there”, involving three “exit” code snippet struggles (only the top one working)), which ended when reading brice/axice/be’s blurb on the PHP setlocale advising webpage, thanks for the brilliance) with gettext.

    Do not think of gettext as some miracle panacea for a language translation issue. It is just a good framework to use, but you still have to do the bulk of the “hard yards” …

    1. creating [domain].po (Poedit) input files where msgid strings have translate from strings and msgstr strings have translate to strings relevant to your language locale (eg. de_DE for German) …
    2. convert these to [domain].mo via …

      msgfmt [domain].po -o [domain].mo
    3. for each relevant locale … you can check for relevance of via …

      locale -a

      … checking

    … with getting the breakthrough get_text.php PHP Gettext Using web application that harnessed some of the .po to .mo work we did when we presented the previous Yahoo YQL JSON Thesaurus Gettext Translation Tutorial, the results of which are reflected in the web application below …


    Previous relevant Yahoo YQL JSON Thesaurus Gettext Translation Tutorial is shown below.

    Yahoo YQL JSON Thesaurus Gettext Translation Tutorial

    Yahoo YQL JSON Thesaurus Gettext Translation Tutorial

    Recently we talked about PHP methods to facilitate (language) internationalization via the “gettext” Human Language and Character Encoding Support module with the PHP Gettext Internationalization Primer Tutorial.

    Yesterday’s Yahoo YQL Web Service JSON Thesaurus Tutorial as shown below, is a good candidate for “gettext” internationalization, and we show the files necessary to oversee yesterday’s HTML and Javascript with a layer of PHP to achieve it. We test this on our local MAMP local web server, where “gettext” is enabled (unfortunately, this is not the case with the rjmprogramming.com.au domain, so today, we only have source code rather than an additional live run … for that you can watch a video playing of a MAMP session using it here).

    Now this additional internationalization concerns the …

    • language of the wording on the screen, and in error messages and titles
    • starting of an execution in the same language as last used … we use PHP methods, but you could also use Cookies for this idea

    The downloadable PHP Ajax_yql_thesaurus.php (we show here the changes to it from yesterday’s HTML at Ajax_yql_thesaurus.php) calls on localization.php.

    Sessions using Poedit (for our Mac laptop) resulted in the necessary translation *.po files (compiled into *.mo) …

    … the languages of the YQL web service of the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

    Leave aside lots of time and/or manperson power for the translation work. Hope this helps you out.


    Previous relevant Yahoo YQL JSON Thesaurus and Translation Tutorial is shown below.

    Yahoo YQL JSON Thesaurus and Translation Tutorial

    Yahoo YQL JSON Thesaurus and Translation Tutorial

    Language teachers will sometimes resort to an immersion method, in the classroom, where the only language allowed to be spoken is the language being learnt, often the second language for the student who is being taught. ESL teachers face this decision sometimes. We read an interesting article on the subject here, and decided to use our Pros and Cons web application to create our own view of the importance of the excellent points talked about in that article, as you can see with our report …

    Then there are degrees of “immersion”, as well, with questions such as whether you allow the use of paper (or electronic) dictionaries and translators. Think there is a lot of agreement that the best language learning happens with some degree of context and use of realia to help the student envisage the situations in which that vocabulary might be encountered. However, with written work or independent study, and even in the classroom a (web application) tool to help the learner with a difficult word could help, and so we’ve extended the functionality of the previous Yahoo YQL Web Service JSON Thesaurus Tutorial as shown below, by offering the chance for the native language be used to translate the word, and offer a list of thesaurus word lists of the language they are learning out of the list of languages below …

    Read more about this below as well, but this tutorial uses a YQL web service into the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

    We found useful, and thank, for this extra functionality, the tremendous MyMemory API resource.

    The downloadable HTML source code for today’s tutorial you could call Ajax_yql_thesaurus.html (changed as per Ajax_yql_thesaurus.html) calls on the PHP yql_thesaurus.php (changed as per yql_thesaurus.php).

    Try a live run yourself and hope this sparks an idea or two for you.


    Previous relevant Yahoo YQL Web Service JSON Thesaurus Tutorial is shown below.

    Yahoo YQL Web Service JSON Thesaurus Tutorial

    Yahoo YQL Web Service JSON Thesaurus Tutorial

    Here is a tutorial that might be re-introducing you to the Yahoo Web Services called YQL, building on previous ones here at this blog. The name is the way it is because it simplified the API aspects of its functionality for the developer to concentrate on SQL, and I’m really supportive of this concept. You don’t have to output in JSON, as other data forms like XML are acceptable. Let’s see what Wikipedia says about YQL below.

    Yahoo! Query Language (YQL) Gumtree Advertisementusing Android Phone Photos Tutorialis an SQL-like query language created by Yahoo! as part of their Developer Network. YQL is designed to retrieve and manipulate data from APIs through a single Web interface, thus allowing mashups that enable developers to create their own applications.[1]

    Initially launched in October 2008 with access to Yahoo APIs,[2] February 2009 saw the addition of open data tables from third parties such as Google Reader, the Guardian, and The New York Times.[3] Some of these APIs still require an API key to access them. On April 29th of 2009, Yahoo introduced the capability to execute the tables of data built through YQL using JavaScript run on the company’s servers for free.[3]

    So this tutorial uses a YQL web service into the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

    And what is a thesaurus? Read what Wikipedia says here but, basically, it can be thought of as a repository of a language’s list of words of a similar meaning to the word of your interest. It is a great tool for people learning a language foreign to them, especially regarding their vocabulary.

    The two big PHP functions of use (as distinct from an Ajax approach, requiring no PHP … read on) for this are:

    • file_get_contents
    • json_decode … when there is a data structure of any complexity, this function is highly recommended, but for today’s tutorial we do not use it, and take the opportunity to show you a solution using Ajax that requires no PHP … link to some downloadable Ajax inspired HTML programming source code which you may want to rename to Ajax_yql_thesaurus.html which changes from the HTML supervising PHP approach as per Ajax_yql_thesaurus.html (and then there is an Ajax live run)

    Good links for information regarding this tutorial (thanks) are:

    Another tool you should have in your armoury for jobs like this is the online JSON validator here. A generic JSON approach to issues could be:

    1. Type the URL you were given into a web browser address bar and have a look at it
    2. Type the URL you were given into http://jsonlint.com/ and have it validated
    3. Understand in your own mind what would be different about 1. to make it suitable
    4. Incorporate findings of 3. into massaging of data between file_get_contents and json_decode

    Here is a link to some downloadable HTML programming source code which you may want to rename to yql_thesaurus.html which calls some downloadable PHP programming source code which you may want to rename to yql_thesaurus.php (and then there is a PHP live run).

    We thank the following free online dictionaries …

    Stay tuned for an interesting blog posting tomorrow which combines the new thesaurus functionality of today’s contribution, along with the functionality “smarts” of yesterday’s PHP/CSS Sentence Auxiliary Verb Game Tutorial.

    Stop Press

    As of 14th May 2015 a blog posting called HTML/Javascript Homonyms Game Tutorial inspired a “tweak” to the arrangement above such that a call of the web application above such as Sense of Humour will cause the display of a lookup during the “onload” event, as required.

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


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


    If this was interesting you may be interested in 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, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , | Leave a comment

AlmaLinux PHP Gettext Translation Tutorial

AlmaLinux PHP Gettext Translation Tutorial

AlmaLinux PHP Gettext Translation Tutorial

With our changeover to …

  • AlmaLinux Apache/PHP/MySql web hosting … using …
  • PHP version with an 8 starting it

… it is time to revisit the PHP gettext (Human Language Translation) module, that had us reach an install situation which looked like …


# dnf list *get*text*
Last metadata expiration check: 1:51:10 ago on Wed 28 Aug 2024 11:45:24 AM AWST.
Installed Packages
ea-php80-php-gettext.x86_64 8.0.30-4.4.8.cpanel @EA4-c9
ea-php80-php-gettext-debuginfo.x86_64 8.0.28-1.1.29.cpanel @EA4-c9
ea-php81-php-gettext.x86_64 8.1.29-1.2.1.cpanel @EA4-c9
ea-php81-php-gettext-debuginfo.x86_64 8.1.19-2.2.1.cpanel @EA4-c9
ea-php82-php-gettext.x86_64 8.2.22-1.2.1.cpanel @EA4-c9
ea-php82-php-gettext-debuginfo.x86_64 8.2.6-2.2.1.cpanel @EA4-c9
ea-php83-php-gettext.x86_64 8.3.10-1.2.1.cpanel @EA4-c9
gettext.x86_64 0.21-8.el9 @baseos
gettext-common-devel.noarch 0.21-8.el9 @appstream
gettext-devel.x86_64 0.21-8.el9 @appstream
gettext-libs.x86_64 0.21-8.el9 @baseos
Available Packages
gettext-devel.i686 0.21-8.el9 appstream
gettext-libs.i686 0.21-8.el9 baseos
mingw32-gettext.noarch 0.21-5.el9 crb
mingw32-gettext-static.noarch 0.21-5.el9 crb
mingw64-gettext.noarch 0.21-5.el9 crb
mingw64-gettext-static.noarch 0.21-5.el9 crb
ocaml-gettext.x86_64 0.4.2-6.el9 crb
ocaml-gettext-devel.x86_64 0.4.2-6.el9 crb
perl-Locale-gettext.x86_64 1.07-21.el9 crb
python3-setuptools-gettext.noarch 0.1.3-2.el9 epel

… (and a …

dnf install glibc-all-langpacks

… to install more locales on AlmaLinux web server) … which you can see happening with today’s animated GIF tutorial presentation, as we got somewhere (albeit, after half a day of struggle (getting from years back to “getting there”, involving three “exit” code snippet struggles (only the top one working)), which ended when reading brice/axice/be’s blurb on the PHP setlocale advising webpage, thanks for the brilliance) with gettext.

Do not think of gettext as some miracle panacea for a language translation issue. It is just a good framework to use, but you still have to do the bulk of the “hard yards” …

  1. creating [domain].po (Poedit) input files where msgid strings have translate from strings and msgstr strings have translate to strings relevant to your language locale (eg. de_DE for German) …
  2. convert these to [domain].mo via …

    msgfmt [domain].po -o [domain].mo
  3. for each relevant locale … you can check for relevance of via …

    locale -a

    … checking

… with getting the breakthrough get_text.php PHP Gettext Using web application that harnessed some of the .po to .mo work we did when we presented the previous Yahoo YQL JSON Thesaurus Gettext Translation Tutorial, the results of which are reflected in the web application below …


Previous relevant Yahoo YQL JSON Thesaurus Gettext Translation Tutorial is shown below.

Yahoo YQL JSON Thesaurus Gettext Translation Tutorial

Yahoo YQL JSON Thesaurus Gettext Translation Tutorial

Recently we talked about PHP methods to facilitate (language) internationalization via the “gettext” Human Language and Character Encoding Support module with the PHP Gettext Internationalization Primer Tutorial.

Yesterday’s Yahoo YQL Web Service JSON Thesaurus Tutorial as shown below, is a good candidate for “gettext” internationalization, and we show the files necessary to oversee yesterday’s HTML and Javascript with a layer of PHP to achieve it. We test this on our local MAMP local web server, where “gettext” is enabled (unfortunately, this is not the case with the rjmprogramming.com.au domain, so today, we only have source code rather than an additional live run … for that you can watch a video playing of a MAMP session using it here).

Now this additional internationalization concerns the …

  • language of the wording on the screen, and in error messages and titles
  • starting of an execution in the same language as last used … we use PHP methods, but you could also use Cookies for this idea

The downloadable PHP Ajax_yql_thesaurus.php (we show here the changes to it from yesterday’s HTML at Ajax_yql_thesaurus.php) calls on localization.php.

Sessions using Poedit (for our Mac laptop) resulted in the necessary translation *.po files (compiled into *.mo) …

… the languages of the YQL web service of the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

Leave aside lots of time and/or manperson power for the translation work. Hope this helps you out.


Previous relevant Yahoo YQL JSON Thesaurus and Translation Tutorial is shown below.

Yahoo YQL JSON Thesaurus and Translation Tutorial

Yahoo YQL JSON Thesaurus and Translation Tutorial

Language teachers will sometimes resort to an immersion method, in the classroom, where the only language allowed to be spoken is the language being learnt, often the second language for the student who is being taught. ESL teachers face this decision sometimes. We read an interesting article on the subject here, and decided to use our Pros and Cons web application to create our own view of the importance of the excellent points talked about in that article, as you can see with our report …

Then there are degrees of “immersion”, as well, with questions such as whether you allow the use of paper (or electronic) dictionaries and translators. Think there is a lot of agreement that the best language learning happens with some degree of context and use of realia to help the student envisage the situations in which that vocabulary might be encountered. However, with written work or independent study, and even in the classroom a (web application) tool to help the learner with a difficult word could help, and so we’ve extended the functionality of the previous Yahoo YQL Web Service JSON Thesaurus Tutorial as shown below, by offering the chance for the native language be used to translate the word, and offer a list of thesaurus word lists of the language they are learning out of the list of languages below …

Read more about this below as well, but this tutorial uses a YQL web service into the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

We found useful, and thank, for this extra functionality, the tremendous MyMemory API resource.

The downloadable HTML source code for today’s tutorial you could call Ajax_yql_thesaurus.html (changed as per Ajax_yql_thesaurus.html) calls on the PHP yql_thesaurus.php (changed as per yql_thesaurus.php).

Try a live run yourself and hope this sparks an idea or two for you.


Previous relevant Yahoo YQL Web Service JSON Thesaurus Tutorial is shown below.

Yahoo YQL Web Service JSON Thesaurus Tutorial

Yahoo YQL Web Service JSON Thesaurus Tutorial

Here is a tutorial that might be re-introducing you to the Yahoo Web Services called YQL, building on previous ones here at this blog. The name is the way it is because it simplified the API aspects of its functionality for the developer to concentrate on SQL, and I’m really supportive of this concept. You don’t have to output in JSON, as other data forms like XML are acceptable. Let’s see what Wikipedia says about YQL below.

Yahoo! Query Language (YQL) Gumtree Advertisementusing Android Phone Photos Tutorialis an SQL-like query language created by Yahoo! as part of their Developer Network. YQL is designed to retrieve and manipulate data from APIs through a single Web interface, thus allowing mashups that enable developers to create their own applications.[1]

Initially launched in October 2008 with access to Yahoo APIs,[2] February 2009 saw the addition of open data tables from third parties such as Google Reader, the Guardian, and The New York Times.[3] Some of these APIs still require an API key to access them. On April 29th of 2009, Yahoo introduced the capability to execute the tables of data built through YQL using JavaScript run on the company’s servers for free.[3]

So this tutorial uses a YQL web service into the data emanating from its links to the altervista thesaurus web service database with Yahoo YQL website … thanks. For the altervista thesaurus database usage it is best to request a key for your web service queries. You fill in a word (or two, or three) of interest to search for like-minded words.

And what is a thesaurus? Read what Wikipedia says here but, basically, it can be thought of as a repository of a language’s list of words of a similar meaning to the word of your interest. It is a great tool for people learning a language foreign to them, especially regarding their vocabulary.

The two big PHP functions of use (as distinct from an Ajax approach, requiring no PHP … read on) for this are:

  • file_get_contents
  • json_decode … when there is a data structure of any complexity, this function is highly recommended, but for today’s tutorial we do not use it, and take the opportunity to show you a solution using Ajax that requires no PHP … link to some downloadable Ajax inspired HTML programming source code which you may want to rename to Ajax_yql_thesaurus.html which changes from the HTML supervising PHP approach as per Ajax_yql_thesaurus.html (and then there is an Ajax live run)

Good links for information regarding this tutorial (thanks) are:

Another tool you should have in your armoury for jobs like this is the online JSON validator here. A generic JSON approach to issues could be:

  1. Type the URL you were given into a web browser address bar and have a look at it
  2. Type the URL you were given into http://jsonlint.com/ and have it validated
  3. Understand in your own mind what would be different about 1. to make it suitable
  4. Incorporate findings of 3. into massaging of data between file_get_contents and json_decode

Here is a link to some downloadable HTML programming source code which you may want to rename to yql_thesaurus.html which calls some downloadable PHP programming source code which you may want to rename to yql_thesaurus.php (and then there is a PHP live run).

We thank the following free online dictionaries …

Stay tuned for an interesting blog posting tomorrow which combines the new thesaurus functionality of today’s contribution, along with the functionality “smarts” of yesterday’s PHP/CSS Sentence Auxiliary Verb Game Tutorial.

Stop Press

As of 14th May 2015 a blog posting called HTML/Javascript Homonyms Game Tutorial inspired a “tweak” to the arrangement above such that a call of the web application above such as Sense of Humour will cause the display of a lookup during the “onload” event, as required.

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


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


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


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

Posted in Not Categorised | Tagged , , , , , , , , , , , , , , | Leave a comment

Ffmpeg User Defined Video Editing Crontab Assisted Sharing Tutorial

Ffmpeg User Defined Video Editing Crontab Assisted Sharing Tutorial

Ffmpeg User Defined Video Editing Crontab Assisted Sharing Tutorial

In yesterday’s Ffmpeg User Defined Video Editing Sharing Tutorial about sharing video data (that might have been edited by ffmpeg command line means) we warned …

even though it is only likely to work for shorter videos

… regarding the data URI hashtagged parts to SMS or email links that we were exclusively using … then. But, with this in mind, what do …

  1. data URI based URLs (hashtagged in an email or SMS link) … and …
  2. absolute URL that points to a web server soft link file, itself pointing to /tmp/ video data files ((we’re still hashtagging, but now, don’t really have to, apply) in an email or SMS link)

… share? We’d say, as far as sharing goes …

A sense of permanency.

But …

  • the second one does not “push the barrow” as much as the first regarding the amount of data … whereas …
  • the first is totally ephemeral and not asking anything more of the web server (ie. the RJM Programming associated one) regarding ongoing storage but is asking a lot of web browsers and client mail applications in the case of video data of any bulk

In terms of sharing videos of any bulk, we’re now, with our web application …

  • renaming the top button (that used to be “Display”) as “Display for a Day” and applying absolute URL (that point at web server soft links that, in turn, point at what can be sizeable video data files that might hang around in RJM Programming domain associated web server /tmp/ location) logics which call on “crontab” … (

    */53 * * * * /etc/init.d/every_hour.sh

    … now mentions …

    ksh -c 'for i in `find /tmp -name "my_video_*.*" -mmin -1440`; do rm -f $i; done'

    ) … assistance to do with the tidy up we feel we need to do on the web server so that large files do not hang around forever (and as you might surmise, at most a day, regarding the bulk of data requirements that are temporarily stored in /tmp/ locations with user associated IP addresses part of the file naming paradigm) … whereas …
  • the bottom button remains as “Display” and still uses data URI based logic

… so that these bulky videos can be successfully shared (via clicks of that “Display for a Day” button) as long as the email or SMS link is attended to by the collaboration recipient within those 24 hours, further to yesterday’s Ffmpeg User Defined Video Editing Sharing Tutorial.

As well, today, as a genericization measure, we stop seeing govetts_leap in any video file naming, replaced by my_video now that the input video control has become less rigid, and now can be controlled, to some extent, by the user in our changed fourth draft of Your Own Ffmpeg Video Changes, which can be that much more useful in a new way in the AlmaLinux web server environment.


Previous relevant Ffmpeg User Defined Video Editing Sharing Tutorial is shown below.

Ffmpeg User Defined Video Editing Sharing Tutorial

Ffmpeg User Defined Video Editing Sharing Tutorial

Sharing options for video based data are often more restrictive regarding email and SMS conduits, but we’ll still go ahead with a …

  • “a” link “mailto:” (for emails) or “sms:” (for SMS) methodology …
  • email subject containing ffmpeg command used for an output video mode of sharing … or …
  • input video mode of sharing before any ffmpeg involvement … based on …
  • email or SMS links where the video data URI (as necessary) is hashtagged

… set of ideas to try out, even though it is only likely to work for shorter videos. The other more obvious sharing mechanism is to download video data via right click options the web browser product you are using offers anyway. And another sharing idea, independent, and working for input videos is to browse for a video using the helper web application from yesterday, and use its Share API based button below the browsing button to share that input video using one of …

  • Mail
  • Messages
  • AirDrop
  • Notes
  • Simulator
  • Freeform

… on our macOS Safari web browser here on a MacBook Air.

Further to yesterday’s Ffmpeg User Defined Browsed Video Editing Tutorial, then, we have some new (PHP writes) Javascript functions …

<?php echo ”

function smsit() {
var smsno=prompt('Please enter SMS number.', '');
if (smsno != null) {
if (document.getElementById('cto').title.indexOf('data:') == 0) {
document.getElementById('asms').href='sms:' + smsno + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('cto').title);
} else {
document.getElementById('asms').href='sms:' + smsno + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('resultav').value);
}
document.getElementById('asms').click();
}
}


function emailit() {
var emailaddr=prompt('Please enter Email address.', '');
if (emailaddr != null) {
if (document.getElementById('cto').title.indexOf('data:') == 0) {
document.getElementById('aemail').href='mailto:' + emailaddr + '?subject=Ffmpeg%20Video' + encodeURIComponent(' ... ' + document.getElementById('mysubtwo').value.replace(/^Display$/g,'')) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('cto').title);
} else {
document.getElementById('aemail').href='mailto:' + emailaddr + '?subject=Ffmpeg%20Video' + encodeURIComponent(' ... ' + document.getElementById('mysubtwo').value.replace(/^Display$/g,'')) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('resultav').value);
}
document.getElementById('aemail').click();
}
}

function documentgetElementByIdmysubpclick() { // new arrangement for the programmatic click of form submit button
if (eval('' + document.getElementById('resultav').value.length) < 300) {
document.getElementById('myiftwo').src=document.URL.split('?')[0].split('#')[0] + '?becomes=' + encodeURIComponent(document.getElementById('becomes').value) + '&browsed=' + encodeURIComponent(document.getElementById('resultav').value);
} else {
document.getElementById('mysubp').click();
}
}

“; ?>

… in our changed third draft of Your Own Ffmpeg Video Changes, which can be that much more useful in a new way in the AlmaLinux web server environment.


Previous relevant Ffmpeg User Defined Browsed Video Editing Tutorial is shown below.

Ffmpeg User Defined Browsed Video Editing Tutorial

Ffmpeg User Defined Browsed Video Editing Tutorial

Today’s work, onto yesterday’s Ffmpeg User Defined Video Editing Tutorial, is to loosen the restrictions regarding “input video file source” we had happening in that “first draft” incarnation of our Ffmpeg User Defined Video Editing web application.

In order to achieve this, we called on a previous Ffmpeg Install and Public Face Tutorial inspired change to our inhouse macos_ffmpeg_convert.php PHP web application, which can serve as our conduit to either/or …

  • browse for a video file off the user local operating system environment … or …
  • path to a web server placed video file … or …
  • URL to a video file

… extra means by which the user can define the “input video file source” that we’re loosening the shackles regarding usage.

To do this, we look for user actions (via PHP writing out Javascript) …

<?php echo ”

var lastpathc='';
var lastopathc='';
var lastvidc='';
var lastvalue='.m4v';
var exactvalue='';
var vext='.mp4';

function lookfor() {
vext='.mp4';
var thisext='';
if (document.getElementById('opath').value != '') {
if (lastopathc != document.getElementById('opath').value && document.getElementById('opath').title != document.getElementById('opath').value) {
lastopathc=document.getElementById('opath').value;
}
}
if (document.getElementById('path').value != '') {
if (lastpathc != document.getElementById('path').value) {
lastpathc=document.getElementById('path').value;
if (lastopathc == ' ') { lastopathc=document.getElementById('opath').value; }
}
}
if (lastopathc.trim() != '') {
thisext=(lastopathc + '.').split('.')[1].split('.')[0].trim();
if (thisext != '') {
document.getElementById('opath').title=lastopathc;
document.getElementById('path').title='video/' + thisext + ';' + lastpathc + lastopathc;
document.getElementById('resultav').value=lastpathc + lastopathc;
lastopathc=' ';
}
}
if (document.getElementById('resultav').value != '') {
if (lastvidc != document.getElementById('resultav').value) {
if ((document.getElementById('path').title + document.getElementById('resultav').value).indexOf('video/') != -1) {
if (document.getElementById('ifbrowse').src.indexOf('=') != -1) {
document.getElementById('myaltin').value=decodeURIComponent(document.getElementById('ifbrowse').src.split('=')[1].split('&')[0].split('#')[0]);
}
if ((document.getElementById('path').title + document.getElementById('resultav').value).indexOf('video/') != -1) {
if (vext.indexOf((document.getElementById('path').title + document.getElementById('resultav').value).split('video/')[1].split(';')[0].split(',')[0]) == -1) {
vext='.' + document.getElementById('resultav').value.split('video/')[1].split(';')[0].split(',')[0];
document.getElementById('myaltin').value=document.getElementById('myaltin').value.split('.')[0] + vext;
document.getElementById('becomes').value=document.getElementById('becomes').value.split('.')[0] + vext;
}
}
lastvidc=document.getElementById('resultav').value;
document.getElementById('resultav').title='rework';
document.getElementById('mysubp').click();
setTimeout(function(){
if (1 == 1) {
document.getElementById('divvid').innerHTML=\"<video id=myinvideo style=width:95%; controls><source id=myinsource type='video/\" + vext.substring(1) + \"' src='\" + document.getElementById('resultav').value + \"'></source></video>\";
} else {
document.getElementById('myinsource').src=document.getElementById('resultav').value;
}
}, 2000);
//setTimeout(function(){
//document.getElementById('resultav').value='';
//}, 20000);
//alert(lastvidc);
setTimeout(lookfor, 23000);
return '';
}
setTimeout(lookfor, 3000);
return '';
}
}
setTimeout(lookfor, 3000);
return '';
}

setTimeout(lookfor, 3000);

“; ?>

… and then arrange the /tmp/ placed temporary video data via …

<?php

if (isset($_POST['browsed']) && isset($_POST['becomes'])) {
$fgccont='';
//file_put_contents('xzm.xzm', '1');
$outtmpfile=str_replace('+',' ',urldecode($_POST['becomes']));
//file_put_contents('xzm2.xzm2', $outtmpfile);
$outext=explode('.', $outtmpfile)[-1 + sizeof(explode('.', $outtmpfile))];
//file_put_contents('xzm3.xzm3', str_replace(' ','+',urldecode($_POST['browsed'])));
if (strpos(('xwq' . $_POST['browsed']), 'xwqdata') !== false) {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), base64_decode(explode(";base64,", str_replace(' ','+',urldecode($_POST['browsed'])))[1]));
} else if (strpos(('xwq' . strtolower($_POST['browsed'])), 'xwqhttps') !== false) {
$fgccont=file_get_contents('http' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),5));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower($_POST['browsed'])), 'xwqhttp') !== false) {
$fgccont=file_get_contents('http' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),4));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower(str_replace('+',' ',urldecode($_POST['browsed'])))), 'xwq//') !== false) {
$fgccont=file_get_contents('http:' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),0));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower(str_replace('+',' ',urldecode($_POST['browsed'])))), 'xwqwww.') !== false) {
$fgccont=file_get_contents('http://' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),0));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (file_exists(str_replace('+',' ',urldecode($_POST['browsed'])))) {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), file_get_contents(str_replace('+',' ',urldecode($_POST['browsed']))));
}
//file_put_contents('xzm4.xzm4', explode(";base64,", str_replace(' ','+',urldecode($_POST['browsed'])))[1]);
exit;
}

?>

… all the while being helped out by a tweaked macos_ffmpeg_convert.php works Ffmpeg Converter Tool PHP web application helper to our changed second draft of Your Own Ffmpeg Video Changes, which can be that much more useful in a new way in the AlmaLinux web server environment.


Previous relevant Ffmpeg User Defined Video Editing Tutorial is shown below.

Ffmpeg User Defined Video Editing Tutorial

Ffmpeg User Defined Video Editing Tutorial

Today we’re combining video contents from …

  • yesterday’s Ffmpeg Helps iPhone Video to YouTube Tutorial … with …
  • our newly created public interface to ffmpeg with the “soon to be DNS version of rjmprogramming.com.au … but not yet” AlmaLinux Apache/PHP/MySql web server install we talked about at Ffmpeg Install and Public Face Tutorial … and …
  • IP address redirecting, as needed, ifconfig (via PHP shell_exec and $_SERVER[‘SERVER_ADDR’]) based logic …
    <?php

    $whereplace=shell_exec("ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'");
    if (strpos(($whereplace . ' ' . $_SERVER['SERVER_ADDR']), '65.254.92.213') !== false) {
    $sv='/usr/bin/ffmpeg';
    header('Location: https://65.254.95.247/PHP/tmp_ffmpeg.php'); //$smallpath='https://65.254.95.247/PHP/'; //header('Location: https://65.254.95.247/PHP/tmp_ffmpeg.php');
    exit; //exit;
    }

    ?>
    … we talked about at AlmaLinux Landing Page WordPress Content Update Solution Tutorial … as well as …
  • user definable form navigation … using …
  • optional dropdown ideas incorporating ideas from Sepia Video via ffmpeg Primer Tutorial … and using …
  • temporary storage places to place output video … and making use of …
  • soft links regarding URLs we talked about at Linux Web Server Soft Link URL Tutorial (saving us having to use ‘data:video/mp4;base64,’ . base64_encode(file_get_contents(trim($endout))) style PHP interventions (which were testing friendships))

… to start down this road towards public facing ffmpeg video editing around here (which we have been hankering for for several years now).

In this first draft of Your Own Ffmpeg Video Changes (via command line ffmpeg) we’re really buttoning down (via not allowing the forward slash character in amongst the user defined ffmpeg command innards) what happens regarding …

  • output video file source location … and …
  • input video file source …

… but who knows what the future holds?!


Previous relevant Ffmpeg Helps iPhone Video to YouTube Tutorial is shown below.

Ffmpeg Helps iPhone Video to YouTube Tutorial

Ffmpeg Helps iPhone Video to YouTube Tutorial

Today we recorded a video looking out from Govetts Leap, Blackheath, here in the Blue Mountains. We captured it via the Camera app on an iPhone via its Video option.

Nineteen seconds long, to share to this MacBook Air we needed AirDrop, the size of it precluding us from using the Photo app’s Mail sharing option.

And that’s where we wanted to use the great ffmpeg in an optimal way to create a video that we could upload to YouTube. In this, we arrived at this excellent link getting us to try …


ffmpeg -i govetts_leap.MOV -c:v libx264 -preset slow -crf 18 -vf scale=out_color_matrix=bt709 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -c:a aac -ar 48000 -ac 2 -b:a 320k -profile:v high -level 4.0 -bf 2 -coder 1 -pix_fmt yuv420p -b:v 10M -threads 4 -cpu-used 0 -r 30 -g 15 -movflags +faststart govetts_leap.mp4

… with success. Checking with this other excellent link, thanks, we were comforted that they would have recommended an output mp4 file format as well, it seems …

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


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


If this was interesting you may be interested in 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, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Ffmpeg User Defined Video Editing Sharing Tutorial

Ffmpeg User Defined Video Editing Sharing Tutorial

Ffmpeg User Defined Video Editing Sharing Tutorial

Sharing options for video based data are often more restrictive regarding email and SMS conduits, but we’ll still go ahead with a …

  • “a” link “mailto:” (for emails) or “sms:” (for SMS) methodology …
  • email subject containing ffmpeg command used for an output video mode of sharing … or …
  • input video mode of sharing before any ffmpeg involvement … based on …
  • email or SMS links where the video data URI (as necessary) is hashtagged

… set of ideas to try out, even though it is only likely to work for shorter videos. The other more obvious sharing mechanism is to download video data via right click options the web browser product you are using offers anyway. And another sharing idea, independent, and working for input videos is to browse for a video using the helper web application from yesterday, and use its Share API based button below the browsing button to share that input video using one of …

  • Mail
  • Messages
  • AirDrop
  • Notes
  • Simulator
  • Freeform

… on our macOS Safari web browser here on a MacBook Air.

Further to yesterday’s Ffmpeg User Defined Browsed Video Editing Tutorial, then, we have some new (PHP writes) Javascript functions …

<?php echo ”

function smsit() {
var smsno=prompt('Please enter SMS number.', '');
if (smsno != null) {
if (document.getElementById('cto').title.indexOf('data:') == 0) {
document.getElementById('asms').href='sms:' + smsno + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('cto').title);
} else {
document.getElementById('asms').href='sms:' + smsno + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('resultav').value);
}
document.getElementById('asms').click();
}
}


function emailit() {
var emailaddr=prompt('Please enter Email address.', '');
if (emailaddr != null) {
if (document.getElementById('cto').title.indexOf('data:') == 0) {
document.getElementById('aemail').href='mailto:' + emailaddr + '?subject=Ffmpeg%20Video' + encodeURIComponent(' ... ' + document.getElementById('mysubtwo').value.replace(/^Display$/g,'')) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('cto').title);
} else {
document.getElementById('aemail').href='mailto:' + emailaddr + '?subject=Ffmpeg%20Video' + encodeURIComponent(' ... ' + document.getElementById('mysubtwo').value.replace(/^Display$/g,'')) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#vcont=' + document.getElementById('resultav').value);
}
document.getElementById('aemail').click();
}
}

function documentgetElementByIdmysubpclick() { // new arrangement for the programmatic click of form submit button
if (eval('' + document.getElementById('resultav').value.length) < 300) {
document.getElementById('myiftwo').src=document.URL.split('?')[0].split('#')[0] + '?becomes=' + encodeURIComponent(document.getElementById('becomes').value) + '&browsed=' + encodeURIComponent(document.getElementById('resultav').value);
} else {
document.getElementById('mysubp').click();
}
}

“; ?>

… in our changed third draft of Your Own Ffmpeg Video Changes, which can be that much more useful in a new way in the AlmaLinux web server environment.


Previous relevant Ffmpeg User Defined Browsed Video Editing Tutorial is shown below.

Ffmpeg User Defined Browsed Video Editing Tutorial

Ffmpeg User Defined Browsed Video Editing Tutorial

Today’s work, onto yesterday’s Ffmpeg User Defined Video Editing Tutorial, is to loosen the restrictions regarding “input video file source” we had happening in that “first draft” incarnation of our Ffmpeg User Defined Video Editing web application.

In order to achieve this, we called on a previous Ffmpeg Install and Public Face Tutorial inspired change to our inhouse macos_ffmpeg_convert.php PHP web application, which can serve as our conduit to either/or …

  • browse for a video file off the user local operating system environment … or …
  • path to a web server placed video file … or …
  • URL to a video file

… extra means by which the user can define the “input video file source” that we’re loosening the shackles regarding usage.

To do this, we look for user actions (via PHP writing out Javascript) …

<?php echo ”

var lastpathc='';
var lastopathc='';
var lastvidc='';
var lastvalue='.m4v';
var exactvalue='';
var vext='.mp4';

function lookfor() {
vext='.mp4';
var thisext='';
if (document.getElementById('opath').value != '') {
if (lastopathc != document.getElementById('opath').value && document.getElementById('opath').title != document.getElementById('opath').value) {
lastopathc=document.getElementById('opath').value;
}
}
if (document.getElementById('path').value != '') {
if (lastpathc != document.getElementById('path').value) {
lastpathc=document.getElementById('path').value;
if (lastopathc == ' ') { lastopathc=document.getElementById('opath').value; }
}
}
if (lastopathc.trim() != '') {
thisext=(lastopathc + '.').split('.')[1].split('.')[0].trim();
if (thisext != '') {
document.getElementById('opath').title=lastopathc;
document.getElementById('path').title='video/' + thisext + ';' + lastpathc + lastopathc;
document.getElementById('resultav').value=lastpathc + lastopathc;
lastopathc=' ';
}
}
if (document.getElementById('resultav').value != '') {
if (lastvidc != document.getElementById('resultav').value) {
if ((document.getElementById('path').title + document.getElementById('resultav').value).indexOf('video/') != -1) {
if (document.getElementById('ifbrowse').src.indexOf('=') != -1) {
document.getElementById('myaltin').value=decodeURIComponent(document.getElementById('ifbrowse').src.split('=')[1].split('&')[0].split('#')[0]);
}
if ((document.getElementById('path').title + document.getElementById('resultav').value).indexOf('video/') != -1) {
if (vext.indexOf((document.getElementById('path').title + document.getElementById('resultav').value).split('video/')[1].split(';')[0].split(',')[0]) == -1) {
vext='.' + document.getElementById('resultav').value.split('video/')[1].split(';')[0].split(',')[0];
document.getElementById('myaltin').value=document.getElementById('myaltin').value.split('.')[0] + vext;
document.getElementById('becomes').value=document.getElementById('becomes').value.split('.')[0] + vext;
}
}
lastvidc=document.getElementById('resultav').value;
document.getElementById('resultav').title='rework';
document.getElementById('mysubp').click();
setTimeout(function(){
if (1 == 1) {
document.getElementById('divvid').innerHTML=\"<video id=myinvideo style=width:95%; controls><source id=myinsource type='video/\" + vext.substring(1) + \"' src='\" + document.getElementById('resultav').value + \"'></source></video>\";
} else {
document.getElementById('myinsource').src=document.getElementById('resultav').value;
}
}, 2000);
//setTimeout(function(){
//document.getElementById('resultav').value='';
//}, 20000);
//alert(lastvidc);
setTimeout(lookfor, 23000);
return '';
}
setTimeout(lookfor, 3000);
return '';
}
}
setTimeout(lookfor, 3000);
return '';
}

setTimeout(lookfor, 3000);

“; ?>

… and then arrange the /tmp/ placed temporary video data via …

<?php

if (isset($_POST['browsed']) && isset($_POST['becomes'])) {
$fgccont='';
//file_put_contents('xzm.xzm', '1');
$outtmpfile=str_replace('+',' ',urldecode($_POST['becomes']));
//file_put_contents('xzm2.xzm2', $outtmpfile);
$outext=explode('.', $outtmpfile)[-1 + sizeof(explode('.', $outtmpfile))];
//file_put_contents('xzm3.xzm3', str_replace(' ','+',urldecode($_POST['browsed'])));
if (strpos(('xwq' . $_POST['browsed']), 'xwqdata') !== false) {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), base64_decode(explode(";base64,", str_replace(' ','+',urldecode($_POST['browsed'])))[1]));
} else if (strpos(('xwq' . strtolower($_POST['browsed'])), 'xwqhttps') !== false) {
$fgccont=file_get_contents('http' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),5));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower($_POST['browsed'])), 'xwqhttp') !== false) {
$fgccont=file_get_contents('http' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),4));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower(str_replace('+',' ',urldecode($_POST['browsed'])))), 'xwq//') !== false) {
$fgccont=file_get_contents('http:' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),0));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower(str_replace('+',' ',urldecode($_POST['browsed'])))), 'xwqwww.') !== false) {
$fgccont=file_get_contents('http://' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),0));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (file_exists(str_replace('+',' ',urldecode($_POST['browsed'])))) {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), file_get_contents(str_replace('+',' ',urldecode($_POST['browsed']))));
}
//file_put_contents('xzm4.xzm4', explode(";base64,", str_replace(' ','+',urldecode($_POST['browsed'])))[1]);
exit;
}

?>

… all the while being helped out by a tweaked macos_ffmpeg_convert.php works Ffmpeg Converter Tool PHP web application helper to our changed second draft of Your Own Ffmpeg Video Changes, which can be that much more useful in a new way in the AlmaLinux web server environment.


Previous relevant Ffmpeg User Defined Video Editing Tutorial is shown below.

Ffmpeg User Defined Video Editing Tutorial

Ffmpeg User Defined Video Editing Tutorial

Today we’re combining video contents from …

  • yesterday’s Ffmpeg Helps iPhone Video to YouTube Tutorial … with …
  • our newly created public interface to ffmpeg with the “soon to be DNS version of rjmprogramming.com.au … but not yet” AlmaLinux Apache/PHP/MySql web server install we talked about at Ffmpeg Install and Public Face Tutorial … and …
  • IP address redirecting, as needed, ifconfig (via PHP shell_exec and $_SERVER[‘SERVER_ADDR’]) based logic …
    <?php

    $whereplace=shell_exec("ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'");
    if (strpos(($whereplace . ' ' . $_SERVER['SERVER_ADDR']), '65.254.92.213') !== false) {
    $sv='/usr/bin/ffmpeg';
    header('Location: https://65.254.95.247/PHP/tmp_ffmpeg.php'); //$smallpath='https://65.254.95.247/PHP/'; //header('Location: https://65.254.95.247/PHP/tmp_ffmpeg.php');
    exit; //exit;
    }

    ?>
    … we talked about at AlmaLinux Landing Page WordPress Content Update Solution Tutorial … as well as …
  • user definable form navigation … using …
  • optional dropdown ideas incorporating ideas from Sepia Video via ffmpeg Primer Tutorial … and using …
  • temporary storage places to place output video … and making use of …
  • soft links regarding URLs we talked about at Linux Web Server Soft Link URL Tutorial (saving us having to use ‘data:video/mp4;base64,’ . base64_encode(file_get_contents(trim($endout))) style PHP interventions (which were testing friendships))

… to start down this road towards public facing ffmpeg video editing around here (which we have been hankering for for several years now).

In this first draft of Your Own Ffmpeg Video Changes (via command line ffmpeg) we’re really buttoning down (via not allowing the forward slash character in amongst the user defined ffmpeg command innards) what happens regarding …

  • output video file source location … and …
  • input video file source …

… but who knows what the future holds?!


Previous relevant Ffmpeg Helps iPhone Video to YouTube Tutorial is shown below.

Ffmpeg Helps iPhone Video to YouTube Tutorial

Ffmpeg Helps iPhone Video to YouTube Tutorial

Today we recorded a video looking out from Govetts Leap, Blackheath, here in the Blue Mountains. We captured it via the Camera app on an iPhone via its Video option.

Nineteen seconds long, to share to this MacBook Air we needed AirDrop, the size of it precluding us from using the Photo app’s Mail sharing option.

And that’s where we wanted to use the great ffmpeg in an optimal way to create a video that we could upload to YouTube. In this, we arrived at this excellent link getting us to try …


ffmpeg -i govetts_leap.MOV -c:v libx264 -preset slow -crf 18 -vf scale=out_color_matrix=bt709 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -c:a aac -ar 48000 -ac 2 -b:a 320k -profile:v high -level 4.0 -bf 2 -coder 1 -pix_fmt yuv420p -b:v 10M -threads 4 -cpu-used 0 -r 30 -g 15 -movflags +faststart govetts_leap.mp4

… with success. Checking with this other excellent link, thanks, we were comforted that they would have recommended an output mp4 file format as well, it seems …

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


If this was interesting you may be interested in 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, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Ffmpeg User Defined Browsed Video Editing Tutorial

Ffmpeg User Defined Browsed Video Editing Tutorial

Ffmpeg User Defined Browsed Video Editing Tutorial

Today’s work, onto yesterday’s Ffmpeg User Defined Video Editing Tutorial, is to loosen the restrictions regarding “input video file source” we had happening in that “first draft” incarnation of our Ffmpeg User Defined Video Editing web application.

In order to achieve this, we called on a previous Ffmpeg Install and Public Face Tutorial inspired change to our inhouse macos_ffmpeg_convert.php PHP web application, which can serve as our conduit to either/or …

  • browse for a video file off the user local operating system environment … or …
  • path to a web server placed video file … or …
  • URL to a video file

… extra means by which the user can define the “input video file source” that we’re loosening the shackles regarding usage.

To do this, we look for user actions (via PHP writing out Javascript) …

<?php echo ”

var lastpathc='';
var lastopathc='';
var lastvidc='';
var lastvalue='.m4v';
var exactvalue='';
var vext='.mp4';

function lookfor() {
vext='.mp4';
var thisext='';
if (document.getElementById('opath').value != '') {
if (lastopathc != document.getElementById('opath').value && document.getElementById('opath').title != document.getElementById('opath').value) {
lastopathc=document.getElementById('opath').value;
}
}
if (document.getElementById('path').value != '') {
if (lastpathc != document.getElementById('path').value) {
lastpathc=document.getElementById('path').value;
if (lastopathc == ' ') { lastopathc=document.getElementById('opath').value; }
}
}
if (lastopathc.trim() != '') {
thisext=(lastopathc + '.').split('.')[1].split('.')[0].trim();
if (thisext != '') {
document.getElementById('opath').title=lastopathc;
document.getElementById('path').title='video/' + thisext + ';' + lastpathc + lastopathc;
document.getElementById('resultav').value=lastpathc + lastopathc;
lastopathc=' ';
}
}
if (document.getElementById('resultav').value != '') {
if (lastvidc != document.getElementById('resultav').value) {
if ((document.getElementById('path').title + document.getElementById('resultav').value).indexOf('video/') != -1) {
if (document.getElementById('ifbrowse').src.indexOf('=') != -1) {
document.getElementById('myaltin').value=decodeURIComponent(document.getElementById('ifbrowse').src.split('=')[1].split('&')[0].split('#')[0]);
}
if ((document.getElementById('path').title + document.getElementById('resultav').value).indexOf('video/') != -1) {
if (vext.indexOf((document.getElementById('path').title + document.getElementById('resultav').value).split('video/')[1].split(';')[0].split(',')[0]) == -1) {
vext='.' + document.getElementById('resultav').value.split('video/')[1].split(';')[0].split(',')[0];
document.getElementById('myaltin').value=document.getElementById('myaltin').value.split('.')[0] + vext;
document.getElementById('becomes').value=document.getElementById('becomes').value.split('.')[0] + vext;
}
}
lastvidc=document.getElementById('resultav').value;
document.getElementById('resultav').title='rework';
document.getElementById('mysubp').click();
setTimeout(function(){
if (1 == 1) {
document.getElementById('divvid').innerHTML=\"<video id=myinvideo style=width:95%; controls><source id=myinsource type='video/\" + vext.substring(1) + \"' src='\" + document.getElementById('resultav').value + \"'></source></video>\";
} else {
document.getElementById('myinsource').src=document.getElementById('resultav').value;
}
}, 2000);
//setTimeout(function(){
//document.getElementById('resultav').value='';
//}, 20000);
//alert(lastvidc);
setTimeout(lookfor, 23000);
return '';
}
setTimeout(lookfor, 3000);
return '';
}
}
setTimeout(lookfor, 3000);
return '';
}

setTimeout(lookfor, 3000);

“; ?>

… and then arrange the /tmp/ placed temporary video data via …

<?php

if (isset($_POST['browsed']) && isset($_POST['becomes'])) {
$fgccont='';
//file_put_contents('xzm.xzm', '1');
$outtmpfile=str_replace('+',' ',urldecode($_POST['becomes']));
//file_put_contents('xzm2.xzm2', $outtmpfile);
$outext=explode('.', $outtmpfile)[-1 + sizeof(explode('.', $outtmpfile))];
//file_put_contents('xzm3.xzm3', str_replace(' ','+',urldecode($_POST['browsed'])));
if (strpos(('xwq' . $_POST['browsed']), 'xwqdata') !== false) {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), base64_decode(explode(";base64,", str_replace(' ','+',urldecode($_POST['browsed'])))[1]));
} else if (strpos(('xwq' . strtolower($_POST['browsed'])), 'xwqhttps') !== false) {
$fgccont=file_get_contents('http' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),5));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower($_POST['browsed'])), 'xwqhttp') !== false) {
$fgccont=file_get_contents('http' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),4));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower(str_replace('+',' ',urldecode($_POST['browsed'])))), 'xwq//') !== false) {
$fgccont=file_get_contents('http:' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),0));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (strpos(('xwq' . strtolower(str_replace('+',' ',urldecode($_POST['browsed'])))), 'xwqwww.') !== false) {
$fgccont=file_get_contents('http://' . substr(str_replace('+',' ',urldecode($_POST['browsed'])),0));
if (trim($fgccont) != '') {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), $fgccont);
}
} else if (file_exists(str_replace('+',' ',urldecode($_POST['browsed'])))) {
file_put_contents(str_replace('+',' ',urldecode($_POST['becomes'])), file_get_contents(str_replace('+',' ',urldecode($_POST['browsed']))));
}
//file_put_contents('xzm4.xzm4', explode(";base64,", str_replace(' ','+',urldecode($_POST['browsed'])))[1]);
exit;
}

?>

… all the while being helped out by a tweaked macos_ffmpeg_convert.php works Ffmpeg Converter Tool PHP web application helper to our changed second draft of Your Own Ffmpeg Video Changes, which can be that much more useful in a new way in the AlmaLinux web server environment.


Previous relevant Ffmpeg User Defined Video Editing Tutorial is shown below.

Ffmpeg User Defined Video Editing Tutorial

Ffmpeg User Defined Video Editing Tutorial

Today we’re combining video contents from …

  • yesterday’s Ffmpeg Helps iPhone Video to YouTube Tutorial … with …
  • our newly created public interface to ffmpeg with the “soon to be DNS version of rjmprogramming.com.au … but not yet” AlmaLinux Apache/PHP/MySql web server install we talked about at Ffmpeg Install and Public Face Tutorial … and …
  • IP address redirecting, as needed, ifconfig (via PHP shell_exec and $_SERVER[‘SERVER_ADDR’]) based logic …
    <?php

    $whereplace=shell_exec("ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'");
    if (strpos(($whereplace . ' ' . $_SERVER['SERVER_ADDR']), '65.254.92.213') !== false) {
    $sv='/usr/bin/ffmpeg';
    header('Location: https://65.254.95.247/PHP/tmp_ffmpeg.php'); //$smallpath='https://65.254.95.247/PHP/'; //header('Location: https://65.254.95.247/PHP/tmp_ffmpeg.php');
    exit; //exit;
    }

    ?>
    … we talked about at AlmaLinux Landing Page WordPress Content Update Solution Tutorial … as well as …
  • user definable form navigation … using …
  • optional dropdown ideas incorporating ideas from Sepia Video via ffmpeg Primer Tutorial … and using …
  • temporary storage places to place output video … and making use of …
  • soft links regarding URLs we talked about at Linux Web Server Soft Link URL Tutorial (saving us having to use ‘data:video/mp4;base64,’ . base64_encode(file_get_contents(trim($endout))) style PHP interventions (which were testing friendships))

… to start down this road towards public facing ffmpeg video editing around here (which we have been hankering for for several years now).

In this first draft of Your Own Ffmpeg Video Changes (via command line ffmpeg) we’re really buttoning down (via not allowing the forward slash character in amongst the user defined ffmpeg command innards) what happens regarding …

  • output video file source location … and …
  • input video file source …

… but who knows what the future holds?!


Previous relevant Ffmpeg Helps iPhone Video to YouTube Tutorial is shown below.

Ffmpeg Helps iPhone Video to YouTube Tutorial

Ffmpeg Helps iPhone Video to YouTube Tutorial

Today we recorded a video looking out from Govetts Leap, Blackheath, here in the Blue Mountains. We captured it via the Camera app on an iPhone via its Video option.

Nineteen seconds long, to share to this MacBook Air we needed AirDrop, the size of it precluding us from using the Photo app’s Mail sharing option.

And that’s where we wanted to use the great ffmpeg in an optimal way to create a video that we could upload to YouTube. In this, we arrived at this excellent link getting us to try …


ffmpeg -i govetts_leap.MOV -c:v libx264 -preset slow -crf 18 -vf scale=out_color_matrix=bt709 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -c:a aac -ar 48000 -ac 2 -b:a 320k -profile:v high -level 4.0 -bf 2 -coder 1 -pix_fmt yuv420p -b:v 10M -threads 4 -cpu-used 0 -r 30 -g 15 -movflags +faststart govetts_leap.mp4

… with success. Checking with this other excellent link, thanks, we were comforted that they would have recommended an output mp4 file format as well, it seems …

If this was interesting you may be interested in 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, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , | Leave a comment