Template Literal Backtick Syntax Quote Delimitation Tutorial

Template Literal Backtick Syntax Quote Delimitation Tutorial

Template Literal Backtick Syntax Quote Delimitation Tutorial

We spend quite a sizeable proportion of our programmatical coding time working out string variable creation where quotes, be they …

Here’s an example of a complex scenario from some Javascript code …


var lastcursor="Url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='66' 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 y='80%'>Alt\\01f3d5</text></svg>\") 16 0, progress";

… which the Template Literal backtick syntax can simplify to …


var lastcursor=`Url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='66' 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 y='80%'>Alt\\01f3d5</text></svg>") 16 0, progress`;

… with no backslashes needed to achieve the same result. This is a simple example, but please see a Javascript function reworked from that within the recent Form or Prompt Output Tagged Template Literal Tutorial blog posting thread.

Here’s the HTML and Javascript behind the iframe content below …


<html><head><script type=text/javascript>
var millis=7656757543;
var strings=[''], rest=';'

function myTag(strings, beingExp, ageExp, secondageExp, breedExp, streetExp, suburbExp, stateExp) {
let str0 = '';
let str1 = '';
let str2 = '';
let str3 = '';
let str4 = '';
let str5 = '';
let str6 = '';
let str7 = '';

for (var ii=0; ii<strings.length; ii++) {
if (ii > 7) {
rest+=' ' + strings[ii];
} else {
eval("str" + ii + ' = "' + strings[ii] + '"');
}
}

let ageStr;
if (ageExp > 99){
ageStr = 'centenarian';
} else {
ageStr = 'youngster';
}

// We can even return a string built using a template literal
return `${str0}${beingExp}${str1}${ageExp}${str2}${secondageExp}${str3}${breedExp}${str4}${streetExp}${str5}${suburbExp}${str6}${stateExp}${str7}` + rest;
}

if (document.URL.indexOf('?') != -1) {
alert(myTag(["one'str",2,3,4], "two'str", "III", "iv", 'seven"str', "six'str", "VII", "viii"));
alert(`seconds elapsed = ${Math.floor(millis / 1000)}`);
} else {
console.log(myTag(["one'str",2,3,4], "two'str", "III", "iv", 'seven"str', "six'str", "VII", "viii"));
console.log(`seconds elapsed = ${Math.floor(millis / 1000)}`);
}
</script></head><body><a style=text-decoration:underline; onclick='location.href=document.URL + String.fromCharCode(63);''=>Click to show backtick calculations to two alert popups</a></body></html>


Previous relevant Form or Prompt Output Tagged Template Literal Tutorial is shown below.

Form or Prompt Output Tagged Template Literal Tutorial

Form or Prompt Output Tagged Template Literal Tutorial

Yesterday’s Scrolling Logging Template Literals Primer Tutorial was the precursor to discussing “Tagged Template Literals” …

A more advanced form of template literals are tagged templates.

Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions.

The tag function can then perform whatever operations on these arguments you wish, and return the manipulated string. (Alternatively, it can return something completely different, as described in one of the following examples.)

… we’ve adapted into an HTML and Javascript tagged_template_literal.html codebase proof of concept web application closely using the start the webpages above started us with … thanks.

These “Tagged Template” logics helped us separate the chaff (small words magically handled via “Tagged Template” usage) from the wheat (form or prompt arguments formalized by our interactive input) in the English sentence … such as (today’s default) …

That Nala is a wonderful 9 year ( 81 in K9 years ) old Golden Retriever who lives at 33 Charles Street, Lawson, State of Wow.

… we produce as a result of all the efforts, here.


<html>
<head>
<title>Tagged Template Literals - RJM Programming - July, 2022 ... thanks to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals</title>
<style> input { width: 20%; } </style>
</head>
<body>
<h2 title='A Tagged Template Literal regimen is dealing with all the little word stuff between the arguments.'>Tagged Template Literals</h2>
<h3>RJM Programming - July, 2022</h3>
<h3>Thanks to <a target=_blank title='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals' href='//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals'>https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals</a></h3>

<p id=blurb></p>

<script type='text/javascript'>
const prompt = location.search.split('prompt=')[1] ? (one,two) => { return window.prompt(one,two); } : (one,two) => { return two; };
const alert = location.search.split('prompt=')[1] ? (one) => { document.getElementById('blurb').innerHTML=one; return one; } : (one) => { return window.alert(one); };
let being = location.search.split('being=')[1] ? prompt('Being', decodeURIComponent(location.search.split('being=')[1].split('&')[0]).replace(/\+/g,' ')) : prompt('Being', 'Nala');
let age = location.search.split('age=')[1] ? prompt('Age',decodeURIComponent(location.search.split('age=')[1].split('&')[0]).replace(/\+/g,' ')) : prompt('Age','9');
let breed = location.search.split('breed=')[1] ? prompt('Breed',decodeURIComponent(location.search.split('breed=')[1].split('&')[0]).replace(/\+/g,' ')) : prompt('Breed','Golden Retriever');
let street = location.search.split('street=')[1] ? prompt('Street',decodeURIComponent(location.search.split('street=')[1].split('&')[0]).replace(/\+/g,' ')) : prompt('Street','33 Charles Street');
let suburb = location.search.split('suburb=')[1] ? prompt('Suburb',decodeURIComponent(location.search.split('suburb=')[1].split('&')[0]).replace(/\+/g,' ')) : prompt('Suburb','Lawson');
let state = location.search.split('state=')[1] ? prompt('State',decodeURIComponent(location.search.split('state=')[1].split('&')[0]).replace(/\+/g,' ')) : prompt('State','State of Wow');
let secondage = location.search.split('secondage=')[1] ? prompt('K9 Age', decodeURIComponent(location.search.split('secondage=')[1].split('&')[0]).replace(/\+/g,' ')) : prompt('K9 Age', '' + eval(eval('' + age) * 9));
let rest = location.search.split('rest=')[1] ? decodeURIComponent(location.search.split('rest=')[1].split('&')[0]) : '';

function doform() {
var ideas=['Being [' + being + ']', 'Age [' + age + ']', 'K9 Age [' + secondage + ']', 'Breed [' + breed + ']', 'Street [' + street + ']', 'Suburb [' + suburb + ']', 'State [' + state + ']'];
var aform='<form method=GET onsubmit="checkis();" action=./tagged_template_literal.html><br><br><input type=submit value=Show></input><br><br><input type=submit name=prompt id=prompt value=Prompt></input></form>';
for (var jj=eval(-1 + ideas.length); jj>=0; jj--) {
aform=aform.replace('>', '><input type=text onblur="if (this.value.length == 0) { this.value=this.placeholder.split(String.fromCharCode(91))[1].split(String.fromCharCode(93))[0]; }" id=' + ideas[jj].split('[')[0].toLowerCase().replace('k9 age', 'secondage') + ' name=' + ideas[jj].split('[')[0].toLowerCase().replace('k9 age', 'secondage') + ' placeholder="' + ideas[jj] + '" value=""></input><br>');
}
document.body.innerHTML+='<br><br>' + aform;
//alert(aform);
//document.getElementById(ideas[0].split('[')[0].toLowerCase().replace('k9 age', 'secondage')).focus();
window.setTimeout(function () {
document.getElementById('being').focus();
}, 1000);
}

function checkis() {
var eis=document.getElementsByTagName('input');
for (var jis=0; jis<eis.length; jis++) {
if (eis[jis].value == '' && ('' + eis[jis].placeholder).indexOf('[') != -1) {
eis[jis].value=eis[jis].placeholder.split(String.fromCharCode(91))[1].split(String.fromCharCode(93))[0];
}
}
}

function myTag(strings, beingExp, ageExp, secondageExp, breedExp, streetExp, suburbExp, stateExp) {
let str0 = '';
let str1 = '';
let str2 = '';
let str3 = '';
let str4 = '';
let str5 = '';
let str6 = '';
let str7 = '';


for (var ii=0; ii<strings.length; ii++) {
if (ii > 7) {
rest+=' ' + strings[ii];
} else {
eval("str" + ii + ' = "' + strings[ii] + '"');
}
}

let ageStr;
if (ageExp > 99){
ageStr = 'centenarian';
} else {
ageStr = 'youngster';
}

// We can even return a string built using a template literal
return `${str0}${beingExp}${str1}${ageExp}${str2}${secondageExp}${str3}${breedExp}${str4}${streetExp}${str5}${suburbExp}${str6}${stateExp}${str7}` + rest;

}

let output = myTag`That ${ being } is a wonderful ${ age } year ( ${ secondage } in K9 years ) old ${ breed } who lives at ${ street }, ${ suburb }, ${ state }.`;

if (document.URL.indexOf('being=') != -1) {
alert(output);
// That Mike is a youngster.
}

doform();
</script>

</body>
</html>


Previous relevant Scrolling Logging Template Literals Primer Tutorial is shown below.

Scrolling Logging Template Literals Primer Tutorial

Scrolling Logging Template Literals Primer Tutorial

Yesterday’s Screen Capture API Download Video Tutorial‘a web application code, thanks to Using Screen Capture, used interesting Javascript Template Literals

Template literals are literals delimited with backtick (`) characters, allowing for multi-line strings, for string interpolation with embedded expressions, and for special constructs called tagged templates.

Template literals are sometimes informally called template strings, because they are used most commonly for string interpolation (to create strings by doing substitution of placeholders). However, a tagged template literal may not result in a string; it can be used with a custom tag function to perform whatever operations you want on the different parts of the template literal.

we’ve adapted for use today in our very simple “Scrolling Logging” console_override.html web application that scrolls like for a command line interactive terminal session …


<html>
<head>
<title>Console Message Override - RJM Programming - July, 2022</title>
<script type='text/javascript'>
var logElem=null;
var firstisnot=false;
var ii=0;

function onl() {
logElem=document.getElementById('log');


console.log = msg => logElem.innerHTML += (firstisnot ? '<span id=span' + ii + '></span>' + document.getElementById('topbit').innerHTML : '') + `${msg}<br>Brought to you via console.log at ` + new Date() + `<br><br>`;
console.error = msg => logElem.innerHTML += `<span class="error">${msg}<br>Brought to you via console.error at ` + new Date() + `</span><br><br>`;
console.warn = msg => logElem.innerHTML += `<span class="warn">${msg}<br>Brought to you via console.warn at ` + new Date() + `<span><br><br>`;
console.info = msg => logElem.innerHTML += `<span class="info">${msg}<br>Brought to you via console.info at ` + new Date() + `</span><br><br>`;


console.log('A console.log message.');
console.error('A console.error message.');
console.warn('A console.warn message.');
console.info('A console.info message.');


if (firstisnot) {
document.getElementById('span' + ii).scrollIntoView();
}
ii++;
firstisnot=true;


setTimeout(onl, 4045);
}

</script>
</head>
<body onload='onl();'>
<div id=topbit>
<h2>Console Message Override</h2>
<h3>RJM Programming - July, 2022</h3>
</div>
<h4 id=log></h4>
</body>
</html>

in action below

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


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


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

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

Google Chrome Web Store Calculator Extension Tutorial

Google Chrome Web Store Calculator Extension Tutorial

Google Chrome Web Store Calculator Extension Tutorial

A logical place to look for those fundamental software applications you use regularly can be the web browser you might be using for day to day “surfing the net” usage. And the …


Google Chrome

… web browser has a helping out …


Chrome Web Store

… online repository of Google Chrome friendly software, from which you can install …


Google Chrome Extensions

… which can look like little desktop applications accessible via a Google Chrome web browser …


Extensions icon

… leading a user to any Google Chrome Extensions installed.

We decided to make this happen for the Google Chrome Extension called “Scientific Calculator”, and were pleased with the simplicity and ease of use, after installing.

Other web browser brands will have similar arrangements to extend their web browser functionality into “extension land”.

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

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

Camera App Photo Live Mode AirDrop Sharing Tutorial

Camera App Photo Live Mode AirDrop Sharing Tutorial

Camera App Photo Live Mode AirDrop Sharing Tutorial

Some time back, with Camera App Photo Live Mode Sharing Tutorial, we discovered …

  • iOS
  • Camera app …
  • Live Photos mode …
  • Sharing menu … via …
  • AirDrop … to our macOS MacBook Air …
  • sends this to your macOS recipient in the image/heic High Efficiency Image File Format

This an Apple format not universally understood by every image editor out there. Gimp can read one but the Paintbrush all coded for macOS does not.

Anyway, the non-live Camera app image formats (and sharing a Live Format image not with AirDrop) share to *.jpeg or *.png image formats, interestingly.

There’s clearly more to learn, here!


Previous relevant Camera App Photo Live Mode Sharing Tutorial is shown below.

Camera App Photo Live Mode Primer Tutorial

Camera App Photo Live Mode Sharing Tutorial

Yesterday’s Camera App Photo Live Mode Primer Tutorial talked about the iOS Camera app’s Live mode functionality, creating an animated GIF type of photo that can be stored in the …


Albums -> Media Types -> Live Photos

… area. Sharing via the Mail option of the Photos app’s Sharing icon and menu lost the “animation” (for the emailee), creating a “still” (photo) as the downloaded media. But, as promised in the Stop Press yesterday, there are some sharing options that can keep that “animated” (GIF) feel …

  • via Messages app the shared photo will play like an animated GIF on a long touch (perhaps also on non-iOS devices (we did not test this?))
  • for sharing with other iOS devices within range and operating system viability you can use AirDrop

… as you can see demonstrated below …

Did you know?

In amongst the Apple “stable” this animated GIF “look and feel” is exclusively a (mobile) iOS (ie. iPhone, iPad etcetera) thing. The same SMS viewed on this macOS MacBook Pro displays as a “still” (photo), and the macOS involvement makes it a “still” even forwarding this on to iOS via the macOS Messages app.


Previous relevant Camera App Photo Live Mode Primer Tutorial is shown below.

Camera App Photo Live Mode Primer Tutorial

Camera App Photo Live Mode Primer Tutorial

Meanwhile, back at Apple‘s iPhone Camera App, further to Camera App Video Slow Motion Primer Tutorial, we wanted to find out more about that yellow “dart board” type “button” up the top that can be toggled between …

  • live off
  • live

What is “Live Mode” as far as the iOS Camera app goes? We consulted Google and came to How to Use Live Photos on iPhone and iPad

Basically, a Live Photo is a combination of a video clip and a still image that results in something akin to an animated GIF when long pressed. With the feature enabled, your iPhone or iPad grabs up to 1.5 seconds of video before and up to 1.5 seconds of video after you tap the shutter button.

… as a “very cute” hybrid between “photo” mode and “video” mode and “slo-mo” (video) mode. Afterwards, if your “live” mode photo is saved into Photos it will sit in …


Albums -> Media Types -> Live Photos

… and will present, initially, like a “still”, but touch (for a goodly time), will “very cutely” turn into an animation (like an animated GIF that you control).

So what happens if you share this “live photo” via email? On this MacBook Pro, it gets shared as a “still”. On an iPad (opened email) it shares as a “still”, as it does on the same iPhone device it was taken on, in that iPhone’s Mail app. But …


Touch Photos app icon -> Albums -> Media Types -> Live Photos -> Long Touch on "Live Photo" of interest

… brings the whole “back story” to light.

Stop Press

If you want to share a Live Mode iPhone Camera app photo in an SMS via Messages app or with another Apple iOS device in the same building, the sharing news is better. We’ll demonstrate tomorrow.


Previous relevant Camera App Video Slow Motion Primer Tutorial is shown below.

Camera App Video Slow Motion Primer Tutorial

Camera App Video Slow Motion Primer Tutorial

Continuing the video theme of yesterday’s QuickTime Player Mov Video Conversion Tutorial today we try out the iPhone (ie. iOS) Camera app’s Video mode’s Slo-Mo mode of use.

Get ready for longer but attention grabbing videos straight from the source

No doubt many of you out there have been trying this feature out yourselves?!


Previous relevant QuickTime Player Mov Video Conversion Tutorial is shown below.

QuickTime Player Mov Video Conversion Tutorial

QuickTime Player Mov Video Conversion Tutorial

Yesterday’s Spinning Around Primer Tutorial changed quite a bit between 27th March 2019 06:00 and 11:20 AEST. Why? Well, our iPhone6 saves its videos (from the Camera iOS application) in *.mov format. This *.mov has an associated mimetype video/quicktime and as you may surmise from that mimetype it’s success as a video playing format depends quite a bit on the user having access to the QuickTime Player application. We say quite a bit here because you can sometimes open an *.mov based URL in a web browser of a computer without QuickTime Player installed, and believe I’ve seen the video be played that way, but with yesterday’s tutorial, we were asking the *.mov be played within an HTML video element (albeit one with no cross-domain issues). The problem here even for computers with QuickTime Player installed …

  • you see a blank black video screen (with controls (because we specified that with our …

    <video style='width:100%;' controlshttp://www.rjmprogramming.com.au/wordpress/wp-admin/post.php?post=44345&action=editsource type='video/quicktime' src='http://www.rjmprogramming.com.au/Mac/iPhone/spinning_around.mov'http://www.rjmprogramming.com.au/wordpress/wp-admin/post.php?post=44345&action=edit/source></video>

    … video element HTML above)
  • you click the play button and nothing happens

All a bit disappointing, but please read on.

Then we set out thinking about conversion from …

  • *.mov to *.m4v via older QuickTime Player Version 10.4 (894.12) (no longer available as of Version 10.5 (928.50)) … which we associated with its video element in Spinning Around Primer Tutorial
  • *.mov to *.mp4 via ffmpeg and help from this great link, thanks, to use on a MacBook Pro (Terminal application) command line, the command …

    ffmpeg -i spinning_around.mov -vcodec h264 -acodec mp2 spinning_around.mp4

    … which we associated with clicking on the tutorial picture of yesterday’s Spinning Around Primer Tutorial

… and then reflecting, and thinking this cannot be so, we got to another great link, thanks, and realized that …


<video style='width:100%;' controls><source type='video/mp4' src='http://www.rjmprogramming.com.au/Mac/iPhone/spinning_around.mov'></source></video>

… could be played in the video element, as below …

You can also see this play out at WordPress 4.1.1’s QuickTime Player Mov Video Conversion Tutorial.


Previous relevant Spinning Around Primer Tutorial is shown below.

Spinning Around Primer Tutorial

Spinning Around Primer Tutorial

That Kylie Minogue song “I’m spinning around …” spinssprings to mind with today’s tutorial.

Have you ever wanted to made a video to try to make yourself, or someone else, dizzy? Well, we thought about this, and decided we’d …

  1. use an iPhone …
  2. start up its Camera app
  3. get it ready for (normal) Video mode
  4. grab a broom
  5. grab a rubber band, the thicker the safer for your iPhone … please be careful …
  6. bind the iPhone onto the broom handle via the rubber band, as tightly as you can
  7. tap the red button awaiting you starting the Video recording, on the iPhone … doh! …
  8. spin the broom handle for a while … we did about 10 seconds
  9. tap the red button to stop recording
  10. share the dizzifying Video, as we do here and below

Are you dizzy yet?

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


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


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


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


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


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

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

Sentence Text Word Underlining Selection Tutorial

Sentence Text Word Underlining Selection Tutorial

Sentence Text Word Underlining Selection Tutorial

We found today, moving on from the recent Sentence Text Word Underlining Primer Tutorial and adding some event logic down the lines of …

Event
selectionchange … we got nowhere when the nested h2 elements were hosted by a div contenteditable=true trying to apply this and so resorted to … onclick
onfocus

… via …


function alertall() {
const nodeList = document.querySelectorAll("h2");
var kk=0;
for (let i = 0; i < nodeList.length; i++) { if (nodeList[i].outerHTML.indexOf(' class=') != -1 && nodeList[i].innerText.trim() != '') { nodeList[i].setAttribute('data-word-ind', '' + (kk + 1)); nodeList[i].onclick=function(event){ thesel=event.target.innerHTML.trim().replace(/\.$/g,'').replace(/\.$/g,'').replace(/\.$/g,'').replace(/\?$/g,'').replace(/\!$/g,'').replace(/\,$/g,'').replace(/\;$/g,''); document.getElementById('myhr').style.display='block'; document.getElementById('myif').style.display='block'; if (1 == 1) { window.open('//www.thefreedictionary.com/' + encodeURIComponent(thesel.trim()), 'myif'); } else { document.getElementById('myif').src='//www.thefreedictionary.com/' + encodeURIComponent(thesel.trim()); } document.getElementById('smore').innerHTML=('Your word number ' + event.target.getAttribute('data-word-ind') + ' is ' + event.target.innerHTML); };
nodeList[i].onfocus=function(event){ thesel=event.target.innerHTML.trim().replace(/\.$/g,'').replace(/\.$/g,'').replace(/\.$/g,'').replace(/\?$/g,'').replace(/\!$/g,'').replace(/\,$/g,'').replace(/\;$/g,''); document.getElementById('myhr').style.display='block'; document.getElementById('myif').style.display='block'; if (1 == 1) { window.open('//www.thefreedictionary.com/' + encodeURIComponent(thesel.trim()), 'myif'); } else { document.getElementById('myif').src='//www.thefreedictionary.com/' + encodeURIComponent(thesel.trim()); } document.getElementById('smore').innerHTML=('Your word number ' + event.target.getAttribute('data-word-ind') + ' is ' + event.target.innerHTML); };
kk++;
}
}

document.addEventListener('selectionchange', handleSelection); // like as used in recent times

… combination to see us through with our aim to add a dictionary lookup (thanks The Free Dictionary) component part to the overall functionality of the changed second draft web application you can also try below.


Previous relevant Sentence Text Word Underlining Primer Tutorial is shown below.

Sentence Text Word Underlining Primer Tutorial

Sentence Text Word Underlining Primer Tutorial

Blog posts like Javascript document.querySelectorAll Textarea Placeholder Tutorial go into our interest in …

Text Talents of HTML Elements
Textarea … versus … Div
And CSS 3D Transformation Matrix Making Of Interactive Integration Tutorial set out how we see the pros and cons as …
Text Functionality Issue HTML Element Type Strength Weakness (where a “Yes” is like … “Oh No!”)
Display Monocolour Text Textarea Yes
Div Yes
Display Editable Text Textarea Yes
Div Yes
Display Multicolour Text Textarea Yes
Div Yes

Well, yesterday’s XML Lint Validation CSS Background Colour Tutorial showcases HTML textarea talents and today’s tutorial involves a new inhouse HTML and Javascript and CSS Sentence Text Word Underlining web application showing a div element talent.

The initial …


<div style='border:3px dotted yellow; margin: 8 8 8 8; padding: 8 8 8 8;background-color: rgb(230,230,230);' onblur=checkthis(this); contenteditable=true id=dpalette class=noerr><h2 class=err>The </h2>&nbsp;<h2 class=err>rain </h2>&nbsp;<h2 class=err>in </h2>&nbsp;<h2 class=err>Spain </h2>&nbsp;<h2 class=err>falls</h2>&nbsp;<h2 class=err>mainly </h2>&nbsp;<h2 class=err>on </h2>&nbsp;<h2 class=err>the </h2>&nbsp;<h2 class=err>plain. </h2>&nbsp;</div>

… look of the underlining involves pure CSS (with no Javascript help) …


<style>
.err {
display: inline-block;
position: relative;
}

.err:before { /* Thanks to https://stackoverflow.com/questions/28152175/a-wavy-underline-in-css */
content: "......................................................................................................";
font-size: 0.6em;
font-weight: 700;
font-family: Times New Roman, Serif;
color: red;
width: 100%;
position: absolute;
top: 22px;
left: -1px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
overflow-x: hidden;
}
</style>

… but our web application allowing for user editing via attribute contenteditable=true needs (the [divElement].innerText help in) Javascript onblur event logic …


<script type='text/javascript'>

function checkthis(dthis) {
var delm='';
var itt=dthis.innerText;
for (var k=0; k<itt.length; k++) {
if (delm == '') {
if (itt.substring(k).substring(0,1) <= ' ' || itt.substring(k).substring(0,1) > '~') {
delm=itt.substring(k).substring(0,1);
//alert('delm=' + delm + '!');
}
} //else if (itt.substring(k).substring(0,1) <= ' ' || itt.substring(k).substring(0,1) > '~') {
//alert(itt.substring(k).substring(0,1).charCodeAt(0));
//}
}
if (delm == '') { delm=' '; }
for (var kk=0; kk<itt.length; kk++) {
//itt=itt.replace(String.fromCharCode(10), delm);
itt=itt.replace(String.fromCharCode(160), delm);
itt=itt.replace(String.fromCharCode(32), delm);
}
var words=itt.replace(/\ \;/g,delm).split(delm);
//alert(itt.replace(/\ \;/g,delm) + ' ... ' + words.length);

var ihwords='';
for (var iiii=0; iiii<words.length; iiii++) {
while (words[iiii].indexOf(String.fromCharCode(10)) != -1) {
words[iiii]=words[iiii].replace(String.fromCharCode(10), '<br>');
}
ihwords+='<h2 class=err>' + words[iiii].replace(/\<br\>/g, '<h2>' + String.fromCharCode(10) + '<h2 class=err>') + '</h2> '
}
//alert(ihwords);
dthis.innerHTML=ihwords;
alertall();
return ihwords;


var ihdthis=dthis.innerHTML;
if (ihdthis == '') { return ihdthis; }
var origihdthis=ihdthis;
if (ihdthis.substring(0,1) != '<') { origihdthis='<h2 class=err>' + ihdthis; }
var ihs=ihdthis.split('</h2>');
if (ihs.length == 1) {
origihdthis+='</h2>';
dthis.innerHTML=origihdthis;
} else {
for (var ii=1; ii<ihs.length; ii++) {
if (ihs[ii].indexOf(' ') != 0) {
dthis=dthis;
} else if (ihs[ii].indexOf(' <') != 0) {
//alert(ihs[ii] + ' okay ' + ihs[ii].substring(6).split('<')[0] + '</h2> ');
ihs[-1 + ii]+='</h2><h2 class=err>' + ihs[ii].substring(6).split('<')[0] + '';
//alert(ihs[-1 + ii]);
ihs[0 + ii]=' ';
}
}
for (var iii=1; iii<ihs.length; iii++) {
if (ihs[iii].indexOf(' ') == 0) {
origihdthis+=' ';
} else {
origihdthis+=ihs[iii] + '</h2>';
}
}
}
dthis.innerHTML=origihdthis;
alertall();
return origihdthis;
}


function alertall() {
const nodeList = document.querySelectorAll("h2");
var kk=0;
for (let i = 0; i < nodeList.length; i++) {
if (nodeList[i].outerHTML.indexOf(' class=') != -1 && nodeList[i].innerText.trim() != '') {
nodeList[i].setAttribute('data-word-ind', '' + (kk + 1));
nodeList[i].onclick=function(event){ document.getElementById('smore').innerHTML=('Your word number ' + event.target.getAttribute('data-word-ind') + ' is ' + event.target.innerHTML); }
kk++;
}
}
}

</script>

… to add that extra level of functionality in the first draft web application you can also try below …


Previous relevant Javascript document.querySelectorAll Textarea Placeholder Tutorial is shown below.

Javascript document.querySelectorAll Textarea Placeholder Tutorial

Javascript document.querySelectorAll Textarea Placeholder Tutorial

Thinking of some great Fred and Ginger types of web application partners we have, at the very least …

  • HTML and Javascript
  • PHP and MySql
  • MySql and phpMyAdmin
  • Ajax and FormData
  • Webpage and Iframe
  • Details and Summary
  • Div and Contenteditable

… and today we’ve partnered Textarea and Placeholder because we’ve discovered that Placeholder (on many browsers and platforms) can be multiline by nature. That suits our style, whereby we try not to bombard users with loads of user entries to have to worry about in web applications, where that is at all possible, but rather resort to intelligent user interaction, often based on delimiters, encouraging the one piece (or perhaps two or three pieces) of information to fill in.

Today’s progress (added to that of yesterday’s Javascript document.querySelectorAll User Scripting Tutorial) concerns that user interaction design to our “Testing Out document.querySelectorAll” web application is to …

  • replace single line input type=text element with textarea element … and …
  • replace single line advice in a single line placeholder attribute with a multiline placeholder “blurb” which includes an example

… and, speaking personally, the relief is incredible, as we have had to grapple with the awkwardness of user entry for days now!

We even styled the placeholder thanks to the advice at W3schools, thanks.

And then we thought we’d allow the user to set the example bit of the placeholder as a “starter” for their real entry via a “two times click on the textarea” set of (on document onload event) logic as per …


function onl(injs) {
if (document.getElementById('myinput')) {
if (document.getElementById('myinput').outerHTML.indexOf('<textarea') != -1) {
var egis=String.fromCharCode(10) + String.fromCharCode(10) + " Example (2xClick) of Einstein Wikipedia Webpage with rounded magenta images and lightblue heading ... " + String.fromCharCode(10) + String.fromCharCode(10) + "http://www.wikipedia.org/wiki/Einstein" + String.fromCharCode(10) + "` img { " + String.fromCharCode(10) + " BORDER-radius:20%; " + String.fromCharCode(10) + " border: 1px dotted magenta; " + String.fromCharCode(10) + " } `" + String.fromCharCode(10) + " function fhlb() {" + String.fromCharCode(10) + " document.getElementById(" + '"' + "firstHeading" + '"' + ").style.backgroundColor=" + '"' + "lightblue" + '"' + "; " + String.fromCharCode(10) + " } " + String.fromCharCode(10) + " setTimeout(fhlb, 2000); " + String.fromCharCode(10);
document.getElementById('myinput').placeholder=document.getElementById('myinput').placeholder.replace(/\|\ /g, String.fromCharCode(10)).replace(' # or ` separate', ' # or ` or first line feed separate').replace(' # or ` and', ' # or ` or first line feed and') + egis;
document.getElementById('myinput').ondblclick = function(event){ ccnt=0; if (event.target.placeholder.indexOf('http') != -1) { event.target.value='http' + event.target.placeholder.split('http')[1]; } };
document.getElementById('myinput').onclick = function(event){ ccnt++; if (ccnt >= 2) { ccnt=0; if (event.target.placeholder.indexOf('http') != -1) { event.target.value='http' + event.target.placeholder.split('http')[1]; } } };

} else {
document.getElementById('myinput').placeholder=document.getElementById('myinput').placeholder.replace(/\|\ /g, '');
}
}

if (injs.trim() != '') {
var tag = document.createElement('script');
tag.type='text/javascript';
tag.src='data:text/javascript;base64,' + btoa(injs);
document.head.appendChild(tag);
}
}

Again, using this changed qsall.htm‘s live run link you can test this out for yourself.


Previous relevant Javascript document.querySelectorAll User Scripting Tutorial is shown below.

Javascript document.querySelectorAll User Scripting Tutorial

Javascript document.querySelectorAll User Scripting Tutorial

Another user defined feature we can add to yesterday’s Javascript document.querySelectorAll Absolute URL Tutorial‘s functionality list of …

  • CSS user defined selector default styling for relative URL
  • CSS user defined styling for relative URL
  • Onclick logic related to that CSS selector via Javascript document.querySelectorAll for relative URL
  • Popup window lor refresh mode child iframe src then srcdoc overlay techniques for relative URL that is nothing (ie. this web application)
  • Absolute URL support as per the top three functionalities above … today we have added …
  • User defined Javascript scripting (with the ` character delimiter added in case styling or scripting requires the # character)

Yes, Javascript can be user defined and dynamic in an already running execution via Javascript such as


<head>
<script type='text/javascript'>
var thejs=location.search.split("thescript=")[1] ? decodeURIComponent(location.search.split("thescript=")[1].split('&')[0]).replace(/\;\ /g, '; ' + String.fromCharCode(10)) : "";;

function onl(injs) {
if (injs.trim() != '') {
var tag = document.createElement('script');
tag.type='text/javascript';
tag.src='data:text/javascript;base64,' + btoa(injs);
document.head.appendChild(tag);
}
}

</script>
</head>
<body onload="document.getElementById('myinput').focus(); onl(thejs);">

Using this changed qsall.htm‘s live run link’s functionalities, we can …

Use dynamically added Javascript to add three dots to top header


Previous relevant Javascript document.querySelectorAll Absolute URL Tutorial is shown below.

Javascript document.querySelectorAll Absolute URL Tutorial

Javascript document.querySelectorAll Absolute URL Tutorial

Just quietly, we add onto the functionality of yesterday’s Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial‘s work with the tolerance for the user to try some absolute URL entries as they try the changed qsall.htm live run link.

As we so often find ourselves doing these days we use the “midair” feeling Ajax/FormData techniques to attempt to satisfy the user interactions, as per


var wasino=null;
var absval='';
var urltosend='';
var zhr=null;
var wasplaceholder='';

function showStuff(evt) {
if (zhr.readyState == 4) {
if (zhr.status == 200) {
absval=zhr.responseText;
//alert(absval);
}
}
}


function ajaxit() {
zhr = new XMLHttpRequest();
var form=new FormData();
form.append('inurl', urltosend);
form.append('tdinto', 'divinv');
if (document.URL.indexOf('localhost:8888') != -1) {
zhr.open('post', 'http://localhost:8888/fgc/', true);
} else {
zhr.open('post', '//www.rjmprogramming.com.au/PHP/fgc/', true);
}
zhr.onreadystatechange = showStuff;
zhr.send(form);
preshowBelow();
}


function preshowBelow() {
if (absval != '') {
wasino.value=wasino.placeholder;
wasino.placeholder=wasplaceholder;
showBelow(wasino);
wasino=null;
absval='';
} else {
setTimeout(preshowBelow, 2000);
}
}


function showBelow(ino) {
var his='', bahis='';
if (wasplaceholder == '') {
wasplaceholder=ino.placeholder;
}
if (('' + ino.value).toLowerCase().indexOf('//') == 0) {
ino.value=document.URL.split(':')[0].toLowerCase() + ':' + ino.value;
} else if (('' + ino.value).toLowerCase().indexOf('www.') == 0) {
ino.value=document.URL.split(':')[0].toLowerCase() + '://' + ino.value;
}
if (('' + ino.value).toLowerCase().indexOf('http') == 0) {
if (absval == '') {
urltosend=ino.value.split('#')[0];
ino.placeholder=ino.value;
ino.value=''; //ino.value.replace(urlis,'');
wasino=ino;
ajaxit();
return;
}
}

if (ino.value.indexOf('#') != -1) {
if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=popup&');
} else {
documentURL+='?window=popup';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=y&');
} else {
documentURL+='?window=y';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?refresh=y&');
} else {
documentURL+='?refresh=y';
}
}
if (ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).indexOf('{') != -1) {
selectorplusis=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY'));
}
selectoris=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).split('{')[0].trim();
}
if (ino.value.trim() != '') {
if (absval != '') {
bahis='data:text/html;base64,' + absval;
//alert(bahis);
absval='';
document.getElementById('ifgoeshere').innerHTML="<iframe id=ifsd onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' srcdoc=\"\"></iframe><iframe id=xifsd onload='checkif(this);' style='display:none;' src=\"" + bahis + "\"></iframe>";
} else
if (ino.value.split('#')[0].trim() == '' && 1 == 2) {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + document.URL + "'></iframe>";
} else if (ino.value.split('#')[0].trim() == '') {
his='<html>' + document.head.outerHTML + document.body.outerHTML + '</html>';
bahis='data:text/html;base64,' + btoa(his);
document.getElementById('ifgoeshere').innerHTML="<iframe id=ifsd onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' srcdoc=\"\"></iframe><iframe id=xifsd onload='checkif(this);' style='display:none;' src=\"" + bahis + "\"></iframe>";
} else {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + ino.value.split('#')[0].trim() + "'></iframe>";
}
}
}


Previous relevant Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial is shown below.

Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial

Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial

Many web applications we present at this blog use what we refer to “inhouse” as …


Client Pre-emptive Iframe

… as that “suck it and see” client approach to do some of the “if it exists try it” functionality you might think has to involve a serverside language like PHP. No, all the discussion below, ignores serverside anything, but instead dwells on …

  • “child” iframe (leaning towards that Client Pre-emptive Iframe) making use of the “fresh start” their “onload” event (and to a lesser extent “onerror”) provides the client (only) programmer …
  • initially via “src” attribute … but new to today’s work (at least for us, that we can remember) …
  • initially involve src=”data:text/html;base64,[base64HTMLContent]” that …
  • (same) “onload” code can redirect that content to another “child” iframe (leaning towards that Client Pre-emptive Iframe) “srcdoc” attribute … and yes, we were not sure until today, but yes …
  • “child” iframe (leaning towards that Client Pre-emptive Iframe) that gets its content via “srcdoc” attribute does pass through the “onload” event logic where the “document” object exists (a very happy discovery for us (though we’ve probably been assuming it already in projects up to now))

… this “proof of concept” experimenting being incorporated into our “Javascript document.querySelectorAll” project for scenarios …

For relative URL that is blank (ie. uses this same webpage) suffixes of two blanks refreshes and that of four blanks opens new window and that of eight blanks opens new popup window.

… to the point where you may not notice the difference between this “srcdoc” processing compared to the other (single) “src” attribute executions of the web application.

How does the client wooooooorrrrrrrllllllldddd handle base64? Well, for simple data …

Why can’t we manage this new functionality in the one pass through the “onload” event logic? Well, any self-respecting webpage content will contain both apostrophe and double quote characters (let alone line feeds and carriage returns) ( but we can if we can get to a Javascript DOM statement like document.getElementById(‘ifsd’).srcdoc=atob((” + ioissrc).split(‘;base64,’)[1]).replace(‘</bo’ + ‘dy>’, ‘ <style> ‘ + selectorplusis + ‘</style> </bo’ + ‘dy>’); ), making it hard to specify on the Javascript codeline constructing your “child” iframe but now this new functionality uses


var documentURL='' + document.URL.split('#')[0];


function showBelow(ino) {
if (ino.value.indexOf('#') != -1) {
if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=popup&');
} else {
documentURL+='?window=popup';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=y&');
} else {
documentURL+='?window=y';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?refresh=y&');
} else {
documentURL+='?refresh=y';
}
}

if (ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).indexOf('{') != -1) {
selectorplusis=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY'));
}
selectoris=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).split('{')[0].trim();
}
if (ino.value.trim() != '') {
if (ino.value.split('#')[0].trim() == '' && 1 == 2) {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + document.URL + "'></iframe>";
} else if (ino.value.split('#')[0].trim() == '') {
var his='<html>' + document.head.outerHTML + document.body.outerHTML + '</html>';
var bahis='data:text/html;base64,' + btoa(his);
document.getElementById('ifgoeshere').innerHTML="<iframe id=ifsd onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' srcdoc=\"\"></iframe><iframe id=xifsd onload='checkif(this);' style='display:none;' src=\"" + bahis + "\"></iframe>";
} else {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + ino.value.split('#')[0].trim() + "'></iframe>";
}
}
}


function checkif(iois) {
var ij, wois=null;
if (iois != null) {
console.log('' + iois.src);
if (('' + iois.src).indexOf('data:') == 0 && ('' + iois.src).indexOf(';base64,') != -1) { // src=data:text/html;base64,[base64HTMLContent] comes here
var ioissrc=('' + iois.src);
iois.src='';
if (selectorplusis.indexOf(' BORDER') != -1) {
eles=document.querySelectorAll(selectoris);
for (ij=eval(-1 + eles.length); ij>=0; ij--) {
froms.push(eles[ij].outerHTML);
tos.push('<a onclick="alert(this.innerHTML);" style="cursor:pointer;text-decoration:none;" title="Border clickable">' + eles[ij].outerHTML + '</a>');
}
for (ij=0; ij<froms.length; ij++) {
ioissrc=ioissrc.replace(froms[ij], tos[ij]);
}
}
var xbodyt=atob(('' + ioissrc).split(';base64,')[1]).replace('</bo' + 'dy>', ' <style> ' + selectorplusis + '</style> </bo' + 'dy>');
var bodyt=xbodyt.split('<bo' + 'dy')[1];
if (('' + documentURL).indexOf('window=') != -1) {
if (('' + documentURL).indexOf('popup') != -1) {
wois=window.open('', '_blank', 'top=0, left=0, width=600, height=600');
} else {
wois=window.open('', '_blank');
}
wois.document.write(atob(('' + ioissrc).split(';base64,')[1]).replace('</bo' + 'dy>', ' <style> ' + selectorplusis + '</style> </bo' + 'dy>'));
} else if (('' + documentURL).indexOf('refresh=') != -1) {
document.body.innerHTML=bodyt.substring(eval(1 + bodyt.indexOf('>'))).split('</bo' + 'dy>')[0];
} else {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifsd').srcdoc=atob(('' + ioissrc).split(';base64,')[1]).replace('</bo' + 'dy>', ' <style> ' + selectorplusis + '</style> </bo' + 'dy>');
}
} else {
// relative URL src comes here, as well as srcdoc (we have discovered today 23/1/2021)
console.log(1);
var aconto = (iois.contentWindow || iois.contentDocument);
console.log(2);
if (aconto != null) {
console.log(3);
//console.log(aconto);
console.log(4);
if (aconto.document) { aconto = aconto.document; }
console.log(5);
if (selectoris != '') {
console.log(6);
if (selectorplusis != '') {
console.log(7);
aconto.body.innerHTML+=' <style> ' + selectorplusis + '</style> ';
console.log(8);
if (selectorplusis.indexOf(' BORDER') != -1) {
console.log(9);
eles=aconto.querySelectorAll(selectoris);
for (ij=eval(-1 + eles.length); ij>=0; ij--) {
froms.push(eles[ij].outerHTML);
tos.push('<a onclick="alert(this.innerHTML);" style="cursor:pointer;text-decoration:none;" title="Border clickable">' + eles[ij].outerHTML + '</a>');
}
for (ij=0; ij<froms.length; ij++) {
aconto.body.innerHTML=aconto.body.innerHTML.replace(froms[ij], tos[ij]);
}
}
} else {
console.log('a');
eles=aconto.querySelectorAll(selectoris);
console.log('b');
for (ij=0; ij<eles.length; ij++) {
eles[ij].style.border='1px dashed red';
}
}
}
}
}
}
}

We hope you revisit the recent Javascript document.querySelectorAll User Styled Clickable Border Tutorial‘s improvements today’s work represents in the changed qsall.htm live run link is worth it to try the (Pure) Javascript meets CSS ideas above.


Previous relevant Javascript document.querySelectorAll User Styled Clickable Border Tutorial is shown below.

Javascript document.querySelectorAll User Styled Clickable Border Tutorial

Javascript document.querySelectorAll User Styled Clickable Border Tutorial

Yesterday’s Javascript document.querySelectorAll Primer Tutorial has been “stretched” in functionality in two ways …

  • yesterday’s user defined selector but static styling is now opened up to user defined styling as well …
  • we wanted to allow a user defined CSS styling that involves the use of ” BORDER” somewhere adds border clickable elements that satisfy the selector criteria used in


function checkif(iois) {
var ij;
if (iois != null) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (selectoris != '') {
if (selectorplusis != '') {
aconto.body.innerHTML+=' <style> ' + selectorplusis + '</style> ';
if (selectorplusis.indexOf(' BORDER') != -1) {
eles=aconto.querySelectorAll(selectoris);
for (ij=eval(-1 + eles.length); ij>=0; ij--) {
froms.push(eles[ij].outerHTML);
tos.push('<a onclick="alert(this.innerHTML);" style="cursor:pointer;text-decoration:none;" title="Border clickable">' + eles[ij].outerHTML + '</a>');
}
for (ij=0; ij<froms.length; ij++) {
aconto.body.innerHTML=aconto.body.innerHTML.replace(froms[ij], tos[ij]);
}
}
} else {
eles=aconto.querySelectorAll(selectoris);
for (ij=0; ij<eles.length; ij++) {
eles[ij].style.border='1px dashed red';
}
}
}
}
}
}

Yes, we needed to ask for help, and got good help here, thanks (for that doh! moment).

Today’s changed live run link is worth it to try the (Pure) Javascript meets CSS ideas above.


Previous relevant Javascript document.querySelectorAll Primer Tutorial is shown below.

Javascript document.querySelectorAll Primer Tutorial

Javascript document.querySelectorAll Primer Tutorial

“Pure Javascript” versus “jQuery” is an issue for many developers of client side web application code logic. More often than not we plump for the former, though there are notable exceptions for us, such as jQuery Ajax is often of use, and we have used the very apt (for today’s topic) jQuery CSS on occasions. But for today’s proof of concept test run of …


document.querySelectorAll([CSS-selector]);

… it’s all “Pure Javascript”. In today’s qsall.html HTML and “Pure Javascript” code you will not find the string “document.querySelectorAll” anywhere because our web application is …

  • just some header HTML elements and one HTML input type=text “textbox” element and one containing div element and one input type=text to avoid “tabbing out” annoyances …
  • “textbox” accepts a relative URL in two parts as per …

    [relativeURLTo-//www.rjmprogramming.com.au/]#[CSS-selector]
  • that relative URL is the “src” attribute to an HTML iframe element that overlays (made to be barely visible) header HTML elements and one HTML input type=text “textbox” element … and whose …
  • “onload” event logic goes …

    function checkif(iois) {
    var ij;
    if (iois != null) {
    var aconto = (iois.contentWindow || iois.contentDocument);
    if (aconto != null) {
    if (aconto.document) { aconto = aconto.document; }
    if (selectoris != '') {
    eles=aconto.querySelectorAll(selectoris);
    for (ij=0; ij<eles.length; ij++) {
    eles[ij].style.border='1px dashed red';
    }
    }
    }
    }
    }

… that you can try for yourself with today’s live run link.

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


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


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


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


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


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


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


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

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

Google Chart Image Chart Geojson Issue Tutorial

Google Chart Image Chart Geojson Issue Tutorial

Google Chart Image Chart Geojson Issue Tutorial

Do you remember our fears, expressed at Region Picker Popup Menu Tutorial, as we were discussing (what used to be) the brilliant Google Chart Image Chart functionality …

… and we feel we might have “put the mockers” on ourselves, because, as you may have read, Geo Chart Image Chart is due for deprecation soon. In fact, the regime at the moment is fewer and fewer hours up, and we’ll have to turn our attention to alternatives. But what out there can do those regional views where the map effectively hugs the bounds of the data … brilliant, and we think hard to do with your normal Google Charts suite of software? As well as the image element result, even though we need to try out the “ready event” normal Google Charts “print” way to achieve this. So much more useful than involving Javascript. And more fun to work with too, it being a conduit to HTML canvas usage.

… regarding it’s imminent demise (and don’t you just hate the word “deprecation”)?

Well, it happened. Where does that leave our integrations regarding Google Chart Image Chart Map Chart we developed with this inhouse PHP interfacing web application? Well, lots is still showing, “hoping for redemption”, and the GeoJson button functionality is still intact. That is, barring “friendly fire”?!

Yes, we’re not sure when, but maybe at the time of the recent Google Chart Image Chart Map Chart Mainstream Primer Tutorial we may have introduced a bug, and today we’re here to try to remedy that situation. That situation goes …

  1. navigate to image_chart.php
  2. fill in a comma separated list of ISO 2 character country codes into that first textbox …
  3. click GeoJson button

… and it would keep a “cloudy woooorrrrlllllddd map”, alas. We debugged it, using Google Chrome’s web inspector, again. The error message, and here the lesson is to believe the “red squiggle underlining parts” …


for (xij=0; xij<xars.length; xij++) { areacon=''; if (maybenogood(xars[xij].outerHTML,'FR,DE,BR,CN,US,IN,ID,AU,NZ,EG,ZA',aars[Math.max(0,eval(-3 + xij))].outerHTML).indexOf( ... blahde blah ...

… in the context of the presented error …

TypeError: Cannot read properties of undefined (reading ‘outerHTML’)

… prompted us to come up with the amended codeline …


for (xij=0; xij<xars.length; xij++) { areacon=''; if (aars.length > eval(-3 + xij)) { if (maybenogood(xars[xij].outerHTML,'FR,DE,BR,CN,US,IN,ID,AU,NZ,EG,ZA',aars[Math.max(0,eval(-3 + xij))].outerHTML).indexOf( ... blahde blah ... } ...

… made things right again in the changed rangegeo.php PHP helping code for web application GeoJson button logic.


Previous relevant Google Chart Image Chart Map Chart Mainstream Primer Tutorial is shown below.

Google Chart Image Chart Map Chart Mainstream Primer Tutorial

Google Chart Image Chart Map Chart Mainstream Primer Tutorial

Ever since we discovered the existence of Google Chart Image Chart Map Charts, the first foray ending with the recent Google Chart Image Chart Map Chart GeoJson Onclick Tutorial, we’ve been keen to hive off functionality …

… given what we’ve learnt regarding each of the above‘s talents, the new member of the interest group bringing regional maps into the picture better for us.

Over many years of integrating the first as the first port of call, though, has us thinking carefully of non “bull at a gate” approaches, and today, we’re only visiting the first idea of our “three point plan” (so far)

  1. Help itself … map.php … phase 1
  2. Redirect to Image Chart Map Chart … map.php and/or geo_chart.php … just after first prompt … phase 2
  3. Caller form method=POST map.php action interventions at onsubmit event … non map.php … phase 3

… asking our favourite integrator to take a hit for the good of the team. Currently map.php is stuck in the bedroom, but we fully expect they’ll be out in just a jiffy to show you a “three part” (so far) PHP code intervention sequence here …

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. … welcome back “mappy” …


var isusdams='<?php echo (isset($_POST['iso']) ? trim(str_replace('+',' ',urldecode($_POST['iso']))) : (isset($_GET['iso']) ? trim(str_replace('+',' ',urldecode($_GET['iso']))) : '')); ?>';
if (window.top || isusdams.trim() != '') {
if (isusdams.trim() != '') {
if (isusdams.indexOf(';') == -1) { isusdams+=';'; }
} else if (top.document.URL.indexOf('/dams_usa.htm') != -1) {
isusdams='US;';
} else if (top.document.URL.indexOf('/australian_') != -1) {
isusdams='AU;';
} else if (document.URL.indexOf('iso=') != -1) {
isusdams=document.URL.split('iso=')[1].split('&')[0].split('#')[0] + ';';
} else if (parent.document.URL.indexOf('/tz_places.php?iso=') != -1) {
isusdams=parent.document.URL.split('/tz_places.php?iso=')[1].split('&')[0].split('#')[0] + ';';
} else if (top.document.URL.indexOf('/tz_places.php?iso=') != -1) {
isusdams=top.document.URL.split('/tz_places.php?iso=')[1].split('&')[0].split('#')[0] + ';';
}
} else if (document.URL.indexOf('iso=') != -1) {
isusdams=document.URL.split('iso=')[1].split('&')[0].split('#')[0] + ';';
}
if (isusdams != '') { // amapidgeo
if (document.getElementById('amapidgeo')) {
document.getElementById('amapidgeo').click();
} else {
setTimeout(latergeoclick, 5000);
}
}
}

function latergeoclick() {
if (document.getElementById('amapidgeo')) {
document.getElementById('amapidgeo').click();
}
}

and

<?php echo ”

function gogeo(usug) {
if (documentURL.indexOf('data=') != -1) {
if ((documentURL + '~').indexOf('&data=~') != -1 && ('' + pardata).replace('undefined','') != '') {
documentURL=documentURL + pardata;
}
var isusdams='" . (isset($_POST['iso']) ? trim(str_replace('+',' ',urldecode($_POST['iso']))) : (isset($_GET['iso']) ? trim(str_replace('+',' ',urldecode($_GET['iso']))) : '')) . "';
if (window.top || isusdams.trim() != '') {
if (isusdams.trim() != '') {
if (isusdams.indexOf(';') == -1) { isusdams+=';'; }
} else if (top.document.URL.indexOf('/dams_usa.htm') != -1) {
isusdams='US;';
} else if (top.document.URL.indexOf('/australian_') != -1) {
isusdams='AU;';
} else if (document.URL.indexOf('iso=') != -1) {
isusdams=document.URL.split('iso=')[1].split('&')[0].split('#')[0] + ';';
} else if (parent.document.URL.indexOf('/tz_places.php?iso=') != -1) {
isusdams=parent.document.URL.split('/tz_places.php?iso=')[1].split('&')[0].split('#')[0] + ';';
} else if (top.document.URL.indexOf('/tz_places.php?iso=') != -1) {
isusdams=top.document.URL.split('/tz_places.php?iso=')[1].split('&')[0].split('#')[0] + ';';
}
} else if (document.URL.indexOf('iso=') != -1) {
isusdams=document.URL.split('iso=')[1].split('&')[0].split('#')[0] + ';';
}
if (isusdams != '') {
locationhref=toolong((documentURL + '%20,%20[-90.0|0.0|~%20~,999999999]').replace('/Map', '/GeoChart').replace('map.php', 'geo_chart.php').replace('?','?width=556&height=347&country=Places&popularity=&aregeographicals=y&').replace('title=','title=' + isusdams).replace(/\=\,/g,'=').replace(/\,\~/g,'|~').replace(/0\,/g,'0|').replace(/1\,/g,'1|').replace(/2\,/g,'2|').replace(/3\,/g,'3|').replace(/4\,/g,'4|').replace(/5\,/g,'5|').replace(/6\,/g,'6|').replace(/7\,/g,'7|').replace(/8\,/g,'8|').replace(/9\,/g,'9|').replace('%27|%20','%27,%20').replace('%27|','%27,').replace(/\~\]/g,'~,1]'));
} else {

locationhref=toolong((documentURL + '%20,%20[-90.0|0.0|~%20~,999999999]').replace('/Map', '/GeoChart').replace('map.php', 'geo_chart.php').replace('?','?width=556&height=347&country=Places&popularity=&aregeographicals=y&').replace(/\=\,/g,'=').replace(/\,\~/g,'|~').replace(/0\,/g,'0|').replace(/1\,/g,'1|').replace(/2\,/g,'2|').replace(/3\,/g,'3|').replace(/4\,/g,'4|').replace(/5\,/g,'5|').replace(/6\,/g,'6|').replace(/7\,/g,'7|').replace(/8\,/g,'8|').replace(/9\,/g,'9|').replace('%27|%20','%27,%20').replace('%27|','%27,').replace(/\~\]/g,'~,1]'));
}
//locationhref=toolong((documentURL + ',[-90.0,0.0,~%20~,999999999]').replace('/Map', '/GeoChart').replace('map.php', 'geo_chart.php').replace('?','?width=556&height=347&country=Places&popularity=&aregeographicals=' + agy + '&').replace(/\=\,/g,'=').replace(/\,\~/g,'|~').replace(/0\,/g,'0|').replace(/1\,/g,'1|').replace(/2\,/g,'2|').replace(/3\,/g,'3|').replace(/4\,/g,'4|').replace(/5\,/g,'5|').replace(/6\,/g,'6|').replace(/7\,/g,'7|').replace(/8\,/g,'8|').replace(/9\,/g,'9|').replace('%27|%20','%27,%20').replace('%27|','%27,').replace(/\~\]/g,'~,1]'));
//locationhref=toolong((documentURL + '').replace('/Map', '/GeoChart').replace('map.php', 'geo_chart.php').replace('?','?width=556&height=347&country=Places&popularity=&aregeographicals=' + agy + '&').replace(/\=\,/g,'=').replace(/\,\~/g,'|~').replace(/0\,/g,'0|').replace(/1\,/g,'1|').replace(/2\,/g,'2|').replace(/3\,/g,'3|').replace(/4\,/g,'4|').replace(/5\,/g,'5|').replace(/6\,/g,'6|').replace(/7\,/g,'7|').replace(/8\,/g,'8|').replace(/9\,/g,'9|').replace('%27|%20','%27,%20').replace('%27|','%27,').replace(/\~\]/g,'~,1]'));
} else {
locationhref=usug;
}
if (locationhref != '#') { location.href=locationhref; } locationhref='';
}

“; ?>

… and within the map.php interactivity logic

<?php

echo ' var title = ourprompt("Enter Map Title (background image URL or image data URI ; separated (followed by ;) before title are options, and suffix by &iso=XX for XX as country code of interest and suffix by &lines=y for overlay clickable link lines and/or suffix by &onclick=y for all onclick functionalities such as &brgplace=[1] for Bearing Distance table and perhaps &brgmode=trip for that table in trip order). Email Attachment Title suffixes are &emailto=[emailTo] &emailsubject=[EmailSubject] ... ' . $promptsuffix . '", "' . str_replace("+"," ",urldecode($GETtitle)). '"); ' . "\n";

?>

… in the changed map.php.php PHP code for our inhouse Google Chart Map Chart interfacer, starting off with “hive offs” to the Geo Chart in this “first of three” (so far) operation we’ve codenamed …

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. … over to you “mappy” …

“first of three” (so far) operation


Previous relevant Google Chart Image Chart Map Chart GeoJson Onclick Tutorial is shown below.

Google Chart Image Chart Map Chart GeoJson Onclick Tutorial

Google Chart Image Chart Map Chart GeoJson Onclick Tutorial

Still on the “reconstituting” trajectory yesterday’s Google Chart Image Chart Map Chart GeoJson Iframe Tutorial had, continuing on with regarding our interfacing to the Google Charts Image Chart Map Chart hosting of GeoJson functionality, today, we “reconstitute” some “onclick” event logics for those brown map infills that occur. Why? Well, we figure user experience wise, people often assume a deliberately colour coded situation like this means that they might glean further information by clicking on that “minority color” at the very least, especially when we are talking “maps”, here.

If you’re happy, and you know it, feel free to honk!

Okay then, what do we do with these new HTML div element “onclick” event logics. Well, so far, we’re showing a list of three nearby timezones, but the main thing is to establish the “infrastructure” to get to this event logic, and often, what you do once there, is less work. Not always, but quite often, we find.


function checkdsa(ath) {
return '';
}

function orflag(thiscc) {
var ccchar='', ccsuff='';
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'];
for (var iccsuff=0; iccsuff<thiscc.length; iccsuff++) {
ccchar=thiscc.substring(iccsuff, eval(1 + eval('' + iccsuff))).toUpperCase();
ccsuff+=String.fromCodePoint(eval('' + dri[eval('' + lri.indexOf(ccchar))])); //'&#' + dri[eval('' + lri.indexOf(ccchar))] + ';';
}
return ccsuff;
}

function ouralert(athis, ctyname, isothree, isotwo, inclist) {
if (isotwo == 'CH') { isotwo='CN'; }
if (goes == 0) { goes=1; answered=true; }
if (('' + isotwo).length == 2) { jtwo=isotwo; }
if (inclist.indexOf(',') != -1) {
lastflag='';
lasttwo='';
if (isotwo.trim() != '') {
lasttwo=isotwo;
lastflag=' ' + orflag(isotwo);
}
checkdsa(athis);
var cls=inclist.replace('Longitude,Latitude coordinates are ','').split(',');
longlastl=ctyname + ': ' + inclist;
//document.getElementById('ntz').value='';
if (cwo) {
if (!cwo.closed) { cwo.close(); }
}
cwo=window.open('/PHP/tz_places.php?countrycode=' + encodeURIComponent(isotwo) + '&place=' + encodeURIComponent(ctyname) + '&latitude=' + encodeURIComponent(cls[1]) + '&longitude=' + encodeURIComponent(cls[0]) + '&ntztontz=y','_blank','top=100,left=100,width=1200,height=250');
cwo.onload=function(){
cwo.document.title='' + ctyname;
};
//setTimeout(lookforntz, 1000);
}
}

Hived off what the GeoJson World Countries web application already did was …

  • used to, in its HTML area elements, set up the “onclick” call to that version of function ouralert … so we transferred that across to …
  • brown coloured reconstituted HTML div elements

… and tweaked code in the changed rangegeo.php PHP helping code for web application GeoJson button logic.

Stop Press

Today’s work met with a previously established PHP code file, again, and so we’ve taken the opportunity, being as we tweaked above, adding new arguments, to change this tz_places.php by adding some more country specific smarts to the resultant display for the scenario where rangegeo.php is calling it.

It’s not full functionality, but also, today, we open the way to some Google Translate translation interfacing with our tweaked image_chart.php PHP web application for you to try.


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


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


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

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

Sentence Text Word Underlining Primer Tutorial

Sentence Text Word Underlining Primer Tutorial

Sentence Text Word Underlining Primer Tutorial

Blog posts like Javascript document.querySelectorAll Textarea Placeholder Tutorial go into our interest in …

Text Talents of HTML Elements
Textarea … versus … Div
And CSS 3D Transformation Matrix Making Of Interactive Integration Tutorial set out how we see the pros and cons as …
Text Functionality Issue HTML Element Type Strength Weakness (where a “Yes” is like … “Oh No!”)
Display Monocolour Text Textarea Yes
Div Yes
Display Editable Text Textarea Yes
Div Yes
Display Multicolour Text Textarea Yes
Div Yes

Well, yesterday’s XML Lint Validation CSS Background Colour Tutorial showcases HTML textarea talents and today’s tutorial involves a new inhouse HTML and Javascript and CSS Sentence Text Word Underlining web application showing a div element talent.

The initial …


<div style='border:3px dotted yellow; margin: 8 8 8 8; padding: 8 8 8 8;background-color: rgb(230,230,230);' onblur=checkthis(this); contenteditable=true id=dpalette class=noerr><h2 class=err>The </h2>&nbsp;<h2 class=err>rain </h2>&nbsp;<h2 class=err>in </h2>&nbsp;<h2 class=err>Spain </h2>&nbsp;<h2 class=err>falls</h2>&nbsp;<h2 class=err>mainly </h2>&nbsp;<h2 class=err>on </h2>&nbsp;<h2 class=err>the </h2>&nbsp;<h2 class=err>plain. </h2>&nbsp;</div>

… look of the underlining involves pure CSS (with no Javascript help) …


<style>
.err {
display: inline-block;
position: relative;
}

.err:before { /* Thanks to https://stackoverflow.com/questions/28152175/a-wavy-underline-in-css */
content: "......................................................................................................";
font-size: 0.6em;
font-weight: 700;
font-family: Times New Roman, Serif;
color: red;
width: 100%;
position: absolute;
top: 22px;
left: -1px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
overflow-x: hidden;
}
</style>

… but our web application allowing for user editing via attribute contenteditable=true needs (the [divElement].innerText help in) Javascript onblur event logic …


<script type='text/javascript'>

function checkthis(dthis) {
var delm='';
var itt=dthis.innerText;
for (var k=0; k<itt.length; k++) {
if (delm == '') {
if (itt.substring(k).substring(0,1) <= ' ' || itt.substring(k).substring(0,1) > '~') {
delm=itt.substring(k).substring(0,1);
//alert('delm=' + delm + '!');
}
} //else if (itt.substring(k).substring(0,1) <= ' ' || itt.substring(k).substring(0,1) > '~') {
//alert(itt.substring(k).substring(0,1).charCodeAt(0));
//}
}
if (delm == '') { delm=' '; }
for (var kk=0; kk<itt.length; kk++) {
//itt=itt.replace(String.fromCharCode(10), delm);
itt=itt.replace(String.fromCharCode(160), delm);
itt=itt.replace(String.fromCharCode(32), delm);
}
var words=itt.replace(/\ \;/g,delm).split(delm);
//alert(itt.replace(/\ \;/g,delm) + ' ... ' + words.length);

var ihwords='';
for (var iiii=0; iiii<words.length; iiii++) {
while (words[iiii].indexOf(String.fromCharCode(10)) != -1) {
words[iiii]=words[iiii].replace(String.fromCharCode(10), '<br>');
}
ihwords+='<h2 class=err>' + words[iiii].replace(/\<br\>/g, '<h2>' + String.fromCharCode(10) + '<h2 class=err>') + '</h2> '
}
//alert(ihwords);
dthis.innerHTML=ihwords;
alertall();
return ihwords;


var ihdthis=dthis.innerHTML;
if (ihdthis == '') { return ihdthis; }
var origihdthis=ihdthis;
if (ihdthis.substring(0,1) != '<') { origihdthis='<h2 class=err>' + ihdthis; }
var ihs=ihdthis.split('</h2>');
if (ihs.length == 1) {
origihdthis+='</h2>';
dthis.innerHTML=origihdthis;
} else {
for (var ii=1; ii<ihs.length; ii++) {
if (ihs[ii].indexOf(' ') != 0) {
dthis=dthis;
} else if (ihs[ii].indexOf(' <') != 0) {
//alert(ihs[ii] + ' okay ' + ihs[ii].substring(6).split('<')[0] + '</h2> ');
ihs[-1 + ii]+='</h2><h2 class=err>' + ihs[ii].substring(6).split('<')[0] + '';
//alert(ihs[-1 + ii]);
ihs[0 + ii]=' ';
}
}
for (var iii=1; iii<ihs.length; iii++) {
if (ihs[iii].indexOf(' ') == 0) {
origihdthis+=' ';
} else {
origihdthis+=ihs[iii] + '</h2>';
}
}
}
dthis.innerHTML=origihdthis;
alertall();
return origihdthis;
}


function alertall() {
const nodeList = document.querySelectorAll("h2");
var kk=0;
for (let i = 0; i < nodeList.length; i++) {
if (nodeList[i].outerHTML.indexOf(' class=') != -1 && nodeList[i].innerText.trim() != '') {
nodeList[i].setAttribute('data-word-ind', '' + (kk + 1));
nodeList[i].onclick=function(event){ document.getElementById('smore').innerHTML=('Your word number ' + event.target.getAttribute('data-word-ind') + ' is ' + event.target.innerHTML); }
kk++;
}
}
}

</script>

… to add that extra level of functionality in the first draft web application you can also try below …


Previous relevant Javascript document.querySelectorAll Textarea Placeholder Tutorial is shown below.

Javascript document.querySelectorAll Textarea Placeholder Tutorial

Javascript document.querySelectorAll Textarea Placeholder Tutorial

Thinking of some great Fred and Ginger types of web application partners we have, at the very least …

  • HTML and Javascript
  • PHP and MySql
  • MySql and phpMyAdmin
  • Ajax and FormData
  • Webpage and Iframe
  • Details and Summary
  • Div and Contenteditable

… and today we’ve partnered Textarea and Placeholder because we’ve discovered that Placeholder (on many browsers and platforms) can be multiline by nature. That suits our style, whereby we try not to bombard users with loads of user entries to have to worry about in web applications, where that is at all possible, but rather resort to intelligent user interaction, often based on delimiters, encouraging the one piece (or perhaps two or three pieces) of information to fill in.

Today’s progress (added to that of yesterday’s Javascript document.querySelectorAll User Scripting Tutorial) concerns that user interaction design to our “Testing Out document.querySelectorAll” web application is to …

  • replace single line input type=text element with textarea element … and …
  • replace single line advice in a single line placeholder attribute with a multiline placeholder “blurb” which includes an example

… and, speaking personally, the relief is incredible, as we have had to grapple with the awkwardness of user entry for days now!

We even styled the placeholder thanks to the advice at W3schools, thanks.

And then we thought we’d allow the user to set the example bit of the placeholder as a “starter” for their real entry via a “two times click on the textarea” set of (on document onload event) logic as per …


function onl(injs) {
if (document.getElementById('myinput')) {
if (document.getElementById('myinput').outerHTML.indexOf('<textarea') != -1) {
var egis=String.fromCharCode(10) + String.fromCharCode(10) + " Example (2xClick) of Einstein Wikipedia Webpage with rounded magenta images and lightblue heading ... " + String.fromCharCode(10) + String.fromCharCode(10) + "http://www.wikipedia.org/wiki/Einstein" + String.fromCharCode(10) + "` img { " + String.fromCharCode(10) + " BORDER-radius:20%; " + String.fromCharCode(10) + " border: 1px dotted magenta; " + String.fromCharCode(10) + " } `" + String.fromCharCode(10) + " function fhlb() {" + String.fromCharCode(10) + " document.getElementById(" + '"' + "firstHeading" + '"' + ").style.backgroundColor=" + '"' + "lightblue" + '"' + "; " + String.fromCharCode(10) + " } " + String.fromCharCode(10) + " setTimeout(fhlb, 2000); " + String.fromCharCode(10);
document.getElementById('myinput').placeholder=document.getElementById('myinput').placeholder.replace(/\|\ /g, String.fromCharCode(10)).replace(' # or ` separate', ' # or ` or first line feed separate').replace(' # or ` and', ' # or ` or first line feed and') + egis;
document.getElementById('myinput').ondblclick = function(event){ ccnt=0; if (event.target.placeholder.indexOf('http') != -1) { event.target.value='http' + event.target.placeholder.split('http')[1]; } };
document.getElementById('myinput').onclick = function(event){ ccnt++; if (ccnt >= 2) { ccnt=0; if (event.target.placeholder.indexOf('http') != -1) { event.target.value='http' + event.target.placeholder.split('http')[1]; } } };

} else {
document.getElementById('myinput').placeholder=document.getElementById('myinput').placeholder.replace(/\|\ /g, '');
}
}

if (injs.trim() != '') {
var tag = document.createElement('script');
tag.type='text/javascript';
tag.src='data:text/javascript;base64,' + btoa(injs);
document.head.appendChild(tag);
}
}

Again, using this changed qsall.htm‘s live run link you can test this out for yourself.


Previous relevant Javascript document.querySelectorAll User Scripting Tutorial is shown below.

Javascript document.querySelectorAll User Scripting Tutorial

Javascript document.querySelectorAll User Scripting Tutorial

Another user defined feature we can add to yesterday’s Javascript document.querySelectorAll Absolute URL Tutorial‘s functionality list of …

  • CSS user defined selector default styling for relative URL
  • CSS user defined styling for relative URL
  • Onclick logic related to that CSS selector via Javascript document.querySelectorAll for relative URL
  • Popup window lor refresh mode child iframe src then srcdoc overlay techniques for relative URL that is nothing (ie. this web application)
  • Absolute URL support as per the top three functionalities above … today we have added …
  • User defined Javascript scripting (with the ` character delimiter added in case styling or scripting requires the # character)

Yes, Javascript can be user defined and dynamic in an already running execution via Javascript such as


<head>
<script type='text/javascript'>
var thejs=location.search.split("thescript=")[1] ? decodeURIComponent(location.search.split("thescript=")[1].split('&')[0]).replace(/\;\ /g, '; ' + String.fromCharCode(10)) : "";;

function onl(injs) {
if (injs.trim() != '') {
var tag = document.createElement('script');
tag.type='text/javascript';
tag.src='data:text/javascript;base64,' + btoa(injs);
document.head.appendChild(tag);
}
}

</script>
</head>
<body onload="document.getElementById('myinput').focus(); onl(thejs);">

Using this changed qsall.htm‘s live run link’s functionalities, we can …

Use dynamically added Javascript to add three dots to top header


Previous relevant Javascript document.querySelectorAll Absolute URL Tutorial is shown below.

Javascript document.querySelectorAll Absolute URL Tutorial

Javascript document.querySelectorAll Absolute URL Tutorial

Just quietly, we add onto the functionality of yesterday’s Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial‘s work with the tolerance for the user to try some absolute URL entries as they try the changed qsall.htm live run link.

As we so often find ourselves doing these days we use the “midair” feeling Ajax/FormData techniques to attempt to satisfy the user interactions, as per


var wasino=null;
var absval='';
var urltosend='';
var zhr=null;
var wasplaceholder='';

function showStuff(evt) {
if (zhr.readyState == 4) {
if (zhr.status == 200) {
absval=zhr.responseText;
//alert(absval);
}
}
}


function ajaxit() {
zhr = new XMLHttpRequest();
var form=new FormData();
form.append('inurl', urltosend);
form.append('tdinto', 'divinv');
if (document.URL.indexOf('localhost:8888') != -1) {
zhr.open('post', 'http://localhost:8888/fgc/', true);
} else {
zhr.open('post', '//www.rjmprogramming.com.au/PHP/fgc/', true);
}
zhr.onreadystatechange = showStuff;
zhr.send(form);
preshowBelow();
}


function preshowBelow() {
if (absval != '') {
wasino.value=wasino.placeholder;
wasino.placeholder=wasplaceholder;
showBelow(wasino);
wasino=null;
absval='';
} else {
setTimeout(preshowBelow, 2000);
}
}


function showBelow(ino) {
var his='', bahis='';
if (wasplaceholder == '') {
wasplaceholder=ino.placeholder;
}
if (('' + ino.value).toLowerCase().indexOf('//') == 0) {
ino.value=document.URL.split(':')[0].toLowerCase() + ':' + ino.value;
} else if (('' + ino.value).toLowerCase().indexOf('www.') == 0) {
ino.value=document.URL.split(':')[0].toLowerCase() + '://' + ino.value;
}
if (('' + ino.value).toLowerCase().indexOf('http') == 0) {
if (absval == '') {
urltosend=ino.value.split('#')[0];
ino.placeholder=ino.value;
ino.value=''; //ino.value.replace(urlis,'');
wasino=ino;
ajaxit();
return;
}
}

if (ino.value.indexOf('#') != -1) {
if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=popup&');
} else {
documentURL+='?window=popup';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=y&');
} else {
documentURL+='?window=y';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?refresh=y&');
} else {
documentURL+='?refresh=y';
}
}
if (ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).indexOf('{') != -1) {
selectorplusis=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY'));
}
selectoris=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).split('{')[0].trim();
}
if (ino.value.trim() != '') {
if (absval != '') {
bahis='data:text/html;base64,' + absval;
//alert(bahis);
absval='';
document.getElementById('ifgoeshere').innerHTML="<iframe id=ifsd onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' srcdoc=\"\"></iframe><iframe id=xifsd onload='checkif(this);' style='display:none;' src=\"" + bahis + "\"></iframe>";
} else
if (ino.value.split('#')[0].trim() == '' && 1 == 2) {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + document.URL + "'></iframe>";
} else if (ino.value.split('#')[0].trim() == '') {
his='<html>' + document.head.outerHTML + document.body.outerHTML + '</html>';
bahis='data:text/html;base64,' + btoa(his);
document.getElementById('ifgoeshere').innerHTML="<iframe id=ifsd onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' srcdoc=\"\"></iframe><iframe id=xifsd onload='checkif(this);' style='display:none;' src=\"" + bahis + "\"></iframe>";
} else {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + ino.value.split('#')[0].trim() + "'></iframe>";
}
}
}


Previous relevant Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial is shown below.

Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial

Javascript document.querySelectorAll Client Pre-emptive Iframe Tutorial

Many web applications we present at this blog use what we refer to “inhouse” as …


Client Pre-emptive Iframe

… as that “suck it and see” client approach to do some of the “if it exists try it” functionality you might think has to involve a serverside language like PHP. No, all the discussion below, ignores serverside anything, but instead dwells on …

  • “child” iframe (leaning towards that Client Pre-emptive Iframe) making use of the “fresh start” their “onload” event (and to a lesser extent “onerror”) provides the client (only) programmer …
  • initially via “src” attribute … but new to today’s work (at least for us, that we can remember) …
  • initially involve src=”data:text/html;base64,[base64HTMLContent]” that …
  • (same) “onload” code can redirect that content to another “child” iframe (leaning towards that Client Pre-emptive Iframe) “srcdoc” attribute … and yes, we were not sure until today, but yes …
  • “child” iframe (leaning towards that Client Pre-emptive Iframe) that gets its content via “srcdoc” attribute does pass through the “onload” event logic where the “document” object exists (a very happy discovery for us (though we’ve probably been assuming it already in projects up to now))

… this “proof of concept” experimenting being incorporated into our “Javascript document.querySelectorAll” project for scenarios …

For relative URL that is blank (ie. uses this same webpage) suffixes of two blanks refreshes and that of four blanks opens new window and that of eight blanks opens new popup window.

… to the point where you may not notice the difference between this “srcdoc” processing compared to the other (single) “src” attribute executions of the web application.

How does the client wooooooorrrrrrrllllllldddd handle base64? Well, for simple data …

Why can’t we manage this new functionality in the one pass through the “onload” event logic? Well, any self-respecting webpage content will contain both apostrophe and double quote characters (let alone line feeds and carriage returns) ( but we can if we can get to a Javascript DOM statement like document.getElementById(‘ifsd’).srcdoc=atob((” + ioissrc).split(‘;base64,’)[1]).replace(‘</bo’ + ‘dy>’, ‘ <style> ‘ + selectorplusis + ‘</style> </bo’ + ‘dy>’); ), making it hard to specify on the Javascript codeline constructing your “child” iframe but now this new functionality uses


var documentURL='' + document.URL.split('#')[0];


function showBelow(ino) {
if (ino.value.indexOf('#') != -1) {
if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=popup&');
} else {
documentURL+='?window=popup';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?window=y&');
} else {
documentURL+='?window=y';
}
} else if (('' + ino.value).indexOf(('' + ino.value).trim() + ' ') != -1) {
if (documentURL.indexOf('?') != -1) {
documentURL=documentURL.replace('?', '?refresh=y&');
} else {
documentURL+='?refresh=y';
}
}

if (ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).indexOf('{') != -1) {
selectorplusis=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY'));
}
selectoris=ourdecodeURIComponent(ino.value.substring(eval(1 + ino.value.indexOf('#'))).replace(/NO\%WAY/g, 'NO%25WAY')).split('{')[0].trim();
}
if (ino.value.trim() != '') {
if (ino.value.split('#')[0].trim() == '' && 1 == 2) {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + document.URL + "'></iframe>";
} else if (ino.value.split('#')[0].trim() == '') {
var his='<html>' + document.head.outerHTML + document.body.outerHTML + '</html>';
var bahis='data:text/html;base64,' + btoa(his);
document.getElementById('ifgoeshere').innerHTML="<iframe id=ifsd onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' srcdoc=\"\"></iframe><iframe id=xifsd onload='checkif(this);' style='display:none;' src=\"" + bahis + "\"></iframe>";
} else {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifgoeshere').innerHTML="<iframe onload='checkif(this);' style='position:absolute;top:0px;left:0px;width:100%;height:100%;z-index:7;' src='" + ino.value.split('#')[0].trim() + "'></iframe>";
}
}
}


function checkif(iois) {
var ij, wois=null;
if (iois != null) {
console.log('' + iois.src);
if (('' + iois.src).indexOf('data:') == 0 && ('' + iois.src).indexOf(';base64,') != -1) { // src=data:text/html;base64,[base64HTMLContent] comes here
var ioissrc=('' + iois.src);
iois.src='';
if (selectorplusis.indexOf(' BORDER') != -1) {
eles=document.querySelectorAll(selectoris);
for (ij=eval(-1 + eles.length); ij>=0; ij--) {
froms.push(eles[ij].outerHTML);
tos.push('<a onclick="alert(this.innerHTML);" style="cursor:pointer;text-decoration:none;" title="Border clickable">' + eles[ij].outerHTML + '</a>');
}
for (ij=0; ij<froms.length; ij++) {
ioissrc=ioissrc.replace(froms[ij], tos[ij]);
}
}
var xbodyt=atob(('' + ioissrc).split(';base64,')[1]).replace('</bo' + 'dy>', ' <style> ' + selectorplusis + '</style> </bo' + 'dy>');
var bodyt=xbodyt.split('<bo' + 'dy')[1];
if (('' + documentURL).indexOf('window=') != -1) {
if (('' + documentURL).indexOf('popup') != -1) {
wois=window.open('', '_blank', 'top=0, left=0, width=600, height=600');
} else {
wois=window.open('', '_blank');
}
wois.document.write(atob(('' + ioissrc).split(';base64,')[1]).replace('</bo' + 'dy>', ' <style> ' + selectorplusis + '</style> </bo' + 'dy>'));
} else if (('' + documentURL).indexOf('refresh=') != -1) {
document.body.innerHTML=bodyt.substring(eval(1 + bodyt.indexOf('>'))).split('</bo' + 'dy>')[0];
} else {
document.getElementById('myh1').style.opacity='0.01';
document.getElementById('myh3').style.opacity='0.01';
document.getElementById('myinput').style.opacity='0.01';
document.getElementById('ifsd').srcdoc=atob(('' + ioissrc).split(';base64,')[1]).replace('</bo' + 'dy>', ' <style> ' + selectorplusis + '</style> </bo' + 'dy>');
}
} else {
// relative URL src comes here, as well as srcdoc (we have discovered today 23/1/2021)
console.log(1);
var aconto = (iois.contentWindow || iois.contentDocument);
console.log(2);
if (aconto != null) {
console.log(3);
//console.log(aconto);
console.log(4);
if (aconto.document) { aconto = aconto.document; }
console.log(5);
if (selectoris != '') {
console.log(6);
if (selectorplusis != '') {
console.log(7);
aconto.body.innerHTML+=' <style> ' + selectorplusis + '</style> ';
console.log(8);
if (selectorplusis.indexOf(' BORDER') != -1) {
console.log(9);
eles=aconto.querySelectorAll(selectoris);
for (ij=eval(-1 + eles.length); ij>=0; ij--) {
froms.push(eles[ij].outerHTML);
tos.push('<a onclick="alert(this.innerHTML);" style="cursor:pointer;text-decoration:none;" title="Border clickable">' + eles[ij].outerHTML + '</a>');
}
for (ij=0; ij<froms.length; ij++) {
aconto.body.innerHTML=aconto.body.innerHTML.replace(froms[ij], tos[ij]);
}
}
} else {
console.log('a');
eles=aconto.querySelectorAll(selectoris);
console.log('b');
for (ij=0; ij<eles.length; ij++) {
eles[ij].style.border='1px dashed red';
}
}
}
}
}
}
}

We hope you revisit the recent Javascript document.querySelectorAll User Styled Clickable Border Tutorial‘s improvements today’s work represents in the changed qsall.htm live run link is worth it to try the (Pure) Javascript meets CSS ideas above.


Previous relevant Javascript document.querySelectorAll User Styled Clickable Border Tutorial is shown below.

Javascript document.querySelectorAll User Styled Clickable Border Tutorial

Javascript document.querySelectorAll User Styled Clickable Border Tutorial

Yesterday’s Javascript document.querySelectorAll Primer Tutorial has been “stretched” in functionality in two ways …

  • yesterday’s user defined selector but static styling is now opened up to user defined styling as well …
  • we wanted to allow a user defined CSS styling that involves the use of ” BORDER” somewhere adds border clickable elements that satisfy the selector criteria used in


function checkif(iois) {
var ij;
if (iois != null) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (selectoris != '') {
if (selectorplusis != '') {
aconto.body.innerHTML+=' <style> ' + selectorplusis + '</style> ';
if (selectorplusis.indexOf(' BORDER') != -1) {
eles=aconto.querySelectorAll(selectoris);
for (ij=eval(-1 + eles.length); ij>=0; ij--) {
froms.push(eles[ij].outerHTML);
tos.push('<a onclick="alert(this.innerHTML);" style="cursor:pointer;text-decoration:none;" title="Border clickable">' + eles[ij].outerHTML + '</a>');
}
for (ij=0; ij<froms.length; ij++) {
aconto.body.innerHTML=aconto.body.innerHTML.replace(froms[ij], tos[ij]);
}
}
} else {
eles=aconto.querySelectorAll(selectoris);
for (ij=0; ij<eles.length; ij++) {
eles[ij].style.border='1px dashed red';
}
}
}
}
}
}

Yes, we needed to ask for help, and got good help here, thanks (for that doh! moment).

Today’s changed live run link is worth it to try the (Pure) Javascript meets CSS ideas above.


Previous relevant Javascript document.querySelectorAll Primer Tutorial is shown below.

Javascript document.querySelectorAll Primer Tutorial

Javascript document.querySelectorAll Primer Tutorial

“Pure Javascript” versus “jQuery” is an issue for many developers of client side web application code logic. More often than not we plump for the former, though there are notable exceptions for us, such as jQuery Ajax is often of use, and we have used the very apt (for today’s topic) jQuery CSS on occasions. But for today’s proof of concept test run of …


document.querySelectorAll([CSS-selector]);

… it’s all “Pure Javascript”. In today’s qsall.html HTML and “Pure Javascript” code you will not find the string “document.querySelectorAll” anywhere because our web application is …

  • just some header HTML elements and one HTML input type=text “textbox” element and one containing div element and one input type=text to avoid “tabbing out” annoyances …
  • “textbox” accepts a relative URL in two parts as per …

    [relativeURLTo-//www.rjmprogramming.com.au/]#[CSS-selector]
  • that relative URL is the “src” attribute to an HTML iframe element that overlays (made to be barely visible) header HTML elements and one HTML input type=text “textbox” element … and whose …
  • “onload” event logic goes …

    function checkif(iois) {
    var ij;
    if (iois != null) {
    var aconto = (iois.contentWindow || iois.contentDocument);
    if (aconto != null) {
    if (aconto.document) { aconto = aconto.document; }
    if (selectoris != '') {
    eles=aconto.querySelectorAll(selectoris);
    for (ij=0; ij<eles.length; ij++) {
    eles[ij].style.border='1px dashed red';
    }
    }
    }
    }
    }

… that you can try for yourself with today’s live run link.

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


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


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


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


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


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


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

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

XML Lint Validation CSS Background Colour Tutorial

XML Lint Validation CSS Background Colour Tutorial

XML Lint Validation CSS Background Colour Tutorial

Onto the recent XML Lint Validation Shared Encoding Tutorial we’d say what could “cheer things up”, shall we say, is to add some colour into the look of the XML Lint Validation web application.

And to do this with inline CSS <style></style> element within the <head></head> non-body part of the webpage. We allow the webpage to keep any of its “style=” specifications within the <body></body> section too, because, personally speaking, if we thought to do it as we were coding, then the chances are, these CSS specification must hold some weight and should stay. Today’s work is an “overall makeover” layer of CSS styling “just for aesthetics”, which is more the way we tend to organize web application CSS styling aesthetics around here. It’s up to you though, obviously, and if you have a dedicated CSS styling employee, then you may roll in a different direction … though Nala and Luna will tell you …

Clockwise is best!

But they would say that! They’ve never travelled north of the Equator!

So what CSS styling got applied?

<?php echo ”

<style>

th[colspan]:not([colspan="1"]) {
background-color: yellow;
}

textarea:nth-child(1) {
background-color: silver;
}

textarea#preincoming {
background-color: silver;
}

textarea:nth-child(2) {
background-color: rgb(245,245,245);
}

textarea#incoming {
background-color: rgb(245,245,245);
}

textarea:nth-child(3) {
background-color: pink !important;
}

textarea#outgoing {
background-color: pink !important;
}

</style>

“; ?>

… in our changed “sixth draft” xmllint_validation.php you might want to try for yourself.


Previous relevant XML Lint Validation Shared Encoding Tutorial is shown below.

XML Lint Validation Shared Encoding Tutorial

XML Lint Validation Shared Encoding Tutorial

There are a lot of web applications we’ve been involved with that …

  1. try to avoid (what we are most “peeved” by, as an issue) gobbledegook when dealing with non-ascii content we try, encoding wise, to corral towards UTF-8 encoding … and today we …
  2. add sharing and collaboration functionality, via email or SMS, to our current XML Lint Validation web application development

… hence the “Shared Encoding” curiosity in our blog posting title … well, you had to be there … today, in the days after yesterday’s XML Lint Validation SelectionChange Tutorial

Fancy a pertinent riddle?

What is always coming but never arrives?

Anyone, anyone?

Yes, Hoagy, do you have an answer?

No Bull Cow No Bull

Well, that’s quite rude and wise all at once, Hoagy! Anybody else? Yes, Edward, your answer …

Rearrange the sycophant!

… has merit too! But wish one of you would enunciate … use your words …
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

You have the answer Tatsumi? Well …

Today

… excellent try! But no, not quite. The answer is …

Tomorrow

But, five points to Hufflepuff, and we add today’s voucher for a cup of tea (no rushing please)!

But, back to business, as far as the encoding issue (of gobbledegook) goes, we mucked around thinking the fault lay with “meta” tags, and such, in the parent, until we relooked at the FileReader arrangements we had going back at a changed client_browsing.htm client side HTML and Javascript inhouse helper. We were always using readAsDataURL() method for this URL call containing “straighttext=” argument pattern, but we found more success starting to use readAsText() method for HTML and XML data inputs. Makes sense really! Now we go


blob.push(file.slice(start, stop + 1));
if (parent.document.getElementById('txtresultout')) {
reader[ij].readAsText(blob[ij]);
} else {
if (document.URL.indexOf('straighttext=') != -1) {
if (window.parent) {
if (parent.document.getElementById('result1') && parent.document.getElementById('result2')) {
reader[ij].readAsText(blob[ij]);
} else {
reader[ij].readAsDataURL(blob[ij]);
}
} else {
reader[ij].readAsDataURL(blob[ij]);
}
} else {

reader[ij].readAsDataURL(blob[ij]);
}
}

as well as


reader[ij].onloadend = (function(mfile) {
return function(evt) {
var dp='', ds=dssuffix, slideshowparent=false, ssuffix='0', nsuffix='2', blnks=' ', xhsf='', zhsfs=[];
var tomt='video/mp4', thext='', ithext=0;
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
if (document.URL.indexOf('straighttext=') != -1) {
if (window.parent) {
if (parent.document.getElementById('result1') && parent.document.getElementById('result2')) {
if (parent.document.getElementById('result1').innerHTML == '') {
parent.document.getElementById('result1').innerHTML=(evt.target.result); // used to use window.atob and .replace('data:application/octet-stream;base64,', '')
} else {
parent.document.getElementById('result2').innerHTML=(evt.target.result); // retest earth_scanner.html
}
}
}
}

// rest of FileReader.DONE code follows
} };
})(files[ij]);

… as a solution to this issue, putting a smile to many an emoji out there.

And as far as our email or SMS sharing goes, we avoided any need for PHP mail ideas by starting to involve hashtagged versions of the incoming XML or HTML input to the XML Lint validator …

<?php echo ”

var ihemail='', ihsms='';

function dohash(isfort) {
//alert('' + isfort);
if (!isfort || 8 == 8) {
var urlis=document.URL.split('?')[0].split('#')[0];
if (('' + document.getElementById('myform').action).indexOf('#') != -1) {
//alert('#' + ('' + document.getElementById('myform').action).split('#')[1]);
document.getElementById('ihid').value='' + ('' + document.getElementById('myform').action).split('#')[1];
document.getElementById('ihid').name='browsecontents';
urlis+='?browsecontents=' + encodeURIComponent(('' + document.getElementById('myform').action).split('#')[1]) + '&' + document.getElementById('myhxfile').name + '=' + encodeURIComponent(document.getElementById('myhxfile').value.replace(/\#/g,'')) + '#' + ('' + document.getElementById('myform').action).split('#')[1] + '&contents=' + encodeURIComponent(document.getElementById('incoming').value);
} else {
//alert('bC = ' + bc);
urlis+='?' + document.getElementById('myhxfile').name + '=' + encodeURIComponent(document.getElementById('myhxfile').value.replace(/\#/g,'')) + '#contents=' + encodeURIComponent(document.getElementById('incoming').value);
}
//alert(urlis);
if (!window.opener || ('' + document.referrer) == '') {
//alert('dref=' + document.referrer + ' urlis=' + urlis);
document.body.style.cursor='progress';
woois=window.open(urlis, '_blank');
} //else {
//alert('top' + document.referrer);
//}
if (1 == 1) {
document.getElementById('myform').target='myif';
ihsms=document.getElementById('dsms').innerHTML;
ihemail=document.getElementById('demail').innerHTML;
document.getElementById('myif').style.position='absolute';
document.getElementById('myif').style.top='0px';
document.getElementById('myif').style.left='0px';
document.getElementById('myif').style.width='100%';
document.getElementById('myif').style.height='100%';
document.getElementById('myif').style.zIndex='100';
document.getElementById('myif').style.display='block';
return true;
} else {
location.href=urlis;
}
return isfort; //false;
}
//alert(87);
return true;
}

function doemail() {
}

function dosms() {
if (document.getElementById('asms').href.indexOf('sms:&') != -1) {
document.getElementById('asms').href=document.getElementById('asms').href.replace('sms:&', 'sms:' + ('' + prompt('Please enter SMS number', '')).replace(/^null/g,'') + '&');
if (document.getElementById('asms').href.indexOf('sms:&') == -1) {
document.getElementById('asms').click();
}
}
}

function checkmyif(iois) {
if (iois != null) {
paconto = (iois.contentWindow || iois.contentDocument);
if (paconto != null) {
if (paconto.document) { paconto = paconto.document; }
if (paconto.body != null && (iois.src.indexOf('?') != -1 || iois.src.indexOf('#') != -1 || ihemail != '')) {
if (('' + document.referrer) == '') {
paconto.body.style.cursor='progress';
}
if (document.getElementById('demail')) {
//alert(document.getElementById('demail').innerHTML);
if (('' + document.referrer) == '') {
paconto.body.style.cursor='progress';
}
if (ihemail != '') {
paconto.document.getElementById('demail').innerHTML=ihemail;
} else {
paconto.document.getElementById('demail').innerHTML=document.getElementById('demail').innerHTML;
}
paconto.document.getElementById('demail').style.display='inline-block';
}
if (document.getElementById('dsms')) {
if (ihsms != '') {
paconto.document.getElementById('demail').innerHTML=ihsms;
} else {
paconto.document.getElementById('dsms').innerHTML=document.getElementById('dsms').innerHTML;
}
paconto.document.getElementById('dsms').style.display='inline-block';
}
}
}
}
}

function maybeshow() {
if (document.getElementById('incoming').value != '') {
var wwoo=window.open('','_blank','top=50,left=50,width=900,height=900');
if (document.getElementById('myhxfile').value != '') {
wwoo.document.write('<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>' + document.getElementById('myhxfile').value + '</title></head><body><textarea style=width:100%;height:100%;>' + document.getElementById('incoming').value + '</textarea></body></html>');
} else if (document.getElementById('myhxfile').placeholder.indexOf('Please ') == -1) {
wwoo.document.write('<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>' + document.getElementById('myhxfile').placeholder + '</title></head><body><textarea style=width:100%;height:100%;>' + document.getElementById('incoming').value + '</textarea></body></html>');
} else {
wwoo.document.write('<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>XML Lint Validation incoming XML or HTML</title></head><body><textarea style=width:100%;height:100%;>' + document.getElementById('incoming').value + '</textarea></body></html>');
}
}
}

“; ?>

… called into play via “a wrapped” HTML form onsubmit event call change

<?php

<form accept-charset="UTF-8" onsubmit=" if (document.getElementById('myhxfile').value == '') { document.getElementById('myhxfile').name='xx'; } return dohash(true);" action=./xmllint_validation.php<?php echo $bc; ?> id=myform method=POST target=_self>

?>

… in our changed “fifth draft” xmllint_validation.php you might want to try for yourself.

Happy sharing!


Previous relevant XML Lint Validation SelectionChange Tutorial is shown below.

XML Lint Validation SelectionChange Tutorial

XML Lint Validation SelectionChange Tutorial

Onto yesterday’s XML Lint Validation Onclick Tutorial‘s …

  • left hand cell hosted pair of textarea element onclick (and ondblclick) event logics … today we think a user could benefit from …
  • right hand cell hosted textarea element SelectionChange (keyboard related) event triggered via the user highlighting that textarea text (containing errors) of interest

… via …

<?php echo ”

var thesel='', reng='';

function prereverseengineer() {
var wasreng=reng;
reng='';
reverseengineer(wasreng);
}

function reverseengineer(what) {
var oury2=0, nexty2=0;
var theheight=eval(eval('' + s2rect.height) / rowseq);
var codelines=s2.value.split(String.fromCharCode(10));
var errdetail='', ierr=0, linenum=0, nums=[];
thergb=redrgb;
var bimg='linear-gradient(to bottom, white, '; // ' white ' + y2 + 'px, ' + thergb + ' ' + y2 + 'px, ' + thergb + ' ' + eval(y2 + eval('' + s1rect.height) / rowseq) + 'px, white ' + eval(y1 + eval('' + s1rect.height) / rowseq) + 'px, white)';
var suff=', white)';

if (what.trim() != '') {
nums=what.split(',');
}
if (eval('' + nums.length) > 0) {
window.scrollTo(0,0);
s1.title='' + nums[0]; // + linenum;
s2.title='' + codelines[eval(-1 + eval('' + nums[0]))];
//alert(what);
oury2=eval(eval(-1 + eval('' + nums[0])) * theheight);
bimg+=' white ' + oury2 + 'px, ' + thergb + ' ' + oury2 + 'px, ' + thergb + ' ' + eval(oury2 + eval('' + s1rect.height) / rowseq) + 'px, white ' + eval(oury2 + eval('' + s1rect.height) / rowseq) + 'px, ';
for (ierr=1; ierr<nums.length; ierr++) {
oury2=eval(eval(-1 + eval('' + nums[ierr])) * theheight);
//bimg+=thergb + ' ' + eval(oury2 + eval('' + s1rect.height) / rowseq) + 'px, white ' + oury2 + 'px, ' + thergb + ' ' + oury2 + 'px, '; // + thergb + ' ' + eval(oury2 + eval('' + s1rect.height) / rowseq) + 'px, ';
bimg+=' white ' + oury2 + 'px, ' + thergb + ' ' + oury2 + 'px, ' + thergb + ' ' + eval(oury2 + eval('' + s1rect.height) / rowseq) + 'px, white ' + eval(oury2 + eval('' + s1rect.height) / rowseq) + 'px, ';
s1.title+=String.fromCharCode(10) + '' + nums[ierr]; // + linenum;
s2.title+=String.fromCharCode(10) + '' + codelines[eval(-1 + eval('' + nums[ierr]))];
}
if (bimg.indexOf(suff) == -1) { bimg+=suff.substring(1); }
s1.style.backgroundImage='' + bimg;
s2.style.backgroundImage='' + bimg;
document.getElementById('outgoing').title='Highlighted to left are codelines ' + what + ' with errors';
}
}

function decorateleft() {
var jerr=0;
reng=''
if (ourdelim == ':') {
for (jerr=1; jerr<ourfindsare.length; jerr++) {
if (ourfindsare[jerr].trim() != '') {
if (ourfindsare[jerr].substring(0,1) >= '0' && ourfindsare[jerr].substring(0,1) <= '9') {
if (ourfindsare[jerr].slice(-1) >= '0' && ourfindsare[jerr].slice(-1) <= '9') {
if ((',' + reng + ',').indexOf(',' + ourfindsare[jerr].split(':')[0] + ',') == -1) {
if (reng == '') { reng=ourfindsare[jerr]; } else { reng+=',' + ourfindsare[jerr]; }
}
}
}
}
}
} else if (ourdelim.trim() != '') {
for (jerr=1; jerr<ourfindsare.length; jerr++) {
if (ourfindsare[jerr].split(':')[0].trim() != '') {
if (ourfindsare[jerr].split(':')[0].substring(0,1) >= '0' && ourfindsare[jerr].split(':')[0].substring(0,1) <= '9') {
if (ourfindsare[jerr].split(':')[0].slice(-1) >= '0' && ourfindsare[jerr].split(':')[0].slice(-1) <= '9') {
if ((',' + reng + ',').indexOf(',' + ourfindsare[jerr].split(':')[0] + ',') == -1) {
if (reng == '') { reng=ourfindsare[jerr].split(':')[0]; } else { reng+=',' + ourfindsare[jerr].split(':')[0]; }
}
}
}
}
}
}
if (reng != '') {
setTimeout(prereverseengineer, 9000); // reverseengineer(reng);
}
}

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

// Make sure this is your textarea
//document.title=(('' + activeElement.id) + activeElement.outerHTML.substring(0,23));
if (activeElement && activeElement.outerHTML.indexOf('<textarea') == 0 && ('' + activeElement.id) == 'outgoing') {
const range = {
start: activeElement.selectionStart,
end: activeElement.selectionEnd
};
ourdelim=':';
ourfindsare=[];
thesel='';
// Do something with your range
if (eval('' + range.end) > eval('' + range.start)) {
thesel=(activeElement.value.substring(range.start).substring(0, eval(eval('' + range.end) - eval('' + range.start) )));
if (thesel.trim() != '' && thesel.indexOf(':') != -1) {
var floc=thesel.split(':')[0];
if (tfis != '') {
if (eval('' + floc.length) >= eval('' + tfis.length)) {
ourdelim=tfis + ':';
ourfindsare=thesel.split(ourdelim);
} else {
thesel=thesel.replace(':', tfis + ':');
ourdelim=tfis + ':';
ourfindsare=thesel.split(ourdelim);
}
} else {
ourfindsare=thesel.split(ourdelim);
}
decorateleft();
}
}
}
}

document.addEventListener('selectionchange', handleSelection);

“; ?>

… in our changed “fourth draft” xmllint_validation.php you might want to try for yourself.


Previous relevant XML Lint Validation Onclick Tutorial is shown below.

XML Lint Validation Onclick Tutorial

XML Lint Validation Onclick Tutorial

Onto yesterday’s XML Lint Validation Browsing Tutorial XML Lint Validation web application progress, today, we start to add some onclick and ondblclick event logic to those left hand table cell pair of textarea elements …

<?php echo ”

function gcbr() {
if (rowseq != '') {
s1rect=s1.getBoundingClientRect();
s1.onclick=function(event) { s1click(event); };
s1.ondblclick=function(event) { alert('Line ' + s1.title + s1.getAttribute('data-status') + ':' + String.fromCharCode(10) + s2.title); };
s2rect=s2.getBoundingClientRect();
s2.onclick=function(event) { s2click(event); };
s2.ondblclick=function(event) { alert('Line ' + s1.title + s1.getAttribute('data-status') + ':' + String.fromCharCode(10) + s2.title); };
}

if (('' + location.hash).replace(/^null/g,'').replace(/^undefined/g,'').trim() != '') {
if (document.getElementById('myhxfile').value == '') {
document.getElementById('myhxfile').placeholder=decodeURIComponent(('' + location.hash).replace(/^\#/g,''));
var tf=document.getElementById('outgoing').value;
var tfis=tf.split(':')[0];
if (tfis.trim() != '') {
while (tf.indexOf(tfis + ':') != -1) {
tf=tf.replace(tfis + ':', decodeURIComponent(('' + location.hash).replace(/^\#/g,'')) + ':');
}
document.getElementById('outgoing').value=tf;
}
}
}
}

“; ?>

… and though we usually do not associate onclick logic with textarea elements, today we’re preferring that to any alternate use of div element alternative because, today, for the first time, we’re making use of the “sharp” colour stops mentioned by linear-gradient(), thanks …

<?php echo ”

function s1click(e) {
var theheight=eval(eval('' + s1rect.height) / rowseq);
var codelines=s2.value.split(String.fromCharCode(10));
var errdetail='', ierr=0, linenum=0;
if (e.touches) {
if (e.touches[0].pageX) {
x1=(eval(e.touches[0].pageX + document.body.scrollLeft * 1) * 1);
y1=(eval(e.touches[0].pageY + eval(eval(e.touches[0].pageY % theheight) - theheight) + document.body.scrollTop * 1) * 1);
linenum=Math.floor(eval(1 + eval(eval(e.touches[0].pageY + document.body.scrollTop - s1rect.top) / theheight)));
} else {
x1=(eval(e.touches[0].clientX + document.body.scrollLeft * 1) * 1);
y1=(eval(e.touches[0].clientY + eval(eval(e.touches[0].clientY % theheight) - theheight) + document.body.scrollTop * 1) * 1);
linenum=Math.floor(eval(1 + eval(eval(e.touches[0].clientY + document.body.scrollTop - s1rect.top) / theheight)));
}
} else if (e.clientX || e.clientY) {
x1=(e.clientX + document.body.scrollLeft * 1);
y1=(e.clientY + eval(eval(e.clientY % theheight) - theheight) + document.body.scrollTop * 1);
linenum=Math.floor(eval(1 + eval(eval(e.clientY + document.body.scrollTop - s1rect.top) / theheight)));
} else {
x1=(e.pageX + document.body.scrollLeft * 1);
y1=(e.pageY + eval(eval(e.pageY % theheight) - theheight) + document.body.scrollTop * 1);
linenum=Math.floor(eval(1 + eval(eval(e.pageY + document.body.scrollTop - s1rect.top) / theheight)));
}
//alert('' + linenum + ' ' + y1 + '/' + document.body.scrollTop + ' ... ' + s1.scrollTop + ' ... ' + s1rect.top + '/' + s1rect.y + ' +++ ' + theheight);
var finds=document.getElementById('outgoing').value.split(':' + linenum + ':');
thergb=greenrgb;
s1.setAttribute('data-status', '');
if (eval('' + finds.length) > 1) {
for (ierr=1; ierr<finds.length; ierr++) {
errdetail+=String.fromCharCode(10) + finds[eval(-1 + ierr)].split(':' + linenum + ':')[0].split(String.fromCharCode(10))[eval(-1 + finds[eval(-1 + ierr)].split(':' + linenum + ':')[0].split(String.fromCharCode(10)).length)] + ':' + linenum + ':' + finds[eval(0 + ierr)].split(String.fromCharCode(10))[0];
}
errdetail+=String.fromCharCode(10);
thergb=redrgb;
s1.setAttribute('data-status', ' (has errors ... ' + errdetail + ' ... over to the right)');
}
s1.title='' + linenum;
s2.title='' + codelines[eval(-1 + linenum)];
y1-=eval('' + s1rect.top);
// linear-gradient(to right, yellow, yellow 20%, #009966 20%, #009966 80%, purple 80%, purple);
//alert('linear-gradient(to bottom, white, white ' + y1 + 'px, ' + thergb + ' ' + y1 + 'px, ' + thergb + ' ' + eval(y1 + eval('' + s2rect.height) / rowseq) + 'px, white ' + eval(y1 + eval('' + s2rect.height) / rowseq) + 'px, white)');
s2.style.backgroundImage='linear-gradient(to bottom, white, white ' + y1 + 'px, ' + thergb + ' ' + y1 + 'px, ' + thergb + ' ' + eval(y1 + eval('' + s2rect.height) / rowseq) + 'px, white ' + eval(y1 + eval('' + s2rect.height) / rowseq) + 'px, white)';
s1.style.backgroundImage='linear-gradient(to bottom, white, white ' + y1 + 'px, ' + thergb + ' ' + y1 + 'px, ' + thergb + ' ' + eval(y1 + eval('' + s2rect.height) / rowseq) + 'px, white ' + eval(y1 + eval('' + s2rect.height) / rowseq) + 'px, white)';
}

function s2click(e) {
var theheight=eval(eval('' + s2rect.height) / rowseq);
var codelines=s2.value.split(String.fromCharCode(10));
var errdetail='', ierr=0, linenum=0;
if (e.touches) {
if (e.touches[0].pageX) {
x2=(eval(e.touches[0].pageX + document.body.scrollLeft * 1) * 1);
y2=(eval(e.touches[0].pageY + eval(eval(e.touches[0].pageY % theheight) - theheight) + document.body.scrollTop * 1) * 1);
linenum=Math.floor(eval(1 + eval(eval(e.touches[0].pageY + document.body.scrollTop - s2rect.top) / theheight)));
} else {
x2=(eval(e.touches[0].clientX + document.body.scrollLeft * 1) * 1);
y2=(eval(e.touches[0].clientY + eval(eval(e.touches[0].clientY % theheight) - theheight) + document.body.scrollTop * 1) * 1);
linenum=Math.floor(eval(1 + eval(eval(e.touches[0].clientY + document.body.scrollTop - s2rect.top) / theheight)));
}
} else if (e.clientX || e.clientY) {
x2=(e.clientX + document.body.scrollLeft * 1);
y2=(e.clientY + eval(eval(e.clientY % theheight) - theheight) + document.body.scrollTop * 1);
linenum=Math.floor(eval(1 + eval(eval(e.clientY + document.body.scrollTop - s2rect.top) / theheight)));
} else {
x2=(e.pageX + document.body.scrollLeft * 1);
y2=(e.pageY + eval(eval(e.pageY % theheight) - theheight) + document.body.scrollTop * 1);
linenum=Math.floor(eval(1 + eval(eval(e.pageY + document.body.scrollTop - s2rect.top) / theheight)));
}
var finds=document.getElementById('outgoing').value.split(':' + linenum + ':');
thergb=greenrgb;
s1.setAttribute('data-status', '');
if (eval('' + finds.length) > 1) {
for (ierr=1; ierr<finds.length; ierr++) {
errdetail+=String.fromCharCode(10) + finds[eval(-1 + ierr)].split(':' + linenum + ':')[0].split(String.fromCharCode(10))[eval(-1 + finds[eval(-1 + ierr)].split(':' + linenum + ':')[0].split(String.fromCharCode(10)).length)] + ':' + linenum + ':' + finds[eval(0 + ierr)].split(String.fromCharCode(10))[0];
}
errdetail+=String.fromCharCode(10);
thergb=redrgb;
s1.setAttribute('data-status', ' (has errors ... ' + errdetail + ' ... over to the right)');
}
s1.title='' + linenum;
s2.title='' + codelines[eval(-1 + linenum)];
y2-=eval('' + s2rect.top);
s2.style.backgroundImage='linear-gradient(to bottom, white, white ' + y2 + 'px, ' + thergb + ' ' + y2 + 'px, ' + thergb + ' ' + eval(y2 + eval('' + s1rect.height) / rowseq) + 'px, white ' + eval(y1 + eval('' + s1rect.height) / rowseq) + 'px, white)';
s1.style.backgroundImage='linear-gradient(to bottom, white, white ' + y2 + 'px, ' + thergb + ' ' + y2 + 'px, ' + thergb + ' ' + eval(y2 + eval('' + s1rect.height) / rowseq) + 'px, white ' + eval(y1 + eval('' + s1rect.height) / rowseq) + 'px, white)';
}

“; ?>

to be able to add colour coding to (the background of) HTML textarea elements.

Also, a hashtagging idea is implemented to aid with bringing over a browsed for file name into the “reporting mix” in our changed “third draft” xmllint_validation.php you might want to try for yourself.


Previous relevant XML Lint Validation Browsing Tutorial is shown below.

XML Lint Validation Browsing Tutorial

XML Lint Validation Browsing Tutorial

Yesterday’s XML Lint Validation Tutorial had us starting out on a discovery tour of XML Lint, yesterday …

  • starting with an HTML or XML URL of interest incoming data way … and today, we add onto that …
  • a local HTML or XMLfile browsing means of defining your input data into …

our changed “second draft” xmllint_validation.php you might want to try for yourself, helped out by a tweaked client_browsing.htm client side HTML and Javascript inhouse helper.

Again, we see, into another way to yesterday’s work, how useful is a textarea element, in that it can facilitate the way …

  • HTML and XML data can be input via populating the textarea innerHTML attribute … which flows through to a …
  • textarea value attribute value where any < is mapped to &lt; and > is mapped to &gt; … ready for …
  • an HTML form hosted textarea, given a filled in name attribute be able to share this data to that form’s action attributed value …
    <?php

    function ronecheck() {
    if (document.getElementById('result1').innerHTML != '') {
    document.getElementById('incoming').innerHTML=document.getElementById('result1').value;
    document.getElementById('result1').innerHTML='';
    document.getElementById('result1').value='';
    document.getElementById('myhxfile').name='xx';
    document.getElementById('mysub').click();
    }
    }

    ?>
    … (in our case being the same PHP) …
  • able to be processed by recall PHP interventional code …
    <?php

    $vsnone='none';
    $prefn='Please enter either HTML or XML file to validate ...';
    $pth='';
    $rn='' .rand(1,78477554);
    $results='';
    $precontents='';
    $contents='';
    $fn='';
    if (!isset($_GET['htmlfile']) && isset($_GET['content'])) {
    $_GET['htmlfile']=$_GET['content'];
    }
    if (!isset($_POST['htmlfile']) && isset($_POST['content'])) {
    $_POST['htmlfile']=$_POST['content'];
    }
    if (isset($_GET['htmlfile'])) {
    if (substr(trim(urldecode($_GET['htmlfile'])) . ' ', 0, 1) == '<') {
    $contents=trim(str_replace('+',' ',urldecode($_GET['htmlfile'])));
    if (strpos(strtolower(explode('>', $contents)[0]), 'html') !== false) {
    $fn='/tmp/html_' . $rn . '.html';
    } else if (strpos(strtolower(explode('>', $contents)[0]), 'xml') !== false) {
    $fn='/tmp/xml_' . $rn . '.xml';
    }
    file_put_contents($fn, $contents);
    } else {
    $fn=str_replace('+',' ',urldecode($_GET['htmlfile']));
    }
    if ($fn != '') {
    if (strpos($fn, 'localhost') !== false) {
    $rhs=explode('localhost' . explode('/', explode('localhost', $fn)[1])[0], $fn)[1];
    $fn=$_SERVER['DOCUMENT_ROOT'] . $rhs;
    $pth='/usr/bin/';
    } else if (strpos($fn, 'rjmprogramming.com.au') !== false) {
    $rhs=explode('rjmprogramming.com.au' . explode('/', explode('rjmprogramming.com.au', $fn)[1])[0], $fn)[1];
    $fn=$_SERVER['DOCUMENT_ROOT'] . $rhs;
    } else if (strpos($_SERVER['SERVER_NAME'], 'localhost') !== false) {
    $pth='/usr/bin/';
    }
    }
    if (file_exists($fn)) {
    if ($contents == '') {
    $contents=file_get_contents($fn);
    }
    $prefn=$fn;
    $fn=realpath($fn);
    if (strpos(strtolower($fn), '.xml') !== false) {
    $vsnone='block';
    $results=shell_exec($pth . 'xmllint --valid --noout ' . $fn . ' 2> ' . ' ' . rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    if (file_exists(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err')) {
    $results.="\n";
    $results.=file_get_contents(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    unlink(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    }
    } else if (strpos(strtolower($fn), '.htm') !== false) {
    $vsnone='block';
    $results=shell_exec($pth . 'xmllint --html --valid --noout ' . $fn . ' 2> ' . ' ' . rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    if (file_exists(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err')) {
    $results.="\n";
    $results.=file_get_contents(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    unlink(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    }
    }
    if (strpos($fn, '/tmp/') !== false) { unlink($fn); }
    } else {
    $contents='';
    if (strpos($fn, '/tmp/') !== false) { unlink($fn); }
    }
    } else if (isset($_POST['htmlfile'])) {
    if (substr(trim(urldecode($_POST['htmlfile'])) . ' ', 0, 1) == '<') {
    $contents=trim(str_replace('+',' ',urldecode($_POST['htmlfile'])));
    if (strpos(strtolower(explode('>', $contents)[0]), 'html') !== false) {
    $fn='/tmp/html_' . $rn . '.html';
    } else if (strpos(strtolower(explode('>', $contents)[0]), 'xml') !== false) {
    $fn='/tmp/xml_' . $rn . '.xml';
    }
    file_put_contents($fn, $contents);
    } else {
    $fn=str_replace('+',' ',urldecode($_POST['htmlfile']));
    }
    if ($fn != '') {
    if (strpos($fn, 'localhost') !== false) {
    $rhs=explode('localhost' . explode('/', explode('localhost', $fn)[1])[0], $fn)[1];
    $fn=$_SERVER['DOCUMENT_ROOT'] . $rhs;
    $pth='/usr/bin/';
    } else if (strpos($fn, 'rjmprogramming.com.au') !== false) {
    $rhs=explode('rjmprogramming.com.au' . explode('/', explode('rjmprogramming.com.au', $fn)[1])[0], $fn)[1];
    $fn=$_SERVER['DOCUMENT_ROOT'] . $rhs;
    } else if (strpos($_SERVER['SERVER_NAME'], 'localhost') !== false) {
    $pth='/usr/bin/';
    }
    }
    if (file_exists($fn)) {
    $prefn=$fn;
    if ($contents == '') {
    $contents=file_get_contents($fn);
    }
    $fn=realpath($fn);
    if (strpos(strtolower($fn), '.xml') !== false) {
    $vsnone='block';
    $results=shell_exec($pth . 'xmllint --valid --noout ' . $fn . ' 2> ' . ' ' . rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    if (file_exists(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err')) {
    $results.="\n";
    $results.=file_get_contents(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    unlink(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    }
    } else if (strpos(strtolower($fn), '.htm') !== false) {
    $vsnone='block';
    $results=shell_exec($pth . 'xmllint --html --valid --noout ' . $fn . ' 2> ' . ' ' . rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    if (file_exists(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err')) {
    $results.="\n";
    $results.=file_get_contents(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    //file_put_contents('xxx.xxx', $results);
    unlink(rtrim(dirname(__FILE__), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'xmllint.err');
    }
    }
    if (strpos($fn, '/tmp/') !== false) { unlink($fn); }
    } else {
    $contents='';
    if (strpos($fn, '/tmp/') !== false) { unlink($fn); }
    }
    }
    if ($contents != '') {
    $lines=explode("\n", $contents);
    for ($ii=1; $ii<=sizeof($lines); $ii++) {
    $precontents.='' . $ii . "\n";
    }
    }

    ?>

Cute, huh?!


Previous relevant XML Lint Validation Tutorial is shown below.

XML Lint Validation Tutorial

XML Lint Validation Tutorial

Do you remember when we discussed the Sanitizer API, talked about at Sanitizer API Primer Tutorial, regarding it as a web application HTML (and more) validation tool?

Well, we’ve based a new “validator” of HTML or XML using the XML Lint web application on what we did then, but this code needing to be …

  • under the auspices of a serverside scenario … ie. PHP … for us … calling on …
  • underlying operating system call such as (for HTML qsall.htm incoming data file) …

    xmllint --html --valid --noout ./qsall.htm

    … via …
  • shell_exec

… there’s not much left of the original HTML and Javascript!

We had a fun time with HTML textarea elements and scrolling with the resultant “first draft” xmllint_validation.php you might want to try for yourself supplying an HTML or XML URL of intetest. Why, in particular? Well, it was the first time that we remember trying to make practically useful …

  • a table cell (ie. td element) (the left of two) hosted …
  • two textarea element arrangement whereby, ideally. they view …
    1. side by side
    2. if one is scrolled the two identically scroll the same amount … (document.body outerHTML) HTML …
      <?php echo ”

      <body onload="s1 = document.getElementById('preincoming'); s2 = document.getElementById('incoming'); s1.addEventListener('scroll', select_scroll_1, false); s2.addEventListener('scroll', select_scroll_2, false);" data-onload='onl();'>
      <h1>XML Lint Validation <!--button onclick='trythis();' title='Try your own'>Usage</button--></h1>
      <h3>RJM Programming - June, 2024</h3>
      <form action=./xmllint_validation.php method=POST target=_self>
      <table style=width:95%; border=5>
      <tr><th colspan=2 style=text-align:center;>XML Lint validation of <input style=width:70%; onblur="if (this.value.length > 0) { document.getElementById('mysub').click(); }" name=htmlfile id=myhxfile placeholder='Please enter either HTML or XML file to validate ...' value="<?php echo str_replace('>','>',str_replace('<','<',$prefn)); ?>"></input></th></tr>
      <tr><th>Data to validate</th><th>XML Lint results</th></tr>
      <tr><td style=vertical-align:top;><textarea style=font-size:8px;display:inline-block;overflow-x:clip;text-wrap:nowrap;text-align:right; id=preincoming><?php echo str_replace('>','>',str_replace('<','<',$precontents)); ?></textarea><textarea onblur="if (this.value.length > 0 && '<?echo $fn; ?>' == '') { document.getElementById('mysub').click(); }" style=font-size:8px;display:inline-block;overflow-x:clip;text-wrap:nowrap; name=content id=incoming><?php echo str_replace('>','>',str_replace('<','<',$contents)); ?></textarea></td><td style=vertical-align:top;><textarea id=outgoing><?php echo str_replace('>','>',str_replace('<','<',$results)); ?></textarea></td></tr>
      <tr><td></td><td><input type=submit id=mysub style=display:<?php echo $vsnone; ?> value=Validate></input></td></tr>
      </table>
      </form>
      </body>

      “; ?>
      … uses Javascript …
      <?php echo ”

      var s1=null, s2=null;

      // Thanks to https://stackoverflow.com/questions/7108270/scrolling-2-different-elements-in-same-time
      function select_scroll_1(e) { s2.scrollTop = s1.scrollTop; }
      function select_scroll_2(e) { s1.scrollTop = s2.scrollTop; }

      “; ?>
      … so that …
    3. the left hand textarea contains code line numbers right aligned … to sidle up next to …
    4. the right hand textarea contains the code (HTML or XML) being validated by xmllint

    … while …

  • the right hand table cell contains the xmllint validation (of HTML or XML) results

… had us, in practice, thanking our lucky stars that …

  1. textarea elements are resizeable
  2. you can simulate “some cockpit action” aligning them vertically … Jim?!


Previous relevant Sanitizer API Primer Tutorial is shown below.

Sanitizer API Primer Tutorial

Sanitizer API Primer Tutorial

Today we’re roadtesting the Sanitizer API

The HTML Sanitizer API allow developers to take untrusted strings of HTML and Document or DocumentFragment objects, and sanitize them for safe insertion into a document’s DOM.

… as another validation idea for HTML to add to our previous HTML Online Validation Tidy Errors Tutorial efforts.

Perhaps you’d like to try the “Usage” button of the proof of concept web application below …

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


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


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


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


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


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


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

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

Xgimi Projector Android TV Web Browser Tutorial

Xgimi Projector Android TV Web Browser Tutorial

Xgimi Projector Android TV Web Browser Tutorial

For some time now, we’ve had no Android phone to test web applications with. This can be like “flying blind” regarding a big sector of the online user cohort.

There are simulators out there, but we thought of another idea early this morning. The recent Projector Viewing Primer Tutorial talked about …

… and we thought that with that word “Android” involved, if the Google Play has an app to support a web browser accessible via the Xgimi projector, then we “might be cooking with gas”.

The second such web browser related app called “Browser”, of many, hit that nail on its head, mentioning in its credentials “Android” in amongst the …


alert('navigator.userAgent=' + ('' + navigator.userAgent)); // via codeline ... // aconto.getElementById('mytable').ondblclick=function(){ alert('navigator.userAgent=' + ('' + navigator.userAgent)); };

… test we conducted for each new Browser app installed.

And using this environment to call our RJM Programming Landing Page links to blog posts like below’s Projector Viewing Primer Tutorial show, at least, two issues …

  1. Landing Page clicks of “those blue backgrounded” thumbnails did not succeed in opening the relevent WordPress Blog post … and …
  2. at that relevant WordPress Blog post clicking the main blog post image failed too

We found, with Android, navigation was friendliest using …


top.location.href=[WordPressBlogPostURL];

… Javascript code arrangements, and in both cases we fell short, with existant code so that we needed to attend to …

  1. Landing Page clicks of “those blue backgrounded” thumbnails did not succeed in opening the relevent WordPress Blog post … was fixed via

    function check_if(iois) {
    if (iois != null) {
    var aconto = (iois.contentWindow || iois.contentDocument);
    if (aconto != null) {
    if (aconto.document) { aconto = aconto.document; }
    if (aconto.body != null) {
    if (navigator.userAgent.match(/Android/i)) {
    aconto.body.innerHTML=aconto.body.innerHTML.replace(/\=one_o_five\;\"/g, "=one_o_five; if (navigator.userAgent.match(/Android/i)) { if (parent.document.getElementById('ibelow')) { top.location.href=('' + this.parentNode.href); } }" + '"');
    }

    var igs=aconto.getElementsByTagName('img');
    for (var jigs=0; jigs<igs.length; jigs++) {
    if (igs[jigs].src.indexOf('?rand') != -1) { igs[jigs].src+='' + Math.floor(Math.random() * 456) + '&x=x'; }
    }
    aconto.getElementById('mytable').style.width='100%';
    aconto.getElementById('mytable').style.backgroundColor='rgba(150,120,250,0.5)';
    //aconto.getElementById('mytable').ondblclick=function(){ alert('navigator.userAgent=' + ('' + navigator.userAgent)); };
    }
    }
    }
    }

    … and …
  2. at that relevant WordPress Blog post clicking the main blog post image failed too … and fixed via TwentyTen theme header.php changes …
    <?php echo ”

    var imgi = document.getElementsByTagName('img');
    for (iyt=0; iyt<imgi.length; iyt++) {
    if (navigator.userAgent.match(/Android/i)) {
    if (iyt == 0) {
    document.getElementById('styleandroid').innerHTML='<sty' + "le> .wp-caption-text { text-decoration: underline; } .wp-caption-text::before { content: '\\01F517 '; } </sty" + 'le>';
    }
    if (imgi[iyt].parentElement) {
    if (imgi[iyt].parentNode.href) {
    imgi[iyt].parentNode.ontouchend=function(event){ top.location.href=event.target.href; };
    //imgi[iyt].ontouchstart=function(evt){ top.location.href=evt.target.parentNode.href; };
    }
    }
    }

    altis = imgi[iyt].alt;
    titleis = imgi[iyt].title;
    if (altis == null) {
    if (titleis != null) {
    if (titleis != '') {
    imgi[iyt].alt = titleis;
    }
    }
    } else if (altis == '') {
    if (titleis != null) {
    if (titleis != '') {
    imgi[iyt].alt = titleis;
    }
    }
    }
    }

    “; ?>

… all possible because of this new Xgimi Google Play and Android TV app called “Browser” (you all might be able to see) on today’s animated GIF presentation showing this install process.


Previous relevant Projector Viewing Primer Tutorial is shown below.

Projector Viewing Primer Tutorial

Projector Viewing Primer Tutorial

Are you interested in swapping out a television viewing system of watching entertainment for a projector based one?

We recently acquired an Xgimi projector, and after setting up the projector with a decent screen to project to, found the setting up of streaming applications through Google Play, via, perhaps, a Gmail account, very easy, to the point we got the usual big players there, as well as the crossover to Apple TV via the Apple ID we had, and no need for the Apple TV hardware! It’s all there ready to go with the one Xgimi projector device (and stand, we found useful).

We’re sure it’s a pros and cons decision for you going this way, or not, but we found …

  • people feel less guilty coming and going from the entertainment viewing when there is no one television screen present (and we saw this as a pro)
  • the viewing screen is naturally big, rather than “damaging to the earth” big, as plasma screens can be
  • there are far fewer leads involved
  • only one remote works everything
  • when not watching (and we’d say, even when watching) the projector system it is not there unnecessarily soaking up attention
  • like back in school, some smart Alec, or stupid Alec, or both, might get to say …

    Down in front!

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


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

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