Walking Trip …

Walking Trip

Walking Trip

Offenbach's Suite ... Warts 'n All

Offenbach's Suite ... Warts 'n All

 📅  

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

Posted in Photography, Trips | Tagged , , | 34 Comments

Keyboard Shortcuts for Bluetooth on macOS Tutorial

Keyboard Shortcuts for Bluetooth on macOS Tutorial

Keyboard Shortcuts for Bluetooth on macOS Tutorial

What is macOS Spotlight?

Spotlight is macOS’s built-in, system-wide search engine. Activated by pressing Command + Spacebar, it lets you instantly find files, launch apps, perform math calculations, convert currency, check weather, and run quick system commands without leaving your current window.

… or, for the purposes of today’s tutorial’s purposes, is the bosom buddy, on macOS, of …

Keyboard Shortcuts

… because, after that initial …

Command + Spacebar

… keyboard … shortcut … to get to the Spotlight desktop application, just about everything is possible to get to, to many degrees, without relying on any clicks anywhere, as the previous Windows and macOS Hanging Useful Keyboard Shortcuts Tutorial set the scene for, too.

So, why the interest?

Well, we got into a spot of bother where it became very useful to use (just keyboard) …

  1. Command + Spacebar
  2. Bluetooth
  3. Return key
  4. Arrow down to Bluetooth File Exchange
  5. Return key
  6. Arrow down to (in our case) M720 Triathlon
  7. Return key

… one day. Huh?!

Let me explain. We’ve had clicking problems with this MacBook Air’s trackpad to do with it’s clicking capabilities only (ie. swipe gestures still worked), and, as we gave a bit of the background to with Bluetooth Mouse Show Desktop Primer Tutorial the way we worked around this was to buy and install a bluetooth mouse from Logitech called the M720 Triathlon. All good for more than a year now. But one day we turned Bluetooth Off then rebooted the MacBook Air. Ouch?! Sure, we could log in to the desktop, but doing much else easily relied on …

  • a fully functional trackpad … or, what could of worked if we’d arranged it …
  • an installed USB lead based mouse … or even, perhaps, we’re not sure …
  • plugging in some USB lead based mouse that is plug and play

… none of which were available to me. But good ol’ Spotlight and Keyboard Shortcuts were (ie. to reconnect the bluetooth mouse)! Yayyyyyy!

Can hear some of you asking …

So, what happens when the M720 Triathlon runs out of battery? Isn’t it the same panic?

Well, it happened last week, and we were wondering too! A message comes up on the macOS screen to say the M720 Triathlon is low on battery power, and we just took that message at it’s word, changing the battery, and carried on.

Can hear some of you asking …

So, do the M720 Triathlon and what’s left of the trackpad’s functionality get in each other’s way?

No, they can either or both work at whatever they are capable of.


Previous relevant Windows and macOS Hanging Useful Keyboard Shortcuts Tutorial is shown below.

Windows and macOS Hanging Useful Keyboard Shortcuts Tutorial

Windows and macOS Hanging Useful Keyboard Shortcuts Tutorial

Revisiting the Dots and Boxes game of Dots and Boxes Game Parameterization Tutorial today, on this macOS MacBook Air …

Shock, Horror, Tragedy

… it gave us that very annoying “hanging experience” to the extent that our MacBook Air rebooted itself. And so, given this, we hereby apologize if a previous version of the Dots and Boxes game has caused you any grief.

But the fix to our dots_and_boxes_game.html Dots and Boxes game was a “one number different” fix, and rather than short change our readers … heaven forbid … we’re going to focus, today, more on what keyboard shortcuts on macOS or Windows might help you out in the bad scenario described above …

keyboard shortcut for force quit current application

For Mac, press Option + Command + Esc to open the Force Quit window, or hold Option + Command + Shift + Esc for three seconds to force quit the active app directly. For Windows, press Alt + F4 to close the active app, or Ctrl + Shift + Esc to open Task Manager to kill processes.

Mac Force Quit Shortcuts:
Force Quit Dialog: Option + Command + Esc
Force Quit Focused App: Option + Command + Shift + Esc (hold for 3 seconds)
Standard Quit: Command + Q

Windows Force Quit Shortcuts:
Close Active App: Alt + F4
Open Task Manager (to terminate app): Ctrl + Shift + Esc
Alternative Task Manager: Ctrl + Alt + Delete then select Task Manager

Linux/Other:
Xkill: Ctrl + Alt + Esc (often used to click and destroy a window)

These may or may not help depending on the severity of the memory issue you are facing, in which case …

keyboard shortcut for rebooting on operating system

For Windows, use Win + X then U then R for a fast restart. Alternatively, Alt + F4 on the desktop opens a shutdown menu. For Mac, use Control + Command + Power Button to force a restart. These methods allow full system control without a mouse.

Windows Restart Shortcuts
Power User Menu (Fastest): Press Win + X, then U, then R.
Desktop Shutdown: Press Alt + F4 while on the desktop to open the shutdown dialog, then select “Restart”.
Ctrl+Alt+Del: Press Ctrl + Alt + Del, use arrow keys to reach the power icon, press Enter, and select “Restart”.
Run Command: Press Win + R, type shutdown -r -t 0, and hit Enter.

macOS Restart Shortcuts
Force Restart: Control + Command + Power button (or Touch ID button).
Standard Restart: Control + Option + Command + Power button (closes apps, then restarts).

Linux/Other
Alt+SysRq+B: Forcibly reboots the system immediately.

We hope, one day, but not too soon, you find this useful?!


Previous relevant Dots and Boxes Game Parameterization Tutorial is shown below.

Dots and Boxes Game Parameterization Tutorial

Dots and Boxes Game Parameterization Tutorial

We quite like …

  • substitutional approaches to coding
  • interpretive approaches to coding
  • take a hardcoded string and either …
    1. parameterize it
    2. repurpose it

… and with the “Dots and Boxes Game” web application of yesterday’s Dots and Boxes Game Primer Tutorial it’s a case of parameterizing the table …

  • number of “span” cells across (used to be 100)
  • number of “span” cells down (used to be 20)

… as per the device width dependant …


var xacross=Math.min(100,Math.round(eval('' + screen.width) / 14.40)); //100;
var ydown=Math.round(eval(xacross / 5)); //20;

… teamed with changes to 100 and 20 and “near to” Javascript code hardcodings changed into forms of “xacross” and “ydown” variables above.

And then there is the hardcoding “Score” we wanted to repurpose so as to allow the user control of whether …

  • notifications
  • “say” audio
  • “toast” message box

… are persisted with, via “toggling code” as per …


var snotifications_on=true;
var osay_on=((('' + navigator.platform.toUpperCase()).indexOf('MAC') >= 0) ? true : false);
var etoast_on=(navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i) ? true : false);

function pse(insc, istoast) { // insc is "Score "
var outsc=insc;
if (outsc.indexOf('Score') == 0) {
outsc=outsc.replace('e', '<a title="Toggle toast show status ' + ('' + etoast_on) + '" onclick="etoast_on=!etoast_on; this.title+=String.fromCharCode(32) + etoast_on;" style="cursor:pointer;text-decoration:none;color:' + (istoast ? 'magenta' : 'magenta') + ';">e</a>');
outsc=outsc.replace('o', '<a title="Toggle say try status ' + ('' + osay_on) + '" onclick="osay_on=!osay_on; this.title+=String.fromCharCode(32) + osay_on;" style="cursor:pointer;text-decoration:none;color:' + (istoast ? 'white' : 'purple') + ';">o</a>');
outsc=outsc.replace('S', '<a title="Toggle notifications try status ' + ('' + osay_on) + '" onclick="snotifications_on=!snotifications_on; this.title+=String.fromCharCode(32) + snotifications_on;" style="cursor:pointer;text-decoration:none;color:' + (istoast ? 'white' : 'blue') + ';">S</a>');
}
return outsc;
}

… in all of the recent …


Previous relevant Dots and Boxes Game Primer Tutorial is shown below.

Dots and Boxes Game Primer Tutorial

Dots and Boxes Game Primer Tutorial

Today, do you fancy …

Morphing a clone

… or should that be …

Cloning a morph

… onto yesterday’s SOS Game Primer Tutorial with our new “Dots and Boxes” game?

Yes, that’s it for us today, simply because the “morphed into” is a lot like “the end result”, our new Dots and Boxes Game. After all, both are …

  • online games
  • on a board
  • with span cells
  • containing onclick logic
  • ideally for 2 or more players

And as for the onclick logic Javascript logic? We can’t remember relying on the outerHTML (ie. the entire HTML element expressed as HTML) of an HTML (span) element for the (onclick event) logic basis, as per (the plug in code different to (and the same as) yesterday’s code)


if (document.getElementById('names')) {
if (document.getElementById('names').value == '' && document.getElementById('names').placeholder.indexOf(',') != -1) {
document.getElementById('names').value=document.getElementById('names').placeholder;
//alert(1);
document.getElementById('numsel').value='' + document.getElementById('names').value.split(',').length;
//alert(document.getElementById('numsel').value);
nparrange(document.getElementById('numsel'));
//alert(11);
document.getElementById('smore').innerHTML=notify('Your go ' + anames[curplayer]);
}
}
console.log('1');
if (spano.innerHTML.toLowerCase() == 's' || spano.innerHTML.toLowerCase() == 'o') { return true; }
console.log('2');
var rtis=spano.getBoundingClientRect();
console.log('3');
e = e || window.event;
e.preventDefault();

if (e.touches) {
if (e.touches[0].pageX) {
xx = e.touches[0].pageX;
yy = e.touches[0].pageY;
} else {
xx = e.touches[0].clientX;
yy = e.touches[0].clientY;
}
//console.log('pos3=' + pos3 + ',pos4=' + pos4);
} else if (e.clientX || e.clientY) {
xx = e.clientX;
yy = e.clientY;
} else {
xx = e.pageX;
yy = e.pageY;
}


var topm=eval(yy - rtis.top);
var bottomm=eval(rtis.bottom - yy);
var leftm=eval(xx - rtis.left);
var rightm=eval(rtis.right - xx);


var sbl=eval('' + noc(spano.outerHTML).split('border-').length);
var sbc=eval('' + spano.outerHTML.split('background-color').length);


var thislet=' ';
var locsubscore=0;
var thisi=eval(spano.id.replace('span',''));
if (Math.min(topm, bottomm,leftm,rightm) == leftm || Math.min(topm, bottomm,leftm,rightm) == rightm) { // s
if (Math.min(topm, bottomm,leftm,rightm) == leftm) { // s
thislet='border-left:2px solid ' + bcols[curplayer]; //alert(56);
spano.style.borderLeft=thislet.split(':')[1];
//document.getElementById('myh4').style.fontSize='6px';
//document.getElementById('myh4').innerHTML='thisi=' + thisi + ' border-left and ' + eval(-1 + thisi) + ' is border-right ' + spano.outerHTML.replace(/\>/g,'>').replace(/\</g,'<');
if ((sbl == 4 && noc(spano.outerHTML).split('border-').length >= 4) && sbc == 1) {
//if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//alert('' + sbl + ' 1:' + noc(spano.outerHTML).split('border-').length + ' ' + spano.outerHTML);
//}
spano.style.backgroundColor=bcols[curplayer];
//alert(1);
locsubscore++;
} //else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && sbl == 4 && sbc == 1) {
//alert('1:' + spano.outerHTML.split('border-').length + ' ' + spano.outerHTML);
//}
if (eval(thisi % 100) >= 1) {
sbl=eval('' + noc(document.getElementById('span' + eval(-1 + thisi)).outerHTML).split('border-').length);
sbc=eval('' + document.getElementById('span' + eval(-1 + thisi)).outerHTML.split('background-color').length);
document.getElementById('span' + eval(-1 + thisi)).style.borderRight=thislet.split(':')[1];
if ((sbl == 4 && noc(document.getElementById('span' + eval(-1 + thisi)).outerHTML).split('border-').length >= 4) && sbc == 1) { //if (document.getElementById('span' + eval(-1 + thisi)).outerHTML.split('border-').length == 5 && document.getElementById('span' + eval(-1 + thisi)).outerHTML.split('background-color').length == 1) {
document.getElementById('span' + eval(-1 + thisi)).style.backgroundColor=bcols[curplayer];
locsubscore++;
}
}
} else {
thislet='border-right:2px solid ' + bcols[curplayer]; //alert(56);
spano.style.borderRight=thislet.split(':')[1];
//document.getElementById('myh4').style.fontSize='6px';
//document.getElementById('myh4').innerHTML='thisi=' + thisi + ' border-right and ' + eval(1 + thisi) + ' is border-left ' + spano.outerHTML.replace(/\>/g,'>').replace(/\</g,'<');
if ((sbl == 4 && noc(spano.outerHTML).split('border-').length >= 4) && sbc == 1) {
spano.style.backgroundColor=bcols[curplayer];
//alert(2);
//if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//alert('' + sbl + ' 2:' + noc(spano.outerHTML).split('border-').length + ' ' + spano.outerHTML);
//}
locsubscore++;
} //else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && sbl == 4 && sbc == 1) {
//alert('2:' + spano.outerHTML.split('border-').length + ' ' + spano.outerHTML);
//}
if (eval(thisi % 100) <= 98) {
sbl=eval('' + noc(document.getElementById('span' + eval(1 + thisi)).outerHTML).split('border-').length);
sbc=eval('' + document.getElementById('span' + eval(1 + thisi)).outerHTML.split('background-color').length);
document.getElementById('span' + eval(1 + thisi)).style.borderLeft=thislet.split(':')[1];
if ((sbl == 4 && noc(document.getElementById('span' + eval(1 + thisi)).outerHTML).split('border-').length >= 4) && sbc == 1) { //if (document.getElementById('span' + eval(1 + thisi)).outerHTML.split('border-').length == 5 && document.getElementById('span' + eval(1 + thisi)).outerHTML.split('background-color').length == 1) {
document.getElementById('span' + eval(1 + thisi)).style.backgroundColor=bcols[curplayer];
locsubscore++;
}
}
}
thislet='&nbsp;'; //'S';
spano.innerHTML=thislet;
spano.style.color='rgb(128,0,128)'; //'#000000';
} else {
if (Math.min(topm, bottomm,leftm,rightm) == bottomm) { // s
thislet='border-bottom:2px solid ' + bcols[curplayer]; //alert(56);
spano.style.borderBottom=thislet.split(':')[1];
//document.getElementById('myh4').style.fontSize='6px';
//document.getElementById('myh4').innerHTML='thisi=' + thisi + ' border-bottom and ' + eval(100 + thisi) + ' is border-top ' + spano.outerHTML.replace(/\>/g,'>').replace(/\</g,'<');
if ((sbl == 4 && spano.outerHTML.split('border-').length >= 4) && sbc == 1) {
spano.style.backgroundColor=bcols[curplayer];
//alert(3);
//if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//alert('' + sbl + ' 3:' + spano.outerHTML.split('border-').length + ' ' + spano.outerHTML);
//}
locsubscore++;
} //else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && sbl == 4 && sbc == 1) {
//alert('3:' + spano.outerHTML.split('border-').length + ' ' + spano.outerHTML);
//}
if (eval(thisi / 100) <= 18) {
sbl=eval('' + noc(document.getElementById('span' + eval(100 + thisi)).outerHTML).split('border-').length);
sbc=eval('' + document.getElementById('span' + eval(100 + thisi)).outerHTML.split('background-color').length);
document.getElementById('span' + eval(100 + thisi)).style.borderTop=thislet.split(':')[1];
if ((sbl == 4 && noc(document.getElementById('span' + eval(100 + thisi)).outerHTML).split('border-').length >= 4) && sbc == 1) { //if (document.getElementById('span' + eval(100 + thisi)).outerHTML.split('border-').length == 5 && document.getElementById('span' + eval(100 + thisi)).outerHTML.split('background-color').length == 1) {
document.getElementById('span' + eval(100 + thisi)).style.backgroundColor=bcols[curplayer];
locsubscore++;
}
}
} else {
thislet='border-top:2px solid ' + bcols[curplayer]; //alert(56);
spano.style.borderTop=thislet.split(':')[1];
//document.getElementById('myh4').style.fontSize='6px';
//document.getElementById('myh4').innerHTML='thisi=' + thisi + ' border-top and ' + eval(-100 + thisi) + ' is border-bottom ' + spano.outerHTML.replace(/\>/g,'>').replace(/\</g,'<');
if ((sbl == 4 && noc(spano.outerHTML).split('border-').length >= 4) && sbc == 1) {
spano.style.backgroundColor=bcols[curplayer];
//alert(4);
//if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//alert('' + sbl + ' 4:' + spano.outerHTML.split('border-').length + ' ' + spano.outerHTML);
//}
locsubscore++;
} //else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && sbl == 4 && sbc == 1) {
//alert('4:' + spano.outerHTML.split('border-').length + ' ' + spano.outerHTML);
//}
if (eval(thisi / 100) >= 1) {
sbl=eval('' + noc(document.getElementById('span' + eval(-100 + thisi)).outerHTML).split('border-').length);
sbc=eval('' + document.getElementById('span' + eval(-100 + thisi)).outerHTML.split('background-color').length);
document.getElementById('span' + eval(-100 + thisi)).style.borderBottom=thislet.split(':')[1];
if ((sbl == 4 && noc(document.getElementById('span' + eval(-100 + thisi)).outerHTML).split('border-').length >= 4) && sbc == 1) { //if (document.getElementById('span' + eval(-100 + thisi)).outerHTML.split('border-').length == 5 && document.getElementById('span' + eval(-100 + thisi)).outerHTML.split('background-color').length == 1) {
document.getElementById('span' + eval(-100 + thisi)).style.backgroundColor=bcols[curplayer];
locsubscore++;
}
}
}
thislet='&nbsp;'; //'O';
spano.innerHTML=thislet;
spano.style.color='#0000ff';
}

if (locsubscore > 0) {
//alert('locsubscore=' + locsubscore + ' yy=' + yy + ' rtis.top=' + rtis.top + ' rtis.y=' + rtis.y + ' rtis.bottom=' + rtis.bottom);
changeu=false;
subscore=locsubscore;
return cscore('pointer', locsubscore);
} else {
subscore=0;
changeu=true;
//alert('change');
return cscore('pointer', 0);
}

… in the “how we got there” dots_and_boxes_game.html Dots and Boxes Game you can also try below …


Previous relevant SOS Game Primer Tutorial is shown below.

SOS Game Primer Tutorial

SOS Game Primer Tutorial

Even though it took too long to get to yesterday’s Word Find Game Viewport Tutorial‘s Word Find Game’s level of satisfaction, for us, it was always going to be worth it, because when you overengineer it can mean cloning off that into another useful web application is a “paring down” exercise, more than anything, and this is infinitely easier than “a reinvention of the wheel” scenario, especially where it comes to “cross platform” game usage “user experience” issues.

The fun bit of such an approach, in thinking about what we end up with today is the thought that a …

  • Word Find Game … could be cloned or morphed into a …
  • SOS Game

… we remember from our days at high school, in less than a day. The memory of the SOS Game did not extend to the detail, and so we thank How to Play – SOS for reminders about the status of diagonality, while up versus down and forwards versus backwards concerns were a bit “per se” regarding “SOS”!

It was the confluence of one “onclick” type event to cover, regarding span elements set out in a grid initialized to a non-breaking space ( ie. &nbsp; ) …

  • fill in contents as “S”
  • fill in contents as “O”

… that set us to determining for the span “cell” click, was it positioned …

  • in the top half means “S” … or …
  • in the bottom half means “O”

? This had us converging on changes to the “clicks” mode onclick event Javascript logic …


function didclick(e, spano) {
if (document.getElementById('names')) {
if (document.getElementById('names').value == '' && document.getElementById('names').placeholder.indexOf(',') != -1) {
document.getElementById('names').value=document.getElementById('names').placeholder;
//alert(1);
document.getElementById('numsel').value='' + document.getElementById('names').value.split(',').length;
//alert(document.getElementById('numsel').value);
nparrange(document.getElementById('numsel'));
//alert(11);
document.getElementById('smore').innerHTML=notify('Your go ' + anames[curplayer]);
}
}
console.log('1');
if (spano.innerHTML.toLowerCase() == 's' || spano.innerHTML.toLowerCase() == 'o') { return true; }
console.log('2');
var rtis=spano.getBoundingClientRect();
console.log('3');
e = e || window.event;
e.preventDefault();

if (e.touches) {
if (e.touches[0].pageX) {
xx = e.touches[0].pageX;
yy = e.touches[0].pageY;
} else {
xx = e.touches[0].clientX;
yy = e.touches[0].clientY;
}
//console.log('pos3=' + pos3 + ',pos4=' + pos4);
} else if (e.clientX || e.clientY) {
xx = e.clientX;
yy = e.clientY;
} else {
xx = e.pageX;
yy = e.pageY;
}



var thislet=' ';
var locsubscore=0;
var thisi=eval(spano.id.replace('span',''));
if (eval(yy - rtis.top) <= eval(rtis.bottom - yy)) { // s
thislet='S';
spano.innerHTML=thislet;
spano.style.color='rgb(128,0,128)'; //'#000000';
} else {
thislet='O';
spano.innerHTML=thislet;
spano.style.color='#0000ff';
}
sbs=[];
if (eval(thisi % 100) >= 2) { // forwards we are at end
if ((sb(document.getElementById('span' + eval(-2 + thisi))).innerHTML + sb(document.getElementById('span' + eval(-1 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
sbs=[];
if (eval(thisi % 100) >= 1 && eval(thisi % 100) <= 98) { // forwards we are in the middle
if ((sb(document.getElementById('span' + eval(-1 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(1 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
sbs=[];
if (eval(thisi % 100) <= 97) { // forwards we are at start
if ((sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(1 + thisi))).innerHTML + sb(document.getElementById('span' + eval(2 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}


if (updownallowed) {
sbs=[];
if (eval(thisi / 100) >= 2) { // down we are at end
if ((sb(document.getElementById('span' + eval(-200 + thisi))).innerHTML + sb(document.getElementById('span' + eval(-100 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
sbs=[];
if (eval(thisi / 100) >= 1 && eval(thisi / 100) <= 18) { // down we are in the middle
if ((sb(document.getElementById('span' + eval(-100 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(100 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
sbs=[];
if (eval(thisi / 100) <= 17) { // down we are at start
if ((sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(100 + thisi))).innerHTML + sb(document.getElementById('span' + eval(200 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
}

if (diagonalsallowed) {
sbs=[];
if (eval(thisi / 100) >= 2 && eval(thisi % 100) >= 2) { // diagonally we are at end
if ((sb(document.getElementById('span' + eval(-202 + thisi))).innerHTML + sb(document.getElementById('span' + eval(-101 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
sbs=[];
if ((sb(document.getElementById('span' + eval(-198 + thisi))).innerHTML + sb(document.getElementById('span' + eval(-99 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
sbs=[];
if (eval(thisi / 100) >= 1 && eval(thisi / 100) <= 18 && eval(thisi % 100) >= 1 && eval(thisi % 100) <= 98) { // diagonally we are in the middle
if ((sb(document.getElementById('span' + eval(-101 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(101 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
sbs=[];
if ((sb(document.getElementById('span' + eval(-99 + thisi))).innerHTML + sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(99 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
sbs=[];
if (eval(thisi / 100) <= 17 && eval(thisi % 100) <= 97) { // diagonally we are at start
if ((sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(101 + thisi))).innerHTML + sb(document.getElementById('span' + eval(202 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
sbs=[];
if ((sb(document.getElementById('span' + eval(thisi))).innerHTML + sb(document.getElementById('span' + eval(99 + thisi))).innerHTML + sb(document.getElementById('span' + eval(198 + thisi))).innerHTML) == 'SOS') {
sbord();
locsubscore++;
}
}
}
sbs=[];

if (locsubscore > 0) {
//alert('locsubscore=' + locsubscore + ' yy=' + yy + ' rtis.top=' + rtis.top + ' rtis.y=' + rtis.y + ' rtis.bottom=' + rtis.bottom);
changeu=false;
subscore=locsubscore;
return cscore('pointer', locsubscore);
} else {
subscore=0;
changeu=true;
//alert('change');
return cscore('pointer', 0);
}



var newi=eval(spano.id.replace('span',''));
var documentgetSelectiontoString='', revsis='';
var wlen=0, ijh=0;
if (setsoftwo.length == 0) {
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
} else {
console.log('Newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
if (Math.floor(newi / 100) == Math.floor(setsoftwo[0] / 100)) {
wlen=eval(1 + Math.abs(eval(setsoftwo[0] - newi)));
if (wlen == 3) { // >= 4) {
for (ijh=Math.min(setsoftwo[0], newi); ijh<=Math.max(setsoftwo[0], newi); ijh++) {
documentgetSelectiontoString+=document.getElementById('span' + ijh).innerHTML;
revsis=document.getElementById('span' + ijh).innerHTML + revsis;
document.getElementById('span' + ijh).style.backgroundColor='orange';
document.getElementById('span' + ijh).title=document.getElementById('span' + ijh).innerHTML;
document.getElementById('span' + ijh).style.cursor='progress';
}
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
findingnemo='';
if (!backwardsallowed) {
setTimeout(retry, 2000);
document.getElementById('nameif').title='';
} else {
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
}
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
setsoftwo=[];
} else {
document.getElementById('span' + ('' + setsoftwo[0]).replace('span','')).style.backgroundColor='#f0f0f0';
setsoftwo=[];
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
console.log('newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
notify('Sorry, but too short.');
}

} else if (eval(newi % 100) == eval(setsoftwo[0] % 100)) {
if (updownallowed) {
console.log('up down');
wlen=eval(1 + Math.abs(eval(Math.floor(setsoftwo[0] / 100) - Math.floor(newi / 100))));
console.log('newi=' + newi + ' and wlen=' + wlen + ' via setsoftwo[0]=' + setsoftwo[0]);
if (wlen == 3) { // >= 4) {
for (ijh=Math.min(setsoftwo[0], newi); ijh<=Math.max(setsoftwo[0], newi); ijh+=100) {
documentgetSelectiontoString+=document.getElementById('span' + ijh).innerHTML;
revsis=document.getElementById('span' + ijh).innerHTML + revsis;
document.getElementById('span' + ijh).style.backgroundColor='orange';
document.getElementById('span' + ijh).title=document.getElementById('span' + ijh).innerHTML;
document.getElementById('span' + ijh).style.cursor='progress';
}
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
findingnemo='';
if (!backwardsallowed) {
setTimeout(retry, 2000);
document.getElementById('nameif').title='';
} else {
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
}
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
setsoftwo=[];
} else {
document.getElementById('span' + ('' + setsoftwo[0]).replace('span','')).style.backgroundColor='#f0f0f0';
setsoftwo=[];
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
console.log('newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
notify('Sorry, need four or more letters.');
}

} else {
document.getElementById('span' + ('' + setsoftwo[0]).replace('span','')).style.backgroundColor='#f0f0f0';
setsoftwo=[];
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
console.log('newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
notify('Sorry, no up or downs allowed.');
}

} else if (Math.abs(Math.floor(eval(newi / 100)) - Math.floor(eval(setsoftwo[0] / 100))) == Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100))) {
if (diagonalsallowed) {
console.log('diagonal');

wlen=eval(1 + Math.abs(eval(Math.floor(setsoftwo[0] / 100) - Math.floor(newi / 100))));
console.log('newi=' + newi + ' and wlen=' + wlen + ' via setsoftwo[0]=' + setsoftwo[0]);
if (wlen == 3) { // >= 4) {
for (ijh=Math.min(setsoftwo[0], newi); ijh<=Math.max(setsoftwo[0], newi); ijh+=eval(eval(Math.max(setsoftwo[0], newi) - Math.min(setsoftwo[0], newi)) / eval(-1 + wlen))) {
documentgetSelectiontoString+=document.getElementById('span' + ijh).innerHTML;
revsis=document.getElementById('span' + ijh).innerHTML + revsis;
document.getElementById('span' + ijh).style.backgroundColor='orange';
document.getElementById('span' + ijh).title=document.getElementById('span' + ijh).innerHTML;
document.getElementById('span' + ijh).style.cursor='progress';
}
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
findingnemo='';
if (!backwardsallowed) {
setTimeout(retry, 2000);
document.getElementById('nameif').title='';
} else {
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
}
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
setsoftwo=[];
} else {
document.getElementById('span' + ('' + setsoftwo[0]).replace('span','')).style.backgroundColor='#f0f0f0';
setsoftwo=[];
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
console.log('newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
notify('Too short, sorry.');
}

} else {
document.getElementById('span' + ('' + setsoftwo[0]).replace('span','')).style.backgroundColor='#f0f0f0';
setsoftwo=[];
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
console.log('newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
notify('Sorry, no diagonals allowed.');
}

} else {
document.getElementById('span' + ('' + setsoftwo[0]).replace('span','')).style.backgroundColor='#f0f0f0';
setsoftwo=[];
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
console.log('newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
}
}
//alert('id=' + spano.id + ' ' + spano.innerHTML);
}

… which on non-mobile platforms compliments the CSS styling …

<style>

span.wunderlay:hover {
background-image: linear-gradient(to bottom, rgba(128,0,128,0.5) , rgba(0,0,255,0.5));
}

</style>

… quite nicely, in a colour coded sense, in the “how we got there” sos_game.html SOS Game you can also try below …


Previous relevant Word Find Game Aesthetics Tutorial is shown below.

Word Find Game Aesthetics Tutorial

Word Find Game Aesthetics Tutorial

CSS styling keeps getting better for webpages, with extended functionality, as proven when CSS3 came to being. Two styling features we find quite impactive are …

  • CSS animation … and …
  • CSS linear gradients

… we use, respectively, regarding …

  • “selection” textarea and “click” div of span elements … helping create a colour coded border “glow” 3D effect …

    <style>

    /* Thanks to https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_glowing_text */

    @-webkit-keyframes glow {
    from {
    box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #e60073, 0 0 9px #e60073, 0 0 11px #e60073, 0 0 13px #e60073, 0 0 15px #e60073;
    }

    to {
    box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #ff4da6, 0 0 10px #ff4da6, 0 0 12px #ff4da6, 0 0 14px #ff4da6, 0 0 16px #ff4da6;
    }
    }

    @-webkit-keyframes wglow {
    from {
    box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #7300e6, 0 0 9px #7300e6, 0 0 11px #7300e6, 0 0 13px #7300e6, 0 0 15px #7300e6;
    }

    to {
    box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #a64dff, 0 0 10px #a64dff, 0 0 12px #a64dff, 0 0 14px #a64dff, 0 0 16px #a64dff;
    }
    }


    textarea {
    font-family: Courier New;
    font-size: 20px;
    opacity: 0.9;
    z-index: 9;
    padding: 0 0 0 0;
    margin: 0 0 0 0;
    text-shadow: -1px 1px 1px #952dff;
    -webkit-animation: glow 1s linear infinite alternate;
    -moz-animation: glow 1s linear infinite alternate;
    animation: glow 1s linear infinite alternate;

    }


    #wunderlay {
    font-family: Courier New;
    font-size: 20px;
    opacity: 0.3;
    z-index: 11;
    padding: 0 0 0 0;
    margin: 0 0 0 0;
    -webkit-animation: glow 1s linear infinite alternate;
    -moz-animation: glow 1s linear infinite alternate;
    animation: glow 1s linear infinite alternate;

    }
    </style>

    … that is dynamically changed to “wglow” (and font-family Courier) should the user select “click” mode of interactive entry
  • background-image CSS property linear gradient background to dropdown and textbox element effect …

    <style>
    /* Thanks to https://medium.com/thirty-9/3-tips-for-using-subtle-css-gradients-f5691e453602 */

    body {
    background-image: linear-gradient(to right bottom, #ffffff, #fcfafc, #f9f6f8, #f8f1f3, #f6ecec);
    }


    #names {
    background-image: linear-gradient(to right bottom, #eeeeee, #ebe9eb, #e8e5e7, #e7e0e2, #e5dbdb);
    }


    select {
    background-image: linear-gradient(to right bottom, white, yellow, pink, silver, lightgray);
    }
    </style>

And so, improving on yesterday’s Word Find Game Mobile Tutorial we have in our changed word_find_game.html Word Find Game you can also try, yes, yet again, below.


Previous relevant Word Find Game Mobile Tutorial is shown below.

Word Find Game Mobile Tutorial

Word Find Game Mobile Tutorial

Yesterday’s Word Find Game Personalization Tutorial, and the Word Find Game from versions before all had an unwieldy relationship with mobile platforms. The …

  • selection, via Selection API, using HTML textarea, suits non-mobile well … but we think today’s newly coded for …
  • click, via HTML span element onclick logics, work better on mobile platforms

… and so we’ve coded for a new dropdown to offer both modus operandi as options, with new “click” modus operandi Javascript …


function didclick(spano) {
var newi=eval(spano.id.replace('span',''));
var documentgetSelectiontoString='', revsis='';
var wlen=0, ijh=0;
if (setsoftwo.length == 0) {
setsoftwo.push(newi);
document.getElementById('span' + newi).style.backgroundColor='yellow';
} else {
console.log('Newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
if (Math.floor(newi / 100) == Math.floor(setsoftwo[0] / 100)) {
wlen=eval(1 + Math.abs(eval(setsoftwo[0] - newi)));
if (wlen >= 4) {
for (ijh=Math.min(setsoftwo[0], newi); ijh<=Math.max(setsoftwo[0], newi); ijh++) {
documentgetSelectiontoString+=document.getElementById('span' + ijh).innerHTML;
revsis=document.getElementById('span' + ijh).innerHTML + revsis;
document.getElementById('span' + ijh).style.backgroundColor='orange';
document.getElementById('span' + ijh).title=document.getElementById('span' + ijh).innerHTML;
document.getElementById('span' + ijh).style.cursor='progress';
}
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
findingnemo='';
if (!backwardsallowed) {
setTimeout(retry, 2000);
document.getElementById('nameif').title='';
} else {
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
}
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
setsoftwo=[];
}
} else if (eval(newi % 100) == eval(setsoftwo[0] % 100)) {
if (updownallowed) {
console.log('up down');
wlen=eval(1 + Math.abs(eval(Math.floor(setsoftwo[0] / 100) - Math.floor(newi / 100))));
console.log('newi=' + newi + ' and wlen=' + wlen + ' via setsoftwo[0]=' + setsoftwo[0]);
if (wlen >= 4) {
for (ijh=Math.min(setsoftwo[0], newi); ijh<=Math.max(setsoftwo[0], newi); ijh+=100) {
documentgetSelectiontoString+=document.getElementById('span' + ijh).innerHTML;
revsis=document.getElementById('span' + ijh).innerHTML + revsis;
document.getElementById('span' + ijh).style.backgroundColor='orange';
document.getElementById('span' + ijh).title=document.getElementById('span' + ijh).innerHTML;
document.getElementById('span' + ijh).style.cursor='progress';
}
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
findingnemo='';
if (!backwardsallowed) {
setTimeout(retry, 2000);
document.getElementById('nameif').title='';
} else {
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
}
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
setsoftwo=[];
}
}
} else if (Math.abs(Math.floor(eval(newi / 100)) - Math.floor(eval(setsoftwo[0] / 100))) == Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100))) {
if (diagonalsallowed) {
console.log('diagonal');

wlen=eval(1 + Math.abs(eval(Math.floor(setsoftwo[0] / 100) - Math.floor(newi / 100))));
console.log('newi=' + newi + ' and wlen=' + wlen + ' via setsoftwo[0]=' + setsoftwo[0]);
if (wlen >= 4) {
for (ijh=Math.min(setsoftwo[0], newi); ijh<=Math.max(setsoftwo[0], newi); ijh+=eval(eval(Math.max(setsoftwo[0], newi) - Math.min(setsoftwo[0], newi)) / eval(-1 + wlen))) {
documentgetSelectiontoString+=document.getElementById('span' + ijh).innerHTML;
revsis=document.getElementById('span' + ijh).innerHTML + revsis;
document.getElementById('span' + ijh).style.backgroundColor='orange';
document.getElementById('span' + ijh).title=document.getElementById('span' + ijh).innerHTML;
document.getElementById('span' + ijh).style.cursor='progress';
}
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
findingnemo='';
if (!backwardsallowed) {
setTimeout(retry, 2000);
document.getElementById('nameif').title='';
} else {
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
}
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
setsoftwo=[];
}
}
} else {
console.log('newi=' + newi + ' and down=' + Math.abs(eval(newi % 100) - eval(setsoftwo[0] % 100)) + ' and across=' + Math.abs(Math.floor(newi / 100) - Math.floor(setsoftwo[0] / 100)) + ' via setsoftwo[0]=' + setsoftwo[0]);
}
}
//alert('id=' + spano.id + ' ' + spano.innerHTML);
}

… in our changed word_find_game.html Word Find Game you can also try, yes, again, below.


Previous relevant Word Find Game Personalization Tutorial is shown below.

Word Find Game Underlay Tutorial

Word Find Game Personalization Tutorial

Yesterday’s Word Find Game Modes of Use Tutorial gave us the means by which we could have multiple players in our “Finding the Word” game, as a number. But many users prefer “names” to “numbers”. And so …

  • we start asking for an optional (comma separated) user name list … that if used …
  • starts looking for Notifications API functionality to keep the players informed about proceedings … and …
  • if underlying Navigator API navigator.platform points at an underlying macOS operating system, also offer the user the chance to turn notification wording to audio commentary, as well

… as per Javascript …


function notify(what) {
if (what.trim() != '' && anames[0].replace('Player 1','').trim() != '') {
if (what != lastwhat) {
lastwhat=what;
setTimeout(lwn, 8000);
document.getElementById('notif').src='./notifications_ideas.php?scheduledblurb=' + encodeURIComponent(what);
if (trysay) { //alert('HTTP://localhost:8888/macos_say_record.php?andsoonclose=y&docronwork=say%20' + encodeURIComponent(what));
window.open('HTTP://localhost:8888/macos_say_record.php?andsoonclose=y&docronwork=say%20' + encodeURIComponent(what), 'sayif', 'top=50,left=50,width=500,height=500');
}
}
}
return what;
}

… showing two different uses of two different invisible HTML iframe elements …


<iframe id=notif style='display:none;' src=></iframe>
<iframe id=sayif name=sayif style='display:none;' src=></iframe>

… in our changed word_find_game.html Word Find Game you can also try, yet again, below.


Previous relevant Word Find Game Modes of Use Tutorial is shown below.

Word Find Game Underlay Tutorial

Word Find Game Modes of Use Tutorial

Online games often feature …

  • degree of difficulty
  • number of player(s)

… modes of use that the user(s) can control. And so, with this in mind, to improve on yesterday’s Word Find Game Underlay Tutorial we’ve set out providing ways the users can control these two concepts via two new dropdowns …


<h1>Word Find Game <select onchange="restart(this);"><option value="hard">Hard</option><option value="easy">Easy</option><option value="easier">Easier</option><option value="easiest">Easiest</option></select> <span id=curbit>for</span> <select id=numsel onchange='nparrange(this);'><option value=1>1 player</option><option value=2>2 players</option><option value=3>3 players</option><option value=4>4 players</option><option value=5>5 players</option></select></h1>

… along with a span element showing the current player number all within that topmost h1 element, and helped out by two new dropdown (ie. select element) onchange event Javascript logics …


var numplayers=1;
var curplayer=0;
var ascores=[0], agoes=[0];
var backwardsallowed=true;
var updownallowed=true;
var diagonalsallowed=true;

var zdebye='';
var zzdebye='';
var lastzdebye='';
var goutstris='';
var delayis=0;
var sofar=';';
var score=0, goes=0, subscore=0;

function nparrange(sio) {
if (eval('' + sio.value) > eval('' + ascores.length)) {
while (eval('' + sio.value) > eval('' + ascores.length)) {
ascores.push(0);
agoes.push(0);
}
numplayers=eval('' + ascores.length);
document.getElementById('curbit').innerHTML='for <font color=green>' + eval(1 + eval('' + curplayer)) + '</font> of';
if (eval('' + ascores.length) > 1) {
var cscores='';
var cgoes='';
var betw='';
//if (eval(0 + eval('' + curplayer)) == 0) { betw='<font color=red>'; }
if (eval(1 + eval('' + curplayer)) >= eval('' + ascores.length)) { betw='<font color=red>'; }
for (var inp=0; inp<eval('' + ascores.length); inp++) {
if (eval('' + curplayer) == inp) {
cscores+=betw + '<font color=green>' + ascores[inp] + '</font>';
cgoes+=betw + '<font color=green>' + agoes[inp] + '</font>';
betw=':<font color=red>';
} else {
cscores+=betw + ascores[inp] + betw.replace(':','').replace('<font color=red>', '</font>').replace('<font color=green>', '</font>');
cgoes+=betw + agoes[inp] + betw.replace(':','').replace('<font color=red>', '</font>').replace('<font color=green>', '</font>');
//betw=':';
betw=(':' + betw.replace(':','')).replace('<font color=red>','').replace('<font color=green>','<font color=red>');
}
console.log('numplayers=' + numplayers + ' at ' + inp + ' vs curplayer=' + curplayer + ' ' + cscores + '/' + cgoes);
}
document.getElementById('score').innerHTML='' + cscores + '/' + cgoes;
//curplayer++;
//if (curplayer >= eval('' + ascores.length)) { curplayer=0; }
//scores=ascores[curplayer];
//goes=agoes[curplayer];
}
}
}

function restart(sio) {
var myblurb=document.getElementById('blurb').innerHTML; // Forwards, backwards, up, down, diagonal 4 letters or more highlight below
var setn=[8,1,1,3,11,1,2,1,8,0,0,3,1,5,7,1,0,5,3,5,3,1,1,0,1,0];
if (sio.value == 'hard') { location.href=document.URL; }
if (sio.value != 'hard' && eval('' + letters.length) == 26) {
myblurb=myblurb.replace(' letters ', ' more common set of letters ');
// A-9, B-2, C-2, D-4, E-12, F-2, G-3, H-2, I-9, J-1, K-1, L-4, M-2, N-6, O-8, P-2, Q-1, R-6, S-4, T-6, U-4, V-2, W-2, X-1, Y-2, Z-1
var kbye=eval('' + letters.length);
for (ibye=0; ibye<kbye; ibye++) {
for (jbye=1; jbye<=setn[ibye]; jbye++) {
letters.push(letters[ibye]);
}
}
}
if (sio.value == 'easiest') {
myblurb=myblurb.replace(', diagonal', '');
myblurb=myblurb.replace(', up, down', '');
myblurb=myblurb.replace(', backwards', '');
backwardsallowed=false;
updownallowed=false;
diagonalsallowed=false;
}
if (sio.value == 'easier') {
myblurb=myblurb.replace(', diagonal', '');
myblurb=myblurb.replace(', up, down', '');
myblurb=myblurb.replace('Forwards 4', 'Forwards, backwards 4');
backwardsallowed=true;
updownallowed=false;
diagonalsallowed=false;
}
if (sio.value == 'easy') {
myblurb=myblurb.replace('Forwards 4', 'Forwards, backwards, up, down, diagonal 4');
myblurb=myblurb.replace('Forwards, backwards 4', 'Forwards, backwards, up, down, diagonal 4');
backwardsallowed=true;
updownallowed=true;
diagonalsallowed=true;
}
document.getElementById('blurb').innerHTML=myblurb;
ebye='';
ibye=0;
jbye=0;
debye='';
aletter=' ';
for (ibye=0; ibye<20; ibye++) {
for (jbye=0; jbye<100; jbye++) {
aletter=letters[Math.floor(Math.random() * letters.length)];
ebye+=aletter;
debye+=aletter;
}
ebye+=String.fromCharCode(10);
debye+='<br>';
}
zdebye='';
zzdebye='';
lastzdebye='';
goutstris='';
delayis=0;
sofar=';';
document.getElementById('mytao').value=ebye;
var divs=document.getElementsByTagName('div');
for (kdivs=0; kdivs<divs.length; kdivs++) {
divs[kdivs].innerHTML='';
}
document.getElementById('underlay').innerHTML=debye;

}

… to help encourage some optional collaboration aspects to our changed word_find_game.html Word Find Game you can also try, again, below.


Previous relevant Word Find Game Underlay Tutorial is shown below.

Word Find Game Underlay Tutorial

Word Find Game Underlay Tutorial

If you are a regular reader at this blog, you will know we discuss the CSS styling idea of …

… but there is essentially only the difference in the control of “z-index” (and maybe “opacity”) property different about the concepts, and to deploy to improve on for the start we made with yesterday’s Word Find Game Primer Tutorial.

“Underlay” usefulness, to us, goes like this …

  • what you “underlay” … for us within the new CSS styling …

    <style>
    textarea {
    font-family: Courier New;
    font-size: 20px;
    opacity: 0.9;
    z-index: 9;
    padding: 0 0 0 0;
    margin: 0 0 0 0;

    }

    #underlay {
    font-family: Courier New;
    font-size: 20px;
    opacity: 0.3;
    z-index: 1;
    padding: 0 0 0 0;
    margin: 0 0 0 0;
    }

    div.underlay {
    font-family: Courier New;
    font-size: 20px;
    opacity: 0.3;
    z-index: 2;
    padding: 0 0 0 0;
    margin: 0 0 0 0;
    }

    </style>

    … regimen …
  • has nothing to do with interactive entry, which should be more in your “overlay” thinking, else the user is stumped … but …
  • can help with dynamically enhanced markup jobs that value add to the aesthetics of the webpage

… specifically showing the user “where they’ve been” amongst the “sea of letters” of our changed word_find_game.html Word Find Game you can also try below.


Previous relevant Word Find Game Primer Tutorial is shown below.

Word Find Game Primer Tutorial

Word Find Game Primer Tutorial

Today’s “Word Find Game” gets its inspirations from two sources …

Today we just do the “proof of concept” first draft word_find_game.html, because the Selection API highlighting really suits …

  • horizontal forwards
  • horizontal backwards

… word finding in the game, but we also want to allow for …

  • vertical down
  • vertical up
  • diagonal right down
  • diagonal right up
  • diagonal left down
  • diagonal left up

… which can be handled, but in a pretty kludgy way …


function retry() {
if (('' + document.getElementById('nameif').title).trim() != '') {
document.getElementById('nameif').src=document.getElementById('nameif').title;
document.getElementById('nameif').title='';
} else {
document.getElementById('mytao').style.cursor=cscore('pointer', subscore);
}
}


function cscore(cursortype, ssc) {
if (ssc != 0) { goes++; }
if (ssc > 0) { score+=ssc; }
document.getElementById('score').innerHTML='' + score + '/' + goes;
subscore=0;
return cursortype;
}


function checkname(iois, iserror) {
var ifnd=-1, newname='';
var revsisc='', jrev=0;
console.log('checkname1');
if (iserror) {
if (iois.src.indexOf('second=') == -1 && iois.src.indexOf('iswordthere=') != -1) {
if (('' + iois.title).trim() != '') {
//document.getElementById('mytao').style.cursor='pointer';
document.body.title='';
iois.src=iois.title;
iois.title='';
} else {
//alert(1);
for (jrev=eval(-1 + eval('' + decodeURIComponent(iois.src.split('iswordthere=')[1].split('&')[0].split('#')[0]).length)); jrev>=0; jrev--) {
revsisc+=decodeURIComponent(iois.src.split('iswordthere=')[1].split('&')[0].split('#')[0]).substring(jrev, eval(1 + jrev));
}
//alert('Newname=' + revsisc);
document.body.title='';
iois.title='';
iois.src=iois.src.split('iswordthere=')[0] + 'second=y&iswordthere=' + encodeURIComponent(revsisc);
}
} else {
document.getElementById('mytao').style.cursor=cscore('pointer', subscore);
}
} else {
if (iois != null) {
ifnd=iois.src.indexOf('iswordthere=');
console.log('checkname2 ' + ifnd);
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null && ifnd != -1) {
console.log('checkname3 ' + ifnd);
if (aconto.document) { aconto = aconto.document; }
if (aconto.body != null) {
console.log('checkname4 ' + ifnd);
if (aconto.body.innerHTML.indexOf('</p>') != -1 && aconto.body.innerHTML.indexOf('></p>') == -1) {
document.body.title='';
iois.title='';
document.getElementById('mytao').style.cursor=cscore('pointer', Math.abs(subscore));
console.log('Found name ' + aconto.body.innerHTML.split('</p>')[0].split('>')[eval(-1 + aconto.body.innerHTML.indexOf('</p>')[0].split('>').length)]);
} else if (aconto.body.innerHTML.indexOf('<') == -1 && aconto.body.innerHTML.trim() != '') {
document.body.title='';
iois.title='';
document.getElementById('mytao').style.cursor=cscore('pointer', Math.abs(subscore));
console.log('Found name ' + aconto.body.innerHTML);
} else if (iois.src.indexOf('second=') == -1 && iois.src.indexOf('iswordthere=') != -1) {
if (('' + iois.title).trim() != '') {
//document.getElementById('mytao').style.cursor='pointer';
document.body.title='';
iois.src=iois.title;
iois.title='';
} else {
//alert(1);
for (jrev=eval(-1 + eval('' + decodeURIComponent(iois.src.split('iswordthere=')[1].split('&')[0].split('#')[0]).length)); jrev>=0; jrev--) {
revsisc+=decodeURIComponent(iois.src.split('iswordthere=')[1].split('&')[0].split('#')[0]).substring(jrev, eval(1 + jrev));
}
//alert('Newname=' + revsisc);
document.body.title='';
iois.title='';
iois.src=iois.src.split('iswordthere=')[0] + 'second=y&iswordthere=' + encodeURIComponent(revsisc);
}
} else {
document.getElementById('mytao').style.cursor=cscore('pointer', subscore);
}
} else {
console.log('checkname5 ' + ifnd);
//alert('WhY?');
document.getElementById('mytao').style.cursor=cscore('pointer', subscore);
}
} else if (ifnd != -1) {
console.log('checkname6 ' + ifnd);
ifnd=ifnd;
if (iois.src.indexOf('second=') == -1 && iois.src.indexOf('iswordthere=') != -1) {
//alert(11);
for (jrev=eval(-1 + eval('' + decodeURIComponent(iois.src.split('iswordthere=')[1].split('&')[0].split('#')[0]).length)); jrev>=0; jrev--) {
revsisc+=decodeURIComponent(iois.src.split('iswordthere=')[1].split('&')[0].split('#')[0]).substring(jrev, eval(1 + jrev));
}
//alert('newname=' + revsisc);
iois.src=iois.src.split('iswordthere=')[0] + 'second=y&iswordthere=' + encodeURIComponent(revsisc);
} else {
document.getElementById('mytao').style.cursor=cscore('pointer', subscore);
}
}
}
}
}


function getmltrans(instris) {
goutstris='';
outstris=instris;
var ebay=ebye, jb=0, kb=2;
while (outstris.indexOf(String.fromCharCode(10)) != -1) {
outstris=outstris.replace(/\ /g,'').replace(String.fromCharCode(10),'');
}
while (ebay.indexOf(String.fromCharCode(10)) != -1) {
ebay=ebay.replace(/\ /g,'').replace(String.fromCharCode(10),'');
}
var linesare=instris.split(String.fromCharCode(10));
var xlinesare=ebye.split(String.fromCharCode(10));
if (eval('' + linesare.length) == 1) { return outstris; }
if (eval('' + linesare.length) > 3) {
var onepos=ebay.indexOf(outstris);
var startpos=eval(onepos % 100);
var endpos=eval(eval(onepos + eval('' + outstris.length)) % 100);
var izero=Math.floor(onepos / 100);
if (startpos > endpos) {
if (eval(startpos - eval(-2 + eval('' + linesare.length))) == endpos) {
outstris=xlinesare[izero].substring(startpos, eval(1 + startpos));
//alert('first character is ' + outstris + ' is startpos=' + startpos + ' in xlinesare[' + izero + ']=' + xlinesare[izero]);
izero++;
for (jb=izero; jb<xlinesare.length; jb++) {
if (kb <= eval('' + linesare.length)) {
startpos--;
outstris+=xlinesare[jb].substring(startpos, eval(1 + startpos));
}
kb++;
}
goutstris=outstris;
delayis=500;
setTimeout(afterbit, delayis);
//alert('izero=' + izero + ' ' + outstris + ' left diagonal string potentially ' + linesare.length + ' long starting at ' + eval(onepos % 100) + ' and ending at ' + endpos);
} else {
outstris='';
}
} else {
if (eval(endpos - eval(-2 + eval('' + linesare.length))) == startpos) {
outstris=xlinesare[izero].substring(startpos, eval(1 + startpos));
izero++;
for (jb=izero; jb<xlinesare.length; jb++) {
if (kb <= eval('' + linesare.length)) {
startpos++;
outstris+=xlinesare[jb].substring(startpos, eval(1 + startpos));
}
kb++;
}
goutstris=outstris;
delayis=500;
setTimeout(afterbit, delayis);
//alert(outstris + ' right diagonal string potentially ' + linesare.length + ' long starting at ' + eval(onepos % 100) + ' and ending at ' + endpos);
} else if (eval(-1 + endpos) == startpos) {
outstris=xlinesare[izero].substring(startpos, eval(1 + startpos));
izero++;
for (jb=izero; jb<xlinesare.length; jb++) {
if (kb <= eval('' + linesare.length)) {
outstris+=xlinesare[jb].substring(startpos, eval(1 + startpos));
}
kb++;
}
goutstris=outstris;
delayis=500;
setTimeout(afterbit, delayis);
//alert('izero=' + izero + ' ' + outstris + ' up or down');
} else {
outstris='';
}
}
//alert('string potentially ' + linesare.length + ' long starting at ' + eval(onepos % 100) + ' and ending at ' + eval(eval(onepos + eval('' + outstris.length)) % 100));
}


return outstris;
}


function afterbit() {
if (goutstris == '') { return ''; }
var revsis='';
var documentgetSelectiontoString=goutstris;
if (eval('' + documentgetSelectiontoString.length) >= 4) {
goutstris='';
//document.getElementById('emailsms').style.display='table-cell';
document.getElementById('mytao').title=documentgetSelectiontoString;
aemailurl=origemailurl + encodeURIComponent(documentgetSelectiontoString);
document.getElementById('aemail').href=aemailurl;
asmsurl=origsmsurl + encodeURIComponent(String.fromCharCode(10) + documentgetSelectiontoString);
document.getElementById('asms').href=asmsurl;
for (var irev=eval(-1 + eval('' + documentgetSelectiontoString.length)); irev>=0; irev--) {
revsis+=documentgetSelectiontoString.substring(irev, eval(1 + irev));
}
console.log(documentgetSelectiontoString);
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
console.log('../PHP/surprise.php?min=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&max=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + documentgetSelectiontoString.toLowerCase());
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
} else {
document.getElementById('mytao').style.cursor='not-allowed';
document.body.title='Already tried.';
}
return goutstris;
}


// addEventListener version
document.addEventListener('selectionchange', () => {
var revsis='';
var documentgetSelectiontoString=getmltrans(document.getSelection().toString());
if (eval('' + documentgetSelectiontoString.length) >= 4) {
if (sofar.indexOf(';' + documentgetSelectiontoString + ';') == -1) {
sofar+=documentgetSelectiontoString + ';';
if (goutstris == '') {
//document.getElementById('emailsms').style.display='table-cell';
document.getElementById('mytao').title=documentgetSelectiontoString;
aemailurl=origemailurl + encodeURIComponent(documentgetSelectiontoString);
document.getElementById('aemail').href=aemailurl;
asmsurl=origsmsurl + encodeURIComponent(String.fromCharCode(10) + documentgetSelectiontoString);
document.getElementById('asms').href=asmsurl;
for (var irev=eval(-1 + eval('' + documentgetSelectiontoString.length)); irev>=0; irev--) {
revsis+=documentgetSelectiontoString.substring(irev, eval(1 + irev));
}
console.log(documentgetSelectiontoString);
subscore=eval(0 - eval('' + documentgetSelectiontoString.length));
console.log('../PHP/surprise.php?min=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&max=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + documentgetSelectiontoString.toLowerCase());
setTimeout(retry, 8000);
document.getElementById('mytao').style.cursor='progress';
document.getElementById('nameif').title='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&second=y&iswordthere=' + encodeURIComponent(revsis);
document.getElementById('nameif').src='../PHP/surprise.php?miZn=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&maZx=' + eval(1 + eval('' + documentgetSelectiontoString.length)) + '&firstJUNKname=y&youllneverfindthis=y' + '&iswordthere=' + encodeURIComponent(documentgetSelectiontoString.toLowerCase());
}
} else {
goutstris='';
document.getElementById('mytao').style.cursor='not-allowed';
document.body.title='Already tried.';
}
}
});


// addEventListener version
document.addEventListener('selectstart', () => {
document.getElementById('mytao').title='';
aemailurl=origemailurl;
asmsurl=origsmsurl;
document.getElementById('mytao').style.cursor=cscore('pointer', subscore);
document.body.title='';
console.log('Selection started');
});

… just relying on Selection API text highlighting in an HTML textarea element. Other ideas to improve await for follow up versions!


Previous relevant Selection API and Clipboard API Tutorial is shown below.

Selection API and Clipboard API Tutorial

Selection API and Clipboard API Tutorial

There’s the …

  • clipboard, the “cut and copy and paste ideas”, for text, as we showed you with Clipboard API Image Tutorial and Clipboard API Primer Tutorial … but there’s also the bit before you reach the clipboard using the …
  • text selection (ie. the bit of text you highlight using your mouse or touchpad) … accessible, today, via our introduction to the Selection API

… using HTML changed code


<table><tr><td><textarea id=mytao class=editor rows=7 cols=120 onmousedown="mustnot=true; setTimeout(mnoff, 2000);" ontouchstart="mustnot=true; setTimeout(mnoff, 2000);"></textarea></td></TR><TR><td id=emailsms style=display:none;vertical-align:top;> <a target=_blank href='mailto:?subject=My%20Selection%20...&body=' id=aemail title=Email>&#128231;</a> <a target=_blank onmouseover="if (smsee.length == 0 && origsmsurl.indexOf('sms:&') != -1) { smsee=prompt('Please enter SMS number to send to.', ''); if (smsee == null) { smsee=''; } else { origsmsurl=origsmsurl.replace('sms:&','sms:' + smsee + '&'); asmsurl=asmsurl.replace('sms:&','sms:' + smsee + '&'); this.href=asmsurl; } }" ontouchstart="if (smsee.length == 0 && origsmsurl.indexOf('sms:&') != -1) { smsee=prompt('Please enter SMS number to send to.', ''); if (smsee == null) { smsee=''; } else { origsmsurl=origsmsurl.replace('sms:&','sms:' + smsee + '&'); asmsurl=asmsurl.replace('sms:&','sms:' + smsee + '&'); this.href=asmsurl; } }" href='sms:&body=My%20Selection%20...' id=asms title=SMS>&#128223;</a></td></tr></table><br><br>

… supported by new Javascript event interventional code …


var origemailurl='mailto:?subject=My%20Selection%20...&body=';
var origsmsurl='sms:&body=My%20Selection%20...';
var smsee='';

// addEventListener version
document.addEventListener('selectionchange', () => {
document.getElementById('emailsms').style.display='table-cell';
document.getElementById('mytao').title=document.getSelection().toString();
aemailurl=origemailurl + encodeURIComponent(document.getSelection().toString());
document.getElementById('aemail').href=aemailurl;
asmsurl=origsmsurl + encodeURIComponent(String.fromCharCode(10) + document.getSelection().toString());
document.getElementById('asms').href=asmsurl;
console.log(document.getSelection().toString());
});

// addEventListener version
document.addEventListener('selectstart', () => {
document.getElementById('mytao').title='';
aemailurl=origemailurl;
asmsurl=origsmsurl;
console.log('Selection started');
});

… to be able to share your highlighted text snippets via email or SMS in the changed clipboard_api_test.html Selection API usage web application you can also try below.


Previous relevant Clipboard API Image Tutorial is shown below.

Clipboard API Image Tutorial

Clipboard API Image Tutorial

Yes, yesterday’s Clipboard API Primer Tutorial‘s Clipboard API usages just involved …

  • text based data … and today we turn our attention to …
  • image based data

… to extend the functionality and interest of our changed clipboard_api_test.htm proof of concept
text and image clipboard using webpage.

It’s lucky for us that there are so many good resources out there to help, one link of real interest, for us, being this excellent link, thanks, getting us to use this new Javascript function …


async function pasteImage() {
//event.stopPropagation();
try {
const permission = await navigator.permissions.query({ name: 'clipboard-read' });
if (permission.state === 'denied') {
throw new Error('Not allowed to read clipboard.');
}
const clipboardContents = await navigator.clipboard.read();
for (const item of clipboardContents) {
if (!item.types.includes('image/png')) {
throw new Error('Clipboard contains non-image data.');
}
const blob = await item.getType('image/png');
imgz = new Image();
anothercell();
imgz.onload = () => {
destinationImage.style.width='' + imgz.width + 'px';
destinationImage.style.height='' + imgz.height + 'px';
prevw=eval('' + ('' + cnv.style.width).replace('px',''));
prevh=eval('' + ('' + cnv.style.height).replace('px',''));
console.log('canvas width becomes ' + eval('' + cnv.width) + ' + ' + eval('' + imgz.width) + ' = ' + '' + eval(eval('' + cnv.width) + eval('' + imgz.width)) + 'px');
cnv.style.width='' + eval(eval('' + ('' + cnv.style.width).replace('px','')) + eval('' + imgz.width)) + 'px';
cnv.style.height='' + eval(eval('' + ('' + cnv.style.height).replace('px','')) + eval('' + imgz.height)) + 'px';
cnv.width='' + ('' + cnv.style.width).replace('px','') + 'px';
cnv.height='' + ('' + cnv.style.height).replace('px','') + 'px';
if (mmode == 'mbefore' || 1 == 1) {
ctx.drawImage(imgz, prevw, prevh);
if (wo) {
wo.close();
wo=null;
}
cnv.style.display='block';
//wo=window.open('','_blank','top=50,left=50,height=600,width=600');
//wo.document.write(cnv.toDataURL('image/png'));
}
};
imgz.src = URL.createObjectURL(blob);
destinationImage.src = URL.createObjectURL(blob);
//cnv.style.backgroundRepeat=(('' + cnv.style.backgroundRepeat) + ',no-repeat').replace(/^\,/g,'');
//if (('' + cnv.style.background + ' ').trim() != '') { document.getElementById('mysummary').innerHTML='Conglomerated Images below ...'; }
cnv.style.background=(('' + cnv.style.background) + ',url(' + destinationImage.src + ') no-repeat').replace(/^\,/g,'');
//document.querySelector(".editor").style.display='block';
//destinationImage.style.display='none';
setTimeout(anothercellz, 6000);
}
}
catch (error) {
console.error(error.message);
}
}

… to achieve a lot of this image data use of the Clipboard API functionality.


Previous relevant Clipboard API Primer Tutorial is shown below.

Clipboard API Primer Tutorial

Clipboard API Primer Tutorial

Here’s another day of testing a Javascript API today, which has that “desktop feel”, that being the Clipboard API

The Clipboard API provides the ability to respond to clipboard commands (cut, copy, and paste) as well as to asynchronously read from and write to the system clipboard.

… our clipboard_api_test.html proof of concept version offering “text clipboard data” functionality from the text based clipboard into an HTML textarea element via …

  • append
  • prepend
  • at cursor

… modes of use, you can also try below (or get a sneak peak at tomorrow’s ideas) …

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


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


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


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


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


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


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


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


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


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


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


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


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

Shower Songs Delimitation Hashtag Tutorial

Shower Songs Delimitation Hashtag Tutorial

Shower Songs Delimitation Hashtag Tutorial

Hashtag … doh!

Around here the hashtag means of constructing URLs, especially regarding “a” email mailto: and SMS sms: URL links, has saved the day manys the time, given our emphasis away from mail server based communication logics.

And today, it is used internally, in URLs, as well. That is because the titles for the seven songs can go beyond the ? and & get argument URL length limits for this blog’s domain Apache/PHP/MySql web server.

In this project, we’ve had the good luck to always organize the shaping of the Song Title data arguments to the end of the ? and & get argument parts of the URLs, wherever they be used. As such, the simple arrangement to not be haunted by URL length restrictions just via a …


var urlofinterest=urlofinterest.replace('&thetlist=', '#thetlist'); // hence ... doh!

… type of Javascript code arrangement. Cute, huh?!

Also, today, after yesterday’s Shower Songs Delimitation Remembering Tutorial, we allow for …

  • as well as that reorder allowance as of yesterday, today we extend that to a “shuffle” piece of functionality
  • a way to unremember

… within …

… yet, still, using the RJM Programming’s 404.shtml HTTP Error Code 404 supervisor …


if (eval(('' + encodeURIComponent((decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')) + ',').replace(/[AEIMQUYcgkosw048]\,/g,'z'))).length) == 77 && eval(('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,''))).length) == 83 && eval('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')).split(',').length) == 7) {
location.href='//www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=' + encodeURIComponent(decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')));
}

making it swing the Shower Songs into play with an erroneous URL such as …


https://www.rjmprogramming.com.au/FtE3hoR_Nvo,W5IKT_xue4o,IfaGhyK78E8,BuN3yCmHb_U,TdiAwCPb_As,euZcUku9XiE,aMs0rNtBZJk


Previous relevant Shower Songs Delimitation Remembering Tutorial is shown below.

Shower Songs Delimitation Remembering Tutorial

Shower Songs Delimitation Remembering Tutorial

Our steps forward onto yesterday’s Shower Songs Delimitation Role Tutorial involve window.localStorage remembering of lists that land within the orbit of Shower Songs YouTube API “radio play” web application.

In a “remembering and recall” scenario …

  • first you have to store such a listing URL into window.localStorage …

    if (('' + window.localStorage.getItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]))).replace(/^undefined/g,'').replace(/^null/g,'') == '') {
    window.localStorage.setItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]), newerproposedurl.replace('?', '?subject=' + encodeURIComponent(document.getElementById('mys1').innerText) + '&'));
    } else {
    window.localStorage.removeItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]));
    window.localStorage.setItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]), newerproposedurl.replace('?', '?subject=' + encodeURIComponent(document.getElementById('mys1').innerText) + '&'));
    }

    … and then …
  • you should recall these stored settings so that they can be reused …

    function ourblurb(inurlidea) {
    return String.fromCharCode(10) + decodeURIComponent(('' + inurlidea + '#thetlist=').split('thetlist=')[1].split('&')[0].split('#')[0]).replace(/\|/g,' ... then ... ' + String.fromCharCode(10));
    }

    function thenagain(inurlidea) {
    var outurlidea=inurlidea, isokayhere=true, iuyx=0;
    //alert(inurlidea + ' becomes ' + ('' + inurlidea + '#order=').split('order=')[1].trim());
    if (inurlidea.indexOf('thelist=') != -1 && eval('' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim().split(',').length) == 7) {
    //alert(inurlidea + ' Becomes ' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0] + ' of length ' + eval('' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].length));
    if (eval('' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].length) == 13) {
    //alert(inurlidea + ' becomeS ' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim());
    var theseurlsare=('' + inurlidea + '#thelist=').split('thelist=')[1].split('&')[0].split('#')[0];
    var newurlsare=theseurlsare;
    var theurlsare=decodeURIComponent(theseurlsare.split('&')[0].split('#')[0]).split(',');
    var thesetsare=('' + inurlidea + '#thetlist=').split('thetlist=')[1].split('&')[0].split('#')[0];
    var newtsare=thesetsare;
    var thetsare=decodeURIComponent(thesetsare.split('&')[0].split('#')[0]).split('|');
    var thenumsarehere=('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim().split(',');
    var minone=-1;
    if ((',' + ('' + inurlidea + '#order=').split('order=')[1].trim() + ',').indexOf(',0,') != -1) {
    minone=0;
    }
    //alert(inurlidea + ' becOmeS ' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim());

    for (iuyx=0; iuyx<thenumsarehere.length; iuyx++) {
    if (eval(minone + eval('' + thenumsarehere[iuyx])) < eval('' + eval('' + theurlsare.length))) {
    isokayhere=isokayhere;
    } else {
    isokayhere=false;
    }
    }

    //alert(33);

    if (!isokayhere) { return outurlidea; }

    newurlsare='';
    newtsare='';

    //alert(5);

    for (iuyx=0; iuyx<thenumsarehere.length; iuyx++) {
    if (eval(minone + eval('' + thenumsarehere[iuyx])) < eval('' + eval('' + theurlsare.length))) {
    if (newurlsare == '') {
    newurlsare=encodeURIComponent(theurlsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    } else {
    newurlsare+=encodeURIComponent(',' + theurlsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    }
    }
    if (eval(minone + eval('' + thenumsarehere[iuyx])) < eval('' + eval('' + thetsare.length))) {
    if (newtsare == '') {
    newtsare=encodeURIComponent(thetsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    } else {
    newtsare+=encodeURIComponent('|' + thetsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    }
    }
    }


    //alert(55);
    if (thesetsare != '') {
    //alert('0:' + theseurlsare + ' vs ' + newurlsare);
    inurlidea=inurlidea.replace(theseurlsare, newurlsare).replace(thesetsare, newtsare);
    } else if (theseurlsare != '') {
    //alert('1:' + theseurlsare + ' vs ' + newurlsare);
    inurlidea=inurlidea.replace(theseurlsare, newurlsare);
    } else {
    //alert('2:' + theseurlsare + ' vs ' + newurlsare);
    return outurlidea;
    }
    if (isokayhere) { return inurlidea.split('order=')[0].replace(/\?$/g,'').replace(/\&$/g,'').replace(/\#$/g,''); }
    }
    }
    return outurlidea;
    }

    if (document.URL.indexOf('/shower_songs.htm') != -1) {
    setTimeout(function(){
    Object.keys(window.localStorage).forEach(function(key){
    if (document.URL.indexOf('/shower_songs.htm') != -1) {
    var compagainst=('thelist=' + (document.URL + '#thelist=').split('thelist=')[1].split('&')[0].split('#')[0]).replace(/^thelist\=$/g,'');
    var listblurbis='';
    if (('' + key).indexOf('song_list_') == 0) { {
    //alert(1);
    if (document.getElementById('myh3')) {
    //alert(11);
    if (potsel == '') {
    potsel='<select id=selpot title="Remembered song lists which are optionally recallable." style=width:60px;display:inline-block;margin-left:25px; onchange="if (this.value.trim().length != 0) { if (this.value.indexOf(' + "'hT'" + ') == 0) { var xzsuff=ourblurb(this.value); xxzz=prompt(' + "'Optionally change order as presented' + xzsuff" + ',' + "'&order=1,2,3,4,5,6,7'" + '); window.open(thenagain(this.value + (xxzz == null ? String.fromCharCode(32).trim() : xxzz)),' + "'_self'" + '); } else { window.open(this.value,' + "'_self'" + '); } }"><option value=>++</option></select>';
    //alert(potsel);
    document.getElementById('myh3').innerHTML+=potsel;
    }
    if (compagainst != '' && document.URL.indexOf('thetlist=') == -1) {
    if (compagainst.indexOf('thelist=' + (('' + key).split('song_list_')[1])) != -1) {
    window.open(window.localStorage.getItem(key), '_blank');
    location.href=document.URL.split('?')[0].split('#')[0];
    }
    }
    if (('' + window.localStorage.getItem(key)).indexOf('thetlist=') != -1) {
    if (document.getElementById('selpot')) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key) + '">First song is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thetlist=')[1])).split('|')[0] + '</option>';
    potsel='';
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first song is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thetlist=')[1]).split('|')[0] + '</option>';
    //alert(22);
    }
    } else {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key) + '">First song is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thetlist=')[1])).split('|')[0] + '</option></select>');
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first song is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thetlist=')[1]).split('|')[0] + '</option></select>');
    //alert(122);
    }
    }
    } else {
    if (document.getElementById('selpot')) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key) + '">First song is ' + decodeURIComponent(('' + window.localStorage.getItem(key))) + '">First YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thelist=')[1]).split(',')[0] + '</option>';
    potsel='';
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first song is ' + decodeURIComponent(('' + window.localStorage.getItem(key))) + '">First YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thelist=')[1]).split(',')[0] + '</option>';
    //alert(222);
    }
    } else {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key) + '">First YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thelist=')[1])).split(',')[0] + '</option></select>');
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thelist=')[1])).split(',')[0] + '</option></select>');
    //alert(2222);
    }
    }
    }
    }
    }
    }
    }
    });
    if (potsel != '' && !document.getElementById('selpot')) {
    document.getElementById('divcbi').innerHTML+=potsel;
    }
    }, 500);
    }

… in …

… still using the RJM Programming’s 404.shtml HTTP Error Code 404 supervisor …


if (eval(('' + encodeURIComponent((decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')) + ',').replace(/[AEIMQUYcgkosw048]\,/g,'z'))).length) == 77 && eval(('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,''))).length) == 83 && eval('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')).split(',').length) == 7) {
location.href='//www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=' + encodeURIComponent(decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')));
}

making it swing the Shower Songs into play with an erroneous URL such as …


https://www.rjmprogramming.com.au/FtE3hoR_Nvo,W5IKT_xue4o,IfaGhyK78E8,BuN3yCmHb_U,TdiAwCPb_As,euZcUku9XiE,aMs0rNtBZJk


Previous relevant Shower Songs Delimitation Role Tutorial is shown below.

Shower Songs Delimitation Role Tutorial

Shower Songs Delimitation Role Tutorial

You’d think we’d be done with ablutions at this blog, but noooooo wayyyy … Luna says … there’s all manner of molecular interest out there …

It’s not just H and the 2 and the O … it’s the art of the roleroll.

… or so says “The Lu” anyway!

We wanted our recent Shower Songs web application be the application of choice for URLs at RJM Programming involving our Shower Songs web application YouTube API “radio play” web application.

In a “remembering and recall” scenario …

  • first you have to store such a listing URL into window.localStorage …


    … and then …
  • you should recall these stored settings so that they can be reused …

… in …

… still using the RJM Programming’s 404.shtml HTTP Error Code 404 supervisor …


if (eval(('' + encodeURIComponent((decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')) + ',').replace(/[AEIMQUYcgkosw048]\,/g,'z'))).length) == 77 && eval(('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,''))).length) == 83 && eval('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')).split(',').length) == 7) {
location.href='//www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=' + encodeURIComponent(decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')));
}

making it swing the Shower Songs into play with an erroneous URL such as …


https://www.rjmprogramming.com.au/FtE3hoR_Nvo,W5IKT_xue4o,IfaGhyK78E8,BuN3yCmHb_U,TdiAwCPb_As,euZcUku9XiE,aMs0rNtBZJk


Previous relevant Shower Songs Colour Coding Tutorial is shown below.

Shower Songs Colour Coding Tutorial

Shower Songs Colour Coding Tutorial

YouTube API Songname Providence Shower Songs Tutorial of recent times had us interfacing …

  • song providence via Wikipedia ideas … with …
  • our inhouse Shower Songs project using YouTube API means to “Radio Play” some, let’s say, “theatrical pursuits by the water”

A couple of times now, we’ve used it as company in the bath via an iPhone, preparing the list ahead of ever having to tap another anything, to hear some songs in the sequence the user establishes ahead of time … ie. the purpose of this web application.

However, we made some bad colour choices, especially regarding the mobile red button overlayed by black text containing the song title. It was hard to see. It is easier now, that text being yellow.

While there, we decided on a pale green background colour to apply to the textarea user interactive input and progress displaying conduit, when it’s relevant YouTube video is playing (in audio stream only mode), and another principle of our Shower Songs logic is that you should only see one pale green textarea for any great period of time … ie. the songs play in sequence, and looping around in continuous play, like on the radio.

Believe it or not, the actual top level hierarchy Shower Songs window needs no changes for this, but …

  • the changed

    <script type=text/javascript>
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval('' + navigator.maxTouchPoints) > 0) {
    if (window.parent != window.self) {
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    document.write('<div><sty' + 'le> button { color: yellow !important; font-weight: bold !important; text-shadow: -1px 1px 1px #e52dff !important; } </sty' + 'le></div>');
    }
    }
    }
    </script>
    </body>

    karaoke_youtube_api.htm inhouse YouTube video interfacer helps with the yellow font via CSS … while with the supervised we have …
  • a changed two scenario Javascript situation …

    // textarea gets a pale green background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='#F0FFF0';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + secscnt + '/' + duration + ' ... ' + 'P=pause/play S=stop M=mute U=unmute Y=YouTube G=Google W=Wikipedia L=loop ';
    //
    // textarea gets usual white background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='white';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + Math.round(cen) + '/' + duration + ' ... ' + 'P=play/pause S=stop M=' + mletter + 'ute U=' + uletter + 'nmute Y=YouTube G=Google W=Wikipedia L=loop' + psuf;

    … where stop_start_youtube.html controls those textarea element background colours in that grandchild YouTube API inhouse interfacer

… were needed to make this colour coding logic happen to improve how the user uses this web application, we’re hoping. Ie. bye for now.

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


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


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


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

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

Shower Songs Delimitation Remembering Tutorial

Shower Songs Delimitation Remembering Tutorial

Shower Songs Delimitation Remembering Tutorial

Our steps forward onto yesterday’s Shower Songs Delimitation Role Tutorial involve window.localStorage remembering of lists that land within the orbit of Shower Songs YouTube API “radio play” web application.

In a “remembering and recall” scenario …

  • first you have to store such a listing URL into window.localStorage …

    if (('' + window.localStorage.getItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]))).replace(/^undefined/g,'').replace(/^null/g,'') == '') {
    window.localStorage.setItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]), newerproposedurl.replace('?', '?subject=' + encodeURIComponent(document.getElementById('mys1').innerText) + '&'));
    } else {
    window.localStorage.removeItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]));
    window.localStorage.setItem('song_list_' + decodeURIComponent(document.URL.split('thelist=')[1].split('&')[0].split('#')[0]), newerproposedurl.replace('?', '?subject=' + encodeURIComponent(document.getElementById('mys1').innerText) + '&'));
    }

    … and then …
  • you should recall these stored settings so that they can be reused …

    function ourblurb(inurlidea) {
    return String.fromCharCode(10) + decodeURIComponent(('' + inurlidea + '#thetlist=').split('thetlist=')[1].split('&')[0].split('#')[0]).replace(/\|/g,' ... then ... ' + String.fromCharCode(10));
    }

    function thenagain(inurlidea) {
    var outurlidea=inurlidea, isokayhere=true, iuyx=0;
    //alert(inurlidea + ' becomes ' + ('' + inurlidea + '#order=').split('order=')[1].trim());
    if (inurlidea.indexOf('thelist=') != -1 && eval('' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim().split(',').length) == 7) {
    //alert(inurlidea + ' Becomes ' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0] + ' of length ' + eval('' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].length));
    if (eval('' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].length) == 13) {
    //alert(inurlidea + ' becomeS ' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim());
    var theseurlsare=('' + inurlidea + '#thelist=').split('thelist=')[1].split('&')[0].split('#')[0];
    var newurlsare=theseurlsare;
    var theurlsare=decodeURIComponent(theseurlsare.split('&')[0].split('#')[0]).split(',');
    var thesetsare=('' + inurlidea + '#thetlist=').split('thetlist=')[1].split('&')[0].split('#')[0];
    var newtsare=thesetsare;
    var thetsare=decodeURIComponent(thesetsare.split('&')[0].split('#')[0]).split('|');
    var thenumsarehere=('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim().split(',');
    var minone=-1;
    if ((',' + ('' + inurlidea + '#order=').split('order=')[1].trim() + ',').indexOf(',0,') != -1) {
    minone=0;
    }
    //alert(inurlidea + ' becOmeS ' + ('' + inurlidea + '#order=').split('order=')[1].split('#')[0].trim());

    for (iuyx=0; iuyx<thenumsarehere.length; iuyx++) {
    if (eval(minone + eval('' + thenumsarehere[iuyx])) < eval('' + eval('' + theurlsare.length))) {
    isokayhere=isokayhere;
    } else {
    isokayhere=false;
    }
    }

    //alert(33);

    if (!isokayhere) { return outurlidea; }

    newurlsare='';
    newtsare='';

    //alert(5);

    for (iuyx=0; iuyx<thenumsarehere.length; iuyx++) {
    if (eval(minone + eval('' + thenumsarehere[iuyx])) < eval('' + eval('' + theurlsare.length))) {
    if (newurlsare == '') {
    newurlsare=encodeURIComponent(theurlsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    } else {
    newurlsare+=encodeURIComponent(',' + theurlsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    }
    }
    if (eval(minone + eval('' + thenumsarehere[iuyx])) < eval('' + eval('' + thetsare.length))) {
    if (newtsare == '') {
    newtsare=encodeURIComponent(thetsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    } else {
    newtsare+=encodeURIComponent('|' + thetsare[eval(minone + eval('' + thenumsarehere[iuyx]))]);
    }
    }
    }


    //alert(55);
    if (thesetsare != '') {
    //alert('0:' + theseurlsare + ' vs ' + newurlsare);
    inurlidea=inurlidea.replace(theseurlsare, newurlsare).replace(thesetsare, newtsare);
    } else if (theseurlsare != '') {
    //alert('1:' + theseurlsare + ' vs ' + newurlsare);
    inurlidea=inurlidea.replace(theseurlsare, newurlsare);
    } else {
    //alert('2:' + theseurlsare + ' vs ' + newurlsare);
    return outurlidea;
    }
    if (isokayhere) { return inurlidea.split('order=')[0].replace(/\?$/g,'').replace(/\&$/g,'').replace(/\#$/g,''); }
    }
    }
    return outurlidea;
    }

    if (document.URL.indexOf('/shower_songs.htm') != -1) {
    setTimeout(function(){
    Object.keys(window.localStorage).forEach(function(key){
    if (document.URL.indexOf('/shower_songs.htm') != -1) {
    var compagainst=('thelist=' + (document.URL + '#thelist=').split('thelist=')[1].split('&')[0].split('#')[0]).replace(/^thelist\=$/g,'');
    var listblurbis='';
    if (('' + key).indexOf('song_list_') == 0) { {
    //alert(1);
    if (document.getElementById('myh3')) {
    //alert(11);
    if (potsel == '') {
    potsel='<select id=selpot title="Remembered song lists which are optionally recallable." style=width:60px;display:inline-block;margin-left:25px; onchange="if (this.value.trim().length != 0) { if (this.value.indexOf(' + "'hT'" + ') == 0) { var xzsuff=ourblurb(this.value); xxzz=prompt(' + "'Optionally change order as presented' + xzsuff" + ',' + "'&order=1,2,3,4,5,6,7'" + '); window.open(thenagain(this.value + (xxzz == null ? String.fromCharCode(32).trim() : xxzz)),' + "'_self'" + '); } else { window.open(this.value,' + "'_self'" + '); } }"><option value=>++</option></select>';
    //alert(potsel);
    document.getElementById('myh3').innerHTML+=potsel;
    }
    if (compagainst != '' && document.URL.indexOf('thetlist=') == -1) {
    if (compagainst.indexOf('thelist=' + (('' + key).split('song_list_')[1])) != -1) {
    window.open(window.localStorage.getItem(key), '_blank');
    location.href=document.URL.split('?')[0].split('#')[0];
    }
    }
    if (('' + window.localStorage.getItem(key)).indexOf('thetlist=') != -1) {
    if (document.getElementById('selpot')) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key) + '">First song is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thetlist=')[1])).split('|')[0] + '</option>';
    potsel='';
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first song is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thetlist=')[1]).split('|')[0] + '</option>';
    //alert(22);
    }
    } else {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key) + '">First song is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thetlist=')[1])).split('|')[0] + '</option></select>');
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first song is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thetlist=')[1]).split('|')[0] + '</option></select>');
    //alert(122);
    }
    }
    } else {
    if (document.getElementById('selpot')) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key) + '">First song is ' + decodeURIComponent(('' + window.localStorage.getItem(key))) + '">First YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thelist=')[1]).split(',')[0] + '</option>';
    potsel='';
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    document.getElementById('selpot').innerHTML+='<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first song is ' + decodeURIComponent(('' + window.localStorage.getItem(key))) + '">First YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key)).split('thelist=')[1]).split(',')[0] + '</option>';
    //alert(222);
    }
    } else {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key) + '">First YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thelist=')[1])).split(',')[0] + '</option></select>');
    if (7 == 7 || (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) <= 0 && document.URL.indexOf('.9JUNK5.247/') == -1)) {
    potsel=potsel.replace('</select>', '<option value="' + window.localStorage.getItem(key).replace(/^HT/g,'hT').replace(/^ht/g,'hT') + '">Reorder list where first YouTube video ID is ' + decodeURIComponent(('' + window.localStorage.getItem(key).split('thelist=')[1])).split(',')[0] + '</option></select>');
    //alert(2222);
    }
    }
    }
    }
    }
    }
    }
    });
    if (potsel != '' && !document.getElementById('selpot')) {
    document.getElementById('divcbi').innerHTML+=potsel;
    }
    }, 500);
    }

… in …

… still using the RJM Programming’s 404.shtml HTTP Error Code 404 supervisor …


if (eval(('' + encodeURIComponent((decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')) + ',').replace(/[AEIMQUYcgkosw048]\,/g,'z'))).length) == 77 && eval(('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,''))).length) == 83 && eval('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')).split(',').length) == 7) {
location.href='//www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=' + encodeURIComponent(decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')));
}

making it swing the Shower Songs into play with an erroneous URL such as …


https://www.rjmprogramming.com.au/FtE3hoR_Nvo,W5IKT_xue4o,IfaGhyK78E8,BuN3yCmHb_U,TdiAwCPb_As,euZcUku9XiE,aMs0rNtBZJk


Previous relevant Shower Songs Delimitation Role Tutorial is shown below.

Shower Songs Delimitation Role Tutorial

Shower Songs Delimitation Role Tutorial

You’d think we’d be done with ablutions at this blog, but noooooo wayyyy … Luna says … there’s all manner of molecular interest out there …

It’s not just H and the 2 and the O … it’s the art of the roleroll.

… or so says “The Lu” anyway!

We wanted our recent Shower Songs web application be the application of choice for URLs at RJM Programming involving our Shower Songs web application YouTube API “radio play” web application.

In a “remembering and recall” scenario …

  • first you have to store such a listing URL into window.localStorage …


    … and then …
  • you should recall these stored settings so that they can be reused …

… in …

… still using the RJM Programming’s 404.shtml HTTP Error Code 404 supervisor …


if (eval(('' + encodeURIComponent((decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')) + ',').replace(/[AEIMQUYcgkosw048]\,/g,'z'))).length) == 77 && eval(('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,''))).length) == 83 && eval('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')).split(',').length) == 7) {
location.href='//www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=' + encodeURIComponent(decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')));
}

making it swing the Shower Songs into play with an erroneous URL such as …


https://www.rjmprogramming.com.au/FtE3hoR_Nvo,W5IKT_xue4o,IfaGhyK78E8,BuN3yCmHb_U,TdiAwCPb_As,euZcUku9XiE,aMs0rNtBZJk


Previous relevant Shower Songs Colour Coding Tutorial is shown below.

Shower Songs Colour Coding Tutorial

Shower Songs Colour Coding Tutorial

YouTube API Songname Providence Shower Songs Tutorial of recent times had us interfacing …

  • song providence via Wikipedia ideas … with …
  • our inhouse Shower Songs project using YouTube API means to “Radio Play” some, let’s say, “theatrical pursuits by the water”

A couple of times now, we’ve used it as company in the bath via an iPhone, preparing the list ahead of ever having to tap another anything, to hear some songs in the sequence the user establishes ahead of time … ie. the purpose of this web application.

However, we made some bad colour choices, especially regarding the mobile red button overlayed by black text containing the song title. It was hard to see. It is easier now, that text being yellow.

While there, we decided on a pale green background colour to apply to the textarea user interactive input and progress displaying conduit, when it’s relevant YouTube video is playing (in audio stream only mode), and another principle of our Shower Songs logic is that you should only see one pale green textarea for any great period of time … ie. the songs play in sequence, and looping around in continuous play, like on the radio.

Believe it or not, the actual top level hierarchy Shower Songs window needs no changes for this, but …

  • the changed

    <script type=text/javascript>
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval('' + navigator.maxTouchPoints) > 0) {
    if (window.parent != window.self) {
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    document.write('<div><sty' + 'le> button { color: yellow !important; font-weight: bold !important; text-shadow: -1px 1px 1px #e52dff !important; } </sty' + 'le></div>');
    }
    }
    }
    </script>
    </body>

    karaoke_youtube_api.htm inhouse YouTube video interfacer helps with the yellow font via CSS … while with the supervised we have …
  • a changed two scenario Javascript situation …

    // textarea gets a pale green background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='#F0FFF0';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + secscnt + '/' + duration + ' ... ' + 'P=pause/play S=stop M=mute U=unmute Y=YouTube G=Google W=Wikipedia L=loop ';
    //
    // textarea gets usual white background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='white';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + Math.round(cen) + '/' + duration + ' ... ' + 'P=play/pause S=stop M=' + mletter + 'ute U=' + uletter + 'nmute Y=YouTube G=Google W=Wikipedia L=loop' + psuf;

    … where stop_start_youtube.html controls those textarea element background colours in that grandchild YouTube API inhouse interfacer

… were needed to make this colour coding logic happen to improve how the user uses this web application, we’re hoping. Ie. bye for now.

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


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


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

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

Shower Songs Delimitation Role Tutorial

Shower Songs Delimitation Role Tutorial

Shower Songs Delimitation Role Tutorial

You’d think we’d be done with ablutions at this blog, but noooooo wayyyy … Luna says … there’s all manner of molecular interest out there …

It’s not just H and the 2 and the O … it’s the art of the roleroll.

… or so says “The Lu” anyway!

We wanted our recent Shower Songs web application be the application of choice for URLs at RJM Programming involving …

  • comma separated (ie. tightly separated) delimiter lists … consisting of …
  • seven items … each …
  • eleven characters long … and satisfying …
  • our YouTube video identifier code tests ( ie. end in a particular character within AEIMQUYcgkosw048 and encodeURIComponent([thisCode]) == [thisCode] ) … else, other comma separated lists might be passed onto Tabular Single Row Image Gallery

… akin to Operating System application “associations”, and carrying on the themes talked about with Media Data URI WordPress Blog Not Found Redirect Tutorial and the recent Shower Songs Colour Coding Tutorial.

It’s going to take longer than today’s work, but progress is there with a “first draft” of making this happen involving …

… along with the RJM Programming’s 404.shtml HTTP Error Code 404 supervisor …


if (eval(('' + encodeURIComponent((decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')) + ',').replace(/[AEIMQUYcgkosw048]\,/g,'z'))).length) == 77 && eval(('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,''))).length) == 83 && eval('' + decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')).split(',').length) == 7) {
location.href='//www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=' + encodeURIComponent(decodeURIComponent(document.URL.replace(anybitstoignore,'').replace('.au ','.au/').replace('.au%20','.au/').split('rjmprogramming.com.au/')[1].replace(/^index\.php/g,'').replace(/^index\.html/g,'').replace(/^index\.htm/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')));
}

making it swing the Shower Songs into play with an erroneous URL such as …


https://www.rjmprogramming.com.au/FtE3hoR_Nvo,W5IKT_xue4o,IfaGhyK78E8,BuN3yCmHb_U,TdiAwCPb_As,euZcUku9XiE,aMs0rNtBZJk


Previous relevant Shower Songs Colour Coding Tutorial is shown below.

Shower Songs Colour Coding Tutorial

Shower Songs Colour Coding Tutorial

YouTube API Songname Providence Shower Songs Tutorial of recent times had us interfacing …

  • song providence via Wikipedia ideas … with …
  • our inhouse Shower Songs project using YouTube API means to “Radio Play” some, let’s say, “theatrical pursuits by the water”

A couple of times now, we’ve used it as company in the bath via an iPhone, preparing the list ahead of ever having to tap another anything, to hear some songs in the sequence the user establishes ahead of time … ie. the purpose of this web application.

However, we made some bad colour choices, especially regarding the mobile red button overlayed by black text containing the song title. It was hard to see. It is easier now, that text being yellow.

While there, we decided on a pale green background colour to apply to the textarea user interactive input and progress displaying conduit, when it’s relevant YouTube video is playing (in audio stream only mode), and another principle of our Shower Songs logic is that you should only see one pale green textarea for any great period of time … ie. the songs play in sequence, and looping around in continuous play, like on the radio.

Believe it or not, the actual top level hierarchy Shower Songs window needs no changes for this, but …

  • the changed

    <script type=text/javascript>
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval('' + navigator.maxTouchPoints) > 0) {
    if (window.parent != window.self) {
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    document.write('<div><sty' + 'le> button { color: yellow !important; font-weight: bold !important; text-shadow: -1px 1px 1px #e52dff !important; } </sty' + 'le></div>');
    }
    }
    }
    </script>
    </body>

    karaoke_youtube_api.htm inhouse YouTube video interfacer helps with the yellow font via CSS … while with the supervised we have …
  • a changed two scenario Javascript situation …

    // textarea gets a pale green background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='#F0FFF0';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + secscnt + '/' + duration + ' ... ' + 'P=pause/play S=stop M=mute U=unmute Y=YouTube G=Google W=Wikipedia L=loop ';
    //
    // textarea gets usual white background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='white';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + Math.round(cen) + '/' + duration + ' ... ' + 'P=play/pause S=stop M=' + mletter + 'ute U=' + uletter + 'nmute Y=YouTube G=Google W=Wikipedia L=loop' + psuf;

    … where stop_start_youtube.html controls those textarea element background colours in that grandchild YouTube API inhouse interfacer

… were needed to make this colour coding logic happen to improve how the user uses this web application, we’re hoping. Ie. bye for now.

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


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

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

Command Line ImageMagick HEIC to JPEG Image Creation Tutorial

Command Line ImageMagick HEIC to JPEG Image Creation Tutorial

Command Line ImageMagick HEIC to JPEG Image Creation Tutorial

Lately, we’ve been finding that the image format of photographs taken by our iPad’s Camera mobile application come out in …


IMG_9999.HEIC

… HEIC format (and file naming style of convention) back downloaded into this MacBook Air’s “realm of interest” (and we base a lot of work, here, in MAMP‘s Document Root folder, as a place to base ourselves in). When browsing for these image/heic such files there are known issues, which we do not feel like addressing directly, just now at least.

But we do have a workaround for it, for now … and just maybe forevvvvvvvvvvvveeeeeerrrrr?! Who knows?

And that solution adds another “layer” to the way the recent crontab/curl scheduled macOS PHP command line approach last talked about with Command Line ImageMagick JPEG Image Creation Tutorial set up it’s solution, so that …

  • on top of it’s existant “PaintBrush macOS can’t do *.jpeg” so we’ll get the PHP to ImageMagick convert *.png (recent) to *.jpeg and *.jpg … today “this other layer” goes …
  • “Local File Browsing’s FileReader fails, natively, regarding File type image/heic files” so then we’ll get the PHP to ImageMagick convert *.HEIC (recent) to *.jpeG and *.jpG

Kludge alert for Windows! Sorry, Windows, macOS has case sensitivity, but last time we looked Windows cannot differentiate this way?!

And what do we do up at the local file browsing FileReader File object created interception point, in the Javascript? Code like …


// Globally ...
var lastreject='';

// ... then, near the top of it's function readBlob(opt_startByte, opt_stopByte) { } ...
if (files[0].type.indexOf("image/") != -1 && files[0].name.indexOf(".HEIC") != -1) {
if (lastreject != files[0].name.replace(".HEIC", ".jpeG")) {
lastreject=files[0].name.replace(".HEIC", ".jpeG");
alert('Please reselect using ' + files[0].name.replace(".HEIC", ".jpeG") + ' assuming you have PHP paintbrush_png_jpg.php active in your scheduling');
}
return;
}

The kludges keep coming?! But we’re pretty happy for now and might see about a better solution down the line. Meanwhile the changed paintbrush_png_jpg.php saves our bacon, for now!

Stop Press

Since, we’ve realized out of the iOS Camera app Photos app downloading, you can end up with *.heic (ie. lowercase) files, which we cater for with a further changed paintbrush_png_jpg.php PHP macOS (via Terminal app) command line application.


Previous relevant Command Line ImageMagick JPEG Image Creation Tutorial is shown below.

Command Line ImageMagick JPEG Image Creation Tutorial

Command Line ImageMagick JPEG Image Creation Tutorial

For a while now, on macOS, we’ve been putting up with a scenario with our beloved macOS Paintbrush desktop application version whereby it will not save images in …

  • JPEG format … any more, so we have been saving in …
  • PNG format

… for some time now. Is this a big deal? Well, that is the question? We got a bit of a surprise in aspects of the solution we came up with.

With that, pretty obvious to us, first aim of smaller sized output image media files to start producing, we decided to involve …

  • macOS command line …
  • PHP usage ( ending up with paintbrush_png_jpg.php ) … in a …
  • crontab scheduled …

    * * * * * ksh -c "cd /Applications/MAMP/htdocs; /Applications/MAMP/bin/php/php7.4.33/bin/php /Applications/MAMP/htdocs/paintbrush_png_jpg.php"

… procedure, running each minute here on this MacBook Air using a command line command exemplified for a PNG called my_image.png …


convert -quality 30 my_image.png my_image.jpeg

… via this PHP ( where we thank this useful link for great help ) …


<?php
// paintbrush_png_jpg.php
// August, 2025
// crontab php command line called way to backup Paintbrush created *.png to reduced size *.jpg
$it = new GlobIterator(__DIR__ . "/*.png");
$last2mis = 9020;
foreach ( $it as $file ) {
if ((time() - $file->getMTime()) <= $last2mis) {
if (!file_exists(str_replace('.png','.jpg',$file)) && !file_exists(str_replace('.png','.jpeg',$file))) {
exec("cd " . __DIR__ . '; /usr/local/bin/convert -quality 30 ' . $file . ' ' . str_replace('.png','.jpeg',$file));
}
}
}
?>

… which achieves it’s objective, for the most part, because we are always saving these PNG files to MAMP‘s Document Root ( ie. /Applications/MAMP/htdocs for us ).

All good, smaller image JPEG files do result, but the twist for us came when we assembled our first JPEG vs PNG sets …


$ ls -l mamp_p*.*g*
-rw-r--r-- 1 user admin 459400 3 Aug 15:15 mamp_paintbrush_job-15.jpeg
-rw-r--r--@ 1 user admin 1857056 3 Aug 14:39 mamp_paintbrush_job-15.png
-rw-r--r-- 1 user admin 413477 3 Aug 15:14 mamp_paintbrush_job-17.jpeg
-rw-r--r--@ 1 user admin 1816410 3 Aug 14:47 mamp_paintbrush_job-17.png
-rw-r--r--@ 1 user admin 246569 3 Aug 15:08 mamp_paintbrush_job-21.jpeg
-rw-r--r--@ 1 user admin 1959028 3 Aug 15:08 mamp_paintbrush_job-21.png
-rw-r--r-- 1 user admin 264874 3 Aug 15:10 mamp_paintbrush_job-23.jpeg
-rw-r--r--@ 1 user admin 2555260 3 Aug 15:09 mamp_paintbrush_job-23.png
-rw-r--r-- 1 user admin 249117 3 Aug 15:11 mamp_paintbrush_job-25.jpeg
-rw-r--r--@ 1 user admin 2704233 3 Aug 15:11 mamp_paintbrush_job-25.png
-rw-r--r-- 1 user admin 230524 3 Aug 15:16 mamp_paintbrush_job-27.jpeg
-rw-r--r--@ 1 user admin 1962296 3 Aug 15:15 mamp_paintbrush_job-27.png
-rw-r--r-- 1 user admin 280417 3 Aug 15:17 mamp_paintbrush_job-29.jpeg
-rw-r--r--@ 1 user admin 2677561 3 Aug 15:16 mamp_paintbrush_job-29.png
$

… into two animated GIF images ( with PNG based one called paintbrush_crontab_png_to_jpeg.gif ) …


$ ls -l paintbrush_*.gif
-rw-r--r--@ 1 user staff 5100166 3 Aug 19:11 paintbrush_crontab_png_to_jpeg.gif
-rw-r--r--@ 1 user staff 6485830 3 Aug 19:14 paintbrush_png_to_jpeg_crontab.gif
$

… via our inhouse animated GIF creator helper web application.

Huh?! Read a bit more about it here!

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


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

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

Debugging Only With Thinking Tutorial

Debugging Only With Thinking Tutorial

Debugging Only With Thinking Tutorial

Some programming problem solutions benefit from …

  1. “standing back a bit”, not getting too emotionally agitated by it, especially if either …
    • it is just an annoyance, and there is an alternative workflow a user can use to get to the functionality
    • it is not mission critical to anything

    … but, at least even there …

  2. note down the issue in writing … and …
  3. if no immediate thought comes to mind … there’s nothing wrong with “stewing on it”

For instance, we’ve had a long running case involving …

  1. at this WordPress blog …
  2. as far as we could tell, iPad users only … could …
  3. tap the tutorial image, and rather than get taken to the “Cut to the Chase” action (perhaps web application) of interest … they would instead …
  4. get taken to the “right click/tap on a tutorial image at this WordPress blog” logic

We categorize this, around here, as …

  • “that’s peeving” (if “peeving” is a word, that is) … and …
  • “are we peeved?” …

    Stay schtum. Stay calm.

    my body is a temple

  • because of the reasons outlined above … but …

Today’s the day … yay!!!!!!

So, in “full flow debugging style awareness” what is the “key phrase” in the description of the issue, above?

We’d say “iPad users only” definitely, because no matter what debugging we do with Apple white leads joining up Safari browser iPad and MacBook Air debugging windows we do (and don’t get me wrong, this did help get the outerHTML of an img element in question, which was useful) clear thinking would reask (the “platform” and “environment” related) …

Why only on iPad (when it doesn’t happen on iPhone)?

… question because, in our experience …

That’s the unusual thing about the issue. And if we’d been on the ultimate ball we’d have noted that that discovery we outline below was made using an iPad!

And then we remembered back to the recent Canvas Interfacer Mobile Image Map Tutorial‘s discovery that …

… our changes being helped out by the discovery that our previous …


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
// is identified around here as a mobile platform
}

… was a bit unreliable identifying mobile iOS platform Safari web browser usage, but this useful link got us to refine that thinking to …


if ( navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) > 0 ) {
// is better identified around here as a mobile platform
}

… with more success. Yayyyyy!

… so we bit the bullet and applied this discovery’s changes to the good ol’ header.php of our TwentyTen themed WordPress blog “go to” piece of code. Yes, good to do, but we found, still no Havana cigar!

So then, relook at the outerHTML of the img element in question. It looked like …


<img decoding="async" tabindex="0"
oncontextmenu="imgedit(event);"
ontouchend="imgedit(event);"
onload="altanimation(this,this.id,this.src);"
onerror="altunzipit(this,this.id,this.src);"
style="border: 15px solid pink; margin-left: -20px;"
alt="Camera App on iOS Revisit Tutorial"
src="//www.rjmprogramming.com.au/Mac/iPhone/camera_app_revisit.gif"
title="Camera App on iOS Revisit Tutorial"
id="igm1790668">

… and that ontouchend=”imgedit(event);” is a clue to follow. Indeed, it took us to the “image right click logics” contained in the changed onrightclick.js external Javascript logic designed for right click analysis. What if it’s “mobile check booleans” need this updating too? And yes, that fixed the issue.

Ahhhhhh!


Previous relevant Canvas Interfacer Mobile Image Map Tutorial is shown below.

Canvas Interfacer Mobile Image Map Tutorial

Canvas Interfacer Mobile Image Map Tutorial

On the same themes as yesterday’s Canvas Interfacer Three Finger Gesture Usage Tutorial‘s …

  • mobile platform chance to have three finger gestures help with scrolling functionality … today we have it so that …
  • mobile platforms are better suited creating Image Maps via canvas and image based inhouse web application (looking out for 🗺️🖼️ emoji button means to create Image Map when ready, as a double click on the canvas can do as well)

… our changes being helped out by the discovery that our previous …


if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
// is identified around here as a mobile platform
}

… was a bit unreliable identifying mobile iOS platform Safari web browser usage, but this useful link got us to refine that thinking to …


if ( navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) > 0 ) {
// is better identified around here as a mobile platform
}

… with more success. Yayyyyy!

Along the way the HTML textarea elements used to identify Image Map subelement area rectangular limits have their disabled attribute set, which has the benefit …

  • that there is no need to allow any focus to these textarea elements when nothing any user can enter into them would make any difference anyway … and yet …
  • at least on non-mobile platforms the useful resizing talents of textarea elements are not stopped because of the disabled attribute being set

We found that the URL usage …


https://www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm#imagemap=url

… had become a little obsolete (at least, regarding the emoji button workflow), in the sense that, like with the canvas ondblclick event (ie. double click) functionality, why not, when clicking that 🗺️🖼️ Image Map creator emoji button grab the contents of the canvas already displaying as the default content presented to the “potential” (ie. it depends, sometimes, whether you double click that canvas element the next time) Image Map creation session?

Relevant to Random Background Image Map Area Polygons Tutorial and the decision then regarding non-mobile platforms to use an initial click followed by right clicks to enable Image Map area element shape=poly components, today, thinking with respect to mobile platforms, we’ve decided Image Map area element shape=poly components can be created via an initial click followed by double click sequences and going back to the polygon start, with either platform type, ending the polygon with two separated clicks. Also relevant to that same tutorial and it’s pointer-events:none; discovery, today’s mobile work regarding the textarea elements plotted to show the rectangular limits of user defined areas already created we found “real world relevance” to applying this to mobile such textarea elements. That is because on some mobile platforms these textarea elements will never be able to be resized out of the way, but if we apply pointer-events:none; to these, it does not matter, as the user can, as required, click/touch through these overlayed elements that have a huge z-index and semi-transparency applied to them.

Again, perhaps on a mobile platform web browser, feel free to try …

Did You Know?

There are known Safari mobile web browser textarea resizing limitations as we discovered trying a Google search of allow textarea resizing on mobile safari web browser, thanks, that we gleaned from the use of …

Solution 2: Standard JavaScript Auto-Grow
If you need to support older versions of iOS Safari that lack the newest CSS specs, you can dynamically update the box height using a tiny JavaScript event listener. This removes the scrollbar and expands the container vertically as they type:

HTML: html
<textarea id=”mobile-textarea” rows=”3″ oninput=”autoGrow(this)”></textarea>

JavaScript: javascript
function autoGrow(element) {
element.style.height = “auto”;
element.style.height = (element.scrollHeight) + “px”;
}

… incorporated ideas to help here.


Previous relevant Canvas Interfacer Three Finger Gesture Usage Tutorial is shown below.

Canvas Interfacer Three Finger Gesture Usage Tutorial

Canvas Interfacer Three Finger Gesture Usage Tutorial

There’s more research needed around here regarding mobile platform usage to the HTML5 canvas based ideas swirling around yesterday’s Random Background Image Map Area Polygons Tutorial‘s work, and one issue we came across was …

  • on mobile platforms you can get to gesture results whereby the canvas is all you see on the screen (eg. of an iPhone) …
  • but what if you are in “scribble mode” at that point?
  • before today, we were having trouble using …
    1. two finger “pinch” gesture to zoom out … or …
    2. one finger “swipe” to reveal more to the right (where, if we could have reached it, that right hand menu of annotation options has none of these “scribble mode” oddities) … because …
    3. before today, that last idea just drew a “scribble” “free drawing” line to the canvas

    … to reach the menu or any other non-canvas element not in “scribble mode” (ie. scrolling could not be achieved, at least in a way we could immediately access)

And so, we asked Google, thanks, “detect three finger gesture and if so scroll in the direction indicated” and got this useful advice …

Web Implementation (JavaScript)

If you are building this for a website or web app, you can use the touchstart and touchmove events to capture finger coordinates, check if exactly three fingers are on the screen, and then calculate the direction.

… to (start with globalvar isthree=false; and) end up with


if (eval('' + event.touches.length) >= 3 && event.type == "touchstart") {
isthree=true;
return;
} else if (isthree && event.type == "touchend") {
//if (isthree) {
isthree=false;
window.top.scrollBy(200,0);
return;
//}
}

… near the top of our function toptouchHandler(event) Javascript code in our changed signature_signature.js external Javascript canvas interfacer helper.


Previous relevant Random Background Image Map Area Polygons Tutorial is shown below.

Random Background Image Map Area Polygons Tutorial

Random Background Image Map Area Polygons Tutorial

Further to the recent Random Background Alternate Image Source Tutorial

  • Image Map only allowing for area subelements with shape=rect … today we also allow for …
  • Image Map now allowing for area subelements with shape=poly …

… via …

Right clicks after an initial click are the means by which you can define area shape=poly ( as distinct from the default shape=rect ) elements where to finish a polygon two click back close to the start point.

… as a modus operandi for the user to cater for more complex shape definitions in their Image Maps.

That doesn’t mean the rectangle around such a polygon is not also significant. Do you know why?

Yes, a hosting HTML div of a specific width and height and positioned absolutely at a precise left and top screen position allows SVG innerHTML like …


<svg xmlns="http://w3.org" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"><polyline points="0,67,56,7,100,0,150,17,0,67"></polyline></svg>
... be showing a polygonal user clicked shape, scaled appropriately, yet responsively, and allowing for those % unit definitions above making all this methodology useful here. Notice the zero co-ordinates? That is no accident. We make the co-ordinates relative to the minimum x and minimum y "datum" to the co-ordinating.

Feel free to try ...

Did You Know?

We broached the idea "pass event logic down through even though an element has a bigger z-index" to Google, thanks, and got back ...

To pass events down through a higher z-index element, add pointer-events: none; to the top element. This tells the browser to ignore the overlay for mouse events, allowing clicks and hovers to "fall through" to the element stacked beneath it.

... to learn a whole new technique we've been looking for for quite some time now ... now, where did we put that "Overlay Disappointments File"?! ... bye bye!


Previous relevant Random Background Alternate Image Source Tutorial is shown below.

Random Background Alternate Image Source Tutorial

Random Background Alternate Image Source Tutorial

Onto the recent Random Background Image Map Integration Tutorial's web application's use of ...

  • Lorem Picsum image repository "source" of image data ... today we allow the user to, instead, get images from ...
  • RJM Programming WordPress Tutorial Images (ie. this WordPress.org blog)

... and we've shored up the copy and pasting of screen logic, so that ...

  • the screen is more filled with image data, and the relevant graphical pasting place "border enhanced", in the process ...
  • the images have better resolution, in the process

... as the two areas of improvement within ...

... regarding it's newish Random Image Map integrations.


Previous relevant Random Background Image Map Integration Tutorial is shown below.

Random Background Image Map Integration Tutorial

Random Background Image Map Integration Tutorial

Like with ...

... and allowing users using our inhouse Random Background interfacer the chance to create some Image Maps using incarnations of these images as the visual basis to them.

We've chosen ...

  • the oncontextmenu (ie. right click) as an intervention point to facilitate this ... or ...
  • if using a macOS operating system a ...
    1. control-command-shift-3
    2. control-command-shift-5

    ...

    document.addEventListener('keydown', (event) => { // thanks to https://www.google.com/search?q=javascript+detecting+control-command-shift-3&rlz=1C5OZZY_en&oq=javascript+detecting+control-command-shift-3&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQIRigATIHCAIQIRigATIHCAMQIRigATIHCAQQIRigATIHCAUQIRiPAjIHCAYQIRiPAjIHCAcQIRiPAtIBCTE3NzMyajBqN6gCALACAA&sourceid=chrome&ie=UTF-8
    // Check if Control, Command (metaKey), and Shift are all held down
    // AND the key pressed is the number 3
    if (
    event.ctrlKey &&
    event.metaKey &&
    event.shiftKey &&
    event.code === 'Digit5'
    ) {
    // Prevent the default browser action if necessary
    //event.preventDefault();

    //var kc=eval(-2 + event.keyCode);

    event.preventDefault();
    event.stopImmediatePropagation();

    // Create a fake event with a modified code (e.g., ArrowDown)
    const simulatedEvent = new KeyboardEvent("keydown", {
    key: "3",
    code: "Digit3",
    ctrlKey: true,
    metaKey: true,
    shiftKey: true
    }); // keyCode: kc, bubbles: true, cancelable: true,

    // Fire the fake event into the DOM
    event.target.dispatchEvent(simulatedEvent);

    if (immap && !holdoff) { holdoff=true; setTimeout(function(){ wowo=window.open('/HTMLCSS/user_of_signature_signature.htm?askforpaste=y&imagemap=url#' + myco.toDataURL('image/jpeg',0.4), '_blank', 'top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height)); setTimeout(function(){ holdoff=false; }, 8000); }, 2000); }

    console.log('Control + Command + Shift + 3 combination detected!');
    // Insert your custom logic here
    }
    });

    ... combination is another modus operandi in play

... within ...

... regarding it's new Random Image Map integrations.


Previous relevant Inhouse Image Map WordPress Integration Tutorial is shown below.

Inhouse Image Map WordPress Integration Tutorial

Inhouse Image Map WordPress Integration Tutorial

The recent work of Inhouse Image Map Creator Browsing Tutorial ...

  • established a URL means by which a single URL call from the canvas residing Inhouse Image Map Creator and Canvas Annotation web application via a data URI hashtag conduit ... and today just ...
  • allowing for an absolute URL in that hashtag is the relatively simple change needed so that, using this, our WordPress "right click over an img image element" functionality can be tweaked ...


var huhifs=prompt('Optionally, please, any CSS for images ... append 3 spaces to be able to edit this ' + (gthing == 'image' ? gthing + ' (and answer of #imagemap will use this image as basis for creation of an image map in a new window)' : gthing) + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
if (huhifs == null) {
huhifs='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (event.target.outerHTML.indexOf('<a ') == 0) {
console.log(6);
ggurl=event.target.href;
} else {
console.log(66);
ggurl=document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="')[eval(-1 + document.body.innerHTML.split(event.target.outerHTML)[0].split(' href="').length)].split('"')[0];
}
if (6 == 6) {
console.log(ggurl);
window.open(ggurl,'_blank'); ggurl='';
// huhifs=window.prompt('Optionally, please, any CSS for images ... append three spaces to be able to edit this ' + gthing + ' in a canvas ... ref. https://www.w3schools.com/cssref/css3_pr_filter.php ... eg. ' + egblurb + usuff + ' ', defblurb);
} else {
setTimeout(function(){ window.open(ggurl,'_blank'); ggurl=''; }, 5000); //alert(event.currentTarget.outerHTML); //event.currentTarget.click();
}
}
}
if (huhifs.toLowerCase() == '#imagemap') {
event.preventDefault();
event.stopPropagation();
ggurl=event.target.src;
window.open('//www.rjmprogramming.com.au/HTMLCSS/user_of_signature_signature.htm?imagemap=url#' + (ggurl.indexOf('//') != -1 ? '//' + ggurl.split('//')[1] : (ggurl.replace(/^\.\//g,'/').indexOf('/') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(1).replace(/^\//g,'ITblog/') : (ggurl.indexOf('../') == 0 ? '//www.rjmprogramming.com.au/' + ggurl.substring(3) : ggurl))),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height));
ggurl='';
} else
if (huhifs.indexOf('data:image/') == 0) {
if (document.getElementById('imgcopycheck') && usuff != '') { //if (document.URL.indexOf('/streetart/') != -1) {
uplitc(huhifs); //alert(document.URL);
}
return '';
}

... as an excerpt from the changed onrightclick.js external Javascript called by WordPress, and calling ...


Previous relevant Inhouse Image Map Creator Browsing Tutorial is shown below.

Inhouse Image Map Creator Browsing Tutorial

Inhouse Image Map Creator Browsing Tutorial

Repeat after me ...

an image is a canvas is an image

?

an image is a canvas is an image

... good, now, again ... an image is a canvas is an image ...

an image is a canvas is an image

... excellent, now, backwards ... egami na si savnac a si egami na ...

egami na si savnac a si egami na

... wow! ... Now, lastly … I want my mamma! Now! ...

I want my mamma! Now!

 

But it's true. Our thinking behind allowing browsed for image files become data URIs that can be the img element "image" part of the "image map", further to yesterday's Inhouse Image Map Creator Mobile Debug Tutorial, we can now create using our inhouse Image Map Creator capable web application uses the "an image via [canvasContext].drawImage() is a canvas via [canvas].toDataURL() is an image" concept that can save us heaps of time with this project. Instead of intervening at each dropdown option mentioning "Browse" to make this design change, we, instead, introduce to the HTML5 canvas element a new ondblclick event ...


<canvas ondblclick="qwowo=window.open(document.URL.split('?')[0].split('#')[0] + '?imagemap=url#' + this.toDataURL('image/jpeg',0.4),'_blank','top=40,left=40,width=' + eval(-80 + screen.width) + ',height=' + eval(-80 + screen.height) + '');" ondragstart="dragstart(event);" draggable="false" title="Ready for you to create your canvas 🎨 content above any signature 💳 panel ... keys U for Undo and R for Redo can work after a discrete click ending any scribble mode of use. Double click can facilitate turning this canvas content into an image map, and this canvas content can be populated by so many of the options in the menu to the right, which includes many local image file browsing choices." id="topcanvas" width=850 height=600 style="background-color:white; position: absolute; top:0; left:0; border-bottom:5px solid yellow; border-right:5px solid blue;"></canvas>

... allowing that "on double click" result in the web application turning into an Image Map Creator where now ...

Image Map ( ie. <img src="[image URL as entered by user or data URI browsed for by the user, or, come to think of it, from a couple of days back, entered in by the user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... is that very pithy redefinition of our web application's view of what an Image Map can be! Though?!

 

Again, feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Mobile Debug Tutorial is shown below.

Inhouse Image Map Creator Mobile Debug Tutorial

Inhouse Image Map Creator Mobile Debug Tutorial

Apologies to any mobile users wanting to access this new inhouse Image Map creator web application last talked about with yesterday's Inhouse Image Map Creator Interactive Drill Down Tutorial before today, that is, but we were leaving the issue until a proper hardware ...

  • Mac Book Air
  • Apple white lead
  • iPhone

... that once the middle one plugs into the top and bottom allows for ...

  • iPhone Safari web browser call of the inhouse Image Map creator ... could tee up with (ie. attain a "connection" with) ...
  • Mac Book Air Safari web browser Develop -> (in our case) Robert's iPhone -> user_of_signature_signature.htm

... online debugging session, could be arranged and a block of time set aside to concentrate on, because "concentrate" is the name of the game here!

Luckily, the issue was straightforward, where many are not. In the overseeing code, we had ...


<script type=text/javascript>
var oklj=0;
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || document.URL.indexOf('?fcol=') != -1) {
oklj=oklj;
} else {
document.write("<iframe id=ifconto name=ifconto src='/PHP/animegif/tutorial_to_animated_gif.php#rand=" + Math.floor(Math.random() * 19878675) + "' style='width:100%;height:900px;display:BLOCK;'></iframe>");
}
</script>

... ba bow ... because in the external Javascript we got pulled up by the debugging of the iPhone execution attempt at a codeline, where the user decides to take on an Image Map creation task ...


top.document.getElementById('ifconto').src='/About_Us.html';

... ba bow. On mobile, that necessary HTML iframe was non-existant! So, with the external Javascript, at this similar juncture, we came up with ...


if (!top.document.getElementById('ifconto')) {
top.document.body.innerHTML+="<iframe id=ifconto name=ifconto src='/About_Us.html' style='width:100%;height:900px;display:none;'></iframe>";
} else {

top.document.getElementById('ifconto').src='/About_Us.html';
}

... to start getting somewhere, here, with these inhouse Image Map creation ideas on mobile platforms.

And what about ...

  1. allow for data URIs pasted into the prompt window
  2. create non-mobile rubber banded overlays to help contextualize further

? Huh?! Feel free to give this all a go with ...


Previous relevant Inhouse Image Map Creator Interactive Drill Down Tutorial is shown below.

Inhouse Image Map Creator Interactive Drill Down Tutorial

Inhouse Image Map Creator Interactive Drill Down Tutorial

It might be the case, often, with Image Map creations, as with our recent web application featuring in yesterday's Inhouse Image Map Creator Drill Down Tutorial that the user needs to ...

strike while the iron is hot

... regarding having the event logic be nuanced as the image map area subelements are created in terms of ...

  • area subelement inline event logic definitions (pointing at, perhaps, local Javascript functions) ... as well as ...
  • the content of those local Javascript functions

... in such a way that, if you come back to "flesh out" the image map HTML coding the next day, say, there are enough clues you've left that you do not have to go and match the "coords" attribute values to a screen position to get some context. That takes a lot longer we find.

And so, today, we now offer ...

Enter an Image URL (append space to create Image Maps where click/tap pairs can define rectangle corners ... cursor is a crosshair for lower left click/tap, first, then cursor is pointer top right ... append another one space to prompt for tailored event logic each time and two spaces to also review the default Javascript used for double click logic image map testing purposes ... we are going to discourage scrolling here, but you can still zoom out or in)

... Javascript prompt windows "on the fly" to allow for this to be a possibility for the Image Map creator using ...


Previous relevant Inhouse Image Map Creator Drill Down Tutorial is shown below.

Inhouse Image Map Creator Drill Down Tutorial

Inhouse Image Map Creator Drill Down Tutorial

Onto yesterday's Inhouse Image Map Creator Tutorial we've decided today's work should stay within non-mobile realms but flesh out more user available functionality to help with "stage two" thinking. With that in mind ...

  • the image map HTML containing textarea created (with yesterday's efforts using the Canvas and Image Map web application (now featuring a new emoji button 🗺️🖼️ to allow for a non-dropdown usage approach)) has an ondblclick event logic added so that when double clicking, at any stage of the image map creation processing, it ...
  • opens a new popup window where that HTML you have so far is surrounded by a default "rest of webpage" scenario as the HTML that goes into making up that popup window HTML content, and where you can test out it's workings ... as well as ...
  • that popup window image map, itself, is given an ondblclick event logic whereby a double click there can create below that image map within the same popup window a new textarea element containing all that HTML (default "rest of webpage" and all) which can be copied into a clipboard buffer as required ... and ...
  • if that textarea within the popup window is edited and the user double clicks that textarea element, a new popup window reflecting your changes is opened above that ... etcetera etcetera etcetera

All this can be used to either/both validate your image map and follow through further to incorporating the image map into a functional HTML webpage, using the changed signature_signature.js external Javascript to make all this possible. Within that changed external Javascript we allow the user to cancel the proposed area subelement currently embarked upon between where the user has clicked/tapped the bottom left and before they shape to click/tap the top right rectangle definition, via a right click, so as to reset back to the click/tap using the crosshair cursor back at a bottom left area shape=rect subelement definition.


Previous relevant Inhouse Image Map Creator Tutorial is shown below.

Inhouse Image Map Creator Tutorial

Inhouse Image Map Creator Tutorial

The "largely canvas" using web application last talked about with WordPress Blog Image Editing Media Tutorial, today, we're excited to announce, has been given an "on first draft just image URL" using new ...

Image Map ( ie. <img src="[image URL as entered by user]" usemap='#htblah' blah /><map name='htblah' id=htblah><area shape=rect coords='tlx,tly,brx,bry' blah /> ... more area elements blah ... blah ... blah ... <area shape=default nohref alt="" /></map> ) creator

... arrangement inhouse means to construct image maps, so far, just via an image URL.

Why hook into the largely canvas savvy web application? Well, it is that basic positional mouse event logic that is needed to create image maps, and here, it is a dominant theme, and useful, even though the rearrangement of data needed is quite substantial, still, that is where we think this new functionality appears most at home, being a new suboption ("Image 🖼 Canvas Matches Actual URL or Image Map rectangle area creations") off a dropdown option means of deploying.

No tests on mobile, yet, but on non-mobile, we're happy, once the user chooses to create Image Maps, so long as ...

  1. we stop user web page scrolling ... while still allowing ...
  2. webpage zooming out or in

... in conjunction with ...

  • replacing the webpage table's left cell content, which used to contain a canvas element, with the user defined image, via it's URL ...
  • replacing the webpage table's right cell content, which used to contain an canvas annotation menu, with the image map URL HTML built up from user lower left and upper right rectangle defining click/taps

... we have the wherewithal to create image map HTML code the user can copy and use, with "stage two" fleshing out!

Try this at ...

... to allow for this image map inhouse functionality. The talents of HTML textarea elements, with their resizing abilities, helps out here, allowing these overlayed textarea elements ...

  1. containing image map HTML ... and/or ...
  2. overlaying semi-transparentally to see what has been clicked already

... also be able to be resized "out of the way" should that be needed perhaps regarding overlapping scenarios, without having to resort to any other type of event logic to allow for. The other big and relevant talent of textarea elements is their ability to contain HTML code and be editable with that HTML code, perhaps user amended, and to be able to Select All then Copy into a clipboard buffer, via it's right click web browser menu, ready to paste somewhere else, that HTML content ready for any required "stage two" embellishment and usage.


Previous relevant WordPress Blog Image Editing Media Tutorial is shown below.

WordPress Blog Image Editing Media Tutorial

WordPress Blog Image Editing Media Tutorial

We're happy to be revisiting ...

... to add to our recent WordPress Blog Image Editing functionality, extending it's capabilities to be able to optionally create either/both ...

  • Video
  • Animated GIF

... media presentations off this should the user pick more than one image, to be edited, in any one web browser tab (via window.sessionStorage) session. So far, we're creating ...

  • window.open
  • background image
  • background-size: contain

... "Video" and "Animated GIF" presentations, and see this as a shareable commodity, into the future, especially as the image slide data ends up being an HTML canvas [canvas].toDataURL() data URI that represents ...

  1. lots of data
  2. but understood everywhere

... and content wise has included within it, any canvas manipulations and annotating and reworking the user has applied plus, at least for Google Chrome, any image filtering CSS the user has requested, into that canvas. We shape to involve the cowsay actual web server disk based media creating interfacing, but not for now. We'll see, because WordPress Visual Synopsis Media Tutorial methodologies also ended up presentation wise, with "inhouse" "Video" and "Animated GIF" presentations.

How does the user make this happen? Well, at the opportune call of our Canvas Image Editor web application some "Mantissa MadnessMagic" takes place using ...


if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").indexOf('.') != -1) {
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]))) {
if ((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "") >= '1') {
setTimeout(function(){
if (document.getElementById('storyboard') && document.getElementById('toptd')) {
document.getElementById('toptd').innerHTML=document.getElementById('toptd').innerHTML.replace(document.getElementById('storyboard').outerHTML, '  <button onclick="top.videoshow();">Video &#128249;</button>  <button onclick="top.agshow();">Animated GIF &#128444;</button> ' + document.getElementById('storyboard').outerHTML);
}
}, 8100);
}
setInterval(function(){
var mycisv=document.getElementById('topcanvas');
var mycisvcon=mycisv.getContext('2d');
var mycanc=mycisv.toDataURL('data/jpeg', 10);
if (top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value.length != mycanc.length) {
top.document.getElementById('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0])).value=mycanc;
top.agup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
top.vdup('slideav' + eval((location.search.split('fcol=')[1] ? decodeURIComponent(location.search.split('fcol=')[1].split('&')[0]) : "").split('.')[0]), mycanc);
}
}, 10000);
}
}

... to look like ...

    

... appearing in the right cell hosted Annotation Menu tools of the changed user_of_signature_signature.htm inhouse image data fed canvas editor web application.

The fourth draft onrightclick.js external Javascript now includes those onclick logic event functions ...


function agshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var ist=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts; } else { document.title=dtp + dtstwo; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist++; setTimeout(startit, 5000); } setTimeout(startit, 2000); </scr' + 'ipt>';
woagis=window.open('','_blank','top=110,left=110,width=700,height=700');
woagis.document.write('<html><head><title>Animated GIF of selected images ... start of looping presentation ...</title>' + ascr + '</head><body style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

function videoshow() {
var ascr='';
var scris='<scr' + 'ipt type=text/javascript> var verbs=[" paused"," playing"], ist=0, inc=0, pref="slideav", thisi="thisimg", dtp=document.title.split(" ... ")[0], dtstwo=" ... looping presentation ", dts=" ... " + document.title.split(" ... ")[1]; function startit() { if (!document.getElementById(pref + ist) || ist == 0) { ist=0; document.title=dtp + dts + verbs[inc]; } else { document.title=dtp + dtstwo + verbs[inc]; } document.body.style.backgroundImage="URL(" + document.getElementById(pref + ist).value + ")"; ist+=inc; setTimeout(startit, 1000); } setTimeout(startit, 1000); </scr' + 'ipt>';
wovdis=window.open('','_blank','top=100,left=100,width=700,height=700');
wovdis.document.write('<html><head><title>Video of selected images ... start of looping presentation </title>' + ascr + '</head><body title="Initially paused but on loop when started. Click to toggle between pause and play." onclick="inc=eval(1 - inc);" style="background-repeat:no-repeat;background-size:contain;">' + document.getElementById('myimepf').outerHTML + scris + '</body></html>');
}

... creating those popup window "Video" and/or "Animated GIF" presentations we've been talking about above.

The WordPress Blog TwentyTen theme's header.php gets a crucial new Javascript function referenced elsewhere ...

<?php echo "

function firstuptop() {
var ifnum=1, arrc=['cow', 'ime'], butsuff='', arrbw=['', ' of Selected Images'], arrolp=['vif','ime'];
var utd='<div id=divime style=display:none;>';
for (var jime=0; jime<2; jime++) {
if (jime > 0) {
utd+="</b><br><iframe name=my" + arrc[jime] + "ifr id=my" + arrc[jime] + "ifr style=display:none; src=/About_Us.html></iframe><form target=my" + arrc[jime] + "ifr action=/cowsay.php method=POST id=my" + arrc[jime] + "pf><div id=div" + arrc[jime] + "pf></div><input type=submit id=vlist" + butsuff + " style=display:none;background-color:lightblue; name=vlist" + butsuff + " value='Video &#128249; " + arrbw[jime] + "'></input> <input type=submit style=display:none;background-color:lightblue; id=aglist" + butsuff + " name=aglist" + butsuff + " value='Animated GIF &#128444; " + arrbw[jime] + "'></input></form><table cellpadding=20><tbody><tr></tr></tbody></table></div><p id='backtoblog'></p>";
}
butsuff='ime';
}
utd+='</div>';
document.body.innerHTML+=utd;
}

"; ?>

... to help create, within the blog posting webpage content, the HTML skeletal necessaries modelled on how WordPress Visual Synopsis Media Tutorial worked it for Visual Synopsis (Slideshows) functionality which included inhouse "Video" and/or "Animated GIF" media presentations.


Previous relevant WordPress Blog Posting Feature Image Editing Tutorial is shown below.

WordPress Blog Posting Feature Image Editing Tutorial

WordPress Blog Posting Feature Image Editing Tutorial

Yesterday's ...

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

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

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

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

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


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

}
};
}, 4000);
}

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

<?php

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

?>

... calling new Javascript function ...

<?php echo "

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

"; ?>

Other than header.php WordPress PHP code we changed ...


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

One Image Website Image Snapshot Editing Tutorial

One Image Website Image Snapshot Editing Tutorial

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

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

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

And then there was "the unknown factor" ...

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

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


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

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

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

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

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

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

... talking about the three appended spaces needed.


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

One Image Website SessionStorage Image Filtering Tutorial

One Image Website SessionStorage Image Filtering Tutorial

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

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

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

Aaaaaahhhhh

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

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


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

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

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

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

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

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


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

... or ...


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

... or ...


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

... or ...


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

... or ...


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

... or ...


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

... or ...


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

Did you know?

All this begs the question ...

What about mobile?

Well, at least for iOS we think ...


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

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


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

One Image Website Scrolling Position Fix Tutorial

One Image Website Scrolling Position Fix Tutorial

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

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


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

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

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


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

One Image Website VTT Tracks Tutorial

One Image Website VTT Tracks Tutorial

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

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

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

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

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

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

This amounted to Javascript changes, as per ...

index.htm ...


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

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


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

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

function rotateImage(place) {

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

anotherNew();

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

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

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

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

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

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

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

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

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

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

}
}

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

function tracks(iois) {
}


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

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


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

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Ffmpeg Log Helper Towards VTT File Primer Tutorial

Yesterday's One Image Website iOS Radio Music One Less Tutorial set us on an "off to the side, but eventually forward" project that intertwines ...

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

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

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

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

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

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


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

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


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

One Image Website iOS Radio Music One Less Tutorial

One Image Website iOS Radio Music One Less Tutorial

Yesterday's One Image Website iOS Radio Music Tutorial "Stop Press" promised ...

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

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

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

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


function rotateImage(place) {

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

anotherNew();

var foreground=document.getElementById(place);


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


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

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

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


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

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



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

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

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


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

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

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

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

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

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

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

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

Stop Press

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


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

One Image Website iOS Radio Music Tutorial

One Image Website iOS Radio Music Tutorial

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


"The Commute"

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

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

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


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

     

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


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

    ... to arrive at the calling window ...

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

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

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

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


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


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


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

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

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


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

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

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

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

Stop Press

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


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

Responsive Web Design Landing Page Image Map Tutorial

Responsive Web Design Landing Page Image Map Tutorial

The recent Responsive Web Design Landing Page Incarnation Tutorial said ...

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

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

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

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

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

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

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

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

<?php echo "

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

"; ?>

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

<?php echo "

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

}

"; ?>

... to call on that new PHP ...

<?php

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

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

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

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

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

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


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

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

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

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



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

exit;
}

?>

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

<?php echo "

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

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

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

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


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

"; ?>

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

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

... we all excluded from new functionality Image Map potential "dark green area clicking" access to photography themed "One Image Websites" ...

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

<?php echo "

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

"; ?>

... 57.


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

Responsive Web Design Landing Page Incarnation Tutorial

Responsive Web Design Landing Page Incarnation Tutorial

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

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

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

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

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


Previous relevant Responsive Web Design Primer Tutorial is shown below.

Responsive Web Design Primer Tutorial

Responsive Web Design Primer Tutorial

Today we wanted to tip our toes into the vast subject of "responsive web design" ...

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

... coming at it from the idea "Can a responsive shell webpage host a non-responsive iframe?"

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

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

    ... as food for (your) thought ...


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

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

Camera App on iOS Revisit Tutorial

Camera App on iOS Revisit Tutorial

Camera App on iOS Revisit Tutorial

Mobile apps “out of the box” are quite likely to change with each, in our case, iOS, upgrade. Sometimes nuanced changes pass you by, unless you are into reading the “fine print” on each upgrade’s documentation, that is.

For that reason, we occasionally revisit the big such “out of the box” apps and …

  • 99% of the time that is just to use them in the usual way … but yesterday …
  • we did it for the “more intense peruse” to take notice of what might be new to us, which we do … ah, let’s see … 100 – 99 = ? … 1% of the time

… as might have been the case when we presented Camera Pinch Tutorial talking specifically about the great iPhone iOS Camera app.

The iOS Camera app’s top right “six dots” menu …

suboptions caught our eye …

  • filter
  • styles
  • aspect

… which we played around with, and are presenting our findings with today’s animated GIF presentation. In amongst all that we thought we’d like to hone in on iOS Camera app’s …

Noir Cool (smallest aspect)

… sticking to the order above, and see whether we can get at all close using …

  • HTML img … element …
  • CSS styling

… to recreating the effect. We asked Google …


recreating Noir Cool using CSS filters

… which was helpful thanks, and then we asked Google …


recreating small aspect using CSS

… which was also helpful thanks, and then we constructed a web application for you to try out the concepts we are getting at here with a first draft Noir Cool (small aspect) simulation web application …


Previous relevant Camera Pinch Tutorial is shown below.

Camera Pinch Tutorial

Camera Pinch Tutorial

Further to the recent New Temporary Folder Arrangements PHP Primer Tutorial we think, perhaps, we can explain …

Nala! Luna! Is there something going on with summer grasses?!

We saw our first stink bug of the summer season! Yayyyyy! Now, we know we may have offended some gardeners out there, but we find it comforting seeing any of …

  1. Stink Bugs … the sighting was of a Bronze Orange Bug sulciventris
  2. Christmas Beetles … Anoplognathus pallidicollis
  3. Bogong Moths … Agrotis infusa

… as a reminder of our eastern Australian summers and that they are still around! Yayyyyy! Because it is a little concerning how little happens on the car windscreen these days insect wise compared to the nineties and into the noughties.

Huh?! Thanks, Nala, Luna! You’ve finished in the summer grasses?! And yes, you want to get to the point? Yes, and you’ve been watching Skippy …

… summer reruns, perhaps?! Huh?!

Yes … well … there you go. Yes, we wanted to … um … point out … in terms of photographic technique … in terms of the digital realm … shall we say …

Okay, Skip … getting there

… let’s just say …

Isn’t the pinch gesture on the Camera app just “the bee’s knees”?

And yes, Skip, bees have knees … before you complain! Sheeesshhh!

Photographing insects …

  • has to have gotten more convenient being out and about with a Camera app, whether that be iOS or Android or whattevvvvvvvveeeerrrr … with the ease of pinch gesture usage when shaping to take the photo … and yet …
  • in the Single Lens Reflex dominance days (of Photography) we’d have had …
    1. much much longer telephoto and/or zoom lenses
    2. tripods
    3. shutter clickers (from a distance)
    4. perhaps more patience
    5. perhaps darkroom enlargement opportunities

    … counteracting that convenience … but yes, you can accessorize?!

One thing is for sure, and that is that you should not feel alone delving into the Citizen Science scene. It is growing … and practising fiercely .


Previous relevant New Temporary Folder Arrangements PHP Primer Tutorial is shown below.

New Temporary Folder Arrangements PHP Primer Tutorial

New Temporary Folder Arrangements PHP Primer Tutorial

Things around here have come to a “pretty pass” …

  • primer tutorials that are not first in the thread
  • presenting the tidying arrangements first

Nala! Luna! Is there something going on with summer grasses?!

Yes, this transitioning from /tmp to /home/rjmprogr has us trying not to rush, because rushing can be associated with places where you assume …

… rather than prepare and study. Besides, Akela said no!

Why choose /home/rjmprogr ?

  1. it can be read and written to by the RJM Programming web server username … and yet …
  2. cannot be referenced by users surfing the net … being lower down the directory tree than the /home/rjmprogr/public_html which corresponds to our Apache Document Root folder
  3. it can be read and written to by the cPanel username … meaning …
  4. our web server’s main functioning crontab scheduling can reference it, like with yesterday’s New Temporary Folder Arrangements Tidying Tutorial

And so, today, building on the themes of yesterday’s New Temporary Folder Arrangements Tidying Tutorial we …

… as our first PHP foray into this work.

More to come regarding /home/rjmprogr as our new “temporary file place of preference” for sure.


Previous relevant New Temporary Folder Arrangements Tidying Tutorial is shown below.

New Temporary Folder Arrangements Tidying Tutorial

New Temporary Folder Arrangements Tidying Tutorial

We’ve had one public and three private dedicated virtual servers running our Apache/PHP/MySql web server here at RJM Programming. The last two have us transitioning from one AlmaLinux web server to another. What could be different? Well (readers who resist reading blog posting titles) security measures move on with a lot of upgrades and migrations in web server “land” these days. On ours, the use of …


/tmp

as per


# df -k /
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/vda1 103019024 58818836 38940980 61% /
# df -k /tmp
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 4054752 1108 3843932 1% /tmp
#

… have in the last AlmaLinux web server incarnation become more contentious in that the RJM Programming web server username (as distinct from the administrator of cPanel username) is unable to write to this /tmp for the first time. This is a little bit of a peeve for us, as we have written quite a bit of PHP that uses it to read and write from, as it’s temporary storage “place of choice”.

There’s no way we are going to rush to remedy this, but, today, after self-ruling out, after discussion with our web hosters, Crazy Domains, the thought of changing any file permissions here, we’re starting, sort of at the back end of the issue, fixing for the future …

  • crontab # ie. scheduled …
  • file tidying (after PHP action) processes

You can glean what we did via watching today’s tutorial animated GIF presentation, but the gist of it involved …

  • in RJM Programming cPanel’s Terminal window …

    crontab -l | grep '/tmp'

    … and copy into a text buffer …
  • back in the macOS MacBook Air desktop application woooorrrrllllddd paste into a TextWrangler editor new file … and then …
  • for relevant records substitute /tmp for /home/rjmprogr (as our new choice of place to act as the temporary storage “place of choice” and which we successfully road tested when we presented the Message Board One Liners Aesthetics Tutorial (with it’s, early days, changed prepend.php) thread of blog postings)
  • change the minutes field 10 less for all such records
  • copy this into a buffer
  • back at RJM Programming cPanel’s Terminal window …

    crontab -e

    … ours uses the great vi editor where we get to the end character and type “i” for insert in order to Paste (via top menu) into the crontab file … followed by “wq” to save (with all being well will result in …

    crontab: installing new crontab

    )

  • readying ourselves for either “tidying up” requirement into the future

Over to you … PHP!

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


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


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


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

Posted in eLearning, Event-Driven Programming, Hardware, Installers, iOS, Photography, Software, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Shower Songs Colour Coding Tutorial

Shower Songs Colour Coding Tutorial

Shower Songs Colour Coding Tutorial

YouTube API Songname Providence Shower Songs Tutorial of recent times had us interfacing …

  • song providence via Wikipedia ideas … with …
  • our inhouse Shower Songs project using YouTube API means to “Radio Play” some, let’s say, “theatrical pursuits by the water”

A couple of times now, we’ve used it as company in the bath via an iPhone, preparing the list ahead of ever having to tap another anything, to hear some songs in the sequence the user establishes ahead of time … ie. the purpose of this web application.

However, we made some bad colour choices, especially regarding the mobile red button overlayed by black text containing the song title. It was hard to see. It is easier now, that text being yellow.

While there, we decided on a pale green background colour to apply to the textarea user interactive input and progress displaying conduit, when it’s relevant YouTube video is playing (in audio stream only mode), and another principle of our Shower Songs logic is that you should only see one pale green textarea for any great period of time … ie. the songs play in sequence, and looping around in continuous play, like on the radio.

Believe it or not, the actual top level hierarchy Shower Songs window needs no changes for this, but …

  • the changed

    <script type=text/javascript>
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval('' + navigator.maxTouchPoints) > 0) {
    if (window.parent != window.self) {
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    document.write('<div><sty' + 'le> button { color: yellow !important; font-weight: bold !important; text-shadow: -1px 1px 1px #e52dff !important; } </sty' + 'le></div>');
    }
    }
    }
    </script>
    </body>

    karaoke_youtube_api.htm inhouse YouTube video interfacer helps with the yellow font via CSS … while with the supervised we have …
  • a changed two scenario Javascript situation …

    // textarea gets a pale green background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='#F0FFF0';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + secscnt + '/' + duration + ' ... ' + 'P=pause/play S=stop M=mute U=unmute Y=YouTube G=Google W=Wikipedia L=loop ';
    //
    // textarea gets usual white background
    if (('' + top.document.URL).indexOf('/shower_songs.htm') != -1 || ('' + parent.parent.document.URL).indexOf('/shower_songs.htm') != -1) {
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).style.backgroundColor='white';
    }
    parent.parent.document.getElementById(location.hash.replace(/\#/g,'')).placeholder='' + Math.round(cen) + '/' + duration + ' ... ' + 'P=play/pause S=stop M=' + mletter + 'ute U=' + uletter + 'nmute Y=YouTube G=Google W=Wikipedia L=loop' + psuf;

    … where stop_start_youtube.html controls those textarea element background colours in that grandchild YouTube API inhouse interfacer

… were needed to make this colour coding logic happen to improve how the user uses this web application, we’re hoping. Ie. bye for now.

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

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