Migration Assistant on macOS Peer to Peer Tutorial

Migration Assistant on macOS Peer to Peer Tutorial

Migration Assistant on macOS Peer to Peer Tutorial

Another triennial, another macOS Migration Assistant (a desktop app in the Application folder’s Utilities folder) job to a MacBook Air with macOS Sonoma, further to Migration Assistant on macOS Primer Tutorial of the previous triennial.

We go …

  • “Peer to Peer” … with the migration … asking …
  • both Macs should share the same WiFi network (established by a screen earlier on to the goings on with today’s animated GIF presentation (where we tried a little “standing on our head” at one point, and which gave us an interesting perspective on life))) … meaning it amounts to an …
  • old Hard Disk to new Hard Disk migration (or copy) … best to have power to both Macs

Phew! Very easy to envisage and understand, and a great way to go with this task, thanks Apple! And don’t be alarmed by the initial 8-10 hour estimates of the time it will take. If it’s like our situation, it ended up maybe even less than one hour to perform!

If you have a Time Machine backup of the old Mac, that is an alternative input approach for a Mac to Mac migration.


Previous relevant Migration Assistant on macOS Primer Tutorial is shown below.

Migration Assistant on macOS Primer Tutorial

Migration Assistant on macOS Primer Tutorial

Setting up the software for new devices, including laptops, is sometimes motivated by the idea that the new computer should be as close as possible to being a clone of the other. This (data) “copy” operation is often referred to as “migration”.

Here, underlying operating systems mean more than brands, and so an Apple iPad (using iOS operating system) cannot be involved with a “migration” involving an Apple MacBook Air (using macOS operating system).

But an Apple MacBook Pro (using macOS operating system) can be involved with a “migration” involving an Apple MacBook Air (using macOS operating system), as we wish to do today, and we are going to try the …


Application -> Utilities

… “Migration Assistant” desktop application, which can work with the following “data conduits” …

  • both macOS devices sharing the same WiFi connection
  • two macOS devices are connected via an Ethernet cable
  • two macOS devices are connected via a USB lead
  • new macOS device imports data via a Time Machine backup off the other macOS device

… our method of choice being “both macOS devices sharing the same WiFi connection”. These modes of use can occur during a “Setup Assistant” session, as we do, or later. You can see this demonstrated with today’s video presentation


Previous relevant Apple iPad to New iPad Bluetooth Assisted Setup Tutorial is shown below.

Apple iPad to New iPad Bluetooth Assisted Setup Tutorial

Apple iPad to New iPad Bluetooth Assisted Setup Tutorial

As with the install qualities bluetooth helped out with during Apple TV Setup via WiFi and Bluetooth Tutorial, the other day we had occasion to setup a new iPad (preferably the same as an ailing old iPad) and, again, bluetooth came to the rescue making an Apple install or setup a very easy and enjoyable experience.

For more than 90% of the setup, including the absorption of a myriad of app installs and password rememberings, the simple steps of …

  1. hold the old iPad near the new iPad … and …
  2. patience (while bluetooth assisted install takes place)

… were all that was required to get up and going with the new iPad in about fifteen minutes from unwrapping! Cute, huh?!


Previous relevant Apple TV Setup via WiFi and Bluetooth Tutorial is shown below.

Apple iPad to New iPad Bluetooth Assisted Setup Tutorial

Apple iPad to New iPad Bluetooth Assisted Setup Tutorial

As with the install qualities bluetooth helped out with during Apple TV Setup via WiFi and Bluetooth Tutorial, the other day we had occasion to setup a new iPad (preferably the same as an ailing old iPad) and, again, bluetooth came to the rescue making an Apple install or setup a very easy and enjoyable experience.

For more than 90% of the setup, including the absorption of a myriad of app installs and password rememberings, the simple steps of …

  1. hold the old iPad near the new iPad … and …
  2. patience (while bluetooth assisted install takes place)

… were all that was required to get up and going with the new iPad in about fifteen minutes from unwrapping! Cute, huh?!


Previous relevant Apple TV Setup via WiFi and Bluetooth Tutorial is shown below.

Apple TV Setup via WiFi and Bluetooth Tutorial

Apple TV Setup via WiFi and Bluetooth Tutorial

We’re following up on the previous Apple TV Primer Tutorial with an upgrade because it is far more functional today, with its live television options (doing away with the need for television aerials for live streaming alternative), and we want to admire the Apple TV setup’s adroitness combining …

  • WiFi … and …
  • Bluetooth

… those two “giants” of modern personal computing networking functionality.

Those two appearing together all the time in Settings scenarios, we’ve often wondered how best to combine their talents, and the recent Apple TV version’s setup used them effectively (though optionally) to our minds.

At a certain point in the setup a choice that could make use of WiFi and Bluetooth together saved us having to remember Apple ID passwords and other such matters. At this point you could bring your other Apple device up close to the Apple TV device during the setup and arrange that Bluetooth was on, and it proceeded as if to suck the useful setting data out of the iPad device we offered up to the “Apple TV God”.

Very savvy indeed, and take a look at some Apple TV stream of consciousness here.

Did you know?

Do you like the jiggle? Let me explain. In iOS land you can delete mobile apps, effectively, by holding a touch down for a while, and waiting for all the icons to jiggle, and (re)touch any you want to delete. Well, the Apple TV operating system can work the same way. Also the same mobile app Install and Open arrangements, so the setup will be familiar to many, am sure.


Previous relevant Apple TV Primer Tutorial is shown below.

Apple TV Primer Tutorial

Apple TV Primer Tutorial

Do you own Apple devices like iPads and iPhones? Do you have a home WiFi wireless router? And do you have a reasonable modern television, or other home-theater device?

Three yes (or yes, no, yes might still work (with AirPlay) on reading here), here, and if you don’t already (have it and working), you might be interested in a product called Apple TV, a hardware product consisting of a “box” and a remote control.

With Apple TV, whatever you can do with video, and/or streaming services, on the iPad or iPhone can often be “projected” (or (Apple says) “mirrored”) onto that much bigger television screen, so that a presentation or piece of entertainment can be shared with others.

The setup is easy, as you can see from this link from Apple …

To start over at any time, unplug your device from power, then plug back in.

  1. Plug into power. Plug your Apple TV into power. …
  2. Connect to your home-theater devices. … with an HDMI cable …
  3. Turn on your television to find the setup screen. …
  4. Connect your remote. …
  5. Pick language settings. …
  6. Choose how to finish setup.

Much more amazing than that “old days” feeling of a Windows desktop being projected onto multiple screens at once!

Today’s tutorial picture shows Apple TV in action around our way.

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


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

Google Chart Gantt Chart Revisit Tutorial

Google Chart Gantt Chart Revisit Tutorial

Google Chart Gantt Chart Revisit Tutorial

When you depend on others for help, as we do here … a lot (thanks, everybody) … if you don’t revisit software using, for example, Google Charts, it can become squidgyware?! We used to reference Yahoo YUI widgets, especially regarding their calendar widget … and … well, yes, class … yes, Henry

Gantt Charts …

  1. do not grow on trees
  2. do not reference dates … which can grow on trees
  3. never take prisoners

… thanks for your grisly, but no doubt accurate … and very precise and detailed offering … 3 points to Gryffindor!

Yes, we based the Gantt Chart PHP logic on, probably the latest Google Chart PHP logic we’d tackled just previous, which probably used Yahoo YUI calendar widgets. Not a problem at the time … but time moves on. Yes, Henry you have a canary … sorry, caveat … yes, go on …

  1. Gantt Charts never move on

… the class gets the picture now … sorry we proved that for a while …

… we can’t gantt …

… but in our defence?

So, what did we relearn from our revisit to our inhouse Gantt Chart interfacer we talked about at Google Chart Gantt Chart Primer Tutorial?

  1. keep thinking simple … if you know no better
  2. the web browser web inspectors are your best debugging tool

It panned out that just one line of code was stopping us. One check before that codeline, and things starting working, even though there was lots more Yahoo YUI Calendar widget code to confuse us. We’d have been faster if we’d have taken more notice of adage 1 above!

So feel free to, hopefully, now, get somewhere trying the changed gantt_chart.php PHP coded inhouse Google Chart Gantt Chart interfacer.


Previous relevant Google Chart Gantt Chart Primer Tutorial is shown below.

Google Chart Gantt Chart Primer Tutorial

Google Chart Gantt Chart Primer Tutorial

Seems a fair time back we were discussing the ‘select’ event in relation to Google Charts functionality, but probably it isn’t. And perhaps it was a fair while back, but maybe it wasn’t, that Google and its Charts team introduced a new chart called the Gantt Chart, which a lot of people out there will know well, or less well, as a Project Management tool.

What can a Gantt Chart help with? Not looking anything up here (but you might) we think the Gantt Chart is great for setting deadlines and to turn up with in meetings focussed on outcomes (more so than incomes … chortle, chortle).

Gantt Charts …

  1. establish date ranges for when tasks (or activities) should start and when they should complete
  2. allow for estimates of task “percentage achieved”
  3. define dependencies, as in, “does this task depend on the completion (or some other criteria) of another task”

Okay, so we are in the “when” of life, linking to other aspects like “why” or “how” or “where” perhaps. This means there are synergies with …

  • Calendar Chart
  • Timeline Chart

… as we last were talking about with Google Chart Select Event Calendar Timeline Post Tutorial as shown below … and so, in our business logic ‘select’ event logic, we mention conversions to these other chart types. Along the way we got great help from this very useful link, so, thanks.

Software wise our new Google Chart Gantt Chart integration involved …

  • gantt_chart.php
  • csv.php is the changed CSV spreadsheet export functionality supervised PHP programming source code as per changes (to cater for spreadsheet CSV exports involving this type of date data types)

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Gantt Charts information … via Google.

This extra ‘select’ event functionality, available via the suffix “&onclick=y” applied to the Google Chart Gantt Chart title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live run for …

Stop Press

It pays to stay informed of changes, here on 6th October 2016. At Google Charts, the “visualization” call has changed and we’ve changed accordingly as per gantt_chart.php is the changed PHP programming source code as per changes. We apologize for this “outage” on this Google Chart … for how long …. we’re not sure … oops.


Previous relevant Google Chart Select Event Calendar Timeline Post Tutorial is shown below.

Google Chart Select Event Calendar Timeline Post Tutorial

Google Chart Select Event Calendar Timeline Post Tutorial

With our Google Graphs API, or Google Chart Tools, web and mobile applications changes today, as with WordPress 4.1.1’s Google Chart Select Event Calendar Timeline Post Tutorial, we chip away at a useful generic improvement. We hook into the PHP server language strength of allowing the POST method processing of HTML form data, to get around the URL “GET” (method) length restriction all web servers have, usually at about 2000 characters (we recommend the following background reading regarding this) … though with our web server it seems to be a smaller limit … anyway. Our guinea pigs today are the Google Charts Calendar Chart and its relationship with the Timeline Chart, following in from yesterday’s Google Chart Select Event Calendar Timeline Trend Tutorial as shown below, we are, again, talking about tools to monitor trends over time, allowing for onclick (or Google Chart “select”) functionality to be added for … except that today we have it working for quite a few more date “data” values …

  • Calendar Chart (and its synergies with)
  • Timeline Chart (for trend analysis, perhaps)

So we offer a conversion from Calendar Chart to Timeline Chart, at times after when the user has selected their second calendar date to “select”. The opposite way around, with the Timeline Chart, we allow conversion to a Calendar Chart with any one “select” event.

These Google Chart Calendar and Timeline Chart changes, with their generic “readiness” aspects, involved …

  • calendar_chart.php is the changed PHP programming source code as per changes
  • timeline_chart.php is the changed PHP programming source code as per changes
  • csv.php is the changed CSV spreadsheet export functionality supervised PHP programming source code as per changes (to cater for spreadsheet CSV exports involving date data types)
  • gchartgen.js is the changed Javascript programming source code as per changes … generic Javascript involving our new …

    function iftoobig(urlin) {
    if (eval(urlin.length) < 1000) { // vs 2000
    return urlin;
    } else {
    var dss, iy, ij, qns, qname='', qval='', newfbit='';
    var ournewf = document.getElementById('postform');
    var ourbae = document.getElementById('bitsatend');
    if (ourbae != null) {
    var qparts=urlin.split('?');
    if (eval(qparts.length) == 2) {
    var aparts=qparts[1].split('&');
    if (ournewf == null) {
    var ds=urlin.split('&data');
    var qp=ds[0];
    if (eval(ds.length) > 1) {
    for (iy=1; iy<eval(ds.length); iy++) {
    dss=ds[iy].indexOf('&');
    if (dss != -1) qp+=ds[iy].substring(dss);
    }
    }
    if (1 == 2) newfbit="<form style='display:none;' id='postform' method='POST' action='" + qparts[0] + "'>"; // "</form>";
    newfbit="<form style='display:none;' id='postform' method='POST' action='" + qp + "'>"; // "</form>";
    for (ij=0; ij<aparts.length; ij++) {
    qns=aparts[ij].split('=');
    newfbit+='<input type="hidden" name="' + qns[0] + '" value="' + (qns[1]) + '"></input>';
    }
    newfbit+='<input type="submit" value="Post Long Values"></input></form>';
    ourbae.innerHTML+=newfbit;
    ournewf = document.getElementById('postform');
    ournewf.submit();
    } else {
    for (ij=0; ij<aparts.length; ij++) {
    qns=aparts[ij].split('=');
    newfbit+='<input type="hidden" name="' + qns[0] + '" value="' + (qns[1]) + '"></input>';
    }
    newfbit+='<input type="submit" value="Post Long Values"></input>';
    ournewf.innerHTML=newfbit;
    ournewf.submit();
    }
    } else {
    return urlin;
    }
    return '#';
    } else {
    return urlin;
    }
    }
    }

We think ideas like this can help with time based trend analysis, and we may be adding sophistication to this over time, in addition to today’s “robustness” push.

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Calendar Chart information … via Google.
Link to Google Chart Tools Timeline Chart information … via Google.

We’d like to thank Trading Economics for the interesting U.S. Housing Starts (in 2015) data.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Calendar and Timeline Chart titles, flow on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live run for …


Previous relevant Google Chart Select Event Calendar Timeline Trend Tutorial is shown below.

Google Chart Select Event Calendar Timeline Trend Tutorial

Google Chart Select Event Calendar Timeline Trend Tutorial

Our Google Graphs API, or Google Chart Tools, web and mobile applications changes today are specific, so far, to the Google Charts Calendar Chart and its relationship with the Timeline Chart, and, as for yesterday’s Google Chart Select Event Geo Pie Trend Tutorial as shown below, we are talking about tools to monitor trends over time, allowing for onclick (or Google Chart “select”) functionality to be added for …

  • Calendar Chart (and its synergies with)
  • Timeline Chart (for trend analysis, perhaps)

So we offer a conversion from Calendar Chart to Timeline Chart, at times after when the user has selected their second calendar date to “select”. The opposite way around, with the Timeline Chart, we allow conversion to a Calendar Chart with any one “select” event.

These Google Chart Calendar and Timeline Chart changes involved …

We think ideas like this can help with trend analysis, and we may be adding sophistication to this over time.

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Calendar Chart information … via Google.
Link to Google Chart Tools Timeline Chart information … via Google.

We’d like to thank Trading Economics for the interesting U.S. Housing Starts (in 2015) data.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Calendar and Timeline Chart titles, flow on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live run for …


Previous relevant Google Chart Select Event Geo Pie Trend Tutorial is shown below.

Google Chart Select Event Geo Pie Trend Tutorial

Google Chart Select Event Geo Pie Trend Tutorial

Our Google Graphs API, or Google Chart Tools, web and mobile applications changes today are specific, so far, to the Google Charts Geo Chart and its relationship with the Pie Chart and Pie Chart Differences (really specifically), as intimated in yesterday’s Google Chart Onclick Pie Chart Differences Tutorial as shown below, allowing for onclick functionality to be added for …

  • Geo Chart (and its synergies with)
  • Pie Chart (data wise) and Pie Chart Differences (for trend analysis, perhaps)

So we offer a conversion from Geo Chart to Pie Chart, and Pie Chart Differences, when the Geo Chart data has two numerical data types defined, but we’ve baulked at the likelihood of the reverse being very applicable.

These Google Chart Geo and Pie Chart changes involved …

We think ideas like this can help with trend analysis, and we may be adding sophistication to this over time.

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Geo Chart information … via Google.
Link to Google Chart Tools Pie Chart information … via Google.
Link to Google Chart Tools Diff Charts information … via Google.

We’d like to thank Worldometers for the interesting population data.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Geo and Pie and Pie Differences Chart titles, flow on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live run for …


Previous relevant Google Chart Onclick Pie Chart Differences Tutorial is shown below.

Google Chart Onclick Pie Chart Differences Tutorial

Google Chart Onclick Pie Chart Differences Tutorial

Our Google Graphs API, or Google Chart Tools, web and mobile applications changes today are specific, so far, to the Google Charts Pie Chart Differences, building on recent work such as yesterday’s Google Chart Select Event Geo Pie Synergy Tutorial as shown below, allowing for onclick functionality to be added for …

  • Pie Chart Differences

… in the sense that there is a known limitation with this chart using the preferred Google Chart “select” event.

You will understand from this, that the mechanisms by which Google Charts works differs from chart to chart, and, especially regarding event programming, and the display options, every chart should be considered to be “a different kettle of fish”.

Tomorrow we want to relate this chart in a more useful way to the Geo Chart, but that is (probably) for tomorrow.

In the meantime these Google Chart Pie Chart Difference changes involved …

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Diff Charts information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Pie Chart Differences title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live run for …


Previous relevant Google Chart Select Event Geo Pie Synergy Tutorial is shown below.

Google Chart Select Event Geo Pie Synergy Tutorial

Google Chart Select Event Geo Pie Synergy Tutorial

Our Google Graphs API, or Google Chart Tools, web and mobile applications changes today are specific, so far, to the Google Charts Geo Chart and its relationship with the Pie Chart, building on recent work such as yesterday’s Google Chart Select Event Map Overlay Lines Tutorial as shown below, allowing for onclick functionality to be added for …

  • Geo Chart (and its synergies with)
  • Pie Chart (data wise)

So we offer a conversion from Geo Chart to Pie Chart, but we’ve baulked at the likelihood of the reverse being very applicable.

These Google Chart Geo and Pie Chart changes involved …

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Geo Chart information … via Google.
Link to Google Chart Tools Pie Chart information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Geo Chart title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live run for …


Previous relevant Google Chart Select Event Map Overlay Lines Tutorial is shown below.

Google Chart Select Event Map Overlay Lines Tutorial

Google Chart Select Event Map Overlay Lines Tutorial

Our Google Graphs API, or Google Chart Tools, web and mobile applications changes today are specific, so far, to the Google Charts Map Chart, building on yesterday’s Google Chart Select Event Cache Issue Tutorial as shown below, allowing for the concept of drawing link lines overlayed onto the …

  • Map Chart

… adding to our …

The CSS “overlay” usual suspects coming into play were …

And what function do we allow once the SVG line is there, overlayed, in place, ready to be hovered over or clicked? We calculate a crow flying distance via …


function great_circle_distance(talis, gnolis, latis, longis) {
var ourdist=0.0;
var rgnol=eval((gnolis) * Math.PI / 180.0);
var rtal=eval((talis) * Math.PI / 180.0);
var rlong=eval((longis) * Math.PI / 180.0);
var rlat=eval((latis) * Math.PI / 180.0);
var deltalong = Math.abs(eval(((gnolis)-(longis)) * Math.PI / 180.0));
var acof = eval(Math.sin(rtal) * Math.sin(rlat)) + (Math.cos(rtal) * Math.cos(rlat) * Math.cos(deltalong)); // via http://en.wikipedia.org/wiki/Great-circle_distance ... thanks
ourdist = eval(Math.round((Math.acos(acof) * 6371000.0) + 0.00001) * 100) / 100;
return ourdist;
}

These Google Chart Map Chart changes involved …

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Map Chart information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Map title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live run for …

and/or

See this functionality in action applied to two of our recent blog postings …

  1. HTML/Javascript Where Does It Get Me To Primer Tutorial live run uses HTML/Javascript programming source code distance_from.html (changed as per distance_from.html for overlay line functionality)
  2. PHP Modularization for Lighthouses in Australia Tutorial live run uses PHP programming source code http://www.rjmprogramming.com.au/PHP/australian_lighthouses.php (changed as per distance_from.html for overlay line functionality)

Previous relevant Google Chart Select Event Cache Issue Tutorial is shown below.

Google Chart Select Event Cache Issue Tutorial

Google Chart Select Event Cache Issue Tutorial

We’re still trying for yet more “genericity” with our Google Graphs API, or Google Chart Tools, web and mobile applications today, building on yesterday’s Google Chart Select Event Email Integration Tutorial as shown below, with integration involving email, yesterday more for non-mobile usage and today, more for mobile platform usage, that we first tried on our recent “guinea pig” “guinea fowl” (so yesterday) “guinea baboon” functionalities (of recent times) …

  • Area Chart
  • Bar Chart (and Bar Chart Differences)
  • Column Chart (and Column Chart Differences)
  • Line Chart
  • Map Chart
  • Pie Chart

It probably comes as no surprise that chart data can be a great conversation starter for meetings or online discussions conducted via email, for example. They say “a picture tells a thousand words” … MMM look at that pie chart over yonder … see … three thousand words … chortle, chortle.

Do you remember yesterday? …

We use mailto links to direct the user to their default client mail supervisors to make all this happen. You will find, with PHP, that you can email without this client email via the use of the mail method.

… Well, our concentration on mailto (that works fine on non-mobile platforms) needed to be balanced with some mobile platform consideration that uses that PHP mail method, so as not to navigate too far away in our iOS app’s WebView.

And we did some work with Google Chart Pie Charts today to add “select” event functionality, and to try to stop it using the cache, as we want the iOS app reflect changes we make to things, and be able to let the iOS app user recover from an unforseen problem exacerbated by the return to a bad caching scenario.

We found good advice about this cache issue at this useful link, so, thanks. You may read from this page that there is an HTML meta tag approach to this, but we prefer a PHP approach, and use, up the top of the PHP the code snippet …


header( "Expires: Mon, 20 Dec 1998 01:00:00 GMT" );
header( "Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT" );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Cache-Control: post-check=0, pre-check=0', false );
header( 'Pragma: no-cache' );

… you will find up the top of the PHP pie_chart.php programming source code.

These Google Chart Pie/Line/Bar/Area/Column/Map Chart changes involved …

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Area Chart information … via Google.
Link to Google Chart Tools Bar Chart information … via Google.
Link to Google Chart Tools Column Chart information … via Google.
Link to Google Chart Tools Line Chart information … via Google.
Link to Google Chart Tools Map Chart information … via Google.
Link to Google Chart Tools Pie Chart information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Area and Bar and Column and Line and Map and Pie Chart title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live runs for …

No guinea pigs (nor guinea fowl, nor guinea baboons) were harmed in the making of this blog post. Honest, hen!


Previous relevant Google Chart Select Event Email Integration Tutorial is shown below.

Google Chart Select Event Email Integration Tutorial

Google Chart Select Event Email Integration Tutorial

We’re still trying for yet more “genericity” with our Google Graphs API, or Google Chart Tools, web and mobile applications today (as with WordPress 4.1.1’s Google Chart Select Event Email Integration Tutorial), building on yesterday’s Google Chart Select Event Spreadsheet Integration Tutorial as shown below, with integration involving email, that we are first trying on our recent “guinea pig” “guinea fowl” functionalities (of recent times) …

  • Area Chart
  • Bar Chart (and Bar Chart Differences)
  • Column Chart (and Column Chart Differences)
  • Line Chart
  • Map Chart

It probably comes as no surprise that chart data can be a great conversation starter for meetings or online discussions conducted via email, for example. They say “a picture tells a thousand words” so imagine how many a “chart” tells?!

So today we make use of the fact that for small amounts of data the Google Charts can be shared via the emailing of a URL link as the body of an email. For larger amounts of data we may have to think some more into the future, though we’re half ready because …

  1. we are using a server side language, PHP … which means that …
  2. the $_POST[] mentions in our PHP code can eventually be put to good use here, down the track

These Google Chart Line/Bar/Area/Column/Map Chart changes involved …

We use mailto links to direct the user to their default client mail supervisors to make all this happen. You will find, with PHP, that you can email without this client email via the use of the mail method.

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Area Chart information … via Google.
Link to Google Chart Tools Bar Chart information … via Google.
Link to Google Chart Tools Column Chart information … via Google.
Link to Google Chart Tools Line Chart information … via Google.
Link to Google Chart Tools Map Chart information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Area and Bar and Column and Line and Map Chart title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live runs for …

No guinea pigs (nor guinea fowl) were harmed in the making of this blog post. Honest, hen!


Previous relevant Google Chart Select Event Spreadsheet Integration Tutorial is shown below.

Google Chart Select Event Spreadsheet Integration Tutorial

Google Chart Select Event Spreadsheet Integration Tutorial

We’re trying more “genericity” with our Google Graphs API, or Google Chart Tools, web and mobile applications today, building on yesterday’s Google Chart Line/Bar/Area/Column Select Event Tutorial, as shown below, with integration involving spreadsheets, that we are first trying on our recent “guinea pig” functionalities (of recent times) …

  • Area Chart
  • Bar Chart (and Bar Chart Differences)
  • Column Chart (and Column Chart Differences)
  • Line Chart
  • Map Chart

It probably comes as no surprise that chart data can be turned into spreadsheet data, especially if you have ever spent much time in those great spreadsheet applications like Microsoft Office’s Excel, where there are various pathways to display charts from your spreadsheet data. So, today, we just turn that thought around a bit, and use Comma Separated Value (CSV) files as a conduit to be able to convert our chart data into a spreadsheet. We leave it up to whatever is the default application you have to open CSV files … it doesn’t even have to be a spreadsheet application as such, but our applications today offer a downloading capability to get the spreadsheet (CSV) data down to your hard disk (or perhaps midair solutions like Google Docs).

So we see this as a good candidate as a generic Google Chart “select” event tool for users looking to integrate with spreadsheet tools.

These Google Chart Line/Bar/Area/Column/Map Chart changes involved …

You’ll see with the PHP code that a crucial technique with today’s work, which involves huge use of PHP’s header method, revolves around the use of the PHP include statement (as well as its closely related require statement). What we “included” in the PHP of above was PHP source code csv.php to aid with constructing the PHP header statements necessary to make the functionality happen. We’d like to thank this very useful link for help here.

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Area Chart information … via Google.
Link to Google Chart Tools Bar Chart information … via Google.
Link to Google Chart Tools Column Chart information … via Google.
Link to Google Chart Tools Line Chart information … via Google.
Link to Google Chart Tools Map Chart information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Area and Bar and Column and Line and Map Chart title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live runs for …

No guinea pigs were harmed in the making of this blog post. Honest, guv’!


Previous relevant Google Chart Line/Bar/Area/Column Select Event Tutorial is shown below.

Google Chart Line/Bar/Area/Column Select Event Tutorial

Google Chart Line/Bar/Area/Column Select Event Tutorial

Today we continue on (from yesterday’s Google Chart Line and Map Chart Select Event Prompt Tutorial) with more integration involving Google Graphs API, or Google Chart Tools, and its “select” event (like onclick) involving …

  • Area Chart
  • Bar Chart (and Bar Chart Differences)
  • Column Chart (and Column Chart Differences)
  • Line Chart

… involve similar data requirements, so we can integrate by offering a redraw of the Google Chart you are currently in, to another type of Google Chart in the list above, and allow this, as an additional “business logic” piece of functionality offered to users when they “click/touch” on the Google Chart, firing off the onclick (or Google Chart “select”) event.

This piece of functionality can be useful, even in terms of aesthetics, as some Google Charts display better than others depending on the density of the data set(s) displayed.

Along the way we also present to the user a moving average of values relevant to each data column of interest.

From yesterday, you may also recall that we can allow a redraw of one the Google Chart types as above (and for lots of others eventually) by allowing user amendment of the data.

And from the day before yesterday we outlined that first bit of “select” event business logic allowing the user to see the difference between values, on “click/touching” any one of them and on doing this firing the “select” event.

These Google Chart Line/Bar/Area/Column Chart changes involved …

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Area Chart information … via Google.
Link to Google Chart Tools Bar Chart information … via Google.
Link to Google Chart Tools Column Chart information … via Google.
Link to Google Chart Tools Line Chart information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Area and Bar and Column and Line Chart title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating your own emailable Google Chart live runs for …


Previous relevant Google Chart Line and Map Chart Select Event Prompt Tutorial is shown below.

Google Chart Line and Map Chart Select Event Prompt Tutorial

Google Chart Line and Map Chart Select Event Prompt Tutorial

Here is a tutorial that further reacquaints you, maybe, with the Google Graphs API, or Google Chart Tools, and its Line Chart functionality, last talked about at this blog with PHP/Javascript/HTML Google Chart Line Chart Tutorial as shown way below, and Map Chart, for its first mention and Google Chart Map Chart Select Event Primer Tutorial, for its last mention.

There is no magic relationship between these two chart types today, rather it is the case that they are the “guinea pigs” for “generic thoughts”.

“Generic” is a favourite word for what we try to achieve here, but it can be like “nirvana” for lots of reasons …

  • do you have a market for the investment you need to put in to push for “genericity”
  • in similar mind, does the project size make it worthwhile
  • is catering for all the web browser and application platforms allow for “genericity” anyway?

… in a big organization, such queries can progress quite nicely by using teams and having planning discussions and setting timelines and deadlines between project groups, but in smaller teams it can be the case of “seeing what problems” come up, to decide on the push for “genericity” with the product, down, eventually, to the level of deciding where “business logic” code should sit (ie. in a “library” or “called” piece of code, or otherwise). So, we’re trying some “generic” thoughts and using these two disparate Google Charts to see whether there is some onclick (ie. Google Charts “select” event, which you can read a lot about here … thanks, Google) logic that, in a business sense (because we like to think of onclick being really closely tied to “business logic”, the reason being, some user “clicked/touched” something, so you better present something heading towards specific interest, to do with business, when they do this.

And we think an approach would be to offer an onclick reworking of the data of a chart should they get to the “click/touch” stage with a chart. And we decided that it is not so bad to present this in an overall “one string” chance to change the chart, because, presumanly the user went through the whole rigmarole of answering questions to get this far, and by this stage will “get the hang” of what to do to make more sweeping changes by using this new functionality. Think, too, a “faster way to do things” presented to “advanced users” willing to give things a go (otherwise they wouldn’t still be reading?!) help to improve the UX (“user experience”) of the application, whether that be web or mobile or desktop or seascape (just checking you’re still awake).

And so, in practical terms, with these two charts, we’ve recently added onclick (Google Charts “select” event) Javascript alert and prompt boxes recently, respectively, for Line Charts and Map Charts. Well, today, we make them both Javascript prompt windows to offer this chance for the user to “reshape” their chart via “click/touch” chart control.

These Google Chart Line Chart and Map Chart changes involved …

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Line Chart information … via Google.
Link to Google Chart Tools Map Chart information … via Google.

This extra functionality, available via the suffix “&onclick=y” applied to the Google Chart Map Chart title, flows on directly to the iPad iOS App we created and talked about, last, with Xcode Swift iOS Application End Game Primer Tutorial.

So please try creating you own emailable Google Chart Line Chart here or Map Chart here.


Previous Previous relevant PHP/Javascript Google Chart Line Chart Select Event Tutorial is shown below.

PHP/Javascript Google Chart Line Chart Select Event Tutorial

PHP/Javascript Google Chart Line Chart Select Event Tutorial

Here is a tutorial that reacquaints you, perhaps, with the Google Graphs API, or Google Chart Tools, and its Line Chart functionality, first talked about at this blog with PHP/Javascript/HTML Google Chart Line Chart Tutorial as shown below.

Google Chart Tools provide a perfect way to visualize data on your website. From simple line charts to complex hierarchical tree maps, the chart galley provides a large number of well-designed chart types. Populating your data is easy using the provided client- and server-side tools.

The reason for the revisit concerns a push to make more use of the onclick “feeling” Google Chart “select” event, an event triggered when you click on a feature of, in this case, a Google Chart Line Chart that our web application helps you create.

Here is some PHP code in live action for this tutorial where you define your line chart characteristics and data, where am appending of “&onclick=y” to your line chart title means the additional “select” event functionality can kick in.

The “select” event functionality (which you can read a lot about here … thanks, Google) would be full of business logic and specific to how you want to use the chart, so it is a bit hard to pin down how you should use it, but in today’s tutorial picture you can see that in a Company Performance line chart showing Sales and Expenses if you click on a Sales figure for any given Year the “select” event business logic brings up a Javascript alert() box that informs the user of the Expenses for that same Year, along with the difference between Sales and Expenses. The logic is not tied down to the exact words “Sales” and “Expenses”, and it will work this out from what you entered in for this earlier on.

Some findings here led to some small changes to that generic Javascript behind the scenes of these Google Chart suite of web applications as well so, all told, the changes involved …

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Line Chart information … via Google.

So please try creating you own emailable Google Chart Line Chart here.


Previous relevant PHP/Javascript/HTML Google Chart Line Chart Tutorial is shown below.

PHP/Javascript/HTML Google Chart Line Chart Tutorial

PHP/Javascript/HTML Google Chart Line Chart Tutorial

Here is a tutorial that introduces you to Google Graphs API, or Google Chart Tools, and its Line Chart functionality.

Google Chart Tools provide a perfect way to visualize data on your website. From simple line charts to complex hierarchical tree maps, the chart galley provides a large number of well-designed chart types. Populating your data is easy using the provided client- and server-side tools.

Let’s see some PHP code in live action for this tutorial where you define your line chart characteristics and data.

Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Line Chart information … via Google.

Link to some downloadable PHP programming code … rename to line_chart.php.

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

Find Games Peer to Peer Tutorial

Find Games Peer to Peer Tutorial

Find Games Peer to Peer Tutorial

It wasn’t our initial intention, but on completion of the cloning aspects to …

  • sporning from the Find the Words game basis … cloning to a …
  • Finding the Numbers game

… as two distinct entities, we could piece them back together as a “more powerful combined unit” via pretty simple “peer to peer” dropdown (ie. select) element considerations.

And that can be the power of the dropdown, with its onchange event … it can be added to easily, and help with the control of webpage navigation thinking …

Find the Words dropdown new suboptions intervention


function modeize(ospan) {
var ihis=ospan.innerHTML.replace('<br> ',''), huhi=1;
var chcs=['', 'Names','Connectives'];
var rest='';
for (var ijk=0; ijk<chcs.length; ijk++) {
if (ihis.replace('Words','') != chcs[ijk]) {
rest+='<option value="' + chcs[ijk].replace('Words','') + ('">' + chcs[ijk] + '<').replace('"><', '">Words<') + '/option>';
huhi++;
}
}
rest+='';
huhi++;
rest+='';
huhi++;
rest+='';
huhi++;

if (ihis.indexOf('<') == -1) {
ospan.innerHTML='<select size=' + huhi + ' onclick="event.stopPropagation();" onchange="modesel(this,' + "'" + ospan.id + "'" + ');"><option value="' + ihis.replace('Words','') + ('">' + ihis + '<').replace('"><', '">Words<') + '/option>' + rest + '</select>';
}
}
Find the Words dropdown onchange event function intervention


function modesel(osel, ospanid) {
var anewurl='';
mode=osel.value;
if (mode != '' && mode.trim() == '') {
anewurl=document.URL.replace('_words.', '_numbers.').split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(mode.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + minwordlength + '&table=' + tabularize; // + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
location.href=anewurl;
} else if (mode.toLowerCase() == 'c') {
anewurl=document.URL.replace('_words.', '_numbers.').split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(mode.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + minwordlength + '&table=' + tabularize; // + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
location.href=anewurl;
}

document.getElementById(ospanid).innerHTML=(osel.value.trim() == '' ? 'Words' : osel.value.replace('Connectives', '<br> Connectives'));
}
Find the Numbers dropdown suboption additions intervention


var seloh='<select style="font-weight:bold;margin-right:40px;background-color:yellow;" id="selmode" onchange="changesel(this);" title="Modes of use for game"><option id=simpleopt value=""></option><option data-answer="" id="clueopt" value="c">Clues</option><option data-answer="" id="hclueopt" value="C">Harder</option><option value=" ">Words</option><option value="Names">Names</option><option value="Connectives">Connectives</option></select>';
Find the Numbers dropdown onchange event function intervention


function changesel(osel) {
var anewurl='';
defv=osel.value;
if (defv != '' && defv.trim() == '') {
anewurl=document.URL.replace('_numbers.', '_words.').split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(defv.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + eval(4 * minwordlength) + '&table=' + tabularize; // + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
location.href=anewurl;
} else if (defv.toLowerCase() == 'names') {
anewurl=document.URL.replace('_numbers.', '_words.').split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(defv.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + eval(4 * minwordlength) + '&table=' + tabularize; // + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
location.href=anewurl;
} else if (defv.toLowerCase() == 'connectives') {
anewurl=document.URL.replace('_numbers.', '_words.').split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(defv.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + eval(4 * minwordlength) + '&table=' + tabularize; // + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
location.href=anewurl;
}

if ((osel.value + ' ').substring(0,1).toLowerCase() == 'c') {
document.getElementById('sclue').style.display='inline';
document.getElementById('sclue').innerHTML='' + isithard('' + findings[eval(-1 + findings.length - thisq)]);
} else {
document.getElementById('sclue').style.display='none';
}
}

And so, onto the recent Find Number Game Clues Tutorial we have …

  • an original idea …
  • cloned into two …
  • conjoinable via dropdown suboptions with an “inhouse functionality” feeling, allowing the user to feel it can be a “one stop shop” for all the underlying functionality

What is “peer to peer” thinking? Well, in this case, it is the thinking that all 6 modes of use for the two Finding web applications have equal status, with “groupthink” design (reflected by the make up of the two dropdown elements involved, which both mention all 6 possibilities) rather than any “hierarchical” structure.

And so, see …

… either capable of being a parent “in name only” (to the other), presented again, for your perusal.


Previous relevant Find Number Game Clues Tutorial is shown below.

Find Number Game Clues Tutorial

Find Number Game Clues Tutorial

Onto the “cloning start” yesterday’s Find Number Game Cloning Tutorial gave us to our Find the Number game, today, we improve on …

  • its modes of play … adding to existant …
    1. find a computer decided upon number … with …
    2. find a number via a fairly simple clue … and …
    3. find a number via a pretty cryptic clue

    … and …

  • add a hierarchy to the scoring so that a down or up user answer is worth more and a diagonal answer is worth even mode and a reversed answer is also worth more regarding the scoring and the clue modes of use add to the scoring worth as well … so that

    score+=eval(eval('' + twowordstocheck[curri].length) * scorefactor);

    … codelines reflect the nuanced variable scorefactor starting as 1 and changed at various points, can bring to the game

… via …

Clue iframe helper HTML


<iframe onload="checkclue(this);" id=hclueif src='//www.rjmprogramming.com.au/Games/Battleshipsandcruisers/index2a.php?clue=' style=display:none;></iframe>
Helped out by this iframe onload event function


var seloh='<select style="font-weight:bold;margin-right:40px;background-color:yellow;" id="selmode" onchange="changesel(this);" title="Modes of use for game"><option id=simpleopt value=""></option><option data-answer="" id="clueopt" value="c">Clues</option><option data-answer="" id="hclueopt" value="C">Harder</option></select>';
var scorefactor=1;
var findings=[], clues=[], findlen=minwordlength, thisq=0, jthisq=0, kthisq=0, alreadydone=';000;', hardclue=['Find number '], longhardclue=[];

function checkclue(iois) {
//if (iois.src.indexOf('?isan=') != -1) { alert('Here'); }
if ((' ' + iois.src).slice(-6) == '?clue=') { return ''; }
var cnum='', ourabi='';
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
ourabi='' + aconto.body.innerHTML;
if (ourabi.indexOf('</p') != -1) {
if (kthisq == 0 && hardclue[0].indexOf('Find number ') == 0) {
cnum=('' + findings[eval(-1 + findings.length - kthisq)]);
cnum=cnum.substring(0,eval(-2 + eval('' + cnum.length))) + '00';
hardclue[0]='Find the number ' + cnum + ' + <font size=2>(' + ourabi.split('>')[1].split('</p')[0] + ')</font>';
longhardclue.push(hardclue[0]);
if (defv == 'C' && document.getElementById('sclue')) {
document.getElementById('sclue').innerHTML=hardclue[0];
}
//alert('0:' + hardclue[0]);
kthisq++;
if (eval(1 + kthisq) < eval(findings.length)) {
//document.title='' + kthisq + ' ' + findings[eval(-1 + findings.length - kthisq)] + '//www.rjmprogramming.com.au/Games/Battleshipsandcruisers/index2a.php?clue=' + findings[eval(-1 + findings.length - kthisq)] + '#' + kthisq;
document.getElementById('hclueif').src='//www.rjmprogramming.com.au/Games/Battleshipsandcruisers/index2a.php?clue=' + eval(findings[eval(-1 + findings.length - kthisq)] % 100);
}
} else {
cnum=('' + findings[eval(-1 + findings.length - kthisq)]);
cnum=cnum.substring(0,eval(-2 + eval('' + cnum.length))) + '00';
longhardclue.push('Find the number ' + cnum + ' + <font size=2>(' + ourabi.split('>')[1].split('</p')[0] + ')</font>');
//alert('1:' + 'Find the number ' + cnum + ' + (' + ourabi.split('>')[1].split('</p')[0] + ')');
kthisq++;
if (eval(1 + kthisq) < eval(findings.length)) {
//document.title='' + kthisq + ' ' + findings[eval(-1 + findings.length - kthisq)] + '//www.rjmprogramming.com.au/Games/Battleshipsandcruisers/index2a.php?clue=' + findings[eval(-1 + findings.length - kthisq)] + '#' + kthisq;
document.getElementById('hclueif').src='//www.rjmprogramming.com.au/Games/Battleshipsandcruisers/index2a.php?clue=' + eval(findings[eval(-1 + findings.length - kthisq)] % 100);
}
}
}
}
}
New Javascript helping out the new dropdown Mode of Use element created via function defval fleshing out of div id=clue innards


function defval(inidea) {
//alert(1);
var cluestr='';
var scoh='';
if (document.getElementById('clue').innerHTML == '') {
defv=mode;
scoh='<span style=display:none;background-color:lightblue; id=sclue>' + isithard('' + findings[eval(-1 + findings.length - thisq)]) + '</span>';
//alert('' + seloh.replace('></option>', '>' + inidea.replace(' ', '').replace('<br>', '') + '</option>'));
document.getElementById('clue').innerHTML=(seloh.replace('></option>', '>' + inidea.replace(' ', '').replace('<br>', '') + '</option>')).replace(' value="' + mode + '"', ' value="' + mode + '" selected') + '    ' + scoh;
//alert((seloh.replace('></option>', '>' + inidea.replace(' ', '').replace('<br>', '') + '</option>')).replace(' value="' + mode + '"', ' value="' + mode + '" selected') + '    ' + scoh);
document.getElementById('selmode').value=(mode + ' ').substring(0,1).trim();
document.getElementById('clueopt').setAttribute('data-answer', '' + findings[eval(-1 + findings.length - thisq)]);
document.getElementById('hclueopt').setAttribute('data-answer', '' + findings[eval(-1 + findings.length - thisq)]);
} else {
document.getElementById('simpleopt').innerText=inidea.replace(' ', '').replace('<br>', '');
document.getElementById('clueopt').setAttribute('data-answer', '' + findings[eval(-1 + findings.length - thisq)]);
document.getElementById('hclueopt').setAttribute('data-answer', '' + findings[eval(-1 + findings.length - thisq)]);
document.getElementById('selmode').value=defv;
document.getElementById('clue').innerHTML=document.getElementById('selmode').outerHTML;
if (document.getElementById('sclue')) {
scoh=document.getElementById('sclue').outerHTML + '';
}
}
if ((document.getElementById('selmode').value + ' ').substring(0,1).toLowerCase() == 'c' || defv.toLowerCase() == 'c') {
scoh='<span style=display:none; id=sclue>' + isithard('' + findings[eval(-1 + findings.length - thisq)]) + '</span>';
scoh=scoh.replace('none;', 'inline;');
cluestr=' Find number ' + document.getElementById('clueopt').getAttribute('data-answer');
if (document.getElementById('sclue')) {
document.getElementById('sclue').style.display='inline';
document.getElementById('sclue').innerHTML=cluestr;
document.getElementById('sclue').style.display='inline-block';
}
} else if (document.getElementById('sclue')) {
scoh=scoh.replace('inline;', 'none;');
document.getElementById('sclue').style.display='none';
}
//alert(cluestr);
document.getElementById('selmode').value=defv;
lastinidea=inidea;
return document.getElementById('selmode').outerHTML.replace(/\ selected/g,'').replace(' value="' + defv + '"', ' value="' + defv + '" selected') + '    ' + scoh;
}

function isithard(insimplecluepart) {
var outhardpart='Find number ' + insimplecluepart;
if (defv == 'C') {
modefactor=2;
outhardpart=hardclue[eval(-1 + hardclue.length)];
} else if (defv == 'c') {
modefactor=1;
if (eval(eval('' + insimplecluepart) % 10) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) * 1.3)) + ' - ' + ('' + eval(eval('' + insimplecluepart) * 0.3)) + ')';
} else if (eval(eval('' + insimplecluepart) % 9) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) * 2 / 9)) + ' + ' + ('' + eval(eval('' + insimplecluepart) * 7 / 9)) + ')';
} else if (eval(eval('' + insimplecluepart) % 8) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) * 3 / 8)) + ' + ' + ('' + eval(eval('' + insimplecluepart) * 5 / 8)) + ')';
} else if (eval(eval('' + insimplecluepart) % 7) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) * 13 / 7)) + ' - ' + ('' + eval(eval('' + insimplecluepart) * 6 / 7)) + ')';
} else if (eval(eval('' + insimplecluepart) % 6) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) / 3)) + ' x 3' + ')';
} else if (eval(eval('' + insimplecluepart) % 5) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) / 5)) + ' + ' + ('' + eval(eval('' + insimplecluepart) * 4 / 5)) + ')';
} else if (eval(eval('' + insimplecluepart) % 4) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) * 3)) + ' / 3' + ')';
} else if (eval(eval('' + insimplecluepart) % 3) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) / 3)) + ' + ' + ('' + eval(eval('' + insimplecluepart) * 2 / 3)) + ')';
} else if (eval(eval('' + insimplecluepart) % 2) == 0) {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) * 1.5)) + ' - ' + ('' + eval(eval('' + insimplecluepart) * 0.5)) + ')';
} else {
outhardpart='Find the number that equates to (' + ('' + eval(eval('' + insimplecluepart) * 3)) + ' - ' + ('' + eval(eval('' + insimplecluepart) * 2)) + ')';
}
} else {
modefactor=0;
}
return outhardpart;
}

function changesel(osel) {
defv=osel.value;
if ((osel.value + ' ').substring(0,1).toLowerCase() == 'c') {
document.getElementById('sclue').style.display='inline';
document.getElementById('sclue').innerHTML='' + isithard('' + findings[eval(-1 + findings.length - thisq)]);
} else {
document.getElementById('sclue').style.display='none';
}
}

… in a changed textarea_find_numbers.html Find the Numbers game for your perusal.


Previous relevant Find Number Game Cloning Tutorial is shown below.

Find Number Game Cloning Tutorial

Find Number Game Cloning Tutorial

Around here we seem to find more use, as far as cloning one web application into another goes, cloning a game into another form of that game, perhaps changing a single data concept or mode of use. Today’s cloning …

  • takes our recent Finding the English Words game web application as a cloning base … for …
  • a new Find the Numbers game web application

… the great thing about cloning often being the transfer of those more advanced sharing functionalities straight over, via the cloning process, into the new web application. We can’t say this cloning process can be “cloned”, but global substitutions often play a part, today’s …

  • calling for a new “clue based” instigator process … we start the ball rolling with a computer decided “ask” … replacing …
  • those English Word dictionary lookups

… so, in a way, simpler, in this first draft … but we plan for more drafts, and the scoring needs more sophistication in versions to come.

Anyway, further to the recent Find English Word Game Collaboration Tutorial “clone source” we have for you today a “how we got there” textarea_find_numbers.html Find the Numbers game you might like to try for youself.


Previous relevant Find English Word Game Collaboration Tutorial is shown below.

Find English Word Game Collaboration Tutorial

Find English Word Game Collaboration Tutorial

Collaboration, regarding games, is synonymous with “level playing field”, and that is a principle upheld with today’s introduction of sharing and collaboration functionality into our Find the Word game, and further to yesterday’s Find English Mobile Clicked Word Ends Game Tutorial.

As such, we need to pick “common denominators”, so to speak, and that is, as of recent times, to encourage the use of …

  • tabular mode of use … when sharing via email or SMS … rather than …
  • textarea selectionchange event mode of use

… in the sense that we don’t know the arrangements for an email or SMS recipient as to whether they’ll be reading the communication on a mobile or non-mobile platform.

Once a communication is sent, the letters presented will match, and to get the competitive juices flowing, we add a timer aspect to the scoring. Much of the change relates to catering for email and SMS hashtagging arrangements …


var mode=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('mode=')[1] ? (decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('mode=')[1].split('&')[0])) : '';
var tabularize=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('table=')[1] ? (decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('table=')[1].split('&')[0])) : 'Null';
var minwordlength=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('min=')[1] ? Math.min(3,eval(decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('min=')[1].split('&')[0]))) : 3;
var maxwordlength=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('max=')[1] ? eval(decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('max=')[1].split('&')[0])) : 15;
var numlettersacross=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('across=')[1] ? eval(decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('across=')[1].split('&')[0])) : (tabularize == 'Null' ? 50 : 80);
var numlettersdown=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('down=')[1] ? eval(decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('down=')[1].split('&')[0])) : 40;
var fontpixels=(location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('pixels=')[1] ? eval(decodeURIComponent((location.search + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').replace(/^\#/g,'&')).split('pixels=')[1].split('&')[0])) : 13;

var firstdate=new Date();
var seconddate=new Date();
var updatehowlong=false, jhis='';

if (('' + window.localStorage.getItem('findwordcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defemail=window.localStorage.getItem('findwordcollaboratoremailee');
}
if (('' + window.localStorage.getItem('findwordcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defsms=window.localStorage.removeItem('findwordcollaboratorsmsno');
}


function doemail(inidea) {
////alert(3);
var zfrom='youllneverfindthis', zto='youllneverfindthis';
var azx=top.document.getElementById('xae' + 'mail');
//alert(33);
if (!azx) { azx=top.document.createElement("a"); }
//alert(3333);
//if (1 == 1) {
//document.getElementById('divas').appendChild(azx);
//} else {
top.document.body.appendChild(azx);
//}
//(334);
azx.style = "display: none";
//alert(2334);
azx.target = "_top";
//alert(6334);
azx.id = 'xae' + 'mail';
//if (1 == 6 && bihbig.indexOf('</he' + 'ad>') != -1 || bihbig.indexOf('<b' + 'o' + 'dy') != -1 || bihbig.indexOf('<h' + '1') == 0) {
//azx.href = 'mailto:' + inidea + '?subject=' + encodeURIComponent(document.getElementsByTagName('h2')[0].innerHTML.split('&')[0].split('<')[0].replace(/\`/g,'').replace(/^Events\ in\ /g, 'Events in Month ').substring(0)) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(bihbig)); //encodeURIComponent(document.URL.split('#')[0] + '<h2' + document.body.innerHTML.split('<h2')[1]));
//} else {
var newurl=document.URL.split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(mode.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + maxwordlength + '&table=' + tabularize + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
if (!oops && tabularize == 'Null' && !document.getElementById('tablemy')) {
zfrom=encodeURIComponent('Highlighting');
zto=encodeURIComponent('Click Start/End');
newurl=document.URL.split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(mode.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + maxwordlength + '&table=y#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
}
if (sparewes) {
azx.href = 'mailto:' + inidea + '?subject=' + encodeURIComponent(sparewes.document.getElementsByTagName('h1')[0].innerText).replace(zfrom,zto) + '&body=' + encodeURIComponent(newurl); //encodeURIComponent(document.URL.split('#')[0] + '<h2' + sparewes.document.body.innerHTML.split('<h2')[1]));
} else {
azx.href = 'mailto:' + inidea + '?subject=' + encodeURIComponent(document.getElementsByTagName('h1')[0].innerText).replace(zfrom,zto) + '&body=' + encodeURIComponent(newurl); //encodeURIComponent(document.URL.split('#')[0] + '<h2' + document.body.innerHTML.split('<h2')[1]));
}
//}
azx.click();
if (!oops && tabularize == 'Null' && !document.getElementById('tablemy')) {
location.href=newurl;
}
if (!updatehowlong) {
updatehowlong=true;
setInterval(upscore, 5000);
}
return '';
}

function dosms() {
if (('' + window.localStorage.getItem('findwordcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defemail=window.localStorage.getItem('findwordcollaboratoremailee');
}
if (('' + window.localStorage.getItem('findwordcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defsms=window.localStorage.removeItem('findwordcollaboratorsmsno');
}
//alert('' + eval('' + ('sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(parent.hfanalyze()))).length));
if (1 == 1 || eval('' + ('sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(mode.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + maxwordlength + '&table=' + tabularize + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,'')))).length) >= 18000) {
snum=('' + prompt('Please enter SMS number to send to. We suspect message is too long for an SMS and if you enter an email address here instead, we will try to send an email instead. Append space(s) to remember, whatever you enter, for next time.', snum)).replace(/^null/g, (defemail.indexOf('@') != -1 ? defemail : (defsms != '' ? defsms : '')) );
} else {
snum=('' + prompt('Please enter SMS number to send to. Append space(s) to remember for next time.', snum)).replace(/^null/g, (defsms != '' ? defsms : (defemail.indexOf('@') != -1 ? defemail : '')));
}
if (snum == null) { snum=''; }
if (snum.indexOf('@') != -1) {
if (snum.trim() != snum) {
snum=snum.trim();
if (('' + window.localStorage.getItem('findwordcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('findwordcollaboratoremailee');
}
window.localStorage.setItem('findwordcollaboratoremailee', snum);
defemail=snum;
}
return doemail(snum);
} else if (snum.trim() != '' && snum.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').trim() == '') {
//alert('Snum=' + snum + '?');
if (snum.trim() != snum) {
snum=snum.trim();
if (('' + window.localStorage.getItem('findwordcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('findwordcollaboratorsmsno');
}
window.localStorage.setItem('findwordcollaboratorsmsno', snum);
defsms=snum;
}
var azx=top.document.getElementById('xas' + 'ms');
if (azx == null) { azx=top.document.createElement("a"); }
//if (1 == 1) {
// document.getElementById('divas').appendChild(azx);
//} else {
top.document.body.appendChild(azx);
// }
azx.id = 'xas' + 'ms';
azx.target = "_top";
azx.style = "display: none";
var newurl=document.URL.split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(mode.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + maxwordlength + '&table=' + tabularize + '#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
if (!oops && tabularize == 'Null' && !document.getElementById('tablemy')) {
newurl=document.URL.split('?')[0].split('#')[0] + '?mode=' + encodeURIComponent(mode.trim()) + '&across=' + numlettersacross + '&down=' + numlettersdown + '&fontpixels=' + fontpixels + '&wordlenmin=' + minwordlength + '&wordlenmax=' + maxwordlength + '&table=y#' + encodeURIComponent(jhis.replace(/\<br\>/g,''));
}
azx.href = 'sms:' + snum + '&body=' + encodeURIComponent(newurl.replace('#','&').replace('?','#')); //encodeURIComponent(document.URL.split('#')[0] + '<h2' + document.body.innerHTML.split('<h2')[1]));
azx.click();
if (!oops && tabularize == 'Null' && !document.getElementById('tablemy')) {
location.href=newurl;
}
if (!updatehowlong) {
updatehowlong=true;
setInterval(upscore, 5000);
}
}
return '';
}

function emailaskit() {
if (defemail == defemail.trim()) {
defemail=defemail.trim() + ' ';
var emailm=prompt('Enter default email address.', defemail.trim());
if (emailm == null) { emailm=''; }
if (emailm.trim() != '' && emailm.trim().indexOf('@') != -1) {
defemail=emailm.trim() + ' ';
if (('' + window.localStorage.getItem('findwordcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defemail=window.localStorage.removeItem('findwordcollaboratoremailee');
}
window.localStorage.setItem('findwordcollaboratoremailee', emailm.trim());
}
}
defemail=defemail.trim() + ' ';
}

function smsaskit() {
if (defsms == defsms.trim()) {
defsms=defsms.trim() + ' ';
var smsm=prompt('Enter default SMS number.', defsms.trim());
if (smsm == null) { smsm=''; }
if (smsm.trim() != '' && smsm.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').trim() == '') {
defsms=smsm.trim() + ' ';
if (('' + window.localStorage.getItem('findwordcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('findwordcollaboratorsmsno');
}
window.localStorage.setItem('findwordcollaboratorsmsno', smsm.trim());
}
}
defsms=defsms.trim() + ' ';
}

… with that “midair feeling” approach to the “a” “mailto:” and/or “sms:” links used via the 📧 (email) and/or 📟 (SMS) emoji buttons now available in the changed textarea_find_words.html Find the Words game.


Previous relevant Find English Mobile Clicked Word Ends Game Tutorial is shown below.

Find English Mobile Clicked Word Ends Game Tutorial

Find English Mobile Clicked Word Ends Game Tutorial

We tried making the mobile platforms work with the selectionchange event of yesterday’s Find English Highlighted Words Game Selection Tutorial‘s Find the Word game web application, but we decided, today …

  1. the default game operation for mobile platforms should be a new …
    • overlayed
    • table … based …
    • cell … onclick event based …
    • modus operandi … for each end of the user chosen words (as user clicked)

    … means by which to play the game … as well as …

  2. the default game operation for non-mobile platforms remains the old textarea selectionchange event methodology … but either above …
  3. defaults can be overridden by a new address bar URL argument

We made the selectionchange event range.start and range.end form the suffix of those “cell” element “IDs” above within the following document.body onload event function


var tabularize=location.search.split('table=')[1] ? (decodeURIComponent(location.search.split('table=')[1].split('&')[0])) : 'Null';

function pickletters() {
var valis='', randval=eval(Math.floor(Math.random() * 26) % 26), ihis='', lvalis='';
for (var ir=1; ir<=numlettersdown; ir++) {
lvalis='';
for (var ic=1; ic<=numlettersacross; ic++) {
valis+=String.fromCharCode(eval(randval + 'A'.charCodeAt(0)));
lvalis+=String.fromCharCode(eval(randval + 'A'.charCodeAt(0)));
if (eval(linesarr.length) < ir) {
linesarr.push(valis.slice(-1));
} else {
linesarr[eval(-1 + ir)]+=valis.slice(-1);
}
if (eval(colsarr.length) < ic) {
colsarr.push(valis.slice(-1));
} else {
colsarr[eval(-1 + ic)]+=valis.slice(-1);
}
ihis+=String.fromCharCode(eval(randval + 'A'.charCodeAt(0)));
randval=eval(Math.floor(Math.random() * 26) % 26);
}
origcomplines.push(lvalis);
lvalis='';
if (ir < 50) {
valis+=String.fromCharCode(10);
ihis+='<br>';
}
}
//alert(valis);
document.getElementById('myta').value=valis;
eol=document.getElementById('myta').value.substring(numlettersacross).split('A')[0].split('B')[0].split('C')[0].split('D')[0].split('E')[0].split('F')[0].split('G')[0].split('H')[0].split('I')[0].split('J')[0].split('K')[0].split('L')[0].split('M')[0].split('N')[0].split('O')[0].split('P')[0].split('Q')[0].split('R')[0].split('S')[0].split('T')[0].split('U')[0].split('V')[0].split('W')[0].split('X')[0].split('Y')[0].split('Z')[0];
oureol=eol;
var lris='ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
for (var ii=0; ii<lris.length; ii++) {
letteremojis.push(orflag(lris[ii]));
blankemojis.push(' '); // ' ';
loweremojis.push(lris[ii].toLowerCase()); // ' ';
upperemojis.push(lris[ii].toUpperCase()); // ' ';
}
firstval=document.getElementById('myta').value;
document.getElementById('mya').href=document.URL.split('#')[0];
if ((tabularize + 'n').toLowerCase().substring(0,1) == 'y' || (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && tabularize == 'Null')) {
document.getElementById('myh1').innerHTML=document.getElementById('myh1').innerHTML.replace('Highlighting', 'Click Start/End')
var rectta=document.getElementById('myta').getBoundingClientRect();
var trline='', ninis=0, icis=0, jicis=0, lettersare=[], tableouter=document.getElementsByTagName('textarea')[0].outerHTML.replace(' style="', ' style="position:absolute;z-index:92;opacity:1.0;background-color:rgba(0,255,0,0.6);top:0px;left:0px;margin:0 0 0 0;padding:0 0 0 0;').replace('myta', 'tablemy').replace(/textarea/g,'table');
for (icis=0; icis<origcomplines.length; icis++) {
lettersare=origcomplines[icis].split('');
trline='<tr></tr>';
for (jicis=0; jicis<lettersare.length; jicis++) {
trline=trline.replace('</tr>', '<td id=td' + ninis + ' onclick=tdanalyze(this);>' + lettersare[jicis] + '</td></tr>');
ninis++;
}
for (jicis=0; jicis<eol.length; jicis++) {
ninis++;
}
tableouter=tableouter.replace('</table>', trline + '</table>');
}
document.body.style.backgroundColor='white';
document.getElementById('myta').style.visibility='hidden';
if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('tdright').style.textAlign='right';
}
document.getElementById('dtable').innerHTML=tableouter;
if (document.getElementById('mybut')) { document.getElementById('mybut').style.display='none'; }
tableih=document.getElementById('dtable').innerHTML;
}

if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (!document.getElementById('tablemy')) { ioff=10000; }
if (!document.getElementById('tablemy')) { clickthere=false; }
}
}

And that way we hived off most of the selectionchange event logic into a global variable sensitive new Javascript function hansel called by both methodologies above …


var tog=['lightgreen', 'olive'];

function hansel() {
var joff=rstart, koff=eval('' + eol.length);
lesssel=thesel;
var huheol=eol;
if (huheol == '') { huheol=String.fromCharCode(10); }
while (lesssel.indexOf(huheol) != -1) {
lesssel=lesssel.replace(huheol, '');
}
complines=(thesel + '~').replace(huheol + '~', '').replace('~','').split(huheol);
//diagl=eval('' + complines.length);
//diagl+=eval(eval(-1 + eval('' + complines.length)) * 80);
//document.title='' + eval('' + lesssel.length) + ' vs ' + eval(eval(eval(-1 + eval('' + complines.length)) * 80) + eval(2 - eval('' + complines.length)));
if (sofar.indexOf(';' + thesel + ';') != -1) {
document.title=document.title.replace('Score:','Score+'); //'Score :' + document.getElementById('score').innerHTML.split('Score:')[1] + ' ... Repeat selection ...';
} else if (sofar.indexOf(';' + thesel + ';') == -1 && eval('' + complines.length) >= minwordlength && eval('' + complines.length) <= maxwordlength && eval('' + lesssel.length) == eval(eval(eval('' + complines.length) + eval(eval(-1 + eval('' + complines.length)) * numlettersacross)))) {
// 3 goes with 163 (2x80 + 3) or 159 (2x80 - 1)
// 4 goes with 244 (3x80 + 4) or 238 (3x80 - 2)
// 5 goes with 325 (4x80 + 5) or 317 (4x80 - 3)
icols=0;
twowordstocheck=[lesssel.substring(icols).toUpperCase().substring(0,1), lesssel.substring(icols).toUpperCase().substring(0,1)];
tworesults=['',''];
//eol=complines[1].substring(numlettersacross);
xnumlettersacross=eval(eval('' + eol.length) + eval('' + numlettersacross));
altsel=thesel.substring(0,1).toLowerCase() + complines[0].substring(1).split(eol)[0] + eol;
//rstart=eval('' + range.start);
//rend=eval('' + range.end);
indxofinterest=eval(rstart % eval(1 * eval(eval('' + eol.length) + eval('' + numlettersacross))));
indxofinterest++;
oureol=eol;
for (ilines=1; ilines<eval('' + complines.length); ilines++) {
if (eval(1 + ilines) >= eval('' + complines.length)) { oureol=''; }
icols+=eval(1 + numlettersacross);
joff+=eval(1 + numlettersacross);
if (document.getElementById('td' + eval(joff + koff))) {
if (document.getElementById('td' + eval(joff + koff)).outerHTML.indexOf('pink') == -1) { lastpinks.push('td' + eval(joff + koff)); }
document.getElementById('td' + eval(joff + koff)).style.backgroundColor='pink';
koff+=eval('' + eol.length);
}
if (indxofinterest > 0) {
altsel+=complines[ilines].substring(0,indxofinterest).toUpperCase() + complines[ilines].substring(indxofinterest).substring(0,1).toLowerCase() + complines[ilines].substring(eval(1 + indxofinterest)).toUpperCase() + oureol;
} else {
altsel+=complines[ilines].substring(0,1).toLowerCase() + complines[ilines].substring(1).toUpperCase() + oureol;
}
indxofinterest++;
twowordstocheck[0]+=lesssel.substring(icols).toUpperCase().substring(0,1);
//alert('twowordstocheck_so_far=' + twowordstocheck[0] + ' ilines=' + ilines + ' rstart % xnumlettersacross+=' + eval(rstart % xnumlettersacross) + ' rstart % numlettersacross=' + eval(rstart % numlettersacross) + ' rstart=' + rstart + ' rend=' + rend + ' complines[ilines]=' + complines[ilines] + ' altsel_so_far=' + altsel);
twowordstocheck[1]=lesssel.substring(icols).toUpperCase().substring(0,1) + twowordstocheck[1];
}
altsel+=thesel.substring(rend);
//alert('twowordstocheck_so_far=' + twowordstocheck[0] + ' ilines=' + ilines + ' rstart % xnumlettersacross+=' + eval(rstart % xnumlettersacross) + ' rstart % numlettersacross=' + eval(rstart % numlettersacross) + ' rstart=' + rstart + ' rend=' + rend + ' complines[ilines]=' + complines[ilines] + ' altsel_so_far=' + altsel);
document.title='Left Diagonal words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').style.backgroundColor='pink';
document.getElementById('results').innerHTML=documenttitle.replace(' words ', ' words <br> ').replace(' being checked', ' <br> being checked');
document.getElementById('myta').style.backgroundColor='rgb(230,230,230)';
if (!document.getElementById('tablemy')) {
if (document.getElementById('mybut')) { document.getElementById('mybut').disabled=false; document.getElementById('mybut').style.display='block'; }
}
sofar+=thesel + ';';
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(preshowthesel, eval(ioff + 4000)); setTimeout(showthesel, eval(ioff + 6000)); }
//rstart=eval('' + range.start);
//rend=eval('' + range.end);
isg1=true;
ish=false;
isd=false;
isg0=false;
showsel=true;
} else if (sofar.indexOf(';' + thesel + ';') == -1 && eval('' + complines.length) >= minwordlength && eval('' + complines.length) <= maxwordlength && eval('' + lesssel.length) == eval(eval(eval(-1 + eval('' + complines.length)) * numlettersacross) + eval(2 - eval('' + complines.length)))) {
// 3 goes with 163 (2x80 + 3) or 159 (2x80 - 1)
// 4 goes with 244 (3x80 + 4) or 238 (3x80 - 2)
// 5 goes with 325 (4x80 + 5) or 317 (4x80 - 3)
icols=0;
twowordstocheck=[lesssel.substring(icols).toUpperCase().substring(0,1), lesssel.substring(icols).toUpperCase().substring(0,1)];
tworesults=['',''];
sofar+=thesel + ';';
//eol=complines[1].substring(numlettersacross);
xnumlettersacross=eval(eval('' + eol.length) + eval('' + numlettersacross));
altsel=thesel.substring(0,1).toLowerCase() + complines[0].substring(1).split(eol)[0] + eol;
//rstart=eval('' + range.start);
//rend=eval('' + range.end);
indxofinterest=eval(rstart % eval(1 * eval(eval('' + eol.length) + eval('' + numlettersacross))));
indxofinterest--;
oureol=eol;
for (ilines=1; ilines<eval('' + complines.length); ilines++) {
if (eval(1 + ilines) >= eval('' + complines.length)) { oureol=''; }
icols+=eval(-1 + numlettersacross);
joff+=eval(-1 + numlettersacross);
if (document.getElementById('td' + eval(joff + koff))) {
if (document.getElementById('td' + eval(joff + koff)).outerHTML.indexOf('pink') == -1) { lastpinks.push('td' + eval(joff + koff)); }
document.getElementById('td' + eval(joff + koff)).style.backgroundColor='pink';
koff+=eval('' + eol.length);
}
if (indxofinterest > 0) {
altsel+=complines[ilines].substring(0,indxofinterest).toUpperCase() + complines[ilines].substring(indxofinterest).substring(0,1).toLowerCase() + complines[ilines].substring(eval(1 + indxofinterest)).toUpperCase() + oureol;
} else {
altsel+=complines[ilines].substring(0,1).toLowerCase() + complines[ilines].substring(1).toUpperCase() + oureol;
}
indxofinterest--;
twowordstocheck[0]+=lesssel.substring(icols).toUpperCase().substring(0,1);
//alert('Twowordstocheck_so_far=' + twowordstocheck[0] + ' ilines=' + ilines + ' rstart % xnumlettersacross+=' + eval(rstart % xnumlettersacross) + ' rstart % numlettersacross=' + eval(rstart % numlettersacross) + ' rstart=' + rstart + ' rend=' + rend + ' complines[ilines]=' + complines[ilines] + ' altsel_so_far=' + altsel);
twowordstocheck[1]=lesssel.substring(icols).toUpperCase().substring(0,1) + twowordstocheck[1];
}
altsel+=thesel.substring(rend);
document.title='Right Diagonal words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').style.backgroundColor='pink';
document.getElementById('results').innerHTML=documenttitle.replace(' words ', ' words <br> ').replace(' being checked', ' <br> being checked');
document.getElementById('myta').style.backgroundColor='rgb(245,245,245)';
if (!document.getElementById('tablemy')) {
if (document.getElementById('mybut')) { document.getElementById('mybut').disabled=false; document.getElementById('mybut').style.display='block'; }
}
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(preshowthesel, eval(ioff + 4000)); setTimeout(showthesel, eval(ioff + 6000)); }
//rstart=eval('' + range.start);
//rend=eval('' + range.end);
isg0=true;
ish=false;
isd=false;
isg1=false;
showsel=true;
} else if (sofar.indexOf(';' + thesel + ';') == -1 && eval('' + complines.length) >= minwordlength && eval('' + complines.length) <= maxwordlength && eval(-1 + eval('' + lesssel.length)) == eval(eval(eval(-1 + eval('' + complines.length)) * numlettersacross) + eval(0 * eval('' + complines.length)))) {
// 6 goes with 401
// 4 goes with 241
icols=0;
twowordstocheck=[lesssel.substring(icols).toUpperCase().substring(0,1), lesssel.substring(icols).toUpperCase().substring(0,1)];
tworesults=['',''];
sofar+=thesel + ';';
//eol=complines[1].substring(numlettersacross);
xnumlettersacross=eval(eval('' + eol.length) + eval('' + numlettersacross));
altsel=thesel.substring(0,1).toLowerCase() + complines[0].substring(1).split(eol)[0] + eol;
//rstart=eval('' + range.start);
//rend=eval('' + range.end);
indxofinterest=eval(rstart % eval(1 * eval(eval('' + eol.length) + eval('' + numlettersacross))));
oureol=eol;
for (ilines=1; ilines<eval('' + complines.length); ilines++) {
icols+=numlettersacross;
joff+=numlettersacross;
if (document.getElementById('td' + eval(joff + koff))) {
if (document.getElementById('td' + eval(joff + koff)).outerHTML.indexOf('pink') == -1) { lastpinks.push('td' + eval(joff + koff)); }
document.getElementById('td' + eval(joff + koff)).style.backgroundColor='pink';
koff+=eval('' + eol.length);
}
if (eval(1 + ilines) >= eval('' + complines.length)) { oureol=''; }
if (indxofinterest > 0) {
altsel+=complines[ilines].substring(0,indxofinterest).toUpperCase() + complines[ilines].substring(indxofinterest).substring(0,1).toLowerCase() + complines[ilines].substring(eval(1 + indxofinterest)).toUpperCase() + oureol;
} else {
altsel+=complines[ilines].substring(0,1).toLowerCase() + complines[ilines].substring(1).toUpperCase() + oureol;
}
twowordstocheck[0]+=lesssel.substring(icols).toUpperCase().substring(0,1);
//alert('TWowordstocheck_so_far=' + twowordstocheck[0] + ' indxofinterest=' + indxofinterest + ' ilines=' + ilines + ' rstart % xnumlettersacross+=' + eval(rstart % xnumlettersacross) + ' rstart % numlettersacross=' + eval(rstart % numlettersacross) + ' rstart=' + rstart + ' rend=' + rend + ' complines[ilines]=' + complines[ilines] + ' altsel_so_far=' + altsel);
twowordstocheck[1]=lesssel.substring(icols).toUpperCase().substring(0,1) + twowordstocheck[1];
}
altsel+=thesel.substring(rend);
//alert('TWowordstocheck_so_far=' + twowordstocheck[0] + ' indxofinterest=' + indxofinterest + ' ilines=' + ilines + ' rstart % xnumlettersacross+=' + eval(rstart % xnumlettersacross) + ' rstart % numlettersacross=' + eval(rstart % numlettersacross) + ' rstart=' + rstart + ' rend=' + rend + ' complines[ilines]=' + complines[ilines] + ' altsel_so_far=' + altsel);
document.title='Down words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').style.backgroundColor='pink';
document.getElementById('results').innerHTML=documenttitle.replace(' words ', ' words <br> ').replace(' being checked', ' <br> being checked');
document.getElementById('myta').style.backgroundColor='rgb(230,230,230)';
if (!document.getElementById('tablemy')) {
if (document.getElementById('mybut')) { document.getElementById('mybut').disabled=false; document.getElementById('mybut').style.display='block'; }
}
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(preshowthesel, eval(ioff + 4000)); setTimeout(showthesel, eval(ioff + 6000)); }
//rstart=eval('' + range.start);
//rend=eval('' + range.end);
isd=true;
ish=false;
isg1=false;
isg0=false;
showsel=true;
} else if (sofar.indexOf(';' + thesel + ';') == -1 && thesel.indexOf(String.fromCharCode(10)) == -1 && eval('' + thesel.length) >= minwordlength && eval('' + thesel.length) <= maxwordlength) {
//alert('Horizontal word ' + eval('' + thesel.length) + ' ... ' + thesel);
twowordstocheck=[lesssel.toUpperCase(), lesssel.split('').reverse().join('').toUpperCase()];
tworesults=['',''];
sofar+=thesel + ';';
document.title='Horizontal words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').style.backgroundColor='pink';
document.getElementById('results').innerHTML=documenttitle.replace(' words ', ' words <br> ').replace(' being checked', ' <br> being checked');
document.getElementById('myta').style.backgroundColor='rgb(230,230,230)';
if (document.getElementById('tablemy')) {
for (var iicols=rstart; iicols<=rend; iicols++) {
if (document.getElementById('td' + iicols)) {
if (document.getElementById('td' + iicols).outerHTML.indexOf('pink') == -1) { lastpinks.push('td' + iicols); }
document.getElementById('td' + iicols).style.backgroundColor='pink';
}
}
}
if (!document.getElementById('tablemy')) {
if (document.getElementById('mybut')) { document.getElementById('mybut').disabled=false; document.getElementById('mybut').style.display='block'; }
}
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(preshowthesel, eval(ioff + 4000)); setTimeout(showthesel, eval(ioff + 6000)); }
showsel=true;
//rstart=eval('' + range.start);
//rend=eval('' + range.end);
ish=true;
isg1=false;
isd=false;
isg0=false;
} else {
document.title='Score:' + document.getElementById('score').innerHTML.split('Score:')[1] + ' ... Find the Words Highlighting Game - RJM Programming - March, 2024';
}
}

function handleSelection() { // thanks to https://stackoverflow.com/questions/46651479/reacting-to-selection-changes-in-an-html-textarea
const activeElement = document.activeElement;

// Make sure this is your textarea
if (activeElement && activeElement.outerHTML.indexOf('<textarea') == 0) {
const range = {
start: activeElement.selectionStart,
end: activeElement.selectionEnd
};
// Do something with your range
isvalid=true;
if (!document.getElementById('tablemy') && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
for (iiis=0; iiis<origcomplines.length; iiis++) {
if (thesel.indexOf(origcomplines[iiis]) == 0) {
isvalid=false;
}
}
}
if (isvalid && eval('' + range.end) > eval('' + range.start)) {
thesel=(activeElement.value.substring(range.start).substring(0, eval(eval('' + range.end) - eval('' + range.start) )));
rstart=eval('' + range.start);
rend=eval('' + range.end);
hansel();
}
}
}

document.addEventListener('selectionchange', handleSelection);

… in the changed textarea_find_words.html Find the Words game.


Previous relevant Find English Highlighted Words Game Selection Tutorial is shown below.

Find English Highlighted Words Game Selection Tutorial

Find English Highlighted Words Game Selection Tutorial

Thinking about yesterday’s Find English Highlighted Words Game Primer Tutorial‘s first draft of a Find the Word game web application, we found it easy to pinpoint where to improve it …

  • better informing the user when a textarea selection event detection caused an analysis of the word forwards and backwards to be analyzed … and flagging this better for them …

    function preshowthesel() {
    if (showsel) {
    if (rend >= 0 && rstart >= 0) {
    if (!clickthere) {
    setTimeout(preshowthesel, 5000);
    return '';
    }
    if (isd || isg0 || isg1) {
    if (altsel.trim() != '' && thesel != '') {
    //alert('here ' + document.getElementById('myta').value.indexOf(thesel) + ' ... ' + altsel)
    document.getElementById('myta').setAttribute('data-alt', encodeURIComponent(document.getElementById('myta').value.replace(thesel.substring(0,eval('' + altsel.length)), hlem(altsel))));
    document.getElementById('myta').value=ovlem(document.getElementById('myta').value.replace(thesel.substring(0,eval('' + altsel.length)), lem(altsel)));
    } else if (altsel.trim() != '' && lastsel != '') {
    //alert('hEre ' + document.getElementById('myta').value.indexOf(lastsel) + ' ... ' + altsel)
    document.getElementById('myta').setAttribute('data-alt', encodeURIComponent(document.getElementById('myta').value.replace(lastsel.substring(0,eval('' + altsel.length)), lem(altsel))));
    document.getElementById('myta').value=ovlem(document.getElementById('myta').value.replace(lastsel.substring(0,eval('' + altsel.length)), lem(altsel)));
    } // else {
    //alert('Why? ' + thesel);
    //}
    } else if (ish) {
    if (eval('' + rstart) > 0) {
    document.getElementById('myta').setAttribute('data-alt', encodeURIComponent(document.getElementById('myta').value.substring(0,rstart).toUpperCase() + hlem(document.getElementById('myta').value.substring(rstart).substring(0, eval(eval('' + rend) - eval('' + rstart) )).toLowerCase()) + document.getElementById('myta').value.substring(rend).toUpperCase()));
    document.getElementById('myta').value=togglelem(document.getElementById('myta').value.substring(0,rstart).toUpperCase() + hlem(document.getElementById('myta').value.substring(rstart).substring(0, eval(eval('' + rend) - eval('' + rstart) )).toLowerCase()) + document.getElementById('myta').value.substring(rend).toUpperCase());
    } else {
    document.getElementById('myta').setAttribute('data-alt', encodeURIComponent(hlem(document.getElementById('myta').value.substring(rstart).substring(0, eval(eval('' + rend) - eval('' + rstart) )).toLowerCase()) + document.getElementById('myta').value.substring(rend).toUpperCase()));
    document.getElementById('myta').value=togglelem(hlem(document.getElementById('myta').value.substring(rstart).substring(0, eval(eval('' + rend) - eval('' + rstart) )).toLowerCase()) + document.getElementById('myta').value.substring(rend).toUpperCase());
    }
    }
    }
    altsel=' ';
    }
    }

    … as your starting point …
  • parameterizations via ? and & address bar URL arguments … pretty self explanatory via …

    var minwordlength=location.search.split('min=')[1] ? Math.min(3,eval(decodeURIComponent(location.search.split('min=')[1].split('&')[0]))) : 3;
    var maxwordlength=location.search.split('max=')[1] ? eval(decodeURIComponent(location.search.split('max=')[1].split('&')[0])) : 15;
    var numlettersacross=location.search.split('across=')[1] ? eval(decodeURIComponent(location.search.split('across=')[1].split('&')[0])) : 76;
    var numlettersdown=location.search.split('down=')[1] ? eval(decodeURIComponent(location.search.split('down=')[1].split('&')[0])) : 40;
    var fontpixels=location.search.split('pixels=')[1] ? eval(decodeURIComponent(location.search.split('pixels=')[1].split('&')[0])) : 13;
  • regional indicator based emoji numerical display helpers for down and diagonal user guesses … in an overlayed textarea element … using …

    var letteremojis=[], blankemojis=[], loweremojis=[], upperemojis=[];

    var lris='ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
    for (var ii=0; ii<lris.length; ii++) {
    letteremojis.push(orflag(lris[ii]));
    blankemojis.push(' '); // ' ';
    loweremojis.push(lris[ii].toLowerCase()); // ' ';
    upperemojis.push(lris[ii].toUpperCase()); // ' ';
    }

    function orflag(thiscc) {
    var lri='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var dri=['127462','127463','127464','127465','127466','127467','127468','127469','127470','127471','127472','127473','127474','127475','127476','127477','127478','127479','127480','127481','127482','127483','127484','127485','127486','127487'];
    var ccsuff='', ccchar=' ', cde='';
    for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
    ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
    ccsuff+=String.fromCodePoint(dri[eval('' + lri.indexOf(ccchar))]); //'&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
    cde='.';
    }
    return ccsuff;
    }

    … as an ascii letter to emoji mapping mechanism … or …
  • toggle the display text case for horizontal user guesses … in an overlayed textarea element … using …

    function togglelem(insg) {
    var outsg='';
    var inarr=insg.split('');
    for (var jin=0; jin<insg.length; jin++) {
    if (insg.substring(jin).substring(0,1) == insg.substring(jin).substring(0,1).toLowerCase() && insg.substring(jin).substring(0,1) != insg.substring(jin).substring(0,1).toUpperCase()) {
    outsg+=insg.substring(jin).substring(0,1).toUpperCase();
    } else if (insg.substring(jin).substring(0,1) != insg.substring(jin).substring(0,1).toLowerCase() && insg.substring(jin).substring(0,1) == insg.substring(jin).substring(0,1).toUpperCase()) {
    outsg+=insg.substring(jin).substring(0,1).toLowerCase();
    } else {
    outsg+=insg.substring(jin).substring(0,1)
    }
    }
    return outsg;
    }
  • add a very simple text CSS styling embellisher …
    <style>

    textarea {
    text-shadow: -1px 1px 1px #952dff;
    }

    </style>
  • use the webpage title (on web browser tab) to allow a synopsis without resorting to right hand information, perhaps … via …

    document.title='Score:' + document.getElementById('score').innerHTML.split('Score:')[1] + ' ... Find the Words Highlighting Game - RJM Programming - March, 2024';

… in the changed textarea_find_words.html Find the Words game.


Previous relevant Find English Highlighted Words Game Primer Tutorial is shown below.

Find English Highlighted Words Game Primer Tutorial

Find English Highlighted Words Game Primer Tutorial

Yesterday’s Event Calendar Collaboration Textarea Highlight Linking Tutorial gave us an idea for an English Word Game based on the use of the “/usr/share/dict/words” inbuilt, in our case, English, dictionary you get to look up for free on macOS and Linux web server systems.

This highlighting within a sea of letters presented in a textarea was the framework for users to play a game highlighting …

  • horizontally
  • vertically
  • diagonally

… words in left to right or top to bottom order, or reversed, to score in our “Find the Words” game presented today.

You might question the design here. Highlighting within a textarea element is easy to understand for the horizontal option above, but how does it work for the other two? Well, the textarea selection start position relative to the selection end position can differentiate between the last two options above, as well as for none of the above. And we hope to help with some better display smarts with future releases.

Take a look at the crucial selectionchange event logic for today’s Find the Word game …


function handleSelection() { // thanks to https://stackoverflow.com/questions/46651479/reacting-to-selection-changes-in-an-html-textarea
const activeElement = document.activeElement;

// Make sure this is your textarea
if (activeElement && activeElement.outerHTML.indexOf('<textarea') == 0) {
const range = {
start: activeElement.selectionStart,
end: activeElement.selectionEnd
};
// Do something with your range
if (eval('' + range.end) > eval('' + range.start)) {
thesel=(activeElement.value.substring(range.start).substring(0, eval(eval('' + range.end) - eval('' + range.start) )));
lesssel=thesel;
while (lesssel.indexOf(String.fromCharCode(10)) != -1) {
lesssel=lesssel.replace(String.fromCharCode(10), '');
}
complines=thesel.split(String.fromCharCode(10));
//diagl=eval('' + complines.length);
//diagl+=eval(eval(-1 + eval('' + complines.length)) * 80);
//document.title='' + eval('' + lesssel.length) + ' vs ' + eval(eval(eval(-1 + eval('' + complines.length)) * 80) + eval(2 - eval('' + complines.length)));
if (sofar.indexOf(';' + thesel + ';') != -1) {
document.title='Repeat selection ...';
} else if (sofar.indexOf(';' + thesel + ';') == -1 && eval('' + complines.length) >= 3 && eval('' + lesssel.length) == eval(eval(eval('' + complines.length) + eval(eval(-1 + eval('' + complines.length)) * 80)))) {
// 3 goes with 163 (2x80 + 3) or 159 (2x80 - 1)
// 4 goes with 244 (3x80 + 4) or 238 (3x80 - 2)
// 5 goes with 325 (4x80 + 5) or 317 (4x80 - 3)
icols=0;
twowordstocheck=[lesssel.substring(icols).substring(0,1), lesssel.substring(icols).substring(0,1)];
tworesults=['',''];
for (ilines=1; ilines<eval('' + complines.length); ilines++) {
icols+=81;
twowordstocheck[0]+=lesssel.substring(icols).substring(0,1);
twowordstocheck[1]=lesssel.substring(icols).substring(0,1) + twowordstocheck[1];
}
document.title='Left Diagonal words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').innerHTML=documenttitle;
sofar+=thesel + ';';
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(showthesel, 5000); }
showsel=true;
} else if (sofar.indexOf(';' + thesel + ';') == -1 && eval('' + complines.length) >= 3 && eval('' + lesssel.length) == eval(eval(eval(-1 + eval('' + complines.length)) * 80) + eval(2 - eval('' + complines.length)))) {
// 3 goes with 163 (2x80 + 3) or 159 (2x80 - 1)
// 4 goes with 244 (3x80 + 4) or 238 (3x80 - 2)
// 5 goes with 325 (4x80 + 5) or 317 (4x80 - 3)
icols=0;
twowordstocheck=[lesssel.substring(icols).substring(0,1), lesssel.substring(icols).substring(0,1)];
tworesults=['',''];
sofar+=thesel + ';';
for (ilines=1; ilines<eval('' + complines.length); ilines++) {
icols+=79;
twowordstocheck[0]+=lesssel.substring(icols).substring(0,1);
twowordstocheck[1]=lesssel.substring(icols).substring(0,1) + twowordstocheck[1];
}
document.title='Right Diagonal words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').innerHTML=documenttitle;
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(showthesel, 5000); }
showsel=true;
} else if (sofar.indexOf(';' + thesel + ';') == -1 && eval('' + complines.length) >= 3 && eval(-1 + eval('' + lesssel.length)) == eval(eval(eval(-1 + eval('' + complines.length)) * 80) + eval(0 * eval('' + complines.length)))) {
// 6 goes with 401
// 4 goes with 241
icols=0;
twowordstocheck=[lesssel.substring(icols).substring(0,1), lesssel.substring(icols).substring(0,1)];
tworesults=['',''];
sofar+=thesel + ';';
for (ilines=1; ilines<eval('' + complines.length); ilines++) {
icols+=80;
twowordstocheck[0]+=lesssel.substring(icols).substring(0,1);
twowordstocheck[1]=lesssel.substring(icols).substring(0,1) + twowordstocheck[1];
}
document.title='Down words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').innerHTML=documenttitle;
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(showthesel, 5000); }
showsel=true;
} else if (sofar.indexOf(';' + thesel + ';') == -1 && thesel.indexOf(String.fromCharCode(10)) == -1 && eval('' + thesel.length) >= 3) {
//alert('Horizontal word ' + eval('' + thesel.length) + ' ... ' + thesel);
twowordstocheck=[lesssel, lesssel.split('').reverse().join('')];
tworesults=['',''];
sofar+=thesel + ';';
document.title='Horizontal words ' + twowordstocheck[0] + ' and ' + twowordstocheck[1] + ' being checked ...';
documenttitle=' ' + document.title;
document.getElementById('results').innerHTML=documenttitle;
//document.getElementById('myta').style.cursor='progress';
if (!showsel) { setTimeout(showthesel, 5000); }
showsel=true;
} else {
document.title='Find the Words Highlighting Game - RJM Programming - March, 2024';
}
}
}
}

document.addEventListener('selectionchange', handleSelection);

… in our first draft Find the Words game you can try below …


Previous relevant Event Calendar Collaboration Textarea Highlight Linking Tutorial is shown below.

Event Calendar Collaboration Textarea Highlight Linking Tutorial

Event Calendar Collaboration Textarea Highlight Linking Tutorial

For the first time we can remember, with our Events in Month web application of yesterday’s Event Calendar Collaboration Remembering Recipient Tutorial

  • we’re channelling how in emails “word strings” starting with “http” become links … and so …
  • in our event in month “blurb” textarea elements we allow user highlighted text containing such “http” “word strings” be opened in popup windows showing the content of those URLs, as available

Here is the relevant Javascript we ended up with, for this …


var thesel='', showsel=false, lastsel='';

function showthesel() {
var uwords=[], iuw=1, ils=0;
if (showsel) {
showsel=false;
if (lastsel != thesel && thesel.toLowerCase().replace('https:', 'http:').indexOf('http://') >= 0) {
lastsel=thesel;
thesel='';
}
if (lastsel != '' && thesel == '') {
uwords=lastsel.toLowerCase().split('http');
ils=eval(4 + eval('' + uwords[0].length));
for (iuw=1; iuw<uwords.length; iuw++) {
window.open('//' + lastsel.substring(ils).split('//')[1].split(' ')[0].split(String.fromCharCode(10))[0].split(String.fromCharCode(13))[0], '_blank', 'top=' + eval(10 * iuw + 50) + ',left=' + eval(10 * iuw + 50) + ',width=600,height=600');
ils+=eval(4 + eval('' + uwords[iuw].length));
}
}
}
}

function handleSelection() { // thanks to https://stackoverflow.com/questions/46651479/reacting-to-selection-changes-in-an-html-textarea
const activeElement = document.activeElement;

// Make sure this is your textarea
if (activeElement && activeElement.outerHTML.indexOf('<textarea') == 0) {
const range = {
start: activeElement.selectionStart,
end: activeElement.selectionEnd
};
// Do something with your range
if (eval('' + range.end) > eval('' + range.start)) {
thesel=(activeElement.value.substring(range.start).substring(0, eval(eval('' + range.end) - eval('' + range.start) )));
if (!showsel && thesel.toLowerCase().replace('https:', 'http:').indexOf('http://') >= 0) {
showsel=true;
setTimeout(showthesel, 5000);
}
}
}
}

document.addEventListener('selectionchange', handleSelection);

Also, today, we have a few CSS tweaks in the changed events_in_month.htm parent of the Events in Month web application. Feel free to try it for yourself.

Stop Press

Just briefly, delved into the wooooorrrrllllldddd of days of the week before 1582 debate … you had to be there … and in the words of Lleyton … Come on!!!! And we came out the other side. Good times! Anyway, thanks for all the interesting discussion, which we recommend you start at with this gem. Anyway, we now allow dates after 1582 (after this was previously set at 1970) in all respects and dates between 0000 and 1581 only via tweaks to the address bar URL you do yourself and we just hide the day of the week string. Otherwise … this could be needed?!


Previous relevant Event Calendar Collaboration Remembering Recipient Tutorial is shown below.

Event Calendar Collaboration Remembering Recipient Tutorial

Event Calendar Collaboration Remembering Recipient Tutorial

When doing our inhouse testing for Event Calendar Collaboration Tutorial the other day, it got us “peeved”, shall we say. We wanted a mechanism, with those “a” link “mailto:” emailing arrangements, of not having to fill out the email address in the “To:” field each time. First world problem alert! Still and all …

  • When it comes to procedures …
  • Aaaaaarrrrgggghhhh
  • Nuances count … regarding …
  • Errrrrrr
  • Saving time …
  • Saving frustration

… resulting in the “easy to remember” acronym WANESS … we rest our cases!

What can help here? Well, it is a personalization … so … anyone, anyone? Yes, Lou, back from holidays, a month late … yes, well, okay … we can see you’ve put some thought into this … HTTP Cookies could be used. Yes, Shwetank, you’ve had your hand up some time now. We agree, Web Storage window.localStorage allows for more data, so we’ll go with that, though either style of approach would work here.

Global variables initialization …

var defemail='', defsms='';
if (('' + window.localStorage.getItem('eventcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defemail=window.localStorage.getItem('eventcollaboratoremailee');
}
if (('' + window.localStorage.getItem('eventcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defsms=window.localStorage.removeItem('eventcollaboratorsmsno');
}
Within document.body onload event logic …

if (document.getElementById('semail') && document.getElementById('ssms')) {
document.getElementById('semail').oncontextmenu=function(){ emailaskit(); };
document.getElementById('semail').ontouchmove=function(){ emailaskit(); };
document.getElementById('ssms').oncontextmenu=function(){ smsaskit(); };
document.getElementById('ssms').ontouchmove=function(){ smsaskit(); };
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('semail').title+=' Move gesture here can ask for new default remembered email address for collaboration purposes';
document.getElementById('ssms').title+=' Move gesture here can ask for new default remembered SMS number for collaboration purposes';
} else {
document.getElementById('semail').title+=' Right click here can ask for new default remembered email address for collaboration purposes';
document.getElementById('ssms').title+=' Right click here can ask for new default remembered SMS number for collaboration purposes';
}
}
Calling these two Javascript function helpers …

function emailaskit() {
if (defemail == defemail.trim()) {
defemail=defemail.trim() + ' ';
var emailm=prompt('Enter default email address.', defemail.trim());
if (emailm == null) { emailm=''; }
if (emailm.trim() != '' && emailm.trim().indexOf('@') != -1) {
defemail=emailm.trim() + ' ';
if (('' + window.localStorage.getItem('eventcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defemail=window.localStorage.removeItem('eventcollaboratoremailee');
}
window.localStorage.setItem('eventcollaboratoremailee', emailm.trim());
}
}
defemail=defemail.trim() + ' ';
}

function smsaskit() {
if (defsms == defsms.trim()) {
defsms=defsms.trim() + ' ';
var smsm=prompt('Enter default SMS number.', defsms.trim());
if (smsm == null) { smsm=''; }
if (smsm.trim() != '' && smsm.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').trim() == '') {
defsms=smsm.trim() + ' ';
if (('' + window.localStorage.getItem('eventcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('eventcollaboratorsmsno');
}
window.localStorage.setItem('eventcollaboratorsmsno', smsm.trim());
}
}
defsms=defsms.trim() + ' ';
}
And allow control, as well, at the SMS prompt window logic

function dosms() {
if (('' + window.localStorage.getItem('eventcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defemail=window.localStorage.getItem('eventcollaboratoremailee');
}
if (('' + window.localStorage.getItem('eventcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
defsms=window.localStorage.removeItem('eventcollaboratorsmsno');
}

//alert('' + eval('' + ('sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(parent.hfanalyze()))).length));
if (eval('' + ('sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(parent.hfanalyze()))).length) >= 18000) {
snum=('' + prompt('Please enter SMS number to send to. We suspect message is too long for an SMS and if you enter an email address here instead, we will try to send an email instead. Append space(s) to remember, whatever you enter, for next time.', snum)).replace(/^null/g, (defemail.indexOf('@') != -1 ? defemail : (defsms != '' ? defsms : '')) );
} else {
snum=('' + prompt('Please enter SMS number to send to. Append space(s) to remember for next time.', snum)).replace(/^null/g, (defsms != '' ? defsms : (defemail.indexOf('@') != -1 ? defemail : '')));
}
if (snum == null) { snum=''; }
if (snum.indexOf('@') != -1) {
if (snum.trim() != snum) {
snum=snum.trim();
if (('' + window.localStorage.getItem('eventcollaboratoremailee')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('eventcollaboratoremailee');
}
window.localStorage.setItem('eventcollaboratoremailee', snum);
defemail=snum;
}

return doemail(snum);
} else if (snum.trim() != '' && snum.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').trim() == '') {
//alert('Snum=' + snum + '?');
if (snum.trim() != snum) {
snum=snum.trim();
if (('' + window.localStorage.getItem('eventcollaboratorsmsno')).replace(/^null/g,'').replace(/^undefined/g,'') != '') {
window.localStorage.removeItem('eventcollaboratorsmsno');
}
window.localStorage.setItem('eventcollaboratorsmsno', snum);
defsms=snum;
}

var azx=top.document.getElementById('xas' + 'ms');
if (azx == null) { azx=top.document.createElement("a"); }
//if (1 == 1) {
// document.getElementById('divas').appendChild(azx);
//} else {
top.document.body.appendChild(azx);
// }
azx.id = 'xas' + 'ms';
azx.target = "_top";
azx.style = "display: none";
azx.href = 'sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(parent.hfanalyze()));
azx.click();
}
return '';
}

Also, today, we battled the logic to allow the textarea element onblur events also open the door to emailing and SMS “work in progress”. Believe it or not, this timing change was quite difficult in the changed events_in_month.htm parent of the Events in Month web application. Never a dull moment in web application I.T. we’d say!


Previous relevant Event Calendar Collaboration Tutorial is shown below.

Event Calendar Collaboration Tutorial

Event Calendar Collaboration Tutorial

The Event Calendar web application project, of Event Calendar PHP Bookmark Tutorial, from last year is worth a revisit, the reason being …

  • it did not have a fully fleshed out collaboration or sharing set of functionalities … at the time, probably, because …
  • each Monthly calendar filled out, and wanting to be saved, could involve much more than the 850 characters available to previous “mailto:” or “sms:” communication conduits, back to when we first tackled this project … but now …
  • hashtagging parts to the “mailto:” URLs (and maybe sometimes the “sms:” URL) might cover the data length needs

… so that this Event Calendar could be a web application at the center of a collaboration network of people working on that event organization. Much more useful, we figure!

Timing became really important with this integration of …

  • email
  • SMS

… communication conduit possibilities. With its design we have to wait until the point where the user is filling in textarea elements regarding a designated …

  1. Month
  2. Year

… of relevance, before we allow the email 📧 and SMS 📟 emoji buttons be shown. In the code …

Amended HTML h1 element static HTML to add, later shown, perhaps, email 📧 and SMS 📟 emoji buttons

<h1>Events in Month &nbsp;&nbsp;<button style=display:none; title='Share via Email' id=semail onclick="doemail('');">&#128231;</button> <button style=display:none; title='Share via SMS' id=ssms onclick=dosms();>&#128223;</button> </h1>
New static HTML div element placed to the bottom of the body element …

<div id=divas></div>
New Javascript global variables (picking up hashtagging parts of the address bar URL, perhaps linked off an email or SMS link clicked) …

var bigbih=('' + ('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'')).split('bih=')[1] ? (decodeURIComponent(('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'')).split('bih=')[1].split('&')[0]) : '';
if (bigbih != '' && bigbih.indexOf('xae' + 'mail') == -1) {
bigbih+='<a target=_blank id=xae' + 'mail style=display:none; href="mailto:"></a>';
}
if (bigbih != '' && bigbih.indexOf('xas' + 'ms') == -1) {
bigbih+='<a target=_blank id=xas' + 'ms style=display:none; href="sms:"></a>';
}
var viatext='', smallbih='', wes=null, sparewes=null;
On or around document.body onload event we can analyze any such location.hash hashtagging data …

if (bigbih.indexOf('</he' + 'ad>') != -1 || bigbih.indexOf('<b' + 'o' + 'dy') != -1 || bigbih.indexOf('<h' + '1') == 0) {
//bigbih=bigbih.replace('" id="eventcalendar"', 'margin-top:50px;" id="eventcalendar"');
viatext=' (via contact at ' + ('' + new Date()) + ')';
if (bigbih.indexOf('<h' + '1') == 0) {
smallbih=bigbih;
} else {
smallbih=bigbih.split('<b' + 'o' + '')[1].split('</b' + 'o' + 'd' + 'y>')[0].replace(bigbih.split('<b' + 'o' + '')[1].split('</b' + 'o' + 'd' + 'y>')[0].split('>')[0] + '>', '');
}
wes=windowopen('./events_in_month.htm','_blank','top=40,left=40,width=800,height=800');
//alert(bigbih);
if (wes) {
setTimeout(function(){
wes.document.write(bigbih);
}, 3000);
//document.body.innerHTML=bigbih;
setTimeout(function(){
wes.document.getElementById('semail').style.display='inline-block';
wes.document.getElementById('ssms').style.display='inline-block';
wes.document.getElementsByTagName('h1')[0].style.display='none';
wes.document.getElementsByTagName('h3')[0].style.display='none';
//wes.setviatext(viatext);
//wes.setphpthere(' ');
//wes.togglewords();
}, 5000);
}
}
A window.open wrapper windowopen Javascript function …

function windowopen(poneis, ptwois, pthreeis) {
document.getElementById('divas').innerHTML='<iframe name=ovif id=ovif style="position:absolute;top:140px;left:0px;width:100%;height:100%;z-index:99;" src="' + poneis + '" onload=wopencheck(this);></iframe>';
//document.getElementsByTagName('h1')[0].style.opacity='0.0';
//document.getElementsByTagName('h3')[0].style.opacity='0.0';
sparewes=window.open(poneis.split('.htm')[0] + '.php', 'ovif');
//sparewes=window.open(poneis, 'ovif');
sparewes.document.write(bigbih);
setTimeout(function(){
sparewes.document.getElementById('semail').style.display='inline-block';
sparewes.document.getElementById('ssms').style.display='inline-block';
var sdem=sparewes.document.getElementById('semail').outerHTML;
var sdss=sparewes.document.getElementById('ssms').outerHTML;
sparewes.document.getElementsByTagName('h1')[0].innerHTML=sparewes.document.getElementsByTagName('h1')[0].innerHTML.replace(sdss,'');
sparewes.document.getElementsByTagName('h1')[0].innerHTML=sparewes.document.getElementsByTagName('h1')[0].innerHTML.replace(sdem,'');
sparewes.document.getElementsByTagName('h1')[0].style.display='none';
sparewes.document.getElementsByTagName('h3')[0].style.display='none';
sparewes.document.getElementById('dmore').innerHTML+=(' ' + sdem.replace('doeJUNKmail(', 'parent.doe' + 'mail(') + ' ' + sdss.replace('dosJUNKms(', 'parent.dos' + 'ms(') + '<br>');
//sparewes.setviatext(viatext);
//sparewes.setphpthere(' ');
//sparewes.togglewords();
}, 5000);
return null;
}
Is augmented by other new Javascript functions …

function hfanalyze() {
var fio=document.getElementById('ecform');
if (forceit) { forceit=false; return true; }
var delm='?';
var fioih=fio.innerHTML;
var fions=fioih.split(' name="');
var testurl=documentURL.split('?')[0].split('#')[0];
//alert(fions.length);
for (var ijk=1; ijk<fions.length; ijk++) {
testurl+=delm + fions[ijk].split('"')[0] + '=' + encodeURIComponent(document.getElementById(fions[ijk].split('"')[0]).value.replace(/\?\>/g,'? >'));
delm='&';
}
//alert(testurl.length);
//if (eval('' + testurl.length) < 750) { return true; }
//if (lastbut.value.indexOf('New') == 0 || 11 == 11) {
if (22 == 22) {
//wo=window.open('', '_blank', 'top=50,left=50,height=600,width=600');
//wo.document.write('<html><head>' + hih.replace("=docum" + "ent.URL", "='" + testurl.replace(/\'/g, "' + String.fromCharCode(39) + '") + "'") + boh + '</html>');
return ('<html><head>' + hih.replace("=docum" + "ent.URL", "='" + testurl.replace(/\'/g, "' + String.fromCharCode(39) + '") + "'") + boh + '</html>');
} else if (phpthere != '') {
if (1 == 1) {
postit(fio, false, testurl);
} else {
fio.target='phpif';
fio.method='POST';
fio.action='./events_in_month.php';
if (!document.getElementById('dmore')) {
document.getElementById('ddmore').innerHTML='<input type=hidden id=caltitle name=caltitle value="' + document.getElementById('myoldsel').options[document.getElementById('myoldsel').selectedIndex].innerText + '"></input><input type=hidden id=phpthere name=phpthere value="' + phpthere + '"></input><input type=hidden id=bigurl name=bigurl value="' + testurl + '"></input>';
} else {
document.getElementById('dmore').innerHTML='<input type=hidden id=phpthere name=phpthere value="' + phpthere + '"></input><input type=hidden id=bigurl name=bigurl value="' + testurl + '"></input>';
}
}
return 'true';
}
return 'false';
}

function doemail(inidea) {
var azx=document.getElementById('xae' + 'mail');
if (!azx) { azx=document.createElement("a"); }
//if (1 == 1) {
//document.getElementById('divas').appendChild(azx);
//} else {
document.body.appendChild(azx);
//}
azx.style = "display: none";
azx.id = 'xaem' + 'ail';
azx.href = 'mailto:' + inidea + '?subject=' + encodeURIComponent(document.getElementsByTagName('h2')[0].innerHTML.split('&')[0].split('<')[0].replace(/\`/g,'').replace(/^Events\ in\ /g, 'Events in Month ').substring(0)) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(hfanalyze())); //encodeURIComponent(document.URL.split('#')[0] + '<h2' + document.body.innerHTML.split('<h2')[1]));
azx.click();
return '';
}

function dosms() {
//alert('' + eval('' + ('sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(hfanalyze()))).length));
if (eval('' + ('sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(hfanalyze()))).length) >= 18000) {
snum=('' + prompt('Please enter SMS number to send to. We suspect message is too long for an SMS and if you enter an email address here instead, we will try to send an email instead.', snum)).replace(/^null/g,'');
} else {
snum=('' + prompt('Please enter SMS number to send to.', snum)).replace(/^null/g,'');
}
if (snum.indexOf('@') != -1) {
return doemail(snum);
} else if (snum.trim() != '') {
alert('Snum=' + snum + '?');
var azx=document.getElementById('xas' + 'ms');
if (azx == null) { azx=document.createElement("a"); }
//if (1 == 1) {
// document.getElementById('divas').appendChild(azx);
//} else {
document.body.appendChild(azx);
// }
azx.id = 'xas' + 'ms';
azx.style = "display: none";
azx.href = 'sms:' + snum + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '#bih=' + encodeURIComponent(hfanalyze()));
azx.click();
}
return '';
}

function wopencheck(iois) {
var aconto = null;
aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
aconto.body.innerHTML=smallbih;
aconto.setviatext(viatext);
}
}
}

function setviatext(towhat) {
viatext=towhat;
}

… to help bed down this new sharing and collaboration functionality in a changed events_in_month.htm parent of the Events in Month web application.


Previous relevant Event Calendar PHP Bookmark Tutorial is shown below.

Event Calendar PHP Bookmark Tutorial

Event Calendar PHP Bookmark Tutorial

Client meets server today, allowing the PHP data storage talents in yesterday’s Event Calendar PHP Tutorial‘s work to meet a “clientside” way to


Record to Remember via Bookmark

… use the web browser Bookmarks to help you recall an Events in Month report with long entries.

Involving a Bookmark still needs those “get” ? and & arguments, and we allow the PHP to lookup for us the data underscoring an address bar URL such as …


https://www.rjmprogramming.com.au/HTMLCSS/events_in_month.php?exactlabel=August__2023_00000__1

… that mapping being possible, now, making use of a pseudo hashtag arrangement … your Clayton‘s hashtag, if you will!

To start to use a hashtag suits, as your hashtag navigation only makes sense in the “clientside” woooorrrrrllllddd, and even there, really using one only tries to position a webpage where an element with an ID matching the hashtag sits (and we are never going to have this ID element in our work), and in the meantime we’ve passed across from the child PHP to the parent HTML a valuable piece of information helping the link to the Bookmark system be possible. The Javascript codeline (you may have noticed) …


var documentURL=document.URL;

… as stupid and simple looking as it is, is crucial for us. We get child webpage parts (like our PHP) to change document.URL to a far too long in normal circumstances address bar URL the rest of the code feeds off. It’s just that now, that far too long in normal circumstances address bar URL has a #[hashtag] appended such as …


#August__2023_00000__1

… uniquifying a Month, Year Events in Month identifier part with a version of the user’s IP address (so that they only see what is relevant to them).

Address bar URLs such as “https://www.rjmprogramming.com.au/HTMLCSS/events_in_month.php?exactlabel=August__2023_00000__1” are Bookmarkable, and so we allow for similar outcomes with less concern about how much data is being “recorded” and recallable (via that web browser’s Bookmark system).

Also, today, a lot of CSS tweaks, so that the CSS styling now looks like …


<style>
#eventcalendar {
background-color: #fcfcfc;
}

td {
padding-top: 2px;
padding-left: 2px;
padding-right: 2px;
padding-bottom: 12px;
}

.dayb {
color: white;
background-color: red;
padding: 5 5 5 5;
border-radius: 80px;
margin-bottom: 15px;
}

.dow {
color: purple;
font-style: bold;
}

.selday {
margin-left: 8px;
background-color: rgba(255,0,0,0.7);
display: inline-block;
width: 50px;
border-color: transparent;
text-overflow: ellipsis;
}

.tablurb {
background: linear-gradient(to right, white, lightpink, pink);
}

input[type="submit"] {
margin-bottom: 3px;
border-radius: 180px;
}

input[type="number"] {
margin-left: 3px;
margin-right: 3px;
border-radius: 180px;
background-color: #f3f3f3;
padding: 2 2 2 2;
}

#smonth {
margin-left: 3px;
margin-right: 3px;
border-radius: 180px;
background-color: #f9f9f9;
padding: 2 2 2 2;
}

.boldtitle {
background-color: rgba(0, 211, 107, 0.2);
}

.boldtitle + .tablurb {
margin-top: 8px;
}


.selhistory {
border-radius: 180px;
background-color: lightpink;
padding: 2 2 2 2;
}
</style>

… and we thank this webpage for the heads up regarding how to calculate week numbers within a year data item displays now available in …


Previous relevant Event Calendar PHP Tutorial is shown below.

Event Calendar PHP Tutorial

Event Calendar PHP Tutorial

Let’s face it. Serverside PHP is just great! It opens up so many opportunities regarding data in your web applications.

As such, onto yesterday’s Event Calendar New Window Tutorial logic we now have a …


Record to Remember

… form submit button (toggling) value to start involving PHP with those longer datasets of Event in Month descriptions, in our most recent project. What do we use as the data conduit? No, not a database. No, not a serverside flat file. No, not clientside window.localStorage nor window.sessionStorage nor HTTP Cookies. We store long Event in Month description data in our new events_in_month.php PHP itself. And this same PHP can populate options in a new dropdown element in the parent to facilitate the recalling of any relevant “Record to Remember” recordings.

The PHP is kind of short, so we will show it below, including one MAMP example of that “self storage” …


<?php
// events_in_month.php
// RJM Programming
// August, 2023
// Help out events_in_month.htm

$hcont=file_get_contents(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'events_in_month.htm');
$cont=file_get_contents(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'events_in_month.php');
$ipad=server_remote_addr();
$ipadless=$ipad;
$js='';

function server_remote_addr() {
global $ipadless;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
$ipadless=str_replace(".", "_", str_replace(":", "_", $rma));
if(preg_match('/(chromium)[ \/]([\w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ \/]([\w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ \/]([\w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ \/]([\w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ \/]([\w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ \/]([\w.]+)/', $ua))
$rma = '0'.$rma;
return str_replace(".", "_", str_replace(":", "_", $rma));
}

$itdone=false;
if (isset($_GET['init'])) {
if (strpos($cont, '_' . $ipad . '=') !== false) {
$things=explode('_' . $ipad . '=', $cont);
for ($it=1; $it<sizeof($things); $it++) {
if ($it == 1 && !$itdone) {
$itdone=true;
$js.="\n parent.document.getElementById('myoldsel').style.display='inline-block'; \n";
}
$js.="\n parent.document.getElementById('myoldsel').innerHTML+='<option value=\"" . explode("\n", $things[$it])[0] . "\">" . explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[0] . ', ' . explode('_', explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[1])[0] . "</option>'; \n";
}
}
if (strpos($cont, '0' . $ipadless . '=') !== false) {
$things=explode('0' . $ipadless . '=', $cont);
for ($it=1; $it<sizeof($things); $it++) {
if ($it == 1 && !$itdone) {
$itdone=true;
$js.="\n parent.document.getElementById('myoldsel').style.display='inline-block'; \n";
}
$js.="\n parent.document.getElementById('myoldsel').innerHTML+='<option value=\"" . explode("\n", $things[$it])[0] . "\">" . explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[0] . ', ' . explode('_', explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[1])[0] . "</option>'; \n";
}
}
echo "<html><head><script type='text/javascript'> " . $js . " </script></head><body><p>" . $ipad . "</p></body></html>";
} else if (isset($_POST['phpthere']) && isset($_POST['bigurl']) && isset($_POST['caltitle'])) {
//file_put_contents('xz.xz', 'l');
if (strpos($cont, '// ' . str_replace(' ','_',str_replace(',','_',str_replace('+',' ',urldecode($_POST['caltitle'])))) . '_' . str_replace('+',' ',urldecode($_POST['phpthere'])) . '=' . $_POST['bigurl'] . "\n") === false) {
//file_put_contents('xz.xzz', 'l');
$cont=str_replace('?' . '>', '// ' . str_replace(' ','_',str_replace(',','_',str_replace('+',' ',urldecode($_POST['caltitle'])))) . '_' . str_replace('+',' ',urldecode($_POST['phpthere'])) . '=' . $_POST['bigurl'] . "\n" . '?' . '>', $cont);
file_put_contents(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'events_in_month.php', $cont);
}
if (strpos($cont, '_' . $ipad . '=') !== false) {
$things=explode('_' . $ipad . '=', $cont);
for ($it=1; $it<sizeof($things); $it++) {
if ($it == 1 && !$itdone) {
$itdone=true;
$js.="\n parent.document.getElementById('myoldsel').style.display='inline-block'; \n";
}
$js.="\n parent.document.getElementById('myoldsel').innerHTML+='<option value=\"" . explode("\n", $things[$it])[0] . "\">" . explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[0] . ', ' . explode('_', explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[1])[0] . "</option>'; \n";
}
}
if (strpos($cont, '0' . $ipadless . '=') !== false) {
$things=explode('0' . $ipadless . '=', $cont);
for ($it=1; $it<sizeof($things); $it++) {
if ($it == 1 && !$itdone) {
$itdone=true;
$js.="\n parent.document.getElementById('myoldsel').style.display='inline-block'; \n";
}
$js.="\n parent.document.getElementById('myoldsel').innerHTML+='<option value=\"" . explode("\n", $things[$it])[0] . "\">" . explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[0] . ', ' . explode('_', explode('__', explode(' ' . ' ' . ' ', $things[-1 + $it])[-1 + sizeof(explode(' ' . ' ' . ' ', $things[-1 + $it]))])[1])[0] . "</option>'; \n";
}
}
//file_put_contents('xz.xzzz', "<html><head><script type='text/javascript'> " . $js . "\n parent.checkif(parent.document.getElementById('phpif')); \n" . " </script></head><body><p>" . str_replace(' ','%20',str_replace('+',' ',urldecode($_POST['bigurl']))) . "</p></body></html>");
echo "<html><head><script type='text/javascript'> " . $js . "\n parent.checkif(parent.document.getElementById('phpif')); \n" . " </script></head><body><p>" . str_replace(' ','%20',str_replace('+',' ',urldecode($_POST['bigurl']))) . "</p></body></html>";
} else {
echo $hcont;
}
exit;

//
//
// January__1970_00000__1=http://localhost:8888/events_in_month.htm?caltitle=January%2C%201970&i01.00=&ta01.00=kgjfjhf%20jhgfjhf%20jhkgkjhg%20jhgkjhg%20jkghhg%20jkhgkjhg%20kjhgkjhg&i02.00=&ta02.00=kjhgkjh%20kjhgkjhg%20jkhgkjhg%20kjhgkjhg%20kjhgkjhg%20jhkgkjhg%20kjgkjhg&i03.00=&ta03.00=kjhgkjhg%20kjhgkjhg%20kjhgkjhg%20kjhgkjhg%20kjhgkjhg%20jhkgkjhg&i04.00=&ta04.00=&i05.00=&ta05.00=&i06.00=&ta06.00=&i07.00=&ta07.00=&i08.00=&ta08.00=&i09.00=&ta09.00=&i10.00=&ta10.00=&i11.00=&ta11.00=&i12.00=&ta12.00=&i13.00=&ta13.00=&i14.00=&ta14.00=&i15.00=&ta15.00=&i16.00=&ta16.00=&i17.00=&ta17.00=&i18.00=&ta18.00=&i19.00=&ta19.00=&i20.00=&ta20.00=&i21.00=&ta21.00=&i22.00=&ta22.00=&i23.00=&ta23.00=&i24.00=&ta24.00=&i25.00=&ta25.00=&i26.00=&ta26.00=&i27.00=&ta27.00=&i28.00=&ta28.00=&i29.00=&ta29.00=&i30.00=&ta30.00=&i31.00=&ta31.00=
?>

Yes, the parent needed to change for our events_in_month.htm parent of Events in Month web application role.


Previous relevant Event Calendar New Window Tutorial is shown below.

Event Calendar New Window Tutorial

Event Calendar New Window Tutorial

Onto yesterday’s Event Calendar Remembered Tutorial‘s “Mystery Dilemma”

But, there’s an inherent weakness with the design, we’ll go into more into the future.

… well … it’s a perennial for us, regarding how if you stick with clientside thinking, only, web applications, when the amount of data to remember starts adding up, the “get arguments approach” ( ie. use ? and & arguments at the address bar ) is restricted by length restrictions regarding URL lengths.

Rather than jump to PHP serverside ideas just yet, we wanted to show some more ideas, staying with “clientside only thinking”, today, as well as improving the UX (user experience) and small steps forward regarding styling.

Okay then, regarding the idea to remember an Event in Month form, when there is a lot of data, and staying “just clientside”, we’ve coded for a “New Window” idea, albeit not as memorable as the default “Remember in Bookmark” possible for your smaller datasets. However, in saying that, we found that within this new window, with our Google Chrome web browser, we could …

  1. bring up Context Menu with a right click or two finger gesture within the popup window webpage content …
  2. pick Inspect option …
  3. be in Elements tab of your Web Inspector … and …
  4. highlight top <html> tag …
  5. Context Menu with a right click or two finger gesture …
  6. pick Copy -> Copy outerHTML … so that …
  7. your Event Calendar for your Events in Month choice is in a text buffer … ready for you to …
  8. Paste into a Text Editor that Events in Month webpage to store (perhaps in a MAMP local Apache/PHP/mySql web server environment, where you can further look at and develop your own ideas)

The user is told when the switch to “New Window” compromise becomes active, decided upon by reconstructing the proposed address bar URL regularly and when too long …


function formanalyze() {
var fio=document.getElementsByTagName('form')[0];
var delm='?';
var fioih=fio.innerHTML;
var fions=fioih.split(' name="');
var testurl=documentURL.split('?')[0].split('#')[0];
for (var ijk=1; ijk<fions.length; ijk++) {
testurl+=delm + fions[ijk].split('"')[0] + '=' + encodeURIComponent(document.getElementById(fions[ijk].split('"')[0]).value);
delm='&';
}
setTimeout(formanalyze, 3000);
if (eval('' + testurl.length) >= 750) {
if (document.getElementById('remember')) { document.getElementById('remember').value='New window'; }
if (document.getElementById('rememberme')) { document.getElementById('rememberme').value='New window'; }
if (document.getElementById('remembermoi')) { document.getElementById('remembermoi').value='New window'; }
} else {
if (document.getElementById('remember')) { document.getElementById('remember').value=document.getElementById('remember').value.replace(/^Remember$/g, 'Remember via Bookmark'); }
if (document.getElementById('rememberme')) { document.getElementById('rememberme').value=document.getElementById('rememberme').value.replace(/^Remember$/g, 'Remember via Bookmark'); }
if (document.getElementById('remembermoi')) { document.getElementById('remembermoi').value=document.getElementById('remembermoi').value.replace(/^Remember$/g, 'Remember via Bookmark'); }
}
return eval('' + testurl.length);
}

… the form submit buttons are reworded accordingly.

Another idea from this blog thread’s inspiration …

… we’ve now addressed in today’s “second draft” is allowing for an optional bold Event Day Blurb Title, available to the user via a new dropdown “Bold Title” option.

And, how can we do more with colour, to help the right bits stand out, and be consistent? We thought …

  • text shadow means by which the text of Event Calendar can be more impactive

    <div style="text-shadow:-1px 1px 1px #ff2d95;" id=eventcalendar></div>
  • dropdown element conditional styling

    <style>
    .dayb {
    color: white;
    background-color: red;
    padding: 5 5 5 5;
    }


    .dow {
    color: purple;
    font-style: bold;
    }

    .selday {
    margin-left: 8px;
    background-color: rgba(255,0,0,0.7);
    display: inline-block;
    width: 50px;
    }
    </style>



    if (thislabel.substring(0,1) == 'i') {
    if (thisval.trim() != '') {
    document.getElementById(thislabel.replace('i', 'sel')).style.color='white';
    document.getElementById(thislabel.replace('i', 'sel')).style.backgroundColor='red';

    }
    document.getElementById(thislabel.replace('i', 'opt')).innerText=thisval.replace(/\+/g, ' ').replace(/\ \ \ /g, ' + '); //.replace(/\+$/g, ' ');
    document.getElementById(thislabel).value=thisval.replace(/\+$/g, ' ');
    } else {
    document.getElementById(thislabel).value=thisval.replace(/\+/g, ' ').replace(/\ \ \ /g, ' + ');
    }
    }
  • placeholder on Blurb conditional existence

    var ourdata='';
    // ...
    if (documentURL.indexOf('?') != -1) {
    if (documentURL.indexOf('?caltitle=') != -1) { ourdata='data-'; }
    // ...
    trtemplate='<tr id=tr01.00><td style=width:22%;><span id=sone01.00 class=dow>' + dotw[adate.getDay()].toUpperCase().substring(0,3) + '</span><br><br><span id=stwo01.00 class=dayb>1<span onblur=sepit(this); contenteditable=true id=sp01.00></span><input type=hidden id=i01.00 name=i01.00 value=""></input><select data-dow=' + dotw[adate.getDay()].toUpperCase().substring(0,3) + ' class=selday onchange="selit(this);" id=sel01.00><option id=opt01.00 value=""></option><option title="All such in month (ie. weekly)" value="...">...</option><option title="And ..." value="&...">&</option><option value=Bold>Bold Title</option><option value=Clone>Clone</option></select></span></td><td class=blurb title="What is on?" id=tb01.00><span title="Event title" style="font-style:bold;color:blue;" id=bd01.00></span><textarea name=ta01.00 id=ta01.00 style="width:100%;height=100%;" ' + ourdata + 'placeholder="Blurb ..." class=tablurb></textarea></td></tr>';
    // ...
    }
    // ...
    }

… for our “second draft” events_in_month.htm Events in Month web application.


Previous relevant Event Calendar Remembered Tutorial is shown below.

Event Calendar Remembered Tutorial

Event Calendar Remembered Tutorial

We were inspired by an Event Calendar pamplette we saw the other day …

… to write a new “proof of concept” Events in Month web application, whose content can be recalled via the web browser’s Bookmark methodologies.

We liked the ideas for day of week and/or date of month grouping arrangements we included, being, the way we interpreted it …

  • just on this day in this month … default
  • on this day of the week throughout the month in question … “
  • on this day and some others in that month in question … “&” … to start with and further amendments available via contenteditable=true span element
  • “Clone” value allows for multiple separated “blurbs” for the one signature day

But, there’s an inherent weakness with the design, we’ll go into more into the future. For now, you can try it yourself below …

Stop Press

This is where we get to for a “second draft” we’ll get into, further, tomorrow …

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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

Distance Mobile Interfacing to Google Chart Geo Chart Tutorial

Distance Mobile Interfacing to Google Chart Geo Chart Tutorial

Distance Mobile Interfacing to Google Chart Geo Chart Tutorial

Onto yesterday’s Distance Interfacing to Google Chart Geo Chart Tutorial we attend to …

  • fix double calls to the Google Chart Geo Charts with the same URL …
  • fitting in with a Geo Chart URL arrangement that flags mobile platform
    <?php echo ”

    function smartcha(iamvalue, iamid, aois) {
    var vval='', vplace='', vcountry='';
    vprefix='';
    if (aois.id == 'topa') {
    vval=document.getElementById('from').value;
    if (vval.indexOf('country=') != -1 && vval.indexOf('fromplace=') != -1) {
    vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
    vplace=vpmaybe(vval.split('fromplace=')[1].split('&')[0].split('#')[0], vcountry);
    if (vcountry != '' && vplace != '') {
    vplace+=', ';
    }
    } else if (vval.indexOf('country=') != -1 && vval.indexOf('place=') != -1) {
    vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
    vplace=vpmaybe(vval.split('olace=')[1].split('&')[0].split('#')[0], vcountry);
    if (vcountry != '' && vplace != '') {
    vplace+=', ';
    }
    }
    } else {
    vval=document.getElementById('to').value;
    //alert(vval);
    if (vval.indexOf('country=') != -1 && vval.indexOf('&place=') != -1) {
    vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
    vplace=vpmaybe(vval.split('&place=')[1].split('&')[0].split('#')[0], vcountry);
    if (vcountry != '' && vplace != '') {
    vplace+=', ';
    }
    //alert(iamid + ' ' + vplace + vcountry);
    } else if (vval.indexOf('country=') != -1 && vval.indexOf('fromplace=') != -1) {
    vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
    vplace=vpmaybe(vval.split('fromplace=')[1].split('&')[0].split('#')[0], vcountry);
    if (vcountry != '' && vplace != '') {
    vplace+=', ';
    }
    }
    }
    if (iamvalue.indexOf("-0") != -1) {
    var latd=document.getElementById("latd");
    var latm=document.getElementById("latm");
    var lats=document.getElementById("lats");
    var longd=document.getElementById("longd");
    var longm=document.getElementById("longm");
    var longs=document.getElementById("longs");

    if (iamid == "gnols") {
    latd=document.getElementById("tald");
    latm=document.getElementById("talm");
    lats=document.getElementById("tals");
    longd=document.getElementById("gnold");
    longm=document.getElementById("gnolm");
    longs=document.getElementById("gnols");
    }

    var latsign = "+";
    if (latd.value.replace("-", "") != latd.value) latsign = "-";
    var longsign = "+";
    if (longd.value.replace("-", "") != longd.value) longsign = "-";
    var alat = eval(latd.value);
    alat = Math.abs(alat);
    var alatsuffix = 0;
    var along = eval(longd.value);
    along = Math.abs(along);
    var alongsuffix = 0;
    if (latm.value != "0" || lats.value != "0") {
    alatsuffix = eval((latm.value) / 60.0);
    alatsuffix = eval(alatsuffix + (lats.value) / 3600.0);
    } else if (latd.value.replace(".", "") != latd.value) {
    alatsuffix = 0;
    }
    if (longm.value != "0" || longs.value != "0") {
    alongsuffix = eval((longm.value) / 60.0);
    alongsuffix = eval(alongsuffix + (longs.value) / 3600.0);
    } else if (longd.value.replace(".", "") != longd.value) {
    alongsuffix = 0;
    }

    var lata = eval(alatsuffix + alat);
    var latis=latsign + lata;
    var xlatis = latis.replace("-", "").replace("+", "");
    if (xlatis == latis) latis = "+" + latis;
    var longa = eval(alongsuffix + along);
    var longis=longsign + longa;
    var retis = ["", ""];

    if (iamid == "gnols") {
    document.getElementById("weatherto").style.display = 'block';
    //retis = find_nearest(latis, longis);
    //alert(retis[0] + " then " + retis[1]);
    if (last_to == '' || last_to != '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim()) {
    last_to='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    if (vprefix != '' && vcountry != '') { vcountry=''; vplace=vplace.replace(/\,\ $/g,''); }
    document.getElementById("weatherto").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?nojwin=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
    } else {

    if (vprefix != '' && vcountry != '') { vcountry=''; vplace=vplace.replace(/\,\ $/g,''); }
    document.getElementById("weatherto").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
    }
    }
    } else if (iamid == "longs") {
    document.getElementById("weatherfrom").style.display = 'block';
    //retis = find_nearest(latis, longis);
    //alert(retis[0] + " tHen " + retis[1]);
    if (last_from == '' || last_from != '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim()) {
    last_from='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    if (vprefix != '' && vcountry != '') { vcountry=''; vplace=vplace.replace(/\,\ $/g,''); }
    document.getElementById("weatherfrom").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?nojwin=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
    } else {

    if (vprefix != '' && vcountry != '') { vcountry=''; vplace=vplace.replace(/\,\ $/g,''); }
    document.getElementById("weatherfrom").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vprefix + vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
    }
    }
    }
    }
    }

    “; ?>
    … usage, and was causing grief with mobile platform calls … sorrrrrrrrryyyyyyy …
  • involving country ISO-3166 2 character country codes where possible either via …
    1. timezone place matching … or …
    2. exact country name matching … via “wrapper style” Javascript function …
      <?php echo ”

      function vpmaybe(placeidea, ctyidea) {
      if (yourtzlist.toLowerCase().indexOf('/' + placeidea.toLowerCase() + "'") != -1) {
      vprefix=yourtzlist.toUpperCase().split('/' + placeidea.toUpperCase() + "'")[1].split(',')[3] + ';';
      } else if (ctyidea != '') {
      for (var imm=1; imm<icc.length; imm+=2) {
      if (ctyidea.toLowerCase().replace(/\_/g,' ') == icc[imm].toLowerCase().replace(/\_/g,' ')) {
      vprefix=icc[eval(-1 + imm)].toUpperCase() + ';';
      }
      }
      }
      return placeidea.replace(/\_/g,' ');
      }

      “; ?>

    … that way being able to present a Geo Chart honed in on that country in the first instance, and the user being able to click a link to turn that into a world view, as they see fit

Codewise …


Previous relevant Distance Interfacing to Google Chart Geo Chart Tutorial is shown below.

Distance Interfacing to Google Chart Geo Chart Tutorial

Distance Interfacing to Google Chart Geo Chart Tutorial

Today, we’re changing the primary interfacing mode of Change the Weather Tutorial‘s Distance via Geographicals web application …

  • from trying to interface to Weather APIs …
  • to interfacing to the Google Charts Geo Chart, via an emoji button 🌐 hover or click, and it’s own menu of functionality, presented as the call is made

We needed new interfacing protocols to the “child” Geo Chart interfacer to make this possible …

<?php echo ”

if (window.self !== window.top && ('' + top.document.URL).indexOf('/PHP/Distance') == -1) {
ournamec=ournamec;
} else if (documentURL.indexOf('?title=') != -1 && documentURL.indexOf('&') == -1 && documentURL.indexOf('#') == -1) {
var lho=0;
var ourico='';
var ourpl='';
var ourti=location.search.split('title=')[1] ? decodeURIComponent(location.search.split('title=')[1].split('&')[0]) : '';
//alert('Ourti=' + ourti);
if (eval('' + ourti.split(',').length) >= 2) {
lho=eval(-2 + ourti.split(',').length);
var ourlgis=ourti.split(',')[eval(-1 + ourti.split(',').length)];
ourico=ourti.split(';')[0];
if (eval('' + ourico.length) == 2) {
ourti=ourti.replace(ourico + ';','');
ourico=ourico.toUpperCase();
} else {
ourico='';
}
var ourltis='', sparet='';
var slc=-1;
while (ourti.split(',')[lho].slice(slc).substring(0,1).replace('-','0').replace('.','0') >= '0' && ourti.split(',')[lho].slice(slc).substring(0,1).replace('-','0').replace('.','0') <= '9' && Math.abs(slc) <= eval('' + ourti.split(',')[lho].length)) {
sparet=ourltis;
ourltis=ourti.split(',')[lho].slice(slc).substring(0,1) + sparet;
//alert('ourltis =' + ourltis);
slc--;
}
if (lho != 0) {
ourpl=ourti.split('' + ourltis)[0];
} else if (ourltis != ourti.split(',')[0]) {
ourpl=ourti.split(',')[0].replace(ourltis,'');
}
//alert('ourltis=' + ourltis);
var winobj=window.self;
var jgeo='ifcountries';
winobj.document.getElementById(jgeo).style.position='absolute';
winobj.document.getElementById(jgeo).style.top='0px';
winobj.document.getElementById(jgeo).style.left='0px';
winobj.document.getElementById(jgeo).style.width='100%';
winobj.document.getElementById(jgeo).style.height='100%';
winobj.document.getElementById(jgeo).style.opacity='1.0';
winobj.document.getElementById(jgeo).style.zIndex='44';
winobj.document.getElementById(jgeo).style.display='block';
if (ournamec != '') {
if (ourpl != '') {
ourpl+=', ';
}
}
if (ournamec != '') {
if (ourico != '') {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + ourico + encodeURIComponent(';') + encodeURIComponent(ourpl + ournamec) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl + ournamec) + '~,2]';
//alert('1:' + winobj.document.getElementById(jgeo).src);
} else {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(ourpl + ournamec) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl + ournamec) + '~,2]';
//alert('2:' + winobj.document.getElementById(jgeo).src);
}
} else if (ourpl != '') {
if (ourico != '') {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + ourico + encodeURIComponent(';') + encodeURIComponent(ourpl) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl) + '~,2]';
//alert('3:' + winobj.document.getElementById(jgeo).src);
} else {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(ourpl) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl) + '~,2]';
//alert('4:' + winobj.document.getElementById(jgeo).src);
}
} else if (ourico != '') {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + ourico + encodeURIComponent(';') + 'My%20Place&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~My%20Place~,2]';
//alert('5:' + winobj.document.getElementById(jgeo).src);
} else {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=My%20Place&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~My%20Place~,2]';
//alert('6:' + winobj.document.getElementById(jgeo).src);
}
setTimeout(function(){ latergmenu(ourpl + ournamec, ourltis, ourlgis); }, 10000);
}
}

“; ?>

… and new Javascript functions up at “parent” Distance via Geographicals PHP …

<?php echo ”

function smartemoji() {
setTimeout(function(){
document.getElementById('topa').innerHTML='&#127760;';
document.getElementById('bottoma').innerHTML='&#127760;';
}, 5000);
}

function smartcha(iamvalue, iamid, aois) {
var vval='', vplace='', vcountry='';
if (aois.id == 'topa') {
vval=document.getElementById('from').value;
if (vval.indexOf('country=') != -1 && vval.indexOf('fromplace=') != -1) {
vplace=vval.split('fromplace=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
} else if (vval.indexOf('country=') != -1 && vval.indexOf('place=') != -1) {
vplace=vval.split('olace=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
}
} else {
vval=document.getElementById('to').value;
//alert(vval);
if (vval.indexOf('country=') != -1 && vval.indexOf('&place=') != -1) {
vplace=vval.split('&place=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
//alert(iamid + ' ' + vplace + vcountry);
} else if (vval.indexOf('country=') != -1 && vval.indexOf('fromplace=') != -1) {
vplace=vval.split('fromplace=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
}
}
if (iamvalue.indexOf("-0") != -1) {
var latd=document.getElementById("latd");
var latm=document.getElementById("latm");
var lats=document.getElementById("lats");
var longd=document.getElementById("longd");
var longm=document.getElementById("longm");
var longs=document.getElementById("longs");

if (iamid == "gnols") {
latd=document.getElementById("tald");
latm=document.getElementById("talm");
lats=document.getElementById("tals");
longd=document.getElementById("gnold");
longm=document.getElementById("gnolm");
longs=document.getElementById("gnols");
}

var latsign = "+";
if (latd.value.replace("-", "") != latd.value) latsign = "-";
var longsign = "+";
if (longd.value.replace("-", "") != longd.value) longsign = "-";
var alat = eval(latd.value);
alat = Math.abs(alat);
var alatsuffix = 0;
var along = eval(longd.value);
along = Math.abs(along);
var alongsuffix = 0;
if (latm.value != "0" || lats.value != "0") {
alatsuffix = eval((latm.value) / 60.0);
alatsuffix = eval(alatsuffix + (lats.value) / 3600.0);
} else if (latd.value.replace(".", "") != latd.value) {
alatsuffix = 0;
}
if (longm.value != "0" || longs.value != "0") {
alongsuffix = eval((longm.value) / 60.0);
alongsuffix = eval(alongsuffix + (longs.value) / 3600.0);
} else if (longd.value.replace(".", "") != longd.value) {
alongsuffix = 0;
}

var lata = eval(alatsuffix + alat);
var latis=latsign + lata;
var xlatis = latis.replace("-", "").replace("+", "");
if (xlatis == latis) latis = "+" + latis;
var longa = eval(alongsuffix + along);
var longis=longsign + longa;
var retis = ["", ""];

if (iamid == "gnols") {
document.getElementById("weatherto").style.display = 'block';
//retis = find_nearest(latis, longis);
//alert(retis[0] + " then " + retis[1]);
document.getElementById("weatherto").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
} else if (iamid == "longs") {
document.getElementById("weatherfrom").style.display = 'block';
//retis = find_nearest(latis, longis);
//alert(retis[0] + " tHen " + retis[1]);
document.getElementById("weatherfrom").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
}
}
}

“; ?>

… to make this happen.

Codewise …


Previous relevant Change the Weather Tutorial is shown below.

Change the Weather Tutorial

Change the Weather Tutorial

Today’s tutorial’s title is a bit cheekier than it really is, as we talk about a change to the software integration of a Weather Reporting web service for the geographicals suite here at this blog. The previous arrangements we detailed below at Integrating Global Weather Ajax with Geographicals Tutorial as shown below.

The previous weather reporting integration used a Web Service and for the changed arrangement we more or less screen scrape with the wonderfully generous World Weather Online website … thanks a lot. And thanks, too, for the link that helped me find this website, as well as the excellent link here that helped with the international country codes that came in handy for the changed arrangements.

Wanted to more or less have the changes in one place and it more or less happened that way, with the vast majority of changes needed to the called get_weather.php code. The calling place_latlong.php called get_weather.php in a different place, but this is only done because am not overly certain the old arrangements will not resurrect themselves. The old way was a bit different in that it did not need any State/Territory type information to proceed, but sometimes our screen scraping method does need to ask for this information.

Think it is good with software integration to aim to keep at least one aspect of the resultant code the same, and so it is here, with the same iframe and Ajax arrangements kept.

Did you know?

If you’ve examined, closely, the changes to get_weather.php above you may have wondered how I could get away with URLs involving city and country (codes) and sometimes state parts and yet, with the code, we are pretty slack about uppercase/lowercase stringency. However, did you notice the URL template we first got as a model to try to achieve …

HTTP://www.worldweatheronline.com/CHITTAGONG-weather/BD.ASPX

… the .ASPX extension tells you this is ASP.Net and would be hosted on a Windows server (and this all happens courtesy of the early days with MS-DOS and some interesting file naming informational link is here), where files in uppercase are the same as those in lowercase or a mix of both, and in this way we get away with some slackness regarding the construction of our URL. If the hosting was Linux or Unix there would be a much more complicated task needed by the programmer, or, as would probably be more likely the case, the website URLs would be arranged differently.


Previous weather integration with geographicals suite via GlobalWeather Integrating Global Weather Ajax with Geographicals Tutorial is shown below.

Integrating Global Weather Ajax with Geographicals Tutorial

Integrating Global Weather Ajax with Geographicals Tutorial

Today’s tutorial is all about software integration and complements yesterday’s Integrating Global Weather into Geographicals Tutorial as shown below.

Software integration takes many forms, and Ajax functionality is that little bit different, perhaps, in that with the tablet and mobile phone “touch” (with all its associated terminology like “gesture recognition”, “pinch” and “smart zoom”) is a concept, with more currency than the “click” and “hover” (of the original web-based systems) and this has increased the choices for ways to achieve things, with there being more accepted mobile world “ways” sometimes a bit different to the laptop/notebook/desktop “ways”. For instance, with Ajax, and the laptop/notebook/desktop world, I tend to want to do a lot with the “hover” (onmouseover) event, but this does not always translate well in the mobile phone/tablet world. In the mobile phone/tablet world multiple window use can get a bit awkward with the smaller screens.

In today’s tutorial we show some integration techniques using HTML “select” (dropdown) and/or
“<a …><img … /></a>” (button) approaches, with the “hover” event doing the same as the “click” event. Whether you like this approach is debatable and you may want to trial such approaches with potential users when you come to creating commercial products. Ideally with catering for all of mobile phone, tablet, desktop and laptop/notebook users you can use the same base code (you may disagree here), with Javascript, HTML and CSS methods employed to compartmentalize device-dependent code using all the various forms of “if” in the softwares.

So the “Get the Weather” functionality of two days ago has a geographical component, that is for sure … the “where” in life is soooo programmable, isn’t it? … so we can integrate it into other Geographical software components we’ve been developing here on this blog.

Today’s part two (of two) of integration tasks, which includes the requirement that some Geographicals of unknown placename should “map” themselves to the nearest placename (via a function called find_nearest (with respect to whatever data source your software uses)), adds the “Get the Weather” Ajax software functionality to each of the “independent child” functions of the Geographicals suite … Sun Angles, Moon Angles, Great Circle Distance and Coriolis Force. Part one (of two) of integration tasks of yesterday was to associate the “Get the Weather” with a placename in the world. This is the more obvious integration task and we show two bits of integration to make that happen way below.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Sun Angles functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Moon Angles functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Great Circle Distance functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Coriolis Force functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the Geographical supervisor of the “Get the Weather” software component (and others) here.

And here is the “independent child” Sun Angles live run (which now includes “Get the Weather”).

And here is the “independent child” Moon Angles live run (which now includes “Get the Weather”).

And here is the “independent child” Great Circle Distance live run (which now includes “Get the Weather”).

And here is the “independent child” Coriolis Force live run (which now includes “Get the Weather”).

And finally here is the “supervisory” live run to test all the integration (which now includes “Get the Weather”) yourself.


Previous relevant Integrating Global Weather into Geographicals Tutorial is shown below.

Integrating Global Weather into Geographicals Tutorial

Integrating Global Weather into Geographicals Tutorial

Today’s tutorial is all about software integration and builds on yesterday’s Ajax Global Weather HTTP Get Primer Tutorial as shown below.

Sometimes (well, in my experience) you get the best “kick” out of integrating software components, rather than the writing of the component itself. Sounds weird, doesn’t it, but the fact is, the more functionality you can build into existing software frameworks you have built up, the more useful software becomes, rather than a whole lot of disparate functionality, which may be very cute, but the procedures for which can be forgotten by people in the length of time it takes to wander up the hallway with the mobile phone attached to one’s cranium (would the Queen do this?!).

So yesterday’s “Get the Weather” functionality has a geographical component, that is for sure … the “where” in life is soooo programmable, isn’t it? … so we can integrate it into other Geographical software components we’ve been developing here on this blog.

Part one (of two) of integration tasks is to associate the “Get the Weather” with a placename in the world. This is the more obvious integration task and we show two bits of integration to make that happen below.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component (from tutorial below) here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the Geographical supervisor of the “Get the Weather” software component (and others) here … lots of the changes here involve readiness for the other piece of integration that we will cover at another tutorial tomorrow.

And finally here is the live run to test all the integration (which now includes “Get the Weather”) yourself.


Previous relevant Ajax Global Weather HTTP Get Primer Tutorial is shown below.

Ajax Global Weather HTTP Get Primer Tutorial

Ajax Global Weather HTTP Get Primer Tutorial

Ajax techniques make your web pages very dynamic and useful, and there will be fewer changes of webpage required when using Ajax, because information derived from a data source (maybe a feed, maybe a database read, maybe a local source of data, maybe a web service website (as for this tutorial … thanks to GlobalWeather here)) make many changes of webpage obsolete.

Today we use HTTP Get methods to procure the data, but you will see other methods that can be used on that link above.

Let’s have a look at Wikipedia’s thoughts on Ajax below.

Ajax (also AJAX; /ˈeɪdʒæks/; an acronym for Asynchronous JavaScript and XML)[1] is a group of interrelated web development techniques used on the client-side to create asynchronous web applications. With Ajax, web applications can send data to, and retrieve data from, a server asynchronously (in the background) without interfering with the display and behavior of the existing page. Data can be retrieved using the XMLHttpRequest object. Despite the name, the use of XML is not required (JSON is often used instead. See AJAJ), and the requests do not need to be asynchronous.[2]

Ajax is not a single technology, but a group of technologies. HTML and CSS can be used in combination to mark up and style information. The DOM is accessed with JavaScript to dynamically display, and allow the user to interact with, the information presented. JavaScript and the XMLHttpRequest object provide a method for exchanging data asynchronously between browser and server to avoid full page reloads.

Have a look at the PHP downloadable code which you could rename to get_weather.php
Try a live run here.


Previous relevant Ajax Preview Window Tutorial is shown below.

Ajax Preview Window Tutorial

Ajax Preview Window Tutorial

Ajax is a client-side meets server-side melding of PHP (or ASP.Net) and Javascript and HTML and CSS and allows you to stay on the web page you are on doing many more things, rather than constantly changing web pages the way that HTML form tag makes you do. Ajax works with XMLHttpRequest object to quiz the server-side while staying on the client side. You may have guessed that we have been working up to this, and I refer you to the previous tutorial about JavaScript and the DOM Tutorial and PHP + JavaScript + HTML Primer Tutorial for important information to learn before tackling Ajax. Ajax shares similar restrictions to iFrames in limiting you to work within your own domain, generally speaking. Ajax normally makes use of the onmouseover (hence the amateurish added rendition of a cursor, where I was hovering over the option tag, but couldn’t take a snapshot of this … ie. too lazy to get the camera!) and onmouseout events of HTML elements and you may notice the less than ideal Internet Explorer behaviour for this Ajax code, and that is because for Internet Explorer the option tag has no onmouseover nor onmouseout event defined, so we did an awful kludge.

Earlier tutorials …

JavaScript is a tremendous web client-side language to learn. You may have heard of a server-side JavaScript, but this tutorial only deals with client-side work. This tutorial builds a JavaScript layer on top of the PHP tutorial made earlier, showing how the DOM can be used to change the look of your webpage dynamically, even if most of it is in an iFrame (but there are limits).

PHP is a wonderful language to learn. It is usually associated with being a web server-side language (as with this tutorial, where it is being shown on a local MAMP web server) but can be a command line tool as well. If you like PHP you may eventually like ASP.Net and/or Python, and vice versa. It has sophisticated data structures, Object Oriented (the thinking that you can build classes with data and methods which define objects created as you run the program … eg. you might write a class for book and have data members for things like numPages and publisher, author, creationDate and have methods called things like getCreationDate, setCreationDate, getAuthor, setAuthor allowing the user to use these methods rather than changing the data members themselves … heaven forbid that!) code concepts, and really combines well with JavaScript (as a client-side language).

Download programming source code and rename to ajax.php (but Ajax only works within the domain you use it, and this code mentions www.rjmprogramming.com.au so just use it for reference purposes or rewrite for purposes that suit you within your domain of interest).

Regarding this topic I really like “JavaScript & Ajax” seventh edition by Tom Negrino and Dori Smith

Did you know …
JavaScript makes a great easy-access Calculator?

Try typing the lines below into the address bar of your favourite browser:

Javascript: eval(512 / 380);
Javascript: eval(512 * 380);
Javascript: eval(512 – 380);
Javascript: eval(512 + 380);
Javascript: eval(512 % 380);

These days we spend so much time on the Internet it is a much quicker way to get to a calculator!

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


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


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


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


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


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


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

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

Distance Interfacing to Google Chart Geo Chart Tutorial

Distance Interfacing to Google Chart Geo Chart Tutorial

Distance Interfacing to Google Chart Geo Chart Tutorial

Today, we’re changing the primary interfacing mode of Change the Weather Tutorial‘s Distance via Geographicals web application …

  • from trying to interface to Weather APIs …
  • to interfacing to the Google Charts Geo Chart, via an emoji button 🌐 hover or click, and it’s own menu of functionality, presented as the call is made

We needed new interfacing protocols to the “child” Geo Chart interfacer to make this possible …

<?php echo ”

if (window.self !== window.top && ('' + top.document.URL).indexOf('/PHP/Distance') == -1) {
ournamec=ournamec;
} else if (documentURL.indexOf('?title=') != -1 && documentURL.indexOf('&') == -1 && documentURL.indexOf('#') == -1) {
var lho=0;
var ourico='';
var ourpl='';
var ourti=location.search.split('title=')[1] ? decodeURIComponent(location.search.split('title=')[1].split('&')[0]) : '';
//alert('Ourti=' + ourti);
if (eval('' + ourti.split(',').length) >= 2) {
lho=eval(-2 + ourti.split(',').length);
var ourlgis=ourti.split(',')[eval(-1 + ourti.split(',').length)];
ourico=ourti.split(';')[0];
if (eval('' + ourico.length) == 2) {
ourti=ourti.replace(ourico + ';','');
ourico=ourico.toUpperCase();
} else {
ourico='';
}
var ourltis='', sparet='';
var slc=-1;
while (ourti.split(',')[lho].slice(slc).substring(0,1).replace('-','0').replace('.','0') >= '0' && ourti.split(',')[lho].slice(slc).substring(0,1).replace('-','0').replace('.','0') <= '9' && Math.abs(slc) <= eval('' + ourti.split(',')[lho].length)) {
sparet=ourltis;
ourltis=ourti.split(',')[lho].slice(slc).substring(0,1) + sparet;
//alert('ourltis =' + ourltis);
slc--;
}
if (lho != 0) {
ourpl=ourti.split('' + ourltis)[0];
} else if (ourltis != ourti.split(',')[0]) {
ourpl=ourti.split(',')[0].replace(ourltis,'');
}
//alert('ourltis=' + ourltis);
var winobj=window.self;
var jgeo='ifcountries';
winobj.document.getElementById(jgeo).style.position='absolute';
winobj.document.getElementById(jgeo).style.top='0px';
winobj.document.getElementById(jgeo).style.left='0px';
winobj.document.getElementById(jgeo).style.width='100%';
winobj.document.getElementById(jgeo).style.height='100%';
winobj.document.getElementById(jgeo).style.opacity='1.0';
winobj.document.getElementById(jgeo).style.zIndex='44';
winobj.document.getElementById(jgeo).style.display='block';
if (ournamec != '') {
if (ourpl != '') {
ourpl+=', ';
}
}
if (ournamec != '') {
if (ourico != '') {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + ourico + encodeURIComponent(';') + encodeURIComponent(ourpl + ournamec) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl + ournamec) + '~,2]';
//alert('1:' + winobj.document.getElementById(jgeo).src);
} else {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(ourpl + ournamec) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl + ournamec) + '~,2]';
//alert('2:' + winobj.document.getElementById(jgeo).src);
}
} else if (ourpl != '') {
if (ourico != '') {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + ourico + encodeURIComponent(';') + encodeURIComponent(ourpl) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl) + '~,2]';
//alert('3:' + winobj.document.getElementById(jgeo).src);
} else {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(ourpl) + '&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~' + encodeURIComponent(ourpl) + '~,2]';
//alert('4:' + winobj.document.getElementById(jgeo).src);
}
} else if (ourico != '') {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + ourico + encodeURIComponent(';') + 'My%20Place&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~My%20Place~,2]';
//alert('5:' + winobj.document.getElementById(jgeo).src);
} else {
winobj.document.getElementById(jgeo).src='//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=My%20Place&aregexographicals=y&aregeographicals=&width=500&height=312&onclick=y&country=Places&popularity=&data=%20[' + ourltis + '|' + ourlgis + '|~My%20Place~,2]';
//alert('6:' + winobj.document.getElementById(jgeo).src);
}
setTimeout(function(){ latergmenu(ourpl + ournamec, ourltis, ourlgis); }, 10000);
}
}

“; ?>

… and new Javascript functions up at “parent” Distance via Geographicals PHP …

<?php echo ”

function smartemoji() {
setTimeout(function(){
document.getElementById('topa').innerHTML='&#127760;';
document.getElementById('bottoma').innerHTML='&#127760;';
}, 5000);
}

function smartcha(iamvalue, iamid, aois) {
var vval='', vplace='', vcountry='';
if (aois.id == 'topa') {
vval=document.getElementById('from').value;
if (vval.indexOf('country=') != -1 && vval.indexOf('fromplace=') != -1) {
vplace=vval.split('fromplace=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
} else if (vval.indexOf('country=') != -1 && vval.indexOf('place=') != -1) {
vplace=vval.split('olace=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
}
} else {
vval=document.getElementById('to').value;
//alert(vval);
if (vval.indexOf('country=') != -1 && vval.indexOf('&place=') != -1) {
vplace=vval.split('&place=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
//alert(iamid + ' ' + vplace + vcountry);
} else if (vval.indexOf('country=') != -1 && vval.indexOf('fromplace=') != -1) {
vplace=vval.split('fromplace=')[1].split('&')[0].split('#')[0];
vcountry=vval.split('country=')[1].split('&')[0].split('#')[0];
if (vcountry != '' && vplace != '') {
vplace+=', ';
}
}
}
if (iamvalue.indexOf("-0") != -1) {
var latd=document.getElementById("latd");
var latm=document.getElementById("latm");
var lats=document.getElementById("lats");
var longd=document.getElementById("longd");
var longm=document.getElementById("longm");
var longs=document.getElementById("longs");

if (iamid == "gnols") {
latd=document.getElementById("tald");
latm=document.getElementById("talm");
lats=document.getElementById("tals");
longd=document.getElementById("gnold");
longm=document.getElementById("gnolm");
longs=document.getElementById("gnols");
}

var latsign = "+";
if (latd.value.replace("-", "") != latd.value) latsign = "-";
var longsign = "+";
if (longd.value.replace("-", "") != longd.value) longsign = "-";
var alat = eval(latd.value);
alat = Math.abs(alat);
var alatsuffix = 0;
var along = eval(longd.value);
along = Math.abs(along);
var alongsuffix = 0;
if (latm.value != "0" || lats.value != "0") {
alatsuffix = eval((latm.value) / 60.0);
alatsuffix = eval(alatsuffix + (lats.value) / 3600.0);
} else if (latd.value.replace(".", "") != latd.value) {
alatsuffix = 0;
}
if (longm.value != "0" || longs.value != "0") {
alongsuffix = eval((longm.value) / 60.0);
alongsuffix = eval(alongsuffix + (longs.value) / 3600.0);
} else if (longd.value.replace(".", "") != longd.value) {
alongsuffix = 0;
}

var lata = eval(alatsuffix + alat);
var latis=latsign + lata;
var xlatis = latis.replace("-", "").replace("+", "");
if (xlatis == latis) latis = "+" + latis;
var longa = eval(alongsuffix + along);
var longis=longsign + longa;
var retis = ["", ""];

if (iamid == "gnols") {
document.getElementById("weatherto").style.display = 'block';
//retis = find_nearest(latis, longis);
//alert(retis[0] + " then " + retis[1]);
document.getElementById("weatherto").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
} else if (iamid == "longs") {
document.getElementById("weatherfrom").style.display = 'block';
//retis = find_nearest(latis, longis);
//alert(retis[0] + " tHen " + retis[1]);
document.getElementById("weatherfrom").src = '//www.rjmprogramming.com.au/PHP/GeoChart/geo_chart.php?title=' + encodeURIComponent(vplace + vcountry) + encodeURIComponent(latsign.replace('+','')) + ('' + latis).replace('-','').replace('+','').trim() + encodeURIComponent(',') + encodeURIComponent(longsign.replace('+','')) + ('' + longis).replace('-','').replace('+','').trim();
}
}
}

“; ?>

… to make this happen.

Codewise …


Previous relevant Change the Weather Tutorial is shown below.

Change the Weather Tutorial

Change the Weather Tutorial

Today’s tutorial’s title is a bit cheekier than it really is, as we talk about a change to the software integration of a Weather Reporting web service for the geographicals suite here at this blog. The previous arrangements we detailed below at Integrating Global Weather Ajax with Geographicals Tutorial as shown below.

The previous weather reporting integration used a Web Service and for the changed arrangement we more or less screen scrape with the wonderfully generous World Weather Online website … thanks a lot. And thanks, too, for the link that helped me find this website, as well as the excellent link here that helped with the international country codes that came in handy for the changed arrangements.

Wanted to more or less have the changes in one place and it more or less happened that way, with the vast majority of changes needed to the called get_weather.php code. The calling place_latlong.php called get_weather.php in a different place, but this is only done because am not overly certain the old arrangements will not resurrect themselves. The old way was a bit different in that it did not need any State/Territory type information to proceed, but sometimes our screen scraping method does need to ask for this information.

Think it is good with software integration to aim to keep at least one aspect of the resultant code the same, and so it is here, with the same iframe and Ajax arrangements kept.

Did you know?

If you’ve examined, closely, the changes to get_weather.php above you may have wondered how I could get away with URLs involving city and country (codes) and sometimes state parts and yet, with the code, we are pretty slack about uppercase/lowercase stringency. However, did you notice the URL template we first got as a model to try to achieve …

HTTP://www.worldweatheronline.com/CHITTAGONG-weather/BD.ASPX

… the .ASPX extension tells you this is ASP.Net and would be hosted on a Windows server (and this all happens courtesy of the early days with MS-DOS and some interesting file naming informational link is here), where files in uppercase are the same as those in lowercase or a mix of both, and in this way we get away with some slackness regarding the construction of our URL. If the hosting was Linux or Unix there would be a much more complicated task needed by the programmer, or, as would probably be more likely the case, the website URLs would be arranged differently.


Previous weather integration with geographicals suite via GlobalWeather Integrating Global Weather Ajax with Geographicals Tutorial is shown below.

Integrating Global Weather Ajax with Geographicals Tutorial

Integrating Global Weather Ajax with Geographicals Tutorial

Today’s tutorial is all about software integration and complements yesterday’s Integrating Global Weather into Geographicals Tutorial as shown below.

Software integration takes many forms, and Ajax functionality is that little bit different, perhaps, in that with the tablet and mobile phone “touch” (with all its associated terminology like “gesture recognition”, “pinch” and “smart zoom”) is a concept, with more currency than the “click” and “hover” (of the original web-based systems) and this has increased the choices for ways to achieve things, with there being more accepted mobile world “ways” sometimes a bit different to the laptop/notebook/desktop “ways”. For instance, with Ajax, and the laptop/notebook/desktop world, I tend to want to do a lot with the “hover” (onmouseover) event, but this does not always translate well in the mobile phone/tablet world. In the mobile phone/tablet world multiple window use can get a bit awkward with the smaller screens.

In today’s tutorial we show some integration techniques using HTML “select” (dropdown) and/or
“<a …><img … /></a>” (button) approaches, with the “hover” event doing the same as the “click” event. Whether you like this approach is debatable and you may want to trial such approaches with potential users when you come to creating commercial products. Ideally with catering for all of mobile phone, tablet, desktop and laptop/notebook users you can use the same base code (you may disagree here), with Javascript, HTML and CSS methods employed to compartmentalize device-dependent code using all the various forms of “if” in the softwares.

So the “Get the Weather” functionality of two days ago has a geographical component, that is for sure … the “where” in life is soooo programmable, isn’t it? … so we can integrate it into other Geographical software components we’ve been developing here on this blog.

Today’s part two (of two) of integration tasks, which includes the requirement that some Geographicals of unknown placename should “map” themselves to the nearest placename (via a function called find_nearest (with respect to whatever data source your software uses)), adds the “Get the Weather” Ajax software functionality to each of the “independent child” functions of the Geographicals suite … Sun Angles, Moon Angles, Great Circle Distance and Coriolis Force. Part one (of two) of integration tasks of yesterday was to associate the “Get the Weather” with a placename in the world. This is the more obvious integration task and we show two bits of integration to make that happen way below.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Sun Angles functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Moon Angles functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Great Circle Distance functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component of the Coriolis Force functionality here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the Geographical supervisor of the “Get the Weather” software component (and others) here.

And here is the “independent child” Sun Angles live run (which now includes “Get the Weather”).

And here is the “independent child” Moon Angles live run (which now includes “Get the Weather”).

And here is the “independent child” Great Circle Distance live run (which now includes “Get the Weather”).

And here is the “independent child” Coriolis Force live run (which now includes “Get the Weather”).

And finally here is the “supervisory” live run to test all the integration (which now includes “Get the Weather”) yourself.


Previous relevant Integrating Global Weather into Geographicals Tutorial is shown below.

Integrating Global Weather into Geographicals Tutorial

Integrating Global Weather into Geographicals Tutorial

Today’s tutorial is all about software integration and builds on yesterday’s Ajax Global Weather HTTP Get Primer Tutorial as shown below.

Sometimes (well, in my experience) you get the best “kick” out of integrating software components, rather than the writing of the component itself. Sounds weird, doesn’t it, but the fact is, the more functionality you can build into existing software frameworks you have built up, the more useful software becomes, rather than a whole lot of disparate functionality, which may be very cute, but the procedures for which can be forgotten by people in the length of time it takes to wander up the hallway with the mobile phone attached to one’s cranium (would the Queen do this?!).

So yesterday’s “Get the Weather” functionality has a geographical component, that is for sure … the “where” in life is soooo programmable, isn’t it? … so we can integrate it into other Geographical software components we’ve been developing here on this blog.

Part one (of two) of integration tasks is to associate the “Get the Weather” with a placename in the world. This is the more obvious integration task and we show two bits of integration to make that happen below.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the “Get the Weather” software component (from tutorial below) here.

Here is a new link to some downloadable PHP programming source code explaining changes made specifically for the Geographical supervisor of the “Get the Weather” software component (and others) here … lots of the changes here involve readiness for the other piece of integration that we will cover at another tutorial tomorrow.

And finally here is the live run to test all the integration (which now includes “Get the Weather”) yourself.


Previous relevant Ajax Global Weather HTTP Get Primer Tutorial is shown below.

Ajax Global Weather HTTP Get Primer Tutorial

Ajax Global Weather HTTP Get Primer Tutorial

Ajax techniques make your web pages very dynamic and useful, and there will be fewer changes of webpage required when using Ajax, because information derived from a data source (maybe a feed, maybe a database read, maybe a local source of data, maybe a web service website (as for this tutorial … thanks to GlobalWeather here)) make many changes of webpage obsolete.

Today we use HTTP Get methods to procure the data, but you will see other methods that can be used on that link above.

Let’s have a look at Wikipedia’s thoughts on Ajax below.

Ajax (also AJAX; /ˈeɪdʒæks/; an acronym for Asynchronous JavaScript and XML)[1] is a group of interrelated web development techniques used on the client-side to create asynchronous web applications. With Ajax, web applications can send data to, and retrieve data from, a server asynchronously (in the background) without interfering with the display and behavior of the existing page. Data can be retrieved using the XMLHttpRequest object. Despite the name, the use of XML is not required (JSON is often used instead. See AJAJ), and the requests do not need to be asynchronous.[2]

Ajax is not a single technology, but a group of technologies. HTML and CSS can be used in combination to mark up and style information. The DOM is accessed with JavaScript to dynamically display, and allow the user to interact with, the information presented. JavaScript and the XMLHttpRequest object provide a method for exchanging data asynchronously between browser and server to avoid full page reloads.

Have a look at the PHP downloadable code which you could rename to get_weather.php
Try a live run here.


Previous relevant Ajax Preview Window Tutorial is shown below.

Ajax Preview Window Tutorial

Ajax Preview Window Tutorial

Ajax is a client-side meets server-side melding of PHP (or ASP.Net) and Javascript and HTML and CSS and allows you to stay on the web page you are on doing many more things, rather than constantly changing web pages the way that HTML form tag makes you do. Ajax works with XMLHttpRequest object to quiz the server-side while staying on the client side. You may have guessed that we have been working up to this, and I refer you to the previous tutorial about JavaScript and the DOM Tutorial and PHP + JavaScript + HTML Primer Tutorial for important information to learn before tackling Ajax. Ajax shares similar restrictions to iFrames in limiting you to work within your own domain, generally speaking. Ajax normally makes use of the onmouseover (hence the amateurish added rendition of a cursor, where I was hovering over the option tag, but couldn’t take a snapshot of this … ie. too lazy to get the camera!) and onmouseout events of HTML elements and you may notice the less than ideal Internet Explorer behaviour for this Ajax code, and that is because for Internet Explorer the option tag has no onmouseover nor onmouseout event defined, so we did an awful kludge.

Earlier tutorials …

JavaScript is a tremendous web client-side language to learn. You may have heard of a server-side JavaScript, but this tutorial only deals with client-side work. This tutorial builds a JavaScript layer on top of the PHP tutorial made earlier, showing how the DOM can be used to change the look of your webpage dynamically, even if most of it is in an iFrame (but there are limits).

PHP is a wonderful language to learn. It is usually associated with being a web server-side language (as with this tutorial, where it is being shown on a local MAMP web server) but can be a command line tool as well. If you like PHP you may eventually like ASP.Net and/or Python, and vice versa. It has sophisticated data structures, Object Oriented (the thinking that you can build classes with data and methods which define objects created as you run the program … eg. you might write a class for book and have data members for things like numPages and publisher, author, creationDate and have methods called things like getCreationDate, setCreationDate, getAuthor, setAuthor allowing the user to use these methods rather than changing the data members themselves … heaven forbid that!) code concepts, and really combines well with JavaScript (as a client-side language).

Download programming source code and rename to ajax.php (but Ajax only works within the domain you use it, and this code mentions www.rjmprogramming.com.au so just use it for reference purposes or rewrite for purposes that suit you within your domain of interest).

Regarding this topic I really like “JavaScript & Ajax” seventh edition by Tom Negrino and Dori Smith

Did you know …
JavaScript makes a great easy-access Calculator?

Try typing the lines below into the address bar of your favourite browser:

Javascript: eval(512 / 380);
Javascript: eval(512 * 380);
Javascript: eval(512 – 380);
Javascript: eval(512 + 380);
Javascript: eval(512 % 380);

These days we spend so much time on the Internet it is a much quicker way to get to a calculator!

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


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


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


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


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


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

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

English Translated Verb Conjugation Countdown Timer Tutorial

English Translated Verb Conjugation Countdown Timer Tutorial

English Translated Verb Conjugation Countdown Timer Tutorial

We had occasion to revisit our inhouse Italian/French/Spanish Verb Conjugation web application “redirector” (in that it is third parties doing the bulk of the work, thanks), further to the English Translated Verb Conjugation Emoji Tutorial‘s last mention.

It struck us, that what could improve the user experience, could be a …

  • 30 second (timed for) …
  • automated click piece of functionality … that is flagged to the user via a …
  • countdown timer (presented as an HTML progress …

    <progress id=myprog title="Click to stop the automated countdown to clicking for conjugations screen" data-allow="y" onclick="this.setAttribute('data-allow','');" style=visibility:hidden; value=30 max=30 min=0></progress>

    … element) …
  • that if clicked, holds off on the automation ideas regarding the Conjugation Emoji Button 📖 clicking …

    function backin() {
    if (myxhr.readyState == 4) {
    if (myxhr.status == 200) {
    if (myxhr.responseText) {
    var towrds=myxhr.responseText.split('"translatedText":"');
    //alert('' + myxhr.responseText);
    if (eval('' + towrds.length) >= 2) {
    //if (myxhr.responseText.indexOf('correre') != -1) { alert(towrds[2]); alert(towrds[1]); alert(towrds[3]); alert(towrds[4]); }
    document.getElementById('ini').value='';
    document.getElementById('ini').placeholder=towrds[1].split('"')[0].split('.')[0].split('!')[0].split('?')[0].replace(/\'/g,'');
    document.getElementById('emojiconjugate').innerHTML='&#128214;'; //' <progress id=myprog title="Click to stop the automated countdown to clicking for conjugations screen" data-allow="y" onclick="event.stopProgagation(); this.setAttribute(' + "'data-allow',''" + '); return false;" style=display:inline-block; value=30 max=30 min=0></progress>';
    document.getElementById('myprog').value=30;
    document.getElementById('myprog').setAttribute('data-allow','y');
    if (1 == 1) {
    document.getElementById('myprog').style.visibility='visible';
    } else {
    document.getElementById('myprog').style.display='inline-block';
    }
    setTimeout(myprogit, 1000);
    setTimeout(function(){
    if (eval('' + ('' + document.getElementById('myprog').getAttribute('data-allow').length)) > 0) {
    document.getElementById('emojiconjugate').click();
    }
    }, 30000);

    }
    }
    }
    }
    }

    function myprogit() {
    if (document.getElementById('myprog')) {
    if (eval('' + ('' + document.getElementById('myprog').getAttribute('data-allow').length)) == 0) {
    if (1 == 1) {
    document.getElementById('myprog').style.visibility='hidden';
    } else {
    document.getElementById('myprog').style.display='none';
    }
    }
    if (eval('' + document.getElementById('myprog').value) > 0) {
    document.getElementById('myprog').value=eval(-1 + eval('' + document.getElementById('myprog').value));
    setTimeout(myprogit, 1000);
    } else {
    if (1 == 1) {
    document.getElementById('myprog').style.visibility='hidden';
    } else {
    document.getElementById('myprog').style.display='none';
    }
    }
    }
    }


    function twofocus(ih) {
    if (ih != '') {
    document.getElementById('ini').focus();
    document.getElementById('ine').focus();
    document.getElementById('emojiconjugate').innerHTML='&nbsp;';
    document.getElementById('myprog').value=30;
    document.getElementById('myprog').setAttribute('data-allow','y');
    if (1 == 1) {
    document.getElementById('myprog').style.visibility='hidden';
    } else {
    document.getElementById('myprog').style.display='none';
    }

    }
    }

… in italian_conjugation.html‘s changed code, can be tried with this live run link, or below.

This change highlights the difference between two CSS approaches to hiding a webpage element …

We chose the latter methodology for today’s work because visibility: hidden; still allows for the room that element would have taken up, so by the time we do apply visibility: visible; there is less annoying jiggering around going on with the webpage look when this happens.


Previous relevant English Translated Verb Conjugation Emoji Tutorial is shown below.

English Translated Verb Conjugation Emoji Tutorial

English Translated Verb Conjugation Emoji Tutorial

When retrying Italian French Spanish Verb Conjugation Emoji Image Tutorial‘s web application recently it struck us that an improvement could be …

  • if the user is entering an English verb to the top left … we could start …
  • filling in the Italian or French or Spanish verb translation (via the textbox’s placeholder attribute, hence, faintly) over to the top right … as well as …
  • add an emoji (button) 📖 (&#128214;) in that top right area too … in addition to the usual …
  • brilliant WordReference.com information presented below this top row in the table

Clicking that emoji (button) 📖 (&#128214;) in that top right area (or merely moving or tabbing in and out of focus at that top right textbox) would link up with WordReference.com verb conjugations better, we think, simulating what happens if the user starts their quest with the top right non-English verb textbox.

You can try this out for yourself in italian_conjugation.html‘s changed code, can be tried with this live run link, or below …


Previous relevant Italian French Spanish Verb Conjugation Emoji Image Tutorial is shown below.

Italian French Spanish Verb Conjugation Emoji Image Tutorial

Italian French Spanish Verb Conjugation Emoji Image Tutorial

We used the combining of …

… to find some practical improvements to some of our existent web applications regarding the use of Emoji Image (in today’s case in the form of background images).

We think the existent French and Italian and Spanish flags as background images are a bit too imposing and so we intervened as per the Javascript …


function emoji_images_maybe(inlineurl) {
switch (inlineurl) {
case "url('it.jpg')":
document.getElementById('mybodtr').style.height='90px';
document.getElementById('englishtoitalian').style.height='90px';
return "linear-gradient(rgba(255,255,255,0.6),rgba(255,255,255,0.6)),url([italianFlagEmojiImageDataURIGoesHere]);
break;


case "url('fr.jpg')":
document.getElementById('mybodtr').style.height='90px';
document.getElementById('englishtoitalian').style.height='90px';
return "linear-gradient(rgba(255,255,255,0.6),rgba(255,255,255,0.6)),url([frenchFlagEmojiImageDataURIGoesHere]);
break;


case "url('es.jpg')":
document.getElementById('mybodtr').style.height='90px';
document.getElementById('englishtoitalian').style.height='90px';
return "linear-gradient(rgba(255,255,255,0.6),rgba(255,255,255,0.6)),url([spanishFlagEmojiImageDataURIGoesHere]);
break;


default:
break;
}
return inlineurl;
}


function fixall(iti) {
was='';
otv='';
document.getElementById('conjugationcell').innerHTML='';
document.getElementById('sl').value=iti;
document.getElementById('sltwo').value=iti;
document.getElementById('slto').value=iti;
document.getElementById('slito').value=iti;
document.getElementById('slverb').value=iti;
document.getElementById('slconj').value=iti;
document.getElementById('mybodtr').style.backgroundImage=emoji_images_maybe("url('" + iti + ".jpg')");
document.getElementById('englishtoitalian').style.backgroundImage=emoji_images_maybe("url('" + iti + ".jpg')");
return iti;
}

Here’s a reminder of how you might derive

Flag
Italian
[italianFlagEmojiImageDataURIGoesHere]
IT 🇮🇹
French
[frenchFlagEmojiImageDataURIGoesHere]
FR 🇫🇷
Spanish
[spanishFlagEmojiImageDataURIGoesHere]
ES 🇪🇸
Navigate to Emoji Image Creator
… into textbox enter (where, regarding an ISO two character code
relating to flag country A=127462 CodePoint to Z=127487 CodePoint) …
127470.127481 127467.127479 127466.127480
… Click “Create Image” button (though use of links above do this for you)
… “Copy Image” the flag at Google Pagespeed
… “Paste” back at Emoji Image Creator …
… Highlight and “Copy” the data uri shown (relevant to flags above)

This mini-makeover for italian_conjugation.html‘s changed code, can be tried with this live run link.


Previous relevant Italian French Spanish Verb Conjugation Text to Speech Tutorial is shown below.

Italian French Spanish Verb Conjugation Text to Speech Tutorial

Italian French Spanish Verb Conjugation Text to Speech Tutorial

In following up on Italian and French and Spanish Verb Conjugation Event Tutorial as shown below we’ve increased functionality of English translations by adding Google Translate Text to Speech capabilities to …

  • Italian
  • French
  • Spanish

… via a new “loudspeaker” icon.

Some of the talking points with today’s changes involve …

  • a “reveal” idea whereby the showing of an HTML element is controlled by its Javascript DOM [element].style.width CSS property, whereby the element is effectively invisible at width:1px and in our case today becomes visible, at width:20px, and, thus, clickable, for Google Translate popup window translation and text to speech capabilities via the control of …
  • binary decision making GUI ease of using HTML input tag type=checkbox and the associated Javascript DOM document.getElementById([element]).checked … because …
  • UX-wise it is good to forewarn users with an option when it comes to functionality involving sound
  • use of Javascript DOM document.getElementsByTagName(‘img’) as a means by which to manipulate HTML elements that are not necessarily provided with an ID global property

As per the other tutorials in this thread, even with new Google Translate Text to Speech and Translation capabilities, nothing changes today about the techniques used today doing away with any need for a server side language by channelling the Ajax jQuery thoughts we presented with Ajax jQuery Primer Tutorial to make the most of the great resource that WordReference.com is. This happens in our HTML and Javascript programming source code you could call italian_conjugation.html, which changed to add in French and Spanish tense contextual verb conjugations in this way, with this live run link.


Previous relevant Italian and French and Spanish Verb Conjugation Event Tutorial is shown below.

Italian and French and Spanish Verb Conjugation Event Tutorial

Italian and French and Spanish Verb Conjugation Event Tutorial

In following up on Italian and French and Spanish Verb Conjugation Tense Tutorial as shown below we’ve increased functionality of English translations to …

  • Italian
  • French
  • Spanish

… and the conjugations from WordReference.com by offering onmouseover (ie. hover) or onclick (or mobile touch) event logic for conjugations offered by using the wonderful MyMemory resource to translate these verb conjugations back into English, and present them in an additional column with a different background colour.

You may recall us using MyMemory once before when we presented HTML/Javascript Hearing and Listening Primer Tutorial earlier on.

As per the other tutorials in this thread, but even more so with gleaning information from the MyMemory API via a get method, nothing changes about the techniques used today doing away with any need for a server side language by channelling the Ajax jQuery thoughts we presented with Ajax jQuery Primer Tutorial to make the most of the great resource that WordReference.com is. This happens in our HTML and Javascript programming source code you could call italian_conjugation.html, which changed to add in French and Spanish tense contextual verb conjugations in this way, with this live run link.

Hope you try out this new functionality.


Previous relevant Italian and French and Spanish Verb Conjugation Tense Tutorial is shown below.

Italian and French and Spanish Verb Conjugation Tense Tutorial

Italian and French and Spanish Verb Conjugation Tense Tutorial

We’ve followed up on Italian Verb Conjugation and Tense Tutorial as shown below with “tense” context to some of the conjugations of …

  • Italian
  • French
  • Spanish

Say “some of the” because …

Even amongst the conjugating language “triplets” above, noticed that when it comes to the “tense” involved, there can be variations, but don’t need to tell a lot of you this old news. Did set me to thinking a bit about the The Tower of Babel story from the Bible, though. What would the world be like if we all spoke the one language? Esperanto, everyone?

There’s a link between “language” and “life”. That’s why a language without “verbs” is not a language. And the Earth back in those dark days before any life, had no conduits for “language”. And it’s hard to see how “life” sort of started up? But I guess chemistry experts might be able to tell us how this might have come about.

“Language” is all about patterns, and mirrors human progress with its “pattern” and “organization” and “flexibility” as a huge part of why we as “humans” got to be such agents of change on Earth. Just wish there had really been a more successful Doctor Dolittle in human history that could have got the “inside goss” (so to speak) on what we could have done better to protect the world’s environments.

As per the other tutorials in this thread, nothing changes about the techniques used today doing away with any need for a server side language by channelling the Ajax jQuery thoughts we presented with Ajax jQuery Primer Tutorial to make the most of the great resource that WordReference.com is. This happens in our HTML and Javascript programming source code you could call italian_conjugation.html, which changed to add in French and Spanish tense contextual verb conjugations in this way, with this live run link.

Hope you try it out, and even contemplate sending us some feedback.


Previous relevant Italian Verb Conjugation and Tense Tutorial is shown below.

Italian Verb Conjugation and Tense Tutorial

Italian Verb Conjugation and Tense Tutorial

Again, we saw that we could extend the functionality of the recent Italian and French and Spanish Verb Conjugation Tutorial as shown below, by, for Italian, to start with, trying to help the native English speaker out for where to look on the “conjugation” table presented for the English verb of interest, regarding conjugation information that might match their (verb) tense of interest.

As you probably well know, every language on Earth has its peculiarities regarding how we express ourselves with regard to time, and a lot of that is associated with the verbs, or action words we use, and in the case of …

  • Italian
  • French
  • Spanish

… that expression of the context of time in the grammatical usage, especially for people speaking the language, is reflected by conjugations made to the verb. Conversely, as I, a native English speaker, got to think about as this web application proceeded, English has words like “am” and “have” and “having” and “been” and “will” and “shall” and “is” and “are” and “was” and “were” and “would” and “should” and “has” and “had” and “to” and ‘”be” and “being” preceeding verbs, which can have, basically, two suffixes “-ing” and “-ed” (expressing present participles and past participles respectively) to try to do what conjugation does for Italian (we program for today) and French and Spanish languages.

But there’s more to “tense” than Past, Present and Future as you well can imagine should you learn a language other than your native tongue, which you tend to “go along with the flow” perhaps unaware that “tense” exists, for some learners. There are concepts as layers on top about the context of the time the person is speaking relative to the time they are or were talking about … it gets complex … so you get concepts like “Present Perfect Progressive” (which we did a tutorial about at HTML/Javascript Present Perfect Progressive Primer Tutorial) if you get right into the ins and outs of all this grammar … which you might need to do to master that second language.

Yet again, nothing changes about the techniques used today doing away with any need for a server side language by channelling the Ajax jQuery thoughts we presented with Ajax jQuery Primer Tutorial to make the most of the great resource that WordReference.com is. This happens in our HTML and Javascript programming source code you could call italian_conjugation.html, which changed to add in Italian “tense” thoughts in this way, with this live run link.

Again, we hope you try some Italian, with specified “tense” prefix words and suffix endings, to see how the new functionality helps you out with Italian verb conjugations.


Previous relevant Italian and French and Spanish Verb Conjugation Tutorial is shown below.

Italian and French and Spanish Verb Conjugation Tutorial

Italian and French and Spanish Verb Conjugation Tutorial

We saw that we could extend the functionality of yesterday’s Italian Verb Conjugation Primer Tutorial as shown below, by accessing other resources from the great WordReference.com, adding French and Spanish verb conjugation to yesterday’s Italian verb conjugation.

As a rule we tend to find that replacing text with HTML select “dropdown” menus can help out this adaption pretty effectively. The other feature of today’s Javascript coding is the use of eval to team with the language code to direct user traffic to the correct parts of the WordReference.com website.

Along the way we added some background “flag” imagery we found at Science Kids … thanks, heaps.

Down the little brick road we also added a couple of hashtag navigators, HTML a links that just navigate within the page, allowing the user to move from the conjugation yellow zone to the translation zone (if you translated from English), as much as anything because the conjugation may need to be prompted by picking the “verb” amongst the list of “translated” possibilities, which you can then feed into the rightmost HTML input type=text textbox to, more than likely, get the (verb) conjugation you may have missed with the first pass.

Nothing changes about the techniques used today doing away with any need for a server side language by channelling the Ajax jQuery thoughts we presented with Ajax jQuery Primer Tutorial to make the most of the great resource that WordReference.com is. This happens in our HTML and Javascript programming source code you could call italian_conjugation.html, which changed to add in French and Spanish in this way, with this live run link.

Hope you try it out.


Previous relevant Italian Verb Conjugation Primer Tutorial is shown below.

Italian Verb Conjugation Primer Tutorial

Italian Verb Conjugation Primer Tutorial

Learning Italian as a native English speaker is best done when you are young, and beginning recently on this quest, I learnt a bit of this.

To me, what stuck out, was how easy we get it in English with regard to (the lack of) conjugating verbs, or articles, or adjectives, in our grammar.

Is it that, in English, we can say something in a hurry and, sort of, wait to fix it up later, because we don’t conjugate verbs in our mind, or is this not how it works in other languages? Actually, am pretty sure no, because conjugation is done so fast in the minds of Italian speakers that it is no issue … hard to imagine, though, from where I’m standing … well, actually, sitting. Am not here to say, but know it is this, that teachers of Italian to English native speakers, concentrate on in early lessons.

With this in mind, we don’t for one second pretend we are not using the wonderful resources at WordReference.com with today’s web application, but we thank them for their brilliance, and just rearrange things that you could glean perfectly well from here but need to take a few more steps to reach the conjugation (today it’s just verbs) web page bits, whereas we throw the conjugation bits straight at you. And yes, we do try to cater for the irregular verbs, and where they are regular you should see the word “regular” mentioned in the yellow zone conjugation areas … because we all know … well, you know what we mean?!

The techniques used today do away with any need for a server side language by channelling the Ajax jQuery thoughts we presented with Ajax jQuery Primer Tutorial to make the most of the great resource that WordReference.com is. This happens in our HTML and Javascript programming source code you could call italian_conjugation.html with this live run link.

So we hope you enjoy this break from our usual (other way around) ESL game (if it’s a game) to some “Conjugate, Italian Style” play.

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


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


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


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


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


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


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


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


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

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

Google Charts Totally Hashtagging Communication Conduits Tutorial

Google Charts Totally Hashtagging Communication Conduits Tutorial

Google Charts Totally Hashtagging Communication Conduits Tutorial

The work of Form Target Self Primer Tutorial got us thinking …

  1. Could it be applied to our inhouse Google Charts PHP web applications?
  2. And if so, is the work generic enough to just be applied to our gchartgen.js external Javascript they, mostly, all use?
  3. And proceeding forward, if it works, how can it help? (Everybody needs a dorothy dixer?!)

… and the jury’s in …

  1. Yes
  2. 95%
  3. Email and SMS communications could all be hashtag navigation based on URLs not needing PHP mail nearly as much

In arriving at our “hived off” (because it is useful just itself for other “parents” out there (as what we like to think of as a “tool”), we’re thinking) hashtagdata_self_post.js


// hashtagdata_self_post.js
// RJM Programming
// July, 2024

function checkfortotalhash() {
//document.title='1';
//document.title='11';
//document.title='111';
if (('' + location.href).split('#')[0].indexOf('?') == -1 && ('' + location.hash).indexOf('=') != -1) {
//document.title='1111';
if (eval('' + ((('' + location.href).split('#')[0].split('?')[0].split('#')[0] + location.hash)).length) < 800) {
//prompt = function(zwords, defwords){ return null; };
location.href=(('' + location.href).split('#')[0].split('?')[0].split('#')[0] + location.hash).replace('#','?');
} else if (('' + location.href).split('#')[0].split('?')[0].split('#')[0].indexOf('.htm') == -1) {
//document.title='11111';
//prompt = function(zwords, defwords){ return null; };
//document.title='111111';
var wlytsp=false;
var formdt='<form action="' + ('' + location.href).split('#')[0].split('?')[0].split('#')[0] + '" method="POST" target="_self"> <input type="submit" id="checkforb"></input></form>';
var labvals=[], ilv=0;
labvals=('' + location.hash).split('=');
for (ilv=1; ilv<labvals.length; ilv++) {
if (labvals[eval(-1 + ilv)].replace(/^\#/g,'&').split('&')[eval(-1 + labvals[eval(-1 + ilv)].replace(/^\#/g,'&').split('&').length)] == 'wouldlikeyoutoseekpermission') {
wlytsp=true;
}
formdt=formdt.replace('<input type="submit"', '<input type="hidden" name="' + labvals[eval(-1 + ilv)].replace(/^\#/g,'&').split('&')[eval(-1 + labvals[eval(-1 + ilv)].replace(/^\#/g,'&').split('&').length)] + '" value="' + decodeURIComponent(labvals[ilv].split('&')[0]) + '"></input><input type="submit"');
}
//document.title='1111111';
setTimeout(function(){
if (!wlytsp) {
//alert(formdt.replace('> <', '><input type=hidden name=wouldlikeyoutoseekpermission value=y></input><'));
document.body.innerHTML+=formdt.replace('> <', '><input type=hidden name=wouldlikeyoutoseekpermission value=y></input><');
} else {
//alert(formdt.slice(-220));
document.body.innerHTML+=formdt;
}
document.getElementById('checkforb').click();
}, 1000);
}
}
}

if (('' + location.href).indexOf('/GeoChart') == -1) {
checkfortotalhash();
}

… proof of concept start we made a discovery that surprised us with …

  • when an intervention point for external Javascript occurs before the webpage’s document.body onload event …
  • you do better scouring location.href rather than document.URL (though, curiously, document.title is okay) and that location.href may contain hashtagging data (or we were dreaming … anyway, we’ve coded for either) … and …
  • is okay recognizing location.hash hashtagging data … but …
  • we found a setTimeout arrangement of adding a form to document.body.innerHTML helps get past the document.body onload event starting timing

… and exceptions for web applications doing their own thaing here should be considered.

And so we used as our guinea pig Google Chart to try, the inhouse Pie Chart interfacer, as you can see from today’s animated GIF presentation to prove this …

  • navigational arrangement “proof of concept” methodology converting hashtagged incoming data into an HTML form method=POST target=_self action=[HereIsLookingAtYouKid] navigation back onto itself … and when happy just slapped that into the changed gchartgen.js external Javascript helper … along with …
  • email (mailto:) and SMS (sms:) URL tweaks to change ? to # to bypass the PHP server woooooorrrrrrllllllddd (and any PHP mail servers) for the Javascript client mailto: and sms: communication conduit wooooooorrrrrllllldddd … causing within a Javascript function called iftoobigthe changes

    if (eval(eval(urlin.length) + eval(urldata.length) + eval(urldata0.length)) < 800 || urlin.split('?')[0].split('#')[0].length < 800) { //1000) { // vs 2000
    return urlin.replace('?','#');
    }

Bear in mind, this is not ignoring the serverside. You’ll notice the chance of form method=POST coming into consideration. You need a serverside language to handle that method=POST … it’s just that not involving a PHP mail server and the mail command, when the amounts of data are substantial, so often, is the improvement, to our mind.

All that being so URLs such as the Google Chart Pie Chart (meddled around with) one …

https://www.rjmprogramming.com.au/PHP/PieChart/pie_chart.php#title=Country%20Populations&onclick=y&task=Country&desc=Populations&data=,%20[~https;China,1347000000,India,1241000000,United%20States,312000000,Indonesia,238000000,Brazil,197000000,Pakistan,177000000,Nigeria,162000000,Bangladesh,151000000,Russia,143000000,Japan,128000000,Mexico,115000000,Philippines,96000000,Vietnam,88000000,Ethiopia,87000000,Germany,81800000,Egypt,82600000,Iran,78000000,Turkey,74000000,Thailand,69500000,Congo,67800000,France,63300000,United%20Kingdom,62700000,Italy,60800000~,100]

… should, these days, show interesting graphical (and sometimes editable) data that is able or able.


Previous relevant Form Target Self Primer Tutorial is shown below.

Form Target Self Primer Tutorial

Form Target Self Primer Tutorial

We’ve rarely used the …

… style of arrangement in the past, but we’ve found it useful recently (a couple of times) because we find we want to, more and more, use …

  • hashtagged data
  • reassembled into a …
    1. form
    2. method=POST
    3. action=[URLofInterestOfPHP]
    4. target=_self

    … arrangement …

… that way keeping any window.parent and window.self and/or window.opener and window.self connections intact, and at the same time, being able to involve very long (mostly hashtagged data) URLs in the arrangements.

Let’s show you an example. In the recently talked about Google Charts Image Chart Map Chart inhouse interfacer called image_chart.php downaways into the code it now goes

<?php

$screenheight='0';
<br>
// ;Continent;CC1|CC2|:blLAT,blLONG,trLAT,trLONG:width,height:scblX,scblY,sctrX,sctrY
$continfo=';Europe;IS|CY|:35.16666,-27.6,67.0,33.36666:468,450:422,560,890,140'; // 53 523
$continfo.=';Australia;AU|AU|:-44,113.65,-10.26667,161.28333:600,450:422,560,866,140';
$continfo.=';Asia;FI|WS|:-14,37,81,179.9:600,450:422,560,866,140';
$continfo.=';America;GS|US|:-56,-179.9,77,-35:600,450:422,560,866,140';
$continfo.=';Africa;TF||:-35,-17,37,52:600,450:422,560,890,140';
if (isset($_GET['screenheight'])) {
$screenheight=str_replace('+',' ',urldecode($_GET['screenheight']));
}
if (isset($_POST['screenheight'])) {
$screenheight=str_replace('+',' ',urldecode($_POST['screenheight']));
}
<br>
if (isset($_GET['nothing'])) {
exit;
} else if ($screenheight != '0' && !isset($_GET['returnxytoparent']) && (!isset($_POST['returnxytoparent']) && !isset($_POST['ix']))) {
echo "<html>
<head>
<script type=text/javascript>
function tryit() {
if (('' + location.hash).indexOf('returnxytoparent=') != -1) {
document.getElementById('returnxytoparent').value=decodeURIComponent(('' + location.hash).split('returnxytoparent=')[1].split('&')[0].split('#'));
document.getElementById('submy').click();
}
}
</script>
</head>
<body onload=tryit();>
<form style=display:none; target=_self action=/PHP/GeoChart/image_chart.php method=POST>
<input type=hidden name=returnxytoparent id=returnxytoparent value=\"\"></input>
<input type=hidden name=screenheight value=" . $screenheight . "></input>
<input type=submit style=display:none; value=Submit id=submy></input>
</form>
</body>
</html>";
exit;

} else if (isset($_GET['returnxytoparent']) || (isset($_POST['returnxytoparent']) && !isset($_POST['ix']))) {
// more code to do with real returnxytoparent data follows
}
// more code follows

?>

… called from our inhouse Region Picker in this way now (where inhouse Javascript function windowdotdotopen can be thought of as window.open for these purposes)


if (eval('' + encodeURIComponent(theurlis).length) > 750) {
dbwo=windowdotdotopen('//www.rjmprogramming.com.au/PHP/GeoChart/image_chart.php' + '?screenheight=' + screen.height + '#returnxytoparent=' + encodeURIComponent(theurlis),'_blank','top=' + eval(-300 + screen.height) + ',left=450,width=600,height=300');
} else {

dbwo=windowdotdotopen('//www.rjmprogramming.com.au/PHP/GeoChart/image_chart.php?returnxytoparent=' + encodeURIComponent(theurlis) + '&screenheight=' + screen.height,'_blank','top=' + eval(-300 + screen.height) + ',left=450,width=600,height=300');
}

… setting up a two way understanding between window.opener Region Picker and window.self Google Charts Image Chart Map Chart inhouse interfacer. Using that target=_self arrangement above allows …

  • despite the “double dipping” transfer of hashtagged URL data (when longer than 750 characters, that is) into method=POST form data (of considerable size) …
  • that understanding between window.open Region Picker and window.self Google Charts Image Chart Map Chart inhouse interfacer remains intact

Yayyyyyy!

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


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

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

Google Charts Geo Chart Region Picker Conditional Positioning Tutorial

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.

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