Select Multiple Mobile Background Image Tutorial

Select Multiple Mobile Background Image Tutorial

Select Multiple Mobile Background Image Tutorial

We had occasion to revisit Window LocalStorage Client Versus Server Map Tutorial‘s web application today changed this way to end up with wls_vs_php.htm, on an iPad, and saw how initially lacking was the advice on how to work the Capital City to Country quiz. The reason, primarily, in our view, is that on mobile platforms an element such as …


<select class=dglow onclick=" console.log('67234'); noif(); " title='Please select Capital(s) below to get Countries Report ...' onfocusout=" document.getElementById('myrepsb').className='dglow'; tablemode = ''; nothere=true; updatecountries(null);" style='width:300px;margin-top:0px;margin-left:0px;vertical-align:top;height:100vh;background-color:lightblue;' id=scapitals multiple>
// innard options //
</select>

… you just see words to the effect …

0 items …

… but we’d see more use for this select element “opened up” on initialization. As we read, and believed, via this useful link, thanks, this “programmatical click on mobile platforms” to open up such a select element is not easy. So we decided to go down the route of …

  • to a select multiple element …
  • on mobile …
  • background image …
  • at top right …
  • that is wording advice “Click/tap me”
  • when first encountered

… and we came up with the document.body onload event call “new Javascript code snippet” …


if (document.URL.indexOf('?') == -1) {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('scapitals').click(); // this is just wishful thinking, but no error is caused, and you never know?
document.getElementById('scapitals').style.background="url(\"data:image/svg+xml;base64," + window.btoa("<svg xmlns='http://www.w3.org/2000/svg' width='126' height='48' viewport='0 0 100 100' style='border-radius:15px;background-color:rgba(0,0,255,0.3);fill:black;font-family:Verdana;font-size:17px;'><text x='5%' y='60%'>Click/tap me</text></svg>") + "\") no-repeat top right";
}
}

Next best approach, we’d say?!


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

Window LocalStorage Client Versus Server Map Tutorial

Window LocalStorage Client Versus Server Map Tutorial

Get a good map, and a goodly number of times you’ll want a map of smaller or larger scale than the one you have. Murphy’s Law? This is probably why in the wonderful woooooooorrrrrrrrlllllld of Google Charts they have included …

  • Geo Chart topographic map of the world or of regions
  • Map Chart terrestrial/satellite map of your group of markers at a zoom level of your choosing

… and hope you can see that the latter can save the day for a Short Distance Trip (corner shop, anyone?!).

So we’ve added onto yesterday’s Window LocalStorage Client Versus Server Timeline Tutorial progress a new toggling button to view a scenario in either Google Chart scenario above.

You can see this integration work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link supervising a tweaked geo_chart.php Geo Chart interfacer.


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

Window LocalStorage Client Versus Server Timeline Tutorial

Window LocalStorage Client Versus Server Timeline Tutorial

Up to yesterday’s Window LocalStorage Client Versus Server User Tutorial‘s progress, our Capital City Find Matching Country Report web application project was all about …

  • where (and capital of “what”) … but we often seek out a way to add into the mix that 4th dimension …
  • when (ie. time)

… and regarding the current project, a …

  • where “map” … can interface with a …
  • when “Trip Plan Itinerary”

… and for this purpose, we’re going to interface to the excellent Google Charts Annotated Timeline Chart, thanks, because it combines links of “time” to “user annotations” in a timeline way, that similar way you might describe the qualities of a Trip, even before you’ve gone on that trip. We’ve also added it so that an unordered places list can be turned into a Trip Plan Itinerary at the click/touch of a new map 🗺 &#128506; emoji button.

Again, see how these timeline amendments were achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link and annotatedtimeline_chart.php which changed quite a lot.


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

Window LocalStorage Client Versus Server User Tutorial

Window LocalStorage Client Versus Server User Tutorial

The inherent weakness with our current Capital City Find Matching Country Report web application project, to our minds, was that places of interest are not restricted to the Capital Cities of Countries, especially when “Trip Planning”. On the other hand, it would be impossible to cater for every “place” in the world. That is far too subjective for good web application applicability. What would be good though, is to allow in user defined …


Place name, Country name

… terms, the definitions of interest to a user. We can ask this …

  • flagged by the click/touch of an emoji button … and …
  • the interactive entry presented via a Javascript prompt window

. When thinking of data applicable to an individual, then that can be catered for by recording it in localStorage where it will be recalled on the next execution of that web application in the same web browser.

This, along with a Colour Wheel of the “nearest TimeZone place” onto the existing logic of yesterday’s Window SessionStorage Client Versus Server Order Tutorial progress could make for a more useful and practical tool for those Trip Planners out there!

See how this was achieved with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Did you know?

To click/touch one of those Google Chart Geo Chart lines between Emoji Flag Markers will show a new Google Maps directions web page with transport times and detail, as well as an inhouse crow fly distance of that trip leg, as shown up the top right of today’s tutorial picture.


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

Window SessionStorage Client Versus Server Order Tutorial

Window SessionStorage Client Versus Server Order Tutorial

If we are to honour our thoughts of being able to use our current Capital City Find Matching Country Report web application as a Trip Planner …

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

… then yesterday’s Window SessionStorage Client Versus Server Flags Tutorial “progress to now” needs to take notice of a user’s order of multiple select (dropdown) element click/touching of Capital City option (sub)elements, just as we did with the recent User Controlled Dynamic Javascript YouTube Embedded API Ordered Tutorial‘s web application project to allow for a user ordered YouTube video playlist.

Because what is a Trip Planner without an ordered trip? Well, that is debatable, but what isn’t (debatable), is that there will be people in the world who appreciate the “mapping out” of a proposed Trip Planning Itinerary. What could we call on here? We can think of the Google Chart Geo Chart work around about the time of Google Geo Chart Co-ordinate Emojis Tutorial, when we started using …

  • a world map … with …
  • emoji markers … and optionally …
  • joined up by straight lines

… an idea for a Trip Plan itinerary synopsis, perhaps?!

If you examined closely yesterday’s code changes you will have noticed our collecting of TimeZone Place geographical latitude and longitude information. Today, we start making use of that preparatory work with our changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.

Stop Press

The “emoji markers” above (as of 2 January 2020) will be “country flags” (as per Window SessionStorage Client Versus Server Flags Tutorial ideas), as defined.


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

Window SessionStorage Client Versus Server Flags Tutorial

Window SessionStorage Client Versus Server Flags Tutorial

Yes, there’s more to do onto yesterday’s Window SessionStorage Client Versus Server CSS Tutorial‘s Capital City Find Matching Country Report web application project, in our eyes. We have not even mentioned “Internationalization” as a concept up to now. In this line of thinking …

Did you know?

Emoji flags via ISO 2 character country codes are dead easy via Regional Indicator Symbol characters …


var lri="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var dri=["127462","127463","127464","127465","127466","127467","127468","127469","127470","127471","127472","127473","127474","127475","127476","127477","127478","127479","127480","127481","127482","127483","127484","127485","127486","127487"];

var thiscc='AU'; // ISO 2 character countrycode for Australia
var ccsuff='', ccchar=' ';
for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
ccsuff+='&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
}
document.getElementById('lastflag').innerHTML=ccsuff;

… to result in (via <span style=font-size:64px;>&#127462;&#127482;</span>) …


🇦🇺

… providing interest and general translatability to the changed wls_vs_php.htm‘s Capital City Find Matching Country Report live run link.


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

Window SessionStorage Client Versus Server CSS Tutorial

Window SessionStorage Client Versus Server CSS Tutorial

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

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

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

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

In terms of CSS styling work …

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

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

    … dovetailing with the “static” internal CSS coding

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

    }
    </style>

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

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

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

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


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

Window SessionStorage Client Versus Server Integration Tutorial

Window SessionStorage Client Versus Server Integration Tutorial

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

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

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

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

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


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

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

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

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

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


var last24='';
var rectdc;

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

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

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

… working with the new HTML …


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

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

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


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

Window SessionStorage Client Versus Server Ajax Tutorial

Window SessionStorage Client Versus Server Ajax Tutorial

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

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

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

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

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

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

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

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

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


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

Window SessionStorage Client Versus Server Canvas Tutorial

Window SessionStorage Client Versus Server Canvas Tutorial

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

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

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

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

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

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

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

… sharing off to an emailee collaborator.

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


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

Window SessionStorage Client Versus Server Share Tutorial

Window SessionStorage Client Versus Server Share Tutorial

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

  • email
  • SMS

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


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

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

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


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

Window SessionStorage Client Versus Server Tutorial

Window SessionStorage Client Versus Server Tutorial

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

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

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


localStorage.removeItem([knownLocalStorageName]);

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

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


var datamode='localStorage';

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

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

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

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


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

Window LocalStorage Client Versus Server Primer Tutorial

Window LocalStorage Client Versus Server Primer Tutorial

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

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

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

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

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

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

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

that’s because the web application’s …


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

return false;
}
}
return true;
}

… HTML form onsubmit event logic …

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

    HTTP 414 "Request URI too long"

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

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

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

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

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

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

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

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


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


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


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


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


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


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


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


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


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


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


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


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

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

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