Wildcard URL Primer Tutorial

Wildcard URL Primer Tutorial

Wildcard URL Primer Tutorial

Like with Page Not Found Error Message Email Subject Tutorial it’s …


404.shtml

… we’re interested in embellishing the functionality of, today. The job is to allow a …


https://www.rjmprogramming.com.au/[FoldersOfRelevance]/[FileSpecificationIncluding*Wildcard]
https://www.rjmprogramming.com.au/HTMLCSS/*.gif

… mean something other than a …


HTTP Error 404 ... Webpage Not Found

… error. For the case of most RJM Programming URLs this “normal case” error reporting will be the responsibility of it’s Apache Document Root 404.shtml file where we’ve added


var locparts=[], rquri='', rfound=false, ri=0;

if (document.URL.indexOf('*') != -1 && document.URL.toLowerCase().indexOf('rjmprogramming.com.au/') != -1) {
locparts=document.URL.split('#')[0].split('/');
while (ri < eval(-1 + eval('' + locparts.length))) {
if (locparts[ri].toLowerCase().indexOf('rjmprogramming.com.au') != -1) {
rfound=true;
ri++;
rquri=locparts[ri];
if (rquri == 'PHP') {
rquri='.';
} else {
rquri='../';
if (ri != eval(-1 + eval('' + locparts.length))) {
rquri+=locparts[ri];
}
}
} else if (ri != eval(-1 + eval('' + locparts.length))) {
if (rfound) {
rquri+='/' + locparts[ri];
}
}
ri++;
}
location.href='//www.rjmprogramming.com.au/PHP/find_images_via_size.php?fsort=&wsort=&hsort=&path=' + encodeURIComponent(rquri) + '&filespec=' + locparts[eval(-1 + eval('' + locparts.length))] + '&wo=%21%3D&wv=-500&ho=%21%3D&hv=-500';
exit;
} else
if (document.URL.indexOf('.au/drupal') != -1) {
location.href='//www.rjmprogramming.com.au/drupal/index.htm';
exit;
}

… so that we redirect to our inhouse Find Images web application and we’ll see about non-image files, as a consideration, into the future!


Previous relevant Page Not Found Error Message Email Subject Tutorial is shown below.

Page Not Found Error Message Email Subject Tutorial

Page Not Found Error Message Email Subject Tutorial

Why, with today’s tutorial, are we conflating two quite disparate subjects …

  1. HTTP (ie. Hypertext Transfer Protocol) Error Code 404 “Page Not Found” or “Server Not Found” …with …
  2. Email Subject lines

… into the one tutorial topic? Well, as we talked about with body of email scenarios, with some email clients (with Window SessionStorage Client Versus Server CSS Tutorial) …

As far as links go, you may expect to need serverside means to construct these in online Email and SMS message interfacing, but email (client program) products like Gmail parse your ascii text and convert http: or https: protocol URLs in your Email body to hyperlinks, as does the Messages SMS application here on this MacBook Pro using macOS Mojave.

… it pans out with some email clients such as iOS Mail app, that email subject lines containing similar http: or https: protocol URLs also get converted into hyperlinks. For us this has become a more likely scenario ever since the email [date] subject line token work typified by Local Datetime Token Subject Integrations Tutorial. The nature of those hyperlinks created, though, seem to be a great concern for these more helpful email clients and if you put into subject lines URLs containing “?” and “&” delimited arguments, the email clients mildly “mash up” these URLs so that recent ones from our “Plot Axes – Linear or Parabolic Formula” web application for (an example like) …


https://www.rjmprogramming.com.au/HTMLCSS/square_hr_tracing.htm?wording=Vertex%20Pointing%20Game&question=%20#blank=plot187|-200,-200,200,200|2,-123

… on email clients that do not do “the (monster) mash”, on an email client that “does hyperlink but mash up” the URL the email subject line takes you to is actually (an additional “layer of encodeURIComponent‘ed content” you can see as you hover over the link, the display normalized as far as looks go, via HTML entity mapping) …


https://www.rjmprogramming.com.au/HTMLCSS/square_hr_tracing.htm?wording=Vertex%20Pointing%20Game&question=%20#blank=plot187|-200,-200,200,200|2,-123

… which, without the tailoring of RJM Programming domain’s Error 404 trapping 404.shtml would not take you to its true destination (of look) … because of “the mash”.

It’s been a while since we set up this 404.shtml Apache web server means to serve “Not Found” (Page) URLs with a more welcoming experience than the default web browser “Error 404 … Not Found” kind of error message, so we started our research into whether it was possible to redirect from a 404.shtml on an Apache web server at this useful Google search, thanks.

Now, it must be noted here, that the search engines may penalise you for making the 404.shtml redirection we are going to show you below. Honestly, we don’t know, but we feel compelled to let you know that such a redirection is possible on an Apache web server’s 404.shtml with a document.body “onload” changed event (HTML and Javascript code snippet) piece of logic as below …


<script type='text/javascript'>
function onPageUnload() {
}

function onPageLoad() {
if (document.URL.indexOf('square_hr_tracing.htm%') != -1) {
location.href=document.URL.replace('%3F','?').replace(/\%23/g, '#').replace(/\%26/g, '&');
exit;
}
}
</script>


</head>
<body style="background: #d4d4d4; margin: 0pt; " onload="onPageLoad();" onunload="onPageUnload();">

… that is helping make sense of the “mashed up” URL (from some email client subject lines) above, as well as the rest of this 404.shtml (placed into RJM Programming domain’s Document Root) showing a more friendly webpage for all those misdirected URLs such as this one.


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

Window SessionStorage Client Versus Server CSS Tutorial

Window SessionStorage Client Versus Server CSS Tutorial

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

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

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

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

In terms of CSS styling work …

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

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

    … dovetailing with the “static” internal CSS coding

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

    }
    </style>

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

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

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

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


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

Window SessionStorage Client Versus Server Integration Tutorial

Window SessionStorage Client Versus Server Integration Tutorial

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

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

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

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

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


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

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

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

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

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


var last24='';
var rectdc;

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

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

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

… working with the new HTML …


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

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

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


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

Window SessionStorage Client Versus Server Ajax Tutorial

Window SessionStorage Client Versus Server Ajax Tutorial

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

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

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

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

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

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

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

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

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


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

Window SessionStorage Client Versus Server Canvas Tutorial

Window SessionStorage Client Versus Server Canvas Tutorial

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

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

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

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

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

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

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

… sharing off to an emailee collaborator.

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


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

Window SessionStorage Client Versus Server Share Tutorial

Window SessionStorage Client Versus Server Share Tutorial

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

  • email
  • SMS

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


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

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

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


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

Window SessionStorage Client Versus Server Tutorial

Window SessionStorage Client Versus Server Tutorial

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

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

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


localStorage.removeItem([knownLocalStorageName]);

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

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


var datamode='localStorage';

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

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

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

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


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

Window LocalStorage Client Versus Server Primer Tutorial

Window LocalStorage Client Versus Server Primer Tutorial

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

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

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

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

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

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

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

that’s because the web application’s …


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

return false;
}
}
return true;
}

… HTML form onsubmit event logic …

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

    HTTP 414 "Request URI too long"

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

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

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

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

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

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

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

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


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


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


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


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


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


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


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


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

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

Genius Scan App PDF Email Slide Management Tutorial

Genius Scan App PDF Email Slide Management Tutorial

Genius Scan App PDF Email Slide Management Tutorial

Further to Genius Scan App PDF Email Tutorial a revisit recently was of great interest, the resultant PDF being sizeable. Are there Genius Scan app functionalities for “stuff ups”? The answer is yes, and they are very useful because …

  • we cannot remember from the last time that the scanning could be so “trigger happy” … which can be good or a tad annoying … in that …
  • the “trigger happy” feel makes the scanning be quicker … with the occasional annoyance that …
  • double takes (as with the iOS Camera app anyway) are possible … but …
  • slide management functionality in the Genius Scan app … is both easy to use and contextual (helping enormously with scan double takes)

… so much so that, in the Apple world, we’d put the Genius Scan app (on iOS mobile) right up there in terms of large PDF production and publishing talents with the great out of the box macOS Preview desktop application (where we can’t go past the Finder multiple slide image selection Open With Preview, and there using it’s own slide management, ahead of Print -> PDF creation process talents).

Both are great “online hardcopy” (which is what PDF amounts to) publication ideas!


Previous relevant Genius Scan App PDF Email Tutorial is shown below.

Genius Scan App PDF Email Tutorial

Genius Scan App PDF Email Tutorial

The raw camera functionality on an iPad is amazing, but short of using stands or rigging up a tripod, its capabilities resolution wise for the scanning of filled out forms can be questionable. We’ve been wanting to do a bit of this recently, and found that the iPad’s Genius Scan (mobile) app we introduced at this blog with Genius Scan App Primer Tutorial (when using it to organize some recipes) could succeed (where raw iPad camera functionality couldn’t (at least for us)) …

  • get the qualities of photograph resolutions required to see “clearly enough” (the emailee complained about the resolution using native iPad Camera work only) filled out form data
  • could assemble into the one PDF several scans (meant to be together) in the one document … and then …
  • share that PDF document by, in our case, emailing it off, to an emailee (ie. recipient)

Cute, huh?!

Today’s PDF slideshow created back on a MacBook Pro’s Preview desktop application illustrates these basic steps (for a two page PDF email attachment) …

  1. If not installed already install the iOS Genius Scan app onto an iPad (in our case, but should work on an iPhone too) via a search of the App Store app for “Genius” … then touch that icon on the iPad desktop to open “Genius Scan” (mobile) app
  2. Touch Camera icon
  3. When form (or other “subject” 1) lined up click the “Shutter” icon
  4. Save to a New Document
  5. Touch Camera icon
  6. When form (or other “subject” 2) lined up click the “Shutter” icon
  7. Save to a Existing Document
  8. Touch that newest Existing Document to open it … so that we can …
  9. Touch the Share icon down at the bottom right
  10. In the Export window that opens up touch the Email icon … which opens a …
  11. Email window with the usual To: CC:/BCC: Subject: Body: filled with the Genius Scan PDF as an email attachment … so we …
  12. Fill out the relevant fields as above and touch the Send “button” up the top left … at which point we can …
  13. Use the iPad’s Home button to bid farewell to the Genius Scan (mobile) app … and in our case open our iPad’s Mail app to view the email ourselves (because we sent it to ourselves)

Pretty efficient really?!


Previous relevant Genius Scan App Primer Tutorial is shown below.

Genius Scan App Primer Tutorial

Genius Scan App Primer Tutorial

When you come across a great mobile application it can be a great boon to your relationship with computer equipment. And if it links hardcoded material to the online world all the better. Do you remember when we talked about QR Codes with QR Codes Writer Primer Tutorial? Well, today, with our tutorial about the great iOS mobile application called Genius Scan (and you can just type “Genius” at the App Store application to find it) it feels a bit like the QR Code creation way a mobile device takes a photo of something that is then used to do something else. That “something else” today is that that photo, perhaps of some hardcoded material, can be turned into a PDF by the Genius Scan app and shared, in our case today, by email.

Around our house we used the Genius Scan app to photograph a loose collection of recipes, in poor condition, and centralise (via reprinting) them via …

  1. If not installed already install the iOS Genius Scan app onto an iPad (in our case, but should work on an iPhone too) via a search of the App Store app for “Genius” … Genius Scan App Primer TutorialGenius Scan App Primer TutorialGenius Scan App Primer Tutorial
  2. Take photos of the loose collection of recipes and store them as PDFs on the iPad
  3. Another user, meanwhile, has a USB memory stick ready using a MacBook Pro (and in our case we used the Finder application to two finger gesture in the root folder arrived at by clicking the USB Disk and two finger gesturing a New Folder called Recipes)
  4. In batches, email (up to about 11, in our case, of) these off to an email address accessed by a user using a MacBook Pro, and we used a web browser session of Gmail for this
  5. Click Download all Attachments to a zip file in the Downloads folder (of MacBook Pro)
  6. Click the zip file creating a new folder within the Downloads folder
  7. Click that new folder to open its contents
  8. Click (ie. tap) top file
  9. Two finger gesture to Copy all these as you click/tap last file
  10. Click USB folder (and in our case we also click Recipes sub folder)
  11. Two finger gesture Paste files to USB
  12. Repeat from “In batches …” above until all done
  13. Take the USB to Officeworks serve yourself document printing machine, in a similar way, but with photos that last time, that we visited good ol’ Officeworks when we presented Holiday Snaps Printing Primer Tutorial as shown below (and the other thing we’ve learnt since then is that they can recycle some of your old printers if you drop it off at their store)
  14. We found it was too much trouble to do one printout per click for $1.00 Australian per sheet and instead got help from an Officeworks employee to put all the 121 files into a batch job at $0.80 cents per printout … voila … Genius Scan App Primer Tutorial

A good result all round!


Previous relevant Holiday Snaps Printing Primer Tutorial is shown below

Holiday Snaps Printing Primer Tutorial

Holiday Snaps Printing Primer Tutorial

We had occasion to think about USB Memory Sticks the other day, perhaps a hardware device on the list of ones in danger of slipping away from relevance if we keep moving on in the mobile device and cloud storage direction.

The history of removable media started a long time ago even before the first Windows, back at DOS, and can remember some Wang 8 inch floppies. Back then it was a lot to do with a very finite amount of disk space reflecting when I.T. was more about “real word” processing, rather than, so much, graphical processing. Nowadays, with removable media, and the relatively modern … but for how long? … memory stick holding several gigabytes of media storage, usually, there are media formatting requirements now that have moved on from the default Windows media formatting supporting a File Allocation Table (FAT) file system.

We’ll get to what’s better to use regarding a USB memory stick media formatting arrangement later, but for now, what happens if you …

  • in Windows or DOS get to a formatting Window and choose to format a USB memory stick of 2gB capacity, for example in “MS-DOS (FAT)” format … or …
  • in Mac OS X Applications -> Utilities -> Disk Utility -> Selected USB memory stick of 2gB capacity -> Erase tab -> Format -> MS-DOS (FAT)

… well, respectively …

  • it will have been formatted to have the disk space of a 3 1/4 inch floppy, it looks like, and work on Windows and DOS and Mac OS X
  • it will have been formatted to have the disk space of a 3 1/4 inch floppy, it looks like, and work on Mac OS X and Windows and DOS

… which is okay but kind of wasteful, in the context of a removable USB 2gB memory stick we wanted to use to store about 320 holiday “snaps” and get printed out. We have these scenarios possible in a house half Mac OS X and half Windows.

So here’s the bit of the tutorial where we can’t help but advertise. Officeworks, with various branches here in Sydney, print 4″ x 6″ photo prints, satin or glossy, at 10 cents per photo. Pretty good, huh? And this can even be done Dragging and Dropping photos online, but up to 20mB, that is. Our 320 holiday “snaps” represented considerably more, and more than for any “MS-DOS (FAT)” file system arrangement, that would get taken for a Same Day do it yourself at a Windows personal computer, with your own USB memory stick arrangement.

So, what is the go to …

  • use the full capacity of the USB memory stick
  • be able to fit 320 photos onto the USB memory stick
  • for normal day to day use, be able to use it on any Mac OS X or Windows computer around the house
  • have a workable and readable USB memory stick to use at the Officeworks photo printing Do It Yourself Windows personal computers

… having seen unreadable USB memory sticks, at Officeworks Windows personal computers using “in Mac OS X Applications -> Utilities -> Disk Utility -> Selected USB memory stick of 2gB capacity -> Erase tab -> Format -> Mac OS Extended (Journaled)” formatting?

Well, I asked the Fat Controllerof course … what do you take me for? … and they said …

“ExFat” DotDotDot man person

… and, lo and behold … not having registered its existence before … there it was as an option achieving both as per …

  • in Windows or DOS get to a formatting Window and choose to format a USB memory stick of 2gB capacity, for example in “exFAT” format … or …
  • in Mac OS X Applications -> Utilities -> Disk Utility -> Selected USB memory stick of 2gB capacity -> Erase tab -> Format -> ExFAT

… resulting in, respectively …

  • it will have been formatted to have the disk space of its 2gB full capacity, it looks like, and work on Windows and DOS and Mac OS X
  • it will have been formatted to have the disk space of its 2gB full capacity, it looks like, and work on Mac OS X and Windows and DOS

So, a happy solution for some holiday “snap” printing, and the ongoing less wasteful use of a USB 2gB memory stick on Windows or Mac OS X, on computers around the house. We show some of these ideas with our tutorial picture today.

To read more about getting the photos to the MacBook Pro laptop from the Android phone, please read, below, the techniques from Android Disk to MacBook Pro Disk Tutorial.


Previous relevant Android Disk to MacBook Pro Disk Tutorial is shown below.

Android Disk to MacBook Pro Disk Tutorial

Android Disk to MacBook Pro Disk Tutorial

We love it here when we can tell you of something that works across the “big brands”, and what we mean by the two “big brands” today is Google (regarding their Android mobile phone operating system) and Apple (regarding their Mac OS X MacBook Pro laptop operating system). Today we transfer files from the Android mobile phone to our MacBook Pro laptop disk via …

  1. (ubiquitous) white lead … called a Micro USB Connector … the same one we used for Android Studio Real Physical Device Tutorial as shown below
  2. some great Mac OS X software we discovered at Android File Transfer

For Share ideas that involve your Android mobile phone and storing media on a local hard disk this could be a great alternative to other Share options for the MacBook Pro and some of the ideas we presented with Android Camera to Mac iPhoto Primer Tutorial.

Today’s tutorial picture shows you the setup for this functionality, and you’ll see the online advice for how you work the Mac OS X application for the Android File Transfer application.


Previous relevant Android Studio Real Physical Device Tutorial is shown below.

Android Studio Real Physical Device Tutorial

Android Studio Real Physical Device Tutorial

When creating Android apps with Android Studio IDE (or any other IDE, for that matter) it’s great to test the working of the app with various mobile phone and tablet emulators with AVD, and it’s even “greater” to extend that to testing on a real physical device.

Today, we’re going to work with …

  • MacBook Pro testing that latest Android app using an Android Studio IDE project which we talked about with Android Studio on Mac OS X Primer Tutorial regarding “ESL Ideas”
  • another (ubiquitous) white lead … called a Micro USB Connector … but not Muc, pleeeeease … decided against the puce one because it just didn’t go with the cushions … but we digress
  • Samsung GT-S5310B Android 4.1.2 mobile phone … and, today of all days the “4.1.2” is a bit significant … because we want to talk about ant buildsbut we digress

The (ubiquitous) white lead goes from the MacBook Pro’s USB port to the “underbelly” of the Samsung GT-S5310B.

One thing to do at the “computer” Android Studio end of the lead is to adjust AndroidManifest.xml to show android:debuggable="true" now.

Now if you’re on Windows I’d have more to say about the “computer” end of the lead, and if that is you, and you’ve never tested on a real device, you’ll want to read this great Google Android Studio page.

Come to think of it, everybody who’s never tested on a real device should read Google Android Studio page. See the advice about Android 4.2 … note that … ie. if the Settings menu’s submenu Developer Options is all grayed out tap on Build number (via Settings->About device) seven times … and “twice on the pipe, if the answer is noooooooooo”but we digress.

However, we have a mobile phone with Android 4.1.2 … and so … this search got me to this great advice … and the consequent turning on of the Settings->Developer Options “switch” to on meant … Bob’s your uncle, Fanny’s your aunt … Android Studio responded like a … like a … well … a very hot studio.

A “Run App” will default to hooking up to this connected physical device (the Samsung GT-S5310B) and run the resultant mobile app on that device.


Previous relevant Android Studio on Mac OS X Primer Tutorial is shown below.

Android Studio on Mac OS X Primer Tutorial

Android Studio on Mac OS X Primer Tutorial

There are a lot of choices of IDE for creating mobile applications, and if you are a developer wanting to develop mobile apps for both Android and iOS platforms, you may be looking to try to set up an environment where all this can be achieved on the one piece of computer equipment.

We prefer to think in terms of two IDEs handling the two mobile app types of iOS, with Swift and/or Objective-C as the source language, and Android, with Java as the source language. We don’t mind there being two separate IDEs involved, but we find it amazing enough that they can both sit on the one MacBook Pro laptop without resorting to any Operating System disk partitions. With the Android app, using Mac OS X (MacBook Pro) we asked Google if it could be done, and came up with the marvellous Android Studio IDE as a possibility … yay!

  • iOS mobile apps get created via the Xcode IDE using Swift and/or Objective-C on a Mac OS X (MacBook Pro)
  • Android apps get created via the Android Studio IDE using Java on a Mac OS X (MacBook Pro)

Today’s tutorial, as with the WordPress 4.1.1’s Android Studio on Mac OS X Primer Tutorial, hones in on that second idea from the install of Android Studio (to a MacBook Pro) through to the “middle game” emulation of an Android app via Android Studio and AVD onto an HTC Nexus One.

Please don’t think this is the only approach … and please research PhoneGap (PhoneGap iOS Mobile Xcode Primer Tutorial) and jQuery Mobile (jQuery Mobile Primer Tutorial) and Embarcadero (Delphi Pascal++ Embarcadero XE6 Primer Tutorial) also, perhaps for an approach that uses other ways of looking at the issue.

In the context of all this, we see the Android app “end game” as involving the creation of an .apk file that can be uploaded to Google Play for public access.

Similarly to our associated Android Studio Google Play Ready Primer Tutorial as shown below, today, the concepts in the Android Studio project regarding the “middle game”, comparing it to the Eclipse IDE (Eclipse Android App Google Play Ready Primer Tutorial), for which huge help came from this great link … thanks … are, again, for our “ESL Ideas” Android mobile app (which “channels” our project, recently, started with HTML/Javascript Themed Supervision Primer Tutorial) of today …

  • Fragments – components of the Android UI … and setting of startup fragment of interest … fragment_weblayout.xml … fragments go some way to addressing that common issue for mobile developers that all the UI elements of a mobile application fit and would ideally be displayed with a tablet but it would be best to only conditionally display some when it comes to using a smaller format mobile device such as an Android mobile phone device
  • Main Java in MainActivity.java … similar to Eclipse
  • Layout in activity_main.xml … similar to Eclipse
  • WebView … similar to Eclipse … allows an Internet web component in your Android mobile app
  • Use of myWebView.getSettings().setJavaScriptEnabled(true); to allow Javascript functionality for the WebView
  • AndroidManifest.xml … INTERNET permission … similar to Eclipse … to Build->”Generate Signed APK…” for Google Play publishing you need the extra … android:debuggable="false" clause
  • Tools->Android->AVD Manager … emulator organization and emulator deployment help … remains the case that it is best to start the emulator all the way to the home page at the simulated device (right swipe unlocking any locks you get) … then run and attach your mobile app to this pre-established connection

You will be pleased to know that after the Android Studio install today, all is (still) well with Xcode on this Mac OS X (MacBook Pro) setup … we mostly like a happy ending … aaaaaaahhhhhhh!


Previous relevant Android Studio Google Play Ready Primer Tutorial is shown below.

Android Studio Google Play Ready Primer Tutorial

Android Studio Google Play Ready Primer Tutorial

Yesterday, with Android Studio Tic Tac Toe Game Tutorial as shown below, we reacquainted ourselves with Android Studio as an alternative IDE to Eclipse (and there are others too) to use the Android SDK and Java to develop mobile apps for an Android mobile device and in our aforesaid mentioned “start game”, “middle game” and “end game” view of mobile development we focussed on the “middle game”.

Today, we extend the “middle game” discussion of yesterday, with tutorial functionality touching on the “end game” with respect to Android Studio creating an Android mobile app on Google Play.

Wonder if you were around when we created the Morse Code emailer … HTML Morse Code Primer Tutorial? Well, today, we turn that into an Android mobile application using Android Studio, and publish it to Google Play for general “consumption” by the public.

So what are some of the concepts in the Android Studio project regarding the “middle game”, for which huge help came from this great link … thanks …

  • Fragments – components of the Android UI … and setting of startup fragment of interest … fragments go some way to addressing that common issue for mobile developers that all the UI elements of a mobile application fit and would ideally be displayed with a tablet but it would be best to only conditionally display some when it comes to using a smaller format mobile device such as an Android mobile phone device
  • Layout in activity_main.xml … similar to Eclipse
  • WebView … similar to Eclipse … allows an Internet web component in your Android mobile app
  • Use of myWebView.getSettings().setJavaScriptEnabled(true); to allow Javascript functionality for the WebView
  • AndroidManifest.xml … INTERNET permission … similar to Eclipse … to Build->”Generate Signed APK…” for Google Play publishing you need the extra … android:debuggable="false" clause
  • Tools->Android->AVD Manager … emulator organization and emulator deployment help … remains the case that it is best to start the emulator all the way to the home page at the simulated device (right swipe unlocking any locks you get) … then run and attach your mobile app to this pre-established connection

Source code wise, of interest to the “middle game”, is …

Before leaving the “middle game” thoughts, sometimes you need to adjust the code of a WebView’s innards (especially) if you want to do away with any “Back” or “Forward” button mobile application functionality, because any escape from the WebView’s control is that mobile application being effectively lost for that session. As such, the Morse Code programming HTML source code became morsecode.html (… and how we got there morsecode.html …) and the method of creating the email was made to use a PHP piece of supervised code as per morsecode.php (with a live run non-mobile web page link) to cater for Android mobile WebView compatibility … and thanks to this useful link.

And what of the “end game”? … Would direct you to the imagery of today’s tutorial … a lot of it covers the same ground as the “Eclipse” corresponding scenario tutorial called Eclipse Android App Google Play Ready Primer Tutorial.

Just to challenge you with a “middle, end, start order” … have a look at some information regarding Android Studio mobile development and the “start game” … Android Studio Primer Tutorial.

Hope this is food for thought for your Android mobile development plans! See the results of the work today at Google Play.


Previous relevant Android Studio Tic Tac Toe Game Tutorial is shown below.

Android Studio Tic Tac Toe Game Tutorial

Android Studio Tic Tac Toe Game Tutorial

Wonder if you were around when we created Tic Tac Toe (or more like Noughts and Crosses, in Australia) using the HTML5 Canvas element and drag and drop methods (if you liked, or just plain box clicking, otherwise, which will be okay for mobile usage) … HTML/Javascript Canvas Tic Tac Toe Game Drag and Drop Tutorial as shown below? Well, today, we turn that into an Android mobile application using Android Studio.

Android Studio is an alternative IDE to Eclipse (and there are others too) to use the Android SDK and Java to develop mobile apps for an Android mobile device and in our aforesaid mentioned “start game”, “middle game” and “end game” view of mobile development we are just showing you the “middle game” today, but if you were to follow through … fore!!!!!!!! … and not shank … and not hook (ie. narrrrrrr … chortle, chortle) … then we may end up at Google Play with a mobile app … by the way, we talk about the “end game” at Eclipse Android App Google Play Ready Primer Tutorial (Android Studio has all this functionality and capability too).

So what are some of the concepts in the Android Studio project, for which huge help came from this great link … thanks …

  • Fragments – components of the Android UI … and setting of startup fragment of interest … fragments go some way to addressing that common issue for mobile developers that all the UI elements of a mobile application fit and would ideally be displayed with a tablet but it would be best to only conditionally display some when it comes to using a smaller format mobile device such as an Android mobile phone device
  • Layout in activity_main.xml … similar to Eclipse
  • WebView … similar to Eclipse … allows an Internet web component in your Android mobile app
  • Use of myWebView.getSettings().setJavaScriptEnabled(true); to allow Javascript functionality for the WebView
  • AndroidManifest.xml … INTERNET permission … similar to Eclipse
  • Tools->Android->AVD Manager … emulator organization and emulator deployment help … remains the case that it is best to start the emulator all the way to the home page at the simulated device (right swipe unlocking any locks you get) … then run and attach your mobile app to this pre-established connection

Source code wise, of interest, is …

So that’s a bit about the mobile world, and so concerning the innards of that WebView …

The Canvas HTML element tag can be used as the container to draw graphics on the fly usually via the use of Javascript functions for rendering and event management.

In today’s tutorial we show some image Drag and Drop functionality that you can use with the Canvas HTML5 element where we create a Tic Tac Toe game webpage. We thank w3schools for the great advice at this link.

The Drag and Drop does not work well on tablets, but for own Tic Tac Toe game today we allow either a drag and drop approach, or a touch/click approach.

You may want to read more at HTML Canvas Reference as a generic reference, or here, at the tutorial javascript – How do I add a simple onClick event handler to a canvas element? – Stack Overflow.

As you can imagine, this HTML canvas element, new to HTML5, can be very useful for some practical client-side web functionality.

Link to some downloadable HTML programming code … rename to tictactoe_chalkboard.html

You’ll notice heavy use of the Javascript Math.random() function.

We hope you enjoy this tutorial as a live run.

Should you find Tac Tac Toe (or even Noughts and Crosses) addictive you should see this … amazing!

Yes … you’ve reached the end … go first in each game and see if you can beat the computer!


Previous relevant HTML/Javascript Canvas Tic Tac Toe Game Drag and Drop Tutorial is shown below.

HTML/Javascript Canvas Tic Tac Toe Game Drag and Drop Tutorial

HTML/Javascript Canvas Tic Tac Toe Game Drag and Drop Tutorial

The Canvas HTML element tag can be used as the container to draw graphics on the fly usually via the use of Javascript functions for rendering and event management.

In today’s tutorial we show some image Drag and Drop functionality that you can use with the Canvas HTML5 element where we create a Tic Tac Toe game webpage. We thank w3schools for the great advice at this link.

The Drag and Drop does not work well on tablets, but for own Tic Tac Toe game today we allow either a drag and drop approach, or a touch/click approach.

You may want to read more at HTML Canvas Reference as a generic reference, or here, at the tutorial javascript – How do I add a simple onClick event handler to a canvas element? – Stack Overflow.

As you can imagine, this HTML canvas element, new to HTML5, can be very useful for some practical client-side web functionality.

Link to some downloadable HTML programming code … rename to tictactoe_chalkboard.html

You’ll notice heavy use of the Javascript Math.random() function.

We hope you enjoy this tutorial as a live run.

Should you find Tac Tac Toe (or even Noughts and Crosses) addictive you should see this … amazing!

Yes … you’ve reached the end … go first in each game and see if you can beat the computer!

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


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


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


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


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


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


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


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

Google Translate WordPress Blog Widget Positioning Tutorial

Google Translate WordPress Blog Widget Positioning Tutorial

Google Translate WordPress Blog Widget Positioning Tutorial

When we last upgraded our WordPress.org website from 4.1.1. to 6.6.2 the Widget section CSS arrangements, barring the installation of a WordPress plugin to backtrack, caused WordPress to start CSS styling the widget area via a new “block” paradigm.

This “block” paradigm seems to have rearranged a non-mobile user’s view of a Google Translate view of one of our WordPress blog posting webpages, translated from English to another language.

Rather than fight this, we want to …

  • stop “fight and flight” base thinking …
  • think more, fitting in … it takes less time … and improves your skills solving problems, we believe

What happens here with non-mobile Google Translate webpage translation scenarios, it starts putting all but our Numerical Quiz (maybe because it is narrower, and we are talking Responsive Design with all of this) Widget components down the bottom of the screen. To us, “above the fold” beats any Responsive Design niceties here. We, at least, want the Search form and Recent Posts widgets to appear to the right and above the fold, predominantly, here, for non-mobile platforms.

Yesterday’s Google Translate WordPress Blog Image URL Fix Tutorial taught us (big time) where to intervene, in our WordPress blog’s TwentyTen theme’s header.php code, we started applying

<?php echo ”

function laterimg() {
var imgi = document.getElementsByTagName('img');
for (iyt=0; iyt<imgi.length; iyt++) {

if (iyt == 0) {
if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (document.getElementById('text-2') && document.getElementById('searchform') && document.getElementById('recent-posts-2')) {
var gtrectis=document.getElementById('text-2').getBoundingClientRect();
//document.getElementById('text-2').style.height='' + ('' + eval(-10 + eval('' + gtrectis.height))) + 'px';
var gsfis=document.getElementById('searchform').getBoundingClientRect();
document.getElementById('searchform').style.position='absolute';
document.getElementById('searchform').style.left='' + eval(-7 + eval('' + gtrectis.left)) + 'px';
document.getElementById('searchform').style.top='' + eval(-10 + 36 + eval('' + gtrectis.bottom)) + 'px';
document.getElementById('searchform').style.backgroundColor='yellow';
document.getElementById('recent-posts-2').style.position='absolute';
document.getElementById('recent-posts-2').style.left='' + gtrectis.left + 'px';
document.getElementById('recent-posts-2').style.top='' + eval(-10 + 24 + eval('' + gtrectis.bottom) + eval('' + gsfis.height)) + 'px';
document.getElementById('recent-posts-2').style.listStyleType='none';
document.getElementById('recent-posts-2').style.backgroundColor='#F0F8FF';
}
}
}

if (('' + top.document.URL).indexOf('rjmprogramming-com-au') != -1) {
if (('' + imgi[iyt].src).indexOf('&u=//') != -1) {
imgi[iyt].src=imgi[iyt].src.split('&u=')[1];
}
}
}
}

“; ?>


Previous relevant Google Translate WordPress Blog Image URL Fix Tutorial is shown below.

Google Translate WordPress Blog Image URL Fix Tutorial

Google Translate WordPress Blog Image URL Fix Tutorial

Further to Google Translate Landing Page Changed Interfacing Links Tutorial we’re revisiting Google Translate “translation of WordPress blog webpage” translation functionality, finding some images getting non RJM Programming “src” properties, oddly. We do not remember this, but interfacing rules can change, of course, and it’s been a while?!

We think, perhaps, too, we were more often than we were needing to, asking for a translation of …


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

… content, and this is usually not the most apt translation to attempt. The permalink WordPress blog URLs are going to be the usual case, and we can find their ?p=[pId] equivalent (and helpful plugged into the Google Translate window.top URL) can be gleaned as the first mention in document.body.innerHTML of …


<div id="post-[pId]">

via Javascript code like …

<?php

function ChangeLcode2Now(val){
//var val = document.getElementById('x2language');
//alert(val.value);
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
//alert(val.value);
var pprefix = ('' + val[val.selectedIndex].id);
var postns=top.document.body.innerHTML.split('<div i' + 'd="post-');
if (eval('' + postns.length) > 1) {
pprefix=postns[1].split('"')[0]; //alert(pprefix + ' ' + postns[1].split('"')[0]);
//window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/?p=' + postns[1].split('"')[0] + '&_x_tr_sl=en&_x_tr_tl=' + val.value + '&_x_tr_hl=en-GB&_x_tr_pto=nui', '_blank', 'top=50,left=50,width=800,height=800');
}

<?php
$p316 = "316";
$pprefix = "";
if (strpos($_SERVER['QUERY_STRING'], "p=0") !== false) {
$pprefix = "";
} else {
if (isset($_GET['p'])) {
if (strpos($_GET['p'], "304") !== false) {
$p316 = "316";
} else {
$p316 = $_GET['p'];
}
}
//echo "window.location = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2FITblog%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
if (1 == 1) { // _x_tr_sl=en&_x_tr_tl=de&_x_tr_hl=en-GB&_x_tr_pto=nui
echo " window.location = 'https://www-rjmprogramming-com-au.translate.goog/ITblog?p=' + pprefix + '&_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp'; " . "\n";
} else {
echo "window.location = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2FITblog%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
}
}
?>
//window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress&tl=' + val.value, '_blank');
//alert("yes" + val.value);
}
}

With all this, we now fix the HTML img elements sometimes getting a Google Translate related URL via the new Javascript code snippet in the WordPress blog’s TwentyTen theme’s header.php via a delayed call of …

<?php echo ”

function laterimg() {
var imgi = document.getElementsByTagName('img');
for (iyt=0; iyt<imgi.length; iyt++) {
if (('' + top.document.URL).indexOf('rjmprogramming-com-au') != -1) {
if (('' + imgi[iyt].src).indexOf('&u=//') != -1) {
imgi[iyt].src=imgi[iyt].src.split('&u=')[1];
}
}
}
}

“; ?>


Previous relevant Google Translate Landing Page Changed Interfacing Links Tutorial is shown below.

Google Translate Landing Page Translate Changed Interfacing Tutorial

Google Translate Landing Page Changed Interfacing Links Tutorial

Onto yesterday’s Google Translate Landing Page Changed Interfacing Tutorial we wanted to extend the functionality, given user intervention, that other links on the Landing Pages can be sent to Google Translate for webpage translation.

We decided to …

Add two new global variables

var uprefix='';
var usuffix='';
For two iframes add id attribute …

<div id=divtagcloud><iframe id=ifdtc style='display:none;' onerror='anticheckd(this);' onload='checkd(this);' src='//www.rjmprogramming.com.au/PHP/divtagcloud.html'></iframe></div>
<iframe id=ifzero onload="noandmaybe(this);" src="PHP/zero.html" title="Recent Blog Posts" style="width:264px;"></iframe>
Change function ChangeLCodeNow …

function ChangeLcodeNow(){
//<![CDATA[
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1) && val.value != val.value.trim()) {
usuffix=usuffix.split('&obsolete=')[0];
document.getElementById('ifzero').src+='?random=' + Math.floor(Math.random() * 198767543); //alert(usuffix);
if (document.getElementById('divtagcloud') && !document.getElementById('ifdtc')) {
document.getElementById('divtagcloud').innerHTML="<iframe id=ifdtc style='display:none;' onerror='anticheckd(this);' onload='checkd(this);' src='PHP/divtagcloud.html?random=" + Math.floor(Math.random() * 198767543) + "'></iframe>";
} else {
document.getElementById('ifdtc').src+='?random=' + Math.floor(Math.random() * 198767543); //alert(usuffix);
}
} else if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var srectis=val.getBoundingClientRect();
var pprefix = val[val.selectedIndex].id;
var dd=new Date();
var wdg=val[val.selectedIndex].innerHTML;
uprefix='https://www-rjmprogramming-com-au.translate.goog';
usuffix='?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value.trim() + '&_x_tr_pto=wapp&obsolete=y';
if (1 == 1) {
//alert('<span style="position:absolute;top:' + srectis.top + 'px;left:' + srectis.left + 'px;">' + val[val.selectedIndex].innerHTML + ' <input type=checkbox onchange="usuffix=usuffix.split(' + "'" + '&obsolete=' + "'" + ')[0];"></input> Everywhere </span>');
if (1 == 2) {
document.body.innerHTML=document.body.innerHTML.replace(val.outerHTML, '<span style="z-index:123;position:absolute;top:' + srectis.top + 'px;left:' + srectis.left + 'px;">' + val[val.selectedIndex].innerHTML + ' <input type=checkbox onchange="usuffix=usuffix.split(' + "'" + '&obsolete=' + "'" + ')[0];"></input> Everywhere </span>');
} else {
document.getElementById('language').innerHTML='<option value="' + val.value.trim() + '" selected>' + wdg + '</option><option value="' + val.value.trim() + ' ">' + wdg + ' (everywhere)</option>';
document.getElementById('language').size='2';
}
window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp', '_blank');
} else {
window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp', '_blank');
document.getElementById('langone').innerHTML=val[val.selectedIndex].innerHTML + ' (and reclick for other translations)';
document.getElementById('langone').title=document.getElementById('langone').innerHTML;
val.title=document.getElementById('langone').innerHTML;
document.getElementById('langone').onclick = function(evt) { usuffix=usuffix.split('&obsolete=')[0]; this.innerHTML=this.innerHTML.split('(')[0] + '(everywhere)'; };
val.value='';
}
}
//]]>
}
Change function mwo …

function mwo(in_url) {
// https://www.rjmprogramming.com.au/ITblog/css-countdown-reveal-tutorial/?pp&pn&title=CSS_Countdown_Reveal_Tutorial
//alert(in_url);
if (in_url.indexOf('&title=') != -1 && in_url.indexOf('?p=') != -1 && in_url.indexOf('rjmprogramming.com.au/') != -1) {
var tis=in_url.split('&title=')[1].split('&')[0].split('#')[0].replace(/\_/g,'-').toLowerCase();
var ptis=in_url.split('?p=')[1].split('&')[0].split('#')[0];
if (isiPad || isiPhone || isiPod || isAndroid) {
if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var inurl=in_url.split('?')[0] + in_url.split('&title=')[1].toLowerCase().replace(/\_/g,'-');
//alert(inurl);
return inurl.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
//return (in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis).replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix + '#post-' + ptis + '#andabit=-70';
//} else if (usuffix != '' && usuffix.indexOf('&obsolete=') != -1) {
//var inurl=in_url.split('?')[0] + in_url.split('&title=')[0].toLowerCase().replace(/\_/g,'-');
//return inurl.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
} else {
return in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis + '#post-' + ptis + '#andabit=-70';
}
} else if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var inurl=in_url.split('?')[0] + in_url.split('&title=')[1].toLowerCase().replace(/\_/g,'-');
//alert(inurl);
return inurl.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
//return (in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis).replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix; // + '#post-' + ptis;
} else {
return in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis; // + '#post-' + ptis;
}
} else if (usuffix != '' && usuffix.indexOf('&obsolete=') != -1) {
return in_url.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
} else {
return in_url;
}
}
Change function windowopen …

function windowopen(myurl,mytarget) {
if (isiPad || isiPhone || isiPod) {
var aobod = document.getElementById('abod');
aobod.href=mwo(myurl);
aobod.click();
} else if (isAndroid) {
top.window.open(mwo(myurl),mytarget);
} else if (usuffix.indexOf('&obsolete=') == -1 && usuffix != '') {
top.window.open(mwo(myurl),mytarget);
} else {
top.window.open(myurl,mytarget);
//location.href=myurl;
}
}
For two iframes change onload event functionalities

function checkd(iois) {
if (iois != null) {
var aconto = (iois.contentWindow || iois.contentDocument);

if (aconto != null) {

if (aconto.document) { aconto = aconto.document; }

if (aconto.body != null) {

if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var wasabi=aconto.body.innerHTML;
var qps=wasabi.split('?p=');
var iqps=0;
var insr='';
qps=wasabi.split(' href="');
for (iqps=1; iqps<qps.length; iqps++) {
insr=qps[iqps].split('"')[0];
wasabi=wasabi.replace(insr, insr.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix);
}
aconto.body.innerHTML=wasabi;
if (divtc != '') { divtc=wasabi; }
} else {

divtc=aconto.body.innerHTML;
}
if (divtc.indexOf(' class="tagcloud"') != -1) {
setTimeout(divtctoggler, 8000);
} else {
document.getElementById('divtagcloud').innerHTML='';
}
}
}
}
}

function noandmaybe(iois) {
var aconto=null, jps=[];
if ((usuffix != '' && usuffix.indexOf('&obsolete=') == -1) || !navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) { // or it is not a mobile device
if (iois != null) {
aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
aconto.body.innerHTML=aconto.body.innerHTML.replace(/\#andabit\=\-70/g,'');
}
if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var wasabi=aconto.body.innerHTML;
var qps=wasabi.split('?p=');
var iqps=0;
var insr='';
for (iqps=1; iqps<qps.length; iqps++) {
wasabi=wasabi.replace('?p=' + qps[iqps].split('"')[0], qps[iqps].split(' alt="')[1].split('"')[0].toLowerCase().replace("+","").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(/---/g,"-").replace(/--/g,"-") + '/');
}
qps=wasabi.split(' href="');
for (iqps=1; iqps<qps.length; iqps++) {
insr=qps[iqps].split('"')[0];
wasabi=wasabi.replace(insr, insr.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix);
}
aconto.body.innerHTML=wasabi;
for (iqps=1; iqps<=5; iqps++) {
insr=document.getElementById('adiv' + iqps).outerHTML;
wasabi=insr.replace('?p=' + insr.split('?p=')[1].split('"')[0], insr.split(' title="')[1].split('"')[0].toLowerCase().replace("+","").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(/---/g,"-").replace(/--/g,"-") + '/');
document.getElementById('adiv' + iqps).href=wasabi.split(' href="')[1].split('"')[0].replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
}
var asis=document.getElementsByTagName('a');
for (iqps=0; iqps<asis.length; iqps++) {
if (('' + asis[iqps].href).toLowerCase().indexOf('rjmprogramming.com.au') != -1) {
asis[iqps].href=(asis[iqps].href.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix).replace('/wordpress/','/ITblog/');
}
}
}

}
}
}

if (document.getElementById('style_3') && ('' + document.getElementById('style_3').title) == '') {
if (!aconto) {
aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
}
}

var omover=' onmouseover="omright(this);" ', omout=' onmouseout="moright(this);" ', bdapp='<table id=tblr style=display:none><tr></tr></table>';
var rdbit='?rand=' + Math.floor(Math.random() * 1985676);
if (aconto) {
if (aconto.body != null) {
if (document.getElementById('p_style_3')) {
document.getElementById('style_3').innerHTML=document.getElementById('p_style_3').outerHTML.replace(/\.jpg/g, '.jpg' + rdbit);
}
var hrefs=aconto.body.innerHTML.split(' href=');
var style_3r=document.getElementById('style_3').getBoundingClientRect();
document.getElementById('style_3').title='Feel free to visit thumbnail links to our WordPress Tutorial blog!';
for (var ihrefs=1; ihrefs<hrefs.length; ihrefs++) {
//document.body.innerHTML+='<div id=ediv' + ihrefs + '></div>';
bdapp=bdapp.replace('</tr>', '<td id=ediv' + ihrefs + '></td></tr>');
jps=hrefs[ihrefs].split('.jpeg?rand=');
console.log(jps[0].slice(-9));
if (jps[0].slice(-3).indexOf('-') != -1) { jps[0]=jps[0].split('-')[eval(-2 + eval('' + jps[0].split('-').length))]; }
switch (jps[0].slice(-3)) {
case 'ght':
document.body.innerHTML+='<a id=adiv5' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/eight.jpg' + rdbit + ');position:absolute;z-index:99;top:' + style_3r.top + 'px;width:30px;height:20px;background-color:transparent;left:' + style_3r.left + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'ven':
document.body.innerHTML+='<a id=adiv4' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/seven.jpg' + rdbit + ');position:absolute;z-index:99;top:' + style_3r.top + 'px;width:30px;height:20px;background-color:transparent;left:' + eval(eval(eval(style_3r.left + style_3r.right) / 2) - 15) + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'six':
document.body.innerHTML+='<a id=adiv3' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/six.jpg' + rdbit + ');position:absolute;z-index:99;top:' + style_3r.top + 'px;width:30px;height:20px;background-color:transparent;left:' + eval(style_3r.right - 30) + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'ive':
document.body.innerHTML+='<a id=adiv2' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/five.jpg' + rdbit + ');position:absolute;z-index:99;top:' + eval(style_3r.bottom - 20) + 'px;width:30px;height:20px;background-color:transparent;left:' + style_3r.left + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'our':
document.body.innerHTML+='<a id=adiv1' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/four.jpg' + rdbit + ');position:absolute;z-index:99;top:' + eval(style_3r.bottom - 20) + 'px;width:30px;height:20px;background-color:transparent;left:' + eval(style_3r.right - 30) + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


default:
break;
}
}
document.body.innerHTML+=bdapp;
bodyrect=document.getElementById('nav_layer').getBoundingClientRect();
}
}
}
}

Feel free to try, coming off a new “(everywhere)” appended dropdown option a user can select!


Previous relevant Google Translate Landing Page Changed Interfacing Tutorial is shown below.

Google Translate Landing Page Translate Changed Interfacing Tutorial

Google Translate Landing Page Changed Interfacing Tutorial

It pays to keep in touch with third party arrangements you have in place, as for the recent Google Translate Landing Page Translate Updated List Tutorial‘s interfacing to the great Google Translate resource capable of translating our RJM Programming blog (via Landing page language dropdown (select) element up the top right) to non-English languages.

But two interfacing to Google Translate aspects have changed since we had occasion to “see how this was going” (oops!)

  1. enforcing https: protocol … and …
  2. extra &_x_tr_pto=wapp to arguments … as per old versus new Landing Page Javascript code arrangements …

    function oldChangeLcodeNow(){
    //<![CDATA[
    var val = document.getElementById('language');
    if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
    var pprefix = val[val.selectedIndex].id;
    var dd=new Date();
    window.open('//www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_blank');
    }
    //]]>
    }



    function ChangeLcodeNow(){
    //<![CDATA[
    var val = document.getElementById('language');
    if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
    var pprefix = val[val.selectedIndex].id;
    var dd=new Date();
    window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp', '_blank');
    }
    //]]>
    }

… linking the user picking a non-English language off the dropdown element be able to translate that day’s latest RJM Programming blog post into that language via Google Translate. Thanks heaps!


Previous relevant Google Translate Landing Page Translate Updated List Tutorial is shown below.

Google Translate Landing Page Translate Updated List Tutorial

Google Translate Landing Page Translate Updated List Tutorial

Yesterday’s Google Translate Landing Page Translate Update Tutorial left off with …

It’s the start that does not ingrain the webpage HTML to any great permanence, and that is for another “PHP involvement” day.

… and that new day is upon us. Whenever you combine …

  • PHP writing public HTML webpage data … with …
  • a user interface (and we’d really only like that “user set” to be an administrator of this blog)

… it’s a potential data security issue you are opening up, and yet, we do want to involve some automation of webpage code here for something that can be ascertained. So let’s try to protect ourselves (to some degree) regarding the PHP below …

<?php

if (isset($_POST['langih']) && strpos(strtolower('' . $_SERVER['HTTP_REFERER']), "rjmprogramming.com.au/about_us.html") !== false) {
$prefis="./";
$ftf=["index.htm","index.html","indexmobile.html","About_Us.html","Contact_Us.html","Guestbook.html","Link.html","Links.html","Services.html","Welcome.html","News.html","Welcome.htm","Welcomeslideshow.htm","Welcomeslideshow.html","slideshow.html"];
$lih=str_replace("+", " ", urldecode($_POST['langih']));
if (strpos("~" . strtolower($lih), "~<option") !== false) {
if (strpos(strtolower($lih) . "~", "</option>~") !== false) {
if (strpos($lih, ">Blog Language") !== false) {



for ($i=0; $i<sizeof($ftf); $i++) {
if (file_exists($prefis . $ftf[$i])) {
$cont=file_get_contents($prefis . $ftf[$i]);
if (strpos($cont, ">Blog Language") !== false) {
if (strpos(str_replace("<option","",str_replace("</option>","",strtolower($lih))), "<") === false) {
if (strlen(explode("</select>", explode(">Blog Language", $lih)[1])[0]) > strlen($wasis)) {
if (sizeof(explode(">",explode("</select>", explode(">Blog Language", $lih)[1])[0])) >= sizeof(explode(">",$wasis))) {

file_put_contents($prefis . $ftf[$i] . "_spare", $cont);
$wasis=explode("</select>", explode(">Blog Language", $cont)[1])[0];
$contnew=str_replace($wasis, explode("</select>", explode(">Blog Language", $lih)[1])[0], $cont);
file_put_contents($prefis . $ftf[$i], $contnew);
}
}
}
}
}
}


}
}
}

}
exit;

?>

… restricting calling URLs and some of the look and size and content of the posted data, and working with the “About Us” webpage “place” to automate, the idea of choosing “English” from the “Blog Language” dropdown, as per the changed Javascript and Ajax “way in”


function ChangeLcodeNow(){
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var pprefix = val[val.selectedIndex].id;
var dd=new Date();
window.open('//www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_blank');
} else if (val.value.length != 0 && val.value.indexOf('en') != (0 - 1)) {
if (ajaxitp) { ajaxitp(); }
}

}

function ajaxitp() {
var xurl = './getme.php';
var formis = new FormData();
myxhr = new XMLHttpRequest();
if (myxhr) {
formis.append('langih', document.getElementById('language').innerHTML);
myxhr.open('POST', xurl); //, true);
myxhr.send(formis);
}
}


Previous relevant Google Translate Landing Page Translate Update Tutorial is shown below.

Google Translate Landing Page Translate Update Tutorial

Google Translate Landing Page Translate Update Tutorial

The recent Google Translate Landing Page Translate Tutorial

… and so, we are here today, with our start to remedies for this (Javascript DOM, via Ajax, change below) …


var myxhr=null;

function backin() {


if (myxhr.readyState == 4) {
if (myxhr.status == 200) {
if (myxhr.responseText) {
if (document.getElementById('language')) {
//alert(myxhr.responseText);
var mhs=myxhr.responseText.replace(/\<\/code\>\<\/td\>/g,'<>').split('><code translate="no" dir="ltr">');
if (mhs.length > 1) {
var thiscodeis='', thisdescis='';
var wasih=document.getElementById('language').innerHTML;
var outih=wasih.split('</option>')[0] + '</option>';
var origih=wasih.replace(outih, '');
for (var iuh=1; iuh<mhs.length; iuh++) {
thisdescis=mhs[eval(-1 + iuh)].split('<td>')[eval(-1 + mhs[eval(-1 + iuh)].split('<td>').length)];
//console.log('first thisdescis=' + thisdescis + ' and mhs[eval(-1 + iuh)]=' + mhs[eval(-1 + iuh)].slice(-200));
thisdescis=thisdescis.split('<')[0];
thiscodeis=mhs[iuh].split('<')[0].split('(')[0].trim();
//console.log('thiscodeis=' + thiscodeis + ' and thisdescis=' + thisdescis + ' and mhs[eval(-1 + iuh)]=' + mhs[eval(-1 + iuh)].slice(-200));
if (wasih.toLowerCase().indexOf(' value="' + thiscodeis.toLowerCase() + '"') == -1 && wasih.toLowerCase().indexOf(thisdescis.toLowerCase()) == -1) {
outih+='<option value="' + thiscodeis + '">' + thisdescis + ' &#10024;</OPTION>';
} else {
outih+='<option value="' + thiscodeis + '">' + thisdescis + '</OPTION>';
}
}
if (outih.indexOf('/OPTION') != -1 && origih.toLowerCase() != outih.toLowerCase()) {
document.getElementById('language').innerHTML=outih.replace('</option>', ' &#10024;</OPTION>');
document.getElementById('language').style.maxWidth='150px';
}
}
}
}
}
}
}

function ajaxit() {
var xurl = '//cloud.google.com/translate/docs/languages';
//alert(1);
myxhr = new XMLHttpRequest();
if (myxhr) {
//alert(2);
myxhr.onreadystatechange = backin;
myxhr.open('GET', 'getme.php?getme=' + encodeURIComponent(xurl), true);
myxhr.send(null);
}
}

function refreshl() {
if (document.getElementById('language')) {
ajaxit();
}
}

setTimeout(refreshl, 5000);

It’s the start that does not ingrain the webpage HTML to any great permanence, and that is for another “PHP involvement” day.


Previous relevant Google Translate Landing Page Translate Tutorial is shown below.

Google Translate Landing Page Translate Tutorial

Google Translate Landing Page Translate Tutorial

Yesterday’s …

  • Google Translate Webpage Translate Tutorial was the major part of RJM Programming’s Google Translate strategy change (ie. getting it working again … doh!) … but it’s not the whole story … and another part is …
  • today we extend that strategy to change the RJM Programming Landing Page Google Translate interfacing to change from a “Landing Page content” strategy to a “Navigate to WordPress Blog” strategy (feeding into yesterday’s thinking), our justification being that the better content of the RJM Programming domain sits within the WordPress Blog we support and maintain

… so there, ngarrrrgh!

But (growing up quickly) we see a better arrangement here, just adding the prefix “Blog” onto the old (just) “Language” labelled dropdown to modify the “new “Blog Language” (to end up with HTML snippet <option value=””>Blog Language</option>) dropdown’s Javascript “onchange” event logic …


// To ...
function ChangeLcodeNow(){
//<![CDATA[
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var pprefix = val[val.selectedIndex].id;
var dd=new Date();
window.open('//www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_blank');
}
//]]>
}


// ... From ...
function olderChangeLcodeNow(){
//<![CDATA[
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var pprefix = val[val.selectedIndex].id;
windowopen('http://translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Findex.html&tl=' + val.value, '_blank');
}
//]]>
}

Again, not too onerous!


Previous relevant Google Translate Webpage Translate Tutorial is shown below.

Google Translate Webpage Translate Tutorial

Google Translate Webpage Translate Tutorial

We really like the way Google Translate can language translate whole webpages for URLs of choice, sometimes. We use it here at this blog, but sometime into the past … we cannot recall (sorrrrrryyyyyyyyy!) … the arrangements of use of this great functionality changed, and today we want to go over what we did for this blog to fix some of this interfacing.

It was in good ol’ WordPress TwentyTen theme’s header.php we made the change to facilitate this “reconnection” to this great functionality …

<?php

function ChangeLcodeNow(){
var val = document.getElementById('language');
//alert(val.value);
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
//alert(val.value);
var pprefix = val[val.selectedIndex].id;
<?php
$p316 = "316";
$pprefix = "";
if (strpos($_SERVER['QUERY_STRING'], "p=0") !== false) {
$pprefix = "";
} else {
if (isset($_GET['p'])) {
if (strpos($_GET['p'], "304") !== false) {
$p316 = "316";
} else {
$p316 = $_GET['p'];
}
}

$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPad');
if ($isiPad === false) {
$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPhone');
}
if ($isiPad === false) {
$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'Android');
}

if (1 == 1) { // _x_tr_sl=en&_x_tr_tl=de&_x_tr_hl=en-GB&_x_tr_pto=nui
echo " window.open('//www-rjmprogramming-com-au.translate.goog/ITblog?p=' + pprefix + '&_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_top'); " . "\n";
} else {

if ($isiPad) {
//echo " window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value, '_top'); " . "\n";
echo " window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value, '_top'); " . "\n";
} else {
//echo "window.location.href = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
echo "window.location.href = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
}
}
}
?>
//window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress&tl=' + val.value, '_blank');
//alert("yes" + val.value);
}
}

?>

Not too bruising!

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


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


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


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


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


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


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


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

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

Google Translate WordPress Blog Image URL Fix Tutorial

Google Translate WordPress Blog Image URL Fix Tutorial

Google Translate WordPress Blog Image URL Fix Tutorial

Further to Google Translate Landing Page Changed Interfacing Links Tutorial we’re revisiting Google Translate “translation of WordPress blog webpage” translation functionality, finding some images getting non RJM Programming “src” properties, oddly. We do not remember this, but interfacing rules can change, of course, and it’s been a while?!

We think, perhaps, too, we were more often than we were needing to, asking for a translation of …


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

… content, and this is usually not the most apt translation to attempt. The permalink WordPress blog URLs are going to be the usual case, and we can find their ?p=[pId] equivalent (and helpful plugged into the Google Translate window.top URL) can be gleaned as the first mention in document.body.innerHTML of …


<div id="post-[pId]">

via Javascript code like …

<?php

function ChangeLcode2Now(val){
//var val = document.getElementById('x2language');
//alert(val.value);
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
//alert(val.value);
var pprefix = ('' + val[val.selectedIndex].id);
var postns=top.document.body.innerHTML.split('<div i' + 'd="post-');
if (eval('' + postns.length) > 1) {
pprefix=postns[1].split('"')[0]; //alert(pprefix + ' ' + postns[1].split('"')[0]);
//window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/?p=' + postns[1].split('"')[0] + '&_x_tr_sl=en&_x_tr_tl=' + val.value + '&_x_tr_hl=en-GB&_x_tr_pto=nui', '_blank', 'top=50,left=50,width=800,height=800');
}

<?php
$p316 = "316";
$pprefix = "";
if (strpos($_SERVER['QUERY_STRING'], "p=0") !== false) {
$pprefix = "";
} else {
if (isset($_GET['p'])) {
if (strpos($_GET['p'], "304") !== false) {
$p316 = "316";
} else {
$p316 = $_GET['p'];
}
}
//echo "window.location = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2FITblog%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
if (1 == 1) { // _x_tr_sl=en&_x_tr_tl=de&_x_tr_hl=en-GB&_x_tr_pto=nui
echo " window.location = 'https://www-rjmprogramming-com-au.translate.goog/ITblog?p=' + pprefix + '&_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp'; " . "\n";
} else {
echo "window.location = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2FITblog%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
}
}
?>
//window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress&tl=' + val.value, '_blank');
//alert("yes" + val.value);
}
}

With all this, we now fix the HTML img elements sometimes getting a Google Translate related URL via the new Javascript code snippet in the WordPress blog’s TwentyTen theme’s header.php via a delayed call of …

<?php echo ”

function laterimg() {
var imgi = document.getElementsByTagName('img');
for (iyt=0; iyt<imgi.length; iyt++) {
if (('' + top.document.URL).indexOf('rjmprogramming-com-au') != -1) {
if (('' + imgi[iyt].src).indexOf('&u=//') != -1) {
imgi[iyt].src=imgi[iyt].src.split('&u=')[1];
}
}
}
}

“; ?>


Previous relevant Google Translate Landing Page Changed Interfacing Links Tutorial is shown below.

Google Translate Landing Page Translate Changed Interfacing Tutorial

Google Translate Landing Page Changed Interfacing Links Tutorial

Onto yesterday’s Google Translate Landing Page Changed Interfacing Tutorial we wanted to extend the functionality, given user intervention, that other links on the Landing Pages can be sent to Google Translate for webpage translation.

We decided to …

Add two new global variables

var uprefix='';
var usuffix='';
For two iframes add id attribute …

<div id=divtagcloud><iframe id=ifdtc style='display:none;' onerror='anticheckd(this);' onload='checkd(this);' src='//www.rjmprogramming.com.au/PHP/divtagcloud.html'></iframe></div>
<iframe id=ifzero onload="noandmaybe(this);" src="PHP/zero.html" title="Recent Blog Posts" style="width:264px;"></iframe>
Change function ChangeLCodeNow …

function ChangeLcodeNow(){
//<![CDATA[
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1) && val.value != val.value.trim()) {
usuffix=usuffix.split('&obsolete=')[0];
document.getElementById('ifzero').src+='?random=' + Math.floor(Math.random() * 198767543); //alert(usuffix);
if (document.getElementById('divtagcloud') && !document.getElementById('ifdtc')) {
document.getElementById('divtagcloud').innerHTML="<iframe id=ifdtc style='display:none;' onerror='anticheckd(this);' onload='checkd(this);' src='PHP/divtagcloud.html?random=" + Math.floor(Math.random() * 198767543) + "'></iframe>";
} else {
document.getElementById('ifdtc').src+='?random=' + Math.floor(Math.random() * 198767543); //alert(usuffix);
}
} else if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var srectis=val.getBoundingClientRect();
var pprefix = val[val.selectedIndex].id;
var dd=new Date();
var wdg=val[val.selectedIndex].innerHTML;
uprefix='https://www-rjmprogramming-com-au.translate.goog';
usuffix='?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value.trim() + '&_x_tr_pto=wapp&obsolete=y';
if (1 == 1) {
//alert('<span style="position:absolute;top:' + srectis.top + 'px;left:' + srectis.left + 'px;">' + val[val.selectedIndex].innerHTML + ' <input type=checkbox onchange="usuffix=usuffix.split(' + "'" + '&obsolete=' + "'" + ')[0];"></input> Everywhere </span>');
if (1 == 2) {
document.body.innerHTML=document.body.innerHTML.replace(val.outerHTML, '<span style="z-index:123;position:absolute;top:' + srectis.top + 'px;left:' + srectis.left + 'px;">' + val[val.selectedIndex].innerHTML + ' <input type=checkbox onchange="usuffix=usuffix.split(' + "'" + '&obsolete=' + "'" + ')[0];"></input> Everywhere </span>');
} else {
document.getElementById('language').innerHTML='<option value="' + val.value.trim() + '" selected>' + wdg + '</option><option value="' + val.value.trim() + ' ">' + wdg + ' (everywhere)</option>';
document.getElementById('language').size='2';
}
window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp', '_blank');
} else {
window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp', '_blank');
document.getElementById('langone').innerHTML=val[val.selectedIndex].innerHTML + ' (and reclick for other translations)';
document.getElementById('langone').title=document.getElementById('langone').innerHTML;
val.title=document.getElementById('langone').innerHTML;
document.getElementById('langone').onclick = function(evt) { usuffix=usuffix.split('&obsolete=')[0]; this.innerHTML=this.innerHTML.split('(')[0] + '(everywhere)'; };
val.value='';
}
}
//]]>
}
Change function mwo …

function mwo(in_url) {
// https://www.rjmprogramming.com.au/ITblog/css-countdown-reveal-tutorial/?pp&pn&title=CSS_Countdown_Reveal_Tutorial
//alert(in_url);
if (in_url.indexOf('&title=') != -1 && in_url.indexOf('?p=') != -1 && in_url.indexOf('rjmprogramming.com.au/') != -1) {
var tis=in_url.split('&title=')[1].split('&')[0].split('#')[0].replace(/\_/g,'-').toLowerCase();
var ptis=in_url.split('?p=')[1].split('&')[0].split('#')[0];
if (isiPad || isiPhone || isiPod || isAndroid) {
if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var inurl=in_url.split('?')[0] + in_url.split('&title=')[1].toLowerCase().replace(/\_/g,'-');
//alert(inurl);
return inurl.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
//return (in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis).replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix + '#post-' + ptis + '#andabit=-70';
//} else if (usuffix != '' && usuffix.indexOf('&obsolete=') != -1) {
//var inurl=in_url.split('?')[0] + in_url.split('&title=')[0].toLowerCase().replace(/\_/g,'-');
//return inurl.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
} else {
return in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis + '#post-' + ptis + '#andabit=-70';
}
} else if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var inurl=in_url.split('?')[0] + in_url.split('&title=')[1].toLowerCase().replace(/\_/g,'-');
//alert(inurl);
return inurl.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
//return (in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis).replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix; // + '#post-' + ptis;
} else {
return in_url.split('rjmprogramming.com.au/')[0] + 'rjmprogramming.com.au/ITblog/' + tis; // + '#post-' + ptis;
}
} else if (usuffix != '' && usuffix.indexOf('&obsolete=') != -1) {
return in_url.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
} else {
return in_url;
}
}
Change function windowopen …

function windowopen(myurl,mytarget) {
if (isiPad || isiPhone || isiPod) {
var aobod = document.getElementById('abod');
aobod.href=mwo(myurl);
aobod.click();
} else if (isAndroid) {
top.window.open(mwo(myurl),mytarget);
} else if (usuffix.indexOf('&obsolete=') == -1 && usuffix != '') {
top.window.open(mwo(myurl),mytarget);
} else {
top.window.open(myurl,mytarget);
//location.href=myurl;
}
}
For two iframes change onload event functionalities

function checkd(iois) {
if (iois != null) {
var aconto = (iois.contentWindow || iois.contentDocument);

if (aconto != null) {

if (aconto.document) { aconto = aconto.document; }

if (aconto.body != null) {

if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var wasabi=aconto.body.innerHTML;
var qps=wasabi.split('?p=');
var iqps=0;
var insr='';
qps=wasabi.split(' href="');
for (iqps=1; iqps<qps.length; iqps++) {
insr=qps[iqps].split('"')[0];
wasabi=wasabi.replace(insr, insr.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix);
}
aconto.body.innerHTML=wasabi;
if (divtc != '') { divtc=wasabi; }
} else {

divtc=aconto.body.innerHTML;
}
if (divtc.indexOf(' class="tagcloud"') != -1) {
setTimeout(divtctoggler, 8000);
} else {
document.getElementById('divtagcloud').innerHTML='';
}
}
}
}
}

function noandmaybe(iois) {
var aconto=null, jps=[];
if ((usuffix != '' && usuffix.indexOf('&obsolete=') == -1) || !navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) { // or it is not a mobile device
if (iois != null) {
aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
aconto.body.innerHTML=aconto.body.innerHTML.replace(/\#andabit\=\-70/g,'');
}
if (usuffix != '' && usuffix.indexOf('&obsolete=') == -1) {
var wasabi=aconto.body.innerHTML;
var qps=wasabi.split('?p=');
var iqps=0;
var insr='';
for (iqps=1; iqps<qps.length; iqps++) {
wasabi=wasabi.replace('?p=' + qps[iqps].split('"')[0], qps[iqps].split(' alt="')[1].split('"')[0].toLowerCase().replace("+","").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(/---/g,"-").replace(/--/g,"-") + '/');
}
qps=wasabi.split(' href="');
for (iqps=1; iqps<qps.length; iqps++) {
insr=qps[iqps].split('"')[0];
wasabi=wasabi.replace(insr, insr.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix);
}
aconto.body.innerHTML=wasabi;
for (iqps=1; iqps<=5; iqps++) {
insr=document.getElementById('adiv' + iqps).outerHTML;
wasabi=insr.replace('?p=' + insr.split('?p=')[1].split('"')[0], insr.split(' title="')[1].split('"')[0].toLowerCase().replace("+","").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace("/","").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(" ","-").replace(/---/g,"-").replace(/--/g,"-") + '/');
document.getElementById('adiv' + iqps).href=wasabi.split(' href="')[1].split('"')[0].replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix;
}
var asis=document.getElementsByTagName('a');
for (iqps=0; iqps<asis.length; iqps++) {
if (('' + asis[iqps].href).toLowerCase().indexOf('rjmprogramming.com.au') != -1) {
asis[iqps].href=(asis[iqps].href.replace('http://www.rjmprogramming.com.au', uprefix).replace('https://www.rjmprogramming.com.au', uprefix).replace('//www.rjmprogramming.com.au', uprefix).replace('http://rjmprogramming.com.au', uprefix).replace('https://rjmprogramming.com.au', uprefix).replace('//rjmprogramming.com.au', uprefix).split('#')[0].split('?')[0] + usuffix).replace('/wordpress/','/ITblog/');
}
}
}

}
}
}

if (document.getElementById('style_3') && ('' + document.getElementById('style_3').title) == '') {
if (!aconto) {
aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
}
}

var omover=' onmouseover="omright(this);" ', omout=' onmouseout="moright(this);" ', bdapp='<table id=tblr style=display:none><tr></tr></table>';
var rdbit='?rand=' + Math.floor(Math.random() * 1985676);
if (aconto) {
if (aconto.body != null) {
if (document.getElementById('p_style_3')) {
document.getElementById('style_3').innerHTML=document.getElementById('p_style_3').outerHTML.replace(/\.jpg/g, '.jpg' + rdbit);
}
var hrefs=aconto.body.innerHTML.split(' href=');
var style_3r=document.getElementById('style_3').getBoundingClientRect();
document.getElementById('style_3').title='Feel free to visit thumbnail links to our WordPress Tutorial blog!';
for (var ihrefs=1; ihrefs<hrefs.length; ihrefs++) {
//document.body.innerHTML+='<div id=ediv' + ihrefs + '></div>';
bdapp=bdapp.replace('</tr>', '<td id=ediv' + ihrefs + '></td></tr>');
jps=hrefs[ihrefs].split('.jpeg?rand=');
console.log(jps[0].slice(-9));
if (jps[0].slice(-3).indexOf('-') != -1) { jps[0]=jps[0].split('-')[eval(-2 + eval('' + jps[0].split('-').length))]; }
switch (jps[0].slice(-3)) {
case 'ght':
document.body.innerHTML+='<a id=adiv5' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/eight.jpg' + rdbit + ');position:absolute;z-index:99;top:' + style_3r.top + 'px;width:30px;height:20px;background-color:transparent;left:' + style_3r.left + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'ven':
document.body.innerHTML+='<a id=adiv4' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/seven.jpg' + rdbit + ');position:absolute;z-index:99;top:' + style_3r.top + 'px;width:30px;height:20px;background-color:transparent;left:' + eval(eval(eval(style_3r.left + style_3r.right) / 2) - 15) + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'six':
document.body.innerHTML+='<a id=adiv3' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/six.jpg' + rdbit + ');position:absolute;z-index:99;top:' + style_3r.top + 'px;width:30px;height:20px;background-color:transparent;left:' + eval(style_3r.right - 30) + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'ive':
document.body.innerHTML+='<a id=adiv2' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/five.jpg' + rdbit + ');position:absolute;z-index:99;top:' + eval(style_3r.bottom - 20) + 'px;width:30px;height:20px;background-color:transparent;left:' + style_3r.left + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


case 'our':
document.body.innerHTML+='<a id=adiv1' + omover + omout + ' target=_blank style="opacity:0.5;background-repeat:no-repeat;background-size:30px 20px;background-image:url(/PHP/four.jpg' + rdbit + ');position:absolute;z-index:99;top:' + eval(style_3r.bottom - 20) + 'px;width:30px;height:20px;background-color:transparent;left:' + eval(style_3r.right - 30) + 'px;" title="' + hrefs[ihrefs].substring(1).split(' title=')[1].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '" href="' + hrefs[ihrefs].substring(1).split(hrefs[ihrefs].substring(0,1))[0] + '"></a>';
break;


default:
break;
}
}
document.body.innerHTML+=bdapp;
bodyrect=document.getElementById('nav_layer').getBoundingClientRect();
}
}
}
}

Feel free to try, coming off a new “(everywhere)” appended dropdown option a user can select!


Previous relevant Google Translate Landing Page Changed Interfacing Tutorial is shown below.

Google Translate Landing Page Translate Changed Interfacing Tutorial

Google Translate Landing Page Changed Interfacing Tutorial

It pays to keep in touch with third party arrangements you have in place, as for the recent Google Translate Landing Page Translate Updated List Tutorial‘s interfacing to the great Google Translate resource capable of translating our RJM Programming blog (via Landing page language dropdown (select) element up the top right) to non-English languages.

But two interfacing to Google Translate aspects have changed since we had occasion to “see how this was going” (oops!)

  1. enforcing https: protocol … and …
  2. extra &_x_tr_pto=wapp to arguments … as per old versus new Landing Page Javascript code arrangements …

    function oldChangeLcodeNow(){
    //<![CDATA[
    var val = document.getElementById('language');
    if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
    var pprefix = val[val.selectedIndex].id;
    var dd=new Date();
    window.open('//www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_blank');
    }
    //]]>
    }



    function ChangeLcodeNow(){
    //<![CDATA[
    var val = document.getElementById('language');
    if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
    var pprefix = val[val.selectedIndex].id;
    var dd=new Date();
    window.open('https://www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value + '&_x_tr_pto=wapp', '_blank');
    }
    //]]>
    }

… linking the user picking a non-English language off the dropdown element be able to translate that day’s latest RJM Programming blog post into that language via Google Translate. Thanks heaps!


Previous relevant Google Translate Landing Page Translate Updated List Tutorial is shown below.

Google Translate Landing Page Translate Updated List Tutorial

Google Translate Landing Page Translate Updated List Tutorial

Yesterday’s Google Translate Landing Page Translate Update Tutorial left off with …

It’s the start that does not ingrain the webpage HTML to any great permanence, and that is for another “PHP involvement” day.

… and that new day is upon us. Whenever you combine …

  • PHP writing public HTML webpage data … with …
  • a user interface (and we’d really only like that “user set” to be an administrator of this blog)

… it’s a potential data security issue you are opening up, and yet, we do want to involve some automation of webpage code here for something that can be ascertained. So let’s try to protect ourselves (to some degree) regarding the PHP below …

<?php

if (isset($_POST['langih']) && strpos(strtolower('' . $_SERVER['HTTP_REFERER']), "rjmprogramming.com.au/about_us.html") !== false) {
$prefis="./";
$ftf=["index.htm","index.html","indexmobile.html","About_Us.html","Contact_Us.html","Guestbook.html","Link.html","Links.html","Services.html","Welcome.html","News.html","Welcome.htm","Welcomeslideshow.htm","Welcomeslideshow.html","slideshow.html"];
$lih=str_replace("+", " ", urldecode($_POST['langih']));
if (strpos("~" . strtolower($lih), "~<option") !== false) {
if (strpos(strtolower($lih) . "~", "</option>~") !== false) {
if (strpos($lih, ">Blog Language") !== false) {



for ($i=0; $i<sizeof($ftf); $i++) {
if (file_exists($prefis . $ftf[$i])) {
$cont=file_get_contents($prefis . $ftf[$i]);
if (strpos($cont, ">Blog Language") !== false) {
if (strpos(str_replace("<option","",str_replace("</option>","",strtolower($lih))), "<") === false) {
if (strlen(explode("</select>", explode(">Blog Language", $lih)[1])[0]) > strlen($wasis)) {
if (sizeof(explode(">",explode("</select>", explode(">Blog Language", $lih)[1])[0])) >= sizeof(explode(">",$wasis))) {

file_put_contents($prefis . $ftf[$i] . "_spare", $cont);
$wasis=explode("</select>", explode(">Blog Language", $cont)[1])[0];
$contnew=str_replace($wasis, explode("</select>", explode(">Blog Language", $lih)[1])[0], $cont);
file_put_contents($prefis . $ftf[$i], $contnew);
}
}
}
}
}
}


}
}
}

}
exit;

?>

… restricting calling URLs and some of the look and size and content of the posted data, and working with the “About Us” webpage “place” to automate, the idea of choosing “English” from the “Blog Language” dropdown, as per the changed Javascript and Ajax “way in”


function ChangeLcodeNow(){
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var pprefix = val[val.selectedIndex].id;
var dd=new Date();
window.open('//www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_blank');
} else if (val.value.length != 0 && val.value.indexOf('en') != (0 - 1)) {
if (ajaxitp) { ajaxitp(); }
}

}

function ajaxitp() {
var xurl = './getme.php';
var formis = new FormData();
myxhr = new XMLHttpRequest();
if (myxhr) {
formis.append('langih', document.getElementById('language').innerHTML);
myxhr.open('POST', xurl); //, true);
myxhr.send(formis);
}
}


Previous relevant Google Translate Landing Page Translate Update Tutorial is shown below.

Google Translate Landing Page Translate Update Tutorial

Google Translate Landing Page Translate Update Tutorial

The recent Google Translate Landing Page Translate Tutorial

… and so, we are here today, with our start to remedies for this (Javascript DOM, via Ajax, change below) …


var myxhr=null;

function backin() {


if (myxhr.readyState == 4) {
if (myxhr.status == 200) {
if (myxhr.responseText) {
if (document.getElementById('language')) {
//alert(myxhr.responseText);
var mhs=myxhr.responseText.replace(/\<\/code\>\<\/td\>/g,'<>').split('><code translate="no" dir="ltr">');
if (mhs.length > 1) {
var thiscodeis='', thisdescis='';
var wasih=document.getElementById('language').innerHTML;
var outih=wasih.split('</option>')[0] + '</option>';
var origih=wasih.replace(outih, '');
for (var iuh=1; iuh<mhs.length; iuh++) {
thisdescis=mhs[eval(-1 + iuh)].split('<td>')[eval(-1 + mhs[eval(-1 + iuh)].split('<td>').length)];
//console.log('first thisdescis=' + thisdescis + ' and mhs[eval(-1 + iuh)]=' + mhs[eval(-1 + iuh)].slice(-200));
thisdescis=thisdescis.split('<')[0];
thiscodeis=mhs[iuh].split('<')[0].split('(')[0].trim();
//console.log('thiscodeis=' + thiscodeis + ' and thisdescis=' + thisdescis + ' and mhs[eval(-1 + iuh)]=' + mhs[eval(-1 + iuh)].slice(-200));
if (wasih.toLowerCase().indexOf(' value="' + thiscodeis.toLowerCase() + '"') == -1 && wasih.toLowerCase().indexOf(thisdescis.toLowerCase()) == -1) {
outih+='<option value="' + thiscodeis + '">' + thisdescis + ' &#10024;</OPTION>';
} else {
outih+='<option value="' + thiscodeis + '">' + thisdescis + '</OPTION>';
}
}
if (outih.indexOf('/OPTION') != -1 && origih.toLowerCase() != outih.toLowerCase()) {
document.getElementById('language').innerHTML=outih.replace('</option>', ' &#10024;</OPTION>');
document.getElementById('language').style.maxWidth='150px';
}
}
}
}
}
}
}

function ajaxit() {
var xurl = '//cloud.google.com/translate/docs/languages';
//alert(1);
myxhr = new XMLHttpRequest();
if (myxhr) {
//alert(2);
myxhr.onreadystatechange = backin;
myxhr.open('GET', 'getme.php?getme=' + encodeURIComponent(xurl), true);
myxhr.send(null);
}
}

function refreshl() {
if (document.getElementById('language')) {
ajaxit();
}
}

setTimeout(refreshl, 5000);

It’s the start that does not ingrain the webpage HTML to any great permanence, and that is for another “PHP involvement” day.


Previous relevant Google Translate Landing Page Translate Tutorial is shown below.

Google Translate Landing Page Translate Tutorial

Google Translate Landing Page Translate Tutorial

Yesterday’s …

  • Google Translate Webpage Translate Tutorial was the major part of RJM Programming’s Google Translate strategy change (ie. getting it working again … doh!) … but it’s not the whole story … and another part is …
  • today we extend that strategy to change the RJM Programming Landing Page Google Translate interfacing to change from a “Landing Page content” strategy to a “Navigate to WordPress Blog” strategy (feeding into yesterday’s thinking), our justification being that the better content of the RJM Programming domain sits within the WordPress Blog we support and maintain

… so there, ngarrrrgh!

But (growing up quickly) we see a better arrangement here, just adding the prefix “Blog” onto the old (just) “Language” labelled dropdown to modify the “new “Blog Language” (to end up with HTML snippet <option value=””>Blog Language</option>) dropdown’s Javascript “onchange” event logic …


// To ...
function ChangeLcodeNow(){
//<![CDATA[
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var pprefix = val[val.selectedIndex].id;
var dd=new Date();
window.open('//www-rjmprogramming-com-au.translate.goog/ITblog/' + dd.getFullYear() + '/' + ('0' + eval(1 + eval('' + dd.getMonth()))).slice(-2) + '/' + ('0' + eval(0 + eval('' + dd.getDate()))).slice(-2) + '/?_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_blank');
}
//]]>
}


// ... From ...
function olderChangeLcodeNow(){
//<![CDATA[
var val = document.getElementById('language');
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
var pprefix = val[val.selectedIndex].id;
windowopen('http://translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Findex.html&tl=' + val.value, '_blank');
}
//]]>
}

Again, not too onerous!


Previous relevant Google Translate Webpage Translate Tutorial is shown below.

Google Translate Webpage Translate Tutorial

Google Translate Webpage Translate Tutorial

We really like the way Google Translate can language translate whole webpages for URLs of choice, sometimes. We use it here at this blog, but sometime into the past … we cannot recall (sorrrrrryyyyyyyyy!) … the arrangements of use of this great functionality changed, and today we want to go over what we did for this blog to fix some of this interfacing.

It was in good ol’ WordPress TwentyTen theme’s header.php we made the change to facilitate this “reconnection” to this great functionality …

<?php

function ChangeLcodeNow(){
var val = document.getElementById('language');
//alert(val.value);
if (val.value.length != 0 && val.value.indexOf('en') == (0 - 1)) {
//alert(val.value);
var pprefix = val[val.selectedIndex].id;
<?php
$p316 = "316";
$pprefix = "";
if (strpos($_SERVER['QUERY_STRING'], "p=0") !== false) {
$pprefix = "";
} else {
if (isset($_GET['p'])) {
if (strpos($_GET['p'], "304") !== false) {
$p316 = "316";
} else {
$p316 = $_GET['p'];
}
}

$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPad');
if ($isiPad === false) {
$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPhone');
}
if ($isiPad === false) {
$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'Android');
}

if (1 == 1) { // _x_tr_sl=en&_x_tr_tl=de&_x_tr_hl=en-GB&_x_tr_pto=nui
echo " window.open('//www-rjmprogramming-com-au.translate.goog/ITblog?p=' + pprefix + '&_x_tr_sl=en&_x_tr_hl=en-GB&_x_tr_pto=nui&_x_tr_tl=' + val.value, '_top'); " . "\n";
} else {

if ($isiPad) {
//echo " window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value, '_top'); " . "\n";
echo " window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value, '_top'); " . "\n";
} else {
//echo "window.location.href = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
echo "window.location.href = '//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress%2F%3Fp%3D' + pprefix + '".$p316."&tl=' + val.value; " . "\n";
}
}
}
?>
//window.open('//translate.google.com/translate?sl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.rjmprogramming.com.au%2Fwordpress&tl=' + val.value, '_blank');
//alert("yes" + val.value);
}
}

?>

Not too bruising!

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


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


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


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


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


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


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

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

Renaming to Aid with Numerical File Sorts AlmaLinux Command Line Tutorial

Renaming to Aid with Numerical File Sorts AlmaLinux Command Line Tutorial

Renaming to Aid with Numerical File Sorts AlmaLinux Command Line Tutorial

We wanted to revisit the File Renaming Web Application of Renaming to Aid with Numerical File Sorts Command Line and Curl Tutorial to see if there are any “moving from” …

  • CentOS Apache PHP version starting with a 5 … to …
  • AlmaLinux Apache PHP version starting with an 8

… issues with the PHP. A mute point, though, as we were reminded during our testing, because we made this web application inactive, probably quite wisely, on our live rjmprogramming.com.au version, so the testing was more that we didn’t stuff up the still actively working “download to a local Apache/PHP/MySql web server such as MAMP” mode of use. Spoiler alert … no muck up! So, what did we learn? Trivial, but …

<?php

if ($argv) {
// do a command line usage set of commands ...


// ... until here
}

?>

… is better expressed as

<?php

if (isset()$argv)) {
// do a command line usage set of commands ...


// ... until here
}

?>

… to avoid errors in a tweaked rename_to_aid_sorting.php we recommend for use on a local Apache/PHP/MySql web server such as MAMP, as mentioned above.


Previous relevant Renaming to Aid with Numerical File Sorts Command Line and Curl Tutorial is shown below.

Renaming to Aid with Numerical File Sorts Command Line and Curl Tutorial

Renaming to Aid with Numerical File Sorts Command Line and Curl Tutorial

Yesterday’s Renaming to Aid with Numerical File Sorts Actions Tutorial had good interaction characteristics, in our books (… but as of this news bulletin, not in our pamphlettes and we hope to resume normal transmission forthwith like …) but, out of PHP’s three modes of use (which we talked about at CSH/KSH/PHP Numerical Bubble Sort Tutorial) …

  • Surfing the Net … is very interactive and we can use HTML form elements for navigation purposes … for example, URL (on local MAMP (Mac) Apache/PHP/MySql web server) … http://localhost:8888/rename_to_aid_sorting.php?dirone=.%2F&dirtwo=Django_Python-&asteriskybit=%5B0123456789%5D*.* … but more than likely the environment where users will think to use this PHP application is via …
  • Command Line Usage … for example, be in MAMP’s /Applications/MAMP/htdocs/ directory with … php rename_to_aid_sorting.php ./Django_Python- # or …
  • Curl Usage … for example, be in MAMP’s /Applications/MAMP/htdocs/ directory with … curl http://localhost:8888/rename_to_aid_sorting.php?inspec=./Django_Python- # you can see in action below …

Up near the top of the code processing input parameters the PHP code differentiation goes …


if (isset($_GET['inspec']) && !isset($_GET['dirone']) && !isset($_GET['dirtwo'])) { // reserved for curl instructions
// Curl usage is hard to differentiate from "Surfing the Net" ... they both ask for a URL whereas Command Line has arguments ... so sometimes Curl usage is best
// organized with one $_GET[] (for us $_GET['inspec']) and limit it to just the one. Why so? Well, "&" on command line is awkward.
// To involve more than one argument in Curl use an internal delimitation character like ^ or ! perhaps to proceed. We were able to just keep it to one today.
//
// ... curl argument processing code goes here
//
} else if ($argv) { // command line usage
//
// ... command line argument processing code goes here
//
} else { // surfing the net usage
//
// ... surfing the net argument processing code goes here
//
}

… and down near the bottom, differentiation regarding the look of the outputs, it goes …


if ($argv || (isset($_GET['inspec']) && !isset($_GET['dirone']) && !isset($_GET['dirtwo']))) { // command line or curl ... just show commands for user to try or not ... they may want a pipe like " | tee do_these_renames.ksh" (and then follow up "ksh -x do_these_renames.ksh")
$outp="";
if (strpos(strtoupper(('' . PHP_OS)), "WINDOW") !== false) {
$lines=explode("\nren" . "ame ");
for ($oi=1; $oi<sizeof($lines); $oi++) {
$outp.="ren" . "ame " . explode("\n", $lines[$oi])[0] . "\n";
}
} else {
$lines=explode("\nm" . "v ",$htmlis);
for ($oi=1; $oi<sizeof($lines); $oi++) {
$outp.="m" . "v " . explode("\n", $lines[$oi])[0] . "\n";
}
}
echo $outp;
} else { // surfing the net form interactions below
echo $htmlis;
}

If you watch the video above, you’ll see us touching on some piping ideas too, with respect to Command Line and Curl modes of use, taking place at the command line. These modes of use just output a set of operating system proposed rename (or non-Windows mv) commands to achieve the same default decisions the Surfing the Net program first shows after you Click/Touch the “Analyze” button. These commands have not been done by the application, as we leave this up to the user, as much as anything because the joys of piping can be used. Take a look at

  • Command Line Usage … for example, be in MAMP’s /Applications/MAMP/htdocs/ directory with … php rename_to_aid_sorting.php ./Django_Python- | tee do_renames.ksh # or …
  • Curl Usage … for example, be in MAMP’s /Applications/MAMP/htdocs/ directory with … curl http://localhost:8888/rename_to_aid_sorting.php?inspec=./Django_Python- | tee do_renames.ksh # you can see in action below …

To make these (default) renamings happen (and now the operating system will supply any error messages, and here, we use our favourite scripting shell on non-Windows …ksh … Korn Shell) …


ksh -x do_renames.ksh

For Windows …

  • Command Line Usage … for example, be in MAMP’s /Applications/MAMP/htdocs/ directory with … php rename_to_aid_sorting.php ./Django_Python- > do_renames.bat # or …
  • Curl Usage … for example, be in MAMP’s /Applications/MAMP/htdocs/ directory with … curl http://localhost:8888/rename_to_aid_sorting.php?inspec=./Django_Python- > do_renames.bat # you can see in action below …

To make these (default) renamings happen, opening the Windows command line application (and now Window’s command line (DOS) operating system will supply any error messages) …


do_renames.bat

The third draft of rename_to_aid_sorting.php, that changed this way, can be tried, by you, at this, still, “forlornly functional, but still showing Analysis phase” (as we outlined with yesterday’s Renaming to Aid with Numerical File Sorts Primer Tutorial) live run link. Its real power, though, is by you downloading it to a local web server environment such as MAMP supplies and code and test things yourself. Feel free.

Did you know?

What is behind how PHP performs the operating system renaming commands … (good ol’) …


exec(urldecode($_POST['cmd']));

Notice “the home of PHP”‘s webpage’s blurb about alternatives …

system() – Execute an external program and display the output
passthru() – Execute an external program and display raw output
escapeshellcmd() – Escape shell metacharacters
pcntl_exec() – Executes specified program in current process space
backtick operator

… and you might be interested in I.T. “land” with the word fork fork fork fork fork fork fork pork … aah … fork.


Previous relevant Renaming to Aid with Numerical File Sorts Actions Tutorial is shown below.

Renaming to Aid with Numerical File Sorts Actions Tutorial

Renaming to Aid with Numerical File Sorts Actions Tutorial

Ah, that’s the thing! “Actions” sounds good’n’all but … and didn’t you … we can’t let anybody loose with a “fully functional” live run to the RJM Programming web server with this renaming web application. We’ll just have to show you what the same codebase produces on our local MAMP (Mac) Apache/PHP/MySql web server in “fully functional” form.

Happily, our second draft of rename_to_aid_sorting.php, that changed this way, can be tried, by you, at this “forlornly functional, but still showing Analysis phase” (as we outlined with yesterday’s Renaming to Aid with Numerical File Sorts Primer Tutorial) live run link.

So after an initial phase of imagining how to resist bad usage thoughts, there were also more things to consider when allowing for real operating system rename commands (or mv on non-Windows operating systems), such as …

  • error (and status) messaging … related to
    1. input file does not exist
    2. output file already exists
    3. rename fails
    4. (else mention if successful)
  • individual checkboxes to allow for individual renamings (which happen at an HTML iframe “child” run of the same codebase PHP that performs an exec rename call from the (relevant) operating system (though we could have used PHP’s rename command to not have to differentiate via operating system, this way), the PHP’s way to tell happening via PHP_OS global)
  • overall checkbox to allow for any non-checked individual checkboxes to be clicked in a batch … and if so …
    1. stagger the timing of it happening so user can read a status message between setTimeout controlled renamings
    2. give a report on the overall run at the end of this run
    3. show progress via cursor:progress; on the overall checkbox going back to cursor:pointer; at the finish
  • control of the individual checkbox “checked” look happens at that HTML iframe’s onload event “Client Pre-Emptive Iframe” inspired logic
  • after a successful rename ensure no bad repeated action, by use of [HTMLinputTextElement].readOnly=true on middle textbox and [HTMLinputCheckboxElement].style.display=’none’ on right hand side checkbox
  • spaces in filenames requires double quoting delimitation

It’s amazing how much extra thought you need to put into procedural web applications like this, because the user needs follow up information in a real sense.

Did you know?

What is behind how PHP takes the input entries and obtains a set of file names (we refer to as “input” files above)? It’s done via one of our favourite PHP functions … (good ol’) …


foreach (glob($dprefix . $asteriskybit) as $filename) {
// process $filename here
}

Notice its abilities as far as wildcards go … * (for any number of character) and ? (for one character) and [0123456789] (we use in this project, for one counting number character).


Previous relevant Renaming to Aid with Numerical File Sorts Primer Tutorial is shown below.

Renaming to Aid with Numerical File Sorts Primer Tutorial

Renaming to Aid with Numerical File Sorts Primer Tutorial

It’s not just the operating systems that throw up issues regarding file names with numerical parts to them that when displayed get sorted alphabetically, but you’d like it either …

  • numerically … or …
  • a hybrid of numerically and alphabetically

We’re not there yet … but “are we there yet”, now? … but we’re starting down the road to this with some PHP we’re developing. This might be useful as a tool because sometimes with real work, you could be talking about hundreds of files needing renaming either to …

  • suit some procedural (process) that is looking for the numbers to determine order, and yet uses defaulting file sorting algorithms … ie. what we are talking about today is a program to make it that both are satisfied, so long as the procedure doesn’t mind filenames being changed this way, to still work
  • annoyance factor issues, the one that springs to mind for me being the assembly of some images that we use Mac OS X desktop application Preview to use to assemble into a PDF slideshow via being in the Mac OS X Finder and highlighting our files and running into the alphabetic/numerical sort conundrum … annoyance only? … by that I mean, you can fix this at Preview, so it rates as an “annoyance” only

What’s involved? Lots … think of this in terms of prefixing the correct number of “0”‘s (ie. zeroes) in the right place of the filename …

  • the file extension … we decide not to cross across file extensions with our mini-renaming-rule sets
  • the number of delimited sets before the period (ie. dot “.”) of the file extension … we decide not to cross across “file extension/number of delimited sets before the period”s with our mini-renaming-rule sets
  • the delimiter itself before the period (and if none, call it the period) … we decide not to cross across “file extension/number of delimited sets before the period/delimiter”s with our mini-renaming-rule sets
  • how many “delimited sets before the period” to apply the renaming logic attempts onto … we’ve decided just the first for now
  • what about non-numerical and non-delimiter characters before the period … hand me the Bex, will you?!

Our first draft of rename_to_aid_sorting.php can be tried, by you, at this live run link.

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


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


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


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

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

WordPress Blog Course via Landing Page Design Tutorial

Wordpress Blog Course via Landing Page Design Tutorial

Wordpress Blog Course via Landing Page Design Tutorial

We had occasion to revisit our inhouse “Design a Course” PHP web application we talked about at WordPress Blog Course via Landing Page Topic Tutorial. It is commonplace on “revisits” to see ways to improve, and this “revisit” was no different.

The first, what we’d categorize as an annoyance, using it was the lack of a designed “back button” equivalent, so that a user does not have to figure this out for themselves, useful for when the multiple selection dropdown page displays, and the user may want to go back to the previous initial webpage.

<?php

<a target=_self href=./design_a_course.php title=Back>Cou</a><a target=_blank href=./design_a_course.php title=New>rse</a> Name:

?>

We thought that when the user gets to that multiple selection dropdown page we saw that a double click on the dropdown caused some more content to show, but for non-mobile onmouseover and for any onclick events associated with the dropdown option elements we should do more over to the right where nothing was happening before, via, in the HTML, encasing the page content within a new table element consisting of two cells, the right hand one (id=’tdright’) …

<?php

echo "<html><head><script type='text/javascript'> var isonclick=1; var multi=1; var comma=''; " . $ctn . " </script><title>Ask About Course</title></head><body style='background-color:lightgray;'>" . $bodyi . "<table id=mytable style=width:100%;><tr id=mytr><td id=tdleft style=vertical-align:top;width:70%;><h1 id=myh1 align='center'>" . $thetopic . " Course Designer</h1><h3 id='sofar'></h3><br><form align='center' action='./design_a_course.php?show=y' method='POST'><input type='hidden' name='courselsq' id='courselsq' value=''></input><input type='hidden' name='coursesq' id='coursesq' value=''></input><a target=_self href=./design_a_course.php title=Back>Cou</a><a target=_blank href=./design_a_course.php title=New>rse</a> Name: <input type='text' style='display:block;' name='coursename' id='coursename' value='" . $topics[0] . "'></input><br><div id='list' style='display:none;'>" . via("") . "</div><select title='Tutorials for course ... you can double click for a preview of any one tutorial below when in Multiple selection mode' id='bc' onchange=' if (multi == 1) { multi = 0; document.getElementById(\"topic\").innerHTML = document.getElementById(\"topic\").innerHTML.replace(/size=20 multiple/g, \"\"); } else { multi=1; document.getElementById(\"topic\").innerHTML = document.getElementById(\"topic\").innerHTML.replace(/select /g, \"select size=20 multiple \"); } '><option value='Multiple'>Multiple (entry mode below)</option><option value='Single'>Single (has advantage that date order can be changed)</option></select><div id='topic' style='display:block;'>" . str_replace("ChangeTutNow(this);", " if (multi == 0) { var ahuh=this.value.split(\"=\"); if (ahuh[ahuh.length - 1] != \"\") { var bhuh=ahuh[1].split(\"&\"); document.getElementById(\"coursesq\").value = document.getElementById(\"coursesq\").value + comma + bhuh[0]; document.getElementById(\"courselsq\").value = document.getElementById(\"courselsq\").value + comma + ahuh[ahuh.length - 1].replace(/_/g, \" \"); document.getElementById(\"sofar\").innerHTML = document.getElementById(\"sofar\").innerHTML + \"<\" + \"br\" + \">\" + ahuh[ahuh.length - 1].replace(/_/g, \" \"); document.getElementById(\"topic\").innerHTML = document.getElementById(\"topic\").innerHTML.replace(ahuh[ahuh.length - 1],\"\").replace(ahuh[ahuh.length - 1],\"\"); comma=\",\"; } } ", via($topics[0])) . "</div><br><br><input onclick='return(ChangeTutNow(document.getElementById(\"" . $thetopic . "tuts\")));' onmouseover=' isonclick=0; ChangeTutNow(document.getElementById(\"" . $thetopic . "tuts\")); isonclick=1; ' align='center' type='submit' name='submit' id='submit' value='Create Your " . $thetopic . " Course Design'></input></form>" . "<h3 id='sofar1'></h3></td><td id=tdright style=vertical-align:top;></td></tr></table></body></html>";

?>

… ready to contain blog content via Javascript DOM logic associated with those events talked about above …

<?php echo ”

var lasturl='';

function wopen(oopt) {
var ooptouterHTML=oopt.outerHTML.replace(/\&quot\;/g,'\"');
if (ooptouterHTML.indexOf('windowopen(') != -1) {
var pone=ooptouterHTML.split('windowopen(')[1].substring(1).split(ooptouterHTML.split('windowopen(')[1].substring(0,1))[0];
if (pone.indexOf('title=') != -1 && pone.indexOf('?') != -1) {
document.getElementById('tdright').innerHTML='<iframe style=width:100%;height:90vh; src=\"' + pone.split('?')[0] + pone.split('title=')[1].toLowerCase().replace(/\//g,'').replace(/\_/g,'-') + '#content\"></iframe>';
if (lasturl != pone) { lasturl=pone; setTimeout(function(){ window.scrollTo(0,0); }, 5000); }
} else if (pone.trim() != '') {
document.getElementById('tdright').innerHTML='<iframe style=width:100%;height:90vh; src=\"' + pone + '#content\"></iframe>';
if (lasturl != pone) { lasturl=pone; setTimeout(function(){ window.scrollTo(0,0); }, 5000); }
}
}
}

function windowopen(pone,ptwo) {
if (pone.indexOf('title=') != -1 && pone.indexOf('?') != -1) {
document.getElementById('tdright').innerHTML='<iframe style=width:100%;height:90vh; src=\"' + pone.split('?')[0] + pone.split('title=')[1].toLowerCase().replace(/\//g,'').replace(/\_/g,'-') + '#content\"></iframe>';
if (lasturl != pone) { lasturl=pone; setTimeout(function(){ window.scrollTo(0,0); }, 5000); }
} else if (pone.trim() != '') {
document.getElementById('tdright').innerHTML='<iframe style=width:100%;height:90vh; src=\"' + pone + '#content\"></iframe>';
if (lasturl != pone) { lasturl=pone; setTimeout(function(){ window.scrollTo(0,0); }, 5000); }
}
return null;
}

“; ?>

… regarding the changed design_a_course.php inhouse Course Designer web application you should feel free to (re-)try.


Previous relevant WordPress Blog Course via Landing Page Topic Tutorial is shown below.

Wordpress Blog Course via Landing Page Topic Tutorial

Wordpress Blog Course via Landing Page Topic Tutorial

Yesterday’s WordPress Blog Course via Landing Page Tutorial addressed interfacing …

  • Landing Page dropdown navigation to …
  • blog posting “thread” ideas (where those horizontal rule <hr /> elements “continue the conversation”) … but today we want to add …
  • blog posting “topic” ideas …

… by taking that (“FirstWord”) blog posting title’s “lead word” as getting us to construct a new “Suggestion” select (dropdown) element collection of relevant blog postings of a “topic”.

Think of a “lead word” like Javascript as an example. “Thread wise” the blog posting “Javascript Rectangle Analyze Follow Up Tutorial” teamed up with blog posting “Javascript Convex Polygon Analyze Tutorial” helps with context and blog posting logic flow. But the user may be interested in other blog posts where the “lead word” of the title (or “topic”) is also Javascript. We gather these blog posting “lead word” Javascript blog postings together into a “Suggestion” select (dropdown) element to overlay onto the “Next” link’s “Suggestion” (wording) hardcoding (as of yesterday’s work), as per PHP code in wp-content/themes/twentyten/functions.php off the WordPress Blog’s document root directory needing to change …

<?php

if ( ! function_exists( 'may_be_obsolete' ) ) :
/**
* Truncate unknown previous/next.
*
* @since October 2014 by RJM Programming
*/
function may_be_obsolete($proposed, $seca, $poti, $idlist) {
if (str_replace("#content","",$seca) == "") {
if (strpos($proposed, ">Previous") !== false) {
if (strpos(($proposed . "&"), "&pp=&") !== false) {
$bitsare = explode(">", $proposed);
$nums = explode("=", str_replace("&", "=", str_replace("&pp=", "", str_replace("&pn", "", str_replace("?p=", "", $proposed)))));
if ($nums[0] == $nums[1]) {
$proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
}
}
} else if (strpos($proposed, ">Next") !== false) {
if (strpos(($proposed . "&"), "&pn=&") !== false) {
$bitsare = explode(">", $proposed);
$nums = explode("=", str_replace("&", "=", str_replace("&pn=", "", str_replace("&pp", "", str_replace("?p=", "", $proposed)))));
if ($nums[0] == $nums[1]) {
$proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
}
}
}
} else if (strpos($proposed, ">Next") !== false && $poti != "") {
if ($idlist == "") { $idlist=file_get_contents(dirname(__FILE__) . "/../../../../index.html"); }
// <option id='MyNew-20200317' onclick='windowopen("//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial","_blank"); ' value='//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial'>Javascript Convex Polygon Analyze Tutorial (20200317)</option>
$ibitsx=explode(">" . $poti, $idlist);
if (sizeof($ibitsx) > 1) {
if (strpos($ibitsx[0], ">" . explode(" ", $poti)[0] . " ") !== false) {
$jbitsx=explode(">" . explode(" ", $poti)[0] . " ", $ibitsx[0]);
if (sizeof($jbitsx) > 1) {
$newt=explode(" ", $poti)[0] . " " . explode(" (", explode("</option>", $jbitsx[1])[0])[0];
$newu=str_replace("&", "&", explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0])))[-1 + sizeof(explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0]))))]);
//file_put_contents("xzc.xzc66", $proposed . "\n" . $newt . "\n" . $newu);
if (strpos($proposed, "'>") !== false && strpos($newu, "?p=") !== false) {
return explode("?p=", $newu)[1] . "'>" . explode("'>", $proposed)[1];
}
}
}
}
//file_put_contents("xzc.xzc44", $poti . "\n" . $idlist);
} else if (strpos($proposed, ">Previous") !== false && $poti != "") {
if ($idlist == "") { $idlist=file_get_contents(dirname(__FILE__) . "/../../../../index.html"); }
// <option id='MyNew-20200317' onclick='windowopen("//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial","_blank"); ' value='//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial'>Javascript Convex Polygon Analyze Tutorial (20200317)</option>
$ibitsx=explode(">" . $poti, $idlist);
if (sizeof($ibitsx) > 1) {
if (strpos($ibitsx[1], ">" . explode(" ", $poti)[0] . " ") !== false) {
$jbitsx=explode(">" . explode(" ", $poti)[0] . " ", $ibitsx[1]);
if (sizeof($jbitsx) > 1) {
$newt=explode(" ", $poti)[0] . " " . explode(" (", explode("</option>", $jbitsx[1])[0])[0];
$newu=str_replace("&", "&", explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0])))[-1 + sizeof(explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0]))))]);
//file_put_contents("xzc.xzc666", $proposed . "\n" . $newt . "\n" . $newu);
if (strpos($proposed, "'>") !== false && strpos($newu, "?p=") !== false) {
$allselect="<sel" . "ect " . str_replace("windowopen", "window.open", explode("<sel" . "ect ", $ibitsx[0])[-1 + sizeof(explode("<sel" . "ect ", $ibitsx[0]))]) . ">" . $poti . " " . str_replace("windowopen", "window.open", explode("</sel" . "ect>", $ibitsx[1])[0]) . "</sel" . "ect>";
$presel=str_replace("90%;", "200px;display:inline-block;", str_replace("ChangeTutNow(this)", "location.href=this.value;", "</a> <" . explode(">", substr($allselect,1))[0] . " onclick='event.stopPropagation();'><option value='#'>Suggestion</option>"));
$postsel="</sel" . "ect><a href=#>";
$jbitsx=explode(">" . explode(" ", $poti)[0] . " ", $allselect);
for ($jii=1; $jii<sizeof($jbitsx); $jii++) {
$presel.=str_replace("/wordpress/", "/ITblog/", str_replace(" onclick=", " data-onclick=", "<opt" . "ion " . explode("<opt" . "ion ", $jbitsx[-1 + $jii])[-1 + sizeof(explode("<opt" . "ion ", $jbitsx[-1 + $jii]))] . ">" . explode(" ", $poti)[0] . " " . explode("</opt" . "ion>", $jbitsx[$jii])[0] . "</opt" . "ion>"));
}
$presel.=$postsel;
return str_replace(" Suggestion", $presel, explode("?p=", $newu)[1] . "'>" . explode("'>", $proposed)[1]);

// return explode("?p=", $newu)[1] . "'>" . explode("'>", $proposed)[1];
}
}
}
}
//file_put_contents("xzc.xzc44", $poti . "\n" . $idlist);
}
return $proposed;
}
endif;

?>


Previous relevant WordPress Blog Course via Landing Page Tutorial is shown below.

Wordpress Blog Course via Landing Page Tutorial

Wordpress Blog Course via Landing Page Tutorial

We’re revisiting Online Course ideas onto the last ideas at WordPress Blog Course Design Double Click Tutorial by adding to the previously catered for “Course Design at a peer to peer level by users”, in favour of offering the idea that simply navigating to this WordPress Blog off the RJM Programming Landing Page‘s blog posting dropdown element (improves on the current iframe content all the same as the current blog post) will use …

  1. the blog posting title as selected by the user …
  2. as applicable, the blog post pointed to down past the first relevant <hr /> …
  3. as applicable, previous blog post of interest down below in the Landing Page dropdown content (latest blog posts up the top) that matches the first word of the current blog post title as selected by the user …
  4. as applicable, next blog post of interest up above in the Landing Page dropdown content (latest blog posts up the top) that matches the first word of the current blog post title as selected by the user …

… to navigate the user to a web page that goes …

WordPress Blog Content via the blog posting title as selected by the user
Previous FirstWord Suggestion (link to 3 above) Hashtag Link to Current Blog Post … Next FirstWord Suggestion (link to 4 above)
WordPress Blog Iframe Content (as of 2 above) WordPress Blog Iframe Content (as of the blog posting title as selected by the user)

… to offer the user the optional chance to get the context of any previous blog postings of relevance, immediately, presented to them, before their eyes.

The PHP code in wp-content/themes/twentyten/functions.php off the WordPress Blog’s document root directory needed to change quite a bit …

<?php

if ( ! function_exists( 'may_be_obsolete' ) ) :
/**
* Truncate unknown previous/next.
*
* @since October 2014 by RJM Programming
*/
function may_be_obsolete($proposed, $seca, $poti, $idlist) {
if (str_replace("#content","",$seca) == "") {
if (strpos($proposed, ">Previous") !== false) {
if (strpos(($proposed . "&"), "&pp=&") !== false) {
$bitsare = explode(">", $proposed);
$nums = explode("=", str_replace("&", "=", str_replace("&pp=", "", str_replace("&pn", "", str_replace("?p=", "", $proposed)))));
if ($nums[0] == $nums[1]) {
$proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
}
}
} else if (strpos($proposed, ">Next") !== false) {
if (strpos(($proposed . "&"), "&pn=&") !== false) {
$bitsare = explode(">", $proposed);
$nums = explode("=", str_replace("&", "=", str_replace("&pn=", "", str_replace("&pp", "", str_replace("?p=", "", $proposed)))));
if ($nums[0] == $nums[1]) {
$proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
}
}
}
} else if (strpos($proposed, ">Next") !== false && $poti != "") {
if ($idlist == "") { $idlist=file_get_contents(dirname(__FILE__) . "/../../../../index.html"); }
// <option id='MyNew-20200317' onclick='windowopen("//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial","_blank"); ' value='//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial'>Javascript Convex Polygon Analyze Tutorial (20200317)</option>
$ibitsx=explode(">" . $poti, $idlist);
if (sizeof($ibitsx) > 1) {
if (strpos($ibitsx[0], ">" . explode(" ", $poti)[0] . " ") !== false) {
$jbitsx=explode(">" . explode(" ", $poti)[0] . " ", $ibitsx[0]);
if (sizeof($jbitsx) > 1) {
$newt=explode(" ", $poti)[0] . " " . explode(" (", explode("</option>", $jbitsx[1])[0])[0];
$newu=str_replace("&", "&", explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0])))[-1 + sizeof(explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0]))))]);
//file_put_contents("xzc.xzc66", $proposed . "\n" . $newt . "\n" . $newu);
if (strpos($proposed, "'>") !== false && strpos($newu, "?p=") !== false) {
return explode("?p=", $newu)[1] . "'>" . explode("'>", $proposed)[1];
}
}
}
}
//file_put_contents("xzc.xzc44", $poti . "\n" . $idlist);
} else if (strpos($proposed, ">Previous") !== false && $poti != "") {
if ($idlist == "") { $idlist=file_get_contents(dirname(__FILE__) . "/../../../../index.html"); }
// <option id='MyNew-20200317' onclick='windowopen("//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial","_blank"); ' value='//www.rjmprogramming.com.au/ITblog/?p=48271&pp=&pn=&title=Javascript_Convex_Polygon_Analyze_Tutorial'>Javascript Convex Polygon Analyze Tutorial (20200317)</option>
$ibitsx=explode(">" . $poti, $idlist);
if (sizeof($ibitsx) > 1) {
if (strpos($ibitsx[1], ">" . explode(" ", $poti)[0] . " ") !== false) {
$jbitsx=explode(">" . explode(" ", $poti)[0] . " ", $ibitsx[1]);
if (sizeof($jbitsx) > 1) {
$newt=explode(" ", $poti)[0] . " " . explode(" (", explode("</option>", $jbitsx[1])[0])[0];
$newu=str_replace("&", "&", explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0])))[-1 + sizeof(explode(" value=", str_replace("'", "", str_replace('"', '', $jbitsx[0]))))]);
//file_put_contents("xzc.xzc666", $proposed . "\n" . $newt . "\n" . $newu);
if (strpos($proposed, "'>") !== false && strpos($newu, "?p=") !== false) {
return explode("?p=", $newu)[1] . "'>" . explode("'>", $proposed)[1];
}
}
}
}
//file_put_contents("xzc.xzc44", $poti . "\n" . $idlist);
}
return $proposed;
}
endif;

if ( ! function_exists( 'get_other_one' ) ) :
/**
* Get unknown previous/next.
*
* @since October 2014 by RJM Programming
*/
function get_other_one($proposedp, $onetogetprefix, $onep, $othv) {
$hashsuffix="";
if (file_exists("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
$prehuh = file_get_contents("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
$xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $proposedp . $onetogetprefix . $xxpaa[0];
} else if (file_exists("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
$prehuh = file_get_contents("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
$xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $onep . $onetogetprefix . $xxpaa[0];
}
$huh = file_get_contents(dirname(__FILE__) . "/../../../../index.html");
//file_put_contents("xzc.xzc00", $proposedp);
if ($proposedp == "") {
if ($othv == "<hr" . " />") {
//file_put_contents("xzc.xzc000", $onep);
if ($onep == "") {
$nextcontis=explode($othv, file_get_contents($_SERVER['REQUEST_URI']));
//file_put_contents("xzc.xzc0000", sizeof($nextcontis));
} else {
$nextcontis=explode($othv, file_get_contents("https://www.rjmprogramming.com.au/ITblog/?p=" . ($onep)));
}
if (sizeof($nextcontis) > 2) {
if (strpos($nextcontis[1], "/ITblog/") !== false && strpos($nextcontis[1], "'>") !== false) {
$hashsuffix="#" . explode("&", explode("/", explode("'>", explode("/ITblog/", $nextcontis[2])[1])[0])[0])[0];
//if ($onep == "") {
// file_put_contents("xzc.xzc55", "https://www.rjmprogramming.com.au/ITblog/?p=" . get_the_ID() . " ... " . $hashsuffix . "\n" . explode("/ITblog/", $nextcontis[1])[1]);
//} else {
// file_put_contents("xzc.xzc555", "https://www.rjmprogramming.com.au/ITblog/?p=" . may_be_obsolete($onep) . " ... " . $hashsuffix);
//}
} else if (strpos($nextcontis[1], "/ITblog/") !== false && strpos($nextcontis[1], '">') !== false) {
$hashsuffix="#" . explode("&", explode("/", explode('">', explode("/ITblog/", $nextcontis[2])[1])[0])[0])[0];
//file_put_contents("xzc.xzc6", "https://www.rjmprogramming.com.au/ITblog/?p=" . may_be_obsolete($onep) . " ... " . $hashsuffix);
}
}
}
$xxp = explode("?p=" . $onep . "&", $huh);
if (sizeof($xxp) > 1) {
$xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $onep . $onetogetprefix . $xxpaa[0] . $hashsuffix;
}
return $onep . $hashsuffix;
} else {
if ($othv == "<hr" . " />") {
//file_put_contents("xzc.xzd000", $proposedp);
if ($proposedp == "") {
$nextcontis=explode($othv, file_get_contents($_SERVER['REQUEST_URI']));
//file_put_contents("xzc.xzd0000", sizeof($nextcontis));
} else {
$nextcontis=explode($othv, file_get_contents("https://www.rjmprogramming.com.au/ITblog/?p=" . ($proposedp)));
}
if (sizeof($nextcontis) > 1) {
if (strpos($nextcontis[1], "/ITblog/") !== false && strpos($nextcontis[1], "'>") !== false) {
$hashsuffix="#" . explode("&", explode("/", explode("'>", explode("/ITblog/", $nextcontis[1])[1])[0])[0])[0];
//if ($onep == "") {
// file_put_contents("xzc.xzd55", "https://www.rjmprogramming.com.au/ITblog/?p=" . get_the_ID() . " ... " . $hashsuffix . "\n" . explode("/ITblog/", $nextcontis[1])[1]);
//} else {
// file_put_contents("xzc.xzd555", "https://www.rjmprogramming.com.au/ITblog/?p=" . may_be_obsolete($proposedp) . " ... " . $hashsuffix);
//}
} else if (strpos($nextcontis[1], "/ITblog/") !== false && strpos($nextcontis[1], '">') !== false) {
$hashsuffix="#" . explode("&", explode("/", explode('">', explode("/ITblog/", $nextcontis[1])[1])[0])[0])[0];
//file_put_contents("xzc.xzd6", "https://www.rjmprogramming.com.au/ITblog/?p=" . may_be_obsolete($proposedp) . " ... " . $hashsuffix);
}
}
}
$xxp = explode("?p=" . $proposedp . "&", $huh);
if (sizeof($xxp) > 1) {
$xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $proposedp . $onetogetprefix . $xxpaa[0] . $hashsuffix;
}
return $proposedp . $hashsuffix;
}
return $proposedp . $hashsuffix;
}
endif;

?>

… called by …

<?php

if ( ! function_exists( 'previous_next' ) ) :
/**
* Allow for next and previous via &pn= and &pp= respectively.
*
* @since October 2014 by RJM Programming
*/
function previous_next($both = true) {
if (isset($_GET['pp']) || isset($_GET['pn'])) {
$getp="";
if (!isset($_GET['p'])) {
$getp=get_the_ID(); //$post->ID;
} else {
$getp=$_GET['p'];
}
$prefix = " id='atop";
if ($both) $prefix = " id='abottom";
$topic = "";
$topsuff = "";
$tget = "";
$isuff = "#content";
$jsuff = "#content";
$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPad');
if ($isiPad === false) {
$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPhone');
}
if ($isiPad === false) {
$isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'Android');
}
if ($isiPad) $isuff = "&content=y";
if (isset($_GET['title'])) {
$tget = "&title=" . $_GET['title'];
$topic = str_replace("~", " ", get_tutorial_topic(str_replace("_", " ", $_GET['title'])));
if ($both) {
$topsuff = "<span>  <a href='#content' title='Back to " . str_replace("~", " ", $_GET['title']) . "'>^</a>  </span>";
}
} else {
$topic = str_replace("~", " ", get_tutorial_topic($post->title));
}
if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
$prefix = $prefix;
} else {
echo "<table style='width:150%; background-color: #F6F5F1;'><tbody><tr>";
$cbackto = "";
if (isset($_GET['backto'])) $isuff = "&content=y";
if (isset($_GET['backto'])) $cbackto = "&backto=" . urldecode($_GET['backto']);
$pnv="";
$ppv="";
if (isset($_GET['pp'])) {
$ppv=may_be_obsolete(get_other_one($_GET['pp'], "&pp=", $getp, "<hr" . " />") . "&pn=" . $getp . $tget . $cbackto . "'>Previous" . $topic . " Suggestion", "","","");
$ppvs=explode("#", $ppv);
if (sizeof($ppvs) >= 2) {
$isuff="#" . explode("&", $ppvs[1])[0];
//file_put_contents("xzc.xzc0", $isuff . " ... " . str_replace("#" . $ppvs[1], "", $ppv));
$ppv=str_replace("#" . $ppvs[1], "", $ppv);
}
}
if (isset($_GET['pn'])) {
$pnv=may_be_obsolete(get_other_one($_GET['pn'], "&pn=", $getp, "") . "&pp=" . $getp . $tget . $cbackto . "'>Next" . $topic . " Suggestion", "","","");
$pnvs=explode("#", $pnv);
if (sizeof($pnvs) >= 2) {
$jsuff="#" . explode("&", $pnvs[1])[0];
$pnv=str_replace("#" . $pnvs[1], "", $pnv);
}
}
$atopsuff=$topsuff;
if (str_replace("#content","",($isuff . $jsuff)) != "") {
$topsuff="";
} else {
$atopsuff="";
}
if (isset($_GET['pp'])) {
echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pp'], "&pp=", $getp, $pnv) . "&pn=" . $getp . $tget . $cbackto . "'>Previous" . $topic . " Suggestion",($isuff . $jsuff),get_the_title( get_the_ID() ),"") . "</a>" . $topsuff . "</th>";
$topsuff = "";
}
if (isset($_GET['pn'])) {
echo "<th>" . $atopsuff . "<a" . $prefix . "n' style=display:inline-block; target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pn'], "&pn=", $getp, $ppv) . "&pp=" . $getp . $tget . $cbackto . "'>Next" . $topic . " Suggestion",($isuff . $jsuff),get_the_title( get_the_ID() ),"") . "</a><th>";
}
if (isset($_GET['backto'])) {
echo "<th><a target=_top href='" . urldecode($_GET['backto']) . "' title='Back to Learning Programming'>Learning Programming</a></th>";
}
if ($both) {
echo "</tr><tr>";
if (isset($_GET['pp'])) {
$turlis=str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . $isuff;
if (strpos($turlis, "#") !== false && strpos($turlis, "&") !== false) {
if (strpos($turlis, "#") < strpos($turlis, "&")) {
$atendis="#" . explode("&", explode("#", $turlis)[1])[0];
//file_put_contents("xzc.xzc7", $atendis . " ... " . str_replace($atendis, "", $turlis) . $atendis);
if (strpos($atendis, "-") !== false && strpos($turlis, "/ITblog/") !== false) {
if (strpos(str_replace($atendis, "", $turlis), "'>") !== false) {
$turlis=str_replace( explode("'>", explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
} else if (strpos(str_replace($atendis, "", $turlis), '">') !== false) {
$turlis=str_replace( explode('">', explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
} else {
$turlis=str_replace(explode("/ITblog/", $turlis)[1], substr($atendis,1) . "#content", $turlis);
}
} else if (strpos(str_replace($atendis, "", $turlis), "'>") !== false) {
$turlis=str_replace("'>", $atendis . "'>", str_replace($atendis, "", $turlis));
} else {
$turlis=str_replace($atendis, "", $turlis) . $atendis;
}
}
} else if (strpos($turlis, "#") !== false && strpos($isuff, "-") !== false && strpos($turlis, "/ITblog/") !== false) {
$atendis="" . $isuff;
//file_put_contents("xzc.xzc70", $atendis . " ... " . str_replace($atendis, "", $turlis) . $atendis);
if (strpos($atendis, "-") !== false && strpos($turlis, "/ITblog/") !== false) {
if (strpos(str_replace($atendis, "", $turlis), "'>") !== false) {
$turlis=str_replace( explode("'>", explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
} else if (strpos(str_replace($atendis, "", $turlis), '">') !== false) {
$turlis=str_replace( explode('">', explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
} else {
$turlis=str_replace(explode("/ITblog/", $turlis)[1], substr($atendis,1) . "#content", $turlis);
}
}
}
echo "<td style='vertical-align:top;'><iframe style=width:100%;height:800px; src='" . $turlis . "'></iframe></td>";
}
if (isset($_GET['pn'])) {
$turlis=str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . $jsuff;
if (strpos($turlis, "#") !== false && strpos($turlis, "&") !== false) {
if (strpos($turlis, "#") < strpos($turlis, "&")) {
$atendis="#" . explode("&", explode("#", $turlis)[1])[0];
//file_put_contents("xzc.xzc8", $atendis . " ... " . str_replace($atendis, "", $turlis) . $atendis);
if (strpos($atendis, "-") !== false && strpos($turlis, "/ITblog/") !== false) {
if (strpos(str_replace($atendis, "", $turlis), "'>") !== false) {
$turlis=str_replace( explode("'>", explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
} else if (strpos(str_replace($atendis, "", $turlis), '">') !== false) {
$turlis=str_replace( explode('">', explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
}
} else if (strpos(str_replace($atendis, "", $turlis), '">') !== false) {
$turlis=str_replace('">', $atendis . '">', str_replace($atendis, "", $turlis));
} else {
$turlis=str_replace($atendis, "", $turlis) . $atendis;
}
}
} else if (strpos($turlis, "#") !== false && strpos($jsuff, "-") !== false && strpos($turlis, "/ITblog/") !== false) {
$atendis="#" . $jsuff;
//file_put_contents("xzc.xzc80", $atendis . " ... " . str_replace($atendis, "", $turlis) . $atendis);
if (strpos($atendis, "-") !== false && strpos($turlis, "/ITblog/") !== false) {
if (strpos(str_replace($atendis, "", $turlis), "'>") !== false) {
$turlis=str_replace( explode("'>", explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
} else if (strpos(str_replace($atendis, "", $turlis), '">') !== false) {
$turlis=str_replace( explode('">', explode("/ITblog/", $turlis)[1])[0] , substr($atendis,1) . "#content", $turlis);
}
}
}
echo "<td style='vertical-align:top;'><iframe style=width:100%;height:800px; src='" . $turlis . "'></iframe></td>";
}
}
echo "</tr></tbody></table>";
}
}
}
endif;

?>


Previous relevant WordPress Blog Course Design Double Click Tutorial is shown below.

Wordpress Blog Course Design Double Click Tutorial

Wordpress Blog Course Design Double Click Tutorial

As a web application programmer do you go around looking at a webpage design and think in an “event driven” way for ways to add functionality? I’m forever thinking this way, as what has mostly disappointed me as an “out there” (but pretty mild, you’d have to agree) way to “leave things as they are but” (the land surveyor’s adage (without that danged “but” … and isn’t there always a “but”?!!) around farmer gates for example) extend functionality is the Javascript event …


ondblclick

But … it got out on “good behaviour” and smooching with the parole officer … go figure … today, we think we’ve found a really good and practical use for the …


HTML select element's ondblclick ("on double click") event, on the proviso that the select element is in multiple selection mode

Can you picture this scenario? Sorry, mobile “touch” gestures aren’t relevant here. This scenario is normally accompanied by an HTML input type=button (or HTML button element) (or some other HTML element “onclick” event scenario) that is responsible to say …

Hey, web browser?!
Yeh, waddaUwant.
We’ve finished selecting. Howse about analyzing, bud! Pal?! My liege.
Yeh, waddevvvvvvvver.

This thing about clicking in an HTML select element, though, is that it is so tied up with selections you can’t differentiate that from another purpose unless the ondblclick event (sorry, no mobile usage applicability here) can be “purloined” into use. And we do have another usage in mind for today’s application of all this, namely …


Design a Course (which we last talked about at WordPress Blog Course Design Word Tutorial)

… WordPress blog functionality here at this blog. Have you ever tried it? Up at the menu above there is a “Course” menu item. Click it and you are offered lots of ways to arrive at a single word … recently modifications allowing for the word to be situated …

  • anywhere in a blog posting title … and always it has been the case that it could be …
  • the first word of a blog posting title

… either way, once you get past this, you arrive at an …


HTML select element (dropdown) in multiple selection mode that today's changes add on a new ondblclick ("on double click") event piece of logic

How does this logic proceed? It depends on a global variable … shock, horror!! within our Design a Course‘s PHP design_a_course.php changed this way (and which can be seen in its WordPress blog context at this link) … initialized …


var dblclickedlist=',';

… that is “analyzed” each time this HTML select (dropdown) detects an ondblclick event, and if a selected option value appears in that dropdown’s selected item hasn’t yet appeared in that global variable


function odcc(sin) {
if (multi == 1 && parent.document.getElementById('dblcdiv')) {
for (var i=0; i<sin.options.length; i++) {
if (sin.options[i].selected) {
if (dblclickedlist.indexOf(',' + sin.options[i].value + ',') == -1) {
dblclickedlist+=sin.options[i].value + ',';
parent.document.getElementById('dblcdiv').style.marginTop='-260px';
parent.document.getElementById('dblcdiv').style.width='100%';
parent.document.getElementById('dblcdiv').style.height='1500px';
parent.document.getElementById('dblcdiv').innerHTML='<iframe style=width:100%;height:1500px; src=' + sin.options[i].value + '#content></iframe>';
}

}
}
}
}

… you get a preview of the blog posting hosted in an HTML iframe element (within that aforesaidlater mentioned HTML div element), below.

Also, setting up the “creation” of that HTML select element (dropdown) within design_a_course.php we needed to (within PHP function via()) …


return "<select ondblclick='odcc(this);' size=20 multiple " . str_replace("tuts'", $infind . "tuts'", $xsel[0]) . ">" . str_replace("</OPTION>", "</option>", $newih) . "</select>";

And second lastly you will have noticed in the “if” controlling whether we do any of this functionality it was on the proviso that the WordPress blog webpage “parent” had in it (existant) an HTML element with an ID=dblcdiv (we make this an HTML div element). Where’s that done? Well, that’s done within the WordPress Blog’s “Add Page” administration area under where design_a_course.php is housed within its HTML iframe element …


<div id='mydi'><iframe id="icourse" src="../PHP/design_a_course.php?show=Y" width="100%" height="800"></iframe></div>
<div id=dblcdiv></div>

And lastly it’s good to give the user a hint that they can use this functionality, and we choose to apply this to HTML select (dropdown) element (as they hover over it) above the multiple mode dropdown we have been discussing above (still within design_a_course.php‘s PHP) …


echo "<html><head><script type='text/javascript'> var isonclick=1; var multi=1; var comma=''; " . $ctn . " </script><title>Ask About Course</title></head><body style='background-color:lightgray;'>" . $bodyi . "<h1 align='center'>" . $thetopic . " Course Designer</h1><h3 id='sofar'></h3><br><form align='center' action='./design_a_course.php?show=y' method='POST'><input type='hidden' name='courselsq' id='courselsq' value=''></input><input type='hidden' name='coursesq' id='coursesq' value=''></input>Course Name: <input type='text' style='display:block;' name='coursename' id='coursename' value='" . $topics[0] . "'></input><br><div id='list' style='display:none;'>" . via("") . "</div><select title='Tutorials for course ... you can double click for a preview of any one tutorial below when in Multiple selection mode' id='bc' onchange=' if (multi == 1) { multi = 0; document.getElementById(\"topic\").innerHTML = document.getElementById(\"topic\").innerHTML.replace(/size=20 multiple/g, \"\"); } else { multi=1; document.getElementById(\"topic\").innerHTML = document.getElementById(\"topic\").innerHTML.replace(/select /g, \"select size=20 multiple \"); } '><option value='Multiple'>Multiple (entry mode below)</option><option value='Single'>Single (has advantage that date order can be changed)</option></select><div id='topic' style='display:block;'>" . str_replace("ChangeTutNow(this);", " if (multi == 0) { var ahuh=this.value.split(\"=\"); if (ahuh[ahuh.length - 1] != \"\") { var bhuh=ahuh[1].split(\"&\"); document.getElementById(\"coursesq\").value = document.getElementById(\"coursesq\").value + comma + bhuh[0]; document.getElementById(\"courselsq\").value = document.getElementById(\"courselsq\").value + comma + ahuh[ahuh.length - 1].replace(/_/g, \" \"); document.getElementById(\"sofar\").innerHTML = document.getElementById(\"sofar\").innerHTML + \"<\" + \"br\" + \">\" + ahuh[ahuh.length - 1].replace(/_/g, \" \"); document.getElementById(\"topic\").innerHTML = document.getElementById(\"topic\").innerHTML.replace(ahuh[ahuh.length - 1],\"\").replace(ahuh[ahuh.length - 1],\"\"); comma=\",\"; } } ", via($topics[0])) . "</div><br><br><input onclick='return(ChangeTutNow(document.getElementById(\"" . $thetopic . "tuts\")));' onmouseover=' isonclick=0; ChangeTutNow(document.getElementById(\"" . $thetopic . "tuts\")); isonclick=1; ' align='center' type='submit' name='submit' id='submit' value='Create Your " . $thetopic . " Course Design'></input></form>" . "<h3 id='sofar1'></h3></body></html>";

Voila! A completely independent “add-on” piece of functionality, and the kind we are very fond of here … the type that …

  • doesn’t interfere with the expected (or main) workflow of the web application
  • one that may have occurred to a user to try, anyway, in that intuitive way a lot of us navigate the web

… at least in our programming dreams.

Which brings us to the question? How do the web browsers differentiate an onclick (event) from an ondblclick (event)? Sorry, have to go! See you! Can you just post me the answer! Taaaaaaa!


Previous relevant WordPress Blog Course Design Word Tutorial is shown below.

Wordpress Blog Course Design Word Tutorial

Wordpress Blog Course Design Word Tutorial

The recent “Feedback” web application’s Contact Us Feedback Filtering WordPress Tutorial had us scouring blog posting titles here at this blog for a sorted wordlist to offer in an HTML select (dropdown) element to facilitate more savvy user functionality. This same logic can also be useful to the “Design a Course” we have here at this blog in its menu (pages) and that we talked about at WordPress Blog Course Design Cookies Tutorial for your perusal.

You will see in today’s tutorial picture a newly introduced HTML select (dropdown) element with a list of words. Sounds familiar? No? If you are a goldfish click here.

We were able to use that “Feedback” web application’s “reduced” functionality call in an HTML iframe element within design_a_course.php (changed this way) …


$bodyi .= "<br><iframe style='display:none;' id='jcourse' src='//www.rjmprogramming.com.au/HTMLCSS/feedback.htm?justideas=Y' width='100%' height='200'></iframe><br>";
echo "<html><head><script type='text/javascript'> var comma=''; " . $ctn . " </script><title>Ask About Course</title></head><body style='background-color:yellow;'>" . $bodyi . "<h1 id='header_course_designer' align='center'>Course Designer</h1><form align='center' action='./design_a_course.php?show=y' method='POST'><input type='hidden' name='coursesq' id='coursesq' value=''></input><input type='text' style='display:none;' name='coursename' id='coursename' value=''></input><div id='list' style='display:block;'>" . str_replace("ChangeTutNow(this);", " var ahuh=this.value.split(\"=\"); location.href = \"./design_a_course.php?topic=\" + ahuh[ahuh.length - 1].replace(\"#\", \"%23\"); ", via("")) . "</div><div id='topic' style='display:none;'>" . via("C++") . "</div><br><br><input style='display:none;' align='center' type='submit' name='submit' id='submit' value='Submit'></input></form>" . "</body></html>";

Populating that new HTML select (dropdown) wordlist and the establishment of a new “logic set” for that dropdown’s onchange event is the job for feedback.htm (changed this way) …


awordlistc.sort();
wordlistc='';
for (ioptl=0; ioptl<awordlistc.length; ioptl++) {
wordlistc+='<option value="' + awordlistc[ioptl].toLowerCase() + '">' + awordlistc[ioptl] + '</option>';
}
var wow=false;
if (parent.document) {
if (parent.document.getElementById('header_course_designer')) {
wow=true;
}
}
if (wow) {
var hdg=parent.document.getElementById('header_course_designer').innerHTML;
parent.document.getElementById('header_course_designer').innerHTML="<select title=\"Course Word Anywhere in Blog Title\" onchange=\" if (this.value != '') { location.href='//www.rjmprogramming.com.au/PHP/design_a_course.php?topic=' + encodeURIComponent(this.value) + '&anywhere=y'; } \"><option value=''></option>" + wordlistc + "</select> " + hdg;
} else
if (specifically == '') {
document.getElementById('bigselect').innerHTML+=wordlistc;
}

… making use of the parent/child webpage/iframe arrangements that cause parent.document to be defined (and being the object of that webpage).


Previous relevant WordPress Blog Course Design Cookies Tutorial is shown below.

Wordpress Blog Course Design Cookies Tutorial

Wordpress Blog Course Design Cookies Tutorial

As the last follow up to … “This WordPress blog could benefit from a directed order of tutorials studied for a particular topic. This may not suit everybody, but it may suit some, and if a system is created that is optional, that can sit on top of what functionality is already there, all the better.” … how about we improve the looks and cookie functionality (panned out that it was best to use cookies to remember the client’s last course viewed) of the WordPress page by which users of this blog can control what order tutorials for a range of subjects or topics could be for Course they design from the list of tutorials at this blog, building on the tutorial of a couple of days ago called WordPress Blog Course Design Looks Tutorial as shown below?

How about we work on the “Course” WordPress “New Page” ( as of a few days ago … as simple as <iframe id="icourse" src="../PHP/design_a_course.php?show=y" width="100%" height="800"></iframe> )) that appears in the top menu that contains up to three parts:

  • new (as of two days ago) optional dropdown up the top that exists if another IP address user has shared any/all of their Course Designs, that you can include in your own IP address user list of Course Designs so that they then show in the next section down as a link (with background image)
  • links (with background images) to previously created courses by any user on the IP address involved (yes, cookie logic introduced today to allow user to go back to last course blog posting undertaken via a new “Last” menu option (on top of the “Course” menu option)) … like a few days back, but as of a couple of days ago there was an improved look, via CSS and PHP
  • an iframe to some PHP which asks the user to optionally create new Course Design for users of the IP address involved … like a few days back, but as of a couple of days ago there was an improved look, via CSS and lots more functionality via PHP

So what changes were needed to the landing page updater? None, but we needed to update the PHP file for the iframe as mentioned above, as below …

… and to handle the cookie logic we need client-side Javascript and HTML as per …

… and there were changes needed for PHP code in wp-content/themes/twentyten/header.php because it establishes the header Javascript and two sections of code are involved …


var ourck=location.search.split('ck=')[1] ? location.search.split('ck=')[1].split('&')[0] : '';
var ourpp=location.search.split('pp=')[1] ? location.search.split('pp=')[1].split('&')[0] : '';
var ourpn=location.search.split('pn=')[1] ? location.search.split('pn=')[1].split('&')[0] : '';
var ourpage=location.search.split('page_id=')[1] ? location.search.split('page_id=')[1].split('&')[0] : '';
var ourp=location.search.split('p=')[1] ? location.search.split('p=')[1].split('&')[0] : '';
var ourcourseurl='';
var ourcoursetitle='';

… at the top just under <script type=’text/javascript’> and …

function topViaDelay() {
parent.scroll(0, 0);
}

function courseCookies() {
if (document.URL.indexOf("#content") != -1) {
setTimeout(topViaDelay, 2000);
} else {
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {
document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='" + document.URL.replace("/wordpress/", "/PHP/coursecookies.html") + "'></iframe>" + document.getElementById("content").innerHTML;
setTimeout(topViaDelay, 2000);
} else {
document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='../PHP/coursecookies.html'></iframe>" + document.getElementById("content").innerHTML;
}
}
}
</script>
</head>

<body onload="courseCookies();" <?php body_class(); ?>>

… around </script>

An idea for a live run could be to look at the WordPress blog’s Newish (menu) Page called “Course”, and note that if you ever follow through, yourself, and ever undertake a course then a cookie will be created so that the next time you visit the blog a new “Last” menu item will be over the usual “Course” menu item to allow you to go to that last Course blog posting you were last visiting however long ago (within last 6 months, I think). Hope the tutorial can help you out in some way.


Previous relevant WordPress Blog Course Design Looks Tutorial is shown below.

Wordpress Blog Course Design Looks Tutorial

Wordpress Blog Course Design Looks Tutorial

As another further follow up to … “This WordPress blog could benefit from a directed order of tutorials studied for a particular topic. This may not suit everybody, but it may suit some, and if a system is created that is optional, that can sit on top of what functionality is already there, all the better.” … how about we improve the looks and functionality of the WordPress page by which users of this blog can control what order tutorials for a range of subjects or topics could be for Course they design from the list of tutorials at this blog, building on yesterday’s WordPress Blog Course Design Page Tutorial as shown below?

How about we work on the “Course” WordPress “New Page” ( as of yesterday … as simple as <iframe id="icourse" src="../PHP/design_a_course.php?show=y" width="100%" height="800"></iframe> )) that appears in the top menu that contains up to three parts:

  • new optional dropdown up the top that exists if another IP address user has shared any/all of their Course Designs, that you can include in your own IP address user list of Course Designs so that they then show in the next section down as a link (with background image)
  • links (with background images) to previously created courses by any user on the IP address involved (no cookies used yet) … like yesterday, but today there is an improved look, via CSS and PHP
  • an iframe to some PHP which asks the user to optionally create new Course Design for users of the IP address involved … like yesterday, but today there is an improved look, via CSS and lots more functionality via PHP

So what changes were needed to the landing page updater? None, but we needed to update the PHP file for the iframe as mentioned above, as below:

An idea for a live run could be to look at the WordPress blog’s Newish (menu) Page called “Course”. Hope the tutorial can help you out in some way.


Previous relevant WordPress Blog Course Design Page Tutorial is shown below.

Wordpress Blog Course Design Page Tutorial

Wordpress Blog Course Design Page Tutorial

As a further follow up to … “This WordPress blog could benefit from a directed order of tutorials studied for a particular topic. This may not suit everybody, but it may suit some, and if a system is created that is optional, that can sit on top of what functionality is already there, all the better.” … how about we set up a WordPress page by which users of this blog can control what order tutorials for a range of subjects or topics could be for Course they design from the list of tutorials at this blog?

How about we create a “Course” WordPress “New Page” ( as simple as <iframe id="icourse" src="../PHP/design_a_course.php?show=y" width="100%" height="800"></iframe> ) that appears in the top menu and it contains two parts:

  • links to previously created courses by any user on the IP address involved (no cookies used yet)
  • an iframe to some PHP which asks the user to optionally create new Course Design for users of the IP address involved

So what changes to the landing page updater are required? None, but we need to create a new PHP file for the iframe as mentioned above, as below:

And did the PHP code in wp-content/themes/twentyten/functions.php off the WordPress Blog’s document root directory need to change … yes, to code so that there is no “Previous link” for the first tutorial of a course and no “Next link” for the last tutorial of a course:


if ( ! function_exists( 'may_be_obsolete' ) ) :
/**
* Truncate unknown previous/next.
*
* @since October 2014 by RJM Programming
*/
function may_be_obsolete($proposed) {
if (strpos($proposed, ">Previous") !== false) {
if (strpos(($proposed . "&"), "&pp=&") !== false) {
$bitsare = explode(">", $proposed);
$nums = explode("=", str_replace("&", "=", str_replace("&pp=", "", str_replace("&pn", "", str_replace("?p=", "", $proposed)))));
if ($nums[0] == $nums[1]) {
$proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
}
}
} else if (strpos($proposed, ">Next") !== false) {
if (strpos(($proposed . "&"), "&pn=&") !== false) {
$bitsare = explode(">", $proposed);
$nums = explode("=", str_replace("&", "=", str_replace("&pn=", "", str_replace("&pp", "", str_replace("?p=", "", $proposed)))));
if ($nums[0] == $nums[1]) {
$proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
}
}
}
return $proposed;
}
endif;

if ( ! function_exists( 'get_other_one' ) ) :
/**
* Get unknown previous/next.
*
* @since October 2014 by RJM Programming
*/
function get_other_one($proposedp, $onetogetprefix, $onep) {

if (file_exists("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
$prehuh = file_get_contents("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
$xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $proposedp . $onetogetprefix . $xxpaa[0];
} else if (file_exists("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
$prehuh = file_get_contents("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
$xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $onep . $onetogetprefix . $xxpaa[0];
}

$huh = file_get_contents(dirname(__FILE__) . "/../../../../index.html");
if ($proposedp == "") {
$xxp = explode("?p=" . $onep . "&", $huh);
if (sizeof($xxp) > 1) {
$xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $onep . $onetogetprefix . $xxpaa[0];
}
return $onep;
} else {
$xxp = explode("?p=" . $proposedp . "&", $huh);
if (sizeof($xxp) > 1) {
$xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $proposedp . $onetogetprefix . $xxpaa[0];
}
return $proposedp;
}
return $proposedp;
}
endif;

if ( ! function_exists( 'get_tutorial_topic' ) ) :
/**
* Get tutorial topic (word).
*
* @since October 2014 by RJM Programming
*/
function get_tutorial_topic($thistopic) {
$words = explode(" ", str_replace(" ", "++", str_replace("~~", "#~", $thistopic)));
if (sizeof($words) > 1) {
return " " . $words[0];
}
return "";
}
endif;

if ( ! function_exists( 'previous_next' ) ) :
/**
* Allow for next and previous via &pn= and &pp= respectively.
*
* @since October 2014 by RJM Programming
*/
function previous_next($both = true) {
if (isset($_GET['pp']) || isset($_GET['pn'])) {

$prefix = " id='atop";
if ($both) $prefix = " id='abottom";
$topic = "";
$tget = "";
if (isset($_GET['title'])) {
$tget = "&title=" . $_GET['title'];

$topic = str_replace("~", " ", get_tutorial_topic(str_replace("_", " ", $_GET['title'])));

} else {

$topic = str_replace("~", " ", get_tutorial_topic($post->title));

}
if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
$prefix = $prefix;
} else {
echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
if (isset($_GET['pp'])) {

echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pp'], "&pp=", $_GET['p']) . "&pn=" . $_GET['p'] . $tget . "'>Previous" . $topic . " Suggestion") . "</a></th>";

}
if (isset($_GET['pn'])) {

echo "<th><a" . $prefix . "n' target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pn'], "&pn=", $_GET['p']) . "&pp=" . $_GET['p'] . $tget . "'>Next" . $topic . " Suggestion") . "</a><th>";

}

if ($both) {
echo "</tr><tr>";
if (isset($_GET['pp'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . "#content' width=400 height=800></iframe></td>";
}
if (isset($_GET['pn'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . "#content' width=400 height=800></iframe></td>";
}
}
echo "</tr></tbody></table>";
}

}

}
endif;

An idea for a live run could be to look at the WordPress blog’s New (menu) Page called “Course”. Hope the tutorial is of some interest for you, and see you later.


Previous relevant WordPress Blog Course Design Database Tutorial is shown below.

Wordpress Blog Course Design Database Tutorial

Wordpress Blog Course Design Database Tutorial

As another follow up to … “This WordPress blog could benefit from a directed order of tutorials studied for a particular topic. This may not suit everybody, but it may suit some, and if a system is created that is optional, that can sit on top of what functionality is already there, all the better.” … how about we set up a WordPress database means by which the the administrator of this blog can control what order tutorials for a range of subjects or topics could be?

How about we allow for the WordPress MySql wp_posts table’s post_excerpt field be used to contain either …

  • a degree of difficulty numerical rating
  • the query string parts &pp=[blog id of previous blog post of interest to current one] and &pn=[blog id of next blog post of interest to current one]&title=[blog posting title]

… because the post_excerpt database column is currently not being utilized, and is easier to implement than WordPress custom fields.

So what changes to the landing page updater are required? For the background to it please read the blog posting called Extended Linux Crontab Curl Tutorial would hold the answer to where the most efficient solution to this lies, in adjusting the PHP code called tutorial_options.php here as below:

And did the PHP code in wp-content/themes/twentyten/functions.php off the WordPress Blog’s document root directory need to change … do fish swim? … see the bits in bold, in particular below:


if ( ! function_exists( 'get_other_one' ) ) :
/**
* Get unknown previous/next.
*
* @since October 2014 by RJM Programming
*/
function get_other_one($proposedp, $onetogetprefix, $onep) {
$huh = file_get_contents(dirname(__FILE__) . "/../../../../index.html");
if ($proposedp == "") {
$xxp = explode("?p=" . $onep . "&", $huh);
if (sizeof($xxp) > 1) {
$xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $onep . $onetogetprefix . $xxpaa[0];
}
return $onep;
} else {
$xxp = explode("?p=" . $proposedp . "&", $huh);
if (sizeof($xxp) > 1) {
$xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
$xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
return $proposedp . $onetogetprefix . $xxpaa[0];
}
return $proposedp;
}
return $proposedp;
}
endif;

if ( ! function_exists( 'get_tutorial_topic' ) ) :
/**
* Get tutorial topic (word).
*
* @since October 2014 by RJM Programming
*/
function get_tutorial_topic($thistopic) {
$words = explode(" ", str_replace(" ", "++", str_replace("~~", "#~", $thistopic)));
if (sizeof($words) > 1) {
return " " . $words[0];
}
return "";
}
endif;

if ( ! function_exists( 'previous_next' ) ) :
/**
* Allow for next and previous via &pn= and &pp= respectively.
*
* @since October 2014 by RJM Programming
*/
function previous_next($both = true) {
if (isset($_GET['pp']) || isset($_GET['pn'])) {

$prefix = " id='atop";
if ($both) $prefix = " id='abottom";
$topic = "";
$tget = "";
if (isset($_GET['title'])) {
$tget = "&title=" . $_GET['title'];

$topic = str_replace("~", " ", get_tutorial_topic(str_replace("_", " ", $_GET['title'])));

} else {

$topic = str_replace("~", " ", get_tutorial_topic($post->title));

}
if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
$prefix = $prefix;
} else {
echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
if (isset($_GET['pp'])) {

echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . get_other_one($_GET['pp'], "&pp=", $_GET['p']) . "&pn=" . $_GET['p'] . $tget . "'>Previous" . $topic . " Suggestion</a></th>";

}
if (isset($_GET['pn'])) {

echo "<th><a" . $prefix . "n' target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . get_other_one($_GET['pn'], "&pn=", $_GET['p']) . "&pp=" . $_GET['p'] . $tget . "'>Next" . $topic . " Suggestion</a><th>";

}

if ($both) {
echo "</tr><tr>";
if (isset($_GET['pp'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . "#content' width=400 height=800></iframe></td>";
}
if (isset($_GET['pn'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . "#content' width=400 height=800></iframe></td>";
}
}
echo "</tr></tbody></table>";
}

}

}
endif;

… and you may want to compare this to the code of the previous WordPress Blog Course Design Follow Up Tutorial as shown below. Today’s explanation of a “live run” is to:

  1. Access the rjmprogramming.com.au domain Landing Page
  2. At the tutorial dropdown you’ll see the 3 blog postings that had their post_excerpt fields filled out up the top and you could “motor” down to the second one dated 20130722 … these are blog posts flagged as part of a course in the order from start of course through to end of course where the Course name is the first word of the blog posting title as shown on the dropdown (so you can tell where one course starts and the next starts)
  3. Hopefully … voila (as per live run as was the “live run” from tutorial way below + a Course name inclusion functionality improvement so that it is like … live run again) … do the same for 20141006 (today’s) and you don’t get the new functionality, but hopefully it doesn’t cause any bugs (as you change code the top priority should be firstly not to break other parts that used to work, and to proceed successfully with new functionality that works)

By the way, the file methodologies of the tutorial below are still active, and we still have to explain how a user can control their own personalized Course Designs, and this file method will come back to the fore then, am pretty sure.

Hope to see you yet again next time.


Previous relevant WordPress Blog Course Design Follow Up Tutorial is shown below.

Wordpress Blog Course Design Follow Up Tutorial

Wordpress Blog Course Design Follow Up Tutorial

As a follow up to … “This WordPress blog could benefit from a directed order of tutorials studied for a particular topic. This may not suit everybody, but it may suit some, and if a system is created that is optional, that can sit on top of what functionality is already there, all the better.” … how about we set up the means by which the user or the administrator of this blog (I knew it) can control what order tutorials for a range of subjects or topics could be?

If you’re designing this (and please don’t get any ideas that there is just the way suggested here) you set a “get parameters” way to express the fact that you want this “guided” Course Design help but don’t know what is a good tutorial to come before nor after, and what logic paths, in order …

  1. accept last recorded &pp=[blog id of previous blog post of interest to current one] and &pn=[blog id of next blog post of interest to current one] advice for this current blog posting from this user (ie. use cookies)
  2. accept last recorded &pp=[blog id of previous blog post of interest to current one] and &pn=[blog id of next blog post of interest to current one] advice for this current blog posting from this client using their IP address
  3. accept last recorded &pp=[blog id of previous blog post of interest to current one] and &pn=[blog id of next blog post of interest to current one] advice for this current blog posting from the administrator of this blog
  4. accept last recorded &pp=[blog id of previous blog post to current one] and &pn=[blog id of next blog post to current one]
  5. disregard display of previous and next suggested tutorials

… to follow in order to come up with the blog posting display that you end up with.

Let’s just first concentrate on options 3 and 4 and 5 above … how about we use &pp=&pn= to mean that if no previous and/or next tutorial information is found anywhere you should (5) “disregard display of previous and next suggested tutorials”, whereas if you specify &pn=&pp= to mean that if no previous and/or next tutorial information is found anywhere you should (4) “accept last recorded &pp=[blog id of previous blog post to current one] and &pn=[blog id of next blog post to current one]”.

This sounds a silly detail to worry about, but the fact is, if this detail is sorted out, this whole “guided” Course Design system can be automated from this domain’s landing page‘s tutorial dropdown, or any other dropdown you want to design to direct people to this WordPress Blog’s tutorials.

And where could we intervene to fix this up? Well, well, well (three holes in the ground … chortle, chortle) … you’d have to be an avid follower of this blog to remember, but the blog posting called Extended Linux Crontab Curl Tutorial would hold the answer to where the most efficient solution to this lies, in adjusting the PHP code called tutorial_options.php here as below …

… to enable an ID= on the links to allow for future Javascript DOM possibilities and a file arrangement for admin and/or IP user based tailoring of previous and/or next blog posting “get” parameters. Future tutorials on this “theme” will look at functionality to maintain and populate these files in a sensible way.

Another question occurs to me. Shouldn’t the name of the proposed Course a blog posting belongs to be part of the display? No, I wouldn’t do that! “Yeah, but who asked you? You’re a cat, remember?” No furry beastings were hurt during the creation of this blog posting.

Is the name of the Course a thing that the Course Designer should designate, or can it be derived from the WordPress blog? This will vary in people’s outlook. Some will be fine for (one of) the WordPress blog posting Category (or Tag?) (names) to suffice, and think I’d be in that camp. But I’m also in the camp that says this could be overridden by a user or administrator defined method … feel a “get parameter” coming on … so let’s see what the adjusted code for the “framework” of these new requirements looks like (the tutorial_options.php needed adjustment for this concept as well) … it panned out to be better to focus on the first word of the blog posting’s title as a better bet for what the Course name could be derived from … the PHP code (snippet) goes into wp-content/themes/twentyten/functions.php off the WordPress Blog’s document root directory …



if ( ! function_exists( 'get_tutorial_topic' ) ) :
/**
* Get tutorial topic (word).
*
* @since October 2014 by RJM Programming
*/
function get_tutorial_topic($thistopic) {
$words = explode(" ", str_replace(" ", "++", str_replace("~~", "#~", $thistopic)));
if (sizeof($words) > 1) {
return " " . $words[0];
}
return "";
}
endif;

if ( ! function_exists( 'previous_next' ) ) :
/**
* Allow for next and previous via &pn= and &pp= respectively.
*
* @since October 2014 by RJM Programming
*/
function previous_next($both = true) {
if (isset($_GET['pp']) || isset($_GET['pn'])) {

$prefix = " id='atop";
if ($both) $prefix = " id='abottom";
$topic = "";
$tget = "";
if (isset($_GET['title'])) {
$tget = "&title=" . $_GET['title'];
$topic = get_tutorial_topic(str_replace("_", " ", $_GET['title']));
} else {
$topic = get_tutorial_topic($post->title);
}
if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
$prefix = $prefix;
} else {
echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
if (isset($_GET['pp'])) {
echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . "&pn=" . $_GET['p'] . $tget . "'>Previous" . $topic . " Suggestion</a></th>";
}
if (isset($_GET['pn'])) {
echo "<th><a" . $prefix . "n' target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . "&pp=" . $_GET['p'] . $tget . "'>Next" . $topic . " Suggestion</a><th>";
}

if ($both) {
echo "</tr><tr>";
if (isset($_GET['pp'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . "#content' width=400 height=800></iframe></td>";
}
if (isset($_GET['pn'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . "#content' width=400 height=800></iframe></td>";
}
}
echo "</tr></tbody></table>";
}

}

}
endif;

… and you may want to compare this to the code of the previous WordPress Blog Course Design Primer Tutorial as shown below. Today’s explanation of a “live run” is to:

  1. Access the rjmprogramming.com.au domain Landing Page
  2. At the tutorial dropdown “motor” down to the tutorial at 20130722 … OOPs (chortle, chortle) … and choose this
  3. Hopefully … voila (as per live run as was the “live run” from tutorial below + a Course name inclusion functionality improvement so that it is like … live run again) … do the same for 20141006 (today’s) and you don’t get the new functionality, but hopefully it doesn’t cause any bugs (as you change code the top priority should be firstly not to break other parts that used to work, and to proceed successfully with new functionality that works)

Hope to see you again next time.


Previous relevant WordPress Blog Course Design Primer Tutorial is shown below.

Wordpress Blog Course Design Primer Tutorial

Wordpress Blog Course Design Primer Tutorial

This WordPress blog could benefit from a directed order of tutorials studied for a particular topic. This may not suit everybody, but it may suit some, and if a system is created that is optional, that can sit on top of what functionality is already there, all the better.

When you want to add PHP (or HTML, for that matter) functionality, with web work, I personally find the get parameters useful, and this is usually fine as long as the data required of this functionality …

  • is not too long
  • is not sensitive (ie. not a password or username)

… otherwise it is better to use post parameters or a database or a file arrangement of some sort.

Step one in our Course Design ideas is to introduce two new ideas with two new get parameters, so that:

  • &pp=[blog id of previous blog post of interest to current one]
  • &pn=[blog id of next blog post of interest to current one]

Here’s a first draft of a PHP snippet of code to use (though over time it may change):


if ( ! function_exists( 'previous_next' ) ) :
/**
* Allow for next and previous via &pn= and &pp= respectively.
*
* @since October 2014 by RJM Programming
*/
function previous_next($both = true) {
if (isset($_GET['pp']) || isset($_GET['pn'])) {
echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
if (isset($_GET['pp'])) {
echo "<th><a target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . "&pn=" . $_GET['p'] . "'>Previous Suggestion</a></th>";
}
if (isset($_GET['pn'])) {
echo "<th><a target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . "&pp=" . $_GET['p'] . "'>Next Suggestion</a><th>";
}
if ($both) {
echo "</tr><tr>";
if (isset($_GET['pp'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . "#content' width=400 height=800></iframe></td>";
}
if (isset($_GET['pn'])) {
echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . "#content' width=400 height=800></iframe></td>";
}
}
echo "</tr></tbody></table>";
}
}
endif;

So where does the code above belong in the WordPress source code? Well, for the TwentyOne theme of this blog, the answer is wp-content/themes/twentyten/functions.php off the WordPress Blog’s document root directory (where PHP functions go, generally).

And the plan will be to call it, for the top and bottom of current posting respectively:

  • <?php previous_next(false); ?>
  • <?php previous_next(true); ?>

So where does this code go? Well, for the TwentyOne theme of this blog, the answer is, in WordPress terminology, in The Loop, for the particular scenario, and the scenario here is the display of a single WordPress Blog posting, as typically happens via the Search Engine links or relevant dropdown links within this rjmprogramming.com.au domain … and this pans out to be within wp-content/themes/twentyten/single.php off the WordPress Blog’s document root directory … after these two lines of PHP code respectively …

  • <?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?>
  • <?php endwhile; // end of the loop. ?>

… for these two looks respectively …

Try an example of a live run of the use of this new functionality here at this WordPress Blog … but there is more to do … and we will visit these other “things to do” over time … thanks for visiting … bye for now.

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


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


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


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


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


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


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


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


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

SVG Emoji Favicon and Title Uniquify Tutorial

SVG Emoji Favicon and Title Uniquify Tutorial

What’s “uniquify” in terms of Information Technology?

To turn an instance of a type into an instance of a new unique copy of the original type.

For us, it is a concept often called into play to separate one online viewer’s data from affecting the viewing of another’s data, or “settings”, concepts which cover the recent web browser tab icon SVG emoji ideas we talked about at the recent SVG Emoji Favicon and Title Tutorial. There we hadn’t coded with much thought to “personalizing” one “Emoji Menu” viewer’s web browser tab icon SVG emoji from another.

This “Emoji Menu” web browser tab icon SVG emoji creation work uses PHP to write out those favicon images (and yes, favicon images do not have to be named “favicon.svg” or “favicon.ico”), and we are choosing a guise of a user’s IP address as our “uniquifier” conduit means. You’ll see it being used in the latest draft


<?php
// emojiicon.php
// RJM Programming
// March, 2025

$usuffix='';
$iponl='';
$rma='';

function massage($inidea) {
if (isset($_GET['ididea'])) {
return str_replace("document.body", "document.getElementById('" . str_replace('+',' ',urldecode($_GET['ididea'])) . "')", $inidea);
}
return str_replace('(7 == 7)', '(56 == 67)',$inidea);
}

function server_remote_addr() {
global $iponl, $rma;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ \/]([\w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ \/]([\w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ \/]([\w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ \/]([\w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ \/]([\w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ \/]([\w.]+)/', $ua))
$rma = '0'.$rma;
$rma=str_replace(':','_',$rma);
$iponl=massage(" onload=\" if (window.parent) { if (parent.document.body.outerHTML.split('>')[0].indexOf(' data-ip=') == -1) { if (7 == 7) { parent.document.body.title=('' + parent.document.body.title) + ' +++ _" . $rma . "'; } parent.document.body.setAttribute('data-ip', '_" . $rma . "'); } } \"");
return $rma;
}

if (isset($_GET['codepoint'])) {
if (strlen($_GET['codepoint']) > 0) {
if (isset($_GET['ishex']) || isset($_GET['tohex']) || isset($_GET['hex'])) {
$usuffix='_' . server_remote_addr();
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.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 {
$usuffix='_' . server_remote_addr();
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.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>');
}
} else if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$usuffix='_' . server_remote_addr();
} else {
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.svg', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">X</text></svg>');
if ($iponl != '' && file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$iponl=massage(" onload=\" if (window.parent) { if (parent.document.body.outerHTML.split('>')[0].indexOf(' data-ip=') == -1) { parent.document.body.setAttribute('data-ip', '_" . $rma . "'); parent.document.body.setAttribute('data-firstip', 'y'); } } \"");
}
}
} else if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$usuffix='_' . server_remote_addr();
} else {
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.svg', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">X</text></svg>');
if ($iponl != '' && file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$iponl=massage(" onload=\" if (window.parent) { if (parent.document.body.outerHTML.split('>')[0].indexOf(' data-ip=') == -1) { parent.document.body.setAttribute('data-ip', '_" . $rma . "'); parent.document.body.setAttribute('data-firstip', 'y'); } } \"");
}
}

echo "<html>
<head>
<link rel='icon' href='/emojiicon/favicon" . $usuffix . ".svg?rand=" . rand(0,3456789) . "' sizes='any' type='image/svg+xml'>
</head>
<body" . $iponl . ">
<h1>Emoji Icon - RJM Programming - March, 2025</h1>
</body>
</html>";
?>

… of emojiicon.php helping out the body element global data attribute using emoji_widget_idea.htm content live run.


Previous relevant SVG Emoji Favicon and Title Tutorial is shown below.

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.


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

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