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

Just Javascript Five Hundred Card Game Tutorial

Just Javascript Five Hundred Card Game Tutorial

Just Javascript Five Hundred Card Game Tutorial

Onto yesterday’s Just Javascript Memories SVG Emoji CSS Animation Tutorial, today, we add on …

  • a pared down version of the card game “500” … featuring …
  • no bidding …
  • no Jokers (yet) …
  • left and right bowers (Jack trumps, Jack other same colour) as the top two cards …
  • for 2 to 25 players …
  • Player 1 leads off first

… the cards dealt out in turn to users and the next card turned over to determine trumps.

It’s early days for the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows). As such, we anticipate improvements to this first venture into card games that “turn on the winning of tricks”.


Previous relevant Just Javascript Memories SVG Emoji CSS Animation Tutorial is shown below.

Just Javascript Memories SVG Emoji CSS Animation Tutorial

Just Javascript Memories SVG Emoji CSS Animation Tutorial

There are lots of styles of animation that do not suit a “Just Javascript” (ie. “No Body Definition”) style of web application as for Just Javascript Memories SVG Emoji Background Tutorial‘s work, but there is one left that can really help add some excitement and colour to the whole project, that being the use of CSS @keyframes Animation techniques.

You’d be amazed how widespread it is regarding the CSS property animation availability we found at Animatable CSS properties, thanks, from colour through aesthetics to positioning and sizing of webpage content.

We decided the way we’d apply some animation was to, between the first and second selection of cards in the Memories game, for any user, we’d add a bit of tension by some mild animated movement applied to the multiple background images. Yes, animations can happen for multiple background images, even variable amounts of change for each single background image part, if you like, but we applied the same movement to every part of the background image components.

We also animated some aesthetics via some CSS filter application, as per …


if (nominal_numplayers) {
defstyle=defstyle.replace('} </style>', ' animation: animatedBackground 10s linear infinite; } @keyframes animatedBackground { from { filter: contrast(175%) brightness(120%) saturate(70%); } to { filter: contrast(95%) brightness(90%) saturate(150%); } } </style>');
}

… that can be built upon by a possible second layer of animation (and plain straight background colour randomness) via the document.head.innerHTML+=bpmore(defstyle); use of …


function bpmore(incss) {
var cgcols=['lime','maroon','lightblue','purple','navy','teal','fuchsia','olive','red','lightgreen','darkorange','pink','orange','yellow'];
var icg=eval(0 + Math.floor(Math.random() * cgcols.length));
var mvt=eval(10 + Math.floor(Math.random() * 40));
var kf=" @keyframes animatedBpos { from { background-position: bp1; } to { background-position: bp2; } } ";
var inkf="", jnkf="", jnkfd="", nn=0;
var inks=[];
if (incss.indexOf('} </style>') != -1) {
if (incss.indexOf('background-position:') != -1) {
inkf=incss.split('background-position:')[1].split(';')[0].trim();
inks=inkf.split(',');
for (nn=0; nn<inks.length; nn++) {
if (('' + inks[nn]).indexOf(' ') != -1) {
if (('' + inks[nn]).indexOf('px') != -1) {
jnkf+=jnkfd + eval(mvt + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[0])) + 'px ' + eval(30 + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[1])) + 'px';
} else {
jnkf+=jnkfd + eval(mvt + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[0])) + '% ' + eval(30 + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[1])) + '%';
}
} else {
jnkf+=jnkfd + inks[nn];
}
jnkfd=',';
}
if (incss.indexOf('} @keyframes ') != -1) {
return incss.replace('yellow',cgcols[icg]).replace('} @keyframes ', ' animation: animatedBpos 10s linear infinite; }' + kf.replace('bp1', inkf).replace('bp2', jnkf) + ' @keyframes ');
} else {
return incss.replace('yellow',cgcols[icg]).replace('} </style>', ' animation: animatedBpos 10s linear infinite; }' + kf.replace('bp1', inkf).replace('bp2', jnkf) + ' } </style>');
}
}
}
return incss;
}

For more colour and pizazz try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories SVG Emoji Background Tutorial is shown below.

Just Javascript Memories SVG Emoji Background Tutorial

Just Javascript Memories SVG Emoji Background Tutorial

Yesterday’s Just Javascript Memories SVG Emoji Cursor Tutorial had good and bad news related to SVG Emoji Cursors?

  • the bad news is that this CSS cursor concept does not work on mobile platforms for similar reasons to why onmouseover does not work … to hover over the mobile device screen means nothing to event logic … while …
  • the good news is that the same type of data-uri of SVG content can work for a (mobile CSS) background image as it can work for (non-mobile CSS) cursor

… and so we can show, ahead of time, via a background image, news about the Memories game on mobile platforms (that are missing that CSS cursor methodology of showing similar information) … as per


var dhi='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
covercover=',80px 60px,80px 60px';
prevsb=String.fromCodePoint(10067,10068) + csuff;
dhi='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
document.head.innerHTML+=dhi;
} else {

document.head.innerHTML+='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
}

… used as per code exemplified by


if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else {

defstyle=defstyle.replace(';background-size:', ',no-repeat,no-repeat' + ';background-size:');
}
if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + opc.style.cursor.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + dhi.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else {

defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(//www.rjmprogramming.com.au' + backi + '); } </style>'); // + ' ' + owidth + ' ' + oheight
}

So yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories SVG Emoji Cursor Tutorial is shown below.

Just Javascript Memories SVG Emoji Cursor Tutorial

Just Javascript Memories SVG Emoji Cursor Tutorial

The “Memories” functionality introduced in yesterday’s Just Javascript Memories Card Game Tutorial is a game component, and it is good to remember the “game” side to that. If a web application is a game and the player is not being timed, they may feel that freedom to be multitasking, go and do something else, and then come back “to work the game”. In that scenario, it would be quite friendly to offer a mechanism by which to remind the player(s) of the status of the game as they left it.

Even though we are in “Just Javascript” (ie. “No Body Definition”) mode of use here, we still have CSS to offer a solution here, and we’ve chosen in the CSS woooooorrrrrllllllddd to research a curiosity we’ve had “for just about ever”. Can we tailor the webpage “cursor” to be “emoji text content”. We’ve looked this up in the past, and did not succeed on that occasion with the “url([SVGcontent])” we thought might be the go. It was tweaking onto this great link that gave examples for us to succeed this time, thanks, using code such as …


csuff='';
var hjg='' + curplayer;
for (var ipl=0; ipl<hjg.length; ipl++) {
csuff+=String.fromCodePoint(eval(8320 + eval(eval('' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0)) - 48)));
}
if (ocp) { ocp.style.cursor='url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + 'HTTP://www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer'; }

… that “ocp” being the “evt.target” of the “onlick” event logics previously talked about. Notice the fallback to those set cursors of “the cursor wooooorrrrrllllllddd”.

Along the way we offer variations to the playing rules of Memories, too, to add some variety for the user(s).

Yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories Card Game Tutorial is shown below.

Just Javascript Memories Card Game Tutorial

Just Javascript Memories Card Game Tutorial

Up until yesterday’s Just Javascript Card Order Game One Window Tutorial every mode of execution of our web application involved the Javascript prompt (popup) window method of getting information off the user.

Today, though, adding a Memories Card Game new functionality part uses a hybrid Javascript prompt window arrangement …

  • a first usage is to use the default Javascript prompt window arrangement you glean from the user the number of players in the Memories Card Game to follow …
  • and then from then on

    var lasttogglenumber='';
    var lastec='', notyet=false;
    var backi="/rjmquiz_plus.jpg";
    var fiftytwo=52;
    var message='';
    var lastcard='';
    var lasttto='';
    var gamescoreprefix='';
    var gamescores=[0];
    var lasttmid='';
    var lasttfrom='';
    var lasttoggleto='';
    var lasttogglefrom='';
    var curplayer=1, card_of_play=0;
    var card_game='memories';
    var nominal_implication='';
    var nominal_numplayers = (document.URL.replace('?','&').indexOf('&card') != -1) ? prompt('How many players are playing your ' + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(0,1).toUpperCase() + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(1).toLowerCase() + ' card game?', '2') : null;

    if (nominal_numplayers) {
    if (('' + nominal_numplayers).replace('0','').trim() != '' && ('' + nominal_numplayers).replace('0','').trim().indexOf('-') == -1) {
    var prompt = function(zwords, defwords){ return null; };
    nominal_implication=" var prompt = function(zwords, defwords){ return null; }; ";
    fiftytwo=-1;
    backi="/Games/Memories/Memories.jpg";
    } else {
    nominal_numplayers=null;
    }
    }

… “prompt” is overridden as above. That, and overriding the scoring mechanisms, and this same codeset is nearly there towards accommodating our new quite different requirement.

But with “No Body Definition”/”Just Javascript” how can we show and implement this new Memories Card Game usage? It’s a two way integration, the easier one being …

  • offer a place for click/touch on the default background imagery … and with that webpage reminder …
  • what is an independent “add on” event methodology available to us, so as not to interfere with event logic that has preceded? … spoiler alert … double click …

    ele.addEventListener('dblclick', function(evt) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    });

    … (or two clicks quickly in a row) … as per

    var lastec='', notyet=false;


    function antilastec() {
    lastec='';
    }


    function antinotyet() {
    notyet=true;
    }


    ele.addEventListener('click', function(evt) {
    if (evt.touches) {
    if (evt.touches[0].pageX) {
    iourx = evt.touches[0].pageX;
    ioury = evt.touches[0].pageY;
    } else {
    iourx = evt.touches[0].clientX;
    ioury = evt.touches[0].clientY;
    }
    //alert('' + iourx);
    } else if (evt.clientX) {
    iourx = evt.clientX; // - elemLeft;
    ioury = evt.clientY; // - elemLeft;
    } else if (!evt.touches) {
    iourx = evt.pageX; // - elemLeft;
    ioury = evt.pageX; // - elemLeft;
    }
    if (('' + iourx + ',' + ioury) == lastec && lastec != '' && notyet) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    } else if (lastec == '') {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    } else {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    }

    clickedmaybe();
    });

Again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game One Window Tutorial is shown below.

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

The “one window” rather than (52 + 1) = 53 windows scenario set up as a possibility with yesterday’s Just Javascript Card Order Game Mobile Tutorial had us wondering …

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

… and tomorrow is today. We’ve decided not to make the one window scenario the default for non-mobile platforms, but serve as a fallback for some of the scenarios mentioned below …

  • the user gets blocked from using the popup windows on their non-mobile platform web browser … big possibility!
  • the user clicks half way through the popup window incarnation the parent window … all the child popups disappear behind … annoying … so

    var flexible=false;

    function secsu() {
    var ewd;
    if (secs == 0) {
    if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    flexible=false;
    } else {
    flexible=true;
    console.log('Flexible=T');
    }

    setTimeout(blater, 2500);
    }
    if (eval('' + overallgoes) < 52) {
    secs++;
    } else if (document.title.indexOf('Congratulations') == -1) {
    document.title+=' ... Congratulations! End of Game! Refresh webpage to try again.';
    }
    var decs=document.title.split('.');
    if (eval('' + decs.length) >= 3) {
    document.title=document.title.replace('.' + decs[2].split(' ')[0] + ' ', '.' + secs + ' ');
    } else {
    ps=document.title.split('/')[0].trim();
    pg=document.title.split('/')[1].split(' ')[0];
    if (ps.indexOf('.') == -1 || pg.indexOf('.') == -1) {
    ps=eval('' + overallscore + '.' + psecs); //eval(document.title.split('/')[0].trim());
    pg=eval('' + overallgoes + '.' + secs);
    document.title=document.title.replace(document.title.split(' ')[0], '' + overallscore + '.' + psecs + '/' + '' + overallgoes + '.' + secs);
    //console.log('document.title becomes ' + document.title);
    } else {
    ps=eval(ps);
    pg=eval(pg);
    }
    }


    if (flexible) {
    if (document.hasFocus()) {
    flexible=false;
    console.log('Flexible=F');
    lastzkq='';
    lastzkl='';
    owidth=oowidth;
    oheight=ooheight;
    for (var igh=0; igh<oplist.length; igh++) {
    opltlistl[igh]=oopltlistl[igh];
    opltlistt[igh]=oopltlistt[igh];
    if (oplist[igh]) {
    console.log('Flexible=F' + igh);
    if (!oplist[igh].closed) {
    try {
    oplist[igh].close();
    oplist[igh]=null;
    } catch(ewd) {
    }
    } else {
    oplist[igh]=null;
    }
    }
    }
    }
    }

    }

… document.hasFocus() to the rescue again … the multiple background images of yesterday’s work being a default part of any incarnation, and whether the click event logic of yesterday becomes relevant depends on …

  • if user is a mobile platform user, always relevant
  • user enters URL with argument like ?onewindow=y then is always relevant … else …
  • a scenario as above means that from that point on, the multiple background image one window click on cards modus operandi becomes relevant

We improve the web browser conditions too, if a non-mobile user “clicks half way through the popup window incarnation the parent window” in that we programmatically close any open child popup windows! Phew!

Feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game Mobile Tutorial is shown below.

Just Javascript Card Order Game Mobile Tutorial

Just Javascript Card Order Game Mobile Tutorial

Yesterday’s Just Javascript Card Order Game Tutorial mobile usage scenario was impractical, in that mobile platforms can not work popup windows in front of a parent window. Can we convert those non-mobile popup windows into … well … what exactly?

Well, in order to keep to our “Just Javascript” (ie. “No Body Definition”) pledge with this project, we needed to simulate those popups as background image parts, in the sense that you can have multiple background images these days with your HTML. Even with html as your CSS styling selector … it pans out … we needed to prove that today.

Also, today, for the first time, we achieved via …

  1. comma separated background-repeat: no-repeat; list
  2. comma separated background-size list (set popup width height list until last one bigger (based on screen.width screen.height) for the parent background image (no-repeat))
  3. comma separated background-position list (as per what window.open in non-mobile was using for left top until last one’s 0px 0px)
  4. comma separated background-image list (as per what window.open in non-mobile was using for URL([imageURL]) until last one’s linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)), url(//www.rjmprogramming.com.au/rjmquiz_plus.jpg))

… as per (the previous “window.open” becomes “windowopen”) …


function windowopen(one, two, three) {
if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
console.log('Here ' + kq);
opltlistl.push((three.split('left=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + one.split('spcp=')[1].split('&')[0]));
opltlistt.push((three.split('top=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + kq));
owidth=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
oheight=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
if (defstyle.indexOf('background: URL(') != -1) {
defstyle=defstyle.split('background: URL(')[0] + 'background-repeat:no-repeat;background-size:' + owidth + 'px ' + oheight + 'px;background-position:' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image: url(' + cards[eval('' + donelist[eval(-1 + donelist.length)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'; // + ' ' + owidth + ' ' + oheight
} else {
defstyle=defstyle.replace(';background-image:', (',' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image:');
defstyle=defstyle.replace('no-repeat','no-repeat,no-repeat');
defstyle=defstyle.replace('background-size:' + owidth + 'px ' + oheight + 'px','background-size:' + owidth + 'px ' + oheight + 'px,' + owidth + 'px ' + oheight + 'px');
defstyle=defstyle.replace('; } </style>', ',url(' + cards[eval('' + donelist[eval(0 + ijk)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'); // + ' ' + owidth + ' ' + oheight
}
return null;
}
return window.open(one, two, three);
}

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

We needed to add event logic we were not sure would work at the start of the day, and saw it working by the end, with …


var iourx=-1, ioury=-1;

function blater() {
if (1 == 2 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
window.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
eles = document.querySelectorAll("*")
for (var ele of eles) {
console.log('yes well');
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ele.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('touchmove', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('click', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
ele.addEventListener('click', function(evt) {
if (evt.touches) {
if (evt.touches[0].pageX) {
iourx = evt.touches[0].pageX;
ioury = evt.touches[0].pageY;
} else {
iourx = evt.touches[0].clientX;
ioury = evt.touches[0].clientY;
}
//alert('' + iourx);
} else if (evt.clientX) {
iourx = evt.clientX; // - elemLeft;
ioury = evt.clientY; // - elemLeft;
} else if (!evt.touches) {
iourx = evt.pageX; // - elemLeft;
ioury = evt.pageX; // - elemLeft;
}
clickedmaybe();
//alert('here');
});
}
}
}
}

See this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform) we, again, welcome you to try for yourself.


Previous relevant Just Javascript Card Order Game Tutorial is shown below.

Just Javascript Card Order Game Tutorial

Just Javascript Card Order Game Tutorial

Today we’ve made the web application of yesterday’s Just Javascript Quiz Drag Tutorial “dual purpose” …

  • quiz … as for yesterday, and before … and as of today, making more use of the card organizational side to the popup windows we introduce …
  • card order game

This card order game asks you to force the focus of the correct popup window (to score in the Card Order Game) in the order as designated by the background image part we have added today, and supported by the following Javascript “mapping” code …


var dragorder=[], curdrag=0;

var cards=["//www.rjmprogramming.com.au/images/01s.gif?n=7",
"//www.rjmprogramming.com.au/images/02s.gif?n=16",
"//www.rjmprogramming.com.au/images/03s.gif?n=33",
"//www.rjmprogramming.com.au/images/04s.gif?n=29",
"//www.rjmprogramming.com.au/images/05s.gif?n=8",
"//www.rjmprogramming.com.au/images/06s.gif?n=35",
"//www.rjmprogramming.com.au/images/07s.gif?n=52",
"//www.rjmprogramming.com.au/images/08s.gif?n=51",
"//www.rjmprogramming.com.au/images/09s.gif?n=12",
"//www.rjmprogramming.com.au/images/10s.gif?n=30",
"//www.rjmprogramming.com.au/images/11s.gif?n=1",
"//www.rjmprogramming.com.au/images/12s.gif?n=36",
"//www.rjmprogramming.com.au/images/13s.gif?n=22",
"//www.rjmprogramming.com.au/images/01h.gif?n=32",
"//www.rjmprogramming.com.au/images/02h.gif?n=23",
"//www.rjmprogramming.com.au/images/03h.gif?n=3",
"//www.rjmprogramming.com.au/images/04h.gif?n=18",
"//www.rjmprogramming.com.au/images/05h.gif?n=28",
"//www.rjmprogramming.com.au/images/06h.gif?n=39",
"//www.rjmprogramming.com.au/images/07h.gif?n=45",
"//www.rjmprogramming.com.au/images/08h.gif?n=48",
"//www.rjmprogramming.com.au/images/09h.gif?n=50",
"//www.rjmprogramming.com.au/images/10h.gif?n=44",
"//www.rjmprogramming.com.au/images/11h.gif?n=4",
"//www.rjmprogramming.com.au/images/12h.gif?n=9",
"//www.rjmprogramming.com.au/images/13h.gif?n=5",
"//www.rjmprogramming.com.au/images/01d.gif?n=27",
"//www.rjmprogramming.com.au/images/02d.gif?n=41",
"//www.rjmprogramming.com.au/images/03d.gif?n=20",
"//www.rjmprogramming.com.au/images/04d.gif?n=11",
"//www.rjmprogramming.com.au/images/05d.gif?n=37",
"//www.rjmprogramming.com.au/images/06d.gif?n=49",
"//www.rjmprogramming.com.au/images/07d.gif?n=42",
"//www.rjmprogramming.com.au/images/08d.gif?n=6",
"//www.rjmprogramming.com.au/images/09d.gif?n=21",
"//www.rjmprogramming.com.au/images/10d.gif?n=31",
"//www.rjmprogramming.com.au/images/11d.gif?n=40",
"//www.rjmprogramming.com.au/images/12d.gif?n=43",
"//www.rjmprogramming.com.au/images/13d.gif?n=17",
"//www.rjmprogramming.com.au/images/01c.gif?n=46",
"//www.rjmprogramming.com.au/images/02c.gif?n=19",
"//www.rjmprogramming.com.au/images/03c.gif?n=47",
"//www.rjmprogramming.com.au/images/04c.gif?n=25",
"//www.rjmprogramming.com.au/images/05c.gif?n=10",
"//www.rjmprogramming.com.au/images/06c.gif?n=15",
"//www.rjmprogramming.com.au/images/07c.gif?n=13",
"//www.rjmprogramming.com.au/images/08c.gif?n=26",
"//www.rjmprogramming.com.au/images/09c.gif?n=38",
"//www.rjmprogramming.com.au/images/10c.gif?n=34",
"//www.rjmprogramming.com.au/images/11c.gif?n=2",
"//www.rjmprogramming.com.au/images/12c.gif?n=14",
"//www.rjmprogramming.com.au/images/13c.gif?n=24"];


for (var ic=1; ic<=cards.length; ic++) {
found=false;
for (var jc=1; jc<=cards.length; jc++) {
if ((cards[eval(-1 + jc)] + '~').indexOf('?n=' + ic + '~') != -1) {
dragorder.push(eval(-1 + jc));
cards[eval(-1 + jc)]=cards[eval(-1 + jc)].replace('?n=' + ic, '');
firstbit+=String.fromCodePoint(eval('' + spcps[eval(-1 + jc)].split('/')[0])) + ' ';
found=true;
}
}
}

… and “making use of” this and the new codeline as popups are created … oplist[eval(-1 + oplist.length)].document.name=” + kl; we have …


function ourprompt(tw, blb, bdef) {
var kijk;
if (oplist[eval('' + tw)].document.name == ('' + dragorder[eval('' + curdrag)]) && eval('' + curdrag) == eval('' + overallgoes)) {
console.log('Dragorder[' + curdrag + ']=' + dragorder[eval('' + curdrag)] + ' vs tw=' + tw + ' and overall;goes=' + overallgoes);
var decs=document.title.split('.');
curdrag++;
overallgoes++;
if (eval('' + decs.length) >= 3) {
document.title=document.title.replace('.' + decs[1] + '.', '.' + curdrag + '/' + overallgoes + '.');
}
oplist[eval('' + tw)].close();
return null;
}

// Quiz only code follows
}

… code.

It must be in the correct order (and not interrupted by quiz answer completions) to score, and you are timed, so you can try improving over time, using a document.title score presentation as per …


[QuizScore].[CardOrderGameScore]/[QuizAnswerAttemptCount].[SecondsElapsed] [MultiPlayerQuizScoreGoesBreakdown] is User: Score/Goes - RJM Programming - April, 2021

… so that both usages for the web application can be accommodated for in the changed cards_usefocus.html code behind the “Just Javascript” live run we welcome you to try for yourself.


Previous relevant Just Javascript Quiz Drag Tutorial is shown below.

Just Javascript Quiz Drag Tutorial

Just Javascript Quiz Drag Tutorial

Adding to yesterday’s Just Javascript Quiz CSS Styling Tutorial we have added some …

  • non-mobile platform, only …
  • drag and drop functionality … for …
  • the child popup windows

… achieved through the comparison of …

  • original [popupWindow].screenLeft and [popupWindow].screenTop … initially, to …
  • [popupWindow].screenLeft and [popupWindow].screenTop over time

… and if one popup is dragged to overlay another it is closed, or you, as the user, can just drag and drop for clarity, leaving the popup window of the next quiz question out in the open, perhaps.

In order to achieve this, and keep backward compatibility we needed to delay the quiz question prompt window via …

  1. document.hasFocus() is true … then if …
  2. inhouse dragging checks clear it of overlaying another popup (in which case that popup is programmatically closed, allowing another popup to become the “focus window”) … then …
  3. delay (by 8 seconds) the prompt window (and in that time the user can be dragging popups (but no popups were harmed in the making of this tutorial)) … via …

    setTimeout(function() { hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } else { hj=window.opener.assess(hj); } if (hj.replace(def,'') != '') { checka(hj); } else { setTimeout(pa,10000); } aminmiddle=false; }, 8000);

… you can see in amongst the changed cards_usefocus.html code behind the “Just Javascript” live run you are welcome to try for yourself … best on non-mobile.

Still “No Body Definition”, “Just Javascript”!


Previous relevant Just Javascript Quiz CSS Styling Tutorial is shown below.

Just Javascript Quiz CSS Styling Tutorial

Just Javascript Quiz CSS Styling Tutorial

Our “Just Javascript” adage used throughout this blog posting thread, up until today, headed by yesterday’s Just Javascript Quiz Content Management Tutorial needs more explanation. Really what we are trying to do might better be described as “No Body Definition” (ie. no defined document.body) but have …

  1. an HTML webpage (ie. within <html> and </html>) … has …
  2. <head> and </head> (ie. document.head) content which can be made up of (at least) title, style, script, link, meta tags

To assert “Just Javascript” is just to allow script content above, but what we should really say is “Just Head Content” but that is not nearly so marketable, is it now?!

The thing is, though, we can dynamically add title, style, link, meta tag content within the script content, and we do this more than statically define it, to feel better about our ethics saying “Just Javascript”.

Dynamically adding style CSS styling either …

  • using Javascript DOM (not available to us for document.getElementById([elementID] and nor can we use inline CSS via style=”[CSSstyling]” statically within HTML element code for that same reason) ideas today though … remember “No Body Definition” … but …
  • we can append to <head> and </head> (for today’s scenario) as per …

    document.head.innerHTML+="<style> html { background-color: yellow; font-size: 36px; background: URL('//www.rjmprogramming.com.au/rjmquiz.jpg'); background-size: cover; } </style>";

… allowing (into the scope of our work CSS styling of) background (image(s)) and other background styling ideas that can get us past the anonymous feel the web application had before today. We tailored the background image above to suit our Quiz and help it be a bit more self explanatory … thanks CSS styling! We add onto the child “card” popup windows, their own background image colour and pizazz, to cheer things up in CSS styling enhanced cards_usefocus.html code behind the “Just Javascript” live run.

You may well ask …

What can we hang our hat on with CSS style selectors without a body element?

Well, we had to step out of our usual comfort zone of CSS styling thinking, and realize, even without that body element we can still use the html selector to “point at” the entirety of your webpage of interest.


Previous relevant Just Javascript Quiz Content Management Tutorial is shown below.

Just Javascript Quiz Content Management Tutorial

Just Javascript Quiz Content Management Tutorial

It feels like an “onions of the 4th dimension” idea to allow the user to control the questions and answers behind the workings of yesterday’s Just Javascript Quiz Multiple Users Tutorial‘s web application, featuring “Just Javascript”.

It’s not “Just Javascript” we’re keeping, it’s “Just HTML” client work rather than involving any serverside anything (eg.PHP) and yet this question and answer data could be quite sizeable. What can we use, given no PHP serverside, and given we’ve decided not to navigate via Ajax/FormData techniques? How about “the better than HTTP Cookies” twins …

Yep, set up a means by which these two can store and restore questions and answers entered by the user, using these storage methods above.


function reassess() {
var retv='', ewq;
var retcols=[];
var ir=0;
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '') {
//alert('0:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?!')[0] + '?');
asq.push(retcols[ir].split('?!')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '') {
//alert('1:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?')[0] + '?');
asq.push(retcols[ir].split('?')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
}


function assess(what) {
var ewq, retv='';
if (what.toLowerCase() == '?x') {
sslistq=[];
sslista=[];
if (window.sessionStorage) {
try {
window.sessionStorage.removeItem('cards_usefocus_session');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase() == '?!x') {
lslistq=[];
lslista=[];
if (window.localStorage) {
try {
window.localStorage.removeItem('cards_usefocus_local');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase().indexOf('?!') != -1) {
if (what.toLowerCase() == '?!') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.localStorage) {
if (lslistq.length == 0) {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', encodeURIComponent(what));
} else {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', window.localStorage.getItem('cards_usefocus_local') + encodeURIComponent('~' + what));
}
}
return '';
} else if (what.toLowerCase().indexOf('?') != -1) {
if (what.toLowerCase() == '?') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.sessionStorage) {
if (sslistq.length == 0) {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', encodeURIComponent(what));
} else {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', window.sessionStorage.getItem('cards_usefocus_session') + encodeURIComponent('~' + what));
}
}
return '';
} else {
firstbit='';
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
}
return what;
}

The fairly significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz Multiple Users Tutorial is shown below.

Just Javascript Quiz Multiple Users Tutorial

Just Javascript Quiz Multiple Users Tutorial

Adding to yesterday’s Just Javascript Quiz via Cards Tutorial we were surprised how difficult it was to stay with “Just Javascript” and allow for multiple player play.

We didn’t opt for the parent to ask about the number of players, curiously, but on the second quiz answer and on, offered any non first player the chance to identify themselves as a new player into the game by appending their answer with a space character.

The implication of that is that we’ll want to run Javascript functions of the parent from the children as per


oplist[eval(-1 + oplist.length)].document.write("<link rel=icon href=" + cards[kl] + "><scr" + "ipt type='text/javascript'> var da='" + eval(0 + kq) + "'; var dp='Given answer is integer from 0 to 25 ... " + sq[kq] + "'; var def=String.fromCodePoint(" + spcps[eval('' + kl)].split('/')[0] + "); function checka(tpa) { var os=''; var ps=eval(window.opener.document.title.split('/')[0].trim()); var pg=eval(window.opener.document.title.split('/')[1].split(' ')[0]); if (tpa.trim() == da) { ps++; os=tpa.split(da)[1]; } else { pg++; os=tpa.split(tpa.trim())[1]; } window.opener.document.title=ps + os + '/' + pg + ' is User Score/Goes'; window.close(); } function pa() { if (document.hasFocus()) { var hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } if (hj.replace(def,'') == '') { setTimeout(pa,1000); } else { checka(hj); } } else { setTimeout(pa,1000); } } pa(); </scr" + "ipt>");

… accessing …


function blurb() { // theblurb and wblurb are global variables changed elsewhere
if (wblurb == ' Hello Player 1' && theblurb == ' If you are player 2 rather than player 1 append space to your answer.') {
theblurb='';
wblurb='';
}
return theblurb + wblurb;
}

… giving the rather curious behaviour whereby a Javascript prompt window can be dynamically different from one document.hasFocus() incarnation (ie. the user might go away and answer another “card” Number Quiz question) to another (even not attending to answering the Javascript prompt window) … huh?!

The significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz via Cards Tutorial is shown below.

Just Javascript Quiz via Cards Tutorial

Just Javascript Quiz via Cards Tutorial

Yesterday’s Just Javascript Navigation Tutorial continues our interest in “Just Javascript” (or “No Body”) web applications.

We think today’s “Numbers Quiz” via a “Card Deck” organizational design ups the ante on all this. We realize now what we have been missing not having involved document.hasFocus() in any of our popup window scenarios. Today, at least on non-mobile, we involve 52 such popup windows each containing a “Number Quiz” question presented as a Javascript prompt (sub-)window. This would not be feasible without document.hasFocus() as you can tell if you examine the cards_usefocus.html code behind the “Just Javascript” live run best used on your non-mobile platforms where popup windows can sit in front of parent (and beside sibling) windows, whereas mobile platforms open new web browser tabs for all the 52 windows of (a card deck) design.

Look out, too, in the code above, for use of window.opener back reference from a popup window back to the parent window where the scoring data is held, and updated by each popup window because of that window.opener avaalability.


Previous relevant Just Javascript Navigation Tutorial is shown below.

Just Javascript Navigation Tutorial

Just Javascript Navigation Tutorial

The recent use we made of …


document.createElement/click()

… got us thinking of the “Just Javascript” (or No Body) blog posting thread headed by Just Javascript Webmail No Body Attachment Tutorial.

As such, today we present the very simple (but first time use of the interesting hasFocus) “proof of concept” …


<html>
<head>
<script type='text/javascript'>
function dothis() {
var ais=null;
var urlis=' ';
while (urlis != '') {
if (document.hasFocus()) {
urlis=prompt('Enter URL that we will send you to (exit to stop)', '');
} else {
setTimeout(dothis, 2000); // urlis=' ';
return;
}
if (urlis == null) { urlis=''; }
if (urlis.toLowerCase() == 'exit') { return; }


if (urlis.trim() != '') {
if (urlis.substring(0,1) == '.') { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
} else if (urlis.substring(0,1) == '/' && urlis.indexOf('//') == -1) { // relative URL
urlis=document.URL.split('//')[0] + '//' + document.URL.split('//')[1].split('/')[0] + '/' + urlis;
} else if (urlis.split('/')[0].indexOf('.') != -1) { // absolute URL
if (urlis.toLowerCase().indexOf('http') != 0) {
if (urlis.indexOf('//') == 0) {
urlis=document.URL.split('//')[0] + urlis;
} else {
urlis=document.URL.split('//')[0] + '//' + urlis;
}
}
} else { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
}
ais=document.createElement('a');
ais.onclick=function() { window.open(urlis, '_blank', 'top=100,left=100,width=600,height=600'); };
if (1 == 2) { ais.href=urlis; }
ais.target='_blank';
ais.click();
}
}
setTimeout(dothis, 2000); // urlis=' ';
}


dothis();

</script>
</head>
</html>

nobody.html‘s live run link for you to use a Javascript prompt popup window’s user interaction results to navigate to a new webpage, as applicable. Bookmarklets may be scarce on the ground, but these “Just Javascript” ideas continue the Bookmarklet Spirit of the past!


Previous relevant Just Javascript Webmail No Body Attachment Tutorial is shown below.

Just Javascript Webmail No Body Attachment Tutorial

Just Javascript Webmail No Body Attachment Tutorial

A “hard liner” for the proper use of “business emails” could argue that an email without an attachment is not productive. Couldn’t you just have a face to face meeting instead, if there is just wording in the email (as we somewhat concur with, as an argument)? So yesterday’s Just Javascript Webmail No Body Tutorial had that limitation of no email attachment logic, which we remedy today.

And this is where PHP’s wonderful file_get_contents (function) means by which we garner (URL) content …

  • definitely works with “relative URLs” relative to HTTP://www.rjmprogramming.com.au/HTMLCSS/ where today’s unchanged webmail_nobody.html resides … in “parsing parlance” …

    "relative (URL)" to the left of any # or ? of what lies to the left of the most right hand "/" (of what the address bar URL is of the webpage you are on)

    … so that …

    1. “relative URLs” starting with “./” (followed by the filename, or just the filename (as you can see us using in today’s tutorial picture)) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/HTMLCSS/” … whereas, for example …
    2. “relative URLs” starting with “../” (followed by the filename) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/” … for example

    … and …

  • might work for “absolute URLs” (those that start with https: or HTTP: or even // (that we beg you not to confuse with Windows UNC pathnames) that infer a transport protocol of the transport protocol (out of https: or HTTP: or even file:) that got you to the webpage you are currently on), the “might” being far more likely on “absolute URLs” pointing to the same domain as indicated on the URL of the address bar of the webpage you are currently on

Upshot is, the user in their email Body section definitions (still no HTML body though!), can throw into any word they use, an “absolute URL” of interest, or a “relative URL” of interest, of files they want to attach (as attachments, doh!) in their email.

Depending on the email rules though, there are limits as to the amount of attachment data allowed. We’ll leave that to you intrepid “explorers of the Net” to discover for yourselves. On this subject though, have you noticed that with the Photos (or Gallery) app Share options, the Email option drops off when you have highlighted a large number of photos or videos or audios to share? That’s that email limit coming into play.

So feel free to try this HTML-body-less web application live run to see what we mean here. Though the parent HTML is unchanged today, the new (email) attachment functionality needed a changed PHP emailhtml.php to make this happen.

Did you know?

This (relative URL) “../” navigation backwards up the hierarchy of the web server directories will, if repeated (ie. nested to “../../” etcetera) too many times, get you into uncharted unnavigable (web server directory) places relative to that web server web site’s Document Root (below which you can not access in public webpages, normally). But when you perform similar thinking with “absolute URLs” and go “HTTP://www.rjmprogramming.com.au/HTMLCSS/../../../blahdeblah.jpg” (in a web browser address bar) for instance, you cannot get into trouble, as you just don’t get beyond this sending you to (attempt the reference to) “HTTP://www.rjmprogramming.com.au/blahdeblah.jpg” because on this rjmprogramming.com.au Apache domain the correspondence of the Document Root (web server directory) is to “HTTP://www.rjmprogramming.com.au/” as the place you are not allowed (and cannot) go below in the hierarchy tree.


Previous relevant Just Javascript Webmail No Body Tutorial is shown below.

Just Javascript Webmail No Body Tutorial

Just Javascript Webmail No Body Tutorial

Were you around and interested in our series of about three blog postings in the series on the theme of creating webpage functionality of some interest, involving no Javascript, when we presented Missing Javascript Audio on Unmute Tutorial? Well, today, it’s the turn of “just Javascript”, which is sort of like what Bookmarklets were about.

With today’s “just Javascript” we have to qualify that a little for our webmail emailing sender application with the architecture …

  • parent webpage with only document.head and apart from a document.title just a script Javascript tag of content (using Javascript prompt windows to ask for user information) …
  • sending (POSTing) data via …
    1. Ajax XMLHttpRequest object … as the conduit for …
    2. FormData object

    … to our changed

  • PHP communication emailing tool emailhtml.php … and out to …
  • the emailee (out there in the big wide woooorrrrrllllldddd)

Guess we find it interesting that you can do all this (sending of email to emailee recipients) with no document.body in sight.

So take a look at that parent webmail_nobody.html‘s live run link to see what we mean here, and/or watch the video below …


Previous relevant Missing Javascript Audio on Unmute Tutorial is shown below.

Missing Javascript Audio on Unmute Tutorial

Missing Javascript Audio on Unmute Tutorial

Our “third cab off the rank” following on from yesterday’s Missing Javascript Stop Watch Tutorial “missing Javascript” ideas is an HTML div nesting scenario using just …

  1. HTML
  2. CSS

… again, with some or all of the “usuals” below …

  • calc method to assist with defining width and height and size dimensions along with operator “+” and/or “-” offset calculation opportunities, and which we’d have used the Javascript window.getComputedStyle and/or [element].getBoundingClientRect methods to cover this (in a much more unwieldy way, as you would probably surmise)
  • CSS variables we started talking about here at CSS Variables Primer Tutorial
  • CSS3 @keyframes rules we first talked about at CSS3 @keyframes Rule Primer Tutorial that assist with animations that we can make work via …
  • CSS3 transitions for scheduled functionality (we’d have used Javascript setTimeout (and setInterval) methods to cover the same “territory”) we first talked about at CSS3 Transition Primer Tutorial … specified with CSS Criteria involving …
  • CSS Selectors :after and :before (and often, as for today’s work, with the content: CSS property) first talked about here with WordPress Bullet Point CSS Styling Primer Tutorial … and, today …
  • CSS3 transform property’s rotate (and translate and scale) settings (for the puppy dog body movements) … as well as the idea that …
  • On non mobile platforms you can set up the playing of “audio” data via the use of an HTML audio tag with the properties …
    1. controls
    2. autostart
    3. loop
    4. muted

    Stop Press

    Above is all fine and good for non-mobile but not so good for mobile, so to keep all happy with the one click, still, is to transfer HTML coding from …


    <audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" />

    … to …


    <!--audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" /-->
    <audio id='myaudiotwo' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="margin-left:-350px;opacity:0.1;" autostart="0" loop controls src="Puppy-sounds.mp3" />

    … and a src= URL data source (as we thank this link for today), or data URI if preferred (which we do for today’s image data from this link, thanks (when we were researching animated GIF data URIs (which we may return to at a later date))

… that sets up the scenario that all the user has to do to hear the audio is to click the “muted” control button, without needing the usual Javascript play() methods … but not on mobile!

Feel free to let the puppy play, that uses the HTML and CSS (but no Javascript) of the_nested.html and based largely on the previous HTML Nested Centering via Multiple Select Tutorial so that these changes reflect how we got to the first draft of today’s work. Maybe some of the ideas are of interest. We hope so!


Previous relevant Missing Javascript Stop Watch Tutorial is shown below.

Missing Javascript Stop Watch Tutorial

Missing Javascript Stop Watch Tutorial

Following on from yesterday’s Missing Javascript Primer Tutorial our second “cab off the rank” for “missing Javascript” ideas is a stop watch featuring just …

  1. HTML
  2. CSS

… again, setting up document.body load instigated

… which we needed to do to make multiple animations happen, but we used animation-delay:5s; to delay its start. The hands (second and minute, hence the two animations) are “overlay”

… feeling HTML horizontal rule elements that also feature linear gradients, to emphasise (in red) the “pointy end” of the “hand conversation” (good on walls with shadows … but we digress).

Feel free to let loose the stop watch that uses the HTML and CSS (but no Javascript) of stop_watch.html for today’s instructional information. Thanks to Clipart – stop watch for the great clip art used.


Previous relevant Missing Javascript Primer Tutorial is shown below.

Missing Javascript Primer Tutorial

Missing Javascript Primer Tutorial

If you were to ask me which programming component is most vital to web application development, I’d not be Robinson Crusoe in saying …

Without a doubt, Javascript

… and with that thought in mind we have a two pronged motive to see how far we go developing some web applications that “don’t use Javascript”, calling into play the …

  • meaning of “missing”, as in, our code is “missing” Javascript … as well as how I feel with the masochism of the exercise, calling into play the …
  • meaning of “missing”, as in, it’s hard work writing meaningful web applications without Javascript … but I guess we’ll learn a bit from the exercise of “see where we go”, allowing for the fact, not today, but down the track, that we will allow the use of server-side languages such as PHP

Okay, so, given that restriction, let’s see today’s challenge, to just use, in a web application …

  1. HTML
  2. CSS

… and here is where we have to point out that CSS3 introduced to us some functionality that improves the prospects for web application design “interest” without using Javascript (though it is hard to convince me even so, that I am not “missing” Javascript) here. CSS3 introduced to us …

… and we use all of these in our Festive Season themed web application today, you can try at this live run‘s calc_use.html (free of any Javascript (but “why” springs to mind … because it is NOT there, perhaps?)).

Here’s the other thing about today. Our long sought after “just make the body background be semi-transparent” but not its foreground parts, was solved, for us via the great advice of …

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


If this was interesting you may be interested in 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 Animation, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Just Javascript Memories SVG Emoji CSS Animation Tutorial

Just Javascript Memories SVG Emoji CSS Animation Tutorial

Just Javascript Memories SVG Emoji CSS Animation Tutorial

There are lots of styles of animation that do not suit a “Just Javascript” (ie. “No Body Definition”) style of web application as for Just Javascript Memories SVG Emoji Background Tutorial‘s work, but there is one left that can really help add some excitement and colour to the whole project, that being the use of CSS @keyframes Animation techniques.

You’d be amazed how widespread it is regarding the CSS property animation availability we found at Animatable CSS properties, thanks, from colour through aesthetics to positioning and sizing of webpage content.

We decided the way we’d apply some animation was to, between the first and second selection of cards in the Memories game, for any user, we’d add a bit of tension by some mild animated movement applied to the multiple background images. Yes, animations can happen for multiple background images, even variable amounts of change for each single background image part, if you like, but we applied the same movement to every part of the background image components.

We also animated some aesthetics via some CSS filter application, as per …


if (nominal_numplayers) {
defstyle=defstyle.replace('} </style>', ' animation: animatedBackground 10s linear infinite; } @keyframes animatedBackground { from { filter: contrast(175%) brightness(120%) saturate(70%); } to { filter: contrast(95%) brightness(90%) saturate(150%); } } </style>');
}

… that can be built upon by a possible second layer of animation (and plain straight background colour randomness) via the document.head.innerHTML+=bpmore(defstyle); use of …


function bpmore(incss) {
var cgcols=['lime','maroon','lightblue','purple','navy','teal','fuchsia','olive','red','lightgreen','darkorange','pink','orange','yellow'];
var icg=eval(0 + Math.floor(Math.random() * cgcols.length));
var mvt=eval(10 + Math.floor(Math.random() * 40));
var kf=" @keyframes animatedBpos { from { background-position: bp1; } to { background-position: bp2; } } ";
var inkf="", jnkf="", jnkfd="", nn=0;
var inks=[];
if (incss.indexOf('} </style>') != -1) {
if (incss.indexOf('background-position:') != -1) {
inkf=incss.split('background-position:')[1].split(';')[0].trim();
inks=inkf.split(',');
for (nn=0; nn<inks.length; nn++) {
if (('' + inks[nn]).indexOf(' ') != -1) {
if (('' + inks[nn]).indexOf('px') != -1) {
jnkf+=jnkfd + eval(mvt + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[0])) + 'px ' + eval(30 + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[1])) + 'px';
} else {
jnkf+=jnkfd + eval(mvt + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[0])) + '% ' + eval(30 + eval('' + inks[nn].replace(/px/g,'').replace(/\%/g,'').split(' ')[1])) + '%';
}
} else {
jnkf+=jnkfd + inks[nn];
}
jnkfd=',';
}
if (incss.indexOf('} @keyframes ') != -1) {
return incss.replace('yellow',cgcols[icg]).replace('} @keyframes ', ' animation: animatedBpos 10s linear infinite; }' + kf.replace('bp1', inkf).replace('bp2', jnkf) + ' @keyframes ');
} else {
return incss.replace('yellow',cgcols[icg]).replace('} </style>', ' animation: animatedBpos 10s linear infinite; }' + kf.replace('bp1', inkf).replace('bp2', jnkf) + ' } </style>');
}
}
}
return incss;
}

For more colour and pizazz try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories SVG Emoji Background Tutorial is shown below.

Just Javascript Memories SVG Emoji Background Tutorial

Just Javascript Memories SVG Emoji Background Tutorial

Yesterday’s Just Javascript Memories SVG Emoji Cursor Tutorial had good and bad news related to SVG Emoji Cursors?

  • the bad news is that this CSS cursor concept does not work on mobile platforms for similar reasons to why onmouseover does not work … to hover over the mobile device screen means nothing to event logic … while …
  • the good news is that the same type of data-uri of SVG content can work for a (mobile CSS) background image as it can work for (non-mobile CSS) cursor

… and so we can show, ahead of time, via a background image, news about the Memories game on mobile platforms (that are missing that CSS cursor methodology of showing similar information) … as per


var dhi='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
covercover=',80px 60px,80px 60px';
prevsb=String.fromCodePoint(10067,10068) + csuff;
dhi='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
document.head.innerHTML+=dhi;
} else {

document.head.innerHTML+='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
}

… used as per code exemplified by


if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else {

defstyle=defstyle.replace(';background-size:', ',no-repeat,no-repeat' + ';background-size:');
}
if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + opc.style.cursor.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + dhi.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else {

defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(//www.rjmprogramming.com.au' + backi + '); } </style>'); // + ' ' + owidth + ' ' + oheight
}

So yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories SVG Emoji Cursor Tutorial is shown below.

Just Javascript Memories SVG Emoji Cursor Tutorial

Just Javascript Memories SVG Emoji Cursor Tutorial

The “Memories” functionality introduced in yesterday’s Just Javascript Memories Card Game Tutorial is a game component, and it is good to remember the “game” side to that. If a web application is a game and the player is not being timed, they may feel that freedom to be multitasking, go and do something else, and then come back “to work the game”. In that scenario, it would be quite friendly to offer a mechanism by which to remind the player(s) of the status of the game as they left it.

Even though we are in “Just Javascript” (ie. “No Body Definition”) mode of use here, we still have CSS to offer a solution here, and we’ve chosen in the CSS woooooorrrrrllllllddd to research a curiosity we’ve had “for just about ever”. Can we tailor the webpage “cursor” to be “emoji text content”. We’ve looked this up in the past, and did not succeed on that occasion with the “url([SVGcontent])” we thought might be the go. It was tweaking onto this great link that gave examples for us to succeed this time, thanks, using code such as …


csuff='';
var hjg='' + curplayer;
for (var ipl=0; ipl<hjg.length; ipl++) {
csuff+=String.fromCodePoint(eval(8320 + eval(eval('' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0)) - 48)));
}
if (ocp) { ocp.style.cursor='url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + 'HTTP://www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer'; }

… that “ocp” being the “evt.target” of the “onlick” event logics previously talked about. Notice the fallback to those set cursors of “the cursor wooooorrrrrllllllddd”.

Along the way we offer variations to the playing rules of Memories, too, to add some variety for the user(s).

Yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories Card Game Tutorial is shown below.

Just Javascript Memories Card Game Tutorial

Just Javascript Memories Card Game Tutorial

Up until yesterday’s Just Javascript Card Order Game One Window Tutorial every mode of execution of our web application involved the Javascript prompt (popup) window method of getting information off the user.

Today, though, adding a Memories Card Game new functionality part uses a hybrid Javascript prompt window arrangement …

  • a first usage is to use the default Javascript prompt window arrangement you glean from the user the number of players in the Memories Card Game to follow …
  • and then from then on

    var lasttogglenumber='';
    var lastec='', notyet=false;
    var backi="/rjmquiz_plus.jpg";
    var fiftytwo=52;
    var message='';
    var lastcard='';
    var lasttto='';
    var gamescoreprefix='';
    var gamescores=[0];
    var lasttmid='';
    var lasttfrom='';
    var lasttoggleto='';
    var lasttogglefrom='';
    var curplayer=1, card_of_play=0;
    var card_game='memories';
    var nominal_implication='';
    var nominal_numplayers = (document.URL.replace('?','&').indexOf('&card') != -1) ? prompt('How many players are playing your ' + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(0,1).toUpperCase() + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(1).toLowerCase() + ' card game?', '2') : null;

    if (nominal_numplayers) {
    if (('' + nominal_numplayers).replace('0','').trim() != '' && ('' + nominal_numplayers).replace('0','').trim().indexOf('-') == -1) {
    var prompt = function(zwords, defwords){ return null; };
    nominal_implication=" var prompt = function(zwords, defwords){ return null; }; ";
    fiftytwo=-1;
    backi="/Games/Memories/Memories.jpg";
    } else {
    nominal_numplayers=null;
    }
    }

… “prompt” is overridden as above. That, and overriding the scoring mechanisms, and this same codeset is nearly there towards accommodating our new quite different requirement.

But with “No Body Definition”/”Just Javascript” how can we show and implement this new Memories Card Game usage? It’s a two way integration, the easier one being …

  • offer a place for click/touch on the default background imagery … and with that webpage reminder …
  • what is an independent “add on” event methodology available to us, so as not to interfere with event logic that has preceded? … spoiler alert … double click …

    ele.addEventListener('dblclick', function(evt) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    });

    … (or two clicks quickly in a row) … as per

    var lastec='', notyet=false;


    function antilastec() {
    lastec='';
    }


    function antinotyet() {
    notyet=true;
    }


    ele.addEventListener('click', function(evt) {
    if (evt.touches) {
    if (evt.touches[0].pageX) {
    iourx = evt.touches[0].pageX;
    ioury = evt.touches[0].pageY;
    } else {
    iourx = evt.touches[0].clientX;
    ioury = evt.touches[0].clientY;
    }
    //alert('' + iourx);
    } else if (evt.clientX) {
    iourx = evt.clientX; // - elemLeft;
    ioury = evt.clientY; // - elemLeft;
    } else if (!evt.touches) {
    iourx = evt.pageX; // - elemLeft;
    ioury = evt.pageX; // - elemLeft;
    }
    if (('' + iourx + ',' + ioury) == lastec && lastec != '' && notyet) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    } else if (lastec == '') {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    } else {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    }

    clickedmaybe();
    });

Again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game One Window Tutorial is shown below.

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

The “one window” rather than (52 + 1) = 53 windows scenario set up as a possibility with yesterday’s Just Javascript Card Order Game Mobile Tutorial had us wondering …

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

… and tomorrow is today. We’ve decided not to make the one window scenario the default for non-mobile platforms, but serve as a fallback for some of the scenarios mentioned below …

  • the user gets blocked from using the popup windows on their non-mobile platform web browser … big possibility!
  • the user clicks half way through the popup window incarnation the parent window … all the child popups disappear behind … annoying … so

    var flexible=false;

    function secsu() {
    var ewd;
    if (secs == 0) {
    if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    flexible=false;
    } else {
    flexible=true;
    console.log('Flexible=T');
    }

    setTimeout(blater, 2500);
    }
    if (eval('' + overallgoes) < 52) {
    secs++;
    } else if (document.title.indexOf('Congratulations') == -1) {
    document.title+=' ... Congratulations! End of Game! Refresh webpage to try again.';
    }
    var decs=document.title.split('.');
    if (eval('' + decs.length) >= 3) {
    document.title=document.title.replace('.' + decs[2].split(' ')[0] + ' ', '.' + secs + ' ');
    } else {
    ps=document.title.split('/')[0].trim();
    pg=document.title.split('/')[1].split(' ')[0];
    if (ps.indexOf('.') == -1 || pg.indexOf('.') == -1) {
    ps=eval('' + overallscore + '.' + psecs); //eval(document.title.split('/')[0].trim());
    pg=eval('' + overallgoes + '.' + secs);
    document.title=document.title.replace(document.title.split(' ')[0], '' + overallscore + '.' + psecs + '/' + '' + overallgoes + '.' + secs);
    //console.log('document.title becomes ' + document.title);
    } else {
    ps=eval(ps);
    pg=eval(pg);
    }
    }


    if (flexible) {
    if (document.hasFocus()) {
    flexible=false;
    console.log('Flexible=F');
    lastzkq='';
    lastzkl='';
    owidth=oowidth;
    oheight=ooheight;
    for (var igh=0; igh<oplist.length; igh++) {
    opltlistl[igh]=oopltlistl[igh];
    opltlistt[igh]=oopltlistt[igh];
    if (oplist[igh]) {
    console.log('Flexible=F' + igh);
    if (!oplist[igh].closed) {
    try {
    oplist[igh].close();
    oplist[igh]=null;
    } catch(ewd) {
    }
    } else {
    oplist[igh]=null;
    }
    }
    }
    }
    }

    }

… document.hasFocus() to the rescue again … the multiple background images of yesterday’s work being a default part of any incarnation, and whether the click event logic of yesterday becomes relevant depends on …

  • if user is a mobile platform user, always relevant
  • user enters URL with argument like ?onewindow=y then is always relevant … else …
  • a scenario as above means that from that point on, the multiple background image one window click on cards modus operandi becomes relevant

We improve the web browser conditions too, if a non-mobile user “clicks half way through the popup window incarnation the parent window” in that we programmatically close any open child popup windows! Phew!

Feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game Mobile Tutorial is shown below.

Just Javascript Card Order Game Mobile Tutorial

Just Javascript Card Order Game Mobile Tutorial

Yesterday’s Just Javascript Card Order Game Tutorial mobile usage scenario was impractical, in that mobile platforms can not work popup windows in front of a parent window. Can we convert those non-mobile popup windows into … well … what exactly?

Well, in order to keep to our “Just Javascript” (ie. “No Body Definition”) pledge with this project, we needed to simulate those popups as background image parts, in the sense that you can have multiple background images these days with your HTML. Even with html as your CSS styling selector … it pans out … we needed to prove that today.

Also, today, for the first time, we achieved via …

  1. comma separated background-repeat: no-repeat; list
  2. comma separated background-size list (set popup width height list until last one bigger (based on screen.width screen.height) for the parent background image (no-repeat))
  3. comma separated background-position list (as per what window.open in non-mobile was using for left top until last one’s 0px 0px)
  4. comma separated background-image list (as per what window.open in non-mobile was using for URL([imageURL]) until last one’s linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)), url(//www.rjmprogramming.com.au/rjmquiz_plus.jpg))

… as per (the previous “window.open” becomes “windowopen”) …


function windowopen(one, two, three) {
if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
console.log('Here ' + kq);
opltlistl.push((three.split('left=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + one.split('spcp=')[1].split('&')[0]));
opltlistt.push((three.split('top=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + kq));
owidth=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
oheight=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
if (defstyle.indexOf('background: URL(') != -1) {
defstyle=defstyle.split('background: URL(')[0] + 'background-repeat:no-repeat;background-size:' + owidth + 'px ' + oheight + 'px;background-position:' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image: url(' + cards[eval('' + donelist[eval(-1 + donelist.length)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'; // + ' ' + owidth + ' ' + oheight
} else {
defstyle=defstyle.replace(';background-image:', (',' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image:');
defstyle=defstyle.replace('no-repeat','no-repeat,no-repeat');
defstyle=defstyle.replace('background-size:' + owidth + 'px ' + oheight + 'px','background-size:' + owidth + 'px ' + oheight + 'px,' + owidth + 'px ' + oheight + 'px');
defstyle=defstyle.replace('; } </style>', ',url(' + cards[eval('' + donelist[eval(0 + ijk)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'); // + ' ' + owidth + ' ' + oheight
}
return null;
}
return window.open(one, two, three);
}

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

We needed to add event logic we were not sure would work at the start of the day, and saw it working by the end, with …


var iourx=-1, ioury=-1;

function blater() {
if (1 == 2 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
window.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
eles = document.querySelectorAll("*")
for (var ele of eles) {
console.log('yes well');
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ele.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('touchmove', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('click', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
ele.addEventListener('click', function(evt) {
if (evt.touches) {
if (evt.touches[0].pageX) {
iourx = evt.touches[0].pageX;
ioury = evt.touches[0].pageY;
} else {
iourx = evt.touches[0].clientX;
ioury = evt.touches[0].clientY;
}
//alert('' + iourx);
} else if (evt.clientX) {
iourx = evt.clientX; // - elemLeft;
ioury = evt.clientY; // - elemLeft;
} else if (!evt.touches) {
iourx = evt.pageX; // - elemLeft;
ioury = evt.pageX; // - elemLeft;
}
clickedmaybe();
//alert('here');
});
}
}
}
}

See this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform) we, again, welcome you to try for yourself.


Previous relevant Just Javascript Card Order Game Tutorial is shown below.

Just Javascript Card Order Game Tutorial

Just Javascript Card Order Game Tutorial

Today we’ve made the web application of yesterday’s Just Javascript Quiz Drag Tutorial “dual purpose” …

  • quiz … as for yesterday, and before … and as of today, making more use of the card organizational side to the popup windows we introduce …
  • card order game

This card order game asks you to force the focus of the correct popup window (to score in the Card Order Game) in the order as designated by the background image part we have added today, and supported by the following Javascript “mapping” code …


var dragorder=[], curdrag=0;

var cards=["//www.rjmprogramming.com.au/images/01s.gif?n=7",
"//www.rjmprogramming.com.au/images/02s.gif?n=16",
"//www.rjmprogramming.com.au/images/03s.gif?n=33",
"//www.rjmprogramming.com.au/images/04s.gif?n=29",
"//www.rjmprogramming.com.au/images/05s.gif?n=8",
"//www.rjmprogramming.com.au/images/06s.gif?n=35",
"//www.rjmprogramming.com.au/images/07s.gif?n=52",
"//www.rjmprogramming.com.au/images/08s.gif?n=51",
"//www.rjmprogramming.com.au/images/09s.gif?n=12",
"//www.rjmprogramming.com.au/images/10s.gif?n=30",
"//www.rjmprogramming.com.au/images/11s.gif?n=1",
"//www.rjmprogramming.com.au/images/12s.gif?n=36",
"//www.rjmprogramming.com.au/images/13s.gif?n=22",
"//www.rjmprogramming.com.au/images/01h.gif?n=32",
"//www.rjmprogramming.com.au/images/02h.gif?n=23",
"//www.rjmprogramming.com.au/images/03h.gif?n=3",
"//www.rjmprogramming.com.au/images/04h.gif?n=18",
"//www.rjmprogramming.com.au/images/05h.gif?n=28",
"//www.rjmprogramming.com.au/images/06h.gif?n=39",
"//www.rjmprogramming.com.au/images/07h.gif?n=45",
"//www.rjmprogramming.com.au/images/08h.gif?n=48",
"//www.rjmprogramming.com.au/images/09h.gif?n=50",
"//www.rjmprogramming.com.au/images/10h.gif?n=44",
"//www.rjmprogramming.com.au/images/11h.gif?n=4",
"//www.rjmprogramming.com.au/images/12h.gif?n=9",
"//www.rjmprogramming.com.au/images/13h.gif?n=5",
"//www.rjmprogramming.com.au/images/01d.gif?n=27",
"//www.rjmprogramming.com.au/images/02d.gif?n=41",
"//www.rjmprogramming.com.au/images/03d.gif?n=20",
"//www.rjmprogramming.com.au/images/04d.gif?n=11",
"//www.rjmprogramming.com.au/images/05d.gif?n=37",
"//www.rjmprogramming.com.au/images/06d.gif?n=49",
"//www.rjmprogramming.com.au/images/07d.gif?n=42",
"//www.rjmprogramming.com.au/images/08d.gif?n=6",
"//www.rjmprogramming.com.au/images/09d.gif?n=21",
"//www.rjmprogramming.com.au/images/10d.gif?n=31",
"//www.rjmprogramming.com.au/images/11d.gif?n=40",
"//www.rjmprogramming.com.au/images/12d.gif?n=43",
"//www.rjmprogramming.com.au/images/13d.gif?n=17",
"//www.rjmprogramming.com.au/images/01c.gif?n=46",
"//www.rjmprogramming.com.au/images/02c.gif?n=19",
"//www.rjmprogramming.com.au/images/03c.gif?n=47",
"//www.rjmprogramming.com.au/images/04c.gif?n=25",
"//www.rjmprogramming.com.au/images/05c.gif?n=10",
"//www.rjmprogramming.com.au/images/06c.gif?n=15",
"//www.rjmprogramming.com.au/images/07c.gif?n=13",
"//www.rjmprogramming.com.au/images/08c.gif?n=26",
"//www.rjmprogramming.com.au/images/09c.gif?n=38",
"//www.rjmprogramming.com.au/images/10c.gif?n=34",
"//www.rjmprogramming.com.au/images/11c.gif?n=2",
"//www.rjmprogramming.com.au/images/12c.gif?n=14",
"//www.rjmprogramming.com.au/images/13c.gif?n=24"];


for (var ic=1; ic<=cards.length; ic++) {
found=false;
for (var jc=1; jc<=cards.length; jc++) {
if ((cards[eval(-1 + jc)] + '~').indexOf('?n=' + ic + '~') != -1) {
dragorder.push(eval(-1 + jc));
cards[eval(-1 + jc)]=cards[eval(-1 + jc)].replace('?n=' + ic, '');
firstbit+=String.fromCodePoint(eval('' + spcps[eval(-1 + jc)].split('/')[0])) + ' ';
found=true;
}
}
}

… and “making use of” this and the new codeline as popups are created … oplist[eval(-1 + oplist.length)].document.name=” + kl; we have …


function ourprompt(tw, blb, bdef) {
var kijk;
if (oplist[eval('' + tw)].document.name == ('' + dragorder[eval('' + curdrag)]) && eval('' + curdrag) == eval('' + overallgoes)) {
console.log('Dragorder[' + curdrag + ']=' + dragorder[eval('' + curdrag)] + ' vs tw=' + tw + ' and overall;goes=' + overallgoes);
var decs=document.title.split('.');
curdrag++;
overallgoes++;
if (eval('' + decs.length) >= 3) {
document.title=document.title.replace('.' + decs[1] + '.', '.' + curdrag + '/' + overallgoes + '.');
}
oplist[eval('' + tw)].close();
return null;
}

// Quiz only code follows
}

… code.

It must be in the correct order (and not interrupted by quiz answer completions) to score, and you are timed, so you can try improving over time, using a document.title score presentation as per …


[QuizScore].[CardOrderGameScore]/[QuizAnswerAttemptCount].[SecondsElapsed] [MultiPlayerQuizScoreGoesBreakdown] is User: Score/Goes - RJM Programming - April, 2021

… so that both usages for the web application can be accommodated for in the changed cards_usefocus.html code behind the “Just Javascript” live run we welcome you to try for yourself.


Previous relevant Just Javascript Quiz Drag Tutorial is shown below.

Just Javascript Quiz Drag Tutorial

Just Javascript Quiz Drag Tutorial

Adding to yesterday’s Just Javascript Quiz CSS Styling Tutorial we have added some …

  • non-mobile platform, only …
  • drag and drop functionality … for …
  • the child popup windows

… achieved through the comparison of …

  • original [popupWindow].screenLeft and [popupWindow].screenTop … initially, to …
  • [popupWindow].screenLeft and [popupWindow].screenTop over time

… and if one popup is dragged to overlay another it is closed, or you, as the user, can just drag and drop for clarity, leaving the popup window of the next quiz question out in the open, perhaps.

In order to achieve this, and keep backward compatibility we needed to delay the quiz question prompt window via …

  1. document.hasFocus() is true … then if …
  2. inhouse dragging checks clear it of overlaying another popup (in which case that popup is programmatically closed, allowing another popup to become the “focus window”) … then …
  3. delay (by 8 seconds) the prompt window (and in that time the user can be dragging popups (but no popups were harmed in the making of this tutorial)) … via …

    setTimeout(function() { hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } else { hj=window.opener.assess(hj); } if (hj.replace(def,'') != '') { checka(hj); } else { setTimeout(pa,10000); } aminmiddle=false; }, 8000);

… you can see in amongst the changed cards_usefocus.html code behind the “Just Javascript” live run you are welcome to try for yourself … best on non-mobile.

Still “No Body Definition”, “Just Javascript”!


Previous relevant Just Javascript Quiz CSS Styling Tutorial is shown below.

Just Javascript Quiz CSS Styling Tutorial

Just Javascript Quiz CSS Styling Tutorial

Our “Just Javascript” adage used throughout this blog posting thread, up until today, headed by yesterday’s Just Javascript Quiz Content Management Tutorial needs more explanation. Really what we are trying to do might better be described as “No Body Definition” (ie. no defined document.body) but have …

  1. an HTML webpage (ie. within <html> and </html>) … has …
  2. <head> and </head> (ie. document.head) content which can be made up of (at least) title, style, script, link, meta tags

To assert “Just Javascript” is just to allow script content above, but what we should really say is “Just Head Content” but that is not nearly so marketable, is it now?!

The thing is, though, we can dynamically add title, style, link, meta tag content within the script content, and we do this more than statically define it, to feel better about our ethics saying “Just Javascript”.

Dynamically adding style CSS styling either …

  • using Javascript DOM (not available to us for document.getElementById([elementID] and nor can we use inline CSS via style=”[CSSstyling]” statically within HTML element code for that same reason) ideas today though … remember “No Body Definition” … but …
  • we can append to <head> and </head> (for today’s scenario) as per …

    document.head.innerHTML+="<style> html { background-color: yellow; font-size: 36px; background: URL('//www.rjmprogramming.com.au/rjmquiz.jpg'); background-size: cover; } </style>";

… allowing (into the scope of our work CSS styling of) background (image(s)) and other background styling ideas that can get us past the anonymous feel the web application had before today. We tailored the background image above to suit our Quiz and help it be a bit more self explanatory … thanks CSS styling! We add onto the child “card” popup windows, their own background image colour and pizazz, to cheer things up in CSS styling enhanced cards_usefocus.html code behind the “Just Javascript” live run.

You may well ask …

What can we hang our hat on with CSS style selectors without a body element?

Well, we had to step out of our usual comfort zone of CSS styling thinking, and realize, even without that body element we can still use the html selector to “point at” the entirety of your webpage of interest.


Previous relevant Just Javascript Quiz Content Management Tutorial is shown below.

Just Javascript Quiz Content Management Tutorial

Just Javascript Quiz Content Management Tutorial

It feels like an “onions of the 4th dimension” idea to allow the user to control the questions and answers behind the workings of yesterday’s Just Javascript Quiz Multiple Users Tutorial‘s web application, featuring “Just Javascript”.

It’s not “Just Javascript” we’re keeping, it’s “Just HTML” client work rather than involving any serverside anything (eg.PHP) and yet this question and answer data could be quite sizeable. What can we use, given no PHP serverside, and given we’ve decided not to navigate via Ajax/FormData techniques? How about “the better than HTTP Cookies” twins …

Yep, set up a means by which these two can store and restore questions and answers entered by the user, using these storage methods above.


function reassess() {
var retv='', ewq;
var retcols=[];
var ir=0;
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '') {
//alert('0:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?!')[0] + '?');
asq.push(retcols[ir].split('?!')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '') {
//alert('1:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?')[0] + '?');
asq.push(retcols[ir].split('?')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
}


function assess(what) {
var ewq, retv='';
if (what.toLowerCase() == '?x') {
sslistq=[];
sslista=[];
if (window.sessionStorage) {
try {
window.sessionStorage.removeItem('cards_usefocus_session');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase() == '?!x') {
lslistq=[];
lslista=[];
if (window.localStorage) {
try {
window.localStorage.removeItem('cards_usefocus_local');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase().indexOf('?!') != -1) {
if (what.toLowerCase() == '?!') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.localStorage) {
if (lslistq.length == 0) {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', encodeURIComponent(what));
} else {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', window.localStorage.getItem('cards_usefocus_local') + encodeURIComponent('~' + what));
}
}
return '';
} else if (what.toLowerCase().indexOf('?') != -1) {
if (what.toLowerCase() == '?') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.sessionStorage) {
if (sslistq.length == 0) {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', encodeURIComponent(what));
} else {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', window.sessionStorage.getItem('cards_usefocus_session') + encodeURIComponent('~' + what));
}
}
return '';
} else {
firstbit='';
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
}
return what;
}

The fairly significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz Multiple Users Tutorial is shown below.

Just Javascript Quiz Multiple Users Tutorial

Just Javascript Quiz Multiple Users Tutorial

Adding to yesterday’s Just Javascript Quiz via Cards Tutorial we were surprised how difficult it was to stay with “Just Javascript” and allow for multiple player play.

We didn’t opt for the parent to ask about the number of players, curiously, but on the second quiz answer and on, offered any non first player the chance to identify themselves as a new player into the game by appending their answer with a space character.

The implication of that is that we’ll want to run Javascript functions of the parent from the children as per


oplist[eval(-1 + oplist.length)].document.write("<link rel=icon href=" + cards[kl] + "><scr" + "ipt type='text/javascript'> var da='" + eval(0 + kq) + "'; var dp='Given answer is integer from 0 to 25 ... " + sq[kq] + "'; var def=String.fromCodePoint(" + spcps[eval('' + kl)].split('/')[0] + "); function checka(tpa) { var os=''; var ps=eval(window.opener.document.title.split('/')[0].trim()); var pg=eval(window.opener.document.title.split('/')[1].split(' ')[0]); if (tpa.trim() == da) { ps++; os=tpa.split(da)[1]; } else { pg++; os=tpa.split(tpa.trim())[1]; } window.opener.document.title=ps + os + '/' + pg + ' is User Score/Goes'; window.close(); } function pa() { if (document.hasFocus()) { var hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } if (hj.replace(def,'') == '') { setTimeout(pa,1000); } else { checka(hj); } } else { setTimeout(pa,1000); } } pa(); </scr" + "ipt>");

… accessing …


function blurb() { // theblurb and wblurb are global variables changed elsewhere
if (wblurb == ' Hello Player 1' && theblurb == ' If you are player 2 rather than player 1 append space to your answer.') {
theblurb='';
wblurb='';
}
return theblurb + wblurb;
}

… giving the rather curious behaviour whereby a Javascript prompt window can be dynamically different from one document.hasFocus() incarnation (ie. the user might go away and answer another “card” Number Quiz question) to another (even not attending to answering the Javascript prompt window) … huh?!

The significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz via Cards Tutorial is shown below.

Just Javascript Quiz via Cards Tutorial

Just Javascript Quiz via Cards Tutorial

Yesterday’s Just Javascript Navigation Tutorial continues our interest in “Just Javascript” (or “No Body”) web applications.

We think today’s “Numbers Quiz” via a “Card Deck” organizational design ups the ante on all this. We realize now what we have been missing not having involved document.hasFocus() in any of our popup window scenarios. Today, at least on non-mobile, we involve 52 such popup windows each containing a “Number Quiz” question presented as a Javascript prompt (sub-)window. This would not be feasible without document.hasFocus() as you can tell if you examine the cards_usefocus.html code behind the “Just Javascript” live run best used on your non-mobile platforms where popup windows can sit in front of parent (and beside sibling) windows, whereas mobile platforms open new web browser tabs for all the 52 windows of (a card deck) design.

Look out, too, in the code above, for use of window.opener back reference from a popup window back to the parent window where the scoring data is held, and updated by each popup window because of that window.opener avaalability.


Previous relevant Just Javascript Navigation Tutorial is shown below.

Just Javascript Navigation Tutorial

Just Javascript Navigation Tutorial

The recent use we made of …


document.createElement/click()

… got us thinking of the “Just Javascript” (or No Body) blog posting thread headed by Just Javascript Webmail No Body Attachment Tutorial.

As such, today we present the very simple (but first time use of the interesting hasFocus) “proof of concept” …


<html>
<head>
<script type='text/javascript'>
function dothis() {
var ais=null;
var urlis=' ';
while (urlis != '') {
if (document.hasFocus()) {
urlis=prompt('Enter URL that we will send you to (exit to stop)', '');
} else {
setTimeout(dothis, 2000); // urlis=' ';
return;
}
if (urlis == null) { urlis=''; }
if (urlis.toLowerCase() == 'exit') { return; }


if (urlis.trim() != '') {
if (urlis.substring(0,1) == '.') { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
} else if (urlis.substring(0,1) == '/' && urlis.indexOf('//') == -1) { // relative URL
urlis=document.URL.split('//')[0] + '//' + document.URL.split('//')[1].split('/')[0] + '/' + urlis;
} else if (urlis.split('/')[0].indexOf('.') != -1) { // absolute URL
if (urlis.toLowerCase().indexOf('http') != 0) {
if (urlis.indexOf('//') == 0) {
urlis=document.URL.split('//')[0] + urlis;
} else {
urlis=document.URL.split('//')[0] + '//' + urlis;
}
}
} else { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
}
ais=document.createElement('a');
ais.onclick=function() { window.open(urlis, '_blank', 'top=100,left=100,width=600,height=600'); };
if (1 == 2) { ais.href=urlis; }
ais.target='_blank';
ais.click();
}
}
setTimeout(dothis, 2000); // urlis=' ';
}


dothis();

</script>
</head>
</html>

nobody.html‘s live run link for you to use a Javascript prompt popup window’s user interaction results to navigate to a new webpage, as applicable. Bookmarklets may be scarce on the ground, but these “Just Javascript” ideas continue the Bookmarklet Spirit of the past!


Previous relevant Just Javascript Webmail No Body Attachment Tutorial is shown below.

Just Javascript Webmail No Body Attachment Tutorial

Just Javascript Webmail No Body Attachment Tutorial

A “hard liner” for the proper use of “business emails” could argue that an email without an attachment is not productive. Couldn’t you just have a face to face meeting instead, if there is just wording in the email (as we somewhat concur with, as an argument)? So yesterday’s Just Javascript Webmail No Body Tutorial had that limitation of no email attachment logic, which we remedy today.

And this is where PHP’s wonderful file_get_contents (function) means by which we garner (URL) content …

  • definitely works with “relative URLs” relative to HTTP://www.rjmprogramming.com.au/HTMLCSS/ where today’s unchanged webmail_nobody.html resides … in “parsing parlance” …

    "relative (URL)" to the left of any # or ? of what lies to the left of the most right hand "/" (of what the address bar URL is of the webpage you are on)

    … so that …

    1. “relative URLs” starting with “./” (followed by the filename, or just the filename (as you can see us using in today’s tutorial picture)) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/HTMLCSS/” … whereas, for example …
    2. “relative URLs” starting with “../” (followed by the filename) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/” … for example

    … and …

  • might work for “absolute URLs” (those that start with https: or HTTP: or even // (that we beg you not to confuse with Windows UNC pathnames) that infer a transport protocol of the transport protocol (out of https: or HTTP: or even file:) that got you to the webpage you are currently on), the “might” being far more likely on “absolute URLs” pointing to the same domain as indicated on the URL of the address bar of the webpage you are currently on

Upshot is, the user in their email Body section definitions (still no HTML body though!), can throw into any word they use, an “absolute URL” of interest, or a “relative URL” of interest, of files they want to attach (as attachments, doh!) in their email.

Depending on the email rules though, there are limits as to the amount of attachment data allowed. We’ll leave that to you intrepid “explorers of the Net” to discover for yourselves. On this subject though, have you noticed that with the Photos (or Gallery) app Share options, the Email option drops off when you have highlighted a large number of photos or videos or audios to share? That’s that email limit coming into play.

So feel free to try this HTML-body-less web application live run to see what we mean here. Though the parent HTML is unchanged today, the new (email) attachment functionality needed a changed PHP emailhtml.php to make this happen.

Did you know?

This (relative URL) “../” navigation backwards up the hierarchy of the web server directories will, if repeated (ie. nested to “../../” etcetera) too many times, get you into uncharted unnavigable (web server directory) places relative to that web server web site’s Document Root (below which you can not access in public webpages, normally). But when you perform similar thinking with “absolute URLs” and go “HTTP://www.rjmprogramming.com.au/HTMLCSS/../../../blahdeblah.jpg” (in a web browser address bar) for instance, you cannot get into trouble, as you just don’t get beyond this sending you to (attempt the reference to) “HTTP://www.rjmprogramming.com.au/blahdeblah.jpg” because on this rjmprogramming.com.au Apache domain the correspondence of the Document Root (web server directory) is to “HTTP://www.rjmprogramming.com.au/” as the place you are not allowed (and cannot) go below in the hierarchy tree.


Previous relevant Just Javascript Webmail No Body Tutorial is shown below.

Just Javascript Webmail No Body Tutorial

Just Javascript Webmail No Body Tutorial

Were you around and interested in our series of about three blog postings in the series on the theme of creating webpage functionality of some interest, involving no Javascript, when we presented Missing Javascript Audio on Unmute Tutorial? Well, today, it’s the turn of “just Javascript”, which is sort of like what Bookmarklets were about.

With today’s “just Javascript” we have to qualify that a little for our webmail emailing sender application with the architecture …

  • parent webpage with only document.head and apart from a document.title just a script Javascript tag of content (using Javascript prompt windows to ask for user information) …
  • sending (POSTing) data via …
    1. Ajax XMLHttpRequest object … as the conduit for …
    2. FormData object

    … to our changed

  • PHP communication emailing tool emailhtml.php … and out to …
  • the emailee (out there in the big wide woooorrrrrllllldddd)

Guess we find it interesting that you can do all this (sending of email to emailee recipients) with no document.body in sight.

So take a look at that parent webmail_nobody.html‘s live run link to see what we mean here, and/or watch the video below …


Previous relevant Missing Javascript Audio on Unmute Tutorial is shown below.

Missing Javascript Audio on Unmute Tutorial

Missing Javascript Audio on Unmute Tutorial

Our “third cab off the rank” following on from yesterday’s Missing Javascript Stop Watch Tutorial “missing Javascript” ideas is an HTML div nesting scenario using just …

  1. HTML
  2. CSS

… again, with some or all of the “usuals” below …

  • calc method to assist with defining width and height and size dimensions along with operator “+” and/or “-” offset calculation opportunities, and which we’d have used the Javascript window.getComputedStyle and/or [element].getBoundingClientRect methods to cover this (in a much more unwieldy way, as you would probably surmise)
  • CSS variables we started talking about here at CSS Variables Primer Tutorial
  • CSS3 @keyframes rules we first talked about at CSS3 @keyframes Rule Primer Tutorial that assist with animations that we can make work via …
  • CSS3 transitions for scheduled functionality (we’d have used Javascript setTimeout (and setInterval) methods to cover the same “territory”) we first talked about at CSS3 Transition Primer Tutorial … specified with CSS Criteria involving …
  • CSS Selectors :after and :before (and often, as for today’s work, with the content: CSS property) first talked about here with WordPress Bullet Point CSS Styling Primer Tutorial … and, today …
  • CSS3 transform property’s rotate (and translate and scale) settings (for the puppy dog body movements) … as well as the idea that …
  • On non mobile platforms you can set up the playing of “audio” data via the use of an HTML audio tag with the properties …
    1. controls
    2. autostart
    3. loop
    4. muted

    Stop Press

    Above is all fine and good for non-mobile but not so good for mobile, so to keep all happy with the one click, still, is to transfer HTML coding from …


    <audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" />

    … to …


    <!--audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" /-->
    <audio id='myaudiotwo' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="margin-left:-350px;opacity:0.1;" autostart="0" loop controls src="Puppy-sounds.mp3" />

    … and a src= URL data source (as we thank this link for today), or data URI if preferred (which we do for today’s image data from this link, thanks (when we were researching animated GIF data URIs (which we may return to at a later date))

… that sets up the scenario that all the user has to do to hear the audio is to click the “muted” control button, without needing the usual Javascript play() methods … but not on mobile!

Feel free to let the puppy play, that uses the HTML and CSS (but no Javascript) of the_nested.html and based largely on the previous HTML Nested Centering via Multiple Select Tutorial so that these changes reflect how we got to the first draft of today’s work. Maybe some of the ideas are of interest. We hope so!


Previous relevant Missing Javascript Stop Watch Tutorial is shown below.

Missing Javascript Stop Watch Tutorial

Missing Javascript Stop Watch Tutorial

Following on from yesterday’s Missing Javascript Primer Tutorial our second “cab off the rank” for “missing Javascript” ideas is a stop watch featuring just …

  1. HTML
  2. CSS

… again, setting up document.body load instigated

… which we needed to do to make multiple animations happen, but we used animation-delay:5s; to delay its start. The hands (second and minute, hence the two animations) are “overlay”

… feeling HTML horizontal rule elements that also feature linear gradients, to emphasise (in red) the “pointy end” of the “hand conversation” (good on walls with shadows … but we digress).

Feel free to let loose the stop watch that uses the HTML and CSS (but no Javascript) of stop_watch.html for today’s instructional information. Thanks to Clipart – stop watch for the great clip art used.


Previous relevant Missing Javascript Primer Tutorial is shown below.

Missing Javascript Primer Tutorial

Missing Javascript Primer Tutorial

If you were to ask me which programming component is most vital to web application development, I’d not be Robinson Crusoe in saying …

Without a doubt, Javascript

… and with that thought in mind we have a two pronged motive to see how far we go developing some web applications that “don’t use Javascript”, calling into play the …

  • meaning of “missing”, as in, our code is “missing” Javascript … as well as how I feel with the masochism of the exercise, calling into play the …
  • meaning of “missing”, as in, it’s hard work writing meaningful web applications without Javascript … but I guess we’ll learn a bit from the exercise of “see where we go”, allowing for the fact, not today, but down the track, that we will allow the use of server-side languages such as PHP

Okay, so, given that restriction, let’s see today’s challenge, to just use, in a web application …

  1. HTML
  2. CSS

… and here is where we have to point out that CSS3 introduced to us some functionality that improves the prospects for web application design “interest” without using Javascript (though it is hard to convince me even so, that I am not “missing” Javascript) here. CSS3 introduced to us …

… and we use all of these in our Festive Season themed web application today, you can try at this live run‘s calc_use.html (free of any Javascript (but “why” springs to mind … because it is NOT there, perhaps?)).

Here’s the other thing about today. Our long sought after “just make the body background be semi-transparent” but not its foreground parts, was solved, for us via the great advice of …

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


If this was interesting you may be interested in 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 Animation, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Just Javascript Memories SVG Emoji Defence Tutorial

Just Javascript Memories SVG Emoji Defence Tutorial

Just Javascript Memories SVG Emoji Defence Tutorial

Perhaps it is the weakness of an optimist programmer to think users will, in all ways, co-operate with your intentions regarding the use of your applications and programs. Those optimists should …

  • wake up early if damage can be done to a web server allowing the user the abilities to chance it with your web applications, but mainly more a concern with serverside language (eg. PHP) work, where a user may write data to the web server … but even if HTML/Javascript/CSS only …
  • can wake up a bit later, but “play defence” for those things you can imagine a user might try …

… the mild naughtiness in our Memories Card Game part of the recent “Just Javascript (ie. “No Body Definition”) being that the user may re-click a card square “squared away” into the score of a user. To fix this is a two part issue in our mind, as an improvement to yesterday’s Just Javascript Memories SVG Emoji Background Tutorial

  • add complexity to an “if” command as per

    var nogolist=',';
    var susslist=',';
    var curpcols=['0,0,255,','0,255,0,','255,0,0,','0,0,127,','0,127,0,','127,0,0,', '255,0,255,','255,255,0,','0,255,255,', '127,0,127,','127,127,0,','0,127,127,'];


    function domessage() {
    gamescoreprefix='Tricks taken are ' + gamescores[0];
    for (var ijkhl=1; ijkhl<eval('' + nominal_numplayers); ijkhl++) {
    if (eval('' + gamescores.length) > eval('' + ijkhl)) {
    gamescoreprefix+=':' + gamescores[eval('' + ijkhl)];
    } else {
    gamescoreprefix+=':0';
    }
    }
    if (message != '') {
    csuff='';
    var hjg='' + curplayer;
    for (var ipl=0; ipl<hjg.length; ipl++) {
    //alert(hjg.substring(ipl,eval(1 + eval('' + ipl))) + ' has ord ' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0) + ' to ' + eval(8304 + eval(eval('' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0)) - 48)));
    csuff+=String.fromCodePoint(eval(8320 + eval(eval('' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0)) - 48)));
    }
    if (ocp) {
    ocp.style.cursor='url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'margin-left:20px;border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer';
    if (defstyle.indexOf('data:image/svg') != -1) {
    defstyle=defstyle.replace(prevsb, String.fromCodePoint(10067,10068) + csuff);
    prevsb=String.fromCodePoint(10067,10068) + csuff;
    //document.head.innerHTML+=defstyle;
    }
    } else if (defstyle.indexOf('data:image/svg') != -1) {
    defstyle=defstyle.replace(prevsb, String.fromCodePoint(10067,10068) + csuff);
    prevsb=String.fromCodePoint(10067,10068) + csuff;
    //document.head.innerHTML+=defstyle;
    }
    alert(gamescoreprefix + ' ... ' + message + '');
    message='';
    // Thanks to https://css-tricks.com/more-control-over-css-borders-with-background-image/
    //alert(' repeating-linear-gradient(0deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(90deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(180deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(270deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px),'.substring(0,1) + togglefrom.replace(/\.gif/g,'.JUNKgif'));
    defstyle=defstyle.replace(toggleto, snapshot(' repeating-linear-gradient(0deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(90deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(180deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(270deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px),'.substring(0,1) + togglefrom.replace(/\.gif/g,'.JUNKgif'))); // + ' 30 round');
    defstyle=defstyle.replace(lasttoggleto, snapshot(' repeating-linear-gradient(0deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(90deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(180deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px), repeating-linear-gradient(270deg, #333333, #333333 10px, transparent 10px, transparent 20px, #333333 20px),'.substring(0,1) + lasttogglefrom.replace(/\.gif/g,'.JUNKgif'))); // + ' 30 round');
    document.head.innerHTML+=defstyle;
    nogolist+=susslist;
    susslist=',';

    lasttto='';
    lasttmid='';
    lasttfrom='';
    lasttoggleto='';
    lasttogglefrom='';
    lastcard='';
    lasttogglenumber='';
    }
    susslist=',';
    }

    function maybeno(xxcw) {
    if (nogolist.indexOf(',' + xxcw + ',') != -1) { return '1234567'; }
    return xxcw;
    }


    function popupsim(zkq, zkl) {
    var xkq='' + zkq;
    aminmiddle=false;
    if (lasttogglenumber != ' ') {
    for (var ihj=0; ihj<spcps.length; ihj++) {
    if (('' + zkl) == spcps[ihj].split('/')[0]) {
    for (var jhj=0; jhj<donelist.length; jhj++) {
    if (('' + donelist[jhj]) == ('' + ihj)) {
    cw=eval(0 + jhj);
    if (nominal_numplayers && eval('' + defstyle.split('url(').length) > eval('' + maybeno(cw))) {
    // etcetera
    }
    // etcetera
    }
    // etcetera
    }
    // etcetera
    }
    // etcetera
    }
  • decorate those “squared away” squares with a tick emoji background image (and hope this stops naughtiness), perhaps colour coded, to additionally make the score be self evident in times when the alert boxes are not showing

And so yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories SVG Emoji Background Tutorial is shown below.

Just Javascript Memories SVG Emoji Background Tutorial

Just Javascript Memories SVG Emoji Background Tutorial

Yesterday’s Just Javascript Memories SVG Emoji Cursor Tutorial had good and bad news related to SVG Emoji Cursors?

  • the bad news is that this CSS cursor concept does not work on mobile platforms for similar reasons to why onmouseover does not work … to hover over the mobile device screen means nothing to event logic … while …
  • the good news is that the same type of data-uri of SVG content can work for a (mobile CSS) background image as it can work for (non-mobile CSS) cursor

… and so we can show, ahead of time, via a background image, news about the Memories game on mobile platforms (that are missing that CSS cursor methodology of showing similar information) … as per


var dhi='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
covercover=',80px 60px,80px 60px';
prevsb=String.fromCodePoint(10067,10068) + csuff;
dhi='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
document.head.innerHTML+=dhi;
} else {

document.head.innerHTML+='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
}

… used as per code exemplified by


if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else {

defstyle=defstyle.replace(';background-size:', ',no-repeat,no-repeat' + ';background-size:');
}
if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + opc.style.cursor.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + dhi.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else {

defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(//www.rjmprogramming.com.au' + backi + '); } </style>'); // + ' ' + owidth + ' ' + oheight
}

So yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories SVG Emoji Cursor Tutorial is shown below.

Just Javascript Memories SVG Emoji Cursor Tutorial

Just Javascript Memories SVG Emoji Cursor Tutorial

The “Memories” functionality introduced in yesterday’s Just Javascript Memories Card Game Tutorial is a game component, and it is good to remember the “game” side to that. If a web application is a game and the player is not being timed, they may feel that freedom to be multitasking, go and do something else, and then come back “to work the game”. In that scenario, it would be quite friendly to offer a mechanism by which to remind the player(s) of the status of the game as they left it.

Even though we are in “Just Javascript” (ie. “No Body Definition”) mode of use here, we still have CSS to offer a solution here, and we’ve chosen in the CSS woooooorrrrrllllllddd to research a curiosity we’ve had “for just about ever”. Can we tailor the webpage “cursor” to be “emoji text content”. We’ve looked this up in the past, and did not succeed on that occasion with the “url([SVGcontent])” we thought might be the go. It was tweaking onto this great link that gave examples for us to succeed this time, thanks, using code such as …


csuff='';
var hjg='' + curplayer;
for (var ipl=0; ipl<hjg.length; ipl++) {
csuff+=String.fromCodePoint(eval(8320 + eval(eval('' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0)) - 48)));
}
if (ocp) { ocp.style.cursor='url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + 'HTTP://www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer'; }

… that “ocp” being the “evt.target” of the “onlick” event logics previously talked about. Notice the fallback to those set cursors of “the cursor wooooorrrrrllllllddd”.

Along the way we offer variations to the playing rules of Memories, too, to add some variety for the user(s).

Yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories Card Game Tutorial is shown below.

Just Javascript Memories Card Game Tutorial

Just Javascript Memories Card Game Tutorial

Up until yesterday’s Just Javascript Card Order Game One Window Tutorial every mode of execution of our web application involved the Javascript prompt (popup) window method of getting information off the user.

Today, though, adding a Memories Card Game new functionality part uses a hybrid Javascript prompt window arrangement …

  • a first usage is to use the default Javascript prompt window arrangement you glean from the user the number of players in the Memories Card Game to follow …
  • and then from then on

    var lasttogglenumber='';
    var lastec='', notyet=false;
    var backi="/rjmquiz_plus.jpg";
    var fiftytwo=52;
    var message='';
    var lastcard='';
    var lasttto='';
    var gamescoreprefix='';
    var gamescores=[0];
    var lasttmid='';
    var lasttfrom='';
    var lasttoggleto='';
    var lasttogglefrom='';
    var curplayer=1, card_of_play=0;
    var card_game='memories';
    var nominal_implication='';
    var nominal_numplayers = (document.URL.replace('?','&').indexOf('&card') != -1) ? prompt('How many players are playing your ' + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(0,1).toUpperCase() + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(1).toLowerCase() + ' card game?', '2') : null;

    if (nominal_numplayers) {
    if (('' + nominal_numplayers).replace('0','').trim() != '' && ('' + nominal_numplayers).replace('0','').trim().indexOf('-') == -1) {
    var prompt = function(zwords, defwords){ return null; };
    nominal_implication=" var prompt = function(zwords, defwords){ return null; }; ";
    fiftytwo=-1;
    backi="/Games/Memories/Memories.jpg";
    } else {
    nominal_numplayers=null;
    }
    }

… “prompt” is overridden as above. That, and overriding the scoring mechanisms, and this same codeset is nearly there towards accommodating our new quite different requirement.

But with “No Body Definition”/”Just Javascript” how can we show and implement this new Memories Card Game usage? It’s a two way integration, the easier one being …

  • offer a place for click/touch on the default background imagery … and with that webpage reminder …
  • what is an independent “add on” event methodology available to us, so as not to interfere with event logic that has preceded? … spoiler alert … double click …

    ele.addEventListener('dblclick', function(evt) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    });

    … (or two clicks quickly in a row) … as per

    var lastec='', notyet=false;


    function antilastec() {
    lastec='';
    }


    function antinotyet() {
    notyet=true;
    }


    ele.addEventListener('click', function(evt) {
    if (evt.touches) {
    if (evt.touches[0].pageX) {
    iourx = evt.touches[0].pageX;
    ioury = evt.touches[0].pageY;
    } else {
    iourx = evt.touches[0].clientX;
    ioury = evt.touches[0].clientY;
    }
    //alert('' + iourx);
    } else if (evt.clientX) {
    iourx = evt.clientX; // - elemLeft;
    ioury = evt.clientY; // - elemLeft;
    } else if (!evt.touches) {
    iourx = evt.pageX; // - elemLeft;
    ioury = evt.pageX; // - elemLeft;
    }
    if (('' + iourx + ',' + ioury) == lastec && lastec != '' && notyet) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    } else if (lastec == '') {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    } else {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    }

    clickedmaybe();
    });

Again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game One Window Tutorial is shown below.

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

The “one window” rather than (52 + 1) = 53 windows scenario set up as a possibility with yesterday’s Just Javascript Card Order Game Mobile Tutorial had us wondering …

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

… and tomorrow is today. We’ve decided not to make the one window scenario the default for non-mobile platforms, but serve as a fallback for some of the scenarios mentioned below …

  • the user gets blocked from using the popup windows on their non-mobile platform web browser … big possibility!
  • the user clicks half way through the popup window incarnation the parent window … all the child popups disappear behind … annoying … so

    var flexible=false;

    function secsu() {
    var ewd;
    if (secs == 0) {
    if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    flexible=false;
    } else {
    flexible=true;
    console.log('Flexible=T');
    }

    setTimeout(blater, 2500);
    }
    if (eval('' + overallgoes) < 52) {
    secs++;
    } else if (document.title.indexOf('Congratulations') == -1) {
    document.title+=' ... Congratulations! End of Game! Refresh webpage to try again.';
    }
    var decs=document.title.split('.');
    if (eval('' + decs.length) >= 3) {
    document.title=document.title.replace('.' + decs[2].split(' ')[0] + ' ', '.' + secs + ' ');
    } else {
    ps=document.title.split('/')[0].trim();
    pg=document.title.split('/')[1].split(' ')[0];
    if (ps.indexOf('.') == -1 || pg.indexOf('.') == -1) {
    ps=eval('' + overallscore + '.' + psecs); //eval(document.title.split('/')[0].trim());
    pg=eval('' + overallgoes + '.' + secs);
    document.title=document.title.replace(document.title.split(' ')[0], '' + overallscore + '.' + psecs + '/' + '' + overallgoes + '.' + secs);
    //console.log('document.title becomes ' + document.title);
    } else {
    ps=eval(ps);
    pg=eval(pg);
    }
    }


    if (flexible) {
    if (document.hasFocus()) {
    flexible=false;
    console.log('Flexible=F');
    lastzkq='';
    lastzkl='';
    owidth=oowidth;
    oheight=ooheight;
    for (var igh=0; igh<oplist.length; igh++) {
    opltlistl[igh]=oopltlistl[igh];
    opltlistt[igh]=oopltlistt[igh];
    if (oplist[igh]) {
    console.log('Flexible=F' + igh);
    if (!oplist[igh].closed) {
    try {
    oplist[igh].close();
    oplist[igh]=null;
    } catch(ewd) {
    }
    } else {
    oplist[igh]=null;
    }
    }
    }
    }
    }

    }

… document.hasFocus() to the rescue again … the multiple background images of yesterday’s work being a default part of any incarnation, and whether the click event logic of yesterday becomes relevant depends on …

  • if user is a mobile platform user, always relevant
  • user enters URL with argument like ?onewindow=y then is always relevant … else …
  • a scenario as above means that from that point on, the multiple background image one window click on cards modus operandi becomes relevant

We improve the web browser conditions too, if a non-mobile user “clicks half way through the popup window incarnation the parent window” in that we programmatically close any open child popup windows! Phew!

Feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game Mobile Tutorial is shown below.

Just Javascript Card Order Game Mobile Tutorial

Just Javascript Card Order Game Mobile Tutorial

Yesterday’s Just Javascript Card Order Game Tutorial mobile usage scenario was impractical, in that mobile platforms can not work popup windows in front of a parent window. Can we convert those non-mobile popup windows into … well … what exactly?

Well, in order to keep to our “Just Javascript” (ie. “No Body Definition”) pledge with this project, we needed to simulate those popups as background image parts, in the sense that you can have multiple background images these days with your HTML. Even with html as your CSS styling selector … it pans out … we needed to prove that today.

Also, today, for the first time, we achieved via …

  1. comma separated background-repeat: no-repeat; list
  2. comma separated background-size list (set popup width height list until last one bigger (based on screen.width screen.height) for the parent background image (no-repeat))
  3. comma separated background-position list (as per what window.open in non-mobile was using for left top until last one’s 0px 0px)
  4. comma separated background-image list (as per what window.open in non-mobile was using for URL([imageURL]) until last one’s linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)), url(//www.rjmprogramming.com.au/rjmquiz_plus.jpg))

… as per (the previous “window.open” becomes “windowopen”) …


function windowopen(one, two, three) {
if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
console.log('Here ' + kq);
opltlistl.push((three.split('left=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + one.split('spcp=')[1].split('&')[0]));
opltlistt.push((three.split('top=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + kq));
owidth=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
oheight=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
if (defstyle.indexOf('background: URL(') != -1) {
defstyle=defstyle.split('background: URL(')[0] + 'background-repeat:no-repeat;background-size:' + owidth + 'px ' + oheight + 'px;background-position:' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image: url(' + cards[eval('' + donelist[eval(-1 + donelist.length)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'; // + ' ' + owidth + ' ' + oheight
} else {
defstyle=defstyle.replace(';background-image:', (',' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image:');
defstyle=defstyle.replace('no-repeat','no-repeat,no-repeat');
defstyle=defstyle.replace('background-size:' + owidth + 'px ' + oheight + 'px','background-size:' + owidth + 'px ' + oheight + 'px,' + owidth + 'px ' + oheight + 'px');
defstyle=defstyle.replace('; } </style>', ',url(' + cards[eval('' + donelist[eval(0 + ijk)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'); // + ' ' + owidth + ' ' + oheight
}
return null;
}
return window.open(one, two, three);
}

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

We needed to add event logic we were not sure would work at the start of the day, and saw it working by the end, with …


var iourx=-1, ioury=-1;

function blater() {
if (1 == 2 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
window.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
eles = document.querySelectorAll("*")
for (var ele of eles) {
console.log('yes well');
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ele.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('touchmove', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('click', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
ele.addEventListener('click', function(evt) {
if (evt.touches) {
if (evt.touches[0].pageX) {
iourx = evt.touches[0].pageX;
ioury = evt.touches[0].pageY;
} else {
iourx = evt.touches[0].clientX;
ioury = evt.touches[0].clientY;
}
//alert('' + iourx);
} else if (evt.clientX) {
iourx = evt.clientX; // - elemLeft;
ioury = evt.clientY; // - elemLeft;
} else if (!evt.touches) {
iourx = evt.pageX; // - elemLeft;
ioury = evt.pageX; // - elemLeft;
}
clickedmaybe();
//alert('here');
});
}
}
}
}

See this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform) we, again, welcome you to try for yourself.


Previous relevant Just Javascript Card Order Game Tutorial is shown below.

Just Javascript Card Order Game Tutorial

Just Javascript Card Order Game Tutorial

Today we’ve made the web application of yesterday’s Just Javascript Quiz Drag Tutorial “dual purpose” …

  • quiz … as for yesterday, and before … and as of today, making more use of the card organizational side to the popup windows we introduce …
  • card order game

This card order game asks you to force the focus of the correct popup window (to score in the Card Order Game) in the order as designated by the background image part we have added today, and supported by the following Javascript “mapping” code …


var dragorder=[], curdrag=0;

var cards=["//www.rjmprogramming.com.au/images/01s.gif?n=7",
"//www.rjmprogramming.com.au/images/02s.gif?n=16",
"//www.rjmprogramming.com.au/images/03s.gif?n=33",
"//www.rjmprogramming.com.au/images/04s.gif?n=29",
"//www.rjmprogramming.com.au/images/05s.gif?n=8",
"//www.rjmprogramming.com.au/images/06s.gif?n=35",
"//www.rjmprogramming.com.au/images/07s.gif?n=52",
"//www.rjmprogramming.com.au/images/08s.gif?n=51",
"//www.rjmprogramming.com.au/images/09s.gif?n=12",
"//www.rjmprogramming.com.au/images/10s.gif?n=30",
"//www.rjmprogramming.com.au/images/11s.gif?n=1",
"//www.rjmprogramming.com.au/images/12s.gif?n=36",
"//www.rjmprogramming.com.au/images/13s.gif?n=22",
"//www.rjmprogramming.com.au/images/01h.gif?n=32",
"//www.rjmprogramming.com.au/images/02h.gif?n=23",
"//www.rjmprogramming.com.au/images/03h.gif?n=3",
"//www.rjmprogramming.com.au/images/04h.gif?n=18",
"//www.rjmprogramming.com.au/images/05h.gif?n=28",
"//www.rjmprogramming.com.au/images/06h.gif?n=39",
"//www.rjmprogramming.com.au/images/07h.gif?n=45",
"//www.rjmprogramming.com.au/images/08h.gif?n=48",
"//www.rjmprogramming.com.au/images/09h.gif?n=50",
"//www.rjmprogramming.com.au/images/10h.gif?n=44",
"//www.rjmprogramming.com.au/images/11h.gif?n=4",
"//www.rjmprogramming.com.au/images/12h.gif?n=9",
"//www.rjmprogramming.com.au/images/13h.gif?n=5",
"//www.rjmprogramming.com.au/images/01d.gif?n=27",
"//www.rjmprogramming.com.au/images/02d.gif?n=41",
"//www.rjmprogramming.com.au/images/03d.gif?n=20",
"//www.rjmprogramming.com.au/images/04d.gif?n=11",
"//www.rjmprogramming.com.au/images/05d.gif?n=37",
"//www.rjmprogramming.com.au/images/06d.gif?n=49",
"//www.rjmprogramming.com.au/images/07d.gif?n=42",
"//www.rjmprogramming.com.au/images/08d.gif?n=6",
"//www.rjmprogramming.com.au/images/09d.gif?n=21",
"//www.rjmprogramming.com.au/images/10d.gif?n=31",
"//www.rjmprogramming.com.au/images/11d.gif?n=40",
"//www.rjmprogramming.com.au/images/12d.gif?n=43",
"//www.rjmprogramming.com.au/images/13d.gif?n=17",
"//www.rjmprogramming.com.au/images/01c.gif?n=46",
"//www.rjmprogramming.com.au/images/02c.gif?n=19",
"//www.rjmprogramming.com.au/images/03c.gif?n=47",
"//www.rjmprogramming.com.au/images/04c.gif?n=25",
"//www.rjmprogramming.com.au/images/05c.gif?n=10",
"//www.rjmprogramming.com.au/images/06c.gif?n=15",
"//www.rjmprogramming.com.au/images/07c.gif?n=13",
"//www.rjmprogramming.com.au/images/08c.gif?n=26",
"//www.rjmprogramming.com.au/images/09c.gif?n=38",
"//www.rjmprogramming.com.au/images/10c.gif?n=34",
"//www.rjmprogramming.com.au/images/11c.gif?n=2",
"//www.rjmprogramming.com.au/images/12c.gif?n=14",
"//www.rjmprogramming.com.au/images/13c.gif?n=24"];


for (var ic=1; ic<=cards.length; ic++) {
found=false;
for (var jc=1; jc<=cards.length; jc++) {
if ((cards[eval(-1 + jc)] + '~').indexOf('?n=' + ic + '~') != -1) {
dragorder.push(eval(-1 + jc));
cards[eval(-1 + jc)]=cards[eval(-1 + jc)].replace('?n=' + ic, '');
firstbit+=String.fromCodePoint(eval('' + spcps[eval(-1 + jc)].split('/')[0])) + ' ';
found=true;
}
}
}

… and “making use of” this and the new codeline as popups are created … oplist[eval(-1 + oplist.length)].document.name=” + kl; we have …


function ourprompt(tw, blb, bdef) {
var kijk;
if (oplist[eval('' + tw)].document.name == ('' + dragorder[eval('' + curdrag)]) && eval('' + curdrag) == eval('' + overallgoes)) {
console.log('Dragorder[' + curdrag + ']=' + dragorder[eval('' + curdrag)] + ' vs tw=' + tw + ' and overall;goes=' + overallgoes);
var decs=document.title.split('.');
curdrag++;
overallgoes++;
if (eval('' + decs.length) >= 3) {
document.title=document.title.replace('.' + decs[1] + '.', '.' + curdrag + '/' + overallgoes + '.');
}
oplist[eval('' + tw)].close();
return null;
}

// Quiz only code follows
}

… code.

It must be in the correct order (and not interrupted by quiz answer completions) to score, and you are timed, so you can try improving over time, using a document.title score presentation as per …


[QuizScore].[CardOrderGameScore]/[QuizAnswerAttemptCount].[SecondsElapsed] [MultiPlayerQuizScoreGoesBreakdown] is User: Score/Goes - RJM Programming - April, 2021

… so that both usages for the web application can be accommodated for in the changed cards_usefocus.html code behind the “Just Javascript” live run we welcome you to try for yourself.


Previous relevant Just Javascript Quiz Drag Tutorial is shown below.

Just Javascript Quiz Drag Tutorial

Just Javascript Quiz Drag Tutorial

Adding to yesterday’s Just Javascript Quiz CSS Styling Tutorial we have added some …

  • non-mobile platform, only …
  • drag and drop functionality … for …
  • the child popup windows

… achieved through the comparison of …

  • original [popupWindow].screenLeft and [popupWindow].screenTop … initially, to …
  • [popupWindow].screenLeft and [popupWindow].screenTop over time

… and if one popup is dragged to overlay another it is closed, or you, as the user, can just drag and drop for clarity, leaving the popup window of the next quiz question out in the open, perhaps.

In order to achieve this, and keep backward compatibility we needed to delay the quiz question prompt window via …

  1. document.hasFocus() is true … then if …
  2. inhouse dragging checks clear it of overlaying another popup (in which case that popup is programmatically closed, allowing another popup to become the “focus window”) … then …
  3. delay (by 8 seconds) the prompt window (and in that time the user can be dragging popups (but no popups were harmed in the making of this tutorial)) … via …

    setTimeout(function() { hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } else { hj=window.opener.assess(hj); } if (hj.replace(def,'') != '') { checka(hj); } else { setTimeout(pa,10000); } aminmiddle=false; }, 8000);

… you can see in amongst the changed cards_usefocus.html code behind the “Just Javascript” live run you are welcome to try for yourself … best on non-mobile.

Still “No Body Definition”, “Just Javascript”!


Previous relevant Just Javascript Quiz CSS Styling Tutorial is shown below.

Just Javascript Quiz CSS Styling Tutorial

Just Javascript Quiz CSS Styling Tutorial

Our “Just Javascript” adage used throughout this blog posting thread, up until today, headed by yesterday’s Just Javascript Quiz Content Management Tutorial needs more explanation. Really what we are trying to do might better be described as “No Body Definition” (ie. no defined document.body) but have …

  1. an HTML webpage (ie. within <html> and </html>) … has …
  2. <head> and </head> (ie. document.head) content which can be made up of (at least) title, style, script, link, meta tags

To assert “Just Javascript” is just to allow script content above, but what we should really say is “Just Head Content” but that is not nearly so marketable, is it now?!

The thing is, though, we can dynamically add title, style, link, meta tag content within the script content, and we do this more than statically define it, to feel better about our ethics saying “Just Javascript”.

Dynamically adding style CSS styling either …

  • using Javascript DOM (not available to us for document.getElementById([elementID] and nor can we use inline CSS via style=”[CSSstyling]” statically within HTML element code for that same reason) ideas today though … remember “No Body Definition” … but …
  • we can append to <head> and </head> (for today’s scenario) as per …

    document.head.innerHTML+="<style> html { background-color: yellow; font-size: 36px; background: URL('//www.rjmprogramming.com.au/rjmquiz.jpg'); background-size: cover; } </style>";

… allowing (into the scope of our work CSS styling of) background (image(s)) and other background styling ideas that can get us past the anonymous feel the web application had before today. We tailored the background image above to suit our Quiz and help it be a bit more self explanatory … thanks CSS styling! We add onto the child “card” popup windows, their own background image colour and pizazz, to cheer things up in CSS styling enhanced cards_usefocus.html code behind the “Just Javascript” live run.

You may well ask …

What can we hang our hat on with CSS style selectors without a body element?

Well, we had to step out of our usual comfort zone of CSS styling thinking, and realize, even without that body element we can still use the html selector to “point at” the entirety of your webpage of interest.


Previous relevant Just Javascript Quiz Content Management Tutorial is shown below.

Just Javascript Quiz Content Management Tutorial

Just Javascript Quiz Content Management Tutorial

It feels like an “onions of the 4th dimension” idea to allow the user to control the questions and answers behind the workings of yesterday’s Just Javascript Quiz Multiple Users Tutorial‘s web application, featuring “Just Javascript”.

It’s not “Just Javascript” we’re keeping, it’s “Just HTML” client work rather than involving any serverside anything (eg.PHP) and yet this question and answer data could be quite sizeable. What can we use, given no PHP serverside, and given we’ve decided not to navigate via Ajax/FormData techniques? How about “the better than HTTP Cookies” twins …

Yep, set up a means by which these two can store and restore questions and answers entered by the user, using these storage methods above.


function reassess() {
var retv='', ewq;
var retcols=[];
var ir=0;
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '') {
//alert('0:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?!')[0] + '?');
asq.push(retcols[ir].split('?!')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '') {
//alert('1:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?')[0] + '?');
asq.push(retcols[ir].split('?')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
}


function assess(what) {
var ewq, retv='';
if (what.toLowerCase() == '?x') {
sslistq=[];
sslista=[];
if (window.sessionStorage) {
try {
window.sessionStorage.removeItem('cards_usefocus_session');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase() == '?!x') {
lslistq=[];
lslista=[];
if (window.localStorage) {
try {
window.localStorage.removeItem('cards_usefocus_local');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase().indexOf('?!') != -1) {
if (what.toLowerCase() == '?!') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.localStorage) {
if (lslistq.length == 0) {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', encodeURIComponent(what));
} else {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', window.localStorage.getItem('cards_usefocus_local') + encodeURIComponent('~' + what));
}
}
return '';
} else if (what.toLowerCase().indexOf('?') != -1) {
if (what.toLowerCase() == '?') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.sessionStorage) {
if (sslistq.length == 0) {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', encodeURIComponent(what));
} else {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', window.sessionStorage.getItem('cards_usefocus_session') + encodeURIComponent('~' + what));
}
}
return '';
} else {
firstbit='';
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
}
return what;
}

The fairly significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz Multiple Users Tutorial is shown below.

Just Javascript Quiz Multiple Users Tutorial

Just Javascript Quiz Multiple Users Tutorial

Adding to yesterday’s Just Javascript Quiz via Cards Tutorial we were surprised how difficult it was to stay with “Just Javascript” and allow for multiple player play.

We didn’t opt for the parent to ask about the number of players, curiously, but on the second quiz answer and on, offered any non first player the chance to identify themselves as a new player into the game by appending their answer with a space character.

The implication of that is that we’ll want to run Javascript functions of the parent from the children as per


oplist[eval(-1 + oplist.length)].document.write("<link rel=icon href=" + cards[kl] + "><scr" + "ipt type='text/javascript'> var da='" + eval(0 + kq) + "'; var dp='Given answer is integer from 0 to 25 ... " + sq[kq] + "'; var def=String.fromCodePoint(" + spcps[eval('' + kl)].split('/')[0] + "); function checka(tpa) { var os=''; var ps=eval(window.opener.document.title.split('/')[0].trim()); var pg=eval(window.opener.document.title.split('/')[1].split(' ')[0]); if (tpa.trim() == da) { ps++; os=tpa.split(da)[1]; } else { pg++; os=tpa.split(tpa.trim())[1]; } window.opener.document.title=ps + os + '/' + pg + ' is User Score/Goes'; window.close(); } function pa() { if (document.hasFocus()) { var hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } if (hj.replace(def,'') == '') { setTimeout(pa,1000); } else { checka(hj); } } else { setTimeout(pa,1000); } } pa(); </scr" + "ipt>");

… accessing …


function blurb() { // theblurb and wblurb are global variables changed elsewhere
if (wblurb == ' Hello Player 1' && theblurb == ' If you are player 2 rather than player 1 append space to your answer.') {
theblurb='';
wblurb='';
}
return theblurb + wblurb;
}

… giving the rather curious behaviour whereby a Javascript prompt window can be dynamically different from one document.hasFocus() incarnation (ie. the user might go away and answer another “card” Number Quiz question) to another (even not attending to answering the Javascript prompt window) … huh?!

The significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz via Cards Tutorial is shown below.

Just Javascript Quiz via Cards Tutorial

Just Javascript Quiz via Cards Tutorial

Yesterday’s Just Javascript Navigation Tutorial continues our interest in “Just Javascript” (or “No Body”) web applications.

We think today’s “Numbers Quiz” via a “Card Deck” organizational design ups the ante on all this. We realize now what we have been missing not having involved document.hasFocus() in any of our popup window scenarios. Today, at least on non-mobile, we involve 52 such popup windows each containing a “Number Quiz” question presented as a Javascript prompt (sub-)window. This would not be feasible without document.hasFocus() as you can tell if you examine the cards_usefocus.html code behind the “Just Javascript” live run best used on your non-mobile platforms where popup windows can sit in front of parent (and beside sibling) windows, whereas mobile platforms open new web browser tabs for all the 52 windows of (a card deck) design.

Look out, too, in the code above, for use of window.opener back reference from a popup window back to the parent window where the scoring data is held, and updated by each popup window because of that window.opener avaalability.


Previous relevant Just Javascript Navigation Tutorial is shown below.

Just Javascript Navigation Tutorial

Just Javascript Navigation Tutorial

The recent use we made of …


document.createElement/click()

… got us thinking of the “Just Javascript” (or No Body) blog posting thread headed by Just Javascript Webmail No Body Attachment Tutorial.

As such, today we present the very simple (but first time use of the interesting hasFocus) “proof of concept” …


<html>
<head>
<script type='text/javascript'>
function dothis() {
var ais=null;
var urlis=' ';
while (urlis != '') {
if (document.hasFocus()) {
urlis=prompt('Enter URL that we will send you to (exit to stop)', '');
} else {
setTimeout(dothis, 2000); // urlis=' ';
return;
}
if (urlis == null) { urlis=''; }
if (urlis.toLowerCase() == 'exit') { return; }


if (urlis.trim() != '') {
if (urlis.substring(0,1) == '.') { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
} else if (urlis.substring(0,1) == '/' && urlis.indexOf('//') == -1) { // relative URL
urlis=document.URL.split('//')[0] + '//' + document.URL.split('//')[1].split('/')[0] + '/' + urlis;
} else if (urlis.split('/')[0].indexOf('.') != -1) { // absolute URL
if (urlis.toLowerCase().indexOf('http') != 0) {
if (urlis.indexOf('//') == 0) {
urlis=document.URL.split('//')[0] + urlis;
} else {
urlis=document.URL.split('//')[0] + '//' + urlis;
}
}
} else { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
}
ais=document.createElement('a');
ais.onclick=function() { window.open(urlis, '_blank', 'top=100,left=100,width=600,height=600'); };
if (1 == 2) { ais.href=urlis; }
ais.target='_blank';
ais.click();
}
}
setTimeout(dothis, 2000); // urlis=' ';
}


dothis();

</script>
</head>
</html>

nobody.html‘s live run link for you to use a Javascript prompt popup window’s user interaction results to navigate to a new webpage, as applicable. Bookmarklets may be scarce on the ground, but these “Just Javascript” ideas continue the Bookmarklet Spirit of the past!


Previous relevant Just Javascript Webmail No Body Attachment Tutorial is shown below.

Just Javascript Webmail No Body Attachment Tutorial

Just Javascript Webmail No Body Attachment Tutorial

A “hard liner” for the proper use of “business emails” could argue that an email without an attachment is not productive. Couldn’t you just have a face to face meeting instead, if there is just wording in the email (as we somewhat concur with, as an argument)? So yesterday’s Just Javascript Webmail No Body Tutorial had that limitation of no email attachment logic, which we remedy today.

And this is where PHP’s wonderful file_get_contents (function) means by which we garner (URL) content …

  • definitely works with “relative URLs” relative to HTTP://www.rjmprogramming.com.au/HTMLCSS/ where today’s unchanged webmail_nobody.html resides … in “parsing parlance” …

    "relative (URL)" to the left of any # or ? of what lies to the left of the most right hand "/" (of what the address bar URL is of the webpage you are on)

    … so that …

    1. “relative URLs” starting with “./” (followed by the filename, or just the filename (as you can see us using in today’s tutorial picture)) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/HTMLCSS/” … whereas, for example …
    2. “relative URLs” starting with “../” (followed by the filename) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/” … for example

    … and …

  • might work for “absolute URLs” (those that start with https: or HTTP: or even // (that we beg you not to confuse with Windows UNC pathnames) that infer a transport protocol of the transport protocol (out of https: or HTTP: or even file:) that got you to the webpage you are currently on), the “might” being far more likely on “absolute URLs” pointing to the same domain as indicated on the URL of the address bar of the webpage you are currently on

Upshot is, the user in their email Body section definitions (still no HTML body though!), can throw into any word they use, an “absolute URL” of interest, or a “relative URL” of interest, of files they want to attach (as attachments, doh!) in their email.

Depending on the email rules though, there are limits as to the amount of attachment data allowed. We’ll leave that to you intrepid “explorers of the Net” to discover for yourselves. On this subject though, have you noticed that with the Photos (or Gallery) app Share options, the Email option drops off when you have highlighted a large number of photos or videos or audios to share? That’s that email limit coming into play.

So feel free to try this HTML-body-less web application live run to see what we mean here. Though the parent HTML is unchanged today, the new (email) attachment functionality needed a changed PHP emailhtml.php to make this happen.

Did you know?

This (relative URL) “../” navigation backwards up the hierarchy of the web server directories will, if repeated (ie. nested to “../../” etcetera) too many times, get you into uncharted unnavigable (web server directory) places relative to that web server web site’s Document Root (below which you can not access in public webpages, normally). But when you perform similar thinking with “absolute URLs” and go “HTTP://www.rjmprogramming.com.au/HTMLCSS/../../../blahdeblah.jpg” (in a web browser address bar) for instance, you cannot get into trouble, as you just don’t get beyond this sending you to (attempt the reference to) “HTTP://www.rjmprogramming.com.au/blahdeblah.jpg” because on this rjmprogramming.com.au Apache domain the correspondence of the Document Root (web server directory) is to “HTTP://www.rjmprogramming.com.au/” as the place you are not allowed (and cannot) go below in the hierarchy tree.


Previous relevant Just Javascript Webmail No Body Tutorial is shown below.

Just Javascript Webmail No Body Tutorial

Just Javascript Webmail No Body Tutorial

Were you around and interested in our series of about three blog postings in the series on the theme of creating webpage functionality of some interest, involving no Javascript, when we presented Missing Javascript Audio on Unmute Tutorial? Well, today, it’s the turn of “just Javascript”, which is sort of like what Bookmarklets were about.

With today’s “just Javascript” we have to qualify that a little for our webmail emailing sender application with the architecture …

  • parent webpage with only document.head and apart from a document.title just a script Javascript tag of content (using Javascript prompt windows to ask for user information) …
  • sending (POSTing) data via …
    1. Ajax XMLHttpRequest object … as the conduit for …
    2. FormData object

    … to our changed

  • PHP communication emailing tool emailhtml.php … and out to …
  • the emailee (out there in the big wide woooorrrrrllllldddd)

Guess we find it interesting that you can do all this (sending of email to emailee recipients) with no document.body in sight.

So take a look at that parent webmail_nobody.html‘s live run link to see what we mean here, and/or watch the video below …


Previous relevant Missing Javascript Audio on Unmute Tutorial is shown below.

Missing Javascript Audio on Unmute Tutorial

Missing Javascript Audio on Unmute Tutorial

Our “third cab off the rank” following on from yesterday’s Missing Javascript Stop Watch Tutorial “missing Javascript” ideas is an HTML div nesting scenario using just …

  1. HTML
  2. CSS

… again, with some or all of the “usuals” below …

  • calc method to assist with defining width and height and size dimensions along with operator “+” and/or “-” offset calculation opportunities, and which we’d have used the Javascript window.getComputedStyle and/or [element].getBoundingClientRect methods to cover this (in a much more unwieldy way, as you would probably surmise)
  • CSS variables we started talking about here at CSS Variables Primer Tutorial
  • CSS3 @keyframes rules we first talked about at CSS3 @keyframes Rule Primer Tutorial that assist with animations that we can make work via …
  • CSS3 transitions for scheduled functionality (we’d have used Javascript setTimeout (and setInterval) methods to cover the same “territory”) we first talked about at CSS3 Transition Primer Tutorial … specified with CSS Criteria involving …
  • CSS Selectors :after and :before (and often, as for today’s work, with the content: CSS property) first talked about here with WordPress Bullet Point CSS Styling Primer Tutorial … and, today …
  • CSS3 transform property’s rotate (and translate and scale) settings (for the puppy dog body movements) … as well as the idea that …
  • On non mobile platforms you can set up the playing of “audio” data via the use of an HTML audio tag with the properties …
    1. controls
    2. autostart
    3. loop
    4. muted

    Stop Press

    Above is all fine and good for non-mobile but not so good for mobile, so to keep all happy with the one click, still, is to transfer HTML coding from …


    <audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" />

    … to …


    <!--audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" /-->
    <audio id='myaudiotwo' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="margin-left:-350px;opacity:0.1;" autostart="0" loop controls src="Puppy-sounds.mp3" />

    … and a src= URL data source (as we thank this link for today), or data URI if preferred (which we do for today’s image data from this link, thanks (when we were researching animated GIF data URIs (which we may return to at a later date))

… that sets up the scenario that all the user has to do to hear the audio is to click the “muted” control button, without needing the usual Javascript play() methods … but not on mobile!

Feel free to let the puppy play, that uses the HTML and CSS (but no Javascript) of the_nested.html and based largely on the previous HTML Nested Centering via Multiple Select Tutorial so that these changes reflect how we got to the first draft of today’s work. Maybe some of the ideas are of interest. We hope so!


Previous relevant Missing Javascript Stop Watch Tutorial is shown below.

Missing Javascript Stop Watch Tutorial

Missing Javascript Stop Watch Tutorial

Following on from yesterday’s Missing Javascript Primer Tutorial our second “cab off the rank” for “missing Javascript” ideas is a stop watch featuring just …

  1. HTML
  2. CSS

… again, setting up document.body load instigated

… which we needed to do to make multiple animations happen, but we used animation-delay:5s; to delay its start. The hands (second and minute, hence the two animations) are “overlay”

… feeling HTML horizontal rule elements that also feature linear gradients, to emphasise (in red) the “pointy end” of the “hand conversation” (good on walls with shadows … but we digress).

Feel free to let loose the stop watch that uses the HTML and CSS (but no Javascript) of stop_watch.html for today’s instructional information. Thanks to Clipart – stop watch for the great clip art used.


Previous relevant Missing Javascript Primer Tutorial is shown below.

Missing Javascript Primer Tutorial

Missing Javascript Primer Tutorial

If you were to ask me which programming component is most vital to web application development, I’d not be Robinson Crusoe in saying …

Without a doubt, Javascript

… and with that thought in mind we have a two pronged motive to see how far we go developing some web applications that “don’t use Javascript”, calling into play the …

  • meaning of “missing”, as in, our code is “missing” Javascript … as well as how I feel with the masochism of the exercise, calling into play the …
  • meaning of “missing”, as in, it’s hard work writing meaningful web applications without Javascript … but I guess we’ll learn a bit from the exercise of “see where we go”, allowing for the fact, not today, but down the track, that we will allow the use of server-side languages such as PHP

Okay, so, given that restriction, let’s see today’s challenge, to just use, in a web application …

  1. HTML
  2. CSS

… and here is where we have to point out that CSS3 introduced to us some functionality that improves the prospects for web application design “interest” without using Javascript (though it is hard to convince me even so, that I am not “missing” Javascript) here. CSS3 introduced to us …

… and we use all of these in our Festive Season themed web application today, you can try at this live run‘s calc_use.html (free of any Javascript (but “why” springs to mind … because it is NOT there, perhaps?)).

Here’s the other thing about today. Our long sought after “just make the body background be semi-transparent” but not its foreground parts, was solved, for us via the great advice of …

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

Just Javascript Memories SVG Emoji Background Tutorial

Just Javascript Memories SVG Emoji Background Tutorial

Just Javascript Memories SVG Emoji Background Tutorial

Yesterday’s Just Javascript Memories SVG Emoji Cursor Tutorial had good and bad news related to SVG Emoji Cursors?

  • the bad news is that this CSS cursor concept does not work on mobile platforms for similar reasons to why onmouseover does not work … to hover over the mobile device screen means nothing to event logic … while …
  • the good news is that the same type of data-uri of SVG content can work for a (mobile CSS) background image as it can work for (non-mobile CSS) cursor

… and so we can show, ahead of time, via a background image, news about the Memories game on mobile platforms (that are missing that CSS cursor methodology of showing similar information) … as per


var dhi='';
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
covercover=',80px 60px,80px 60px';
prevsb=String.fromCodePoint(10067,10068) + csuff;
dhi='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
document.head.innerHTML+=dhi;
} else {

document.head.innerHTML+='<style> html { cursor: url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + '//www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer; } </style>';
}

… used as per code exemplified by


if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace(';background-size:', ',repeat,repeat' + ';background-size:');
} else {

defstyle=defstyle.replace(';background-size:', ',no-repeat,no-repeat' + ';background-size:');
}
if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && ocp) {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + opc.style.cursor.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else if ((nominal_numplayers && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) && dhi != '') {
defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(' + dhi.split('url(')[1].split(') ')[0] + '); } </style>'); // + ' ' + owidth + ' ' + oheight
} else {

defstyle=defstyle.replace('; } </style>', ',linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)),url(//www.rjmprogramming.com.au' + backi + '); } </style>'); // + ' ' + owidth + ' ' + oheight
}

So yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories SVG Emoji Cursor Tutorial is shown below.

Just Javascript Memories SVG Emoji Cursor Tutorial

Just Javascript Memories SVG Emoji Cursor Tutorial

The “Memories” functionality introduced in yesterday’s Just Javascript Memories Card Game Tutorial is a game component, and it is good to remember the “game” side to that. If a web application is a game and the player is not being timed, they may feel that freedom to be multitasking, go and do something else, and then come back “to work the game”. In that scenario, it would be quite friendly to offer a mechanism by which to remind the player(s) of the status of the game as they left it.

Even though we are in “Just Javascript” (ie. “No Body Definition”) mode of use here, we still have CSS to offer a solution here, and we’ve chosen in the CSS woooooorrrrrllllllddd to research a curiosity we’ve had “for just about ever”. Can we tailor the webpage “cursor” to be “emoji text content”. We’ve looked this up in the past, and did not succeed on that occasion with the “url([SVGcontent])” we thought might be the go. It was tweaking onto this great link that gave examples for us to succeed this time, thanks, using code such as …


csuff='';
var hjg='' + curplayer;
for (var ipl=0; ipl<hjg.length; ipl++) {
csuff+=String.fromCodePoint(eval(8320 + eval(eval('' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0)) - 48)));
}
if (ocp) { ocp.style.cursor='url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + 'HTTP://www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer'; }

… that “ocp” being the “evt.target” of the “onlick” event logics previously talked about. Notice the fallback to those set cursors of “the cursor wooooorrrrrllllllddd”.

Along the way we offer variations to the playing rules of Memories, too, to add some variety for the user(s).

Yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories Card Game Tutorial is shown below.

Just Javascript Memories Card Game Tutorial

Just Javascript Memories Card Game Tutorial

Up until yesterday’s Just Javascript Card Order Game One Window Tutorial every mode of execution of our web application involved the Javascript prompt (popup) window method of getting information off the user.

Today, though, adding a Memories Card Game new functionality part uses a hybrid Javascript prompt window arrangement …

  • a first usage is to use the default Javascript prompt window arrangement you glean from the user the number of players in the Memories Card Game to follow …
  • and then from then on

    var lasttogglenumber='';
    var lastec='', notyet=false;
    var backi="/rjmquiz_plus.jpg";
    var fiftytwo=52;
    var message='';
    var lastcard='';
    var lasttto='';
    var gamescoreprefix='';
    var gamescores=[0];
    var lasttmid='';
    var lasttfrom='';
    var lasttoggleto='';
    var lasttogglefrom='';
    var curplayer=1, card_of_play=0;
    var card_game='memories';
    var nominal_implication='';
    var nominal_numplayers = (document.URL.replace('?','&').indexOf('&card') != -1) ? prompt('How many players are playing your ' + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(0,1).toUpperCase() + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(1).toLowerCase() + ' card game?', '2') : null;

    if (nominal_numplayers) {
    if (('' + nominal_numplayers).replace('0','').trim() != '' && ('' + nominal_numplayers).replace('0','').trim().indexOf('-') == -1) {
    var prompt = function(zwords, defwords){ return null; };
    nominal_implication=" var prompt = function(zwords, defwords){ return null; }; ";
    fiftytwo=-1;
    backi="/Games/Memories/Memories.jpg";
    } else {
    nominal_numplayers=null;
    }
    }

… “prompt” is overridden as above. That, and overriding the scoring mechanisms, and this same codeset is nearly there towards accommodating our new quite different requirement.

But with “No Body Definition”/”Just Javascript” how can we show and implement this new Memories Card Game usage? It’s a two way integration, the easier one being …

  • offer a place for click/touch on the default background imagery … and with that webpage reminder …
  • what is an independent “add on” event methodology available to us, so as not to interfere with event logic that has preceded? … spoiler alert … double click …

    ele.addEventListener('dblclick', function(evt) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    });

    … (or two clicks quickly in a row) … as per

    var lastec='', notyet=false;


    function antilastec() {
    lastec='';
    }


    function antinotyet() {
    notyet=true;
    }


    ele.addEventListener('click', function(evt) {
    if (evt.touches) {
    if (evt.touches[0].pageX) {
    iourx = evt.touches[0].pageX;
    ioury = evt.touches[0].pageY;
    } else {
    iourx = evt.touches[0].clientX;
    ioury = evt.touches[0].clientY;
    }
    //alert('' + iourx);
    } else if (evt.clientX) {
    iourx = evt.clientX; // - elemLeft;
    ioury = evt.clientY; // - elemLeft;
    } else if (!evt.touches) {
    iourx = evt.pageX; // - elemLeft;
    ioury = evt.pageX; // - elemLeft;
    }
    if (('' + iourx + ',' + ioury) == lastec && lastec != '' && notyet) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    } else if (lastec == '') {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    } else {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    }

    clickedmaybe();
    });

Again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game One Window Tutorial is shown below.

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

The “one window” rather than (52 + 1) = 53 windows scenario set up as a possibility with yesterday’s Just Javascript Card Order Game Mobile Tutorial had us wondering …

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

… and tomorrow is today. We’ve decided not to make the one window scenario the default for non-mobile platforms, but serve as a fallback for some of the scenarios mentioned below …

  • the user gets blocked from using the popup windows on their non-mobile platform web browser … big possibility!
  • the user clicks half way through the popup window incarnation the parent window … all the child popups disappear behind … annoying … so

    var flexible=false;

    function secsu() {
    var ewd;
    if (secs == 0) {
    if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    flexible=false;
    } else {
    flexible=true;
    console.log('Flexible=T');
    }

    setTimeout(blater, 2500);
    }
    if (eval('' + overallgoes) < 52) {
    secs++;
    } else if (document.title.indexOf('Congratulations') == -1) {
    document.title+=' ... Congratulations! End of Game! Refresh webpage to try again.';
    }
    var decs=document.title.split('.');
    if (eval('' + decs.length) >= 3) {
    document.title=document.title.replace('.' + decs[2].split(' ')[0] + ' ', '.' + secs + ' ');
    } else {
    ps=document.title.split('/')[0].trim();
    pg=document.title.split('/')[1].split(' ')[0];
    if (ps.indexOf('.') == -1 || pg.indexOf('.') == -1) {
    ps=eval('' + overallscore + '.' + psecs); //eval(document.title.split('/')[0].trim());
    pg=eval('' + overallgoes + '.' + secs);
    document.title=document.title.replace(document.title.split(' ')[0], '' + overallscore + '.' + psecs + '/' + '' + overallgoes + '.' + secs);
    //console.log('document.title becomes ' + document.title);
    } else {
    ps=eval(ps);
    pg=eval(pg);
    }
    }


    if (flexible) {
    if (document.hasFocus()) {
    flexible=false;
    console.log('Flexible=F');
    lastzkq='';
    lastzkl='';
    owidth=oowidth;
    oheight=ooheight;
    for (var igh=0; igh<oplist.length; igh++) {
    opltlistl[igh]=oopltlistl[igh];
    opltlistt[igh]=oopltlistt[igh];
    if (oplist[igh]) {
    console.log('Flexible=F' + igh);
    if (!oplist[igh].closed) {
    try {
    oplist[igh].close();
    oplist[igh]=null;
    } catch(ewd) {
    }
    } else {
    oplist[igh]=null;
    }
    }
    }
    }
    }

    }

… document.hasFocus() to the rescue again … the multiple background images of yesterday’s work being a default part of any incarnation, and whether the click event logic of yesterday becomes relevant depends on …

  • if user is a mobile platform user, always relevant
  • user enters URL with argument like ?onewindow=y then is always relevant … else …
  • a scenario as above means that from that point on, the multiple background image one window click on cards modus operandi becomes relevant

We improve the web browser conditions too, if a non-mobile user “clicks half way through the popup window incarnation the parent window” in that we programmatically close any open child popup windows! Phew!

Feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game Mobile Tutorial is shown below.

Just Javascript Card Order Game Mobile Tutorial

Just Javascript Card Order Game Mobile Tutorial

Yesterday’s Just Javascript Card Order Game Tutorial mobile usage scenario was impractical, in that mobile platforms can not work popup windows in front of a parent window. Can we convert those non-mobile popup windows into … well … what exactly?

Well, in order to keep to our “Just Javascript” (ie. “No Body Definition”) pledge with this project, we needed to simulate those popups as background image parts, in the sense that you can have multiple background images these days with your HTML. Even with html as your CSS styling selector … it pans out … we needed to prove that today.

Also, today, for the first time, we achieved via …

  1. comma separated background-repeat: no-repeat; list
  2. comma separated background-size list (set popup width height list until last one bigger (based on screen.width screen.height) for the parent background image (no-repeat))
  3. comma separated background-position list (as per what window.open in non-mobile was using for left top until last one’s 0px 0px)
  4. comma separated background-image list (as per what window.open in non-mobile was using for URL([imageURL]) until last one’s linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)), url(//www.rjmprogramming.com.au/rjmquiz_plus.jpg))

… as per (the previous “window.open” becomes “windowopen”) …


function windowopen(one, two, three) {
if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
console.log('Here ' + kq);
opltlistl.push((three.split('left=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + one.split('spcp=')[1].split('&')[0]));
opltlistt.push((three.split('top=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + kq));
owidth=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
oheight=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
if (defstyle.indexOf('background: URL(') != -1) {
defstyle=defstyle.split('background: URL(')[0] + 'background-repeat:no-repeat;background-size:' + owidth + 'px ' + oheight + 'px;background-position:' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image: url(' + cards[eval('' + donelist[eval(-1 + donelist.length)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'; // + ' ' + owidth + ' ' + oheight
} else {
defstyle=defstyle.replace(';background-image:', (',' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image:');
defstyle=defstyle.replace('no-repeat','no-repeat,no-repeat');
defstyle=defstyle.replace('background-size:' + owidth + 'px ' + oheight + 'px','background-size:' + owidth + 'px ' + oheight + 'px,' + owidth + 'px ' + oheight + 'px');
defstyle=defstyle.replace('; } </style>', ',url(' + cards[eval('' + donelist[eval(0 + ijk)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'); // + ' ' + owidth + ' ' + oheight
}
return null;
}
return window.open(one, two, three);
}

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

We needed to add event logic we were not sure would work at the start of the day, and saw it working by the end, with …


var iourx=-1, ioury=-1;

function blater() {
if (1 == 2 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
window.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
eles = document.querySelectorAll("*")
for (var ele of eles) {
console.log('yes well');
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ele.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('touchmove', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('click', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
ele.addEventListener('click', function(evt) {
if (evt.touches) {
if (evt.touches[0].pageX) {
iourx = evt.touches[0].pageX;
ioury = evt.touches[0].pageY;
} else {
iourx = evt.touches[0].clientX;
ioury = evt.touches[0].clientY;
}
//alert('' + iourx);
} else if (evt.clientX) {
iourx = evt.clientX; // - elemLeft;
ioury = evt.clientY; // - elemLeft;
} else if (!evt.touches) {
iourx = evt.pageX; // - elemLeft;
ioury = evt.pageX; // - elemLeft;
}
clickedmaybe();
//alert('here');
});
}
}
}
}

See this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform) we, again, welcome you to try for yourself.


Previous relevant Just Javascript Card Order Game Tutorial is shown below.

Just Javascript Card Order Game Tutorial

Just Javascript Card Order Game Tutorial

Today we’ve made the web application of yesterday’s Just Javascript Quiz Drag Tutorial “dual purpose” …

  • quiz … as for yesterday, and before … and as of today, making more use of the card organizational side to the popup windows we introduce …
  • card order game

This card order game asks you to force the focus of the correct popup window (to score in the Card Order Game) in the order as designated by the background image part we have added today, and supported by the following Javascript “mapping” code …


var dragorder=[], curdrag=0;

var cards=["//www.rjmprogramming.com.au/images/01s.gif?n=7",
"//www.rjmprogramming.com.au/images/02s.gif?n=16",
"//www.rjmprogramming.com.au/images/03s.gif?n=33",
"//www.rjmprogramming.com.au/images/04s.gif?n=29",
"//www.rjmprogramming.com.au/images/05s.gif?n=8",
"//www.rjmprogramming.com.au/images/06s.gif?n=35",
"//www.rjmprogramming.com.au/images/07s.gif?n=52",
"//www.rjmprogramming.com.au/images/08s.gif?n=51",
"//www.rjmprogramming.com.au/images/09s.gif?n=12",
"//www.rjmprogramming.com.au/images/10s.gif?n=30",
"//www.rjmprogramming.com.au/images/11s.gif?n=1",
"//www.rjmprogramming.com.au/images/12s.gif?n=36",
"//www.rjmprogramming.com.au/images/13s.gif?n=22",
"//www.rjmprogramming.com.au/images/01h.gif?n=32",
"//www.rjmprogramming.com.au/images/02h.gif?n=23",
"//www.rjmprogramming.com.au/images/03h.gif?n=3",
"//www.rjmprogramming.com.au/images/04h.gif?n=18",
"//www.rjmprogramming.com.au/images/05h.gif?n=28",
"//www.rjmprogramming.com.au/images/06h.gif?n=39",
"//www.rjmprogramming.com.au/images/07h.gif?n=45",
"//www.rjmprogramming.com.au/images/08h.gif?n=48",
"//www.rjmprogramming.com.au/images/09h.gif?n=50",
"//www.rjmprogramming.com.au/images/10h.gif?n=44",
"//www.rjmprogramming.com.au/images/11h.gif?n=4",
"//www.rjmprogramming.com.au/images/12h.gif?n=9",
"//www.rjmprogramming.com.au/images/13h.gif?n=5",
"//www.rjmprogramming.com.au/images/01d.gif?n=27",
"//www.rjmprogramming.com.au/images/02d.gif?n=41",
"//www.rjmprogramming.com.au/images/03d.gif?n=20",
"//www.rjmprogramming.com.au/images/04d.gif?n=11",
"//www.rjmprogramming.com.au/images/05d.gif?n=37",
"//www.rjmprogramming.com.au/images/06d.gif?n=49",
"//www.rjmprogramming.com.au/images/07d.gif?n=42",
"//www.rjmprogramming.com.au/images/08d.gif?n=6",
"//www.rjmprogramming.com.au/images/09d.gif?n=21",
"//www.rjmprogramming.com.au/images/10d.gif?n=31",
"//www.rjmprogramming.com.au/images/11d.gif?n=40",
"//www.rjmprogramming.com.au/images/12d.gif?n=43",
"//www.rjmprogramming.com.au/images/13d.gif?n=17",
"//www.rjmprogramming.com.au/images/01c.gif?n=46",
"//www.rjmprogramming.com.au/images/02c.gif?n=19",
"//www.rjmprogramming.com.au/images/03c.gif?n=47",
"//www.rjmprogramming.com.au/images/04c.gif?n=25",
"//www.rjmprogramming.com.au/images/05c.gif?n=10",
"//www.rjmprogramming.com.au/images/06c.gif?n=15",
"//www.rjmprogramming.com.au/images/07c.gif?n=13",
"//www.rjmprogramming.com.au/images/08c.gif?n=26",
"//www.rjmprogramming.com.au/images/09c.gif?n=38",
"//www.rjmprogramming.com.au/images/10c.gif?n=34",
"//www.rjmprogramming.com.au/images/11c.gif?n=2",
"//www.rjmprogramming.com.au/images/12c.gif?n=14",
"//www.rjmprogramming.com.au/images/13c.gif?n=24"];


for (var ic=1; ic<=cards.length; ic++) {
found=false;
for (var jc=1; jc<=cards.length; jc++) {
if ((cards[eval(-1 + jc)] + '~').indexOf('?n=' + ic + '~') != -1) {
dragorder.push(eval(-1 + jc));
cards[eval(-1 + jc)]=cards[eval(-1 + jc)].replace('?n=' + ic, '');
firstbit+=String.fromCodePoint(eval('' + spcps[eval(-1 + jc)].split('/')[0])) + ' ';
found=true;
}
}
}

… and “making use of” this and the new codeline as popups are created … oplist[eval(-1 + oplist.length)].document.name=” + kl; we have …


function ourprompt(tw, blb, bdef) {
var kijk;
if (oplist[eval('' + tw)].document.name == ('' + dragorder[eval('' + curdrag)]) && eval('' + curdrag) == eval('' + overallgoes)) {
console.log('Dragorder[' + curdrag + ']=' + dragorder[eval('' + curdrag)] + ' vs tw=' + tw + ' and overall;goes=' + overallgoes);
var decs=document.title.split('.');
curdrag++;
overallgoes++;
if (eval('' + decs.length) >= 3) {
document.title=document.title.replace('.' + decs[1] + '.', '.' + curdrag + '/' + overallgoes + '.');
}
oplist[eval('' + tw)].close();
return null;
}

// Quiz only code follows
}

… code.

It must be in the correct order (and not interrupted by quiz answer completions) to score, and you are timed, so you can try improving over time, using a document.title score presentation as per …


[QuizScore].[CardOrderGameScore]/[QuizAnswerAttemptCount].[SecondsElapsed] [MultiPlayerQuizScoreGoesBreakdown] is User: Score/Goes - RJM Programming - April, 2021

… so that both usages for the web application can be accommodated for in the changed cards_usefocus.html code behind the “Just Javascript” live run we welcome you to try for yourself.


Previous relevant Just Javascript Quiz Drag Tutorial is shown below.

Just Javascript Quiz Drag Tutorial

Just Javascript Quiz Drag Tutorial

Adding to yesterday’s Just Javascript Quiz CSS Styling Tutorial we have added some …

  • non-mobile platform, only …
  • drag and drop functionality … for …
  • the child popup windows

… achieved through the comparison of …

  • original [popupWindow].screenLeft and [popupWindow].screenTop … initially, to …
  • [popupWindow].screenLeft and [popupWindow].screenTop over time

… and if one popup is dragged to overlay another it is closed, or you, as the user, can just drag and drop for clarity, leaving the popup window of the next quiz question out in the open, perhaps.

In order to achieve this, and keep backward compatibility we needed to delay the quiz question prompt window via …

  1. document.hasFocus() is true … then if …
  2. inhouse dragging checks clear it of overlaying another popup (in which case that popup is programmatically closed, allowing another popup to become the “focus window”) … then …
  3. delay (by 8 seconds) the prompt window (and in that time the user can be dragging popups (but no popups were harmed in the making of this tutorial)) … via …

    setTimeout(function() { hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } else { hj=window.opener.assess(hj); } if (hj.replace(def,'') != '') { checka(hj); } else { setTimeout(pa,10000); } aminmiddle=false; }, 8000);

… you can see in amongst the changed cards_usefocus.html code behind the “Just Javascript” live run you are welcome to try for yourself … best on non-mobile.

Still “No Body Definition”, “Just Javascript”!


Previous relevant Just Javascript Quiz CSS Styling Tutorial is shown below.

Just Javascript Quiz CSS Styling Tutorial

Just Javascript Quiz CSS Styling Tutorial

Our “Just Javascript” adage used throughout this blog posting thread, up until today, headed by yesterday’s Just Javascript Quiz Content Management Tutorial needs more explanation. Really what we are trying to do might better be described as “No Body Definition” (ie. no defined document.body) but have …

  1. an HTML webpage (ie. within <html> and </html>) … has …
  2. <head> and </head> (ie. document.head) content which can be made up of (at least) title, style, script, link, meta tags

To assert “Just Javascript” is just to allow script content above, but what we should really say is “Just Head Content” but that is not nearly so marketable, is it now?!

The thing is, though, we can dynamically add title, style, link, meta tag content within the script content, and we do this more than statically define it, to feel better about our ethics saying “Just Javascript”.

Dynamically adding style CSS styling either …

  • using Javascript DOM (not available to us for document.getElementById([elementID] and nor can we use inline CSS via style=”[CSSstyling]” statically within HTML element code for that same reason) ideas today though … remember “No Body Definition” … but …
  • we can append to <head> and </head> (for today’s scenario) as per …

    document.head.innerHTML+="<style> html { background-color: yellow; font-size: 36px; background: URL('//www.rjmprogramming.com.au/rjmquiz.jpg'); background-size: cover; } </style>";

… allowing (into the scope of our work CSS styling of) background (image(s)) and other background styling ideas that can get us past the anonymous feel the web application had before today. We tailored the background image above to suit our Quiz and help it be a bit more self explanatory … thanks CSS styling! We add onto the child “card” popup windows, their own background image colour and pizazz, to cheer things up in CSS styling enhanced cards_usefocus.html code behind the “Just Javascript” live run.

You may well ask …

What can we hang our hat on with CSS style selectors without a body element?

Well, we had to step out of our usual comfort zone of CSS styling thinking, and realize, even without that body element we can still use the html selector to “point at” the entirety of your webpage of interest.


Previous relevant Just Javascript Quiz Content Management Tutorial is shown below.

Just Javascript Quiz Content Management Tutorial

Just Javascript Quiz Content Management Tutorial

It feels like an “onions of the 4th dimension” idea to allow the user to control the questions and answers behind the workings of yesterday’s Just Javascript Quiz Multiple Users Tutorial‘s web application, featuring “Just Javascript”.

It’s not “Just Javascript” we’re keeping, it’s “Just HTML” client work rather than involving any serverside anything (eg.PHP) and yet this question and answer data could be quite sizeable. What can we use, given no PHP serverside, and given we’ve decided not to navigate via Ajax/FormData techniques? How about “the better than HTTP Cookies” twins …

Yep, set up a means by which these two can store and restore questions and answers entered by the user, using these storage methods above.


function reassess() {
var retv='', ewq;
var retcols=[];
var ir=0;
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '') {
//alert('0:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?!')[0] + '?');
asq.push(retcols[ir].split('?!')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '') {
//alert('1:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?')[0] + '?');
asq.push(retcols[ir].split('?')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
}


function assess(what) {
var ewq, retv='';
if (what.toLowerCase() == '?x') {
sslistq=[];
sslista=[];
if (window.sessionStorage) {
try {
window.sessionStorage.removeItem('cards_usefocus_session');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase() == '?!x') {
lslistq=[];
lslista=[];
if (window.localStorage) {
try {
window.localStorage.removeItem('cards_usefocus_local');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase().indexOf('?!') != -1) {
if (what.toLowerCase() == '?!') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.localStorage) {
if (lslistq.length == 0) {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', encodeURIComponent(what));
} else {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', window.localStorage.getItem('cards_usefocus_local') + encodeURIComponent('~' + what));
}
}
return '';
} else if (what.toLowerCase().indexOf('?') != -1) {
if (what.toLowerCase() == '?') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.sessionStorage) {
if (sslistq.length == 0) {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', encodeURIComponent(what));
} else {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', window.sessionStorage.getItem('cards_usefocus_session') + encodeURIComponent('~' + what));
}
}
return '';
} else {
firstbit='';
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
}
return what;
}

The fairly significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz Multiple Users Tutorial is shown below.

Just Javascript Quiz Multiple Users Tutorial

Just Javascript Quiz Multiple Users Tutorial

Adding to yesterday’s Just Javascript Quiz via Cards Tutorial we were surprised how difficult it was to stay with “Just Javascript” and allow for multiple player play.

We didn’t opt for the parent to ask about the number of players, curiously, but on the second quiz answer and on, offered any non first player the chance to identify themselves as a new player into the game by appending their answer with a space character.

The implication of that is that we’ll want to run Javascript functions of the parent from the children as per


oplist[eval(-1 + oplist.length)].document.write("<link rel=icon href=" + cards[kl] + "><scr" + "ipt type='text/javascript'> var da='" + eval(0 + kq) + "'; var dp='Given answer is integer from 0 to 25 ... " + sq[kq] + "'; var def=String.fromCodePoint(" + spcps[eval('' + kl)].split('/')[0] + "); function checka(tpa) { var os=''; var ps=eval(window.opener.document.title.split('/')[0].trim()); var pg=eval(window.opener.document.title.split('/')[1].split(' ')[0]); if (tpa.trim() == da) { ps++; os=tpa.split(da)[1]; } else { pg++; os=tpa.split(tpa.trim())[1]; } window.opener.document.title=ps + os + '/' + pg + ' is User Score/Goes'; window.close(); } function pa() { if (document.hasFocus()) { var hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } if (hj.replace(def,'') == '') { setTimeout(pa,1000); } else { checka(hj); } } else { setTimeout(pa,1000); } } pa(); </scr" + "ipt>");

… accessing …


function blurb() { // theblurb and wblurb are global variables changed elsewhere
if (wblurb == ' Hello Player 1' && theblurb == ' If you are player 2 rather than player 1 append space to your answer.') {
theblurb='';
wblurb='';
}
return theblurb + wblurb;
}

… giving the rather curious behaviour whereby a Javascript prompt window can be dynamically different from one document.hasFocus() incarnation (ie. the user might go away and answer another “card” Number Quiz question) to another (even not attending to answering the Javascript prompt window) … huh?!

The significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz via Cards Tutorial is shown below.

Just Javascript Quiz via Cards Tutorial

Just Javascript Quiz via Cards Tutorial

Yesterday’s Just Javascript Navigation Tutorial continues our interest in “Just Javascript” (or “No Body”) web applications.

We think today’s “Numbers Quiz” via a “Card Deck” organizational design ups the ante on all this. We realize now what we have been missing not having involved document.hasFocus() in any of our popup window scenarios. Today, at least on non-mobile, we involve 52 such popup windows each containing a “Number Quiz” question presented as a Javascript prompt (sub-)window. This would not be feasible without document.hasFocus() as you can tell if you examine the cards_usefocus.html code behind the “Just Javascript” live run best used on your non-mobile platforms where popup windows can sit in front of parent (and beside sibling) windows, whereas mobile platforms open new web browser tabs for all the 52 windows of (a card deck) design.

Look out, too, in the code above, for use of window.opener back reference from a popup window back to the parent window where the scoring data is held, and updated by each popup window because of that window.opener avaalability.


Previous relevant Just Javascript Navigation Tutorial is shown below.

Just Javascript Navigation Tutorial

Just Javascript Navigation Tutorial

The recent use we made of …


document.createElement/click()

… got us thinking of the “Just Javascript” (or No Body) blog posting thread headed by Just Javascript Webmail No Body Attachment Tutorial.

As such, today we present the very simple (but first time use of the interesting hasFocus) “proof of concept” …


<html>
<head>
<script type='text/javascript'>
function dothis() {
var ais=null;
var urlis=' ';
while (urlis != '') {
if (document.hasFocus()) {
urlis=prompt('Enter URL that we will send you to (exit to stop)', '');
} else {
setTimeout(dothis, 2000); // urlis=' ';
return;
}
if (urlis == null) { urlis=''; }
if (urlis.toLowerCase() == 'exit') { return; }


if (urlis.trim() != '') {
if (urlis.substring(0,1) == '.') { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
} else if (urlis.substring(0,1) == '/' && urlis.indexOf('//') == -1) { // relative URL
urlis=document.URL.split('//')[0] + '//' + document.URL.split('//')[1].split('/')[0] + '/' + urlis;
} else if (urlis.split('/')[0].indexOf('.') != -1) { // absolute URL
if (urlis.toLowerCase().indexOf('http') != 0) {
if (urlis.indexOf('//') == 0) {
urlis=document.URL.split('//')[0] + urlis;
} else {
urlis=document.URL.split('//')[0] + '//' + urlis;
}
}
} else { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
}
ais=document.createElement('a');
ais.onclick=function() { window.open(urlis, '_blank', 'top=100,left=100,width=600,height=600'); };
if (1 == 2) { ais.href=urlis; }
ais.target='_blank';
ais.click();
}
}
setTimeout(dothis, 2000); // urlis=' ';
}


dothis();

</script>
</head>
</html>

nobody.html‘s live run link for you to use a Javascript prompt popup window’s user interaction results to navigate to a new webpage, as applicable. Bookmarklets may be scarce on the ground, but these “Just Javascript” ideas continue the Bookmarklet Spirit of the past!


Previous relevant Just Javascript Webmail No Body Attachment Tutorial is shown below.

Just Javascript Webmail No Body Attachment Tutorial

Just Javascript Webmail No Body Attachment Tutorial

A “hard liner” for the proper use of “business emails” could argue that an email without an attachment is not productive. Couldn’t you just have a face to face meeting instead, if there is just wording in the email (as we somewhat concur with, as an argument)? So yesterday’s Just Javascript Webmail No Body Tutorial had that limitation of no email attachment logic, which we remedy today.

And this is where PHP’s wonderful file_get_contents (function) means by which we garner (URL) content …

  • definitely works with “relative URLs” relative to HTTP://www.rjmprogramming.com.au/HTMLCSS/ where today’s unchanged webmail_nobody.html resides … in “parsing parlance” …

    "relative (URL)" to the left of any # or ? of what lies to the left of the most right hand "/" (of what the address bar URL is of the webpage you are on)

    … so that …

    1. “relative URLs” starting with “./” (followed by the filename, or just the filename (as you can see us using in today’s tutorial picture)) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/HTMLCSS/” … whereas, for example …
    2. “relative URLs” starting with “../” (followed by the filename) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/” … for example

    … and …

  • might work for “absolute URLs” (those that start with https: or HTTP: or even // (that we beg you not to confuse with Windows UNC pathnames) that infer a transport protocol of the transport protocol (out of https: or HTTP: or even file:) that got you to the webpage you are currently on), the “might” being far more likely on “absolute URLs” pointing to the same domain as indicated on the URL of the address bar of the webpage you are currently on

Upshot is, the user in their email Body section definitions (still no HTML body though!), can throw into any word they use, an “absolute URL” of interest, or a “relative URL” of interest, of files they want to attach (as attachments, doh!) in their email.

Depending on the email rules though, there are limits as to the amount of attachment data allowed. We’ll leave that to you intrepid “explorers of the Net” to discover for yourselves. On this subject though, have you noticed that with the Photos (or Gallery) app Share options, the Email option drops off when you have highlighted a large number of photos or videos or audios to share? That’s that email limit coming into play.

So feel free to try this HTML-body-less web application live run to see what we mean here. Though the parent HTML is unchanged today, the new (email) attachment functionality needed a changed PHP emailhtml.php to make this happen.

Did you know?

This (relative URL) “../” navigation backwards up the hierarchy of the web server directories will, if repeated (ie. nested to “../../” etcetera) too many times, get you into uncharted unnavigable (web server directory) places relative to that web server web site’s Document Root (below which you can not access in public webpages, normally). But when you perform similar thinking with “absolute URLs” and go “HTTP://www.rjmprogramming.com.au/HTMLCSS/../../../blahdeblah.jpg” (in a web browser address bar) for instance, you cannot get into trouble, as you just don’t get beyond this sending you to (attempt the reference to) “HTTP://www.rjmprogramming.com.au/blahdeblah.jpg” because on this rjmprogramming.com.au Apache domain the correspondence of the Document Root (web server directory) is to “HTTP://www.rjmprogramming.com.au/” as the place you are not allowed (and cannot) go below in the hierarchy tree.


Previous relevant Just Javascript Webmail No Body Tutorial is shown below.

Just Javascript Webmail No Body Tutorial

Just Javascript Webmail No Body Tutorial

Were you around and interested in our series of about three blog postings in the series on the theme of creating webpage functionality of some interest, involving no Javascript, when we presented Missing Javascript Audio on Unmute Tutorial? Well, today, it’s the turn of “just Javascript”, which is sort of like what Bookmarklets were about.

With today’s “just Javascript” we have to qualify that a little for our webmail emailing sender application with the architecture …

  • parent webpage with only document.head and apart from a document.title just a script Javascript tag of content (using Javascript prompt windows to ask for user information) …
  • sending (POSTing) data via …
    1. Ajax XMLHttpRequest object … as the conduit for …
    2. FormData object

    … to our changed

  • PHP communication emailing tool emailhtml.php … and out to …
  • the emailee (out there in the big wide woooorrrrrllllldddd)

Guess we find it interesting that you can do all this (sending of email to emailee recipients) with no document.body in sight.

So take a look at that parent webmail_nobody.html‘s live run link to see what we mean here, and/or watch the video below …


Previous relevant Missing Javascript Audio on Unmute Tutorial is shown below.

Missing Javascript Audio on Unmute Tutorial

Missing Javascript Audio on Unmute Tutorial

Our “third cab off the rank” following on from yesterday’s Missing Javascript Stop Watch Tutorial “missing Javascript” ideas is an HTML div nesting scenario using just …

  1. HTML
  2. CSS

… again, with some or all of the “usuals” below …

  • calc method to assist with defining width and height and size dimensions along with operator “+” and/or “-” offset calculation opportunities, and which we’d have used the Javascript window.getComputedStyle and/or [element].getBoundingClientRect methods to cover this (in a much more unwieldy way, as you would probably surmise)
  • CSS variables we started talking about here at CSS Variables Primer Tutorial
  • CSS3 @keyframes rules we first talked about at CSS3 @keyframes Rule Primer Tutorial that assist with animations that we can make work via …
  • CSS3 transitions for scheduled functionality (we’d have used Javascript setTimeout (and setInterval) methods to cover the same “territory”) we first talked about at CSS3 Transition Primer Tutorial … specified with CSS Criteria involving …
  • CSS Selectors :after and :before (and often, as for today’s work, with the content: CSS property) first talked about here with WordPress Bullet Point CSS Styling Primer Tutorial … and, today …
  • CSS3 transform property’s rotate (and translate and scale) settings (for the puppy dog body movements) … as well as the idea that …
  • On non mobile platforms you can set up the playing of “audio” data via the use of an HTML audio tag with the properties …
    1. controls
    2. autostart
    3. loop
    4. muted

    Stop Press

    Above is all fine and good for non-mobile but not so good for mobile, so to keep all happy with the one click, still, is to transfer HTML coding from …


    <audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" />

    … to …


    <!--audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" /-->
    <audio id='myaudiotwo' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="margin-left:-350px;opacity:0.1;" autostart="0" loop controls src="Puppy-sounds.mp3" />

    … and a src= URL data source (as we thank this link for today), or data URI if preferred (which we do for today’s image data from this link, thanks (when we were researching animated GIF data URIs (which we may return to at a later date))

… that sets up the scenario that all the user has to do to hear the audio is to click the “muted” control button, without needing the usual Javascript play() methods … but not on mobile!

Feel free to let the puppy play, that uses the HTML and CSS (but no Javascript) of the_nested.html and based largely on the previous HTML Nested Centering via Multiple Select Tutorial so that these changes reflect how we got to the first draft of today’s work. Maybe some of the ideas are of interest. We hope so!


Previous relevant Missing Javascript Stop Watch Tutorial is shown below.

Missing Javascript Stop Watch Tutorial

Missing Javascript Stop Watch Tutorial

Following on from yesterday’s Missing Javascript Primer Tutorial our second “cab off the rank” for “missing Javascript” ideas is a stop watch featuring just …

  1. HTML
  2. CSS

… again, setting up document.body load instigated

… which we needed to do to make multiple animations happen, but we used animation-delay:5s; to delay its start. The hands (second and minute, hence the two animations) are “overlay”

… feeling HTML horizontal rule elements that also feature linear gradients, to emphasise (in red) the “pointy end” of the “hand conversation” (good on walls with shadows … but we digress).

Feel free to let loose the stop watch that uses the HTML and CSS (but no Javascript) of stop_watch.html for today’s instructional information. Thanks to Clipart – stop watch for the great clip art used.


Previous relevant Missing Javascript Primer Tutorial is shown below.

Missing Javascript Primer Tutorial

Missing Javascript Primer Tutorial

If you were to ask me which programming component is most vital to web application development, I’d not be Robinson Crusoe in saying …

Without a doubt, Javascript

… and with that thought in mind we have a two pronged motive to see how far we go developing some web applications that “don’t use Javascript”, calling into play the …

  • meaning of “missing”, as in, our code is “missing” Javascript … as well as how I feel with the masochism of the exercise, calling into play the …
  • meaning of “missing”, as in, it’s hard work writing meaningful web applications without Javascript … but I guess we’ll learn a bit from the exercise of “see where we go”, allowing for the fact, not today, but down the track, that we will allow the use of server-side languages such as PHP

Okay, so, given that restriction, let’s see today’s challenge, to just use, in a web application …

  1. HTML
  2. CSS

… and here is where we have to point out that CSS3 introduced to us some functionality that improves the prospects for web application design “interest” without using Javascript (though it is hard to convince me even so, that I am not “missing” Javascript) here. CSS3 introduced to us …

… and we use all of these in our Festive Season themed web application today, you can try at this live run‘s calc_use.html (free of any Javascript (but “why” springs to mind … because it is NOT there, perhaps?)).

Here’s the other thing about today. Our long sought after “just make the body background be semi-transparent” but not its foreground parts, was solved, for us via the great advice of …

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

Just Javascript Memories SVG Emoji Cursor Tutorial

Just Javascript Memories SVG Emoji Cursor Tutorial

Just Javascript Memories SVG Emoji Cursor Tutorial

The “Memories” functionality introduced in yesterday’s Just Javascript Memories Card Game Tutorial is a game component, and it is good to remember the “game” side to that. If a web application is a game and the player is not being timed, they may feel that freedom to be multitasking, go and do something else, and then come back “to work the game”. In that scenario, it would be quite friendly to offer a mechanism by which to remind the player(s) of the status of the game as they left it.

Even though we are in “Just Javascript” (ie. “No Body Definition”) mode of use here, we still have CSS to offer a solution here, and we’ve chosen in the CSS woooooorrrrrllllllddd to research a curiosity we’ve had “for just about ever”. Can we tailor the webpage “cursor” to be “emoji text content”. We’ve looked this up in the past, and did not succeed on that occasion with the “url([SVGcontent])” we thought might be the go. It was tweaking onto this great link that gave examples for us to succeed this time, thanks, using code such as …


csuff='';
var hjg='' + curplayer;
for (var ipl=0; ipl<hjg.length; ipl++) {
csuff+=String.fromCodePoint(eval(8320 + eval(eval('' + hjg.substring(ipl,eval(1 + eval('' + ipl))).charCodeAt(0)) - 48)));
}
if (ocp) { ocp.style.cursor='url("data:image/svg+xml;utf8,<svg xmlns=' + "'" + 'HTTP://www.w3.org/2000/svg' + "'" + ' width=' + "'" + '96' + "'" + ' height=' + "'" + '48' + "'" + ' viewport=' + "'" + '0 0 100 100' + "'" + ' style=' + "'" + 'border-radius:60px;background-color:rgba(255,0,0,0.1);fill:black;font-size:24px;' + "'" + '><text y=' + "'" + '50%' + "'" + '>' + String.fromCodePoint(10067,10068) + csuff + '</text></svg>") 16 0, pointer'; }

… that “ocp” being the “evt.target” of the “onlick” event logics previously talked about. Notice the fallback to those set cursors of “the cursor wooooorrrrrllllllddd”.

Along the way we offer variations to the playing rules of Memories, too, to add some variety for the user(s).

Yet again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Memories Card Game Tutorial is shown below.

Just Javascript Memories Card Game Tutorial

Just Javascript Memories Card Game Tutorial

Up until yesterday’s Just Javascript Card Order Game One Window Tutorial every mode of execution of our web application involved the Javascript prompt (popup) window method of getting information off the user.

Today, though, adding a Memories Card Game new functionality part uses a hybrid Javascript prompt window arrangement …

  • a first usage is to use the default Javascript prompt window arrangement you glean from the user the number of players in the Memories Card Game to follow …
  • and then from then on

    var lasttogglenumber='';
    var lastec='', notyet=false;
    var backi="/rjmquiz_plus.jpg";
    var fiftytwo=52;
    var message='';
    var lastcard='';
    var lasttto='';
    var gamescoreprefix='';
    var gamescores=[0];
    var lasttmid='';
    var lasttfrom='';
    var lasttoggleto='';
    var lasttogglefrom='';
    var curplayer=1, card_of_play=0;
    var card_game='memories';
    var nominal_implication='';
    var nominal_numplayers = (document.URL.replace('?','&').indexOf('&card') != -1) ? prompt('How many players are playing your ' + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(0,1).toUpperCase() + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(1).toLowerCase() + ' card game?', '2') : null;

    if (nominal_numplayers) {
    if (('' + nominal_numplayers).replace('0','').trim() != '' && ('' + nominal_numplayers).replace('0','').trim().indexOf('-') == -1) {
    var prompt = function(zwords, defwords){ return null; };
    nominal_implication=" var prompt = function(zwords, defwords){ return null; }; ";
    fiftytwo=-1;
    backi="/Games/Memories/Memories.jpg";
    } else {
    nominal_numplayers=null;
    }
    }

… “prompt” is overridden as above. That, and overriding the scoring mechanisms, and this same codeset is nearly there towards accommodating our new quite different requirement.

But with “No Body Definition”/”Just Javascript” how can we show and implement this new Memories Card Game usage? It’s a two way integration, the easier one being …

  • offer a place for click/touch on the default background imagery … and with that webpage reminder …
  • what is an independent “add on” event methodology available to us, so as not to interfere with event logic that has preceded? … spoiler alert … double click …

    ele.addEventListener('dblclick', function(evt) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    });

    … (or two clicks quickly in a row) … as per

    var lastec='', notyet=false;


    function antilastec() {
    lastec='';
    }


    function antinotyet() {
    notyet=true;
    }


    ele.addEventListener('click', function(evt) {
    if (evt.touches) {
    if (evt.touches[0].pageX) {
    iourx = evt.touches[0].pageX;
    ioury = evt.touches[0].pageY;
    } else {
    iourx = evt.touches[0].clientX;
    ioury = evt.touches[0].clientY;
    }
    //alert('' + iourx);
    } else if (evt.clientX) {
    iourx = evt.clientX; // - elemLeft;
    ioury = evt.clientY; // - elemLeft;
    } else if (!evt.touches) {
    iourx = evt.pageX; // - elemLeft;
    ioury = evt.pageX; // - elemLeft;
    }
    if (('' + iourx + ',' + ioury) == lastec && lastec != '' && notyet) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    } else if (lastec == '') {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    } else {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    }

    clickedmaybe();
    });

Again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game One Window Tutorial is shown below.

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

The “one window” rather than (52 + 1) = 53 windows scenario set up as a possibility with yesterday’s Just Javascript Card Order Game Mobile Tutorial had us wondering …

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

… and tomorrow is today. We’ve decided not to make the one window scenario the default for non-mobile platforms, but serve as a fallback for some of the scenarios mentioned below …

  • the user gets blocked from using the popup windows on their non-mobile platform web browser … big possibility!
  • the user clicks half way through the popup window incarnation the parent window … all the child popups disappear behind … annoying … so

    var flexible=false;

    function secsu() {
    var ewd;
    if (secs == 0) {
    if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    flexible=false;
    } else {
    flexible=true;
    console.log('Flexible=T');
    }

    setTimeout(blater, 2500);
    }
    if (eval('' + overallgoes) < 52) {
    secs++;
    } else if (document.title.indexOf('Congratulations') == -1) {
    document.title+=' ... Congratulations! End of Game! Refresh webpage to try again.';
    }
    var decs=document.title.split('.');
    if (eval('' + decs.length) >= 3) {
    document.title=document.title.replace('.' + decs[2].split(' ')[0] + ' ', '.' + secs + ' ');
    } else {
    ps=document.title.split('/')[0].trim();
    pg=document.title.split('/')[1].split(' ')[0];
    if (ps.indexOf('.') == -1 || pg.indexOf('.') == -1) {
    ps=eval('' + overallscore + '.' + psecs); //eval(document.title.split('/')[0].trim());
    pg=eval('' + overallgoes + '.' + secs);
    document.title=document.title.replace(document.title.split(' ')[0], '' + overallscore + '.' + psecs + '/' + '' + overallgoes + '.' + secs);
    //console.log('document.title becomes ' + document.title);
    } else {
    ps=eval(ps);
    pg=eval(pg);
    }
    }


    if (flexible) {
    if (document.hasFocus()) {
    flexible=false;
    console.log('Flexible=F');
    lastzkq='';
    lastzkl='';
    owidth=oowidth;
    oheight=ooheight;
    for (var igh=0; igh<oplist.length; igh++) {
    opltlistl[igh]=oopltlistl[igh];
    opltlistt[igh]=oopltlistt[igh];
    if (oplist[igh]) {
    console.log('Flexible=F' + igh);
    if (!oplist[igh].closed) {
    try {
    oplist[igh].close();
    oplist[igh]=null;
    } catch(ewd) {
    }
    } else {
    oplist[igh]=null;
    }
    }
    }
    }
    }

    }

… document.hasFocus() to the rescue again … the multiple background images of yesterday’s work being a default part of any incarnation, and whether the click event logic of yesterday becomes relevant depends on …

  • if user is a mobile platform user, always relevant
  • user enters URL with argument like ?onewindow=y then is always relevant … else …
  • a scenario as above means that from that point on, the multiple background image one window click on cards modus operandi becomes relevant

We improve the web browser conditions too, if a non-mobile user “clicks half way through the popup window incarnation the parent window” in that we programmatically close any open child popup windows! Phew!

Feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game Mobile Tutorial is shown below.

Just Javascript Card Order Game Mobile Tutorial

Just Javascript Card Order Game Mobile Tutorial

Yesterday’s Just Javascript Card Order Game Tutorial mobile usage scenario was impractical, in that mobile platforms can not work popup windows in front of a parent window. Can we convert those non-mobile popup windows into … well … what exactly?

Well, in order to keep to our “Just Javascript” (ie. “No Body Definition”) pledge with this project, we needed to simulate those popups as background image parts, in the sense that you can have multiple background images these days with your HTML. Even with html as your CSS styling selector … it pans out … we needed to prove that today.

Also, today, for the first time, we achieved via …

  1. comma separated background-repeat: no-repeat; list
  2. comma separated background-size list (set popup width height list until last one bigger (based on screen.width screen.height) for the parent background image (no-repeat))
  3. comma separated background-position list (as per what window.open in non-mobile was using for left top until last one’s 0px 0px)
  4. comma separated background-image list (as per what window.open in non-mobile was using for URL([imageURL]) until last one’s linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)), url(//www.rjmprogramming.com.au/rjmquiz_plus.jpg))

… as per (the previous “window.open” becomes “windowopen”) …


function windowopen(one, two, three) {
if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
console.log('Here ' + kq);
opltlistl.push((three.split('left=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + one.split('spcp=')[1].split('&')[0]));
opltlistt.push((three.split('top=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + kq));
owidth=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
oheight=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
if (defstyle.indexOf('background: URL(') != -1) {
defstyle=defstyle.split('background: URL(')[0] + 'background-repeat:no-repeat;background-size:' + owidth + 'px ' + oheight + 'px;background-position:' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image: url(' + cards[eval('' + donelist[eval(-1 + donelist.length)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'; // + ' ' + owidth + ' ' + oheight
} else {
defstyle=defstyle.replace(';background-image:', (',' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image:');
defstyle=defstyle.replace('no-repeat','no-repeat,no-repeat');
defstyle=defstyle.replace('background-size:' + owidth + 'px ' + oheight + 'px','background-size:' + owidth + 'px ' + oheight + 'px,' + owidth + 'px ' + oheight + 'px');
defstyle=defstyle.replace('; } </style>', ',url(' + cards[eval('' + donelist[eval(0 + ijk)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'); // + ' ' + owidth + ' ' + oheight
}
return null;
}
return window.open(one, two, three);
}

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

We needed to add event logic we were not sure would work at the start of the day, and saw it working by the end, with …


var iourx=-1, ioury=-1;

function blater() {
if (1 == 2 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
window.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
eles = document.querySelectorAll("*")
for (var ele of eles) {
console.log('yes well');
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ele.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('touchmove', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('click', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
ele.addEventListener('click', function(evt) {
if (evt.touches) {
if (evt.touches[0].pageX) {
iourx = evt.touches[0].pageX;
ioury = evt.touches[0].pageY;
} else {
iourx = evt.touches[0].clientX;
ioury = evt.touches[0].clientY;
}
//alert('' + iourx);
} else if (evt.clientX) {
iourx = evt.clientX; // - elemLeft;
ioury = evt.clientY; // - elemLeft;
} else if (!evt.touches) {
iourx = evt.pageX; // - elemLeft;
ioury = evt.pageX; // - elemLeft;
}
clickedmaybe();
//alert('here');
});
}
}
}
}

See this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform) we, again, welcome you to try for yourself.


Previous relevant Just Javascript Card Order Game Tutorial is shown below.

Just Javascript Card Order Game Tutorial

Just Javascript Card Order Game Tutorial

Today we’ve made the web application of yesterday’s Just Javascript Quiz Drag Tutorial “dual purpose” …

  • quiz … as for yesterday, and before … and as of today, making more use of the card organizational side to the popup windows we introduce …
  • card order game

This card order game asks you to force the focus of the correct popup window (to score in the Card Order Game) in the order as designated by the background image part we have added today, and supported by the following Javascript “mapping” code …


var dragorder=[], curdrag=0;

var cards=["//www.rjmprogramming.com.au/images/01s.gif?n=7",
"//www.rjmprogramming.com.au/images/02s.gif?n=16",
"//www.rjmprogramming.com.au/images/03s.gif?n=33",
"//www.rjmprogramming.com.au/images/04s.gif?n=29",
"//www.rjmprogramming.com.au/images/05s.gif?n=8",
"//www.rjmprogramming.com.au/images/06s.gif?n=35",
"//www.rjmprogramming.com.au/images/07s.gif?n=52",
"//www.rjmprogramming.com.au/images/08s.gif?n=51",
"//www.rjmprogramming.com.au/images/09s.gif?n=12",
"//www.rjmprogramming.com.au/images/10s.gif?n=30",
"//www.rjmprogramming.com.au/images/11s.gif?n=1",
"//www.rjmprogramming.com.au/images/12s.gif?n=36",
"//www.rjmprogramming.com.au/images/13s.gif?n=22",
"//www.rjmprogramming.com.au/images/01h.gif?n=32",
"//www.rjmprogramming.com.au/images/02h.gif?n=23",
"//www.rjmprogramming.com.au/images/03h.gif?n=3",
"//www.rjmprogramming.com.au/images/04h.gif?n=18",
"//www.rjmprogramming.com.au/images/05h.gif?n=28",
"//www.rjmprogramming.com.au/images/06h.gif?n=39",
"//www.rjmprogramming.com.au/images/07h.gif?n=45",
"//www.rjmprogramming.com.au/images/08h.gif?n=48",
"//www.rjmprogramming.com.au/images/09h.gif?n=50",
"//www.rjmprogramming.com.au/images/10h.gif?n=44",
"//www.rjmprogramming.com.au/images/11h.gif?n=4",
"//www.rjmprogramming.com.au/images/12h.gif?n=9",
"//www.rjmprogramming.com.au/images/13h.gif?n=5",
"//www.rjmprogramming.com.au/images/01d.gif?n=27",
"//www.rjmprogramming.com.au/images/02d.gif?n=41",
"//www.rjmprogramming.com.au/images/03d.gif?n=20",
"//www.rjmprogramming.com.au/images/04d.gif?n=11",
"//www.rjmprogramming.com.au/images/05d.gif?n=37",
"//www.rjmprogramming.com.au/images/06d.gif?n=49",
"//www.rjmprogramming.com.au/images/07d.gif?n=42",
"//www.rjmprogramming.com.au/images/08d.gif?n=6",
"//www.rjmprogramming.com.au/images/09d.gif?n=21",
"//www.rjmprogramming.com.au/images/10d.gif?n=31",
"//www.rjmprogramming.com.au/images/11d.gif?n=40",
"//www.rjmprogramming.com.au/images/12d.gif?n=43",
"//www.rjmprogramming.com.au/images/13d.gif?n=17",
"//www.rjmprogramming.com.au/images/01c.gif?n=46",
"//www.rjmprogramming.com.au/images/02c.gif?n=19",
"//www.rjmprogramming.com.au/images/03c.gif?n=47",
"//www.rjmprogramming.com.au/images/04c.gif?n=25",
"//www.rjmprogramming.com.au/images/05c.gif?n=10",
"//www.rjmprogramming.com.au/images/06c.gif?n=15",
"//www.rjmprogramming.com.au/images/07c.gif?n=13",
"//www.rjmprogramming.com.au/images/08c.gif?n=26",
"//www.rjmprogramming.com.au/images/09c.gif?n=38",
"//www.rjmprogramming.com.au/images/10c.gif?n=34",
"//www.rjmprogramming.com.au/images/11c.gif?n=2",
"//www.rjmprogramming.com.au/images/12c.gif?n=14",
"//www.rjmprogramming.com.au/images/13c.gif?n=24"];


for (var ic=1; ic<=cards.length; ic++) {
found=false;
for (var jc=1; jc<=cards.length; jc++) {
if ((cards[eval(-1 + jc)] + '~').indexOf('?n=' + ic + '~') != -1) {
dragorder.push(eval(-1 + jc));
cards[eval(-1 + jc)]=cards[eval(-1 + jc)].replace('?n=' + ic, '');
firstbit+=String.fromCodePoint(eval('' + spcps[eval(-1 + jc)].split('/')[0])) + ' ';
found=true;
}
}
}

… and “making use of” this and the new codeline as popups are created … oplist[eval(-1 + oplist.length)].document.name=” + kl; we have …


function ourprompt(tw, blb, bdef) {
var kijk;
if (oplist[eval('' + tw)].document.name == ('' + dragorder[eval('' + curdrag)]) && eval('' + curdrag) == eval('' + overallgoes)) {
console.log('Dragorder[' + curdrag + ']=' + dragorder[eval('' + curdrag)] + ' vs tw=' + tw + ' and overall;goes=' + overallgoes);
var decs=document.title.split('.');
curdrag++;
overallgoes++;
if (eval('' + decs.length) >= 3) {
document.title=document.title.replace('.' + decs[1] + '.', '.' + curdrag + '/' + overallgoes + '.');
}
oplist[eval('' + tw)].close();
return null;
}

// Quiz only code follows
}

… code.

It must be in the correct order (and not interrupted by quiz answer completions) to score, and you are timed, so you can try improving over time, using a document.title score presentation as per …


[QuizScore].[CardOrderGameScore]/[QuizAnswerAttemptCount].[SecondsElapsed] [MultiPlayerQuizScoreGoesBreakdown] is User: Score/Goes - RJM Programming - April, 2021

… so that both usages for the web application can be accommodated for in the changed cards_usefocus.html code behind the “Just Javascript” live run we welcome you to try for yourself.


Previous relevant Just Javascript Quiz Drag Tutorial is shown below.

Just Javascript Quiz Drag Tutorial

Just Javascript Quiz Drag Tutorial

Adding to yesterday’s Just Javascript Quiz CSS Styling Tutorial we have added some …

  • non-mobile platform, only …
  • drag and drop functionality … for …
  • the child popup windows

… achieved through the comparison of …

  • original [popupWindow].screenLeft and [popupWindow].screenTop … initially, to …
  • [popupWindow].screenLeft and [popupWindow].screenTop over time

… and if one popup is dragged to overlay another it is closed, or you, as the user, can just drag and drop for clarity, leaving the popup window of the next quiz question out in the open, perhaps.

In order to achieve this, and keep backward compatibility we needed to delay the quiz question prompt window via …

  1. document.hasFocus() is true … then if …
  2. inhouse dragging checks clear it of overlaying another popup (in which case that popup is programmatically closed, allowing another popup to become the “focus window”) … then …
  3. delay (by 8 seconds) the prompt window (and in that time the user can be dragging popups (but no popups were harmed in the making of this tutorial)) … via …

    setTimeout(function() { hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } else { hj=window.opener.assess(hj); } if (hj.replace(def,'') != '') { checka(hj); } else { setTimeout(pa,10000); } aminmiddle=false; }, 8000);

… you can see in amongst the changed cards_usefocus.html code behind the “Just Javascript” live run you are welcome to try for yourself … best on non-mobile.

Still “No Body Definition”, “Just Javascript”!


Previous relevant Just Javascript Quiz CSS Styling Tutorial is shown below.

Just Javascript Quiz CSS Styling Tutorial

Just Javascript Quiz CSS Styling Tutorial

Our “Just Javascript” adage used throughout this blog posting thread, up until today, headed by yesterday’s Just Javascript Quiz Content Management Tutorial needs more explanation. Really what we are trying to do might better be described as “No Body Definition” (ie. no defined document.body) but have …

  1. an HTML webpage (ie. within <html> and </html>) … has …
  2. <head> and </head> (ie. document.head) content which can be made up of (at least) title, style, script, link, meta tags

To assert “Just Javascript” is just to allow script content above, but what we should really say is “Just Head Content” but that is not nearly so marketable, is it now?!

The thing is, though, we can dynamically add title, style, link, meta tag content within the script content, and we do this more than statically define it, to feel better about our ethics saying “Just Javascript”.

Dynamically adding style CSS styling either …

  • using Javascript DOM (not available to us for document.getElementById([elementID] and nor can we use inline CSS via style=”[CSSstyling]” statically within HTML element code for that same reason) ideas today though … remember “No Body Definition” … but …
  • we can append to <head> and </head> (for today’s scenario) as per …

    document.head.innerHTML+="<style> html { background-color: yellow; font-size: 36px; background: URL('//www.rjmprogramming.com.au/rjmquiz.jpg'); background-size: cover; } </style>";

… allowing (into the scope of our work CSS styling of) background (image(s)) and other background styling ideas that can get us past the anonymous feel the web application had before today. We tailored the background image above to suit our Quiz and help it be a bit more self explanatory … thanks CSS styling! We add onto the child “card” popup windows, their own background image colour and pizazz, to cheer things up in CSS styling enhanced cards_usefocus.html code behind the “Just Javascript” live run.

You may well ask …

What can we hang our hat on with CSS style selectors without a body element?

Well, we had to step out of our usual comfort zone of CSS styling thinking, and realize, even without that body element we can still use the html selector to “point at” the entirety of your webpage of interest.


Previous relevant Just Javascript Quiz Content Management Tutorial is shown below.

Just Javascript Quiz Content Management Tutorial

Just Javascript Quiz Content Management Tutorial

It feels like an “onions of the 4th dimension” idea to allow the user to control the questions and answers behind the workings of yesterday’s Just Javascript Quiz Multiple Users Tutorial‘s web application, featuring “Just Javascript”.

It’s not “Just Javascript” we’re keeping, it’s “Just HTML” client work rather than involving any serverside anything (eg.PHP) and yet this question and answer data could be quite sizeable. What can we use, given no PHP serverside, and given we’ve decided not to navigate via Ajax/FormData techniques? How about “the better than HTTP Cookies” twins …

Yep, set up a means by which these two can store and restore questions and answers entered by the user, using these storage methods above.


function reassess() {
var retv='', ewq;
var retcols=[];
var ir=0;
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '') {
//alert('0:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?!')[0] + '?');
asq.push(retcols[ir].split('?!')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '') {
//alert('1:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?')[0] + '?');
asq.push(retcols[ir].split('?')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
}


function assess(what) {
var ewq, retv='';
if (what.toLowerCase() == '?x') {
sslistq=[];
sslista=[];
if (window.sessionStorage) {
try {
window.sessionStorage.removeItem('cards_usefocus_session');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase() == '?!x') {
lslistq=[];
lslista=[];
if (window.localStorage) {
try {
window.localStorage.removeItem('cards_usefocus_local');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase().indexOf('?!') != -1) {
if (what.toLowerCase() == '?!') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.localStorage) {
if (lslistq.length == 0) {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', encodeURIComponent(what));
} else {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', window.localStorage.getItem('cards_usefocus_local') + encodeURIComponent('~' + what));
}
}
return '';
} else if (what.toLowerCase().indexOf('?') != -1) {
if (what.toLowerCase() == '?') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.sessionStorage) {
if (sslistq.length == 0) {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', encodeURIComponent(what));
} else {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', window.sessionStorage.getItem('cards_usefocus_session') + encodeURIComponent('~' + what));
}
}
return '';
} else {
firstbit='';
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
}
return what;
}

The fairly significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz Multiple Users Tutorial is shown below.

Just Javascript Quiz Multiple Users Tutorial

Just Javascript Quiz Multiple Users Tutorial

Adding to yesterday’s Just Javascript Quiz via Cards Tutorial we were surprised how difficult it was to stay with “Just Javascript” and allow for multiple player play.

We didn’t opt for the parent to ask about the number of players, curiously, but on the second quiz answer and on, offered any non first player the chance to identify themselves as a new player into the game by appending their answer with a space character.

The implication of that is that we’ll want to run Javascript functions of the parent from the children as per


oplist[eval(-1 + oplist.length)].document.write("<link rel=icon href=" + cards[kl] + "><scr" + "ipt type='text/javascript'> var da='" + eval(0 + kq) + "'; var dp='Given answer is integer from 0 to 25 ... " + sq[kq] + "'; var def=String.fromCodePoint(" + spcps[eval('' + kl)].split('/')[0] + "); function checka(tpa) { var os=''; var ps=eval(window.opener.document.title.split('/')[0].trim()); var pg=eval(window.opener.document.title.split('/')[1].split(' ')[0]); if (tpa.trim() == da) { ps++; os=tpa.split(da)[1]; } else { pg++; os=tpa.split(tpa.trim())[1]; } window.opener.document.title=ps + os + '/' + pg + ' is User Score/Goes'; window.close(); } function pa() { if (document.hasFocus()) { var hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } if (hj.replace(def,'') == '') { setTimeout(pa,1000); } else { checka(hj); } } else { setTimeout(pa,1000); } } pa(); </scr" + "ipt>");

… accessing …


function blurb() { // theblurb and wblurb are global variables changed elsewhere
if (wblurb == ' Hello Player 1' && theblurb == ' If you are player 2 rather than player 1 append space to your answer.') {
theblurb='';
wblurb='';
}
return theblurb + wblurb;
}

… giving the rather curious behaviour whereby a Javascript prompt window can be dynamically different from one document.hasFocus() incarnation (ie. the user might go away and answer another “card” Number Quiz question) to another (even not attending to answering the Javascript prompt window) … huh?!

The significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz via Cards Tutorial is shown below.

Just Javascript Quiz via Cards Tutorial

Just Javascript Quiz via Cards Tutorial

Yesterday’s Just Javascript Navigation Tutorial continues our interest in “Just Javascript” (or “No Body”) web applications.

We think today’s “Numbers Quiz” via a “Card Deck” organizational design ups the ante on all this. We realize now what we have been missing not having involved document.hasFocus() in any of our popup window scenarios. Today, at least on non-mobile, we involve 52 such popup windows each containing a “Number Quiz” question presented as a Javascript prompt (sub-)window. This would not be feasible without document.hasFocus() as you can tell if you examine the cards_usefocus.html code behind the “Just Javascript” live run best used on your non-mobile platforms where popup windows can sit in front of parent (and beside sibling) windows, whereas mobile platforms open new web browser tabs for all the 52 windows of (a card deck) design.

Look out, too, in the code above, for use of window.opener back reference from a popup window back to the parent window where the scoring data is held, and updated by each popup window because of that window.opener avaalability.


Previous relevant Just Javascript Navigation Tutorial is shown below.

Just Javascript Navigation Tutorial

Just Javascript Navigation Tutorial

The recent use we made of …


document.createElement/click()

… got us thinking of the “Just Javascript” (or No Body) blog posting thread headed by Just Javascript Webmail No Body Attachment Tutorial.

As such, today we present the very simple (but first time use of the interesting hasFocus) “proof of concept” …


<html>
<head>
<script type='text/javascript'>
function dothis() {
var ais=null;
var urlis=' ';
while (urlis != '') {
if (document.hasFocus()) {
urlis=prompt('Enter URL that we will send you to (exit to stop)', '');
} else {
setTimeout(dothis, 2000); // urlis=' ';
return;
}
if (urlis == null) { urlis=''; }
if (urlis.toLowerCase() == 'exit') { return; }


if (urlis.trim() != '') {
if (urlis.substring(0,1) == '.') { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
} else if (urlis.substring(0,1) == '/' && urlis.indexOf('//') == -1) { // relative URL
urlis=document.URL.split('//')[0] + '//' + document.URL.split('//')[1].split('/')[0] + '/' + urlis;
} else if (urlis.split('/')[0].indexOf('.') != -1) { // absolute URL
if (urlis.toLowerCase().indexOf('http') != 0) {
if (urlis.indexOf('//') == 0) {
urlis=document.URL.split('//')[0] + urlis;
} else {
urlis=document.URL.split('//')[0] + '//' + urlis;
}
}
} else { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
}
ais=document.createElement('a');
ais.onclick=function() { window.open(urlis, '_blank', 'top=100,left=100,width=600,height=600'); };
if (1 == 2) { ais.href=urlis; }
ais.target='_blank';
ais.click();
}
}
setTimeout(dothis, 2000); // urlis=' ';
}


dothis();

</script>
</head>
</html>

nobody.html‘s live run link for you to use a Javascript prompt popup window’s user interaction results to navigate to a new webpage, as applicable. Bookmarklets may be scarce on the ground, but these “Just Javascript” ideas continue the Bookmarklet Spirit of the past!


Previous relevant Just Javascript Webmail No Body Attachment Tutorial is shown below.

Just Javascript Webmail No Body Attachment Tutorial

Just Javascript Webmail No Body Attachment Tutorial

A “hard liner” for the proper use of “business emails” could argue that an email without an attachment is not productive. Couldn’t you just have a face to face meeting instead, if there is just wording in the email (as we somewhat concur with, as an argument)? So yesterday’s Just Javascript Webmail No Body Tutorial had that limitation of no email attachment logic, which we remedy today.

And this is where PHP’s wonderful file_get_contents (function) means by which we garner (URL) content …

  • definitely works with “relative URLs” relative to HTTP://www.rjmprogramming.com.au/HTMLCSS/ where today’s unchanged webmail_nobody.html resides … in “parsing parlance” …

    "relative (URL)" to the left of any # or ? of what lies to the left of the most right hand "/" (of what the address bar URL is of the webpage you are on)

    … so that …

    1. “relative URLs” starting with “./” (followed by the filename, or just the filename (as you can see us using in today’s tutorial picture)) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/HTMLCSS/” … whereas, for example …
    2. “relative URLs” starting with “../” (followed by the filename) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/” … for example

    … and …

  • might work for “absolute URLs” (those that start with https: or HTTP: or even // (that we beg you not to confuse with Windows UNC pathnames) that infer a transport protocol of the transport protocol (out of https: or HTTP: or even file:) that got you to the webpage you are currently on), the “might” being far more likely on “absolute URLs” pointing to the same domain as indicated on the URL of the address bar of the webpage you are currently on

Upshot is, the user in their email Body section definitions (still no HTML body though!), can throw into any word they use, an “absolute URL” of interest, or a “relative URL” of interest, of files they want to attach (as attachments, doh!) in their email.

Depending on the email rules though, there are limits as to the amount of attachment data allowed. We’ll leave that to you intrepid “explorers of the Net” to discover for yourselves. On this subject though, have you noticed that with the Photos (or Gallery) app Share options, the Email option drops off when you have highlighted a large number of photos or videos or audios to share? That’s that email limit coming into play.

So feel free to try this HTML-body-less web application live run to see what we mean here. Though the parent HTML is unchanged today, the new (email) attachment functionality needed a changed PHP emailhtml.php to make this happen.

Did you know?

This (relative URL) “../” navigation backwards up the hierarchy of the web server directories will, if repeated (ie. nested to “../../” etcetera) too many times, get you into uncharted unnavigable (web server directory) places relative to that web server web site’s Document Root (below which you can not access in public webpages, normally). But when you perform similar thinking with “absolute URLs” and go “HTTP://www.rjmprogramming.com.au/HTMLCSS/../../../blahdeblah.jpg” (in a web browser address bar) for instance, you cannot get into trouble, as you just don’t get beyond this sending you to (attempt the reference to) “HTTP://www.rjmprogramming.com.au/blahdeblah.jpg” because on this rjmprogramming.com.au Apache domain the correspondence of the Document Root (web server directory) is to “HTTP://www.rjmprogramming.com.au/” as the place you are not allowed (and cannot) go below in the hierarchy tree.


Previous relevant Just Javascript Webmail No Body Tutorial is shown below.

Just Javascript Webmail No Body Tutorial

Just Javascript Webmail No Body Tutorial

Were you around and interested in our series of about three blog postings in the series on the theme of creating webpage functionality of some interest, involving no Javascript, when we presented Missing Javascript Audio on Unmute Tutorial? Well, today, it’s the turn of “just Javascript”, which is sort of like what Bookmarklets were about.

With today’s “just Javascript” we have to qualify that a little for our webmail emailing sender application with the architecture …

  • parent webpage with only document.head and apart from a document.title just a script Javascript tag of content (using Javascript prompt windows to ask for user information) …
  • sending (POSTing) data via …
    1. Ajax XMLHttpRequest object … as the conduit for …
    2. FormData object

    … to our changed

  • PHP communication emailing tool emailhtml.php … and out to …
  • the emailee (out there in the big wide woooorrrrrllllldddd)

Guess we find it interesting that you can do all this (sending of email to emailee recipients) with no document.body in sight.

So take a look at that parent webmail_nobody.html‘s live run link to see what we mean here, and/or watch the video below …


Previous relevant Missing Javascript Audio on Unmute Tutorial is shown below.

Missing Javascript Audio on Unmute Tutorial

Missing Javascript Audio on Unmute Tutorial

Our “third cab off the rank” following on from yesterday’s Missing Javascript Stop Watch Tutorial “missing Javascript” ideas is an HTML div nesting scenario using just …

  1. HTML
  2. CSS

… again, with some or all of the “usuals” below …

  • calc method to assist with defining width and height and size dimensions along with operator “+” and/or “-” offset calculation opportunities, and which we’d have used the Javascript window.getComputedStyle and/or [element].getBoundingClientRect methods to cover this (in a much more unwieldy way, as you would probably surmise)
  • CSS variables we started talking about here at CSS Variables Primer Tutorial
  • CSS3 @keyframes rules we first talked about at CSS3 @keyframes Rule Primer Tutorial that assist with animations that we can make work via …
  • CSS3 transitions for scheduled functionality (we’d have used Javascript setTimeout (and setInterval) methods to cover the same “territory”) we first talked about at CSS3 Transition Primer Tutorial … specified with CSS Criteria involving …
  • CSS Selectors :after and :before (and often, as for today’s work, with the content: CSS property) first talked about here with WordPress Bullet Point CSS Styling Primer Tutorial … and, today …
  • CSS3 transform property’s rotate (and translate and scale) settings (for the puppy dog body movements) … as well as the idea that …
  • On non mobile platforms you can set up the playing of “audio” data via the use of an HTML audio tag with the properties …
    1. controls
    2. autostart
    3. loop
    4. muted

    Stop Press

    Above is all fine and good for non-mobile but not so good for mobile, so to keep all happy with the one click, still, is to transfer HTML coding from …


    <audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" />

    … to …


    <!--audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" /-->
    <audio id='myaudiotwo' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="margin-left:-350px;opacity:0.1;" autostart="0" loop controls src="Puppy-sounds.mp3" />

    … and a src= URL data source (as we thank this link for today), or data URI if preferred (which we do for today’s image data from this link, thanks (when we were researching animated GIF data URIs (which we may return to at a later date))

… that sets up the scenario that all the user has to do to hear the audio is to click the “muted” control button, without needing the usual Javascript play() methods … but not on mobile!

Feel free to let the puppy play, that uses the HTML and CSS (but no Javascript) of the_nested.html and based largely on the previous HTML Nested Centering via Multiple Select Tutorial so that these changes reflect how we got to the first draft of today’s work. Maybe some of the ideas are of interest. We hope so!


Previous relevant Missing Javascript Stop Watch Tutorial is shown below.

Missing Javascript Stop Watch Tutorial

Missing Javascript Stop Watch Tutorial

Following on from yesterday’s Missing Javascript Primer Tutorial our second “cab off the rank” for “missing Javascript” ideas is a stop watch featuring just …

  1. HTML
  2. CSS

… again, setting up document.body load instigated

… which we needed to do to make multiple animations happen, but we used animation-delay:5s; to delay its start. The hands (second and minute, hence the two animations) are “overlay”

… feeling HTML horizontal rule elements that also feature linear gradients, to emphasise (in red) the “pointy end” of the “hand conversation” (good on walls with shadows … but we digress).

Feel free to let loose the stop watch that uses the HTML and CSS (but no Javascript) of stop_watch.html for today’s instructional information. Thanks to Clipart – stop watch for the great clip art used.


Previous relevant Missing Javascript Primer Tutorial is shown below.

Missing Javascript Primer Tutorial

Missing Javascript Primer Tutorial

If you were to ask me which programming component is most vital to web application development, I’d not be Robinson Crusoe in saying …

Without a doubt, Javascript

… and with that thought in mind we have a two pronged motive to see how far we go developing some web applications that “don’t use Javascript”, calling into play the …

  • meaning of “missing”, as in, our code is “missing” Javascript … as well as how I feel with the masochism of the exercise, calling into play the …
  • meaning of “missing”, as in, it’s hard work writing meaningful web applications without Javascript … but I guess we’ll learn a bit from the exercise of “see where we go”, allowing for the fact, not today, but down the track, that we will allow the use of server-side languages such as PHP

Okay, so, given that restriction, let’s see today’s challenge, to just use, in a web application …

  1. HTML
  2. CSS

… and here is where we have to point out that CSS3 introduced to us some functionality that improves the prospects for web application design “interest” without using Javascript (though it is hard to convince me even so, that I am not “missing” Javascript) here. CSS3 introduced to us …

… and we use all of these in our Festive Season themed web application today, you can try at this live run‘s calc_use.html (free of any Javascript (but “why” springs to mind … because it is NOT there, perhaps?)).

Here’s the other thing about today. Our long sought after “just make the body background be semi-transparent” but not its foreground parts, was solved, for us via the great advice of …

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


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


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


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


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


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


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


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


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


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


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


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


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


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

Just Javascript Memories Card Game Tutorial

Just Javascript Memories Card Game Tutorial

Just Javascript Memories Card Game Tutorial

Up until yesterday’s Just Javascript Card Order Game One Window Tutorial every mode of execution of our web application involved the Javascript prompt (popup) window method of getting information off the user.

Today, though, adding a Memories Card Game new functionality part uses a hybrid Javascript prompt window arrangement …

  • a first usage is to use the default Javascript prompt window arrangement you glean from the user the number of players in the Memories Card Game to follow …
  • and then from then on

    var lasttogglenumber='';
    var lastec='', notyet=false;
    var backi="/rjmquiz_plus.jpg";
    var fiftytwo=52;
    var message='';
    var lastcard='';
    var lasttto='';
    var gamescoreprefix='';
    var gamescores=[0];
    var lasttmid='';
    var lasttfrom='';
    var lasttoggleto='';
    var lasttogglefrom='';
    var curplayer=1, card_of_play=0;
    var card_game='memories';
    var nominal_implication='';
    var nominal_numplayers = (document.URL.replace('?','&').indexOf('&card') != -1) ? prompt('How many players are playing your ' + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(0,1).toUpperCase() + document.URL.replace('?','&').split('&card')[1].split('&')[0].split('#')[0].split('=')[0].replace(/\_/g,' ').trim().substring(1).toLowerCase() + ' card game?', '2') : null;

    if (nominal_numplayers) {
    if (('' + nominal_numplayers).replace('0','').trim() != '' && ('' + nominal_numplayers).replace('0','').trim().indexOf('-') == -1) {
    var prompt = function(zwords, defwords){ return null; };
    nominal_implication=" var prompt = function(zwords, defwords){ return null; }; ";
    fiftytwo=-1;
    backi="/Games/Memories/Memories.jpg";
    } else {
    nominal_numplayers=null;
    }
    }

… “prompt” is overridden as above. That, and overriding the scoring mechanisms, and this same codeset is nearly there towards accommodating our new quite different requirement.

But with “No Body Definition”/”Just Javascript” how can we show and implement this new Memories Card Game usage? It’s a two way integration, the easier one being …

  • offer a place for click/touch on the default background imagery … and with that webpage reminder …
  • what is an independent “add on” event methodology available to us, so as not to interfere with event logic that has preceded? … spoiler alert … double click …

    ele.addEventListener('dblclick', function(evt) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    });

    … (or two clicks quickly in a row) … as per

    var lastec='', notyet=false;


    function antilastec() {
    lastec='';
    }


    function antinotyet() {
    notyet=true;
    }


    ele.addEventListener('click', function(evt) {
    if (evt.touches) {
    if (evt.touches[0].pageX) {
    iourx = evt.touches[0].pageX;
    ioury = evt.touches[0].pageY;
    } else {
    iourx = evt.touches[0].clientX;
    ioury = evt.touches[0].clientY;
    }
    //alert('' + iourx);
    } else if (evt.clientX) {
    iourx = evt.clientX; // - elemLeft;
    ioury = evt.clientY; // - elemLeft;
    } else if (!evt.touches) {
    iourx = evt.pageX; // - elemLeft;
    ioury = evt.pageX; // - elemLeft;
    }
    if (('' + iourx + ',' + ioury) == lastec && lastec != '' && notyet) {
    location.href=document.URL.split('?')[0].split('#')[0] + '?card_memories=y';
    } else if (lastec == '') {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    } else {
    setTimeout(antilastec, 2000);
    setTimeout(antinotyet, 200);
    notyet=false;
    lastec='' + iourx + ',' + ioury;
    }

    clickedmaybe();
    });

Again, feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” Memories Card Game or live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game One Window Tutorial is shown below.

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

The “one window” rather than (52 + 1) = 53 windows scenario set up as a possibility with yesterday’s Just Javascript Card Order Game Mobile Tutorial had us wondering …

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

… and tomorrow is today. We’ve decided not to make the one window scenario the default for non-mobile platforms, but serve as a fallback for some of the scenarios mentioned below …

  • the user gets blocked from using the popup windows on their non-mobile platform web browser … big possibility!
  • the user clicks half way through the popup window incarnation the parent window … all the child popups disappear behind … annoying … so

    var flexible=false;

    function secsu() {
    var ewd;
    if (secs == 0) {
    if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    flexible=false;
    } else {
    flexible=true;
    console.log('Flexible=T');
    }

    setTimeout(blater, 2500);
    }
    if (eval('' + overallgoes) < 52) {
    secs++;
    } else if (document.title.indexOf('Congratulations') == -1) {
    document.title+=' ... Congratulations! End of Game! Refresh webpage to try again.';
    }
    var decs=document.title.split('.');
    if (eval('' + decs.length) >= 3) {
    document.title=document.title.replace('.' + decs[2].split(' ')[0] + ' ', '.' + secs + ' ');
    } else {
    ps=document.title.split('/')[0].trim();
    pg=document.title.split('/')[1].split(' ')[0];
    if (ps.indexOf('.') == -1 || pg.indexOf('.') == -1) {
    ps=eval('' + overallscore + '.' + psecs); //eval(document.title.split('/')[0].trim());
    pg=eval('' + overallgoes + '.' + secs);
    document.title=document.title.replace(document.title.split(' ')[0], '' + overallscore + '.' + psecs + '/' + '' + overallgoes + '.' + secs);
    //console.log('document.title becomes ' + document.title);
    } else {
    ps=eval(ps);
    pg=eval(pg);
    }
    }


    if (flexible) {
    if (document.hasFocus()) {
    flexible=false;
    console.log('Flexible=F');
    lastzkq='';
    lastzkl='';
    owidth=oowidth;
    oheight=ooheight;
    for (var igh=0; igh<oplist.length; igh++) {
    opltlistl[igh]=oopltlistl[igh];
    opltlistt[igh]=oopltlistt[igh];
    if (oplist[igh]) {
    console.log('Flexible=F' + igh);
    if (!oplist[igh].closed) {
    try {
    oplist[igh].close();
    oplist[igh]=null;
    } catch(ewd) {
    }
    } else {
    oplist[igh]=null;
    }
    }
    }
    }
    }

    }

… document.hasFocus() to the rescue again … the multiple background images of yesterday’s work being a default part of any incarnation, and whether the click event logic of yesterday becomes relevant depends on …

  • if user is a mobile platform user, always relevant
  • user enters URL with argument like ?onewindow=y then is always relevant … else …
  • a scenario as above means that from that point on, the multiple background image one window click on cards modus operandi becomes relevant

We improve the web browser conditions too, if a non-mobile user “clicks half way through the popup window incarnation the parent window” in that we programmatically close any open child popup windows! Phew!

Feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game Mobile Tutorial is shown below.

Just Javascript Card Order Game Mobile Tutorial

Just Javascript Card Order Game Mobile Tutorial

Yesterday’s Just Javascript Card Order Game Tutorial mobile usage scenario was impractical, in that mobile platforms can not work popup windows in front of a parent window. Can we convert those non-mobile popup windows into … well … what exactly?

Well, in order to keep to our “Just Javascript” (ie. “No Body Definition”) pledge with this project, we needed to simulate those popups as background image parts, in the sense that you can have multiple background images these days with your HTML. Even with html as your CSS styling selector … it pans out … we needed to prove that today.

Also, today, for the first time, we achieved via …

  1. comma separated background-repeat: no-repeat; list
  2. comma separated background-size list (set popup width height list until last one bigger (based on screen.width screen.height) for the parent background image (no-repeat))
  3. comma separated background-position list (as per what window.open in non-mobile was using for left top until last one’s 0px 0px)
  4. comma separated background-image list (as per what window.open in non-mobile was using for URL([imageURL]) until last one’s linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)), url(//www.rjmprogramming.com.au/rjmquiz_plus.jpg))

… as per (the previous “window.open” becomes “windowopen”) …


function windowopen(one, two, three) {
if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
console.log('Here ' + kq);
opltlistl.push((three.split('left=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + one.split('spcp=')[1].split('&')[0]));
opltlistt.push((three.split('top=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + kq));
owidth=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
oheight=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
if (defstyle.indexOf('background: URL(') != -1) {
defstyle=defstyle.split('background: URL(')[0] + 'background-repeat:no-repeat;background-size:' + owidth + 'px ' + oheight + 'px;background-position:' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image: url(' + cards[eval('' + donelist[eval(-1 + donelist.length)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'; // + ' ' + owidth + ' ' + oheight
} else {
defstyle=defstyle.replace(';background-image:', (',' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image:');
defstyle=defstyle.replace('no-repeat','no-repeat,no-repeat');
defstyle=defstyle.replace('background-size:' + owidth + 'px ' + oheight + 'px','background-size:' + owidth + 'px ' + oheight + 'px,' + owidth + 'px ' + oheight + 'px');
defstyle=defstyle.replace('; } </style>', ',url(' + cards[eval('' + donelist[eval(0 + ijk)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'); // + ' ' + owidth + ' ' + oheight
}
return null;
}
return window.open(one, two, three);
}

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

We needed to add event logic we were not sure would work at the start of the day, and saw it working by the end, with …


var iourx=-1, ioury=-1;

function blater() {
if (1 == 2 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
window.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
eles = document.querySelectorAll("*")
for (var ele of eles) {
console.log('yes well');
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ele.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('touchmove', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('click', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
ele.addEventListener('click', function(evt) {
if (evt.touches) {
if (evt.touches[0].pageX) {
iourx = evt.touches[0].pageX;
ioury = evt.touches[0].pageY;
} else {
iourx = evt.touches[0].clientX;
ioury = evt.touches[0].clientY;
}
//alert('' + iourx);
} else if (evt.clientX) {
iourx = evt.clientX; // - elemLeft;
ioury = evt.clientY; // - elemLeft;
} else if (!evt.touches) {
iourx = evt.pageX; // - elemLeft;
ioury = evt.pageX; // - elemLeft;
}
clickedmaybe();
//alert('here');
});
}
}
}
}

See this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform) we, again, welcome you to try for yourself.


Previous relevant Just Javascript Card Order Game Tutorial is shown below.

Just Javascript Card Order Game Tutorial

Just Javascript Card Order Game Tutorial

Today we’ve made the web application of yesterday’s Just Javascript Quiz Drag Tutorial “dual purpose” …

  • quiz … as for yesterday, and before … and as of today, making more use of the card organizational side to the popup windows we introduce …
  • card order game

This card order game asks you to force the focus of the correct popup window (to score in the Card Order Game) in the order as designated by the background image part we have added today, and supported by the following Javascript “mapping” code …


var dragorder=[], curdrag=0;

var cards=["//www.rjmprogramming.com.au/images/01s.gif?n=7",
"//www.rjmprogramming.com.au/images/02s.gif?n=16",
"//www.rjmprogramming.com.au/images/03s.gif?n=33",
"//www.rjmprogramming.com.au/images/04s.gif?n=29",
"//www.rjmprogramming.com.au/images/05s.gif?n=8",
"//www.rjmprogramming.com.au/images/06s.gif?n=35",
"//www.rjmprogramming.com.au/images/07s.gif?n=52",
"//www.rjmprogramming.com.au/images/08s.gif?n=51",
"//www.rjmprogramming.com.au/images/09s.gif?n=12",
"//www.rjmprogramming.com.au/images/10s.gif?n=30",
"//www.rjmprogramming.com.au/images/11s.gif?n=1",
"//www.rjmprogramming.com.au/images/12s.gif?n=36",
"//www.rjmprogramming.com.au/images/13s.gif?n=22",
"//www.rjmprogramming.com.au/images/01h.gif?n=32",
"//www.rjmprogramming.com.au/images/02h.gif?n=23",
"//www.rjmprogramming.com.au/images/03h.gif?n=3",
"//www.rjmprogramming.com.au/images/04h.gif?n=18",
"//www.rjmprogramming.com.au/images/05h.gif?n=28",
"//www.rjmprogramming.com.au/images/06h.gif?n=39",
"//www.rjmprogramming.com.au/images/07h.gif?n=45",
"//www.rjmprogramming.com.au/images/08h.gif?n=48",
"//www.rjmprogramming.com.au/images/09h.gif?n=50",
"//www.rjmprogramming.com.au/images/10h.gif?n=44",
"//www.rjmprogramming.com.au/images/11h.gif?n=4",
"//www.rjmprogramming.com.au/images/12h.gif?n=9",
"//www.rjmprogramming.com.au/images/13h.gif?n=5",
"//www.rjmprogramming.com.au/images/01d.gif?n=27",
"//www.rjmprogramming.com.au/images/02d.gif?n=41",
"//www.rjmprogramming.com.au/images/03d.gif?n=20",
"//www.rjmprogramming.com.au/images/04d.gif?n=11",
"//www.rjmprogramming.com.au/images/05d.gif?n=37",
"//www.rjmprogramming.com.au/images/06d.gif?n=49",
"//www.rjmprogramming.com.au/images/07d.gif?n=42",
"//www.rjmprogramming.com.au/images/08d.gif?n=6",
"//www.rjmprogramming.com.au/images/09d.gif?n=21",
"//www.rjmprogramming.com.au/images/10d.gif?n=31",
"//www.rjmprogramming.com.au/images/11d.gif?n=40",
"//www.rjmprogramming.com.au/images/12d.gif?n=43",
"//www.rjmprogramming.com.au/images/13d.gif?n=17",
"//www.rjmprogramming.com.au/images/01c.gif?n=46",
"//www.rjmprogramming.com.au/images/02c.gif?n=19",
"//www.rjmprogramming.com.au/images/03c.gif?n=47",
"//www.rjmprogramming.com.au/images/04c.gif?n=25",
"//www.rjmprogramming.com.au/images/05c.gif?n=10",
"//www.rjmprogramming.com.au/images/06c.gif?n=15",
"//www.rjmprogramming.com.au/images/07c.gif?n=13",
"//www.rjmprogramming.com.au/images/08c.gif?n=26",
"//www.rjmprogramming.com.au/images/09c.gif?n=38",
"//www.rjmprogramming.com.au/images/10c.gif?n=34",
"//www.rjmprogramming.com.au/images/11c.gif?n=2",
"//www.rjmprogramming.com.au/images/12c.gif?n=14",
"//www.rjmprogramming.com.au/images/13c.gif?n=24"];


for (var ic=1; ic<=cards.length; ic++) {
found=false;
for (var jc=1; jc<=cards.length; jc++) {
if ((cards[eval(-1 + jc)] + '~').indexOf('?n=' + ic + '~') != -1) {
dragorder.push(eval(-1 + jc));
cards[eval(-1 + jc)]=cards[eval(-1 + jc)].replace('?n=' + ic, '');
firstbit+=String.fromCodePoint(eval('' + spcps[eval(-1 + jc)].split('/')[0])) + ' ';
found=true;
}
}
}

… and “making use of” this and the new codeline as popups are created … oplist[eval(-1 + oplist.length)].document.name=” + kl; we have …


function ourprompt(tw, blb, bdef) {
var kijk;
if (oplist[eval('' + tw)].document.name == ('' + dragorder[eval('' + curdrag)]) && eval('' + curdrag) == eval('' + overallgoes)) {
console.log('Dragorder[' + curdrag + ']=' + dragorder[eval('' + curdrag)] + ' vs tw=' + tw + ' and overall;goes=' + overallgoes);
var decs=document.title.split('.');
curdrag++;
overallgoes++;
if (eval('' + decs.length) >= 3) {
document.title=document.title.replace('.' + decs[1] + '.', '.' + curdrag + '/' + overallgoes + '.');
}
oplist[eval('' + tw)].close();
return null;
}

// Quiz only code follows
}

… code.

It must be in the correct order (and not interrupted by quiz answer completions) to score, and you are timed, so you can try improving over time, using a document.title score presentation as per …


[QuizScore].[CardOrderGameScore]/[QuizAnswerAttemptCount].[SecondsElapsed] [MultiPlayerQuizScoreGoesBreakdown] is User: Score/Goes - RJM Programming - April, 2021

… so that both usages for the web application can be accommodated for in the changed cards_usefocus.html code behind the “Just Javascript” live run we welcome you to try for yourself.


Previous relevant Just Javascript Quiz Drag Tutorial is shown below.

Just Javascript Quiz Drag Tutorial

Just Javascript Quiz Drag Tutorial

Adding to yesterday’s Just Javascript Quiz CSS Styling Tutorial we have added some …

  • non-mobile platform, only …
  • drag and drop functionality … for …
  • the child popup windows

… achieved through the comparison of …

  • original [popupWindow].screenLeft and [popupWindow].screenTop … initially, to …
  • [popupWindow].screenLeft and [popupWindow].screenTop over time

… and if one popup is dragged to overlay another it is closed, or you, as the user, can just drag and drop for clarity, leaving the popup window of the next quiz question out in the open, perhaps.

In order to achieve this, and keep backward compatibility we needed to delay the quiz question prompt window via …

  1. document.hasFocus() is true … then if …
  2. inhouse dragging checks clear it of overlaying another popup (in which case that popup is programmatically closed, allowing another popup to become the “focus window”) … then …
  3. delay (by 8 seconds) the prompt window (and in that time the user can be dragging popups (but no popups were harmed in the making of this tutorial)) … via …

    setTimeout(function() { hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } else { hj=window.opener.assess(hj); } if (hj.replace(def,'') != '') { checka(hj); } else { setTimeout(pa,10000); } aminmiddle=false; }, 8000);

… you can see in amongst the changed cards_usefocus.html code behind the “Just Javascript” live run you are welcome to try for yourself … best on non-mobile.

Still “No Body Definition”, “Just Javascript”!


Previous relevant Just Javascript Quiz CSS Styling Tutorial is shown below.

Just Javascript Quiz CSS Styling Tutorial

Just Javascript Quiz CSS Styling Tutorial

Our “Just Javascript” adage used throughout this blog posting thread, up until today, headed by yesterday’s Just Javascript Quiz Content Management Tutorial needs more explanation. Really what we are trying to do might better be described as “No Body Definition” (ie. no defined document.body) but have …

  1. an HTML webpage (ie. within <html> and </html>) … has …
  2. <head> and </head> (ie. document.head) content which can be made up of (at least) title, style, script, link, meta tags

To assert “Just Javascript” is just to allow script content above, but what we should really say is “Just Head Content” but that is not nearly so marketable, is it now?!

The thing is, though, we can dynamically add title, style, link, meta tag content within the script content, and we do this more than statically define it, to feel better about our ethics saying “Just Javascript”.

Dynamically adding style CSS styling either …

  • using Javascript DOM (not available to us for document.getElementById([elementID] and nor can we use inline CSS via style=”[CSSstyling]” statically within HTML element code for that same reason) ideas today though … remember “No Body Definition” … but …
  • we can append to <head> and </head> (for today’s scenario) as per …

    document.head.innerHTML+="<style> html { background-color: yellow; font-size: 36px; background: URL('//www.rjmprogramming.com.au/rjmquiz.jpg'); background-size: cover; } </style>";

… allowing (into the scope of our work CSS styling of) background (image(s)) and other background styling ideas that can get us past the anonymous feel the web application had before today. We tailored the background image above to suit our Quiz and help it be a bit more self explanatory … thanks CSS styling! We add onto the child “card” popup windows, their own background image colour and pizazz, to cheer things up in CSS styling enhanced cards_usefocus.html code behind the “Just Javascript” live run.

You may well ask …

What can we hang our hat on with CSS style selectors without a body element?

Well, we had to step out of our usual comfort zone of CSS styling thinking, and realize, even without that body element we can still use the html selector to “point at” the entirety of your webpage of interest.


Previous relevant Just Javascript Quiz Content Management Tutorial is shown below.

Just Javascript Quiz Content Management Tutorial

Just Javascript Quiz Content Management Tutorial

It feels like an “onions of the 4th dimension” idea to allow the user to control the questions and answers behind the workings of yesterday’s Just Javascript Quiz Multiple Users Tutorial‘s web application, featuring “Just Javascript”.

It’s not “Just Javascript” we’re keeping, it’s “Just HTML” client work rather than involving any serverside anything (eg.PHP) and yet this question and answer data could be quite sizeable. What can we use, given no PHP serverside, and given we’ve decided not to navigate via Ajax/FormData techniques? How about “the better than HTTP Cookies” twins …

Yep, set up a means by which these two can store and restore questions and answers entered by the user, using these storage methods above.


function reassess() {
var retv='', ewq;
var retcols=[];
var ir=0;
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '') {
//alert('0:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?!')[0] + '?');
asq.push(retcols[ir].split('?!')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '') {
//alert('1:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?')[0] + '?');
asq.push(retcols[ir].split('?')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
}


function assess(what) {
var ewq, retv='';
if (what.toLowerCase() == '?x') {
sslistq=[];
sslista=[];
if (window.sessionStorage) {
try {
window.sessionStorage.removeItem('cards_usefocus_session');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase() == '?!x') {
lslistq=[];
lslista=[];
if (window.localStorage) {
try {
window.localStorage.removeItem('cards_usefocus_local');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase().indexOf('?!') != -1) {
if (what.toLowerCase() == '?!') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.localStorage) {
if (lslistq.length == 0) {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', encodeURIComponent(what));
} else {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', window.localStorage.getItem('cards_usefocus_local') + encodeURIComponent('~' + what));
}
}
return '';
} else if (what.toLowerCase().indexOf('?') != -1) {
if (what.toLowerCase() == '?') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.sessionStorage) {
if (sslistq.length == 0) {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', encodeURIComponent(what));
} else {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', window.sessionStorage.getItem('cards_usefocus_session') + encodeURIComponent('~' + what));
}
}
return '';
} else {
firstbit='';
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
}
return what;
}

The fairly significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz Multiple Users Tutorial is shown below.

Just Javascript Quiz Multiple Users Tutorial

Just Javascript Quiz Multiple Users Tutorial

Adding to yesterday’s Just Javascript Quiz via Cards Tutorial we were surprised how difficult it was to stay with “Just Javascript” and allow for multiple player play.

We didn’t opt for the parent to ask about the number of players, curiously, but on the second quiz answer and on, offered any non first player the chance to identify themselves as a new player into the game by appending their answer with a space character.

The implication of that is that we’ll want to run Javascript functions of the parent from the children as per


oplist[eval(-1 + oplist.length)].document.write("<link rel=icon href=" + cards[kl] + "><scr" + "ipt type='text/javascript'> var da='" + eval(0 + kq) + "'; var dp='Given answer is integer from 0 to 25 ... " + sq[kq] + "'; var def=String.fromCodePoint(" + spcps[eval('' + kl)].split('/')[0] + "); function checka(tpa) { var os=''; var ps=eval(window.opener.document.title.split('/')[0].trim()); var pg=eval(window.opener.document.title.split('/')[1].split(' ')[0]); if (tpa.trim() == da) { ps++; os=tpa.split(da)[1]; } else { pg++; os=tpa.split(tpa.trim())[1]; } window.opener.document.title=ps + os + '/' + pg + ' is User Score/Goes'; window.close(); } function pa() { if (document.hasFocus()) { var hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } if (hj.replace(def,'') == '') { setTimeout(pa,1000); } else { checka(hj); } } else { setTimeout(pa,1000); } } pa(); </scr" + "ipt>");

… accessing …


function blurb() { // theblurb and wblurb are global variables changed elsewhere
if (wblurb == ' Hello Player 1' && theblurb == ' If you are player 2 rather than player 1 append space to your answer.') {
theblurb='';
wblurb='';
}
return theblurb + wblurb;
}

… giving the rather curious behaviour whereby a Javascript prompt window can be dynamically different from one document.hasFocus() incarnation (ie. the user might go away and answer another “card” Number Quiz question) to another (even not attending to answering the Javascript prompt window) … huh?!

The significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz via Cards Tutorial is shown below.

Just Javascript Quiz via Cards Tutorial

Just Javascript Quiz via Cards Tutorial

Yesterday’s Just Javascript Navigation Tutorial continues our interest in “Just Javascript” (or “No Body”) web applications.

We think today’s “Numbers Quiz” via a “Card Deck” organizational design ups the ante on all this. We realize now what we have been missing not having involved document.hasFocus() in any of our popup window scenarios. Today, at least on non-mobile, we involve 52 such popup windows each containing a “Number Quiz” question presented as a Javascript prompt (sub-)window. This would not be feasible without document.hasFocus() as you can tell if you examine the cards_usefocus.html code behind the “Just Javascript” live run best used on your non-mobile platforms where popup windows can sit in front of parent (and beside sibling) windows, whereas mobile platforms open new web browser tabs for all the 52 windows of (a card deck) design.

Look out, too, in the code above, for use of window.opener back reference from a popup window back to the parent window where the scoring data is held, and updated by each popup window because of that window.opener avaalability.


Previous relevant Just Javascript Navigation Tutorial is shown below.

Just Javascript Navigation Tutorial

Just Javascript Navigation Tutorial

The recent use we made of …


document.createElement/click()

… got us thinking of the “Just Javascript” (or No Body) blog posting thread headed by Just Javascript Webmail No Body Attachment Tutorial.

As such, today we present the very simple (but first time use of the interesting hasFocus) “proof of concept” …


<html>
<head>
<script type='text/javascript'>
function dothis() {
var ais=null;
var urlis=' ';
while (urlis != '') {
if (document.hasFocus()) {
urlis=prompt('Enter URL that we will send you to (exit to stop)', '');
} else {
setTimeout(dothis, 2000); // urlis=' ';
return;
}
if (urlis == null) { urlis=''; }
if (urlis.toLowerCase() == 'exit') { return; }


if (urlis.trim() != '') {
if (urlis.substring(0,1) == '.') { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
} else if (urlis.substring(0,1) == '/' && urlis.indexOf('//') == -1) { // relative URL
urlis=document.URL.split('//')[0] + '//' + document.URL.split('//')[1].split('/')[0] + '/' + urlis;
} else if (urlis.split('/')[0].indexOf('.') != -1) { // absolute URL
if (urlis.toLowerCase().indexOf('http') != 0) {
if (urlis.indexOf('//') == 0) {
urlis=document.URL.split('//')[0] + urlis;
} else {
urlis=document.URL.split('//')[0] + '//' + urlis;
}
}
} else { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
}
ais=document.createElement('a');
ais.onclick=function() { window.open(urlis, '_blank', 'top=100,left=100,width=600,height=600'); };
if (1 == 2) { ais.href=urlis; }
ais.target='_blank';
ais.click();
}
}
setTimeout(dothis, 2000); // urlis=' ';
}


dothis();

</script>
</head>
</html>

nobody.html‘s live run link for you to use a Javascript prompt popup window’s user interaction results to navigate to a new webpage, as applicable. Bookmarklets may be scarce on the ground, but these “Just Javascript” ideas continue the Bookmarklet Spirit of the past!


Previous relevant Just Javascript Webmail No Body Attachment Tutorial is shown below.

Just Javascript Webmail No Body Attachment Tutorial

Just Javascript Webmail No Body Attachment Tutorial

A “hard liner” for the proper use of “business emails” could argue that an email without an attachment is not productive. Couldn’t you just have a face to face meeting instead, if there is just wording in the email (as we somewhat concur with, as an argument)? So yesterday’s Just Javascript Webmail No Body Tutorial had that limitation of no email attachment logic, which we remedy today.

And this is where PHP’s wonderful file_get_contents (function) means by which we garner (URL) content …

  • definitely works with “relative URLs” relative to HTTP://www.rjmprogramming.com.au/HTMLCSS/ where today’s unchanged webmail_nobody.html resides … in “parsing parlance” …

    "relative (URL)" to the left of any # or ? of what lies to the left of the most right hand "/" (of what the address bar URL is of the webpage you are on)

    … so that …

    1. “relative URLs” starting with “./” (followed by the filename, or just the filename (as you can see us using in today’s tutorial picture)) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/HTMLCSS/” … whereas, for example …
    2. “relative URLs” starting with “../” (followed by the filename) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/” … for example

    … and …

  • might work for “absolute URLs” (those that start with https: or HTTP: or even // (that we beg you not to confuse with Windows UNC pathnames) that infer a transport protocol of the transport protocol (out of https: or HTTP: or even file:) that got you to the webpage you are currently on), the “might” being far more likely on “absolute URLs” pointing to the same domain as indicated on the URL of the address bar of the webpage you are currently on

Upshot is, the user in their email Body section definitions (still no HTML body though!), can throw into any word they use, an “absolute URL” of interest, or a “relative URL” of interest, of files they want to attach (as attachments, doh!) in their email.

Depending on the email rules though, there are limits as to the amount of attachment data allowed. We’ll leave that to you intrepid “explorers of the Net” to discover for yourselves. On this subject though, have you noticed that with the Photos (or Gallery) app Share options, the Email option drops off when you have highlighted a large number of photos or videos or audios to share? That’s that email limit coming into play.

So feel free to try this HTML-body-less web application live run to see what we mean here. Though the parent HTML is unchanged today, the new (email) attachment functionality needed a changed PHP emailhtml.php to make this happen.

Did you know?

This (relative URL) “../” navigation backwards up the hierarchy of the web server directories will, if repeated (ie. nested to “../../” etcetera) too many times, get you into uncharted unnavigable (web server directory) places relative to that web server web site’s Document Root (below which you can not access in public webpages, normally). But when you perform similar thinking with “absolute URLs” and go “HTTP://www.rjmprogramming.com.au/HTMLCSS/../../../blahdeblah.jpg” (in a web browser address bar) for instance, you cannot get into trouble, as you just don’t get beyond this sending you to (attempt the reference to) “HTTP://www.rjmprogramming.com.au/blahdeblah.jpg” because on this rjmprogramming.com.au Apache domain the correspondence of the Document Root (web server directory) is to “HTTP://www.rjmprogramming.com.au/” as the place you are not allowed (and cannot) go below in the hierarchy tree.


Previous relevant Just Javascript Webmail No Body Tutorial is shown below.

Just Javascript Webmail No Body Tutorial

Just Javascript Webmail No Body Tutorial

Were you around and interested in our series of about three blog postings in the series on the theme of creating webpage functionality of some interest, involving no Javascript, when we presented Missing Javascript Audio on Unmute Tutorial? Well, today, it’s the turn of “just Javascript”, which is sort of like what Bookmarklets were about.

With today’s “just Javascript” we have to qualify that a little for our webmail emailing sender application with the architecture …

  • parent webpage with only document.head and apart from a document.title just a script Javascript tag of content (using Javascript prompt windows to ask for user information) …
  • sending (POSTing) data via …
    1. Ajax XMLHttpRequest object … as the conduit for …
    2. FormData object

    … to our changed

  • PHP communication emailing tool emailhtml.php … and out to …
  • the emailee (out there in the big wide woooorrrrrllllldddd)

Guess we find it interesting that you can do all this (sending of email to emailee recipients) with no document.body in sight.

So take a look at that parent webmail_nobody.html‘s live run link to see what we mean here, and/or watch the video below …


Previous relevant Missing Javascript Audio on Unmute Tutorial is shown below.

Missing Javascript Audio on Unmute Tutorial

Missing Javascript Audio on Unmute Tutorial

Our “third cab off the rank” following on from yesterday’s Missing Javascript Stop Watch Tutorial “missing Javascript” ideas is an HTML div nesting scenario using just …

  1. HTML
  2. CSS

… again, with some or all of the “usuals” below …

  • calc method to assist with defining width and height and size dimensions along with operator “+” and/or “-” offset calculation opportunities, and which we’d have used the Javascript window.getComputedStyle and/or [element].getBoundingClientRect methods to cover this (in a much more unwieldy way, as you would probably surmise)
  • CSS variables we started talking about here at CSS Variables Primer Tutorial
  • CSS3 @keyframes rules we first talked about at CSS3 @keyframes Rule Primer Tutorial that assist with animations that we can make work via …
  • CSS3 transitions for scheduled functionality (we’d have used Javascript setTimeout (and setInterval) methods to cover the same “territory”) we first talked about at CSS3 Transition Primer Tutorial … specified with CSS Criteria involving …
  • CSS Selectors :after and :before (and often, as for today’s work, with the content: CSS property) first talked about here with WordPress Bullet Point CSS Styling Primer Tutorial … and, today …
  • CSS3 transform property’s rotate (and translate and scale) settings (for the puppy dog body movements) … as well as the idea that …
  • On non mobile platforms you can set up the playing of “audio” data via the use of an HTML audio tag with the properties …
    1. controls
    2. autostart
    3. loop
    4. muted

    Stop Press

    Above is all fine and good for non-mobile but not so good for mobile, so to keep all happy with the one click, still, is to transfer HTML coding from …


    <audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" />

    … to …


    <!--audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" /-->
    <audio id='myaudiotwo' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="margin-left:-350px;opacity:0.1;" autostart="0" loop controls src="Puppy-sounds.mp3" />

    … and a src= URL data source (as we thank this link for today), or data URI if preferred (which we do for today’s image data from this link, thanks (when we were researching animated GIF data URIs (which we may return to at a later date))

… that sets up the scenario that all the user has to do to hear the audio is to click the “muted” control button, without needing the usual Javascript play() methods … but not on mobile!

Feel free to let the puppy play, that uses the HTML and CSS (but no Javascript) of the_nested.html and based largely on the previous HTML Nested Centering via Multiple Select Tutorial so that these changes reflect how we got to the first draft of today’s work. Maybe some of the ideas are of interest. We hope so!


Previous relevant Missing Javascript Stop Watch Tutorial is shown below.

Missing Javascript Stop Watch Tutorial

Missing Javascript Stop Watch Tutorial

Following on from yesterday’s Missing Javascript Primer Tutorial our second “cab off the rank” for “missing Javascript” ideas is a stop watch featuring just …

  1. HTML
  2. CSS

… again, setting up document.body load instigated

… which we needed to do to make multiple animations happen, but we used animation-delay:5s; to delay its start. The hands (second and minute, hence the two animations) are “overlay”

… feeling HTML horizontal rule elements that also feature linear gradients, to emphasise (in red) the “pointy end” of the “hand conversation” (good on walls with shadows … but we digress).

Feel free to let loose the stop watch that uses the HTML and CSS (but no Javascript) of stop_watch.html for today’s instructional information. Thanks to Clipart – stop watch for the great clip art used.


Previous relevant Missing Javascript Primer Tutorial is shown below.

Missing Javascript Primer Tutorial

Missing Javascript Primer Tutorial

If you were to ask me which programming component is most vital to web application development, I’d not be Robinson Crusoe in saying …

Without a doubt, Javascript

… and with that thought in mind we have a two pronged motive to see how far we go developing some web applications that “don’t use Javascript”, calling into play the …

  • meaning of “missing”, as in, our code is “missing” Javascript … as well as how I feel with the masochism of the exercise, calling into play the …
  • meaning of “missing”, as in, it’s hard work writing meaningful web applications without Javascript … but I guess we’ll learn a bit from the exercise of “see where we go”, allowing for the fact, not today, but down the track, that we will allow the use of server-side languages such as PHP

Okay, so, given that restriction, let’s see today’s challenge, to just use, in a web application …

  1. HTML
  2. CSS

… and here is where we have to point out that CSS3 introduced to us some functionality that improves the prospects for web application design “interest” without using Javascript (though it is hard to convince me even so, that I am not “missing” Javascript) here. CSS3 introduced to us …

… and we use all of these in our Festive Season themed web application today, you can try at this live run‘s calc_use.html (free of any Javascript (but “why” springs to mind … because it is NOT there, perhaps?)).

Here’s the other thing about today. Our long sought after “just make the body background be semi-transparent” but not its foreground parts, was solved, for us via the great advice of …

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


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


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


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


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


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


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


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


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


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


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


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


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

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

Just Javascript Card Order Game One Window Tutorial

The “one window” rather than (52 + 1) = 53 windows scenario set up as a possibility with yesterday’s Just Javascript Card Order Game Mobile Tutorial had us wondering …

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

… and tomorrow is today. We’ve decided not to make the one window scenario the default for non-mobile platforms, but serve as a fallback for some of the scenarios mentioned below …

  • the user gets blocked from using the popup windows on their non-mobile platform web browser … big possibility!
  • the user clicks half way through the popup window incarnation the parent window … all the child popups disappear behind … annoying … so

    var flexible=false;

    function secsu() {
    var ewd;
    if (secs == 0) {
    if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    flexible=false;
    } else {
    flexible=true;
    console.log('Flexible=T');
    }

    setTimeout(blater, 2500);
    }
    if (eval('' + overallgoes) < 52) {
    secs++;
    } else if (document.title.indexOf('Congratulations') == -1) {
    document.title+=' ... Congratulations! End of Game! Refresh webpage to try again.';
    }
    var decs=document.title.split('.');
    if (eval('' + decs.length) >= 3) {
    document.title=document.title.replace('.' + decs[2].split(' ')[0] + ' ', '.' + secs + ' ');
    } else {
    ps=document.title.split('/')[0].trim();
    pg=document.title.split('/')[1].split(' ')[0];
    if (ps.indexOf('.') == -1 || pg.indexOf('.') == -1) {
    ps=eval('' + overallscore + '.' + psecs); //eval(document.title.split('/')[0].trim());
    pg=eval('' + overallgoes + '.' + secs);
    document.title=document.title.replace(document.title.split(' ')[0], '' + overallscore + '.' + psecs + '/' + '' + overallgoes + '.' + secs);
    //console.log('document.title becomes ' + document.title);
    } else {
    ps=eval(ps);
    pg=eval(pg);
    }
    }


    if (flexible) {
    if (document.hasFocus()) {
    flexible=false;
    console.log('Flexible=F');
    lastzkq='';
    lastzkl='';
    owidth=oowidth;
    oheight=ooheight;
    for (var igh=0; igh<oplist.length; igh++) {
    opltlistl[igh]=oopltlistl[igh];
    opltlistt[igh]=oopltlistt[igh];
    if (oplist[igh]) {
    console.log('Flexible=F' + igh);
    if (!oplist[igh].closed) {
    try {
    oplist[igh].close();
    oplist[igh]=null;
    } catch(ewd) {
    }
    } else {
    oplist[igh]=null;
    }
    }
    }
    }
    }

    }

… document.hasFocus() to the rescue again … the multiple background images of yesterday’s work being a default part of any incarnation, and whether the click event logic of yesterday becomes relevant depends on …

  • if user is a mobile platform user, always relevant
  • user enters URL with argument like ?onewindow=y then is always relevant … else …
  • a scenario as above means that from that point on, the multiple background image one window click on cards modus operandi becomes relevant

We improve the web browser conditions too, if a non-mobile user “clicks half way through the popup window incarnation the parent window” in that we programmatically close any open child popup windows! Phew!

Feel free to try this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform, and if non-mobile it will try child popup windows).


Previous relevant Just Javascript Card Order Game Mobile Tutorial is shown below.

Just Javascript Card Order Game Mobile Tutorial

Just Javascript Card Order Game Mobile Tutorial

Yesterday’s Just Javascript Card Order Game Tutorial mobile usage scenario was impractical, in that mobile platforms can not work popup windows in front of a parent window. Can we convert those non-mobile popup windows into … well … what exactly?

Well, in order to keep to our “Just Javascript” (ie. “No Body Definition”) pledge with this project, we needed to simulate those popups as background image parts, in the sense that you can have multiple background images these days with your HTML. Even with html as your CSS styling selector … it pans out … we needed to prove that today.

Also, today, for the first time, we achieved via …

  1. comma separated background-repeat: no-repeat; list
  2. comma separated background-size list (set popup width height list until last one bigger (based on screen.width screen.height) for the parent background image (no-repeat))
  3. comma separated background-position list (as per what window.open in non-mobile was using for left top until last one’s 0px 0px)
  4. comma separated background-image list (as per what window.open in non-mobile was using for URL([imageURL]) until last one’s linear-gradient(rgba(255,255,255,0.4),rgba(255,255,255,0.4)), url(//www.rjmprogramming.com.au/rjmquiz_plus.jpg))

… as per (the previous “window.open” becomes “windowopen”) …


function windowopen(one, two, three) {
if (document.URL.indexOf('onewindow=') != -1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
console.log('Here ' + kq);
opltlistl.push((three.split('left=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + one.split('spcp=')[1].split('&')[0]));
opltlistt.push((three.split('top=')[1].split(',')[0].split(')')[0].split('.')[0] + '.' + kq));
owidth=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
oheight=eval(three.split('width=')[1].split(',')[0].split(')')[0].split('.')[0]);
if (defstyle.indexOf('background: URL(') != -1) {
defstyle=defstyle.split('background: URL(')[0] + 'background-repeat:no-repeat;background-size:' + owidth + 'px ' + oheight + 'px;background-position:' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image: url(' + cards[eval('' + donelist[eval(-1 + donelist.length)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'; // + ' ' + owidth + ' ' + oheight
} else {
defstyle=defstyle.replace(';background-image:', (',' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px' + ';background-image:');
defstyle=defstyle.replace('no-repeat','no-repeat,no-repeat');
defstyle=defstyle.replace('background-size:' + owidth + 'px ' + oheight + 'px','background-size:' + owidth + 'px ' + oheight + 'px,' + owidth + 'px ' + oheight + 'px');
defstyle=defstyle.replace('; } </style>', ',url(' + cards[eval('' + donelist[eval(0 + ijk)])] + ') ' + (' ' + ('' + opltlistl[eval(-1 + opltlistl.length)]).split('.')[0] + 'px ' + ('' + opltlistt[eval(-1 + opltlistt.length)]).split('.')[0] + '' + 'px').substring(0,1) + '; } </style>'); // + ' ' + owidth + ' ' + oheight
}
return null;
}
return window.open(one, two, three);
}

… a one window solution that saves the day for mobile and we see as a good candidate for “default-ness” for non-mobile … we’ll let that one sink in for a day or so?!

We needed to add event logic we were not sure would work at the start of the day, and saw it working by the end, with …


var iourx=-1, ioury=-1;

function blater() {
if (1 == 2 && navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
window.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
eles = document.querySelectorAll("*")
for (var ele of eles) {
console.log('yes well');
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
ele.addEventListener('touchstart', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('touchmove', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
ele.addEventListener('click', function(evt) {
evt.preventDefault();
var touches = evt.changedTouches;
//if (evt.touches) {
if (touches[0].pageX) {
iourx = touches[0].pageX;
ioury = touches[0].pageY;
} else if (touches[0].clientX) {
iourx = touches[0].clientX;
ioury = touches[0].clientY;
}
//alert('x:' + iourx);
//}
clickedmaybe();
}, false);
} else {
ele.addEventListener('click', function(evt) {
if (evt.touches) {
if (evt.touches[0].pageX) {
iourx = evt.touches[0].pageX;
ioury = evt.touches[0].pageY;
} else {
iourx = evt.touches[0].clientX;
ioury = evt.touches[0].clientY;
}
//alert('' + iourx);
} else if (evt.clientX) {
iourx = evt.clientX; // - elemLeft;
ioury = evt.clientY; // - elemLeft;
} else if (!evt.touches) {
iourx = evt.pageX; // - elemLeft;
ioury = evt.pageX; // - elemLeft;
}
clickedmaybe();
//alert('here');
});
}
}
}
}

See this in the changed cards_usefocus.html code behind the “Just Javascript” live run with single window (good for mobile) or default live run (for your platform) we, again, welcome you to try for yourself.


Previous relevant Just Javascript Card Order Game Tutorial is shown below.

Just Javascript Card Order Game Tutorial

Just Javascript Card Order Game Tutorial

Today we’ve made the web application of yesterday’s Just Javascript Quiz Drag Tutorial “dual purpose” …

  • quiz … as for yesterday, and before … and as of today, making more use of the card organizational side to the popup windows we introduce …
  • card order game

This card order game asks you to force the focus of the correct popup window (to score in the Card Order Game) in the order as designated by the background image part we have added today, and supported by the following Javascript “mapping” code …


var dragorder=[], curdrag=0;

var cards=["//www.rjmprogramming.com.au/images/01s.gif?n=7",
"//www.rjmprogramming.com.au/images/02s.gif?n=16",
"//www.rjmprogramming.com.au/images/03s.gif?n=33",
"//www.rjmprogramming.com.au/images/04s.gif?n=29",
"//www.rjmprogramming.com.au/images/05s.gif?n=8",
"//www.rjmprogramming.com.au/images/06s.gif?n=35",
"//www.rjmprogramming.com.au/images/07s.gif?n=52",
"//www.rjmprogramming.com.au/images/08s.gif?n=51",
"//www.rjmprogramming.com.au/images/09s.gif?n=12",
"//www.rjmprogramming.com.au/images/10s.gif?n=30",
"//www.rjmprogramming.com.au/images/11s.gif?n=1",
"//www.rjmprogramming.com.au/images/12s.gif?n=36",
"//www.rjmprogramming.com.au/images/13s.gif?n=22",
"//www.rjmprogramming.com.au/images/01h.gif?n=32",
"//www.rjmprogramming.com.au/images/02h.gif?n=23",
"//www.rjmprogramming.com.au/images/03h.gif?n=3",
"//www.rjmprogramming.com.au/images/04h.gif?n=18",
"//www.rjmprogramming.com.au/images/05h.gif?n=28",
"//www.rjmprogramming.com.au/images/06h.gif?n=39",
"//www.rjmprogramming.com.au/images/07h.gif?n=45",
"//www.rjmprogramming.com.au/images/08h.gif?n=48",
"//www.rjmprogramming.com.au/images/09h.gif?n=50",
"//www.rjmprogramming.com.au/images/10h.gif?n=44",
"//www.rjmprogramming.com.au/images/11h.gif?n=4",
"//www.rjmprogramming.com.au/images/12h.gif?n=9",
"//www.rjmprogramming.com.au/images/13h.gif?n=5",
"//www.rjmprogramming.com.au/images/01d.gif?n=27",
"//www.rjmprogramming.com.au/images/02d.gif?n=41",
"//www.rjmprogramming.com.au/images/03d.gif?n=20",
"//www.rjmprogramming.com.au/images/04d.gif?n=11",
"//www.rjmprogramming.com.au/images/05d.gif?n=37",
"//www.rjmprogramming.com.au/images/06d.gif?n=49",
"//www.rjmprogramming.com.au/images/07d.gif?n=42",
"//www.rjmprogramming.com.au/images/08d.gif?n=6",
"//www.rjmprogramming.com.au/images/09d.gif?n=21",
"//www.rjmprogramming.com.au/images/10d.gif?n=31",
"//www.rjmprogramming.com.au/images/11d.gif?n=40",
"//www.rjmprogramming.com.au/images/12d.gif?n=43",
"//www.rjmprogramming.com.au/images/13d.gif?n=17",
"//www.rjmprogramming.com.au/images/01c.gif?n=46",
"//www.rjmprogramming.com.au/images/02c.gif?n=19",
"//www.rjmprogramming.com.au/images/03c.gif?n=47",
"//www.rjmprogramming.com.au/images/04c.gif?n=25",
"//www.rjmprogramming.com.au/images/05c.gif?n=10",
"//www.rjmprogramming.com.au/images/06c.gif?n=15",
"//www.rjmprogramming.com.au/images/07c.gif?n=13",
"//www.rjmprogramming.com.au/images/08c.gif?n=26",
"//www.rjmprogramming.com.au/images/09c.gif?n=38",
"//www.rjmprogramming.com.au/images/10c.gif?n=34",
"//www.rjmprogramming.com.au/images/11c.gif?n=2",
"//www.rjmprogramming.com.au/images/12c.gif?n=14",
"//www.rjmprogramming.com.au/images/13c.gif?n=24"];


for (var ic=1; ic<=cards.length; ic++) {
found=false;
for (var jc=1; jc<=cards.length; jc++) {
if ((cards[eval(-1 + jc)] + '~').indexOf('?n=' + ic + '~') != -1) {
dragorder.push(eval(-1 + jc));
cards[eval(-1 + jc)]=cards[eval(-1 + jc)].replace('?n=' + ic, '');
firstbit+=String.fromCodePoint(eval('' + spcps[eval(-1 + jc)].split('/')[0])) + ' ';
found=true;
}
}
}

… and “making use of” this and the new codeline as popups are created … oplist[eval(-1 + oplist.length)].document.name=” + kl; we have …


function ourprompt(tw, blb, bdef) {
var kijk;
if (oplist[eval('' + tw)].document.name == ('' + dragorder[eval('' + curdrag)]) && eval('' + curdrag) == eval('' + overallgoes)) {
console.log('Dragorder[' + curdrag + ']=' + dragorder[eval('' + curdrag)] + ' vs tw=' + tw + ' and overall;goes=' + overallgoes);
var decs=document.title.split('.');
curdrag++;
overallgoes++;
if (eval('' + decs.length) >= 3) {
document.title=document.title.replace('.' + decs[1] + '.', '.' + curdrag + '/' + overallgoes + '.');
}
oplist[eval('' + tw)].close();
return null;
}

// Quiz only code follows
}

… code.

It must be in the correct order (and not interrupted by quiz answer completions) to score, and you are timed, so you can try improving over time, using a document.title score presentation as per …


[QuizScore].[CardOrderGameScore]/[QuizAnswerAttemptCount].[SecondsElapsed] [MultiPlayerQuizScoreGoesBreakdown] is User: Score/Goes - RJM Programming - April, 2021

… so that both usages for the web application can be accommodated for in the changed cards_usefocus.html code behind the “Just Javascript” live run we welcome you to try for yourself.


Previous relevant Just Javascript Quiz Drag Tutorial is shown below.

Just Javascript Quiz Drag Tutorial

Just Javascript Quiz Drag Tutorial

Adding to yesterday’s Just Javascript Quiz CSS Styling Tutorial we have added some …

  • non-mobile platform, only …
  • drag and drop functionality … for …
  • the child popup windows

… achieved through the comparison of …

  • original [popupWindow].screenLeft and [popupWindow].screenTop … initially, to …
  • [popupWindow].screenLeft and [popupWindow].screenTop over time

… and if one popup is dragged to overlay another it is closed, or you, as the user, can just drag and drop for clarity, leaving the popup window of the next quiz question out in the open, perhaps.

In order to achieve this, and keep backward compatibility we needed to delay the quiz question prompt window via …

  1. document.hasFocus() is true … then if …
  2. inhouse dragging checks clear it of overlaying another popup (in which case that popup is programmatically closed, allowing another popup to become the “focus window”) … then …
  3. delay (by 8 seconds) the prompt window (and in that time the user can be dragging popups (but no popups were harmed in the making of this tutorial)) … via …

    setTimeout(function() { hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } else { hj=window.opener.assess(hj); } if (hj.replace(def,'') != '') { checka(hj); } else { setTimeout(pa,10000); } aminmiddle=false; }, 8000);

… you can see in amongst the changed cards_usefocus.html code behind the “Just Javascript” live run you are welcome to try for yourself … best on non-mobile.

Still “No Body Definition”, “Just Javascript”!


Previous relevant Just Javascript Quiz CSS Styling Tutorial is shown below.

Just Javascript Quiz CSS Styling Tutorial

Just Javascript Quiz CSS Styling Tutorial

Our “Just Javascript” adage used throughout this blog posting thread, up until today, headed by yesterday’s Just Javascript Quiz Content Management Tutorial needs more explanation. Really what we are trying to do might better be described as “No Body Definition” (ie. no defined document.body) but have …

  1. an HTML webpage (ie. within <html> and </html>) … has …
  2. <head> and </head> (ie. document.head) content which can be made up of (at least) title, style, script, link, meta tags

To assert “Just Javascript” is just to allow script content above, but what we should really say is “Just Head Content” but that is not nearly so marketable, is it now?!

The thing is, though, we can dynamically add title, style, link, meta tag content within the script content, and we do this more than statically define it, to feel better about our ethics saying “Just Javascript”.

Dynamically adding style CSS styling either …

  • using Javascript DOM (not available to us for document.getElementById([elementID] and nor can we use inline CSS via style=”[CSSstyling]” statically within HTML element code for that same reason) ideas today though … remember “No Body Definition” … but …
  • we can append to <head> and </head> (for today’s scenario) as per …

    document.head.innerHTML+="<style> html { background-color: yellow; font-size: 36px; background: URL('//www.rjmprogramming.com.au/rjmquiz.jpg'); background-size: cover; } </style>";

… allowing (into the scope of our work CSS styling of) background (image(s)) and other background styling ideas that can get us past the anonymous feel the web application had before today. We tailored the background image above to suit our Quiz and help it be a bit more self explanatory … thanks CSS styling! We add onto the child “card” popup windows, their own background image colour and pizazz, to cheer things up in CSS styling enhanced cards_usefocus.html code behind the “Just Javascript” live run.

You may well ask …

What can we hang our hat on with CSS style selectors without a body element?

Well, we had to step out of our usual comfort zone of CSS styling thinking, and realize, even without that body element we can still use the html selector to “point at” the entirety of your webpage of interest.


Previous relevant Just Javascript Quiz Content Management Tutorial is shown below.

Just Javascript Quiz Content Management Tutorial

Just Javascript Quiz Content Management Tutorial

It feels like an “onions of the 4th dimension” idea to allow the user to control the questions and answers behind the workings of yesterday’s Just Javascript Quiz Multiple Users Tutorial‘s web application, featuring “Just Javascript”.

It’s not “Just Javascript” we’re keeping, it’s “Just HTML” client work rather than involving any serverside anything (eg.PHP) and yet this question and answer data could be quite sizeable. What can we use, given no PHP serverside, and given we’ve decided not to navigate via Ajax/FormData techniques? How about “the better than HTTP Cookies” twins …

Yep, set up a means by which these two can store and restore questions and answers entered by the user, using these storage methods above.


function reassess() {
var retv='', ewq;
var retcols=[];
var ir=0;
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '') {
//alert('0:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?!')[0] + '?');
asq.push(retcols[ir].split('?!')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '') {
//alert('1:' + retv);
retcols=decodeURIComponent(retv).split('~');
sq=[];
asq=[];
for (ir=0; ir<retcols.length; ir++) {
sq.push(retcols[ir].split('?')[0] + '?');
asq.push(retcols[ir].split('?')[1]);
nomap=false;
given='';
}
return;
}
} catch(ewq) {
}
}
}


function assess(what) {
var ewq, retv='';
if (what.toLowerCase() == '?x') {
sslistq=[];
sslista=[];
if (window.sessionStorage) {
try {
window.sessionStorage.removeItem('cards_usefocus_session');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase() == '?!x') {
lslistq=[];
lslista=[];
if (window.localStorage) {
try {
window.localStorage.removeItem('cards_usefocus_local');
} catch(ewq) {
}
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
return '';
} else if (what.toLowerCase().indexOf('?!') != -1) {
if (what.toLowerCase() == '?!') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.localStorage) {
if (lslistq.length == 0) {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', encodeURIComponent(what));
} else {
lslistq.push(what.split('?!')[0]);
lslista.push(what.split('?!')[1]);
window.localStorage.setItem('cards_usefocus_local', window.localStorage.getItem('cards_usefocus_local') + encodeURIComponent('~' + what));
}
}
return '';
} else if (what.toLowerCase().indexOf('?') != -1) {
if (what.toLowerCase() == '?') {
location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897);
return '';
}
if (window.sessionStorage) {
if (sslistq.length == 0) {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', encodeURIComponent(what));
} else {
sslistq.push(what.split('?')[0]);
sslista.push(what.split('?')[1]);
window.sessionStorage.setItem('cards_usefocus_session', window.sessionStorage.getItem('cards_usefocus_session') + encodeURIComponent('~' + what));
}
}
return '';
} else {
firstbit='';
if (window.localStorage) {
try {
retv=('' + window.localStorage.getItem('cards_usefocus_local')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
if (window.sessionStorage) {
try {
retv=('' + window.sessionStorage.getItem('cards_usefocus_session')).replace(/^null$/g,'');
if (retv != '' && nomap) { location.href=document.URL.split('#')[0].split('?')[0] + '?rand=' + Math.floor(Math.random() * 198765897); }
} catch(ewq) {
}
}
}
return what;
}

The fairly significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz Multiple Users Tutorial is shown below.

Just Javascript Quiz Multiple Users Tutorial

Just Javascript Quiz Multiple Users Tutorial

Adding to yesterday’s Just Javascript Quiz via Cards Tutorial we were surprised how difficult it was to stay with “Just Javascript” and allow for multiple player play.

We didn’t opt for the parent to ask about the number of players, curiously, but on the second quiz answer and on, offered any non first player the chance to identify themselves as a new player into the game by appending their answer with a space character.

The implication of that is that we’ll want to run Javascript functions of the parent from the children as per


oplist[eval(-1 + oplist.length)].document.write("<link rel=icon href=" + cards[kl] + "><scr" + "ipt type='text/javascript'> var da='" + eval(0 + kq) + "'; var dp='Given answer is integer from 0 to 25 ... " + sq[kq] + "'; var def=String.fromCodePoint(" + spcps[eval('' + kl)].split('/')[0] + "); function checka(tpa) { var os=''; var ps=eval(window.opener.document.title.split('/')[0].trim()); var pg=eval(window.opener.document.title.split('/')[1].split(' ')[0]); if (tpa.trim() == da) { ps++; os=tpa.split(da)[1]; } else { pg++; os=tpa.split(tpa.trim())[1]; } window.opener.document.title=ps + os + '/' + pg + ' is User Score/Goes'; window.close(); } function pa() { if (document.hasFocus()) { var hj=prompt(dp + window.opener.blurb(), def); if (hj == null) { hj=''; } if (hj.replace(def,'') == '') { setTimeout(pa,1000); } else { checka(hj); } } else { setTimeout(pa,1000); } } pa(); </scr" + "ipt>");

… accessing …


function blurb() { // theblurb and wblurb are global variables changed elsewhere
if (wblurb == ' Hello Player 1' && theblurb == ' If you are player 2 rather than player 1 append space to your answer.') {
theblurb='';
wblurb='';
}
return theblurb + wblurb;
}

… giving the rather curious behaviour whereby a Javascript prompt window can be dynamically different from one document.hasFocus() incarnation (ie. the user might go away and answer another “card” Number Quiz question) to another (even not attending to answering the Javascript prompt window) … huh?!

The significantly changed cards_usefocus.html code behind the “Just Javascript” live run is worth a look, we figure, for up to 52 players who play in turn.


Previous relevant Just Javascript Quiz via Cards Tutorial is shown below.

Just Javascript Quiz via Cards Tutorial

Just Javascript Quiz via Cards Tutorial

Yesterday’s Just Javascript Navigation Tutorial continues our interest in “Just Javascript” (or “No Body”) web applications.

We think today’s “Numbers Quiz” via a “Card Deck” organizational design ups the ante on all this. We realize now what we have been missing not having involved document.hasFocus() in any of our popup window scenarios. Today, at least on non-mobile, we involve 52 such popup windows each containing a “Number Quiz” question presented as a Javascript prompt (sub-)window. This would not be feasible without document.hasFocus() as you can tell if you examine the cards_usefocus.html code behind the “Just Javascript” live run best used on your non-mobile platforms where popup windows can sit in front of parent (and beside sibling) windows, whereas mobile platforms open new web browser tabs for all the 52 windows of (a card deck) design.

Look out, too, in the code above, for use of window.opener back reference from a popup window back to the parent window where the scoring data is held, and updated by each popup window because of that window.opener avaalability.


Previous relevant Just Javascript Navigation Tutorial is shown below.

Just Javascript Navigation Tutorial

Just Javascript Navigation Tutorial

The recent use we made of …


document.createElement/click()

… got us thinking of the “Just Javascript” (or No Body) blog posting thread headed by Just Javascript Webmail No Body Attachment Tutorial.

As such, today we present the very simple (but first time use of the interesting hasFocus) “proof of concept” …


<html>
<head>
<script type='text/javascript'>
function dothis() {
var ais=null;
var urlis=' ';
while (urlis != '') {
if (document.hasFocus()) {
urlis=prompt('Enter URL that we will send you to (exit to stop)', '');
} else {
setTimeout(dothis, 2000); // urlis=' ';
return;
}
if (urlis == null) { urlis=''; }
if (urlis.toLowerCase() == 'exit') { return; }


if (urlis.trim() != '') {
if (urlis.substring(0,1) == '.') { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
} else if (urlis.substring(0,1) == '/' && urlis.indexOf('//') == -1) { // relative URL
urlis=document.URL.split('//')[0] + '//' + document.URL.split('//')[1].split('/')[0] + '/' + urlis;
} else if (urlis.split('/')[0].indexOf('.') != -1) { // absolute URL
if (urlis.toLowerCase().indexOf('http') != 0) {
if (urlis.indexOf('//') == 0) {
urlis=document.URL.split('//')[0] + urlis;
} else {
urlis=document.URL.split('//')[0] + '//' + urlis;
}
}
} else { // relative URL
urlis=document.URL.split('nobody.htm')[0] + urlis;
}
ais=document.createElement('a');
ais.onclick=function() { window.open(urlis, '_blank', 'top=100,left=100,width=600,height=600'); };
if (1 == 2) { ais.href=urlis; }
ais.target='_blank';
ais.click();
}
}
setTimeout(dothis, 2000); // urlis=' ';
}


dothis();

</script>
</head>
</html>

nobody.html‘s live run link for you to use a Javascript prompt popup window’s user interaction results to navigate to a new webpage, as applicable. Bookmarklets may be scarce on the ground, but these “Just Javascript” ideas continue the Bookmarklet Spirit of the past!


Previous relevant Just Javascript Webmail No Body Attachment Tutorial is shown below.

Just Javascript Webmail No Body Attachment Tutorial

Just Javascript Webmail No Body Attachment Tutorial

A “hard liner” for the proper use of “business emails” could argue that an email without an attachment is not productive. Couldn’t you just have a face to face meeting instead, if there is just wording in the email (as we somewhat concur with, as an argument)? So yesterday’s Just Javascript Webmail No Body Tutorial had that limitation of no email attachment logic, which we remedy today.

And this is where PHP’s wonderful file_get_contents (function) means by which we garner (URL) content …

  • definitely works with “relative URLs” relative to HTTP://www.rjmprogramming.com.au/HTMLCSS/ where today’s unchanged webmail_nobody.html resides … in “parsing parlance” …

    "relative (URL)" to the left of any # or ? of what lies to the left of the most right hand "/" (of what the address bar URL is of the webpage you are on)

    … so that …

    1. “relative URLs” starting with “./” (followed by the filename, or just the filename (as you can see us using in today’s tutorial picture)) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/HTMLCSS/” … whereas, for example …
    2. “relative URLs” starting with “../” (followed by the filename) refer to the web server directory corresponding to “HTTP://www.rjmprogramming.com.au/” … for example

    … and …

  • might work for “absolute URLs” (those that start with https: or HTTP: or even // (that we beg you not to confuse with Windows UNC pathnames) that infer a transport protocol of the transport protocol (out of https: or HTTP: or even file:) that got you to the webpage you are currently on), the “might” being far more likely on “absolute URLs” pointing to the same domain as indicated on the URL of the address bar of the webpage you are currently on

Upshot is, the user in their email Body section definitions (still no HTML body though!), can throw into any word they use, an “absolute URL” of interest, or a “relative URL” of interest, of files they want to attach (as attachments, doh!) in their email.

Depending on the email rules though, there are limits as to the amount of attachment data allowed. We’ll leave that to you intrepid “explorers of the Net” to discover for yourselves. On this subject though, have you noticed that with the Photos (or Gallery) app Share options, the Email option drops off when you have highlighted a large number of photos or videos or audios to share? That’s that email limit coming into play.

So feel free to try this HTML-body-less web application live run to see what we mean here. Though the parent HTML is unchanged today, the new (email) attachment functionality needed a changed PHP emailhtml.php to make this happen.

Did you know?

This (relative URL) “../” navigation backwards up the hierarchy of the web server directories will, if repeated (ie. nested to “../../” etcetera) too many times, get you into uncharted unnavigable (web server directory) places relative to that web server web site’s Document Root (below which you can not access in public webpages, normally). But when you perform similar thinking with “absolute URLs” and go “HTTP://www.rjmprogramming.com.au/HTMLCSS/../../../blahdeblah.jpg” (in a web browser address bar) for instance, you cannot get into trouble, as you just don’t get beyond this sending you to (attempt the reference to) “HTTP://www.rjmprogramming.com.au/blahdeblah.jpg” because on this rjmprogramming.com.au Apache domain the correspondence of the Document Root (web server directory) is to “HTTP://www.rjmprogramming.com.au/” as the place you are not allowed (and cannot) go below in the hierarchy tree.


Previous relevant Just Javascript Webmail No Body Tutorial is shown below.

Just Javascript Webmail No Body Tutorial

Just Javascript Webmail No Body Tutorial

Were you around and interested in our series of about three blog postings in the series on the theme of creating webpage functionality of some interest, involving no Javascript, when we presented Missing Javascript Audio on Unmute Tutorial? Well, today, it’s the turn of “just Javascript”, which is sort of like what Bookmarklets were about.

With today’s “just Javascript” we have to qualify that a little for our webmail emailing sender application with the architecture …

  • parent webpage with only document.head and apart from a document.title just a script Javascript tag of content (using Javascript prompt windows to ask for user information) …
  • sending (POSTing) data via …
    1. Ajax XMLHttpRequest object … as the conduit for …
    2. FormData object

    … to our changed

  • PHP communication emailing tool emailhtml.php … and out to …
  • the emailee (out there in the big wide woooorrrrrllllldddd)

Guess we find it interesting that you can do all this (sending of email to emailee recipients) with no document.body in sight.

So take a look at that parent webmail_nobody.html‘s live run link to see what we mean here, and/or watch the video below …


Previous relevant Missing Javascript Audio on Unmute Tutorial is shown below.

Missing Javascript Audio on Unmute Tutorial

Missing Javascript Audio on Unmute Tutorial

Our “third cab off the rank” following on from yesterday’s Missing Javascript Stop Watch Tutorial “missing Javascript” ideas is an HTML div nesting scenario using just …

  1. HTML
  2. CSS

… again, with some or all of the “usuals” below …

  • calc method to assist with defining width and height and size dimensions along with operator “+” and/or “-” offset calculation opportunities, and which we’d have used the Javascript window.getComputedStyle and/or [element].getBoundingClientRect methods to cover this (in a much more unwieldy way, as you would probably surmise)
  • CSS variables we started talking about here at CSS Variables Primer Tutorial
  • CSS3 @keyframes rules we first talked about at CSS3 @keyframes Rule Primer Tutorial that assist with animations that we can make work via …
  • CSS3 transitions for scheduled functionality (we’d have used Javascript setTimeout (and setInterval) methods to cover the same “territory”) we first talked about at CSS3 Transition Primer Tutorial … specified with CSS Criteria involving …
  • CSS Selectors :after and :before (and often, as for today’s work, with the content: CSS property) first talked about here with WordPress Bullet Point CSS Styling Primer Tutorial … and, today …
  • CSS3 transform property’s rotate (and translate and scale) settings (for the puppy dog body movements) … as well as the idea that …
  • On non mobile platforms you can set up the playing of “audio” data via the use of an HTML audio tag with the properties …
    1. controls
    2. autostart
    3. loop
    4. muted

    Stop Press

    Above is all fine and good for non-mobile but not so good for mobile, so to keep all happy with the one click, still, is to transfer HTML coding from …


    <audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" />

    … to …


    <!--audio id='myaudio' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="display:none;margin-left:-350px;opacity:0.1;" autostart muted loop controls src="Puppy-sounds.mp3" /-->
    <audio id='myaudiotwo' title='Got a sock in my mouth, so you might want to unmute me!' type='audio/mp3' style="margin-left:-350px;opacity:0.1;" autostart="0" loop controls src="Puppy-sounds.mp3" />

    … and a src= URL data source (as we thank this link for today), or data URI if preferred (which we do for today’s image data from this link, thanks (when we were researching animated GIF data URIs (which we may return to at a later date))

… that sets up the scenario that all the user has to do to hear the audio is to click the “muted” control button, without needing the usual Javascript play() methods … but not on mobile!

Feel free to let the puppy play, that uses the HTML and CSS (but no Javascript) of the_nested.html and based largely on the previous HTML Nested Centering via Multiple Select Tutorial so that these changes reflect how we got to the first draft of today’s work. Maybe some of the ideas are of interest. We hope so!


Previous relevant Missing Javascript Stop Watch Tutorial is shown below.

Missing Javascript Stop Watch Tutorial

Missing Javascript Stop Watch Tutorial

Following on from yesterday’s Missing Javascript Primer Tutorial our second “cab off the rank” for “missing Javascript” ideas is a stop watch featuring just …

  1. HTML
  2. CSS

… again, setting up document.body load instigated

… which we needed to do to make multiple animations happen, but we used animation-delay:5s; to delay its start. The hands (second and minute, hence the two animations) are “overlay”

… feeling HTML horizontal rule elements that also feature linear gradients, to emphasise (in red) the “pointy end” of the “hand conversation” (good on walls with shadows … but we digress).

Feel free to let loose the stop watch that uses the HTML and CSS (but no Javascript) of stop_watch.html for today’s instructional information. Thanks to Clipart – stop watch for the great clip art used.


Previous relevant Missing Javascript Primer Tutorial is shown below.

Missing Javascript Primer Tutorial

Missing Javascript Primer Tutorial

If you were to ask me which programming component is most vital to web application development, I’d not be Robinson Crusoe in saying …

Without a doubt, Javascript

… and with that thought in mind we have a two pronged motive to see how far we go developing some web applications that “don’t use Javascript”, calling into play the …

  • meaning of “missing”, as in, our code is “missing” Javascript … as well as how I feel with the masochism of the exercise, calling into play the …
  • meaning of “missing”, as in, it’s hard work writing meaningful web applications without Javascript … but I guess we’ll learn a bit from the exercise of “see where we go”, allowing for the fact, not today, but down the track, that we will allow the use of server-side languages such as PHP

Okay, so, given that restriction, let’s see today’s challenge, to just use, in a web application …

  1. HTML
  2. CSS

… and here is where we have to point out that CSS3 introduced to us some functionality that improves the prospects for web application design “interest” without using Javascript (though it is hard to convince me even so, that I am not “missing” Javascript) here. CSS3 introduced to us …

… and we use all of these in our Festive Season themed web application today, you can try at this live run‘s calc_use.html (free of any Javascript (but “why” springs to mind … because it is NOT there, perhaps?)).

Here’s the other thing about today. Our long sought after “just make the body background be semi-transparent” but not its foreground parts, was solved, for us via the great advice of …

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


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


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


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


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


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


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


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


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


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


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


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

Just Javascript Card Order Game Mobile Tutorial