… of guessing a code, do you know what that code is? If not, do you know what …
73,786,976,294,838,206,464
… represents? Well, how about we leave a snail trail hint …
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
… it’s the same as 64^11 … and the first thing that springs to mind regarding 64 might be …
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
… base64?! And the next thing that might spring to mind regarding 11 might be …
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
… number of characters in a YouTube video ID?! Leaving us with …
So what’s the go with “/ 4“?
Well, there you need a lesson in YouTubeonetrics and we’re recommending …
… for mathematics enthusiasts and IT historians alike here. The odds of you guessing any one YouTube video ID of interest just got 4 times easier!
On viewing this totally useful video, thanks, we decided to have a first pass not using Ajax to determine whether a user’s 11 character string is a legitimate YouTube video, and plumping in our …
Day 5 Nuance 3
… pass today, with the “can sometimes not get it right, but that is not really that bad” means by which we can rule out some 11 character strings from consideration as YouTube video references, via …
function elevenize(whatwords) {
var outwords=whatwords;
if (!butnotif) {
var klines=0, kwords=0
var otherlines=whatwords.split(String.fromCharCode(10));
var otherwords=[];
for (klines=0; klines<otherlines.length; klines++) {
otherwords=otherlines[klines].split(' ');
for (kwords=0; kwords<otherwords.length; kwords++) {
otherwords[kwords]=otherwords[kwords].split('</')[0];
if (eval('' + otherwords[kwords].length) == 11) {
outwords=outwords.replace(otherwords[kwords], '<tspan class="' + maybelegit(otherwords[kwords],'tubeaudioyou') + '">' + otherwords[kwords] + '</tspan> ');
}
}
}
}
return outwords;
}
But, alas, strings like programming will still get through even though, at the time of writing, is not a valid YouTube video ID yet?!, though the shouted out PROGRAMMING has no truck, now …
… describing the HTML elements added for mobile usage, here. Even then, annoyingly, if you tapped on one of these, the Javascript would too often call function addcontents in a way we thought was aggravating, and so we resorted to a global variable usage and started doing as below …
var allowed=true;
function addcontents(inboc) {
if (!allowed) {
allowed=true;
return false;
}
var nboc='', seventeen="17", zero=0, numlines=1, one=1, grest='', ghuh='', wasfound=false, jnew=0;
// blah blah blah open textarea popup window blah blah blah
}
function notallowed() {
allowed=false;
setTimeout(function(){ allowed=true; }, 1000);
}
Well, onto yesterday’s SVG Tspan Element Primer Tutorial our “two day” job is “two days” of sorts. Definitely for non-mobile, deploying the “inline audio stream of YouTube video play” concept we wanted, but for mobile, let me “count the ways” …
to get any functionality down to “one tap/click to play” … well …
we tried for mobile, and haven’t given up, but the complexity of “overlay” related z-index and “where to place iframe element” issues exploded my tiny little brain … and so …
for mobile we’ve “parked” the ideal solution … in favour of, for now …
the mobile “two day solution” that, like for non-mobile, underlines those 11 characterYouTubereferences as links that can navigate interested users to a new tab/window YouTube window to play the “whole shebang” (and … sigh … needing that extra tap/click) … leaving …
Days 3 (and on) to nuance
Another project where the last 10% nuances is probably going to take more time than the rest! Anyway, we’ll see how this “mini project” develops.
now SVG tspan savvy external Javascript ytaudioonly.js assisting YouTube Audio Stream of Video Plays … specifically …
// blah blah blah
var thespansare=[];
function ihun(ao) {
var aih=ao.innerText;
if (aih.trim() != '') {
var newihis='';
for (var iaih=0; iaih<aih.length; iaih++) {
newihis+='_';
}
ao.innerHTML=newihis;
}
}
regarding improvements to existant functionality it is most important to not interfere with any current functionality … and then …
implement new functionalities off this platform
… and with our “mini project” of embellishing 11 letter words in the Speech Bubbles of our Select Multiple Webpage Palette Speech Bubble web application of recent times, we have a natural compartmentalization playing out mimicking those ideas above, that goes …
Day 1 – work with the data that is the HTML (and SVG) of Speech Bubbles where they look and behave as ever, but 11 letter words get nested into SVG tspan elements
Day 2 – embellish the web application via those SVG tspan elements
It’s our first go using SVG tspan elements as a “forward thinking” tool, and it helped us thinking on this regarding the corrollaries to HTML span element. What initially concerned us using SVG tspan was whether we’d have to specify x and y attributes, but, as it panned out, no, the SVG text element nesting the tspan takes care of that, so, “top supportive” we’d say, and a lot like how we think of the HTML span element working, and helping out, enormously!
Into “Day 2” though, and we’ll be wanting to do Javascript DOM things in the “overlay” line of thinking. So part of a “Day 1” paradigm, you will better leave that “Day 1” proving the work of “Day 2” is possible, and this was achieved via …
function detecttspan() {
var tsrect=null;
var tss=document.getElementsByTagName('tspan');
for (var itss=0; itss<tss.length; itss++) {
tsrect=tss[itss].getBoundingClientRect();
alert('' + tss[itss].outerHTML + ' left:' + tsrect.left + ' top:' + tsrect.top);
}
}
… with the good news we started “Day 1” not being sure of “passed the test”, as you can see from today’s tutorial picture, and …
privacy for Group Talk “public” Bulletin Board functionalities …
involved logic for the two scenarios …
data-applyprivacy=Y … via two prefixing spaces entered by originator of Group … completely hides relevant Group Talk Bulletin Board data from viewers outside that Group Talk
data-applyprivacy=y … via one prefixing space entered by originator of Group … hides contact parts of Group Talk Bulletin Board data from viewers outside that Group Talk
… but we had not “nuanced” the functionality for that second suboption on that first subpass
… and that is the work discussed today, a nuance that amounts to …
Allow non-group Bulletin Board readers see what we say but given cryptic username choices will not know how to contact that Group
Select Multiple Webpage Palette Speech Bubble Group Talk Privacy Tutorial
Meanwhile, back at some other ranch … somewhere … we’re some of the way down the line, with our recent …
Select Multiple Webpage Palette web application …
Bulletin Board subset of functionality, towards with it’s …
Group Talk (comma separated list of username/contacts) abilities … now offer …
Bulletin Board privacy
… as people in a Group Talk may appreciate. In other words, your generic Bulletin Board viewers would not see your Group Talk setup communications should the originator of any Group Talk now, either at …
best, as a To: + spaces appendage to a textarea line record (delimited by line feed) … ahead of a way with …
spaces prefixing to the prompt widow off right click or gesture events … starting the ball rolling …
populating a new data-applyprivacy global data attribute into the SVG
… allowing this new privacy functionality to work.
Again, we’ll need more than the work today to bed this in, but we now do not think there are any impassable concepts to its implementation.
… and allowing for emojis within a Group Talk user’s username (via control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard) be an identifier on their Speech Bubbles … well, it leaves us speechless with nuance!
Yesterday we were attempting to do this but had more success, today, with …
/**
* Convert a string to HTML entities ... Thanks to https://zditect.com/code/javascript/easy-solution-to-encode-html-entities-in-javascript.html
*/
String.prototype.toHtmlEntities = function() {
return this.replace(/./gm, function(s) {
return (s.match(/[a-z0-9" . "\\" . "s]+/i)) ? s : '' + s.charCodeAt(0) + ';';
});
};
function maybeemoji(insvg) {
var outthing='', newoutthing='', jb=0;
var outsvg=insvg;
//alert('0:' + outsvg);
if (outsvg.indexOf(' data-otherc') != -1 && outsvg.indexOf(' data-ip') != -1) {
outsvg=outsvg.replace(outsvg.split(' data-otherc')[1].split(' data-ip')[0],'').split('97%')[0];
}
//alert(outsvg);
outhtmlentities='';
nonouthtmlentities='';
var nonencodeds=outsvg.split('');
for (jb=1; jb<nonencodeds.length; jb++) {
if (eval('' + nonencodeds[jb].split(';')[0]) >= 1000 && nonouthtmlentities == '') {
outhtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
newoutthing+=String.fromCodePoint(eval('' + nonencodeds[jb].split(';')[0]));
if (nonencodeds[jb] != (nonencodeds[jb].split(';')[0] + ';')) {
nonouthtmlentities=' ';
}
} else if (outhtmlentities != '') {
nonouthtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
}
}
if (outhtmlentities != '') { outthing=outhtmlentities; }
help differentiate Speech Bubbles of different users in a Group Talk arrangement with our public Bulletin Board functionality
Today’s research into displaying emoji text at the pointy corner of the Speech Bubble hopes to help out here, and though we may have nuances yet to come, we can say with the changedselect_palette.htmlweb application helped out by the changedselect_palette.php “fifth draft” PHP we have made a start making this “emoji dream” happen.
we need to consider user IP addresses, as Wikipedia describes …
An Internet Protocol address (IP address) is a numerical label such as 192.0.2.1 that is assigned to a device connected to a computer network that uses the Internet Protocol for communication.[1][2] IP addresses serve two main functions: network interface identification, and location addressing.
Some readers may have noted for a couple of days now, our newly introduced PHP has been assisting the calling HTML, and itself, by remembering the user’s IP address. Yesterday, it was to help colour code Speech Bubbles, and today, it helps in amongst …
The concept of Group Talk started with yesterday’s Select Multiple Webpage Palette Speech Bubble Invitations Tutorial. It made us think that we should start thinking about the differentiation of voices amongst the Speech Bubbles of the public Bulletin Board we’re supporting with the associated web application and its user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic talents.
We decided that one way could be to …
Colour Code the background colour of the Speech Bubbles via the user IP address …
<?php
$gbcol="0,0,255";
function server_remote_addr() {
global $gbcol;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
$uas=explode('.', str_replace('::1','65.254.95.247',$rma)); // 65.254.93.32
the day before’s SVG data enhancemants … today improves yesterday’s …
public Bulletin Board via user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logics … today, adding …
optional invitation communication email and/or SMS logics via Group Talk set comma separated optional user username/contact entered data set lists helping with Group Talk filtering means of filtering the Speech Bubble data
… around here a lot, as PHP is our domain’s “first call” serverside language.
Add to that that “yesterday’s tomorrow is today” we’re supposed to be finished with our “short two day mini project sojourn”, and in a crude way we have, but we want a third day to add nuance to the arrangements with data filtering and more sophistication regarding collection, within the approach of our new …
Yes, all possible with SVG, though not the first thing we think of using SVG data within our HTML. We normally think, just display thoughts, but today, we’re paving the way for tomorrow, and our “short two day mini project sojourn” will become clearer regarding motives, then, or get hints trying with strategically changedselect_palette.htmlweb application‘s mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic …
var taar=[];
var preadd=0;
var windowuser='', windowcontact='', windowask=true, suffix='';
We rethought yesterday’s HTML textarea start regarding line feed Speech Bubble creation possibilities, and thought …
It’s too unwieldy for a user to add to their textual data when what they really want to do is Speech Bubbles.
Yesterday’s thinking really hoped the user entered a Speech Bubble data one at a time, but what if the user wants to enter several Speech Bubbles in the one textarea incarnation?
Good question. (Calling all ducks with a slow paddle going?!) …
Yes, but there is that ~~ existing delimitation rule, as of yesterday equating to a line feed. Supposing ~~ was given the delimitation roles …
the character sets … lineFeed~~lineFeed
… separate Speech Bubbles … ie. in the textarea a ~~ record is all there is on a line of textarea text
the character set … ~~lineFeed
… at the start wipes out any previously remembered text data and starts again
else retain the ~~ mapping to lineFeed
… in combination with the textarea always first presented blank and the previous Speech Bubble or Lines of Text remembered and retained unless the middle condition above happens?
ask for user interactive input via a window.open (ie. popup) “here’s looking at you, kid” window.opener incarnation guise of our changedselect_palette.htmlweb application … just consisting of …
still capable of ~~ delimitation as with the Javascript prompt window thinking … but also now …
harnessing the talents of a textarea line feed delimitation within it’s value attribute
… able to extend functionality towards decent …
speech bubble feeling thoughts (so far, just) … because …
it opens up the idea that the div element innerHTML attribute can be the SVG we had previously been supplying as background HTML/CSS (via Javascript DOM) data
Cute, huh?! (ahead of the “Speech Bubble styling” niceties making it really cute, yet, for us … but who knows what you can achieve on the “cute styling front”?!).
In the world of web applications, there are often many ways to approach any given requirement. Like with yesterday’s Select Multiple Mobile Background Image Tutorial, today’s “albeit a bit out there idea” is to …
offer a select (multiple attribute) “dropdown” HTML element …
as a webpage covering …
template or palette … where the user …
writes user defined lines of words created
… onto. Pretty simple idea for a “firstthenseconddraft“! But maybe not the first idea to spring to mind regarding making such an idea happen?!
<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";
}
}
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?!).
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 ChartsAnnotated 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 🗺 🗺 emoji button.
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!
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.
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.
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 ChartGeo 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?!
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;>🇦🇺</span>) …
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) …
“dynamic” Javascript DOM HTML “style” attribute changes
“dynamic” Javascript DOM “class” modifications to dovetail with the “static” internal CSS coding as above
… 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 …
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'; }
… 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
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) …
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.
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); “>” …
… 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.
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 …
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 …
onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)
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” …
position:absolute property (with associated top and left (px defined) properties)
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 …
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 …
… 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”.
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 …
a known entity … ie. same web application … at …
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 changedwls_vs_php.htmCapital 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;
}
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.
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.htmlCapital 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 …
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 …
localStorage was a known web browser piece of functionality
… and so as per our localStorage logic we …
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.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
… describing the HTML elements added for mobile usage, here. Even then, annoyingly, if you tapped on one of these, the Javascript would too often call function addcontents in a way we thought was aggravating, and so we resorted to a global variable usage and started doing as below …
var allowed=true;
function addcontents(inboc) {
if (!allowed) {
allowed=true;
return false;
}
var nboc='', seventeen="17", zero=0, numlines=1, one=1, grest='', ghuh='', wasfound=false, jnew=0;
// blah blah blah open textarea popup window blah blah blah
}
function notallowed() {
allowed=false;
setTimeout(function(){ allowed=true; }, 1000);
}
Well, onto yesterday’s SVG Tspan Element Primer Tutorial our “two day” job is “two days” of sorts. Definitely for non-mobile, deploying the “inline audio stream of YouTube video play” concept we wanted, but for mobile, let me “count the ways” …
to get any functionality down to “one tap/click to play” … well …
we tried for mobile, and haven’t given up, but the complexity of “overlay” related z-index and “where to place iframe element” issues exploded my tiny little brain … and so …
for mobile we’ve “parked” the ideal solution … in favour of, for now …
the mobile “two day solution” that, like for non-mobile, underlines those 11 characterYouTubereferences as links that can navigate interested users to a new tab/window YouTube window to play the “whole shebang” (and … sigh … needing that extra tap/click) … leaving …
Days 3 (and on) to nuance
Another project where the last 10% nuances is probably going to take more time than the rest! Anyway, we’ll see how this “mini project” develops.
now SVG tspan savvy external Javascript ytaudioonly.js assisting YouTube Audio Stream of Video Plays … specifically …
// blah blah blah
var thespansare=[];
function ihun(ao) {
var aih=ao.innerText;
if (aih.trim() != '') {
var newihis='';
for (var iaih=0; iaih<aih.length; iaih++) {
newihis+='_';
}
ao.innerHTML=newihis;
}
}
regarding improvements to existant functionality it is most important to not interfere with any current functionality … and then …
implement new functionalities off this platform
… and with our “mini project” of embellishing 11 letter words in the Speech Bubbles of our Select Multiple Webpage Palette Speech Bubble web application of recent times, we have a natural compartmentalization playing out mimicking those ideas above, that goes …
Day 1 – work with the data that is the HTML (and SVG) of Speech Bubbles where they look and behave as ever, but 11 letter words get nested into SVG tspan elements
Day 2 – embellish the web application via those SVG tspan elements
It’s our first go using SVG tspan elements as a “forward thinking” tool, and it helped us thinking on this regarding the corrollaries to HTML span element. What initially concerned us using SVG tspan was whether we’d have to specify x and y attributes, but, as it panned out, no, the SVG text element nesting the tspan takes care of that, so, “top supportive” we’d say, and a lot like how we think of the HTML span element working, and helping out, enormously!
Into “Day 2” though, and we’ll be wanting to do Javascript DOM things in the “overlay” line of thinking. So part of a “Day 1” paradigm, you will better leave that “Day 1” proving the work of “Day 2” is possible, and this was achieved via …
function detecttspan() {
var tsrect=null;
var tss=document.getElementsByTagName('tspan');
for (var itss=0; itss<tss.length; itss++) {
tsrect=tss[itss].getBoundingClientRect();
alert('' + tss[itss].outerHTML + ' left:' + tsrect.left + ' top:' + tsrect.top);
}
}
… with the good news we started “Day 1” not being sure of “passed the test”, as you can see from today’s tutorial picture, and …
privacy for Group Talk “public” Bulletin Board functionalities …
involved logic for the two scenarios …
data-applyprivacy=Y … via two prefixing spaces entered by originator of Group … completely hides relevant Group Talk Bulletin Board data from viewers outside that Group Talk
data-applyprivacy=y … via one prefixing space entered by originator of Group … hides contact parts of Group Talk Bulletin Board data from viewers outside that Group Talk
… but we had not “nuanced” the functionality for that second suboption on that first subpass
… and that is the work discussed today, a nuance that amounts to …
Allow non-group Bulletin Board readers see what we say but given cryptic username choices will not know how to contact that Group
Select Multiple Webpage Palette Speech Bubble Group Talk Privacy Tutorial
Meanwhile, back at some other ranch … somewhere … we’re some of the way down the line, with our recent …
Select Multiple Webpage Palette web application …
Bulletin Board subset of functionality, towards with it’s …
Group Talk (comma separated list of username/contacts) abilities … now offer …
Bulletin Board privacy
… as people in a Group Talk may appreciate. In other words, your generic Bulletin Board viewers would not see your Group Talk setup communications should the originator of any Group Talk now, either at …
best, as a To: + spaces appendage to a textarea line record (delimited by line feed) … ahead of a way with …
spaces prefixing to the prompt widow off right click or gesture events … starting the ball rolling …
populating a new data-applyprivacy global data attribute into the SVG
… allowing this new privacy functionality to work.
Again, we’ll need more than the work today to bed this in, but we now do not think there are any impassable concepts to its implementation.
… and allowing for emojis within a Group Talk user’s username (via control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard) be an identifier on their Speech Bubbles … well, it leaves us speechless with nuance!
Yesterday we were attempting to do this but had more success, today, with …
/**
* Convert a string to HTML entities ... Thanks to https://zditect.com/code/javascript/easy-solution-to-encode-html-entities-in-javascript.html
*/
String.prototype.toHtmlEntities = function() {
return this.replace(/./gm, function(s) {
return (s.match(/[a-z0-9" . "\\" . "s]+/i)) ? s : '' + s.charCodeAt(0) + ';';
});
};
function maybeemoji(insvg) {
var outthing='', newoutthing='', jb=0;
var outsvg=insvg;
//alert('0:' + outsvg);
if (outsvg.indexOf(' data-otherc') != -1 && outsvg.indexOf(' data-ip') != -1) {
outsvg=outsvg.replace(outsvg.split(' data-otherc')[1].split(' data-ip')[0],'').split('97%')[0];
}
//alert(outsvg);
outhtmlentities='';
nonouthtmlentities='';
var nonencodeds=outsvg.split('');
for (jb=1; jb<nonencodeds.length; jb++) {
if (eval('' + nonencodeds[jb].split(';')[0]) >= 1000 && nonouthtmlentities == '') {
outhtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
newoutthing+=String.fromCodePoint(eval('' + nonencodeds[jb].split(';')[0]));
if (nonencodeds[jb] != (nonencodeds[jb].split(';')[0] + ';')) {
nonouthtmlentities=' ';
}
} else if (outhtmlentities != '') {
nonouthtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
}
}
if (outhtmlentities != '') { outthing=outhtmlentities; }
help differentiate Speech Bubbles of different users in a Group Talk arrangement with our public Bulletin Board functionality
Today’s research into displaying emoji text at the pointy corner of the Speech Bubble hopes to help out here, and though we may have nuances yet to come, we can say with the changedselect_palette.htmlweb application helped out by the changedselect_palette.php “fifth draft” PHP we have made a start making this “emoji dream” happen.
we need to consider user IP addresses, as Wikipedia describes …
An Internet Protocol address (IP address) is a numerical label such as 192.0.2.1 that is assigned to a device connected to a computer network that uses the Internet Protocol for communication.[1][2] IP addresses serve two main functions: network interface identification, and location addressing.
Some readers may have noted for a couple of days now, our newly introduced PHP has been assisting the calling HTML, and itself, by remembering the user’s IP address. Yesterday, it was to help colour code Speech Bubbles, and today, it helps in amongst …
The concept of Group Talk started with yesterday’s Select Multiple Webpage Palette Speech Bubble Invitations Tutorial. It made us think that we should start thinking about the differentiation of voices amongst the Speech Bubbles of the public Bulletin Board we’re supporting with the associated web application and its user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic talents.
We decided that one way could be to …
Colour Code the background colour of the Speech Bubbles via the user IP address …
<?php
$gbcol="0,0,255";
function server_remote_addr() {
global $gbcol;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
$uas=explode('.', str_replace('::1','65.254.95.247',$rma)); // 65.254.93.32
the day before’s SVG data enhancemants … today improves yesterday’s …
public Bulletin Board via user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logics … today, adding …
optional invitation communication email and/or SMS logics via Group Talk set comma separated optional user username/contact entered data set lists helping with Group Talk filtering means of filtering the Speech Bubble data
… around here a lot, as PHP is our domain’s “first call” serverside language.
Add to that that “yesterday’s tomorrow is today” we’re supposed to be finished with our “short two day mini project sojourn”, and in a crude way we have, but we want a third day to add nuance to the arrangements with data filtering and more sophistication regarding collection, within the approach of our new …
Yes, all possible with SVG, though not the first thing we think of using SVG data within our HTML. We normally think, just display thoughts, but today, we’re paving the way for tomorrow, and our “short two day mini project sojourn” will become clearer regarding motives, then, or get hints trying with strategically changedselect_palette.htmlweb application‘s mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic …
var taar=[];
var preadd=0;
var windowuser='', windowcontact='', windowask=true, suffix='';
We rethought yesterday’s HTML textarea start regarding line feed Speech Bubble creation possibilities, and thought …
It’s too unwieldy for a user to add to their textual data when what they really want to do is Speech Bubbles.
Yesterday’s thinking really hoped the user entered a Speech Bubble data one at a time, but what if the user wants to enter several Speech Bubbles in the one textarea incarnation?
Good question. (Calling all ducks with a slow paddle going?!) …
Yes, but there is that ~~ existing delimitation rule, as of yesterday equating to a line feed. Supposing ~~ was given the delimitation roles …
the character sets … lineFeed~~lineFeed
… separate Speech Bubbles … ie. in the textarea a ~~ record is all there is on a line of textarea text
the character set … ~~lineFeed
… at the start wipes out any previously remembered text data and starts again
else retain the ~~ mapping to lineFeed
… in combination with the textarea always first presented blank and the previous Speech Bubble or Lines of Text remembered and retained unless the middle condition above happens?
ask for user interactive input via a window.open (ie. popup) “here’s looking at you, kid” window.opener incarnation guise of our changedselect_palette.htmlweb application … just consisting of …
still capable of ~~ delimitation as with the Javascript prompt window thinking … but also now …
harnessing the talents of a textarea line feed delimitation within it’s value attribute
… able to extend functionality towards decent …
speech bubble feeling thoughts (so far, just) … because …
it opens up the idea that the div element innerHTML attribute can be the SVG we had previously been supplying as background HTML/CSS (via Javascript DOM) data
Cute, huh?! (ahead of the “Speech Bubble styling” niceties making it really cute, yet, for us … but who knows what you can achieve on the “cute styling front”?!).
In the world of web applications, there are often many ways to approach any given requirement. Like with yesterday’s Select Multiple Mobile Background Image Tutorial, today’s “albeit a bit out there idea” is to …
offer a select (multiple attribute) “dropdown” HTML element …
as a webpage covering …
template or palette … where the user …
writes user defined lines of words created
… onto. Pretty simple idea for a “firstthenseconddraft“! But maybe not the first idea to spring to mind regarding making such an idea happen?!
<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";
}
}
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?!).
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 ChartsAnnotated 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 🗺 🗺 emoji button.
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!
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.
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.
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 ChartGeo 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?!
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;>🇦🇺</span>) …
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) …
“dynamic” Javascript DOM HTML “style” attribute changes
“dynamic” Javascript DOM “class” modifications to dovetail with the “static” internal CSS coding as above
… 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 …
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'; }
… 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
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) …
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.
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); “>” …
… 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.
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 …
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 …
onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)
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” …
position:absolute property (with associated top and left (px defined) properties)
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 …
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 …
… 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”.
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 …
a known entity … ie. same web application … at …
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 changedwls_vs_php.htmCapital 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;
}
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.
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.htmlCapital 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 …
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 …
localStorage was a known web browser piece of functionality
… and so as per our localStorage logic we …
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.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
… describing the HTML elements added for mobile usage, here. Even then, annoyingly, if you tapped on one of these, the Javascript would too often call function addcontents in a way we thought was aggravating, and so we resorted to a global variable usage and started doing as below …
var allowed=true;
function addcontents(inboc) {
if (!allowed) {
allowed=true;
return false;
}
var nboc='', seventeen="17", zero=0, numlines=1, one=1, grest='', ghuh='', wasfound=false, jnew=0;
// blah blah blah open textarea popup window blah blah blah
}
function notallowed() {
allowed=false;
setTimeout(function(){ allowed=true; }, 1000);
}
Well, onto yesterday’s SVG Tspan Element Primer Tutorial our “two day” job is “two days” of sorts. Definitely for non-mobile, deploying the “inline audio stream of YouTube video play” concept we wanted, but for mobile, let me “count the ways” …
to get any functionality down to “one tap/click to play” … well …
we tried for mobile, and haven’t given up, but the complexity of “overlay” related z-index and “where to place iframe element” issues exploded my tiny little brain … and so …
for mobile we’ve “parked” the ideal solution … in favour of, for now …
the mobile “two day solution” that, like for non-mobile, underlines those 11 characterYouTubereferences as links that can navigate interested users to a new tab/window YouTube window to play the “whole shebang” (and … sigh … needing that extra tap/click) … leaving …
Days 3 (and on) to nuance
Another project where the last 10% nuances is probably going to take more time than the rest! Anyway, we’ll see how this “mini project” develops.
now SVG tspan savvy external Javascript ytaudioonly.js assisting YouTube Audio Stream of Video Plays … specifically …
// blah blah blah
var thespansare=[];
function ihun(ao) {
var aih=ao.innerText;
if (aih.trim() != '') {
var newihis='';
for (var iaih=0; iaih<aih.length; iaih++) {
newihis+='_';
}
ao.innerHTML=newihis;
}
}
regarding improvements to existant functionality it is most important to not interfere with any current functionality … and then …
implement new functionalities off this platform
… and with our “mini project” of embellishing 11 letter words in the Speech Bubbles of our Select Multiple Webpage Palette Speech Bubble web application of recent times, we have a natural compartmentalization playing out mimicking those ideas above, that goes …
Day 1 – work with the data that is the HTML (and SVG) of Speech Bubbles where they look and behave as ever, but 11 letter words get nested into SVG tspan elements
Day 2 – embellish the web application via those SVG tspan elements
It’s our first go using SVG tspan elements as a “forward thinking” tool, and it helped us thinking on this regarding the corrollaries to HTML span element. What initially concerned us using SVG tspan was whether we’d have to specify x and y attributes, but, as it panned out, no, the SVG text element nesting the tspan takes care of that, so, “top supportive” we’d say, and a lot like how we think of the HTML span element working, and helping out, enormously!
Into “Day 2” though, and we’ll be wanting to do Javascript DOM things in the “overlay” line of thinking. So part of a “Day 1” paradigm, you will better leave that “Day 1” proving the work of “Day 2” is possible, and this was achieved via …
function detecttspan() {
var tsrect=null;
var tss=document.getElementsByTagName('tspan');
for (var itss=0; itss<tss.length; itss++) {
tsrect=tss[itss].getBoundingClientRect();
alert('' + tss[itss].outerHTML + ' left:' + tsrect.left + ' top:' + tsrect.top);
}
}
… with the good news we started “Day 1” not being sure of “passed the test”, as you can see from today’s tutorial picture, and …
privacy for Group Talk “public” Bulletin Board functionalities …
involved logic for the two scenarios …
data-applyprivacy=Y … via two prefixing spaces entered by originator of Group … completely hides relevant Group Talk Bulletin Board data from viewers outside that Group Talk
data-applyprivacy=y … via one prefixing space entered by originator of Group … hides contact parts of Group Talk Bulletin Board data from viewers outside that Group Talk
… but we had not “nuanced” the functionality for that second suboption on that first subpass
… and that is the work discussed today, a nuance that amounts to …
Allow non-group Bulletin Board readers see what we say but given cryptic username choices will not know how to contact that Group
Select Multiple Webpage Palette Speech Bubble Group Talk Privacy Tutorial
Meanwhile, back at some other ranch … somewhere … we’re some of the way down the line, with our recent …
Select Multiple Webpage Palette web application …
Bulletin Board subset of functionality, towards with it’s …
Group Talk (comma separated list of username/contacts) abilities … now offer …
Bulletin Board privacy
… as people in a Group Talk may appreciate. In other words, your generic Bulletin Board viewers would not see your Group Talk setup communications should the originator of any Group Talk now, either at …
best, as a To: + spaces appendage to a textarea line record (delimited by line feed) … ahead of a way with …
spaces prefixing to the prompt widow off right click or gesture events … starting the ball rolling …
populating a new data-applyprivacy global data attribute into the SVG
… allowing this new privacy functionality to work.
Again, we’ll need more than the work today to bed this in, but we now do not think there are any impassable concepts to its implementation.
… and allowing for emojis within a Group Talk user’s username (via control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard) be an identifier on their Speech Bubbles … well, it leaves us speechless with nuance!
Yesterday we were attempting to do this but had more success, today, with …
/**
* Convert a string to HTML entities ... Thanks to https://zditect.com/code/javascript/easy-solution-to-encode-html-entities-in-javascript.html
*/
String.prototype.toHtmlEntities = function() {
return this.replace(/./gm, function(s) {
return (s.match(/[a-z0-9" . "\\" . "s]+/i)) ? s : '' + s.charCodeAt(0) + ';';
});
};
function maybeemoji(insvg) {
var outthing='', newoutthing='', jb=0;
var outsvg=insvg;
//alert('0:' + outsvg);
if (outsvg.indexOf(' data-otherc') != -1 && outsvg.indexOf(' data-ip') != -1) {
outsvg=outsvg.replace(outsvg.split(' data-otherc')[1].split(' data-ip')[0],'').split('97%')[0];
}
//alert(outsvg);
outhtmlentities='';
nonouthtmlentities='';
var nonencodeds=outsvg.split('');
for (jb=1; jb<nonencodeds.length; jb++) {
if (eval('' + nonencodeds[jb].split(';')[0]) >= 1000 && nonouthtmlentities == '') {
outhtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
newoutthing+=String.fromCodePoint(eval('' + nonencodeds[jb].split(';')[0]));
if (nonencodeds[jb] != (nonencodeds[jb].split(';')[0] + ';')) {
nonouthtmlentities=' ';
}
} else if (outhtmlentities != '') {
nonouthtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
}
}
if (outhtmlentities != '') { outthing=outhtmlentities; }
help differentiate Speech Bubbles of different users in a Group Talk arrangement with our public Bulletin Board functionality
Today’s research into displaying emoji text at the pointy corner of the Speech Bubble hopes to help out here, and though we may have nuances yet to come, we can say with the changedselect_palette.htmlweb application helped out by the changedselect_palette.php “fifth draft” PHP we have made a start making this “emoji dream” happen.
we need to consider user IP addresses, as Wikipedia describes …
An Internet Protocol address (IP address) is a numerical label such as 192.0.2.1 that is assigned to a device connected to a computer network that uses the Internet Protocol for communication.[1][2] IP addresses serve two main functions: network interface identification, and location addressing.
Some readers may have noted for a couple of days now, our newly introduced PHP has been assisting the calling HTML, and itself, by remembering the user’s IP address. Yesterday, it was to help colour code Speech Bubbles, and today, it helps in amongst …
The concept of Group Talk started with yesterday’s Select Multiple Webpage Palette Speech Bubble Invitations Tutorial. It made us think that we should start thinking about the differentiation of voices amongst the Speech Bubbles of the public Bulletin Board we’re supporting with the associated web application and its user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic talents.
We decided that one way could be to …
Colour Code the background colour of the Speech Bubbles via the user IP address …
<?php
$gbcol="0,0,255";
function server_remote_addr() {
global $gbcol;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
$uas=explode('.', str_replace('::1','65.254.95.247',$rma)); // 65.254.93.32
the day before’s SVG data enhancemants … today improves yesterday’s …
public Bulletin Board via user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logics … today, adding …
optional invitation communication email and/or SMS logics via Group Talk set comma separated optional user username/contact entered data set lists helping with Group Talk filtering means of filtering the Speech Bubble data
… around here a lot, as PHP is our domain’s “first call” serverside language.
Add to that that “yesterday’s tomorrow is today” we’re supposed to be finished with our “short two day mini project sojourn”, and in a crude way we have, but we want a third day to add nuance to the arrangements with data filtering and more sophistication regarding collection, within the approach of our new …
Yes, all possible with SVG, though not the first thing we think of using SVG data within our HTML. We normally think, just display thoughts, but today, we’re paving the way for tomorrow, and our “short two day mini project sojourn” will become clearer regarding motives, then, or get hints trying with strategically changedselect_palette.htmlweb application‘s mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic …
var taar=[];
var preadd=0;
var windowuser='', windowcontact='', windowask=true, suffix='';
We rethought yesterday’s HTML textarea start regarding line feed Speech Bubble creation possibilities, and thought …
It’s too unwieldy for a user to add to their textual data when what they really want to do is Speech Bubbles.
Yesterday’s thinking really hoped the user entered a Speech Bubble data one at a time, but what if the user wants to enter several Speech Bubbles in the one textarea incarnation?
Good question. (Calling all ducks with a slow paddle going?!) …
Yes, but there is that ~~ existing delimitation rule, as of yesterday equating to a line feed. Supposing ~~ was given the delimitation roles …
the character sets … lineFeed~~lineFeed
… separate Speech Bubbles … ie. in the textarea a ~~ record is all there is on a line of textarea text
the character set … ~~lineFeed
… at the start wipes out any previously remembered text data and starts again
else retain the ~~ mapping to lineFeed
… in combination with the textarea always first presented blank and the previous Speech Bubble or Lines of Text remembered and retained unless the middle condition above happens?
ask for user interactive input via a window.open (ie. popup) “here’s looking at you, kid” window.opener incarnation guise of our changedselect_palette.htmlweb application … just consisting of …
still capable of ~~ delimitation as with the Javascript prompt window thinking … but also now …
harnessing the talents of a textarea line feed delimitation within it’s value attribute
… able to extend functionality towards decent …
speech bubble feeling thoughts (so far, just) … because …
it opens up the idea that the div element innerHTML attribute can be the SVG we had previously been supplying as background HTML/CSS (via Javascript DOM) data
Cute, huh?! (ahead of the “Speech Bubble styling” niceties making it really cute, yet, for us … but who knows what you can achieve on the “cute styling front”?!).
In the world of web applications, there are often many ways to approach any given requirement. Like with yesterday’s Select Multiple Mobile Background Image Tutorial, today’s “albeit a bit out there idea” is to …
offer a select (multiple attribute) “dropdown” HTML element …
as a webpage covering …
template or palette … where the user …
writes user defined lines of words created
… onto. Pretty simple idea for a “firstthenseconddraft“! But maybe not the first idea to spring to mind regarding making such an idea happen?!
<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";
}
}
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?!).
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 ChartsAnnotated 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 🗺 🗺 emoji button.
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!
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.
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.
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 ChartGeo 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?!
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;>🇦🇺</span>) …
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) …
“dynamic” Javascript DOM HTML “style” attribute changes
“dynamic” Javascript DOM “class” modifications to dovetail with the “static” internal CSS coding as above
… 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 …
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'; }
… 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
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) …
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.
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); “>” …
… 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.
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 …
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 …
onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)
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” …
position:absolute property (with associated top and left (px defined) properties)
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 …
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 …
… 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”.
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 …
a known entity … ie. same web application … at …
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 changedwls_vs_php.htmCapital 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;
}
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.
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.htmlCapital 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 …
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 …
localStorage was a known web browser piece of functionality
… and so as per our localStorage logic we …
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.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
Well, onto yesterday’s SVG Tspan Element Primer Tutorial our “two day” job is “two days” of sorts. Definitely for non-mobile, deploying the “inline audio stream of YouTube video play” concept we wanted, but for mobile, let me “count the ways” …
to get any functionality down to “one tap/click to play” … well …
we tried for mobile, and haven’t given up, but the complexity of “overlay” related z-index and “where to place iframe element” issues exploded my tiny little brain … and so …
for mobile we’ve “parked” the ideal solution … in favour of, for now …
the mobile “two day solution” that, like for non-mobile, underlines those 11 characterYouTubereferences as links that can navigate interested users to a new tab/window YouTube window to play the “whole shebang” (and … sigh … needing that extra tap/click) … leaving …
Days 3 (and on) to nuance
Another project where the last 10% nuances is probably going to take more time than the rest! Anyway, we’ll see how this “mini project” develops.
now SVG tspan savvy external Javascript ytaudioonly.js assisting YouTube Audio Stream of Video Plays … specifically …
// blah blah blah
var thespansare=[];
function ihun(ao) {
var aih=ao.innerText;
if (aih.trim() != '') {
var newihis='';
for (var iaih=0; iaih<aih.length; iaih++) {
newihis+='_';
}
ao.innerHTML=newihis;
}
}
regarding improvements to existant functionality it is most important to not interfere with any current functionality … and then …
implement new functionalities off this platform
… and with our “mini project” of embellishing 11 letter words in the Speech Bubbles of our Select Multiple Webpage Palette Speech Bubble web application of recent times, we have a natural compartmentalization playing out mimicking those ideas above, that goes …
Day 1 – work with the data that is the HTML (and SVG) of Speech Bubbles where they look and behave as ever, but 11 letter words get nested into SVG tspan elements
Day 2 – embellish the web application via those SVG tspan elements
It’s our first go using SVG tspan elements as a “forward thinking” tool, and it helped us thinking on this regarding the corrollaries to HTML span element. What initially concerned us using SVG tspan was whether we’d have to specify x and y attributes, but, as it panned out, no, the SVG text element nesting the tspan takes care of that, so, “top supportive” we’d say, and a lot like how we think of the HTML span element working, and helping out, enormously!
Into “Day 2” though, and we’ll be wanting to do Javascript DOM things in the “overlay” line of thinking. So part of a “Day 1” paradigm, you will better leave that “Day 1” proving the work of “Day 2” is possible, and this was achieved via …
function detecttspan() {
var tsrect=null;
var tss=document.getElementsByTagName('tspan');
for (var itss=0; itss<tss.length; itss++) {
tsrect=tss[itss].getBoundingClientRect();
alert('' + tss[itss].outerHTML + ' left:' + tsrect.left + ' top:' + tsrect.top);
}
}
… with the good news we started “Day 1” not being sure of “passed the test”, as you can see from today’s tutorial picture, and …
privacy for Group Talk “public” Bulletin Board functionalities …
involved logic for the two scenarios …
data-applyprivacy=Y … via two prefixing spaces entered by originator of Group … completely hides relevant Group Talk Bulletin Board data from viewers outside that Group Talk
data-applyprivacy=y … via one prefixing space entered by originator of Group … hides contact parts of Group Talk Bulletin Board data from viewers outside that Group Talk
… but we had not “nuanced” the functionality for that second suboption on that first subpass
… and that is the work discussed today, a nuance that amounts to …
Allow non-group Bulletin Board readers see what we say but given cryptic username choices will not know how to contact that Group
Select Multiple Webpage Palette Speech Bubble Group Talk Privacy Tutorial
Meanwhile, back at some other ranch … somewhere … we’re some of the way down the line, with our recent …
Select Multiple Webpage Palette web application …
Bulletin Board subset of functionality, towards with it’s …
Group Talk (comma separated list of username/contacts) abilities … now offer …
Bulletin Board privacy
… as people in a Group Talk may appreciate. In other words, your generic Bulletin Board viewers would not see your Group Talk setup communications should the originator of any Group Talk now, either at …
best, as a To: + spaces appendage to a textarea line record (delimited by line feed) … ahead of a way with …
spaces prefixing to the prompt widow off right click or gesture events … starting the ball rolling …
populating a new data-applyprivacy global data attribute into the SVG
… allowing this new privacy functionality to work.
Again, we’ll need more than the work today to bed this in, but we now do not think there are any impassable concepts to its implementation.
… and allowing for emojis within a Group Talk user’s username (via control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard) be an identifier on their Speech Bubbles … well, it leaves us speechless with nuance!
Yesterday we were attempting to do this but had more success, today, with …
/**
* Convert a string to HTML entities ... Thanks to https://zditect.com/code/javascript/easy-solution-to-encode-html-entities-in-javascript.html
*/
String.prototype.toHtmlEntities = function() {
return this.replace(/./gm, function(s) {
return (s.match(/[a-z0-9" . "\\" . "s]+/i)) ? s : '' + s.charCodeAt(0) + ';';
});
};
function maybeemoji(insvg) {
var outthing='', newoutthing='', jb=0;
var outsvg=insvg;
//alert('0:' + outsvg);
if (outsvg.indexOf(' data-otherc') != -1 && outsvg.indexOf(' data-ip') != -1) {
outsvg=outsvg.replace(outsvg.split(' data-otherc')[1].split(' data-ip')[0],'').split('97%')[0];
}
//alert(outsvg);
outhtmlentities='';
nonouthtmlentities='';
var nonencodeds=outsvg.split('');
for (jb=1; jb<nonencodeds.length; jb++) {
if (eval('' + nonencodeds[jb].split(';')[0]) >= 1000 && nonouthtmlentities == '') {
outhtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
newoutthing+=String.fromCodePoint(eval('' + nonencodeds[jb].split(';')[0]));
if (nonencodeds[jb] != (nonencodeds[jb].split(';')[0] + ';')) {
nonouthtmlentities=' ';
}
} else if (outhtmlentities != '') {
nonouthtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
}
}
if (outhtmlentities != '') { outthing=outhtmlentities; }
help differentiate Speech Bubbles of different users in a Group Talk arrangement with our public Bulletin Board functionality
Today’s research into displaying emoji text at the pointy corner of the Speech Bubble hopes to help out here, and though we may have nuances yet to come, we can say with the changedselect_palette.htmlweb application helped out by the changedselect_palette.php “fifth draft” PHP we have made a start making this “emoji dream” happen.
we need to consider user IP addresses, as Wikipedia describes …
An Internet Protocol address (IP address) is a numerical label such as 192.0.2.1 that is assigned to a device connected to a computer network that uses the Internet Protocol for communication.[1][2] IP addresses serve two main functions: network interface identification, and location addressing.
Some readers may have noted for a couple of days now, our newly introduced PHP has been assisting the calling HTML, and itself, by remembering the user’s IP address. Yesterday, it was to help colour code Speech Bubbles, and today, it helps in amongst …
The concept of Group Talk started with yesterday’s Select Multiple Webpage Palette Speech Bubble Invitations Tutorial. It made us think that we should start thinking about the differentiation of voices amongst the Speech Bubbles of the public Bulletin Board we’re supporting with the associated web application and its user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic talents.
We decided that one way could be to …
Colour Code the background colour of the Speech Bubbles via the user IP address …
<?php
$gbcol="0,0,255";
function server_remote_addr() {
global $gbcol;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
$uas=explode('.', str_replace('::1','65.254.95.247',$rma)); // 65.254.93.32
the day before’s SVG data enhancemants … today improves yesterday’s …
public Bulletin Board via user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logics … today, adding …
optional invitation communication email and/or SMS logics via Group Talk set comma separated optional user username/contact entered data set lists helping with Group Talk filtering means of filtering the Speech Bubble data
… around here a lot, as PHP is our domain’s “first call” serverside language.
Add to that that “yesterday’s tomorrow is today” we’re supposed to be finished with our “short two day mini project sojourn”, and in a crude way we have, but we want a third day to add nuance to the arrangements with data filtering and more sophistication regarding collection, within the approach of our new …
Yes, all possible with SVG, though not the first thing we think of using SVG data within our HTML. We normally think, just display thoughts, but today, we’re paving the way for tomorrow, and our “short two day mini project sojourn” will become clearer regarding motives, then, or get hints trying with strategically changedselect_palette.htmlweb application‘s mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic …
var taar=[];
var preadd=0;
var windowuser='', windowcontact='', windowask=true, suffix='';
We rethought yesterday’s HTML textarea start regarding line feed Speech Bubble creation possibilities, and thought …
It’s too unwieldy for a user to add to their textual data when what they really want to do is Speech Bubbles.
Yesterday’s thinking really hoped the user entered a Speech Bubble data one at a time, but what if the user wants to enter several Speech Bubbles in the one textarea incarnation?
Good question. (Calling all ducks with a slow paddle going?!) …
Yes, but there is that ~~ existing delimitation rule, as of yesterday equating to a line feed. Supposing ~~ was given the delimitation roles …
the character sets … lineFeed~~lineFeed
… separate Speech Bubbles … ie. in the textarea a ~~ record is all there is on a line of textarea text
the character set … ~~lineFeed
… at the start wipes out any previously remembered text data and starts again
else retain the ~~ mapping to lineFeed
… in combination with the textarea always first presented blank and the previous Speech Bubble or Lines of Text remembered and retained unless the middle condition above happens?
ask for user interactive input via a window.open (ie. popup) “here’s looking at you, kid” window.opener incarnation guise of our changedselect_palette.htmlweb application … just consisting of …
still capable of ~~ delimitation as with the Javascript prompt window thinking … but also now …
harnessing the talents of a textarea line feed delimitation within it’s value attribute
… able to extend functionality towards decent …
speech bubble feeling thoughts (so far, just) … because …
it opens up the idea that the div element innerHTML attribute can be the SVG we had previously been supplying as background HTML/CSS (via Javascript DOM) data
Cute, huh?! (ahead of the “Speech Bubble styling” niceties making it really cute, yet, for us … but who knows what you can achieve on the “cute styling front”?!).
In the world of web applications, there are often many ways to approach any given requirement. Like with yesterday’s Select Multiple Mobile Background Image Tutorial, today’s “albeit a bit out there idea” is to …
offer a select (multiple attribute) “dropdown” HTML element …
as a webpage covering …
template or palette … where the user …
writes user defined lines of words created
… onto. Pretty simple idea for a “firstthenseconddraft“! But maybe not the first idea to spring to mind regarding making such an idea happen?!
<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";
}
}
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?!).
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 ChartsAnnotated 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 🗺 🗺 emoji button.
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!
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.
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.
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 ChartGeo 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?!
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;>🇦🇺</span>) …
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) …
“dynamic” Javascript DOM HTML “style” attribute changes
“dynamic” Javascript DOM “class” modifications to dovetail with the “static” internal CSS coding as above
… 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 …
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'; }
… 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
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) …
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.
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); “>” …
… 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.
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 …
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 …
onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)
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” …
position:absolute property (with associated top and left (px defined) properties)
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 …
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 …
… 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”.
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 …
a known entity … ie. same web application … at …
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 changedwls_vs_php.htmCapital 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;
}
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.
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.htmlCapital 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 …
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 …
localStorage was a known web browser piece of functionality
… and so as per our localStorage logic we …
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.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
regarding improvements to existant functionality it is most important to not interfere with any current functionality … and then …
implement new functionalities off this platform
… and with our “mini project” of embellishing 11 letter words in the Speech Bubbles of our Select Multiple Webpage Palette Speech Bubble web application of recent times, we have a natural compartmentalization playing out mimicking those ideas above, that goes …
Day 1 – work with the data that is the HTML (and SVG) of Speech Bubbles where they look and behave as ever, but 11 letter words get nested into SVG tspan elements
Day 2 – embellish the web application via those SVG tspan elements
It’s our first go using SVG tspan elements as a “forward thinking” tool, and it helped us thinking on this regarding the corrollaries to HTML span element. What initially concerned us using SVG tspan was whether we’d have to specify x and y attributes, but, as it panned out, no, the SVG text element nesting the tspan takes care of that, so, “top supportive” we’d say, and a lot like how we think of the HTML span element working, and helping out, enormously!
Into “Day 2” though, and we’ll be wanting to do Javascript DOM things in the “overlay” line of thinking. So part of a “Day 1” paradigm, you will better leave that “Day 1” proving the work of “Day 2” is possible, and this was achieved via …
function detecttspan() {
var tsrect=null;
var tss=document.getElementsByTagName('tspan');
for (var itss=0; itss<tss.length; itss++) {
tsrect=tss[itss].getBoundingClientRect();
alert('' + tss[itss].outerHTML + ' left:' + tsrect.left + ' top:' + tsrect.top);
}
}
… with the good news we started “Day 1” not being sure of “passed the test”, as you can see from today’s tutorial picture, and …
privacy for Group Talk “public” Bulletin Board functionalities …
involved logic for the two scenarios …
data-applyprivacy=Y … via two prefixing spaces entered by originator of Group … completely hides relevant Group Talk Bulletin Board data from viewers outside that Group Talk
data-applyprivacy=y … via one prefixing space entered by originator of Group … hides contact parts of Group Talk Bulletin Board data from viewers outside that Group Talk
… but we had not “nuanced” the functionality for that second suboption on that first subpass
… and that is the work discussed today, a nuance that amounts to …
Allow non-group Bulletin Board readers see what we say but given cryptic username choices will not know how to contact that Group
Select Multiple Webpage Palette Speech Bubble Group Talk Privacy Tutorial
Meanwhile, back at some other ranch … somewhere … we’re some of the way down the line, with our recent …
Select Multiple Webpage Palette web application …
Bulletin Board subset of functionality, towards with it’s …
Group Talk (comma separated list of username/contacts) abilities … now offer …
Bulletin Board privacy
… as people in a Group Talk may appreciate. In other words, your generic Bulletin Board viewers would not see your Group Talk setup communications should the originator of any Group Talk now, either at …
best, as a To: + spaces appendage to a textarea line record (delimited by line feed) … ahead of a way with …
spaces prefixing to the prompt widow off right click or gesture events … starting the ball rolling …
populating a new data-applyprivacy global data attribute into the SVG
… allowing this new privacy functionality to work.
Again, we’ll need more than the work today to bed this in, but we now do not think there are any impassable concepts to its implementation.
… and allowing for emojis within a Group Talk user’s username (via control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard) be an identifier on their Speech Bubbles … well, it leaves us speechless with nuance!
Yesterday we were attempting to do this but had more success, today, with …
/**
* Convert a string to HTML entities ... Thanks to https://zditect.com/code/javascript/easy-solution-to-encode-html-entities-in-javascript.html
*/
String.prototype.toHtmlEntities = function() {
return this.replace(/./gm, function(s) {
return (s.match(/[a-z0-9" . "\\" . "s]+/i)) ? s : '' + s.charCodeAt(0) + ';';
});
};
function maybeemoji(insvg) {
var outthing='', newoutthing='', jb=0;
var outsvg=insvg;
//alert('0:' + outsvg);
if (outsvg.indexOf(' data-otherc') != -1 && outsvg.indexOf(' data-ip') != -1) {
outsvg=outsvg.replace(outsvg.split(' data-otherc')[1].split(' data-ip')[0],'').split('97%')[0];
}
//alert(outsvg);
outhtmlentities='';
nonouthtmlentities='';
var nonencodeds=outsvg.split('');
for (jb=1; jb<nonencodeds.length; jb++) {
if (eval('' + nonencodeds[jb].split(';')[0]) >= 1000 && nonouthtmlentities == '') {
outhtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
newoutthing+=String.fromCodePoint(eval('' + nonencodeds[jb].split(';')[0]));
if (nonencodeds[jb] != (nonencodeds[jb].split(';')[0] + ';')) {
nonouthtmlentities=' ';
}
} else if (outhtmlentities != '') {
nonouthtmlentities+=''+nonencodeds[jb].split(';')[0]+';';
}
}
if (outhtmlentities != '') { outthing=outhtmlentities; }
help differentiate Speech Bubbles of different users in a Group Talk arrangement with our public Bulletin Board functionality
Today’s research into displaying emoji text at the pointy corner of the Speech Bubble hopes to help out here, and though we may have nuances yet to come, we can say with the changedselect_palette.htmlweb application helped out by the changedselect_palette.php “fifth draft” PHP we have made a start making this “emoji dream” happen.
we need to consider user IP addresses, as Wikipedia describes …
An Internet Protocol address (IP address) is a numerical label such as 192.0.2.1 that is assigned to a device connected to a computer network that uses the Internet Protocol for communication.[1][2] IP addresses serve two main functions: network interface identification, and location addressing.
Some readers may have noted for a couple of days now, our newly introduced PHP has been assisting the calling HTML, and itself, by remembering the user’s IP address. Yesterday, it was to help colour code Speech Bubbles, and today, it helps in amongst …
The concept of Group Talk started with yesterday’s Select Multiple Webpage Palette Speech Bubble Invitations Tutorial. It made us think that we should start thinking about the differentiation of voices amongst the Speech Bubbles of the public Bulletin Board we’re supporting with the associated web application and its user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic talents.
We decided that one way could be to …
Colour Code the background colour of the Speech Bubbles via the user IP address …
<?php
$gbcol="0,0,255";
function server_remote_addr() {
global $gbcol;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
$uas=explode('.', str_replace('::1','65.254.95.247',$rma)); // 65.254.93.32
the day before’s SVG data enhancemants … today improves yesterday’s …
public Bulletin Board via user mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logics … today, adding …
optional invitation communication email and/or SMS logics via Group Talk set comma separated optional user username/contact entered data set lists helping with Group Talk filtering means of filtering the Speech Bubble data
… around here a lot, as PHP is our domain’s “first call” serverside language.
Add to that that “yesterday’s tomorrow is today” we’re supposed to be finished with our “short two day mini project sojourn”, and in a crude way we have, but we want a third day to add nuance to the arrangements with data filtering and more sophistication regarding collection, within the approach of our new …
Yes, all possible with SVG, though not the first thing we think of using SVG data within our HTML. We normally think, just display thoughts, but today, we’re paving the way for tomorrow, and our “short two day mini project sojourn” will become clearer regarding motives, then, or get hints trying with strategically changedselect_palette.htmlweb application‘s mobile ontouchend and non-mobile oncontextmenu event interfacing Javascript logic …
var taar=[];
var preadd=0;
var windowuser='', windowcontact='', windowask=true, suffix='';
We rethought yesterday’s HTML textarea start regarding line feed Speech Bubble creation possibilities, and thought …
It’s too unwieldy for a user to add to their textual data when what they really want to do is Speech Bubbles.
Yesterday’s thinking really hoped the user entered a Speech Bubble data one at a time, but what if the user wants to enter several Speech Bubbles in the one textarea incarnation?
Good question. (Calling all ducks with a slow paddle going?!) …
Yes, but there is that ~~ existing delimitation rule, as of yesterday equating to a line feed. Supposing ~~ was given the delimitation roles …
the character sets … lineFeed~~lineFeed
… separate Speech Bubbles … ie. in the textarea a ~~ record is all there is on a line of textarea text
the character set … ~~lineFeed
… at the start wipes out any previously remembered text data and starts again
else retain the ~~ mapping to lineFeed
… in combination with the textarea always first presented blank and the previous Speech Bubble or Lines of Text remembered and retained unless the middle condition above happens?
ask for user interactive input via a window.open (ie. popup) “here’s looking at you, kid” window.opener incarnation guise of our changedselect_palette.htmlweb application … just consisting of …
still capable of ~~ delimitation as with the Javascript prompt window thinking … but also now …
harnessing the talents of a textarea line feed delimitation within it’s value attribute
… able to extend functionality towards decent …
speech bubble feeling thoughts (so far, just) … because …
it opens up the idea that the div element innerHTML attribute can be the SVG we had previously been supplying as background HTML/CSS (via Javascript DOM) data
Cute, huh?! (ahead of the “Speech Bubble styling” niceties making it really cute, yet, for us … but who knows what you can achieve on the “cute styling front”?!).
In the world of web applications, there are often many ways to approach any given requirement. Like with yesterday’s Select Multiple Mobile Background Image Tutorial, today’s “albeit a bit out there idea” is to …
offer a select (multiple attribute) “dropdown” HTML element …
as a webpage covering …
template or palette … where the user …
writes user defined lines of words created
… onto. Pretty simple idea for a “firstthenseconddraft“! But maybe not the first idea to spring to mind regarding making such an idea happen?!
<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";
}
}
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?!).
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 ChartsAnnotated 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 🗺 🗺 emoji button.
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!
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.
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.
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 ChartGeo 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?!
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;>🇦🇺</span>) …
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) …
“dynamic” Javascript DOM HTML “style” attribute changes
“dynamic” Javascript DOM “class” modifications to dovetail with the “static” internal CSS coding as above
… 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 …
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'; }
… 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
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) …
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.
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); “>” …
… 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.
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 …
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 …
onload event opportunity of an iframe element (we group into “Iframe Client Pre-Emptive” methods, here)
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” …
position:absolute property (with associated top and left (px defined) properties)
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 …
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 …
… 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”.
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 …
a known entity … ie. same web application … at …
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 changedwls_vs_php.htmCapital 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;
}
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.
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.htmlCapital 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 …
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 …
localStorage was a known web browser piece of functionality
… and so as per our localStorage logic we …
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.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
Further to the daily crontab/curl (and PHP based) WordPress “Recent Posts” daily functionality that happens here at RJM Programming, as talked about with the recent WordPress Recent Posts Korn Shell Tutorial, the last couple of days we had a problem with non-rendering WordPress Blog tutorial thumbnails, to which our reaction involved …
one day of denial … where we did the necessary copy of image file on the web server so that the zero length crontab/curl image version could be sidestepped …
second day …
It happened again! Ugh!!
… let’s investigate …
PHP folder error_log … tail -2 error_log
[09-Jun-2025 05:05:34 Australia/Perth] PHP Warning: file_get_contents(/image_flipping_or_flopping_at_speed_more.gif): Failed to open stream: No such file or directory in /home/rjmprogr/public_html/PHP/recent-posts-2.php on line 131
[09-Jun-2025 05:05:39 Australia/Perth] PHP Warning: file_get_contents(/image_flipping_or_flopping_at_speed_share.gif): Failed to open stream: No such file or directory in /home/rjmprogr/public_html/PHP/recent-posts-2.php on line 131
… got us, luckily, stumbling upon a “controllable environment”. In thinking on this, it is an advantage of PHP that it leaves clues in Apache error_log log files, so, thanks.
What did we see on arriving at erroneous line 131 of recent-posts-2.php editing in macOS TextWrangler?
And it was really line 126 that reminded us what we’d done a couple of days ago. We were getting no peace on our primary IP address to RJM Programming domain web server, but found peace back at the old one. What about we write the blog postings on the old web server WordPress blog “admin” section place, and then transfer what we end up with over to the newer IP address when conditions are better, and we don’t have to pfaff around quite so much that way? Good idea, except that the tutorial image may not show if it contains an absolute image URL back to the “hounded upon” IP address version, so being that said images exist in both IP address places, let’s make the blog posting tutorial image a “relative one” starting with / (but just one, not two, getting back to line 126) so that we can see it render properly.
So what?! (we hear you wonder) Indeed! But, our crontab/curl code above needed to end up with …
<?php
if (substr($thisimg,0,2) == '//') {
$thisimg='http:' . $thisimg; // new SSL specific line 4/5/2017
} else if (substr($thisimg,0,1) == '/') { // ... and what about a relative image URL
$thisimg='http://www.rjmprogramming.com.au' . $thisimg;
} else if (substr($thisimg,0,3) == '../') { // ... and what about a relative image URL
$thisimg='http://www.rjmprogramming.com.au' . substr($thisimg,2);
} else if (substr($thisimg,0,2) == './') { // ... and what about a relative image URL
$thisimg='http://www.rjmprogramming.com.au/ITblog' . substr($thisimg,1);
}
//echo "\n" . str_replace('https:','http:',$thisimg) . "\n";
if (strpos($thisimg, 'rjmprogramming.com.au/') !== false) {
copy('/home/rjmprogr/public_html/' . explode('rjmprogramming.com.au/', $thisimg)[1], dirname(__FILE__) . "/" . $narray[$thisij] . ".jpg");
} else {
$icont = file_get_contents(str_replace('https:','http:',$thisimg));
file_put_contents(dirname(__FILE__) . "/" . $narray[$thisij] . ".jpg", $icont);
}
if (file_exists(dirname(__FILE__) . "/" . $narray[$thisij] . ".jpeg")) {
unlink(dirname(__FILE__) . "/" . $narray[$thisij] . ".jpeg");
}
?>
… to cater for this very mild and reasonable change of WordPress blog posting creation “habit” affecting the changedrecent-posts-2.php WordPress “Recent Posts” PHP processing codeset.
Did you know?
Are you aware, on Linux or macOS of the wonders of, for example …
tail -f error_log
… as a means of dynamically tracking new records being added to error_log in real time?! Can be incredibly useful for debugging PHP!
For a reason still unclear to us the recent-posts-2.php exec call of ImageMagick convert creation of thumbnails failed, after a failure creating zero length non-thumbnail images (fixed now using PHP copy rather than file_put_contents), though it works on the command line in a Linux environment with that same priviledged username.
Especially given that thumbnail usage is optional in the WordPress Recent Posts functionality, rather than spend more time unhappy, we’re happy if a beginning to Korn Shell (which the PHP now writes in a way so that the execution of the Korn Shell causes it’s self destruction) involvement …
… within the crontab purview.
Hopefully we’ll have good news tomorrow that it worked as a new approach.
Back to the topic of “WordPress Blog Recent Posts” (and its relationship to the RJM Programming Landing Page) last referenced at WordPress Recent Posts Widget Caching Issues Tutorial, is today’s fix to an iPhone usage hashtag navigational annoyance that would leave the Blog Title lose a bit of its visibility up the top when navigated to via the RJM Programming Landing Page top left “Recent Posts” thumbnail images.
The fix saw us add to the existant “#post-” prefixed hashtag navigation with our “#andabit=-70” “double hashtagging” as mentioned in WordPress Blog Hashtag Navigation Return Onmouseover Tutorial. It took us a while to track down where to intervene to achieve this, and we eventually cottoned onto the way that if that RJM Programming Landing Page top left “Recent Posts” iframe container (ie. zero.html) of those thumbnail images could involve URLs suffixed by “#andabit=-70” we would rid the hashtag navigation of that annoyance …
The WordPress blog you are reading, with the TwentyTen theme, has a useful “widget” (contained unit of functionality on the webpage that WordPress knows about) called “Recent Posts”, which we’ve had a lot of fun over the years, working with, but “working against”, a tad (because the issue is not exactly mission critical, and) if you are not careful, are the combination of …
the content needed to be up to date at all times would need to counter the once a day crontab/curl arrangements (that WordPress does not know about) for the new posting each day … versus …
the caching of the web browser used can circumvent the up to date correspondence of …
“a” link nesting … of …
“img” blog posting thumbnail
… in two scenarios that we have discovered …
you arrive back at a blog posting webpage after a crontab/curl sequence has happened … the caching causes the “img” and “a” not to correspond, at least on that first such occasion, sometimes …
you arrive off the Landing Page (after a crontab/curl sequence has happened) and up the top left you click on a blog posting that isn’t the latest, and you visited the day before, the caching from that day before causes the “img” and “a” not to correspond, at least on that first such occasion, sometimes
Today’s animated GIF presentation represents a warts and all (occasionally mistaking a Javascript issue for a CSS one) showing of the troubleshooting and investigation of such caching WordPress Recent Posts issues.
Central to the solutions are the idea that the crontab/curl work leaves behind a zero.html “report webpage” we can effectively test the caching against as like a “sanity test” … like. As “caching” is a “client” thaing whereas the PHP of the TwentyTen theme code “header.php” happens is taking place at the “server” end of thaings, what can be the “conduit” between these two woooooorrrrrrllllllldddds …
… helps resolve the second issue’s mismatched data sources which caching may exacerbate.
What about the first issue? Well, we went down the route of thinking this was bound to be a Javascript scripting issue and went through the code with that in mind, until searching for “one.jp” (I think it was) within “header.php” got us tweaked into realizing some of the CSS styling there was encouraging the cache to not let go of “img” “src” attributes. As we are more and more fond of doing these days, even for image URLs, we add some “get” “?” and/or “&” arguments to cause the web browser to go back to the source (and so, around the “cache”) to get its data, as per “header.php”‘s (changed) …
Continuing in that long line of WordPress Recent Posts work you look over to your right (or down the bottom, for some mobile platforms) of the blog webpage for the relevant widget that has that relationship to the Landing Page as we last talked about with Landing Page WordPress Tags Primer Tutorial. There, you can see, we hope, more reliable correspondence of “a” to “img” data sources, in their rightful order, the catalyst for change being that once a day crontab/curl “inhouse” publishing of one WordPress blog post.
… supporting the new HTML …
<div id=divtagcloud><iframe style='display:none;' onerror='anticheckd(this);' onload='checkd(this);' src='//www.rjmprogramming.com.au/PHP/divtagcloud.html'></iframe></div>
… with …
existing Google Chart Pie Chart example of use
… in its “div widget” within the Landing Page HTML. As far as the crontab/curl PHP goes the changedrecent-posts-2.php does its job of populating …
… and so it came to pass, as one example of today’s web application rework. This second idea can have the advantage that if element “tdmiddle” is already “above the fold”, probably no programmatical scrolling will happen, and often that is good news, whereas the first approach tries to make sure element “tdmiddle” finishes up the top of the device’s webpage’s screen, often “a sledgehammer to crack a nut” approach.
And here’s why revisits are good practice? Would you believe we spent ten minutes on the “revisit” thinking the webpage started with the Google Maps Geo Chart and Map Chart table element section until …
previous blog posting images … and …
the code modification above
… tweaked us to the importance of the Wikipedia optioned dropdown that was there neglected “above the fold” for those ten minutes! Doh!
Okay, not good, but that embarrassment, at least, got us to wonder about how to better “decorate” that dropdown for the user, and then were thankful that this project was a PHP one, because we could reference a “very generous, thank you” image from Wikipedia as a background image “decoration” idea, as per (first simplistic go) …
… effectively, those CSS linear-gradients helping make the background image “further off into the background” and the use of background-repeat property being “repeat” a rare venture for us, and even rarer combined with a background-size property being “contain”, to better suit “backgrounding” a thing that is a lot wider than it is high.
We also tracked down some sort of data anomaly with Submarine Volcanoes on Earth Wikipedia data that we have skirted over for now, and that was stopping the webpage displaying for this Wikipedia choice.
PHP Wikipedia Geo Map Google Chart Region Tutorial
Of course, it would be great if the people of the world could think more in terms of the Earth as a whole … social justice for all, freedom for all, lessening of poverty, end of slavery, end of war, care for the animals we share the Earth with, care for the environment … the list goes on. But alas, as far as organization of life goes, it is hard to think past the regional. You may have noticed with yesterday’s PHP Wikipedia Geo Map Google Chart Genericization Tutorial how the Google ChartGeo Charts were based on a map of the world, even for topics that were to do with a region (mode format), such as the “Mountains in Turkey” shown.
That awkwardness of presentation was the fault of the inadequacies, back then, of our interface to the Google Chart Geo Chart, rather than a paucity of functionality up at the Google end … doh. But now, and before actually, we have a better way for the user to define Google Chart Geo Chart regional displays, and we improve our interface to do that with a changed PHP codegeo_chart.php (that you can try in isolation for yourself, if you like, at this live run link). With those changes there you may notice that we also now cater for text mode format whereby the Geo Chart is further annotated via the placename text, rather than any markers or shading alternative annotations. This mode of use is faster in that we don’t look for any image URLs for any markers, and so we now offer dropdown options using this faster presentation mode for those users in a real hurry. What about cluttered text? Well, Google Charts code (natively) handles that very well with an inbuilt “inset view” when the going gets tight. Cute, huh?!
Also, we offer the user the chance to try and define their own Wikipedia geodata URL of interest, via a Javascript prompt window ask, but, as you can imagine, we cannot guarantee success with this user defined mode of use. Here we might describe another “noun” concept, the (?isocode=) ISO Two Letter Code Country Code where the user can say that they want to zoom in on that region of interest with their Geo Chart display.
Yet again, feel free to try this changed PHP codecraters.phplive run to go exploring other “where of life” ideas in more apt regional settings, perhaps.
PHP Wikipedia Geo Map Google Chart Genericization Tutorial
As we wrote the “where of life” “Meteorite Craters on Earth” PHP web application code behind yesterday’s PHP Wikipedia Geo Map Google Chart Tutorial, as with many other codes we write, we were on the lookout, just quietly, for how parameterizable its “inputs” were. In a fairly simple web application concept, the parameters are often “parameterizable” … doh … so that you might reach a point where you question …
Does this web application have the potential to be more than what it has initially been modelled to cater for?
How do you know what a “candidate” for this feels like? To us, that goes, “look for the nouns associated with the hardcodings” you made, and probably repeated in code, in that first incarnation. For us, with yesterday’s work that led us to consider, as parameters, two major “parameters”, namely …
$url
$title
Simple, huh?! So now, think of the mechanism to offer those two concepts as “parameterizable” ideas where the user is given choice, and, as is so often the case for us, that involves turning a hardcoded HTML (h1, in this case) textual element into an HTML select (dropdown) element. Within that HTML select element we use all of …
its value, for storing a $url of relevance
its HTML option subelement innerHTML properties … for display purposes
its HTML option subelement title properties … for “particularization” purposes (eg. mechanism to enable a suffix to the eventual Wikipedia search that will happen in the Geo Chart HTML iframe)
What else would we say is part of a “genericization drive”, quite often? Glad you didn’t ask! The delimitation rules of “plucking out” relevant geodata from Wikipedia data involves various PHP “explode” (first argument) delimiters of interest, depending on the data of interest. You can’t cater for everything, but cater for formats of some commonality on the net. Later, we may extend further, offering the option that the user directs towards the $url of interest themselves, rather than it being “trapped” in a programmer defined HTML select (dropdown) element makeup. Take a look at PHP code here …
$dataarray=explode("&title=", $cont); // where $cont is webpage content
if (sizeof($dataarray) == 1) {
$dataarray=explode("&title=", $cont);
}
if (sizeof($dataarray) == 1) {
if (sizeof(explode('&params=', $cont)) > 1) {
$altf='&params=';
$dataarray=explode($altf, $cont);
} else if (sizeof(explode('_W_"><span', $cont)) > 1) {
$altf='_W_"><span';
$dataarray=explode($altf, $cont);
} else if (sizeof(explode('&params=', $cont)) > 1) {
$altf='&params=';
$dataarray=explode($altf, $cont);
} else if (sizeof(explode('_W_"><span', $cont)) > 1) {
$altf='_W_"><span';
$dataarray=explode($altf, $cont);
} else if (sizeof(explode('_E_"><span', $cont)) > 1) {
$altf='_E_"><span';
$dataarray=explode($altf, $cont);
} else if (sizeof(explode('_W_', $cont)) > 1) {
$altf='_W_';
$dataarray=explode($altf, $cont);
} else if (sizeof(explode('_E_', $cont)) > 1) {
$altf='_E_';
$dataarray=explode($altf, $cont);
}
}
… to get a delimitation basis, on which you “plant” yourself looking to the right only sometimes but more to the left to then glean $url and $title data item (concepts).
The “where of life” talents of Google Chart are pretty irresistible to us, for web application ideas. More and more we see both the combination of the talents of …
And so, in the tradition of blog postings like PHP Wikipedia Australian List Integration Tutorial, today, we have written a web application exploring the “where of life” subject, “Meteorite Craters on Earth”.
Want to do some Meteorite Crater exploration? Try this craters.phplive run to go exploring. Hope this is of interest to you.
For us, with many “where of life” web applications, the Google ChartsMap Chart is a core part of the functionality, as the receptacle, and more and more often as time goes on, also a launching pad out to other concepts, such as …
Nearest TimeZone=Z (and onto Other Side of the World and Weather)
YouTube=Y (looking for placename)
… the latter integrating us with YouTubeAPI for Iframe embedded videos interface HTML/Javascript “parent” web application called karaoke_youtube_api.htm HTML iframe elements in another direction additional to yesterday’s usage. Along the way, we tweak the Google Map=G menu option, adding more map type options and zooming in a little less by default, and with the Nearby Airports=A option making the default be a search for 3 (rather than 4) nearby airports. A lot of this all happens because of the changes to …
… which all got changed to allow for an “Animate” feature, allowing for an automated right to left “animation” (via hashtagging) of the Wikipedia based slides near the top of this suite of web application’s webpages. We hope you get to try all this out for yourself.
We were inspired to take on this “makeover” of “where of life” functionalities because earlier on today we discovered a stupendous online resource for Australian geography enthusiasts, the Bonzle Digital Atlas of Australia, with incredibly detailed and flexible search mechanisms, thanks heaps!
We’ve decided to include extra buttons (to those already linking to Google Maps links and to the relevant Wikipedia webpage) for that suite of web applications above for …
PHP Modularization for Lighthouses in Australia Tutorial
Today we want to try two more things …
continuing on with our PHP code (you could call australian_lighthouses.php) for our Australian Lighthouses project
talk about PHP glob and its modularization sensibilities
… so let’s talk about the second one first … it’s south of north … chortle, chortle.
What does PHP’s glob do? It is doing functionality like the “underworkings” of any browse button you would see would do when you have a hard disk (in your life) … unfortunately, this is no longer a given (with mobile technology and the “cloud” challenging this thinking, sometimes). Give glob a file specification and a directory to start with, and it will happily (if you were both “globular” and “modular” you would be, too) provide you with a list of filenames, so that we use it to construct this PHP function for use with our lighthouses web application …
… and hope you can see that glob could be used for PHP code to self-detect sibling variation programs, so that, for instance, if we “plonked” (ie. eg. (s)ftp it) an egypt_lighthouses.php (probably with an egypt_lighthouses.js accompanying Javascript file) into the same directory as our …
… it would automatically be added into the functionality of its siblings without you having to change any code of those siblings … and that egypt_lighthouses.php is free to be a web application with a totally different method of functionality … cute, huh?!
You see, there are so many many different ways to “skin a cat” in Information Technology, quite often … not always … but “quite often” … and why be cornered into thinking there is only one way to do things?
The other thing you’ll find is that even though ireland_lighthouses.php differs a lot to its nearest matching sibling (in terms of methodology), new_zealand_lighthouses.php the Javascript corresponding codesets called ireland_lighthouses.js and new_zealand_lighthouses.js are only superficially different … in other words our PHP coalesces concepts into a similar “client” look … a “modularization” of sorts … not everybody’s sort, but a sort none the less … and this begs a question?
Why is “modularization” a good thing? Well, to me, you don’t have to have any “modularization” going on at all, and this is fine by me, but you must deal with issues that allow you to modify many many codesets efficiently and accurately in vastly different ways to be efficient, or be “modular” and be able to, perhaps, even, automate your changes, because of these “modular” patterns you’ve created … many people find “modularization” blissful … and often it suits the work patterns for teams of programmers. Perhaps you want to read about MVC (and its like) as a coding modularization idea for PHP (or many other programming languages, for that matter).
PHP/Javascript Asynchronous Lighthouses in Australia Tutorial
Today we want to try two things …
continuing on with our PHP code (you could call australian_lighthouses.php) for our Australian Lighthouses project
talk about Javascript asynchronous script tag option
… so let’s talk about the second one first … it’s south … chortle, chortle.
Why should you be interested in the HTML’s script tag attributes …
asynch=”asynch”
defer=”defer”
? Well, we want our web pages to load as fast as possible. Yaaaaaa?! So if there was the mechanism to do more than one bit of ((client) Javascript) thinking at a time would you avail yourself of the opportunity … or would you pick what’s behind door 3?
Do you want to hear more on this theory wise? It seems to me, there are web application mission critical parts, and there are embellishments, quite often … “nice to haves” but not “mission critical” … well, if those “nice to haves” could be arranged not to hog all the web application designated CPU that would be good, wouldn’t it?! Yaaaaaaaaaaa?!
So, that, in theory, is y why.
Now back to the project at hand … Australian Lighthouses … don’t you think some geographical sorting options and place name sorting options might be useful? Yaaaaaaaaaaaaaaaaa?! But for us it doesn’t feel mission critical … so we …
we load it from the PHP via
<script type=”text/javascript” src=”australian_lighthouses.js” async=”async”></script>
… and this amounts to the only change to today’s PHP code from yesterday as per this link
… and this becomes a way to modularize your thinking regarding a project … please don’t think there are not a myriad of other ways … this is just one idea here.
With regard to how we approached our external Javascript we did not demand anything (much) of our parent PHP and this may not be the fastest way to approach this. What we mean by that is that, perhaps, as a general rule, external Javascript can perform faster with the parent PHP or HTML leaving it with a lot more HTML element id=”[elementId]” to hang its hats on, so to speak … instead, here, we acted innocently with our Javascript and used lots of calls to the Javascript DOM method getElementsByTagName() (which results in an array return value). Perhaps calls to getElementById() via (parent) arranged id=”[elementId]” would be faster?! Today, as with the previous Static HTML Javascript Primer Tutorial we concentrated on the “modular” feel to additional external Javascript code ideas.
Today we examine some of the methodology behind a project idea.
Projects need …
an idea … ours came from listening to the radio and hearing about Lighthouses, and how the technologies had changed what they look like and how they function these days … to quote Wikipedia with respect to Australian Lighthouses (thanks) …
The first lighthouse was Macquarie Lighthouse, which was lit in 1793 as a tripod mounted wood and coal fired beacon. The last manned lighthouse was Maatsuyker Island Lighthouse, off the south coast of Tasmania, which was automated in 1996.
a means to access information … much easier these days with the search engines … we went with a Google Search as per list of lighthouse positions … which led to …
the source data format … initially, at least, via View->Page Source, relative to the webpage … to get ideas for how to parse the data … so that we can determine a …
programming language of choice … which is PHP … no surprise here … will need a server-side language … and a method like PHP’s file_get_contents() … from there …
PHP coding to parse the data and put it into another format that value adds … otherwise why do it, as the Wikipedia information is fine as is … that is where we determine that we should …
include an iframe that uses the Google Chart Map Chart to add that extra overall positional view of Lighthouses … a definite asset to the reader’s understanding of the subject … definitely a “where” web application … and in doing this we notice that …
Google Chart Map Chart map.php web application needed to be able to handle much larger input data streams than it could in its previous incarnation of only allowing PHP $_GET[] parameters … so we change it to allow $_POST[] parameters … maybe you noticed this with yesterday’s PHP/Javascript/HTML Google Chart Map Onclick Tutorial as shown below … as this meant that …
we need an HTML form that POSTs to the iframe with the Google Chart Map Chart map.php web application allowable because we are on the same domain with this thinking … and using an HTML textarea element to store the huge string of Lighthouse data that will be passed across via urldecode($_POST[‘data’]) at map.php … using PHP’s urldecode() and urlencode() methods and Javascript’s decodeURIComponent() method … as well as utilizing …
Google Chart Map Chart map.php web application onclick and tooltip functionality we’ve been working on lately … hence the talk about this below … working out what (component) tools could do with a “makeover” is an extremely important part of any project and can be a useful compartmentalizing of the project
… and so we end up with our live run behind which is the PHP programming source code you could call australian_lighthouses.php for your perusal.
PHP/Javascript/HTML Google Chart Map Onclick Tutorial
They say “the knee bone’s connected to the thigh bone” then they say “the thigh bone’s connected to the … hip bone” then they say “let’s call the whole thing off” … sometimes.
Today we say “the onmouseover event is connected to the onclick event” then we say “the onclick event is connected to the online woooooorld” … “do … the hokey pokey” x3 … “that’s what the onclick event preceeded by the onmouseover event within the environs you are encountering … is all about”.
That news is pretty good actually, because it means mobile users are not missing out on much not having easy access to any onmouseover (ie. hover) functionality … they’ll still reach any onclick logic you present them, in the default case of events where onclick is a valid “touch” event as well.
So the data structure of arrangements to allow for this onclick functionality is intrinsically the same as allowed for yesterday with the PHP/Javascript/HTML Google Chart Map Tooltips Tutorial as shown below, but we just check for some more delimitation issue matters, and our updated prompting window logic gets quite “blurby” as per the Javascript (via PHP) …
echo " datalinesuffix = prompt('Enter decimal Latitude,Longitude ' + thisline + extra + ' (for no more hit Cancel button and append with ' + '\\n\\n' + ',\"A tooltip and clicking link for Google Map of <a target=_blank href=https://www.google.com.au/maps/place/' + encodeURIComponent(dlp2) + '>' + dlp2 + '</a>\" ' + '\\n\\n' + ' or maybe perhaps ' + '\\n\\n' + ',\"A tooltip and clicking link for Google Map based on latitude and longitude of <a target=_blank href=https://maps.google.com.au/maps?' + encodeURIComponent('z=15&t=m&q=loc:') + '{latitude}{longitude}>' + dlp2 + '</a>\"' + '\\n\\n' + ' optionally (as (just) two examples of what is possible with HTML included (activates with onclick bit not onmouseover))', thisdef); " . "\n";
echo ' if (datalinesuffix != null) { if (datalinesuffix.indexOf("{latitude}") != -1) { dlsa=datalinesuffix.split(","); if (dlsa[0].indexOf("-") == -1) { datalinesuffix=datalinesuffix.replace("{latitude}",encodeURIComponent("+" + dlsa[0])); } else { datalinesuffix=datalinesuffix.replace("{latitude}",encodeURIComponent(dlsa[0])); } } if (datalinesuffix.indexOf("{longitude}") != -1) { dlsa=datalinesuffix.split(","); if (dlsa.length > 1) { if (dlsa[1].indexOf("-") == -1) { datalinesuffix=datalinesuffix.replace("{longitude}",encodeURIComponent("+" + dlsa[1])); } else { datalinesuffix=datalinesuffix.replace("{longitude}",encodeURIComponent(dlsa[1])); } } } } ' . "\n";
… as again we are making use of $_GET[] parameters coming into the PHP at the server side.
The bigger picture plan for how this helps something else we are trying will become apparent over time … in the fullness of time … at the appropriate juncture of juxtapositions.
Let’s see some PHP code in live action for this tutorial where you define your map characteristics and data.
Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Map information … via Google.
Link to Google Chart tooltips information … via Google.
Link to some downloadable PHP programming code … rename to map.php which changed from yesterday as per this link.
PHP/Javascript/HTML Google Chart Map Tooltips Tutorial
Here is a tutorial that is revisiting Google Graphs API, or Google Chart Tools, and its Map functionality, which we first talked about with PHP/Javascript/HTML Google Chart Map Tutorial as shown below. Please read …
Google Chart Tools provide a perfect way to visualize data on your website. From simple line charts to complex hierarchical tree maps, the chart galley provides a large number of well-designed chart types. Populating your data is easy using the provided client- and server-side tools.
Why are we revisiting? Well, we are interested in the interactive side to this wonderful product. We are going to start with a look into “tooltips”. Tooltips are those optional informational features of some webpages that happen when hovering over an HTML element, principally through the filling out of an HTML element’s title global attribute.. Google Charts functionality amounts to the use of Javascript, and, these days, SVG HTML elements, so “tooltips” are very relevant to the “user experience” when using Google Charts. With the Map Chart, the latitude, laongitude set is combined with a title, which can be the default “tooltip” shown, as this is all fine for many usages, but we want to extend it so that that title doesn’t have to be the tooltip.
The integration of this added functionality into the Google Chart Map Chart involves adding an extra “string” column to the data table as per the bold bits of the new Javascript (via PHP) snippet …
… making use of $_GET[] parameters coming into the PHP at the server side … you’ll find that Javascript loves to work with PHP as one of those Fred and Ginger relationships of the programming world … you’ll be happier writing Javascript from your PHP too … try it and you’ll see the advantages time and again and again and again … did we leave out one? … and again.
The bigger picture plan for how this helps something else we are trying will hopefully become apparent over time.
Let’s see some PHP code in live action for this tutorial where you define your map characteristics and data.
Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Map information … via Google.
Link to Google Chart tooltips information … via Google.
Here is a tutorial that introduces you to Google Graphs API, or Google Chart Tools, and its Map functionality.
Google Chart Tools provide a perfect way to visualize data on your website. From simple line charts to complex hierarchical tree maps, the chart galley provides a large number of well-designed chart types. Populating your data is easy using the provided client- and server-side tools.
Let’s see some PHP code in live action for this tutorial where you define your map characteristics and data.
Link to Google Chart Tools “spiritual home” … via Google.
Link to Google Chart Tools Map information … via Google.
Link to some downloadable PHP programming code … rename to map.php.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
So what is the point of the new checkbox? Well, that involves some aesthetic display work involving a new horizontal rule ( ie. hr <hr id=myhr style=display:none;z-index:-1;transform:rotate(90deg);overflow:visible;></hr> ) element we use to approximate the axis around which the Flip or Flop (of the image) is taking place …
onto yesterday’s Image URL means of addressing your image today we allow for local file browsing of your image file (and transferred into the web application’s image contents via Javascript …
var imgo=null;
var sxis=1.0, syis=0.0;
var rpm=eval(300 / 10);
var isecs=eval(30 / rpm); // 0.1;
var imagedurl='', theimgurl='http://www.rjmprogramming.com.au/Android/NalaLuna.jpg';
var theclass=theimgurl.slice(-96).replace(/\:/g,'!').replace(/\./g,'|'); //'http!//www.rjmprogramming.com.au/Android/NalaLuna|jpg';
var dcbi='', started=false;
… teaming up with the HTML access to our inhouse local file browser …
<div id=divcbi style=display:inline-block;><iframe scrolling=no frameborder=0 id=cbi data-accept="image/*" style="width:163px;height:228px;margin-top:-204px;display:inline-block;background-color:transparent;" src="/HTMLCSS/client_browsing.htm?d=3121605626826&wording=Allimages%20images%2E%20"></iframe></div>
… allowing for the data URI to be gleaned this way)
allow for a CSS border-radius property be applied to your image via …
var brad="0";
onto yesterday’s Flip and Flop transform options today we add FlipFlop and FlopFlip options this way …
var ffnum=0;
var flipflops=['scaleX(1) scaleY(1)','scaleX(-1) scaleY(1)','scaleX(-1) scaleY(-1)','scaleX(1) scaleY(-1)'];
var flopflips=['scaleX(1) scaleY(1)','scaleX(1) scaleY(-1)','scaleX(-1) scaleY(-1)','scaleX(-1) scaleY(1)'];
… web application. At first, with it, we wondered, regarding our animation, whether we could …
create “smoothed out” flipping or flopping scenarios via CSS keyframes and transition animations … or …
use Javascript DOM
… and sadly the “CSS keyframes and transition animations” is a “no go” for this project (ie. not every CSS property can be animated this way, as we have alluded to in the past).
Never mind, today we supplied the starting three controls the user has, over to the right of their image …