Google Charts Debugging via Web Inspector and View Page Source Tutorial

Google Charts Debugging via Web Inspector and View Page Source Tutorial

Google Charts Debugging via Web Inspector and View Page Source Tutorial

The combination of (showing Google Chrome web browser wording)

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

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

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

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

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

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


Previous relevant Google Calendar Chart Revisit Tutorial is shown below.

Google Calendar Chart Revisit Tutorial

Google Calendar Chart Revisit Tutorial

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

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

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

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

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

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

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

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

>


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

Google Calendar Chart Difference Report Planning Tutorial

Google Calendar Chart Difference Report Planning Tutorial

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

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

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

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

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

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

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


String.fromCharCode(10)

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

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

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

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


Previous relevant Google Timeline Chart Clipboard Tutorial is shown below.

Google Timeline Chart Clipboard Tutorial

Google Timeline Chart Clipboard Tutorial

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


Date

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

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

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

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

  1. Year
  2. Month
  3. Date

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

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

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

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

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

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


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

Google Geo Intensity Map Chart Multimedia Background Tutorial

Google Geo Intensity Map Chart Multimedia Background Tutorial

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

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


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

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

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

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

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

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

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

Did you know?

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


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

Google Line Area Bar Column Chart Multimedia Background Tutorial

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

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

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

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

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

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

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


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

Google Pie Chart Multimedia Background Tutorial

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

  • image
  • video
  • audio

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

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

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

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

… which involved, device wise …

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

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

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

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

Google Map Chart Email Attachment Reply Tutorial

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

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

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

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

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

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


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

It already fills in for an entry such as …


Sydney

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

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


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

Google Chart Email Attachment Reply Tutorial

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


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

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

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

    location.href=toolong([PieChartURL]);

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

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

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

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


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

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

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


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

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


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

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

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

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

PHP and Javascript code wise …

From little guinea pigs, bigger guinea pigs grow?!


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

Google Chart Email Attachment Mobile Tutorial

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

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

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

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

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


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

Google Chart Email Attachment Post Tutorial

Yesterday’s Google Chart Email Attachment Tutorial intimated …

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

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

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

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


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

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

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

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

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

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


Previous relevant Google Chart Email Attachment Tutorial is shown below.

Google Chart Email Attachment Tutorial

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

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

We arrange these changes at the …

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

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


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

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

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

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

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

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


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

Google Chart Pie Chart Background Image Tutorial

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

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

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

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

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

    backgroundColor: 'none'

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

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

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

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

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

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

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


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

Google Pie Chart via Clipboard Co-ordinates Tutorial

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

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


String.fromCharCode(10)

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

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


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

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

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

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

  1. copy the contents below …

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

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

Google Map Chart via Clipboard Co-ordinates Tutorial

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

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

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

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

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

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

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

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

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

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


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

Google Map Chart via URL Co-ordinates Tutorial

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

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


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

… from a CSV data URL look with contents …


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

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


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

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

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


include "../csv.php";

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

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

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

Emoji Name Search Map Chart Weather Tutorial

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

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

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

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

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

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


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

Emoji Name Search Map Chart Tutorial

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

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

We wanted to enhance its integration by …

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

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

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

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


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

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

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


Previous relevant Emoji Name Search Timezone Tutorial is shown below.

Emoji Name Search Timezone Tutorial

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

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

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


&ccode=[ISO 2 letter Country Code]

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


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

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


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

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


Previous relevant Emoji Name Search Map Tutorial is shown below.

Emoji Name Search Map Tutorial

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

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

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

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

Another way to zoom around the world online!

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


Previous relevant Emoji Name Search Posting Tutorial is shown below.

Emoji Name Search Posting Tutorial

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

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

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

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

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


Previous relevant Emoji Name Search Tailoring Tutorial is shown below.

Emoji Name Search Tailoring Tutorial

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

 

  • sharing
  • personalization

 

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

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

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

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

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

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

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

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

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

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

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


Previous relevant Emoji Name Search Primer Tutorial is shown below.

Emoji Name Search Primer Tutorial

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

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

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

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

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


Previous relevant Rainbow Games PHP Emoji Tutorial is shown below.

Rainbow Games PHP Emoji Tutorial

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

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

… we had a choice of …

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

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

  1. Emojipedia
  2. FileFormat Information
  3. Iemoji

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

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

How to work the interfacing to Emoji Terra?

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

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

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

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

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


Previous relevant Rainbow Games Genericization Tutorial is shown below.

Rainbow Games Genericization Tutorial

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

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

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

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

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

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

    … in altered ways like …

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

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

    … not forgetting to …

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

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


Previous relevant Rainbow Games Double Transformation Tutorial is shown below.

Rainbow Games Double Transformation Tutorial

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

‍♀️

… table cell mirroring styling as per …


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

select { font-size: 36px; }

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

‍♀️

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

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

‍♀️

Florence

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


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

select { font-size: 36px; }

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

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

‍♀️

Florence

</style>

… works as a “double transform” to first …

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

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


Previous relevant Rainbow Games Primer Tutorial is shown below.

Interesting Places Primer Tutorial

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

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

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

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

Yesterday’s …

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

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

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

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

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


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

}
};
}, 4000);
}

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

<?php

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

?>

… calling new Javascript function …

<?php echo ”

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

“; ?>

Other than header.php WordPress PHP code we changed …


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

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

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

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

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

And then there was “the unknown factor” …

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

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


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

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

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

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

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

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

… talking about the three appended spaces needed.


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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

Did you know?

All this begs the question …

What about mobile?

Well, at least for iOS we think …


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per

index.htm …


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

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

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

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

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    … to arrive at the calling window

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said …

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

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

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

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

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

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

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

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

<?php echo ”

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

“; ?>

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

<?php echo ”

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

}

“; ?>

… to call on that new PHP …

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo ”

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

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

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

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


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

“; ?>

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

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

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

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

<?php echo ”

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

“; ?>

57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

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

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

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

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

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

    … as food for (your) thought …


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

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


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


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


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


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


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


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


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


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


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


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

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

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

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

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

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

And then there was “the unknown factor” …

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

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


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

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

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

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

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

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

… talking about the three appended spaces needed.


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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

Did you know?

All this begs the question …

What about mobile?

Well, at least for iOS we think …


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per

index.htm …


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

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

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

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

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    … to arrive at the calling window

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said …

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

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

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

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

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

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

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

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

<?php echo ”

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

“; ?>

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

<?php echo ”

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

}

“; ?>

… to call on that new PHP …

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo ”

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

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

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

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


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

“; ?>

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

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

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

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

<?php echo ”

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

“; ?>

57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

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

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

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

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

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

    … as food for (your) thought …


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

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


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


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


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


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


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


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


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


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


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

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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

… or …


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

Did you know?

All this begs the question …

What about mobile?

Well, at least for iOS we think …


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per

index.htm …


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

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

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

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

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    … to arrive at the calling window

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said …

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

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

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

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

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

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

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

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

<?php echo ”

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

“; ?>

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

<?php echo ”

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

}

“; ?>

… to call on that new PHP …

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo ”

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

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

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

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


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

“; ?>

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

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

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

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

<?php echo ”

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

“; ?>

57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

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

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

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

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

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

    … as food for (your) thought …


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

    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, iOS, Photography, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Dice Games Peer to Peer Emoji Tutorial

Dice Games Peer to Peer Emoji Tutorial

Dice Games Peer to Peer Emoji Tutorial

The recent Knockout Dice Game Emoji Tutorial got us a little peeved. We do like fairness, even for your humble web application, and when The Knockout Dice Game got an “emoji makeover” a few days ago … well … we’re telling you … around here there were stares and whispers … or was that 🖕👇stairs and wise purrs.

And so, regarding The Three Amigos

… all demanded “emoji ⚖ equality” … and who are we to argue?!

Each demanded nuanced modification differences, but we were glad regarding the “code cloning” that got us arriving at a fairly consistent starting point even before the Knockout Dice Game changes of Knockout Dice Game Emoji Tutorial and the day before that. Cloning should take place whenever you as the programmer have achieved functioning milestones.

And then we come to …

If you (Dice Game web applications) all want consistency you’ll want to easily see that grouping reflected in a peer to peer dropdown navigation arrangement?

Rhetorical question alert!!

Yes, dropdown (ie. select) elements are great for these peer to peer concept ideas, but the default CSS styling grates here. So how can a select element look more like an h1 element? Glad we asked! Have a look at this …


// Make the dropdown look like the nesting h1
var divelem=document.getElementById('gamemode');
var output=document.getElementById('myh1');
divelem.style.fontFamily = window.getComputedStyle(output,null).fontFamily || output.style.fontFamily || output.currentStyle.getCurrentProperty('font-family');
divelem.style.fontSize = window.getComputedStyle(output,null).fontSize || output.style.fontSize || output.currentStyle.getCurrentProperty('font-size');
divelem.style.fontWeight = window.getComputedStyle(output,null).fontWeight || output.style.fontWeight || output.currentStyle.getCurrentProperty('font-weight');
divelem.style.border = window.getComputedStyle(output,null).border || output.style.border || output.currentStyle.getCurrentProperty('border');
divelem.style.padding = window.getComputedStyle(output,null).padding || output.style.padding || output.currentStyle.getCurrentProperty('padding');
divelem.style.margin = window.getComputedStyle(output,null).margin || output.style.margin || output.currentStyle.getCurrentProperty('margin');
divelem.style.overflow = window.getComputedStyle(output,null).overflow || output.style.overflow || output.currentStyle.getCurrentProperty('overflow');
divelem.style.padding = window.getComputedStyle(output,null).padding || output.style.padding || output.currentStyle.getCurrentProperty('padding');
divelem.style.color = window.getComputedStyle(output,null).color || output.style.color || output.currentStyle.getCurrentProperty('color');

… Javascript code snippet. Isn’t Javascript wonderful!? Rhetorical question alert!!

Stop Press

Are you looking for a cross-browser means of right justifying the option text of a select (ie. dropdown) element? This very useful link, thanks, got us to try, successfully …


<select dir="rtl" style="text-align:right;" onchange="location.href='/HTMLCSS/' + this.value + '_dice_game.html?rand=' + Math.floor(Math.random() * 19878654);" id=gamemode><option value=knockout>Knockout</option><option value=runforit>Run for It &#127939;&#8205;&#9792;&#65039;</option><option value=threeormore>Three or More &#128338;<sup>&#10133;&#10133;</option></select>

… to look like …


Previous relevant Knockout Dice Game Emoji Tutorial is shown below.

Knockout Dice Game Emoji Tutorial

Knockout Dice Game Emoji Tutorial

To our mind, the invention of emojis has been a really positive part of the online world. Maybe we’re that extra bit fond of them because it can go somewhere on the way to …

  • covering up image media deficiencies (cough, cough) with this text/image hybrid alternative where the artistry has already been done, just asking for your coding intervention to use (where our favourite emoji coding access means, (using example of “dice” here) is to …
    1. type … [search strings] emojipedia ( ie. dice emojipedia ) … into the web browser address bar …
    2. click/tap relevant Google search Emojipedia link
    3. click/tap Technical Information tab link
    4. copy the U+1F3B2 style of Codepoint presented to paste into the web browser address bar …
    5. click/tap the relevant link (our preferred being, for single entities, the FileFormat.info) link
    6. copy the relevant HTML Entity (decimal) ( ie. &#127922; ) into the buffer

    ) … ready to paste at the relevant place ( or use String.fromCodePoint(127922) … 🎲 ) of the HTML or Javascript code … as well as the emoji talents of …

  • emojis are a help with Internationalization of your web application … as well as …
  • adding colour into the webpage aesthetics look
  • adding interest into the webpage aesthetics look … and because they are that hybrid between image and text …
  • adding interest into the webpage content
  • With this in mind, we spent some time, onto yesterday’s Knockout Dice Game Checkbox Tutorial progress for that Knockout Dice Game making it …

    Knockout 👊 Dice 🎲🎲 Game

    … even there in the web browser tab’s title.

    For the first time we can remember we needed to get ahead of the curve picking a suitable CSS font-family property for all text with this work because we found that some of the dice guise emojis were really new and not found in all the font families out there, so …


    <style>
    * { font-family: 'DejaVu Sans'; }

    .xone:before { font-family: 'DejaVu Sans'; content: '\002680'; color:blue; }
    .xtwo:before { font-family: 'DejaVu Sans'; content: '\002681'; color:blue; }
    .xthree:before { font-family: 'DejaVu Sans'; content: '\002682'; color:blue; }
    .xfour:before { font-family: 'DejaVu Sans'; content: '\002683'; color:blue; }
    .xfive:before { font-family: 'DejaVu Sans'; content: '\002684'; color:blue; }
    .xsix:before { font-family: 'DejaVu Sans'; content: '\002685'; color:blue; }
    .zone:after { font-family: 'DejaVu Sans'; content: '\002680'; color:blue; }
    .ztwo:after { font-family: 'DejaVu Sans'; content: '\002681'; color:blue; }
    .zthree:after { font-family: 'DejaVu Sans'; content: '\002682'; color:blue; }
    .zfour:after { font-family: 'DejaVu Sans'; content: '\002683'; color:blue; }
    .zfive:after { font-family: 'DejaVu Sans'; content: '\002684'; color:blue; }
    .zsix:after { font-family: 'DejaVu Sans'; content: '\002685'; color:blue; }

    .kout:after { content: '\01f44A'; }

    #snum { background-color: yellow; }

    #header { background-color: #f0f0f0; }

    select { white-space:pre-wrap; border-radius: 6px; }

    button { border-radius: 12px; }

    </style>

    … solved some issues for us, here. And in researching totally CSS ways to style via content, again, we got a leave pass to not look again. CSS (style) and HTML (substance) have been separated by the W3C powers that be, for a reason, and we see that CSS selectors based on “content starts with” will never happen, though you can probably use jQuery library calls to achieve this.

    Okay, with that in mind, we abandoned a CSS only “cute” way to display die values either side of a numerical dice roll total in the header table cell which updates dynamically, instead using this Javascript …


    function diceemojis(totv, secv) {
    var hprefix='', hsuffix='', classbit='';
    var firstv=eval(totv - secv);
    if (1 == 1) {
    var sels=document.getElementsByTagName('select');
    for (var isels=0; isels<sels.length; isels++) {
    if (('' + sels[isels].value.replace(/^0/g,'')) == ('' + totv)) { classbit=' class="kout"'; }
    }
    hprefix=('' + secv).replace(/1/g, '<sup class=xone></sup>').replace(/2/g, '<sup class=xtwo></sup>').replace(/3/g, '<sup class=xthree></sup>').replace(/4/g, '<sup class=xfour></sup>').replace(/5/g, '<sup class=xfive></sup>').replace(/6/g, '<sup class=xsix></sup>')
    hsuffix=('' + firstv).replace(/1/g, '<sub class=zone></sub>').replace(/2/g, '<sub class=ztwo></sub>').replace(/3/g, '<sub class=zthree></sub>').replace(/4/g, '<sub class=zfour></sub>').replace(/5/g, '<sub class=zfive></sub>').replace(/6/g, '<sub class=zsix></sub>')
    return hprefix + '<span' + classbit + ' id="span' + rollno + '">' + totv + '</span>' + hsuffix;
    }
    return (' <span class="' + firstv + ' ' + secv + '">' + totv + '</span>').replace(/\ 1\"/g, ' zone"').replace(/\ 2\"/g, ' ztwo"').replace(/\ 3\"/g, ' zthree"').replace(/\ 4\"/g, ' zfour"').replace(/\ 5\"/g, ' zfive"').replace(/\ 6\"/g, ' zsix"').replace(/\"1\ /g, '"xone ').replace(/\"2\ /g, '"xtwo ').replace(/\"3\ /g, '"xthree ').replace(/\"4\ /g, '"xfour ').replace(/\"5\ /g, '"xfive ').replace(/\"6\ /g, '"xsix ');
    }

    … to start making this happen in the changed knockout_dice_game.html Knockout Dice Game you can also try below.


    Previous relevant Knockout Dice Game Checkbox Tutorial is shown below.

    Knockout Dice Game Checkbox Tutorial

    Knockout Dice Game Checkbox Tutorial

    Around here, we’re often moving on in a project via …

    • the changing of hardcodings into “dropdown” select elements (especially within h1 header elements) … but today, to move on, we arrange for …
    • the nested insertion of a checkbox (initially checked) within an h1 header element

    … which for the first time we can remember, we adjust “opacity aesthetics” to add a useful dynamic setting adjustment to the Knockout Dice Game created when we presented Knockout Dice Game Primer Tutorial some time ago now …


    <h1><div id=divword style=display:inline-block;>Knockout</div> Dice Game for <div id='dnum' style='display:inline-block;'><select style='display:inline-block;' onchange='fixinstone(this.value);' id='snum'><option value=2>2</option><option value=3>3</option><option value=4>4</option><option value=5>5</option><option value=6>6</option><option value=7>7</option><option value=8>8</option><option value=9>9</option></select></div> <span id=sgwta style=opacity:1.0;><input onchange="document.getElementById('sgwta').style.opacity='' + eval(1.1 - eval('' + document.getElementById('sgwta').style.opacity));" style=display:inline-block;opacity:1.0; type=checkbox id=gwta checked></input>Winner Take All</span> Players</h1>

    This “Winner Takes All” checkbox controlled mode of use defaults to being set (which is unusual for us, when we add a new form of methodology like this) because we discovered, revisiting this game, that “passivity” was, sort of, being rewarded and so we felt like we needed to add in the idea (and the concept of “No Winner” needed to be added), into the game, where it is really user participation encouraged here, to make the game interesting. Adding to that interest is that in a “Winner Takes All” mode of use, if a player can be the lone player to survive “Knockouts” they score a point for every roll of the two dice to get to this “lone winner” scenario.

    The other issue we noticed were the right hand overflows of our tabulated dropdowns when a lot of players are asked for. We started rearranging content justifications (to now be left justified) so it did not matter if we reduced the (now a better Responsive Design friendly table cell percentage) widths of those dropdowns, so as to fit more fields into the webpage …


    tg+="<td><select style=width:100%;background-color:cyan; id='gplayer" + jhow + "'><option value='06'>[6] Knockout value ...</option><option value='6'>6</option><option value='7'>7</option><option value='8'>8</option><option value='9'>9</option></select></td><td><div id='score" + jhow + "'>Score: 0/0</div></td>";

    … in the changed knockout_dice_game.html Knockout Dice Game you can also try below …


    Previous relevant Knockout Dice Game Primer Tutorial is shown below.

    Knockout Dice Game Primer Tutorial

    Knockout Dice Game Primer Tutorial

    Further to the previous Dice Guessing Game Primer Tutorial, today, we have for you another Dice Game, this time …

    • a dice game for 2 to 9 players … which you should establish, as necessary, straight up …
    • then rename any player names you don’t want to be the default Player1 up to Player9 values, again, making use of the contenteditable=”true” global HTML attribute and the HTML div element’s onchange event to achieve this
    • then in each round of competition the players choose a two dice roll value between 6 to 9 as the value they don’t want to see turn up, because if it does, they score nothing for that round of competition, else the players last not rejected when there is one or no players left, score a point in that round of competition … and …
    • the web application randomly throws the dice the necessary number of times to find winner(s) once the “Roll the Dice for Each Player” button is pressed

    We’d like to thank the very useful webpage for ideas for how (for the most part) this Knockout Dice Game design, execution and rules should go.

    And again, we’d welcome your try out of this new Knockout Dice Guessing Game, and please feel free to tell us what you think. Its HTML and Javascript and CSS underpinning its functionality can be perused by downloading the knockout_dice_game.html link.


    Previous relevant Dice Guessing Game Primer Tutorial is shown below.

    Dice Guessing Game Primer Tutorial

    Dice Guessing Game Primer Tutorial

    There are many HTML Entities based around punctuation that can add to the means by which you communicate ideas with your web applications.

    In today’s new (up to two player) Dice Game, we use some of these to represent the numbers from 1 to 6 on the faces of the dice, similar to how you may have seen this happen with dice in various games you play, or hanging from your car’s front visor perhaps?

    We’d welcome your try out of this Dice Guessing Game, and feel free to tell us what you think (or if its two of you “tell us what you think” … huh?!). Its HTML and Javascript and CSS underpinning its functionality can be perused by downloading the dice_game.html link. If you do, you’ll see the mildly interesting scoring system, that can be explained via the equation …


    [CorrectAnswerScoreIncrement] = 7 - (NumberOfPossibilitiesInFull36PossibilitiesSet)

    … allowing for the incorporation of this Javascript array initialization …


    var probabilities=[0,0,1,2,3,4,5,6,5,4,3,2,1]; // score will be 7-guessValue

    … that we were capable of working out ourselves but were reassured by the mathematics of this very useful link, thanks.

    Another game thought unique to how we do things that has been introduced today, is that a user can change the default player names, those being Player1 and Player2 via an HTML div element utilizing the contenteditable=”true” global HTML attribute to make it look readable, but be also “quietly” editable.

    You can also see this play out at WordPress 4.1.1’s Dice Guessing Game Primer Tutorial.

    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.

    Posted in eLearning, Event-Driven Programming, Games, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

    Viewport and CSS Calc Screen Resize Tutorial

    Viewport and CSS Calc Screen Resize Tutorial

    Viewport and CSS Calc Screen Resize Tutorial

    As well as the …

    As with that previous blog posting, when …

    • a web browser screen resizes … the best place to intervene is, a little counterintuitively …
    • the document.body onresize event

    … and rather than bothering trying to stay with the same webpage incarnation here, because the webpage content is static, all we need to do to cater for screen resizing here, in the code, is to …


    <body onresize='setTimeout(function(){ location.href=document.URL; }, 3000);' onload='dbih=document.body.innerHTML; divpolys();' onresize='if (!rdone) { rdone=true; setTimeout(reloadit, 50); divpolys(); } else { divpolys(); }'>

    … the delay being so the user can complete their final resizing so that the onresize event number of calls is minimized, in the changed viewport_poc.htm‘s live run link.


    Previous relevant Viewport and CSS Calc Intersection Resize Tutorial is shown below.

    Viewport and CSS Calc Intersection Resize Tutorial

    Viewport and CSS Calc Intersection Resize Tutorial

    Yesterday’s Viewport and CSS Calc Intersection Algorithm Tutorial showed no issues with …

    • mobile “pinch” and “spread” gestures … no issues surprisingly … but there were with …
    • non-mobile “onresize” (of window) created issue of a misplaced yellow intersection HTML div

    Fixing this bug was interesting. At first we thought that yesterday’s …

    … we can just create overlayed HTML div elements (position:absolute; opacity:0.7; z-index:11; top and left and width and height in px specified) to represent the intersection of Polygon 5 and 6.

    … should be arranged to be …


    ... we can just create overlayed HTML div elements (position:absolute; opacity:0.7; z-index:11; top and left and width and height in % specified) to represent the intersection of Polygon 5 and 6.

    … but found that that (idea that “W% = (WpxValue * 100.0 / screen.width)”) was not really the silver bullet here.

    What was better was to create a bit of a “rubber band” feel (for 1/20 of a second of flexibility) to onresize events as per …


    // HTML
    <body onload='dbih=document.body.innerHTML; divpolys();' onresize='if (!rdone) { rdone=true; setTimeout(reloadit, 50); divpolys(); } else { divpolys(); }'>
    // Javascript
    var rdone=false;
    function reloadit() {
    location.href=document.URL;
    }

    Yet again, take a look at the changed viewport_poc.htm‘s live run link …

    Now
    Was

    Previous relevant Viewport and CSS Calc Intersection Algorithm Tutorial is shown below.

    Viewport and CSS Calc Intersection Algorithm Tutorial

    Viewport and CSS Calc Intersection Algorithm Tutorial

    Do you eat “separatist style”? I used to, leaving the good stuff until last, until one day a grandparent kindly taught me the weakness with this system, quietly pinching the best stuff during the prelude period. The recent Viewport and CSS Calc Primer Tutorial has set us on a “separatist course” (which we hope does not lead to any tears at bedtime) …

    • initially talking just HTML and CSS (and no Javascript) with that first incarnation of the “Viewport and CSS Calc” proof of concept web application as above … and now today …
    • we add Javascript (that dynamically creates its own HTML and CSS via two conduit helpers … those being …

      1. <body onload='divpolys();'>

      2. function divpolys() {
        var divsii;
        divs=document.getElementsByTagName('div');
        for (var ii=0; ii<divs.length; ii++) {
        divsii=divs[ii].getBoundingClientRect(); // the way CSS proportionate styling can become co-ordinate reality
        // co-ordinate finding processing continues
        }
        // More work here
        }

      … helping us show, in another “proof of concept” that will get nuanced and genericized (we hope) to show “Two Convex Polygon Intersections”)

    “Nuanced and genericized”? Yes, as our case is even simpler (because in our case the polygons are always rectangles) than the premise of our muse for today’s work, the wonderful algorithmic ideas for Intersection of Convex Polygons Algorithm (and also helped out by the great PNPOLY – Point Inclusion in Polygon Test) but we plump for an array of structures data arrangement (rather than classes) reminiscent of our book web application discussion at Javascript Array of Structures Primer Tutorial (and also see MySql Polygon Spatial Relations via Image Map Tutorial for GIS MySql Spatial functions regarding some of this same line of thinking). And so, being that simple, we can just create overlayed HTML div elements (position:absolute; opacity:0.7; z-index:11; top and left and width and height in px specified) to represent the intersection of Polygon 5 and 6.

    Again, take a look at the changed viewport_poc.html‘s live run link …

    … or HTML iframe supervision to see what we are getting at here.


    Previous relevant Viewport and CSS Calc Primer Tutorial is shown below.

    Viewport and CSS Calc Primer Tutorial

    Viewport and CSS Calc Primer Tutorial

    Keeping on with some themes of yesterday’s Responsive Design Viewport Width Considerations Tutorial, today, we combine ideas around …

    … in a “proof of concept” web application we are using to explore ideas from the ground up … hello, wormies!

    This is precise pixel placement 101, bringing us to a division of concept with webpage design …

    Screen Viewport
    Width and Height Unitary Units px px
    Width Proportionate Units % vx
    Height Proportionate Units % vh
    Width (or Left) Calc-friendly %,px %,px,100vx
    Height (or Top) Calc-friendly %,px %,px,vh,100vh

    … where our “proof of concept” findings (on Safari, Firefox, Chrome, Opera and Safari simulations of Edge and Internet Explorer) so far make us believe the Viewport width: calc(100vx – 60px); CSS definition type of syntax that sounds great on paper does not appear to work in practice.

    So take a look at our very symmetric viewport_poc.html‘s live run link …

    … or HTML iframe supervision to see what we are getting at here.


    Previous relevant Responsive Design Viewport Width Considerations Tutorial is shown below.

    Responsive Design Viewport Width Considerations Tutorial

    Responsive Design Viewport Width Considerations Tutorial

    Regarding our Landing Page series of HTML/Javascript/CSS webpages here at RJM Programming, we’re streamlining our device width (Responsive Web Design) considerations of …

    • Mobile Friendly Meta Viewport Tag Zoom Tutorial by now going with …
      Was .. Now is

      <meta id=”myviewport” name=”viewport” content=”width=device-width, initial-scale=1, minimum-scale=0.25, maximum-scale=8, user-scalable=yes” />

      <meta name="viewport" content="width=device-width, initial-scale=1.0">
    • Google PageSpeed and Firebug Mobile Friendly Primer Tutorial by now going with …
      Was ..

      function widthfix() { //
      if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) { // it is a mobile device
      document.getElementById('body_content').style.width='100%';
      document.getElementById('nav_layer').style.width='100%';
      document.getElementById('widget0').style.width='100%';
      }
      Now is

      function widthfix() { //
      if (1 == 7 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) { // it is a mobile device
      document.getElementById('body_content').style.width='100%';
      document.getElementById('nav_layer').style.width='100%';
      document.getElementById('widget0').style.width='100%';
      }

    Why?

    • viewport advice of W3School’s Responsive Web Design – The Viewport useful link, thanks … to keep it simple …

      <meta name="viewport" content="width=device-width, initial-scale=1.0">
    • we were able to use Safari (web browser) Develop Menu “Responsive Design Mode” functionality (as per Safari Develop Menu Responsive Design Primer Tutorial) to see for ourselves the improvement where our previous width based Javascript logic amendments had been interfering with the meta viewport suggestions better in keeping with Responsive Design thoughts

    Food for thought, we hope, for those chipping away at responsive design amalgamations!

    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in 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

    SVG Emoji Favicon and Title Tutorial

    SVG Emoji Favicon and Title Tutorial

    SVG Emoji Favicon and Title Tutorial

    The recent SVG Network Clock Start Local Time Favicon Tutorial talked about …

    • SVG data basis …
    • emoji data content …
    • favicon web browser tab icon … SVG type not accepted by all browsers and platforms …
    • dynamism … and today we start with another offshoot of thought regarding this, as well as …
    • document.title also showing in the web browser tab icon … universally accepted …

    … ideas we wanted to get into by writing a pretty simple generic PHP helper emojiicon.php, we got a great heads up from regarding its logic, thanks, to dynamically create favicon.svg, currently looking like …

    … in our nominated folder (so, so far not catering for a lot of online traffic … we’ll see) …


    <?php
    // emojiicon.php
    // RJM Programming
    // March, 2025

    if (isset($_GET['codepoint'])) {
    if (strlen($_GET['codepoint']) > 0) {
    if (isset($_GET['ishex']) || isset($_GET['tohex']) || isset($_GET['hex'])) {
    //file_put_contents('xxx.xxx', str_replace('+',' ',urldecode($_GET['codepoint'])));
    //file_put_contents('xx.xx', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#x' . str_replace(',',';&#x',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>');
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon.svg', str_replace('🇦','🇦🇩','<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#x' . str_replace(',',';&#x',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>'));
    } else {
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon.svg', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#' . str_replace(',',';&#',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>');
    }
    }
    }

    echo "<html>
    <head>
    <link rel='icon' href='/emojiicon/favicon.svg?rand=" . rand(0,3456789) . "' sizes='any' type='image/svg+xml'>
    </head>
    <body>
    <h1>Emoji Icon - RJM Programming - March, 2025</h1>
    </body>
    </html>";
    ?>

    … used in a changed emoji_widget_idea.htm content live run.


    Previous relevant SVG Network Clock Start Local Time Favicon Tutorial is shown below.

    SVG Network Clock Start Local Time Favicon Tutorial

    SVG Network Clock Start Local Time Favicon Tutorial

    Today we’re revisiting the SVG Network Clock we last talked about with SVG Network Clock Minimize Tutorial. Why?

    Well, we were re-researching the topic of Favicon (those images on the tabs of your web browser tabs) that we talked about when we presented Gimp Favicon via Logo Primer Tutorial, but we realize now, things have moved on with the web browsers supporting SVG svg+xml “favicons” so much better these days, that we’d better “get with the plan”, so to speak (though it might be better if I give that a rest for a minute).












    Okay, minutes up!

    With increased usage of SVG svg+xml text element solutions for things around here lately, we wondered whether there was a dynamic way to start using these SVG favicons, in some way. Then we thought of our SVG Clock work. At first we thought a favicon that is a relevant timestamp, but realized the impost on the web server is too big for that, and so we set out to present a local start time of the SVG Clock for a user of this web application. The SVG favicon basis is so simple …


    <?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg width="32" height="32" version="1.1" xmlns="http://www.w3.org/2000/svg" style="background-color:white; letter-spacing:-1px; transform:scale(1,1.6);>
    <text x="0%" y="65%" stroke="black" stroke-width="1" fill="red" font-size="16px">11:54</text>
    </svg>

    Stick the SVG file in Document Root folder, and replace “11:54” with the relevant timestamp and we’re away, right? Yes, sort of, but there is the little matter of the relevant favicon link statement existing as a non-dynamic call to that SVG in the head section of the webpage.

    Bit onerous, huh? But, what did work for us was to have a static starting wrong favicon SVG link (in head) statement that now goes in the parental svg_clock.html SVG Network Clock

    <head>


    <link id='mylink' rel='icon' href='/faviJUNKcon.svg' sizes='any' type='image/svg+xml'>

    </head>

    … and set up the changed cldate.php PHP now called …

    <body>

    <script type='text/javascript'>
    var pwo=null;
    var analoguesuffix='';
    var bothsuffix='';
    if (document.URL.indexOf('analogue=') != -1) { analoguesuffix=' selected'; }
    if (document.URL.indexOf('both=') != -1) { bothsuffix=' selected'; }
    var pretzlist='';
    var tzlist="<option value='Africa/Abidjan' data-geo='5.31666,-4.03334,GMT,CI,+0'>Africa/Abidjan</option><option value='Africa/Accra' data-geo='5.55,-0.21667,GMT,GH,+0'>Africa/Accra</option>"; // etcetera etcetera etcetera

    if (tz != "") {
    document.write("<h1 title='Clock clicks popup Colour Wheel, Separator click for Timezone Info, Separator right click for Google Geo Chart Map, Flag text click for Google Maps and right click for concatenated Google Map Chart' id=myh1>SVG Network Clock</h1><h3>RJM Programming <button title='- for here and toggle to + for to right' id=lhmode onclick='this.innerHTML=this.innerHTML.replace(String.fromCharCode(45),String.fromCharCode(93)).replace(String.fromCharCode(43),String.fromCharCode(45)).replace(String.fromCharCode(93),String.fromCharCode(43));'>-</button> January, 2020</h3><h4 onclick='woit(this.title);' id=myh4 title='" + sih + "'>Enter toggles fullscreen mode and thanks to The PHP Anthology Volume II: Applications by Harry Fuecks</h4><p>The <select id=mysel onchange=gonext(this.value);>" + ("<option value='GMT'>GMT</option><option value='localtime'>Localtime</option>" + setpretz() + tzlist).replace('>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<',' selected>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<') + "</select> <select style='display:inline-block;' onchange=\"locationhref=(document.URL.replace('analogue=','x=').replace('both=','y=') + ('&' + this.value + '=y').replace('&=y','')).replace('.html&','.html?').replace('.htm&','.htm?') + lh; lhit(prevmysel,this);\"><option value=''>digital clock</option><option value=analogue" + analoguesuffix + ">analogue clock</option><option value=both" + bothsuffix + ">digital and analogue clock</option></select> sponsored by SVG is<br><hr id=myhr style='height:3px;' title='Click here for any Daylight Saving Time information' onclick=\"window.open('http://www.timezoneconverter.com/cgi-bin/zoneinfo?tz=" + encodeURIComponent(tz) + "','_blank','top=50,left=50,width=500,height=500');\"><br><object id=myclock data='svg_clock.php?timezone=" + encodeURIComponent(tz + loct) + uprefix + "' width='" + nh + "' height='530' type='image/svg+xml' /></p>" + es);
    } else {
    document.write("<h1 title='Clock clicks popup Colour Wheel, Separator click for Timezone Info, Separator right click for Google Geo Chart Map, Flag text click for Google Maps and right click for concatenated Google Map Chart' id=myh1>SVG Network Clock</h1><h3>RJM Programming <button title='- for here and toggle to + for to right' id=lhmode onclick='this.innerHTML=this.innerHTML.replace(String.fromCharCode(45),String.fromCharCode(93)).replace(String.fromCharCode(43),String.fromCharCode(45)).replace(String.fromCharCode(93),String.fromCharCode(43));'>-</button> January, 2020</h3><h4 onclick='woit(this.title);' id=myh4 title='" + sih + "'>Enter toggles fullscreen mode and thanks to The PHP Anthology Volume II: Applications by Harry Fuecks</h4><p>The <select id=mysel onchange=gonext(this.value);>" + ("<option value='GMT'>GMT</option><option value='localtime'>Localtime</option>" + setpretz() + tzlist).replace('>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<',' selected>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<') + "</select> <select style='display:inline-block;' onchange=\"locationhref=(document.URL.replace('analogue=','x=').replace('both=','y=') + ('&' + this.value + '=y').replace('&=y','')).replace('.html&','.html?').replace('.htm&','.htm?') + lh; lhit(prevmysel,this);\"><option value=''>digital clock</option><option value=analogue" + analoguesuffix + ">analogue clock</option><option value=both" + bothsuffix + ">digital and analogue clock</option></select> sponsored by SVG is<br><br><br><object id=myclock data='svg_clock.php" + uprefix.replace('&','?') + "' width='" + nh + "' height='530' type='image/svg+xml' /></p>");
    }
    document.write("<iframe style=height:60vh; frameborder=0 id='loces' onload='getmelt(this);' src='cldate.php?localtime=y&firstcall=" + ('' + Intl.DateTimeFormat().resolvedOptions().timeZone) + '&nowis=' + ('0' + (new Date().getHours())).slice(-2) + ':' + ('0' + (new Date().getMinutes())).slice(-2) + "'></iframe>");
    </script>
    <!--iframe style=height:60vh; frameborder=0 id='loces' onload='getmelt(this);' src='cldate.php?localtime=y'></iframe-->

    </body>

    … “helper” code to create the amended favicon.svg and amend the parent to use the new favicon.svg as per …

    <?php

    $pdt="";

    if (strpos(('' . $_SERVER['QUERY_STRING']), "localtime") !== false) {
    if (strpos(('' . $_SERVER['QUERY_STRING']), "firstcall") !== false) {
    if (strpos(('' . $_SERVER['QUERY_STRING']), "nowis=") !== false) {
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg')) {
    $fsvg=file_get_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg');
    if (strpos($fsvg, '</text>') !== false) {
    $curts=explode('>', explode('</text>', $fsvg)[0])[-1 + sizeof(explode('>', explode('</text>', $fsvg)[0]))];
    if (strpos($fsvg, '>' . $curts . '</text>')) {
    $pdt=" parent.document.title+=' you started at " . str_replace('+',' ',urldecode($_GET['nowis'])) . " local time'; parent.document.getElementById('myh1').innerHTML+='<font size=1> ... you started at " . str_replace('+',' ',urldecode($_GET['nowis'])) . " local time</font>'; ";
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg', str_replace('>' . $curts . '</text>', '>' . str_replace('+',' ',urldecode($_GET['nowis'])) . '</text>', $fsvg));
    }
    }
    }
    } else {
    $localtime = localtime();
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg')) {
    $fsvg=file_get_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg');
    if (strpos($fsvg, '</text>') !== false) {
    $curts=explode('>', explode('</text>', $fsvg)[0])[-1 + sizeof(explode('>', explode('</text>', $fsvg)[0]))];
    if (strpos($fsvg, '>' . $curts . '</text>')) {
    $pdt=" parent.document.title+=' you started at " . substr(('0' . $localtime[2]),-2,2) . ':' . substr(('0' . $localtime[1]),-2,2) . " local time'; parent.document.getElementById('myh1').innerHTML+='<font size=1> ... you started at " . str_replace('+',' ',urldecode($_GET['nowis'])) . " local time</font>'; ";
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg', str_replace('>' . $curts . '</text>', '>' . substr(('0' . $localtime[2]),-2,2) . ':' . substr(('0' . $localtime[1]),-2,2) . '</text>', $fsvg));
    }
    }
    }
    }

    }
    echo "<html><head><script type='text/javascript'> var iwois=null; </script></head><body><div id=mydiv></div><script type='text/javascript'>
    var asuff='" . $midbit . $csuff . "';
    var adate = new Date();
    var dow=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
    var his=eval('' + adate.getHours());
    var mis=eval('' + adate.getMinutes());
    var sis=eval('' + adate.getSeconds());
    var ssuff='';
    if (('' + adate).indexOf(' GMT') != -1) { ssuff=' GMT' + ('' + adate).split(' GMT')[1]; }
    if (1 == 1) {
    document.getElementById('mydiv').innerHTML=dow[eval('' + adate.getDay())] + ' ' + ('0' + his).slice(-2) + ':' + ('0' + mis).slice(-2) + ':' + ('0' + sis).split('.')[0].slice(-2) + ' ' + ('0' + adate.getDate()).slice(-2) + ' ' + ('0' + eval(1 + eval('' + adate.getMonth()))).slice(-2).replace('01','Jan').replace('02','Feb').replace('03','Mar').replace('04','Apr').replace('05','May').replace('06','Jun').replace('07','Jul').replace('08','Aug').replace('09','Sep').replace('10','Oct').replace('11','Nov').replace('12','Dec') + ' ' + ('' + adate.getFullYear()) + ' ' + ssuff + asuff;
    } else {
    document.write(dow[eval('' + adate.getDay())] + ' ' + ('0' + his).slice(-2) + ':' + ('0' + mis).slice(-2) + ':' + ('0' + sis).split('.')[0].slice(-2) + ' ' + ('0' + adate.getDate()).slice(-2) + ' ' + ('0' + eval(1 + eval('' + adate.getMonth()))).slice(-2).replace('01','Jan').replace('02','Feb').replace('03','Mar').replace('04','Apr').replace('05','May').replace('06','Jun').replace('07','Jul').replace('08','Aug').replace('09','Sep').replace('10','Oct').replace('11','Nov').replace('12','Dec') + ' ' + ('' + adate.getFullYear()) + ' ' + ssuff + asuff);
    }
    var myl=parent.document.getElementById('mylink').href;
    if (myl.indexOf('JUNK') != -1) { parent.document.getElementById('mylink').href='/favicon.svg?rand=" . rand(0, 4534567) . "'; " . $pdt . " }

    </script></body></html>";
    }

    ?>

    Interesting, huh?!


    Previous relevant SVG Network Clock Minimize Tutorial is shown below.

    SVG Network Clock Minimize Tutorial

    SVG Network Clock Minimize Tutorial

    Today’s blog posting’s underlying SVG Network Clock web application (we last talked about with Colour Wheel Size and Spoke Colour Tutorial’>Colour Wheel Size and Spoke Colour Tutorial) shares a couple of commonalities with yesterday’s MAMP Timekeeping Web Application Visibility Tutorial, those being …

    … those Page Visibility API ideas you might equate to “minimize” concepts, that originated when GUIs were left to deal with how to present the representation of an application when it is no longer front and center in front of the user as an opened up window. We’d “minimize” back down to the desktop icon or toolbar view of the application. Web browsers can have tabs for this equivalent purpose, and we can improve the usefulness of a web application that can still be useful when “minimized” out of the top viewing tab. Date and time themed web applications can be your more obvious candidate for usefulness here. Just present a form of “digital clock readout” and your web applications like our SVG Network Clock can still be a source of information, even when “minimized”. We think that is an improvement?!

    As you might have noticed with the last application of Page Visibility API “smarts”, this API is not hard to use, but for the first time we can remember, making changes just to the changed HTML supervisor svg_clock.html SVG Network Clock supervisor HTML and Javascript, and only changed to see in a new external Javascript svg_clock.js helper, we saved coding time by being able to …

    • scrutinize the DOM …
    • within an “object” HTML element’s …
    • SVG … featuring in some new Javascript with its own Page Visibility API reference

      function huhcont() {
      var dtidea='';
      var dotwis=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
      if (document.title != origdtis || ishd == ishd.toUpperCase()) { setTimeout(huhcont, 1000); }
      ishd == ishd.toLowerCase();
      if (document.getElementById('myclock') && ('' + document.visibilityState) == 'hidden') {
      if (document.getElementById('myclock').contentDocument.documentElement.outerHTML.indexOf(' id="sclock"') != -1) {
      console.log('predtidea');
      dtidea=document.getElementById('myclock').contentDocument.documentElement.outerHTML.split(' id="sclock"')[1].split('<')[0].split('>')[1].trim();
      console.log('dtidea=' + dtidea + ' ... ' + document.URL);
      if (dtidea != '') {
      document.title=dtidea;
      } else if (document.URL.indexOf('timezone=') != -1) {
      document.title=('' + new Date().toLocaleString("en-US", {timeZone: (location.search.split('timezone=')[1] ? decodeURIComponent(location.search.split('timezone=')[1].split('&')[0]) : "")}) + ' ' + (location.search.split('timezone=')[1] ? decodeURIComponent(location.search.split('timezone=')[1].split('&')[0]) : "") + ' ' + (location.search.split('emflag=')[1] ? decodeURIComponent(location.search.split('emflag=')[1].split('&')[0]) : ""));
      } else {
      document.title=new Date().toLocaleString("en-US", {timeZone: "GMT"});
      }
      } else {
      console.log('Why?');
      }
      }
      }

      … where we’d like to thank this useful link, thanks, for the heads up

    Interesting, huh?!


    Previous relevant MAMP Timekeeping Web Application Desktop Application Tutorial is shown below.

    MAMP Timekeeping Web Application Desktop Application Tutorial

    MAMP Timekeeping Web Application Desktop Application Tutorial

    We figured that an improvement on the progress with our Timekeeping web application of the recent MAMP Timekeeping Web Application Audio Broadcast Tutorial would be to mention what macOS or Mac OS X Desktop Application is topmost when the screenshot is taken. When thinking about solutions for this, there was not much time before thinking turned to …

    • Apple Script, which has its GUI Apple “look” … but also …
    • Apple Script PHP shell_exec and (macOS Terminal) command line accessible osascript command line “look” too

    … and excellent resources such as this excellent one to read that made us realize a PHP codeline such as …

    <?php

    $tma="";
    if (!file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'script.jxa')) {
    // Thanks to https://stackoverflow.com/questions/5292204/macosx-get-foremost-window-title
    $scris="var seApp = Application(\"System Events\");
    var oProcess = seApp.processes.whose({frontmost: true})[0];
    var appName = oProcess.displayedName();

    var url;
    var title;

    switch(appName) {
    case \"Safari\":
    url = Application(appName).documents[0].url();
    title = Application(appName).documents[0].name();
    break;
    case \"Opera\":
    url = Application(appName).windows[0].activeTab().url();
    title = Application(appName).windows[0].activeTab().name();
    break;
    case \"Google Chrome\":
    url = Application(appName).windows[0].activeTab().url();
    title = Application(appName).windows[0].activeTab().name();
    break;
    case \"Google Chrome Canary\", \"Chromium\":
    url = Application(appName).windows[0].activeTab().url();
    title = Application(appName).windows[0].activeTab().name();
    break;
    default:
    title = oProcess.
    windows().
    find(w => w.attributes.byName(\"AXMain\").value() === true).
    attributes.
    byName(\"AXTitle\").
    value()
    }

    JSON.stringify({
    appname: appName,
    url: url,
    title: title
    });";
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'script.jxa', $scris);
    }
    $tma=shell_exec('osascript -l JavaScript ' . $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'script.jxa');

    ?>

    … can glean such useful JSON results such as …


    {"appname":"Safari","url":"http://localhost:8888/HTMLCSS/quarter_hour_timer.php?tz=Australia%2FSydney&qs=e&audiosave=%20-v%20Victoria%20%20-o%20out.aiff%20%20Screenshot%20%20at%20Monday%20July%2025%202022%2021%2030%20AEST","title":"‎localhost:8888/HTMLCSS/quarter_hour_timer.php?tz=Australia%2FSydney&qs=e&audiosave=%20-v%20Victoria%20%20-o%20out.aiff%20%20Screenshot%20%20at%20Monday%20July%2025%202022%2021%2030%20AEST"}

    … well, it almost makes us speechless!

    This change affected …

    … and we hope you try it for yourself!


    Previous relevant MAMP Timekeeping Web Application Audio Broadcast Tutorial is shown below.

    MAMP Timekeeping Web Application Audio Broadcast Tutorial

    MAMP Timekeeping Web Application Audio Broadcast Tutorial

    We thought what could be a benefit to the Timekeeping web application of the recent MAMP Timekeeping Web Application Web Share Personalization Tutorial would be to …

    • offer an optional audio broadcasting piece of functionality … presented via a new 📢 (&#128226;) emoji button, that might accompany …
    • notifications

    … when a screenshot is taken. As good as notifications are, it could be that the user is beavering away with their head down at work as the screenshot is taken, but welcome the audio queue that a Timekeeping screenshot has been taken. As well as that, with this new audio broadcasting, the *.aiff audio files created are available to share via email or SMS using the Web Share API interfacing code. This involved changes to …


    Previous relevant MAMP Timekeeping Web Application Web Share Personalization Tutorial is shown below.

    MAMP Timekeeping Web Application Web Share Personalization Tutorial

    MAMP Timekeeping Web Application Web Share Personalization Tutorial

    Your words, helped out by some computer derived detail data, can help personalize your work using the Quarter Hour Timekeeping web application of yesterday’s MAMP Timekeeping Web Application Web Share API Tutorial which, at least with the Safari browser (and a whole lot of other macOS conditions), now integrates with the Web Share API to attach images to prepared emails with a “body blurb”. It is that prepared “body blurb” we are trying to refine, today, should the user attach any of those Timekeeper screenshot files created via macOS screencapture command.

    This is because these screenshot file names, by our convention, are of the format …


    screen-yyyymmdd-hhmi.jpg

    … within the macOS MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] folder (though the path to the file is unavailable to File API File object programmers).

    That, teamed with the fact that individual user comments linked to any one quarter hour screenshot image has an ID attribute of the form …


    tatd_yyyymmdd_hhmi

    … and you have modified Javascript helping the user to tailor better personalized and detail email or SMS communications using the changed macos_say_record.js external Javascript via …


    var wsadate=new Date();
    var lfd=String.fromCharCode(10);

    function getwsadate(dd, mm, yyyy, hh, mi) {
    wsadate=new Date(yyyy, eval(-1 + eval('' + mm)), dd, hh, mi, 0, 0);
    var outdstr=wsadate.toDateString() + ' ' + wsadate.toTimeString();
    outdstr=outdstr.replace('Sun ', 'Sunday ').replace('Mon ', 'Monday ').replace('Tue ', 'Tuesday ').replace('Wed ', 'Wednesday ').replace('Thu ', 'Thursday ').replace('Fri ', 'Friday ').replace('Sat ', 'Saturday ');
    outdstr=outdstr.replace(':00 ', ' ').replace(' Jan ', ' January ').replace(' Feb ', ' February ').replace(' Mar ', ' March ').replace(' Apr ', ' April ').replace(' Jun ', ' June ').replace(' Jul ', ' July ').replace(' Aug ', ' August ').replace(' Sep ', ' September ').replace(' Oct ', ' October ').replace(' Nov ', ' November ').replace(' Dec ', ' December ');
    //console.log('tatd_' + yyyy + mm + dd + '_' + hh + mi);
    if (document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi)) {
    //console.log('yes tatd_' + yyyy + mm + dd + '_' + hh + mi);
    if (document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).value.trim() != '') {
    outdstr+=' ' + String.fromCharCode(10) + '"' + document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).value + '"';
    } else if (document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).innerHTML.trim() != '') {
    outdstr+=' ' + String.fromCharCode(10) + '"' + document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).innerHTML + '"';
    }
    }
    lfd='';
    return outdstr + String.fromCharCode(10);
    }


    async function atclick() {
    const files = document.getElementById('files').files;
    var moressi='', ifl=0, lessssi='';

    if (files.length === 0) {
    shareurl();
    document.getElementById('output').textContent = 'No files selected.';
    return;
    } else {
    for (ifl=0; ifl<files.length; ifl++) {
    if (('' + files[ifl].name).indexOf('screen-') != -1) {
    if (('' + files[ifl].name).split('screen-')[1].split('-')[0].length == 8) {
    if (('' + files[ifl].name).split('screen-')[1].split('-')[1].split('.')[0].length == 4) {
    moressi+=lfd + ' on ' + getwsadate(('' + files[ifl].name).split('screen-')[1].split('-')[0].slice(-2), ('' + files[ifl].name).split('screen-')[1].split('-')[0].slice(-4).substring(0,2), ('' + files[ifl].name).split('screen-')[1].split('-')[0].substring(0,4), ('' + files[ifl].name).split('screen-')[1].split('-')[1].split('.')[0].substring(0,2), ('' + files[ifl].name).split('screen-')[1].split('-')[1].split('.')[0].slice(-2));
    }
    }
    }
    }

    }

    lessssi=moressi;
    while (lessssi.indexOf(String.fromCharCode(10)) != -1) {
    lessssi=lessssi.replace(String.fromCharCode(10), ' ');
    }


    // feature detecting navigator.canShare() also implies
    // the same for the navigator.share()
    if (!navigator.canShare) {
    //if (document.URL.indexOf('localhost') != -1) { alert('Can not share'); }
    document.getElementById('output').textContent = `Your browser doesn't support the Web Share API.`;
    return;
    //} else {
    //if (document.URL.indexOf('localhost') != -1) { alert('Can Share'); }
    }

    if (navigator.canShare({ files })) {
    try {
    console.log('Can share');
    await navigator.share({
    files,
    title: 'Timekeeping screenshots' + lessssi + ' or media or documents',
    text: 'Timekeeping screenshots' + moressi + ' perhaps?! Take a look at media or documents below' + String.fromCharCode(10) + String.fromCharCode(10)
    });
    document.getElementById('output').textContent = 'Shared!';
    } catch (error) {
    document.getElementById('output').textContent = `Error: ${error.message}`;
    }
    } else {
    //if (document.URL.indexOf('localhost') != -1) { alert('Cannot share'); }
    document.getElementById('output').textContent = `Your system doesn't support sharing these files.`;
    }
    lfd=String.fromCharCode(10);
    }


    Previous relevant MAMP Timekeeping Web Application Web Share API Tutorial is shown below.

    MAMP Timekeeping Web Application Web Share API Tutorial

    MAMP Timekeeping Web Application Web Share API Tutorial

    Adding onto yesterday’s MAMP Timekeeping Web Application Audio Commentary Tutorial

    • Timekeeping Web Application newish Text to Audio (via macOS say via MAMP “Intranet feel”) … today, we have …
    • Timekeeping Web Application new Web Share API (public domain Document Root external Javascript Web Share API) Javascript logic

    This got us decoupling what can become …

    … but as we’ve warned before you may need all these for total success for the Timekeeping Quarter Hour Timer web application (that can screenshot, can create notification when screenshot taken, and have audio commentary, and share screenshot image(s) or Timekeeper URL) …


    Previous relevant MAMP Timekeeping Web Application Audio Commentary Tutorial is shown below.

    MAMP Timekeeping Web Application Audio Commentary Tutorial

    MAMP Timekeeping Web Application Audio Commentary Tutorial

    The recent MAMP Timekeeping Web Application PHP Notifications Tutorial‘s Timekeeping via Screenshots changed HTML and Javascript quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Web Application supervisor is another very suitable candidate for interfacing to our recent Webpage Audio Commentary functionality. Both …

    … share an …

    • underlying macOS or Mac OS X operating system dependence …
    • underlying local web server such as MAMP …
    • downloaded into that local web server Document Root folder PHP code

    … set of interest points for full and useful functionality, because of two macOS or Mac OS X commands, respectively …

    We add the changed macos_say_record.js external Javascript call into the supervisory HTML and Javascript <head></head> webpage section via …


    <script type='text/javascript' src='//www.rjmprogramming.com.au/macos_say_record.js?ongoing=1721156687576' defer></script>

    … sitting up at the Document Root of your public domain, that “?ongoing=” based $_GET[‘ongoing’] argument deliberate, effectively asking the code to look out for “on the fly” HTML elements created within an execution run of the webpage.

    We add some “smarts” to those global data attribute usage we talked about at Webpage macOS Say Audio Commentary Access Count Tutorial, allowing some “date extraction” templating via the supervisory HTML and Javascript array declaration as per


    <script type='text/javascript'>
    var commentary_array=['textarea', 'You can enter comments about this screenshot here %value%outerHTML%@yyyymmdd%hhmm%.', 'img', 'Timekeeper screenshot here %id%@yyyymmdd%hhmm%.'];
    </script>

    … where the first field describes an HTML element attribute to first look at, the optional second is a stand by attribute, followed by “date extraction” fields to match with numerical data found so as to substitute the blue parts with a “date and timestamp” string.


    Previous relevant MAMP Timekeeping Web Application PHP Notifications Tutorial is shown below.

    MAMP Timekeeping Web Application PHP Notifications Tutorial

    MAMP Timekeeping Web Application PHP Notifications Tutorial

    Today we’re revisiting the macOS (or Mac OS X) or Windows timekeeping web application of 2016’s Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial. Why? Well, given our recent work with Notifications API based web applications you can read about at Notification API Hidden Popup Tutorial, the timekeeping one is a great candidate for functionality improvement here, it being a web application that …

    • can work behind the scenes …
    • not necessarily frontmost … but benefitting from any …
    • notification reminders separate from web activities and webpage focus issues can help tell the user when they might want to turn back attention to the timekeeping screenshot recording

    This needs PHP to work and it needs real access via PHP exec function to underlying operating system commands. When this happens, we still try to offer a public RJM Programming interface but this interface is far less useful if you have not downloaded to your local Apache/PHP/MySql local web server (such as a MAMP one) as per …

    1. the changed quarter_hour_timer.php (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage
    2. the unchanged (from tutorial below, supervisory HTML and Javascript) quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application
    3. the “how we got there” PHP notifications_ideas.php (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] subfolder) Notification API functionality PHP web application

    … in what we like to call an “Intranet feeling” scenario.

    Up at the public RJM Programming domain, as far as the Notification API functionality supervisor webpage goes, the changed HTML and Javascript notifications_ideas.html Notification API functionality HTML and Javascript web application is worth trying.


    Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial is shown below.

    Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial

    Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial

    To finish up our revisit to the Timekeeping web application of the recent Mac OS MAMP Timekeeping Web Application PHP Calendar Iframe Tutorial we …

    • make some styling calendar tweaks

      <style>
      td { vertical-align: top; }
      #divmc { background-color: #ffffff; }
      p:not(:empty) { border: 1px dotted red; }
      td { text-align: center; vertical-align: top; }
      th { background-color: cyan; }
      #thyear { background-color: pink; }
      div { word-wrap: break-word; }
      .adaNOte { border: 3px solid pink; border-radius: 7px; }
      a.adate { border:2px solid transparent; background-color:lightgreen; border-radius:50px; }

      </style>
    • settle for mobile platforms never being able to screenshot, on this round of looking, and redirecting to the “Monthly Chronicler” web application (of (the unchanged) monthly_chronicler.html we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder)

      <script>
      if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i)) {
      document.write("<scri" + "pt> location.href='./monthly_chronicler.html'; </scr" + "ipt> <style> a.adate { border:1px solid green; background-color:#f0f0f0; border-radius:50px; } </style> <table id=mtable style=display:none;width:95%;><tr><th><input style=width:450px; placeholder='' id=iask type=text value=''></input><</th><th><input onclick=\" document.getElementById('mtable').style.display='none'; document.getElementById('mybod').style.opacity='1.0'; postask(document.getElementById('iask'));\" type=button value=OK></input></th><th><input onclick=\"document.getElementById('iask').value=''; document.getElementById('mtable').style.display='none'; document.getElementById('mybod').style.opacity='1.0'; \" type=button value=Cancel></input></th></tr></table>");
      }
      </script>

      … dumbing down, but working more reliably, using “Javascript writes Javascript” methodology

    Again, feel free to try the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a “mobile platform check” changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment, or all showing up at an RJM Programming public domain webpage, in an iframe element, visible now.


    Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Windows Tutorial is shown below.

    Mac OS MAMP Timekeeping Web Application PHP Calendar Windows Tutorial

    Mac OS MAMP Timekeeping Web Application PHP Calendar Windows Tutorial

    Did you notice that the “Timekeeping” PHP did not have to change for yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial?

    But the PHP is the change agent for Windows (client) integration called quarter_hour_timer.php today …

    <?php

    // blah top
    $lportbit=":8888";

    $user_agent = $_SERVER["HTTP_USER_AGENT"];
    function getOS() { // thanks to https://www.daniweb.com/programming/web-development/threads/495588/getting-users-os-info-out-of-server-http-user-agent
    global $user_agent, $lportbit;
    $os_platform = "win Unknown OS Platform";
    $os_array = array(
    '/windows nt 10/i' => 'Windows 10',
    '/windows nt 6.3/i' => 'Windows 8.1',
    '/windows nt 6.2/i' => 'Windows 8',
    '/windows nt 6.1/i' => 'Windows 7',
    '/windows nt 6.0/i' => 'Windows Vista',
    '/windows nt 5.2/i' => 'Windows Server 2003/XP x64',
    '/windows nt 5.1/i' => 'Windows XP',
    '/windows xp/i' => 'Windows XP',
    '/windows nt 5.0/i' => 'Windows 2000',
    '/windows me/i' => 'Windows ME',
    '/win98/i' => 'Windows 98',
    '/win95/i' => 'Windows 95',
    '/win16/i' => 'Windows 3.11',
    '/macintosh|mac os x/i' => 'Mac OS X',
    '/mac_powerpc/i' => 'Mac OS 9',
    '/linux/i' => 'Linux',
    '/ubuntu/i' => 'Ubuntu',
    '/iphone/i' => 'iPhone',
    '/ipod/i' => 'iPod',
    '/ipad/i' => 'iPad',
    '/android/i' => 'Android',
    '/blackberry/i' => 'BlackBerry',
    '/webos/i' => 'Mobile'
    );

    foreach ($os_array as $regex => $value) {

    if (preg_match($regex, $user_agent)) {
    $os_platform = $value;
    }

    }

    return $os_platform;
    }

    $callornot="call ";
    $precmds="";
    $impreexe="screenCapture"; //"import";
    $switches=""; //" -window root ";
    if (substr(strtoupper(getOS()),0,3) === 'WIN') {
    $lportbit="";
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . "\\" . $impreexe . ".exe")) {
    $precmds=$_SERVER['DOCUMENT_ROOT'] . "\\";
    } else {
    foreach (glob("C:\\Users\\*\\" . $impreexe . ".exe") as $infl) {
    $precmds=explode($impreexe . ".exe", $infl)[0];
    }
    }
    }

    // blah blah some other PHP functions

    if (isset($_GET['yourta'])) {
    // calendar work
    } else if (isset($_GET['myta'])) {
    // embed image metadata
    } else if (isset($_POST['myta'])) {
    // parse image metadata
    } else if ($lportbit != "") {
    exec("/usr/sbin/screencapture -Cd -tjpg " . $_SERVER['DOCUMENT_ROOT'] . "/screen-`date +\"%Y%m%d-%H%M\"`.jpg");
    } else {
    if (isset($_GET['tz'])) {
    $tzis=str_replace('+','_',urldecode($_GET['tz']));
    if (strpos($tzis, "/") !== false) { date_default_timezone_set($tzis); }
    }
    $dateis = date('Ymd-Hi');
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . "\\screenCapture.jpg")) {
    exec('copy ' . '"' . $_SERVER['DOCUMENT_ROOT'] . "\\screenCapture.jpg" . '" "' . $_SERVER['DOCUMENT_ROOT'] . "\\screen-" . $dateis . '.jpg"');
    // exec('erase ' . '"' . $_SERVER['DOCUMENT_ROOT'] . "\\screenCapture.jpg" . '"');
    } else {
    exec($callornot . '"' . $precmds . $impreexe . '.exe" ' . $switches . ' "' . $_SERVER['DOCUMENT_ROOT'] . "\\screen-" . $dateis . '.jpg"');
    }
    }

    exit;

    ?>

    … which you may glean has a Windows “fallback” position (with that “copy” codeline). Why? Well, we found a .Net framework “exe creation via bat” using ScreenCapture.bat (thanks to this useful link) created black screen shots. Probably a privilege thing or PHP exec thing, but we’ve opted for the workaround, which is just “Windows talk” …

    • write Windows batch scapcontinuous.bat as a continuous fifteen minute user of the .Net Framework (ScreenCapture.exe) derived from above
    • set up a task via “Task Schedular” (please ignore the warts ‘n all “garden path” schtask ideas in the video below) that has an action “C:\MAMP\htdocs\scapcontinuous.bat” and starts when the Windows user logs in and takes (successful) screen shots at 14 and 29 and 44 and 59 minutes (in the hour) times

    Take a more detailed look at “warts ‘n all” crab progression towards the Windows (client) solution, below …


    Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial is shown below.

    Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial

    Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial

    Yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial‘s “Calendar Past” improvements don’t have to be the end of the story regarding “calendar timings”. There is an Apple iCal standard interfacing format that can drive calendar integrations with many well known online Calendar applications.

    You may recall us talking about this with Calendar Location Services Integration Tutorial and we tweak the changed ics_attachment.php (which we’d ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “PHP” subfolder) and its standalone ical creator to better integrate with the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage.

    This bit of functionality works (interfacing) both with MAMP and with the public RJM Programming domain incarnation of the Timekeeping web application, so that could be interesting. It can interface via …

    … modes of use. In action, should you create an iCal file this way, the web application will download the resultant .ics file into your Downloads folder and to interface into your default online Calendar application double click that Downloads folder file to complete the Calendar integration …


    function icalpostit(tl, tg) {
    var today = new Date();
    var dd = today.getDate();
    var mm = today.getMonth()+1; //January is 0!
    var yyyy = today.getFullYear();
    var hh = today.getHours();
    var minm = today.getMinutes(); //January is 0!
    //if (icalavailable) { alert('is ' + ('' + yyyy + ('00' + mm).slice(-2) + ('00' + dd).slice(-2) ) + ' >= ' + tl.substring(1)); }
    if ((document.getElementById('yics').value.indexOf('all') != -1 || tl.substring(1) >= ('' + yyyy + ('00' + mm).slice(-2) + ('00' + dd).slice(-2) )) && icalavailable && document.getElementById('yics').value != '') {
    if (document.getElementById('yics').value.indexOf('nw') != -1) {
    icald=tl.substring(1) + ':' + ('00' + hh).slice(-2) + ('00' + minm).slice(-2) + '59';
    icalg=tg;
    if (icalwo != null) { icalwo.close(); icalwo=null; }
    icalwo=window.open('../PHP/ics_attachment.php','_blank','top=100,left=100,width=740,height=800');
    if (1 == 1) {
    setTimeout(icalw, 3000);
    } else {
    icalwo.document.getElementById('datestart').value=icald;
    icalwo.document.getElementById('dateend').value=icald;
    icalwo.document.getElementById('eventwords').value=icalg.replace(/\<br\>/g, String.fromCharCode(10)).replace(/\<Br\>/g, String.fromCharCode(10)).replace(/\<BR\>/g, String.fromCharCode(10));
    if (document.URL.indexOf('localhost') != -1) {
    var jcald=icalg.replace(/\<br\>/g, String.fromCharCode(10)).replace(/\<Br\>/g, String.fromCharCode(10)).replace(/\<BR\>/g, String.fromCharCode(10)).replace(/\ \;>/g, ' ');
    while (jcald.indexOf(String.fromCharCode(10)) != -1) { jcald=jcald.replace(String.fromCharCode(10),' '); }
    icalwo.document.getElementById('title').value=jcald;
    } else {
    icalwo.document.getElementById('title').value='Calendar event at ' + icald;
    }
    icalwo.document.getElementById('description').value='Calendar event at ' + icald;
    icalwo.document.getElementById('address').value=document.URL.split('?')[0].split('#')[0];
    icalwo.document.getElementById('mmdatestart').value=icald.substring(4,6);
    icalwo.document.getElementById('mmdateend').value=icald.substring(4,6);
    icalwo.document.getElementById('dddatestart').value=icald.substring(6,8);
    icalwo.document.getElementById('dddateend').value=icald.substring(6,8);
    icalwo.document.getElementById('ssdatestart').value='59';
    icalwo.document.getElementById('ssdateend').value='59';
    icalwo.document.getElementById('yyyydatestart').value=icald.substring(0,4);
    icalwo.document.getElementById('yyyydateend').value=icald.substring(0,4);
    if ( ('' + today.getTimezoneOffset()).replace('null','').replace('undefined','') != '' ) {
    //alert(('' + eval(eval('' + qd.getTimezoneOffset()) / 60.0)).replace('.00','').replace('.0',''));
    icalwo.document.getElementById('tz').value=('' + eval(eval('' + today.getTimezoneOffset()) / 60.0)).replace('.00','').replace('.0','');
    }
    //icalwo.document.getElementById('pform').onsubmit=function() { window.opener.document.getElementById('icalstatus').innerHTML=' '; return true; };

    }
    } else if (document.getElementById('yics').value.indexOf('if') != -1) {
    icald=tl.substring(1) + ':' + ('00' + hh).slice(-2) + ('00' + minm).slice(-2) + '59';
    icalg=tg;
    document.getElementById('divics').style.display='block';
    document.getElementById('divics').style.width='100%';
    document.getElementById('divics').style.height='800px';
    document.getElementById('icslocit').style.display='block';
    document.getElementById('icslocit').style.width='100%';
    document.getElementById('icslocit').style.height='800px';
    document.getElementById('icslocit').src='../PHP/ics_attachment.php?rand=' + Math.floor(Math.random() * 19876564);
    } else {
    var xzhr = new XMLHttpRequest();
    var xform=new FormData();
    xform.append('icald',tl.substring(1) + ':' + ('00' + hh).slice(-2) + ('00' + minm).slice(-2) + '59');
    xform.append('icalc',tg);
    xzhr.open('post','./quarter_hour_timer.php',true);
    xzhr.send(xform);
    }
    }
    }


    Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial is shown below.

    Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial

    Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial

    We’ve spoken quite a bit in the past about the joys of involving the “contenteditable=true” attribute for HTML elements that have an “innerHTML” (ie. they have a formalized end tag arrangement eg. div, span, p, td, th etcetera) and with today’s work which extends that started with yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial it is the turn of a set of “p” elements it helps out today.

    The scenario is that yesterday’s work did not allow for “orphaned screenshots” of the past be allowed to be brought back into play to “annotate them” and in so doing “give them a home”. This led us to …

    • allow for a new “Infill Earlier Days All Screenshots” button augment yesterday‘s “Infill Earlier Days Just Annotated Screenshots” button …
    • the pressing of that new “Infill Earlier Days All Screenshots” button causes all screenshot 15 minute entries relevant to the current year be displayed in the calendar … but then it occurred to us users might want to “annotate them” … but how? …
    • in the PHP we introduced code
      <?php

      if (isset($_GET['yourta'])) {
      $dru="http://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
      $cet="";
      if (strlen($_GET['yourta']) != 0) { $cet=" contenteditable=true onblur=repostit(this); onfocus=wopen(event,false); "; }

      // blah blah blah
      $ccpre="" . $cet . " onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-repeat:no-repeat;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); onmouseover=wopen(event,true); onmouseout=wopen(event,false); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
      // blah blah blah
      }

      ?>
      … to, when an “orphaned” screen shot image is happened upon, allows …
    • contenteditable=true “does its stuff” turning might might have been a pretty unintelligent HTML element into a “textarea” type collector of user input, and then that onblur event logic’s “midair feeling” Ajax/FormData “recursive feeling” methodology …

      function repostit(ih) {
      var ihis=(ih.innerText || ih.contentWindow || ih.contentDocument);
      var pathpart=ih.id;
      if (ihis != '') {
      var xzhr = new XMLHttpRequest();
      var xform=new FormData();
      xform.append('myta',ihis);
      xform.append(pathpart.split('.')[0].replace('ip_','screen-').replace('_','-'),'');
      xzhr.open('post','./quarter_hour_timer.php',true);
      xzhr.send(xform);
      }
      }

      … which can cement that (newly user entered) annotation into future permanency in the “Yearly Report Calendar” section

    … of the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a contenteditable=true changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment.


    Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial is shown below.

    Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial

    Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial

    If you’ve been using the Timekeeping web application as of yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial you would have noticed a very …

    • first person
    • present tense

    … feel to it all. Today, we improve on the latter “restrictiveness” issue, within yesterday’s “Yearly Report Calendar” new functionality, by looking back into the current calendar year’s “past” with respect to the date of using the web application, whether that be …

    • screen captures from days in the current calendar year’s “past”
    • text entries made and remembered (in window.localStorage) in the current calendar year’s “past”

    … to infill and flesh out that “Yearly Report Calendar” better. This involved bringing over a lot of (the unchanged) monthly_chronicler.html‘s Javascript logic into the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a calendar’s past integrationally changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment.

    <?php

    // quarter_hour_timer.php
    // RJM Programming
    // December, 2021

    if (isset($_GET['yourta'])) {
    $dru="HTTP://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
    $contis=str_replace('+',' ',urldecode($_GET['yourta']));
    //file_put_contents('xx.xx', $contis);
    $htmlis='';
    $myf='';
    $backi='';
    $cali='';
    $taback='';
    $bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
    if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
    if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
    foreach ($_GET as $name=>$val) {
    if ($name != 'yourta') { // && $val == '') {
    //echo $name;
    $orig=$name;
    $myf=$name;
    for ($imh=12; $imh>=1; $imh--) {
    for ($idd=31; $idd>=1; $idd--) {
    //file_put_contents('xz.xz',$orig . ' Is ' . substr('00' . $imh,-2,2) . substr('00' . $idd,-2,2) . ' less than ' . $val);
    if (substr('00' . $imh,-2,2) . substr('00' . $idd,-2,2) < $val) {
    for ($ihh=0; $ihh<=23; $ihh++) {
    for ($imm=0; $imm<=45; $imm+=15) {
    //if ($ihh != 0 || $imm != 0) {
    $myf=str_replace("0101_", substr('00' . $imh,-2,2) . substr('00' . $idd,-2,2) . "_",$orig);
    $myf=str_replace("_0000", "_" . substr('00' . $ihh,-2,2) . substr('00' . $imm,-2,2),$myf);
    //}
    $taback=str_replace('-','_',str_replace('itd','tatd',$myf));
    $backi=str_replace('-','_',str_replace('screen-','itd_',$myf));
    $cali=str_replace('-','',str_replace('screen-','td',$myf));
    $idcali=explode('-',explode('_',str_replace('screen-','td',str_replace('itd_','td',$myf)))[0])[0];

    // Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

    // Path to jpeg file
    $path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . str_replace('_','-',str_replace('itd_','screen-',$myf)) . '.jpg';
    //file_put_contents('x.x',$path);
    if (file_exists($path)) {
    $capt = ""; // Thanks to https://www.php.net/manual/en/function.iptcparse.php
    $size = getimagesize( $path, $info );
    if (isset($info["APP13"])) {
    //file_put_contents('xx.xx',$path);
    if ($iptc = iptcparse( $info["APP13"] ) ) {
    //file_put_contents('xxx.xxx',$path);
    $capt = str_replace( "\000", "", $iptc["2#120"][0] );
    //file_put_contents('xxxx.xxxx',$capt);
    }
    }
    $bcontis="" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "";
    $ccpre="<p onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-repeat:no-repeat;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); onmouseover=wopen(event,true); onmouseout=wopen(event,false); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
    $ccpost="</p>";
    $ccontis="<br><p style='background-color:orange; title='" . str_replace('td','p',$cali) . "' id=" . str_replace('td','p',$cali) . ">" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "<br>", str_replace("\r\n", "<br>", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "</p>";
    //file_put_contents('xxxxx.xxxxx',$bcontis);
    //file_put_contents('xxxxxx.xxxxxx',$taback . ' ... ' . $backi);
    //file_put_contents('xxxxxxx.xxxxxxx',"parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; ");

    }

    if ($bcontis != "''" && $bcontis != "") {
    if ($htmlis == '') {
    $htmlis="<html><head><script type=text/javascript> var imois=null, iwo=null; function wopen(event,overvsout) { if (!overvsout) { if (imois == event.target) { imois=null; } return; } imois=event.target; setTimeout(postwopen, 2000); } function postwopen() { var pois=imois; if (pois.outerHTML.indexOf('URL(') != -1) { window.open(pois.outerHTML.split('URL(')[1].split(')')[0].replace(String.fromCharCode(34),'').replace(String.fromCharCode(34),''),'_blank','top=50,left=50,width=600,height=600'); } }</script></head><body onload=\" var huhg=''; if (parent.document.getElementById('" . $idcali . "')) { huhg='" . $ccpre . $bcontis . $ccpost . "'; while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; } \"></body></html>";
    } else if (strpos($htmlis, $bcontis) === false) {
    $htmlis=str_replace("+=huhg; }", "+=huhg; huhg='" . $ccpre . $bcontis . $ccpost . "'; while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; }", $htmlis);
    }
    }

    }
    }

    if ($htmlis != "") { echo $htmlis; }

    }
    }
    }
    }
    }
    }

    // blah else if blah else if blah

    ?>

    … which you may notice implements a “long hover” window.open scenario (using non-mobile platforms) for screenshot images on the calendar by combining the use of …

    • global variables …

      var imois=null;
      var iwo=null;
    • onmouseover event logic …
      Call
      onmouseover=wopen(event,true);
    • setTimeout delays …
      Called

      function wopen(event,overvsout) {
      if (!overvsout) {
      if (imois == event.target) {
      imois=null;
      }
      return;
      }
      imois=event.target;
      setTimeout(postwopen, 2000);
      }


      function postwopen() { //pois) {
      if (imois) {
      var pois=imois;
      if (pois.outerHTML.indexOf('URL(') != -1) {
      if (iwo) { iwo.close(); iwo=null; }
      iwo = window.open(pois.outerHTML.split('URL(')[1].split(')')[0].replace(String.fromCharCode(34), '').replace(String.fromCharCode(34), ''), '_blank', 'top=50,left=50,width=600,height=600');
      }
      }
      }
    • onmouseout event logic …
      Call
      onmouseout=wopen(event,false);

    … so that this logic is not responsible for clobbering the default “hover” shows of the “p” element “title” attribute with the onmouseover event for non-mobile platforms.


    Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial is shown below.

    Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial

    Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial

    Okay then, yesterday’s Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial “image metadata smarts” puts us in a position to get onto the “bells and whistles” side of our Timekeeping (macOS and Mac OS X only at this stage) web application. We channel the calendar display talents of Monthly Chronicler LocalStorage Tutorial in thought and act (its web application is opened in an iframe … hence our need to ask you to download monthly_chronicler.html to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) to offer a new (“reveal”) piece of details/summary hosted “Yearly Report Calendar” functionality.

    <?php

    // quarter_hour_timer.php
    // RJM Programming
    // December, 2021

    // iptc_make_tag() function by Thies C. Arntzen
    function iptc_make_tag($rec, $data, $value) {
    $length = strlen($value);
    $retval = chr(0x1C) . chr($rec) . chr($data);

    if($length < 0x8000)
    {
    $retval .= chr($length >> 8) . chr($length & 0xFF);
    }
    else
    {
    $retval .= chr(0x80) .
    chr(0x04) .
    chr(($length >> 24) & 0xFF) .
    chr(($length >> 16) & 0xFF) .
    chr(($length >> 8) & 0xFF) .
    chr($length & 0xFF);
    }

    return $retval . $value;
    }

    if (isset($_GET['myta'])) {
    $dru="HTTP://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
    $contis=str_replace('+',' ',urldecode($_GET['myta']));
    //file_put_contents('xx.xx', $contis);
    $myf='';
    $backi='';
    $cali='';
    $taback='';
    $bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
    if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
    if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
    foreach ($_GET as $name=>$val) {
    if ($name != 'myta' && $val == '') {
    //echo $name;
    $myf=$name;
    $taback=str_replace('-','_',str_replace('itd','tatd',$myf));
    $backi=str_replace('-','_',str_replace('screen-','itd_',$myf));
    $cali=str_replace('-','',str_replace('screen-','td',$myf));
    $idcali=explode('-',explode('_',str_replace('screen-','td',str_replace('itd_','td',$myf)))[0])[0];


    // Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

    // Path to jpeg file
    $path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . str_replace('_','-',str_replace('itd_','screen-',$myf)) . '.jpg';
    //file_put_contents('x.x',$path);

    $capt = ""; // Thanks to https://www.php.net/manual/en/function.iptcparse.php
    $size = getimagesize( $path, $info );
    if (isset($info["APP13"])) {
    //file_put_contents('xx.xx',$path);
    if ($iptc = iptcparse( $info["APP13"] ) ) {
    //file_put_contents('xxx.xxx',$path);
    $capt = str_replace( "\000", "", $iptc["2#120"][0] );
    //file_put_contents('xxxx.xxxx',$capt);
    }
    }
    $bcontis="" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "";
    $ccpre="<p onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
    $ccpost="</p>";
    $ccontis="<br><p style='background-color:orange; title='" . str_replace('td','p',$cali) . "' id=" . str_replace('td','p',$cali) . ">" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "<br>", str_replace("\r\n", "<br>", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "</p>";

    //file_put_contents('xxxxx.xxxxx',$bcontis);
    //file_put_contents('xxxxxx.xxxxxx',$taback . ' ... ' . $backi);
    //file_put_contents('xxxxxxx.xxxxxxx',"parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; ");

    }
    if ($bcontis != "''") { echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; if (parent.document.getElementById('" . $idcali . "')) { var huhg='" . $ccpre . "' + parent.document.getElementById('" . $taback . "').value + '" . $ccpost . "'; while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; } \"></body></html>"; }
    }
    } else if (isset($_POST['myta'])) {
    $dru="HTTP://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
    $contis=str_replace('+',' ',urldecode($_POST['myta']));
    //file_put_contents('xx.xx', $contis);
    $myf='';
    $backi='';
    $cali='';
    $bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";


    $ccpre="<p onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
    $ccpost="</p>";
    $ccontis="<br><p style='background-color:orange; title='" . str_replace('td','p',$cali) . "' id=" . str_replace('td','p',$cali) . ">" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "<br>", str_replace("\r\n", "<br>", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "</p>";


    if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
    if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
    foreach ($_POST as $name=>$val) {
    if ($name != 'myta') {
    $myf=$name;
    $backi=str_replace('-','_',str_replace('screen-','itd_',$myf));
    $taback=str_replace('tatd','tatd_',substr(str_replace('-','',str_replace('_','',str_replace('itd','tatd',str_replace('screen','tatd',$myf)))),0,12)) . '_' . substr(str_replace('-','',str_replace('_','',str_replace('itd','tatd',str_replace('screen','tatd',$myf)))),-4,4);
    $pback=str_replace('tatd','ip',$taback);
    $cali=str_replace('-','',str_replace('screen-','td',$myf));
    $idcali=explode('-',explode('_',str_replace('screen-','td',str_replace('itd_','td',$myf)))[0])[0];


    // Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

    // Path to jpeg file
    $path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $myf . '.jpg';

    //file_put_contents('x.x', $path);

    // Set the IPTC tags
    $iptc = array(
    '2#120' => $contis,
    '2#116' => 'Copyright 2021, RJM Programming'
    );

    // Convert the IPTC tags into binary code
    $data = '';

    foreach($iptc as $tag => $string) {
    $tag = substr($tag, 2);
    $data .= iptc_make_tag(2, $tag, $string);
    }

    // Embed the IPTC data
    $content = iptcembed($data, $path);

    // Write the new image data out to the file.
    $fp = fopen($path, "wb");
    fwrite($fp, $content);
    fclose($fp);

    }
    echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title=" . $bcontis . "; if (parent.document.getElementById('" . $idcali . "')) { var huhg='" . $ccpre . "' + parent.document.getElementById('" . $taback . "').value + '" . $ccpost . "'; if (parent.document.getElementById('" . $pback . "')) { huhg=parent.document.getElementById('" . $taback . "').value; } while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } if (parent.document.getElementById('" . $pback . "')) { parent.document.getElementById('" . $pback . "').innerHTML=huhg; } else { parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; } } \"></body></html>";
    }
    } else {
    exec("/usr/sbin/screencapture -Cd -tjpg /Applications/MAMP/htdocs/screen-`date +\"%Y%m%d-%H%M\"`.jpg");
    }
    exit;

    ?>

    And so, again, our changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a calendar integrationally changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment.


    Previous relevant Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial is shown below.

    Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial

    Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial

    In our opinion, what would make the day before yesterday’s Mac OS MAMP Timekeeping Web Application PHP Intranet Tutorial “Timekeeping Web Application” cooler would be to add to the intelligence of the screen capture images, ahead of other data related improvements to come.

    We’ve spoken in the past about Exif in that respect but PHP has Iptc image metadata functions we can call on …

    • iptcembed to embed new metadata into an existant image from those associated “caption” textarea elements we offer
    • iptcparse to extract old metadata from an existant image into those associated “caption” textarea elements we offer

    This metadata can be like a database source we use moving forward on this project, meaning the one image data entity can suffice for both visual and textual usage purposes.

    And so our changed quarter_hour_timer.html Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a much more usefully changed quarter_hour_timer.php PHP …

    <?php

    // quarter_hour_timer.php
    // RJM Programming
    // December, 2021

    // iptc_make_tag() function by Thies C. Arntzen
    function iptc_make_tag($rec, $data, $value) {
    $length = strlen($value);
    $retval = chr(0x1C) . chr($rec) . chr($data);

    if($length < 0x8000)
    {
    $retval .= chr($length >> 8) . chr($length & 0xFF);
    }
    else
    {
    $retval .= chr(0x80) .
    chr(0x04) .
    chr(($length >> 24) & 0xFF) .
    chr(($length >> 16) & 0xFF) .
    chr(($length >> 8) & 0xFF) .
    chr($length & 0xFF);
    }

    return $retval . $value;
    }

    if (isset($_GET['myta'])) {
    $contis=str_replace('+',' ',urldecode($_GET['myta']));
    //file_put_contents('xx.xx', $contis);
    $myf='';
    $backi='';
    $taback='';
    $bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
    if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
    if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
    foreach ($_GET as $name=>$val) {
    if ($name != 'myta' && $val == '') {
    //echo $name;
    $myf=$name;
    $taback=str_replace('-','_',str_replace('itd','tatd',$myf));
    $backi=str_replace('-','_',str_replace('screen-','itd_',$myf));

    // Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

    // Path to jpeg file
    $path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . str_replace('_','-',str_replace('itd_','screen-',$myf)) . '.jpg';
    //file_put_contents('x.x',$path);

    $capt = ""; // Thanks to https://www.php.net/manual/en/function.iptcparse.php
    $size = getimagesize( $path, $info );
    if (isset($info["APP13"])) {
    //file_put_contents('xx.xx',$path);
    if ($iptc = iptcparse( $info["APP13"] ) ) {
    //file_put_contents('xxx.xxx',$path);
    $capt = str_replace( "\000", "", $iptc["2#120"][0] );
    //file_put_contents('xxxx.xxxx',$capt);
    }
    }
    $bcontis="" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "";
    //file_put_contents('xxxxx.xxxxx',$bcontis);
    //file_put_contents('xxxxxx.xxxxxx',$taback . ' ... ' . $backi);
    //file_put_contents('xxxxxxx.xxxxxxx',"parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; ");

    }
    if ($bcontis != "''") { echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; \"><p>parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "';</p></body></html>"; }
    }
    } else if (isset($_POST['myta'])) {
    $contis=str_replace('+',' ',urldecode($_POST['myta']));
    //file_put_contents('xx.xx', $contis);
    $myf='';
    $backi='';
    $bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
    if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
    if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
    foreach ($_POST as $name=>$val) {
    if ($name != 'myta') {
    $myf=$name;
    $backi=str_replace('-','_',str_replace('screen-','itd_',$myf));

    // Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

    // Path to jpeg file
    $path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $myf . '.jpg';

    //file_put_contents('x.x', $path);

    // Set the IPTC tags
    $iptc = array(
    '2#120' => $contis,
    '2#116' => 'Copyright 2021, RJM Programming'
    );

    // Convert the IPTC tags into binary code
    $data = '';

    foreach($iptc as $tag => $string) {
    $tag = substr($tag, 2);
    $data .= iptc_make_tag(2, $tag, $string);
    }

    // Embed the IPTC data
    $content = iptcembed($data, $path);

    // Write the new image data out to the file.
    $fp = fopen($path, "wb");
    fwrite($fp, $content);
    fclose($fp);

    }
    echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title=" . $bcontis . "; \"></body></html>";
    }
    } else {
    exec("/usr/sbin/screencapture -Cd -tjpg /Applications/MAMP/htdocs/screen-`date +\"%Y%m%d-%H%M\"`.jpg");
    }
    exit;

    ?>


    Previous relevant Mac OS X MAMP Timekeeping Web Application Email Tutorial is shown below.

    Mac OS X MAMP Timekeeping Web Application Email Tutorial

    Mac OS X MAMP Timekeeping Web Application Email Tutorial

    The practicalities of yesterday’s (Mac OS X MAMP Timekeeping Web Application Primer Tutorial) timekeeping Mac OS X Web Application, left as they are, would leave you with a somewhat useful web application whose use is only for the here and now, but what if you want it to be more accountable? Well, that is when we, here, at RJM Programming, like to use that tried and trusted email form of communication.

    Today’s email methods spurn the use of server-side intervention, at least for now. So what is available to us as tools, if we don’t include Ajax nor jQuery in that list? Well, we have, to our minds …

    • mailto links (get us to the email client) +
    • the body section of that email can have a clipboard image pasted into it, for which we can utilize HTML5 canvas element’s toDataURL() method, teamed up with a window.open popup window of the toDataURL image data, which can be selected and copied, optionally, by the user themselves, should they wish this to make their email more self explanatory

    We last discussed this thinking with Canvas Annotation Email Attachment Clipboard Tutorial.

    We rely on the crontab functionality, being as there is no server-side help, to create the image file, whose contents eventually go to make up the contents that can be selected and copied and pasted by the user into the body section of the email (and sent off to whosoever they feel like sending it too, as you have the full power of the email client available to you with the interaction you have with an actual email client program).

    Here is the HTML and Javascript quarter_hour_timer.html which changed to cater for today’s email functionality in this way, and, as per the Stop Press from yesterday, we’ll also have a live run link here today.


    Previous relevant Mac OS X MAMP Timekeeping Web Application Primer Tutorial is shown below.

    Mac OS X MAMP Timekeeping Web Application Primer Tutorial

    Mac OS X MAMP Timekeeping Web Application Primer Tutorial

    Sometimes when you program, especially for administrative type functionality, there are useful programs to write, that are able to become web applications, but in a limited set of platforms. So it is today with our timekeeping web application that relies on …

    • Mac OS X operating system +
    • Existance of [/usr/sbin/]screencapture +
    • crontab active and editable via crontab -e +
    • One of …
      1. MAMP installed to, in our case, /Applications/MAMP/htdocs/ (as is mentioned in the relevant crontab background task that snapshots the user’s screen every quarter hour) that maps to the MAMP web application URL http://localhost:8888/ … or …
      2. crontab directory mention that corresponds to a URL call of our web application like for our Google Chrome example (where the directory below, used, could be a place of your choosing (that matches what is in your crontab task entry)) …

        file:///Applications/MAMP/htdocs/quarter_hour_timer.html?localplace=

        … or just, via the web browser’s File -> Open File menu …

        file:///Applications/MAMP/htdocs/quarter_hour_timer.html

    … pretty restrictive, huh? … but pretty useful for our quarter hour timekeeping purposes today.

    We want to have a web application that is running at the user’s discretion, and when first fired up, looks for outputs from crontab tasks above …


    0,15,30,45 * * * * /usr/sbin/screencapture -Cd -tjpg /Applications/MAMP/htdocs/screen-`date +"\%Y\%m\%d-\%H\%M"`.jpg

    … for the current day in question and if existant show …

    1. a date and time stamp +
    2. the snapshot of what you were doing at the quarter hour, that is clickable to make bigger for more in depth viewing +
    3. an HTML textarea element in which you can optionally type in more specifics about that quarter hour

    So, as much as we like to think of Mac OS X Terminal application’s BSD (a unix derivative) operating system, as being a lot like Linux, there are some commands and usage that …

    • adds Mac OS X specific command line functionality to a Linux or unix base set of functionality, like for today’s screencapture command … and we’ve included another such example, below, with the command say featuring in Mac OS X Text to English Speech Primer Tutorial as shown below
    • changes switches on Linux or unix commands
    • won’t have some Linux or unix commands that other platforms do

    In the great tradition of behoving … we behove … we behove thee quarter_hour_timer.html if you like, my liege. On this occasion you’ll have gleaned that there is no live run link, because the RJM Programming web server is not Mac OS X … so command line screencapture has no meaning for a CentOS web server’s operating system command line. You’ll see in the code that rather than use “Client Pre-emptive Iframe” concepts to check for existence of crontab screen capture images, we, instead use the onerror event for HTML img elements to check for non-existance.

    Stop Press

    Just noticed that, perhaps, after all, a live run from the RJM Programming website can make sense if you have a Mac OS X laptop, for instance, that is running that suggested crontab entry as explained in tutorial above. That type of live run managed to latch on to our local crontab screencaptures on my MacBook Pro.


    Previous relevant Mac OS X Text to English Speech Primer Tutorial is shown below.

    Mac OS X Text to English Speech Primer Tutorial

    Mac OS X Text to English Speech Primer Tutorial

    We’ve got a few new ideas today …

    1. Text to English Speech via Mac OS X’s command line say command used by PHP via exec to make say.php (which is useful as a download to a Mac OS X laptop using MAMP) which, today, does not have a live run because the web server of domain rjmprogramming.com.au is a CentOS Linux server … Linux equivalent of Mac OS X’s say? … read here
    2. Trying to present this brought up the usual movie production problem with iMovie overlaying the audio on top of the video (though you may want to try, and you could start reading with this link) versus QuickTime Player talent to catch both audio and video tracks (and that we ended up using), but not of the “screen goings on”, alas versus MPlayer OSX Extended which can play separately but not two tracks on top and doesn’t do any reconstituting … so …
    3. Improved on our inhouse Video/Audio synchronizing efforts by allowing audio_video.html supervisor (changed in this way) be able to be called to press one of its preconceived synchronization buttons onload which we do with (the newly added) Macbeth Act 1 Scene 1 … in a small celebration of the Bard … who, am thinking (in that Falstaff way), would have got a huge chuckle out of “anonymous” instead of “anon” during the Three Witches scene … we had to do something to say Happy Birthday

    Along the way we tried filming the MacBook Pro with the iPad to a YouTube

    … but weren’t happy with the audio quality, alas (too/two).

    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in 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, GUI, Tutorials | Tagged , , , , , , , , , , , , , | Leave a comment

    Floor Wall and Roof Framing Members Song Lyrics Tutorial

    Floor Wall and Roof Framing Members Song Lyrics Tutorial

    Floor Wall and Roof Framing Members Song Lyrics Tutorial

    What do Carpentry and Octopus Anatomy have in common? Anyone, anyone?

    Yes, Ringo?

    Yes, perhaps they both live in a Yellow Submarine? Or the Octopus’s Garden needs a new lattice? But, no, we invite other takers … Anyone, anyone?

    Yes, Paul … you have a vision coming on … ?

    2026 … yes …
    World Cup … yes …
    Winner will be … yes …



    A…










     

     

    Okay, that’s it! No more! Not even “finding an arrowed diagram for Octopus Anatomy that functioned like the one we used for our Carpentry web application” … though that’s remarkably prescient. No, it’s that … yes, Katherine and Richard … you’re right there … Songs, Lyrics, Music!

    And so, further to yesterday’s Octopus Anatomy YouTube Tutorial, we’re adding access to the great Lyrics.com because, let’s face it, songs have been written for a lot of life’s ideas and thoughts in both …

    • floor_wall_roof_framing_members‘s changed code Carpentry Gamealso below

      function check(oa) {
      var dorandd=false, dolyricsmatch=false;
      //alert(document.getElementById('ui').width + ' ... ' + document.getElementById('ui').style.top + ' ... ' + document.getElementById('ui').style.left);
      var rectarr=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];
      var words=oa.getAttribute("data-title").replace(",","").replace("(","").replace(")","").toLowerCase().split('_');
      var minx=-1, miny=-1, maxx=-1, maxy=-1, jj=0;
      var carray=oa.coords.split(',');
      if (carray.length > 4) {
      carray.push(carray[0]);
      carray.push(carray[1]);
      }
      var considered=' ... (' + carray.length + ') ';
      for (var ii=0; ii<carray.length; ii++) {
      jj = eval(eval(ii - eval(ii % 2)) / 2);
      considered+=' =' + jj + '= ';
      if (carray.length == 4) {
      if (ii == 0) {
      minx=eval(carray[ii]);
      maxx=eval(carray[ii]);
      } else if (ii == 1) {
      miny=eval(carray[ii]);
      maxy=eval(carray[ii]);
      } else if (ii == 2) {
      if (eval(carray[ii]) < minx) minx=eval(carray[ii]);
      if (eval(carray[ii]) > maxx) maxx=eval(carray[ii]);
      } else {
      if (eval(carray[ii]) < miny) miny=eval(carray[ii]);
      if (eval(carray[ii]) > maxy) maxy=eval(carray[ii]);
      }
      } else if (eval(ii % 2) == 0 && (jj == 0 || jj == 1 || jj == eval(-1 + eval(carray.length / 2)) || jj == eval(-2 + eval(carray.length / 2)) || jj == eval(-3 + eval(carray.length / 2)))) {
      if (ii == 0) {
      considered+='' + carray[ii] + ',' + carray[eval(1 + ii)];
      minx=eval(carray[ii]);
      maxx=eval(carray[ii]);
      miny=eval(carray[eval(1 + ii)]);
      maxy=eval(carray[eval(1 + ii)]);
      } else {
      considered+=',' + carray[ii] + ',' + carray[eval(1 + ii)];
      if (eval(carray[ii]) < minx) minx=eval(carray[ii]);
      if (eval(carray[ii]) > maxx) maxx=eval(carray[ii]);
      if (eval(carray[eval(1 + ii)]) < miny) miny=eval(carray[eval(1 + ii)]);
      if (eval(carray[eval(1 + ii)]) > maxy) maxy=eval(carray[eval(1 + ii)]);
      }
      }
      }
      if (minx < 75) {
      maxx=75;
      } else if (minx < 460) {
      minx=460;
      }
      if (maxx > eval(0 + document.getElementById('ui').width)) maxx = eval(0 + document.getElementById('ui').width);
      if (maxy > eval(0 + document.getElementById('ui').height)) maxy = eval(0 + document.getElementById('ui').height);
      //if (carray.length > 4) {
      // alert(carray + ' ... ' + minx + ',' + miny + ',' + ',' + maxx + ',' + maxy + considered);
      //}
      //if (oa.title.indexOf('rimmer') != -1) alert(oa.title + ' ... ' + "<div style=\"border:1px solid red;position:absolute;z-index:9;background-repeat:no-repeat;background:URL('floor_wall_roof_framing_members.jpg');background-position:-" + minx + "px -" + miny + "px;left:" + minx + "px;top:" + miny + "px;width:" + eval(maxx - minx) + "px;height:" + eval(maxy - miny) + "px;display:block;\"></div>");
      var ans=prompt("What did you point at? One blank character is the answer to give up and reveal answer, while two will offer YouTube based research material regarding the answer as well, three also does a Song Lyrics search. Suffix your answer with a space to do this research, two spaces for song lyrics, anyway, as well.", "");
      goes++;
      var prevscore=score;
      if (ans != null) {
      if (ans.indexOf(' ') == 0 && ans.trim() == '') {
      dolyricsmatch=true;
      dorandd=true;
      ans=' ';
      } else
      if (ans.indexOf(' ') == 0 && ans.trim() == '') {
      dorandd=true;
      ans=' ';
      } else if (('!' + ans + '~').replace(/\ \ \~$/g,'') != ('!' + ans + '~') && ans.trim() != '') {
      dolyricsmatch=true;
      dorandd=true;
      ans=ans.trim();

      } else if (('!' + ans + '~').replace(/\ \~$/g,'') != ('!' + ans + '~') && ans.trim() != '') {
      dorandd=true;
      ans=ans.trim();
      }
      var bwords=ans.replace(",","").replace("(","").replace(")","").toLowerCase().split(' ');
      for (var kk=0; kk<bwords.length; kk++) {
      if (bwords[kk] != "") {
      for (var mm=0; mm<words.length; mm++) {
      if (words[mm] == bwords[kk]) score++;
      }
      }
      }
      }
      if (prevscore != score || ans == " ") {
      document.getElementById('overlays').innerHTML+="<div style=\"position:absolute;z-index:9;background-repeat:no-repeat;background:URL('floor_wall_roof_framing_members.jpg');background-position:-" + minx + "px -" + miny + "px;left:" + eval(0 + minx) + "px;top:" + eval(6 + miny) + "px;width:" + eval(maxx - minx) + "px;height:" + eval(maxy - miny) + "px;display:block;\"></div>";
      if (window.self != window.parent) {
      document.getElementById('score').innerHTML='Score: ' + score + '/' + goes + " ... <br>" + oa.getAttribute("data-title").replace(/_/g,' ');
      } else {
      document.getElementById('score').innerHTML='Score: ' + score + '/' + goes + " ... " + oa.getAttribute("data-title").replace(/_/g,' ');
      }
      } else {
      document.getElementById('score').innerHTML='Score: ' + score + '/' + goes;
      }

      if (dorandd) {
      tost=fromst.replace('Djibouti%2C%20Djibouti', encodeURIComponent('carpentry ' + oa.getAttribute("data-title").replace(/_/g,' ')));
      document.getElementById('ifkar').src=ifkar.replace(fromst, tost);
      document.getElementById('ifkar').style.display='block';
      }
      if (dolyricsmatch) {
      if (lwo) {
      if (!lwo.closed) {
      lwo.close();
      lwo=null;
      }
      }
      lwo=window.open('//www.lyrics.com/lyrics/' + encodeURIComponent(oa.getAttribute("data-title").replace(/_/g,' ').toLowerCase()), '_blank', 'top=0,left=' + eval(-490 + screen.width) + ',width=490,height=520');
      }

      }
    • octopus.html‘s changed code Octopus Anatomy Game as way below


    Previous relevant Octopus Anatomy YouTube Tutorial is shown below.

    Octopus Anatomy YouTube Tutorial

    Octopus Anatomy YouTube Tutorial

    Today’s work, onto that of Octopus Anatomy Primer Tutorial is a story revolving around …

    • research … related to …
    • audio/visual learning techniques …
    • HTML iframe interfacing … to …
    • YouTube videos … via …
    • YouTube API

    … as a methodology to “drill down” into subject matter whose scope is initially too big for a learner to know where to start, perhaps


    function check(oa) {
    var dorandd=false;
    //alert(document.getElementById('ui').width + ' ... ' + document.getElementById('ui').style.top + ' ... ' + document.getElementById('ui').style.left);
    var rectarr=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];
    var words=oa.getAttribute("data-title").replace(",","").replace("(","").replace(")","").toLowerCase().split('_');
    var minx=-1, miny=-1, maxx=-1, maxy=-1, jj=0;
    var carray=oa.coords.split(',');
    if (carray.length > 4) {
    carray.push(carray[0]);
    carray.push(carray[1]);
    }
    var considered=' ... (' + carray.length + ') ';
    for (var ii=0; ii<carray.length; ii++) {
    jj = eval(eval(ii - eval(ii % 2)) / 2);
    considered+=' =' + jj + '= ';
    if (carray.length == 4) {
    if (ii == 0) {
    minx=eval(carray[ii]);
    maxx=eval(carray[ii]);
    } else if (ii == 1) {
    miny=eval(carray[ii]);
    maxy=eval(carray[ii]);
    } else if (ii == 2) {
    if (eval(carray[ii]) < minx) minx=eval(carray[ii]);
    if (eval(carray[ii]) > maxx) maxx=eval(carray[ii]);
    } else {
    if (eval(carray[ii]) < miny) miny=eval(carray[ii]);
    if (eval(carray[ii]) > maxy) maxy=eval(carray[ii]);
    }
    } else if (eval(ii % 2) == 0 && (jj == 0 || jj == 1 || jj == eval(-1 + eval(carray.length / 2)) || jj == eval(-2 + eval(carray.length / 2)) || jj == eval(-3 + eval(carray.length / 2)))) {
    if (ii == 0) {
    considered+='' + carray[ii] + ',' + carray[eval(1 + ii)];
    minx=eval(carray[ii]);
    maxx=eval(carray[ii]);
    miny=eval(carray[eval(1 + ii)]);
    maxy=eval(carray[eval(1 + ii)]);
    } else {
    considered+=',' + carray[ii] + ',' + carray[eval(1 + ii)];
    if (eval(carray[ii]) < minx) minx=eval(carray[ii]);
    if (eval(carray[ii]) > maxx) maxx=eval(carray[ii]);
    if (eval(carray[eval(1 + ii)]) < miny) miny=eval(carray[eval(1 + ii)]);
    if (eval(carray[eval(1 + ii)]) > maxy) maxy=eval(carray[eval(1 + ii)]);
    }
    }
    //alert('ii=' + ii + ' ' + oa.outerHTML + ' ... ' + maxx + ' - ' + minx + ' = ' + eval(maxx - minx));
    }
    // if (minx < 75) {
    // maxx=75;
    // } else if (minx < 460) {
    // minx=460;
    // }
    if (maxx > eval(0 + document.getElementById('ui').width)) { maxx = eval(0 + document.getElementById('ui').width); }
    if (maxy > eval(0 + document.getElementById('ui').height)) { maxy = eval(0 + document.getElementById('ui').height); }
    //if (carray.length > 4) {
    // alert(carray + ' ... ' + minx + ',' + miny + ',' + ',' + maxx + ',' + maxy + considered);
    //}
    //if (oa.title.indexOf('rimmer') != -1) alert(oa.title + ' ... ' + "<div style=\"border:1px solid red;position:absolute;z-index:9;background-repeat:no-repeat;background:URL('floor_wall_roof_framing_members.jpg');background-position:-" + minx + "px -" + miny + "px;left:" + minx + "px;top:" + miny + "px;width:" + eval(maxx - minx) + "px;height:" + eval(maxy - miny) + "px;display:block;\"></div>");
    var ans=prompt("What did you point at? One blank character is the answer to give up and reveal answer, while two will offer YouTube based research material regarding the answer as well. Suffix your answer with a space to do this research, anyway, as well.", "");
    goes++;
    var prevscore=score;
    if (ans != null) {
    if (ans.indexOf(' ') == 0 && ans.trim() == '') {
    dorandd=true;
    ans=' ';
    } else if (('!' + ans + '~').replace(/\ \~$/g,'') != ('!' + ans + '~') && ans.trim() != '') {
    dorandd=true;
    ans=ans.trim();
    }

    var bwords=ans.replace(",","").replace("(","").replace(")","").toLowerCase().split(' ');
    for (var kk=0; kk<bwords.length; kk++) {
    if (bwords[kk] != "") {
    for (var mm=0; mm<words.length; mm++) {
    if (words[mm] == bwords[kk]) score++;
    }
    }
    }
    }
    if (prevscore != score || ans == " ") {
    document.getElementById('overlays').innerHTML+="<div style=\"position:absolute;z-index:9;background-repeat:no-repeat;background:URL('oct_opus.png');background-position:-" + minx + "px -" + miny + "px;left:" + eval(0 + minx) + "px;top:" + eval(6 + miny) + "px;width:" + eval(maxx - minx) + "px;height:" + eval(maxy - miny) + "px;display:block;\"></div>";
    document.getElementById('score').innerHTML='Score: ' + score + '/' + goes + " ... " + oa.getAttribute("data-title").replace(/_/g,' ');
    //if (ans == " ") { alert(oa.getAttribute("data-title").replace(/_/g,' ')); }
    } else {
    if (window.self != window.parent) {
    document.getElementById('score').innerHTML='Score: ' + score + '/' + goes + " ... <br>" + oa.getAttribute("data-title").replace(/_/g,' ');
    } else {
    document.getElementById('score').innerHTML='Score: ' + score + '/' + goes;
    }
    //if (prevscore == score) { alert(oa.getAttribute("data-title").replace(/_/g,' ')); }
    }

    if (dorandd) {
    tost=fromst.replace('Djibouti%2C%20Djibouti', encodeURIComponent('octopus ' + oa.getAttribute("data-title").replace(/_/g,' ')));
    document.getElementById('ifkar').src=ifkar.replace(fromst, tost);
    document.getElementById('ifkar').style.display='block';
    }

    }

    … in octopus.html‘s changed code Octopus Anatomy game …


    Previous relevant Octopus Anatomy Primer Tutorial is shown below.

    Octopus Anatomy Primer Tutorial

    Octopus Anatomy Primer Tutorial

    What do Carpentry and Octopus Anatomy have in common? Many hands make light fittings get a bevelled edge? No, for us, finding an arrowed diagram for Octopus Anatomy that functioned like the one we used for our Carpentry web application of Floor Wall and Roof Framing Members Primer Tutorial below.

    So much so, we kept the same Javascript logic and bits of the HTML other than the …

    • img element image … doh! … and …
    • underlying (image) map element … created in that similar (great, stupendous) mobilefish (thanks) method as for the Carpentry web application

    To get from today’s octopus.html‘s changed code then we …

    1. started with the Carpentry HTML and Javascript code as a basis …
    2. surfing the net found interesting octopus image via this Google image search finding this applicable image (from “Methodologies for studying finfish and shellfish biology” (ISBN: 978-93-82263-03-6) by Dineshbabu Ap), thanks, that we scanned and copied (and which we later change) into an image file on this MacBook Pro that was uploaded to …
    3. visited mobilefish to create the new image (img element) and associated map element …
    4. replaced the old Carpentry img and map with the new Octopus ones, pointing the img element src property at the correct image … that image now …
    5. opened octopus image in Gimp and Gaussian Blurred out the octopus labels via …
      • Tools -> Selection Tools -> Rectangle Select
      • Filters -> Blur -> Gaussian Blur… Horizontal: 14.0px Vertical: 14.0px
    6. (unit) tested code, and realized we’d forgotten to …
    7. within the new octopus img and map code replace all ” title=” for ” data-title=” (to hide answers from the user) and ” href=” for ” data-href=” to stop navigation resetting the score

    … to arrive at where we are at with today’s live run. We hope you try it, and learn a bit about Octopus Anatomy should that be your thing!


    Previous relevant Floor Wall and Roof Framing Members Primer Tutorial is shown below.

    Floor Wall and Roof Framing Members Primer Tutorial

    Floor Wall and Roof Framing Members Primer Tutorial

    We all learn differently, but personally, I find it easier to learn things of a certain ilk and things that are new to me, when the study material is augmented by pictures in the form of a diagram or photograph or video, perhaps. I know very little about carpentry, and get lost in conversations talking about “joists” and “bearers”, so, today, we’ve purloined the great mobilefish image map (of HTML area elements) creator website and this very useful webpage (the source of the great diagram … thanks) to piece together today’s “click and learn” web application.

    We use some overlay techniques with today’s game where the user tries to identify diagram labels Gaussian Blurred out (via GIMP) while a non-Gaussian-Blurred-out image is used (in an overlayed way) as the background (via background-position definitions) for HTML divs …

    • position:absolute; left:[derivedViaMinAreaXCoords]px; top:[derivedViaMinAreaYCoords]px; width:[derivedViaMaxMinDiffAreaXCoords]px; height:[derivedViaMaxMinDiffAreaYCoords]px;
    • z-index:9;
    • background:URL([non-Gaussian-Blurred-out_image]); background-position:-[derivedViaMinAreaXCoords]px -[derivedViaMinAreaYCoords]px;
    • data attributes (eg. data-title) hide answers from the user to avoid making it all too easy, and internalize navigation (eg. data-href)

    revealed as above when the user gives up (via a space answer) or answers some words correctly in the Javascript prompt window used to prompt the user for “carpentry” terminology word matches, the score incrementing for each correct word match.

    Now hope you don’t go around “nogging” in public with your newfound knowledge trying out today’s live run test of your carpentry and building knowledge. It is based on HTML and CSS and Javascript you could call floor_wall_roof_framing_members.html and download, as you wish.

    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.

    Posted in eLearning, Event-Driven Programming, Games, Tutorials | Tagged , , , , , , , , , , , , , , , , , | Leave a comment