Multipurpose Buttons Emoji UTF-16 Tutorial

Multipurpose Buttons Emoji UTF-16 Tutorial

Multipurpose Buttons Emoji UTF-16 Tutorial

Yesterday’s Multipurpose Buttons Emoji Input Tutorial‘s HTML Entity emoji input Javascript code sometimes output …


&#[UTF-16-Decimal-In-Range-0xDC00-0xDFFF];&#[UTF-16-Decimal-Surrogate-Pair];

… and today’s work was to turn such arrangements into a single …


&#[HTML-Entity-Decimal];

… so our Javascript can form the emoji display via …


String.fromCodePoint([HTML-Entity-Decimal]);

to improve the code snippet …


/**
* Converts an html characterSet into its original character.
*
* @param {String} str htmlSet entities
**/
mapencode : function(str) {
var H=0, C=0, L=0;
if (mappingsin.indexOf('' + str) == -1) {
return '' + str;
}
//alert('str=' + str);
if (mappingseval[mappingsin.indexOf('' + str)].split(',').length == 4) { // Thanks to https://mathiasbynens.be/notes/javascript-encoding
H=eval(mappingseval[mappingsin.indexOf('' + str)].split(',')[0].split('(')[1]);
if (H >= 0xD800 && H <= 0xDBFF) {
L=eval(mappingseval[mappingsin.indexOf('' + str)].split(',')[1].split(',')[0]);
C=eval((H - 0xD800) * 0x400 + L - 0xDC00 + 0x10000);
H=eval(mappingseval[mappingsin.indexOf('' + str)].split(',')[2].split(',')[0]);
L=eval(mappingseval[mappingsin.indexOf('' + str)].split(',')[3].split(')')[0]);
mappingseval[mappingsin.indexOf('' + str)]='String.fromCodePoint(' + C + ',' + eval((H - 0xD800) * 0x400 + L - 0xDC00 + 0x10000) + ')';
mappingsout[mappingsin.indexOf('' + str)]=eval('String.fromCodePoint(' + C + ',' + eval((H - 0xD800) * 0x400 + L - 0xDC00 + 0x10000) + ')');
}
} else if (mappingseval[mappingsin.indexOf('' + str)].split(',').length == 2) { // Thanks to https://mathiasbynens.be/notes/javascript-encoding
H=eval(mappingseval[mappingsin.indexOf('' + str)].split(',')[0].split('(')[1]);
if (H >= 0xD800 && H <= 0xDBFF) {
//alert('sfcp=' + mappingseval[mappingsin.indexOf('' + str)] + ' ' + eval(mappingseval[mappingsin.indexOf('' + str)]));
L=eval(mappingseval[mappingsin.indexOf('' + str)].split(',')[1].split(')')[0]);
C=eval((H - 0xD800) * 0x400 + L - 0xDC00 + 0x10000);
//alert('ssfcp=' + C + ' ' + eval('String.fromCodePoint(' + C + ')'));
mappingseval[mappingsin.indexOf('' + str)]='String.fromCodePoint(' + C + ')';
mappingsout[mappingsin.indexOf('' + str)]=eval('String.fromCodePoint(' + C + ')');
} //else {
//alert('SFCP=' + mappingseval[mappingsin.indexOf('' + str)] + ' ' + eval(mappingseval[mappingsin.indexOf('' + str)]));
//}
} //else {
//alert('Sfcp=' + mappingseval[mappingsin.indexOf('' + str)] + ' ' + eval(mappingseval[mappingsin.indexOf('' + str)]));
//}

return '' + eval(mappingseval[mappingsin.indexOf('' + str)]);
},

Like yesterday, the changed external Javascript multipurpose_buttons.js greatly helps out the ninth draft multipurpose_buttons.html live run link.


Previous relevant Multipurpose Buttons Emoji Input Tutorial is shown below.

Multipurpose Buttons Emoji Input Tutorial

Multipurpose Buttons Emoji Input Tutorial

Progressing further into our “Multipurpose Buttons” project onto yesterday’s Multipurpose Buttons Ondblclick Event Tutorial

  • emojis are not only useful as menu type Multipurpose Buttons Emoji Links Tutorial links … but also as …
  • emoji text input for the button look, just as our ascii text can be placed on that button display

… the beauty here being that we graphically challenged can beautify our button aesthetics.

Why the big deal? Well, this change is not straightforward for our default logic of a one to one correspondence of character button display content to an “onclick” event logic because an emoji is worth more than one character. So we need a mapping system of one character for our emoji content to map to as the basis for establishing the onclick logics, then map back again to get the emoji button display we were after using an emoji entry mechanism such as macOS’s keyboard control=command-space one to enter these emojis into the user definable HTML textarea presented in the web application.

Here we delve into the wooooorrrrrllllldddd of HTML Entities (and UTF-8 character set) not just with respect to emojis but also as a solution to that navigational “+” character issue we referred to with Multipurpose Buttons Email Attachment Download Tutorial.

Below are new Javascript snippets of relevance here for this ongoing set of changes (part 1 today)


var mappingsi=1;
var mappingsin=[];
var mappingseval=[];
var mappingsout=[];
var lastmatch='';
var lastprecedes='';
var cpa=[0];
var cps='';
var evalcps='';
var dcnumx='';
var prevint=false;
var dotsub=0;

if (!String.fromCodePoint) { // thanks to //xahlee.info/js/js_unicode_code_point.html
// ES6 Unicode Shims 0.1 , Β© 2012 Steven Levithan , MIT License
String.fromCodePoint = function fromCodePoint () {
var chars = [], point, offset, units, i;
for (i = 0; i &lt; arguments.length; ++i) {
point = arguments[i];
offset = point - 0x10000;
units = point &gt; 0xFFFF ? [0xD800 + (offset &gt;&gt; 10), 0xDC00 + (offset & 0x3FF)] : [point];
chars.push(String.fromCharCode.apply(null, units));
}
return chars.join("");
}
}

// Thanks to https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript
(function(window){
window.htmlentities = {
/**
* Converts a string to its html characters completely.
*
* @param {String} str String with unescaped HTML characters
**/
encode : function(str) {
var buf = [];


for (var i=str.length-1;i&gt;=0;i--) {
buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
}


return buf.join('');
},
/**
* Converts an html characterSet into its original character.
*
* @param {String} str htmlSet entities
**/
mapencode : function(str) {
if (mappingsin.indexOf('' + str) == -1) {
return '' + str;
}
//alert('str=' + str);
return '' + eval(mappingseval[mappingsin.indexOf('' + str)]);
},
/**
* Converts an html characterSet into its original character.
*
* @param {String} str htmlSet entities
**/
mapdecode : function(str) {
return str.replace(/&#(\d+);/g, function(match, dec) {
var restis=[], irestis=0, cps='', evalcps='', xcps=String.fromCodePoint(cpa[0]);
var idec=eval('' + match.replace('&#','').replace(';',''));
evalcps='';
//cps='';
for (var ii=1; ii&lt;cpa.length; ii++) {
xcps+=String.fromCodePoint(cpa[ii]);
}
if (eval('' + idec) &gt;= 32 && eval('' + idec) &lt; 128) {
cpa=[0];
//if (prevint) { alert('interesting after match=' + match); }
prevint=false;
return String.fromCharCode(idec);
} else if (cpa.indexOf('' + eval('' + match.replace('&#','').replace(';',''))) != -1) {
prevint=false;
return '';
} else if (lastprecedes.indexOf(match) != -1) {
cpa=[0];
lastprecedes='';
prevint=false;
return '';
} else if (match == lastmatch && match.indexOf('&#') != -1) {
cpa=[0];
prevint=false;
return '';
} else if (mappingsout.indexOf(xcps) == -1 && match.length &gt; 6) {
if (cpa[0] == 0) {
cpa=[];
cps=String.fromCodePoint(eval('' + match.replace('&#','').replace(';','')));
evalcps='String.fromCodePoint(' + eval('' + match.replace('&#','').replace(';','')) + ')';
cpa.push('' + eval('' + match.replace('&#','').replace(';','')));
if (cnumx.substring(dotsub).indexOf(match + '&#') != -1) {
dotsub+=cnumx.substring(dotsub).indexOf(match + '&#');
restis=('&#' + cnumx.split(match + '&#')[1]).split(';');
if ((match + ' precedes ' + restis[0] + ';') == lastprecedes) {
prevint=false;
return '';
} else {
lastprecedes=(match + ' precedes ' + restis[0] + ';');
//alert(match + ' precedes ' + restis[0]);
while ((restis[irestis] + ' ').replace('&#','').substring(0,1) &gt;= '0' && (restis[irestis] + ' ').replace('&#','').substring(0,1) &lt;= '9' && restis[irestis].length &gt; 6) {
//alert(restis[irestis]);
if (irestis == 0 || evalcps.indexOf('' + eval('' + match.replace('&#','').replace(';',''))) == -1) {
cps+=String.fromCodePoint(eval('' + restis[irestis].replace('&#','').replace(';','')));
evalcps=evalcps.replace(')', ',' + eval('' + restis[irestis].replace('&#','').replace(';','')) + ')');
cpa.push('' + eval('' + restis[irestis].replace('&#','').replace(';','')));
} else {
//alert('huh');
prevint=false;
return '';
}
irestis++;
}
}
}
} else {
cps=String.fromCodePoint(eval('' + match.replace('&#','').replace(';','')));
evalcps='String.fromCodePoint(' + eval('' + match.replace('&#','').replace(';','')) + ')';
cpa.push('' + eval('' + match.replace('&#','').replace(';','')));
//alert('why');
prevint=false;
return '';
}
if (mappingsout.indexOf(eval(evalcps)) != -1) {
return mappingsin[mappingsout.indexOf(eval(evalcps))]; //String.fromCharCode(dec);
} else {
//mappingsout.push(cps);
//alert('evalcps=' + evalcps);
mappingsout.push(eval(evalcps));
mappingseval.push(evalcps);
mappingsin.push(String.fromCharCode(mappingsi));
mappingsi++;
//alert(evalcps + ' ' + match + ' ... ' + eval(evalcps) + ' ... ' + cnumx);
}
} else {
if (match.indexOf('&#') != -1) { lastmatch=match; }
prevint=true;
return mappingsin[mappingsout.indexOf(eval(evalcps))]; //String.fromCharCode(dec);
}
//if (match.indexOf('&#') != -1) { lastmatch=match; }
prevint=true;
return mappingsin[eval(-1 + mappingsi)]; //String.fromCharCode(dec);
});
},
/**
* Converts an html characterSet into its original character.
*
* @param {String} str htmlSet entities
**/
decode : function(str) {
return str.replace(/&#(\d+);/g, function(match, dec) {
return String.fromCharCode(dec);
});
}
};
})(window);

/**
* Create string from HTML entities
*/
String.fromHtmlEntities = function(strng) {
return (strng+"").replace(/&#\d+;/gm,function(s) {
return String.fromCharCode(s.match(/\d+/gm)[0]);
})
};

As you might imagine the changed external Javascript multipurpose_buttons.js greatly helped out the eighth draft multipurpose_buttons.html live run link.


Previous relevant Multipurpose Buttons Ondblclick Event Tutorial is shown below.

Multipurpose Buttons Ondblclick Event Tutorial

Multipurpose Buttons Ondblclick Event Tutorial

Yesterday’s Multipurpose Buttons Email Attachment Download Tutorial built on Multipurpose Buttons Onclick Event Logic Tutorial before it, but today’s job is to shore up some of the weaknesses for mobile platforms of attempting to use the mobile (touch) “ontouchend” event as a replacement for the non-existant “ondblclick” event (for mobile platforms).

That assumption was causing all clicks on mobile to ask for event logics off the user. To fix this, we needed to have a look at our previously published Details Summary Button Delayed Onclick Tutorial and do both …

  • nullify our “ontouchend” and “ondblclick” logics … but map their previous logics onto a …
  • reworked “onclick” logic works as an invisible “ondblclick” logic set for mobile or non-mobile … whereby …
  • the delayed timer approach gives us a chance to count individual “on the same element” counts that if greater than one represent the chance to call on the previous “ondblclick” logic

… as per …

Now
<span class=bxandy data-ontouchend=defineclick(this); data-ondblclick=defineclick(this); onclick=’makeGvalDelayedHandler(this.innerHTML,2000);’>2</span>
Used to be
<span class=bxandy ontouchend=defineclick(this); ondblclick=defineclick(this); onclick=’gval=this.innerHTML;’>2</span>
Now
var eventtargets=[];
var gevent=null;

function makeDelayedHandler(f, time){ // Delay execution of event handler function “f” by “time” ms, thanks to https://stackoverflow.com/questions/3048005/document-onclick-settimeout-function-javascript-help
setTimeout(iclicked, time);
return true;
}

function makeGvalDelayedHandler(fih, time){ // Delay execution of event handler function “f” by “time” ms, thanks to https://stackoverflow.com/questions/3048005/document-onclick-settimeout-function-javascript-help
gval=fih;
if (event) {
gevent=event;
//console.log(event.target.className);
if ((” + event.target.className) != ”) {
eventtargets.push(document.getElementById(event.target.className));
}
} else if (window.event) {
gevent=window.event;
//console.log(window.event.target.className);
if ((” + event.target.className) != ”) {
eventtargets.push(document.getElementById(window.event.target.className));
}
}
return false;
}


function iclicked(event) {
var isok=true, styleis='<style> ‘ + document.head.innerHTML.split(‘</style>’)[0].split(‘<style>’)[1] + document.getElementById(‘divstyle’).innerHTML.replace(/\<style\>/g,”).replace(/\<\/style\>/g,”) + ‘ </style>';
rectis=null;
if (eventtargets.length > 0) {
if (!event) { event=gevent; }
event.target=eventtargets[eval(-1 + eventtargets.length)];
eventtargets.shift();
if (eventtargets.length > 0) {
defineclick(event.target);
return true;
}
}

// Rest of iclicked follows …
// End of iclicked
}
Used to be
function iclicked(event) {
var isok=true, styleis='<style> ‘ + document.head.innerHTML.split(‘</style>’)[0].split(‘<style>’)[1] + document.getElementById(‘divstyle’).innerHTML.replace(/\<style\>/g,”).replace(/\<\/style\>/g,”) + ‘ </style>';
rectis=null;
// Rest of iclicked follows …
// End of iclicked
}

… expressed in the seventh draft multipurpose_buttons.html live run link helped out by the changed external Javascript multipurpose_buttons.js.


Previous relevant Multipurpose Buttons Email Attachment Download Tutorial is shown below.

Multipurpose Buttons Email Attachment Download Tutorial

Multipurpose Buttons Email Attachment Download Tutorial

Most of the time developing webpages for a public URL on the World Wide Web we’d suggest and encourage Relative URLs rather than Absolute URLs for …

  • brevity
  • avoids mixed content issues

… but there are some occasions where it is the other way around. Think …

  • web browser File -> Open File… (some HTML file) type of functionality … and what amounts to a similar thing is …
  • email attachment of HTML downloaded and opened

Why are these two in any way similar? They both end up at a web browser address bar using a URL with the file: protocol (ie. not http: nor https: nor sftp: nor ftp: protocols). In this environment, if you want a more seamless progression with this attached email HTML content downloaded and opened into a file: protocol web browser URL arrangement to still support links and form navigations, you are going to suddenly hanker for Absolute URLs in the HTML and Javascript and CSS code, believe me! That is because a Relative URL will suddenly be based on some awkward client device download folder (we’re guessing), rather than a public URL place pointing to a http: or https: protocol place on a public web server, the arrangement most of us deal with a great deal of the time surfing the net.

We create these email attachments using Ajax/FormData techniques? What is the biggest issue sending whole webpage content to an attached HTML content attachment and relying on the Javascript to work within that HTML? We think the “+” character encoding is the most annoying thing. We can handle it within a data URL but within Javascript? Wow!!! How annoying is the way the “+” will map to a space ” ” and wreck the Javascript logic. We rearranged the Javascript to sit in a new external Javascript http: or https: protocol place called multipurpose_buttons.js to get around a lot of this as of today. We also where we might have had a …


Relative URL such as ./multipurpose_buttons.html

… now say, in the static Javascript external Javascript …


Absolute (but no defined protocol) URL such as //www.rjmprogramming.com.au/HTMLCSS/multipurpose_buttons.html

… which maintains Mixed Content friendly code, while in the public parts of the net, which is amended just before the Ajax/FormData sends off the email HTML content attachment to be sent as …


Absolute URL such as HTTP://www.rjmprogramming.com.au/HTMLCSS/multipurpose_buttons.html

… so that the file: protocol execution of the HTML is not confused nor causing problems.

And so, improving on yesterday’s Multipurpose Buttons Onclick Event Logic Tutorial‘s email communication abilities, please see this with the sixth draft multipurpose_buttons.html live run link.


Previous relevant Multipurpose Buttons Onclick Event Logic Tutorial is shown below.

Multipurpose Buttons Onclick Event Logic Tutorial

Multipurpose Buttons Onclick Event Logic Tutorial

The web would be a very boring woooooorrrrrlllllldddd without onclick logics. The number of thoughts regarding what to do when you click on an HTML element are more than the number of grains of sand on Bondi Beach, or the Sahara Desert. Yesterday’s Multipurpose Buttons Emoji Links Tutorial had a static arrangement as far as “onclick” event logic is concerned.

Today’s job is threefold in purpose …

  • facilitate a means by which a user can define onclick logic set(s) … and we’ve chosen for this …
  • ondblclick event for non-mobile and ontouchend event for mobile … and have it that …
  • renavigating back after a content change these onclick logics get restored, as required

Can you define an onclick event logic dynamically? You bet! You can addEventListener or rewrite an element within a nesting container element (that often being a div element) or you can go something like (with Javascript) …


document.getElementById('ix').onclick=function(event){ alert('We have clicked element called ' + ('' + event.target.id)); }

The nature of this is that it gets unwieldy to define the codeline above using some Javascript eval arrangement. Rather we allow the user definition to move along with the HTML element. Can you think how? Yes, global attributes, as per the Javascript code snippet, where “newcl” contains the user onclick event logic entered as they were prompted for it …


if (newcl.trim().indexOf('function') == 0) {
aspan.setAttribute('data-onclick', (newcl.trim() + '~`').replace('}~`','').replace('~`','').substring(eval(1 + newcl.trim().indexOf('{'))) + String.fromCharCode(9));
aspan.onclick=function(event){ eval(event.target.getAttribute('data-onclick')); }
} else {
aspan.setAttribute('data-onclick', newcl + String.fromCharCode(9));
aspan.onclick=function(event){ eval(event.target.getAttribute('data-onclick')); }
}

Please see this with the fifth draft multipurpose_buttons.html live run link.


Previous relevant Multipurpose Buttons Emoji Links Tutorial is shown below.

Multipurpose Buttons Media Content Tutorial

Multipurpose Buttons Emoji Links Tutorial

We’re adding emojis into the mix of Multipurpose Buttons Media Content Tutorial functionality today. We often describe such additional functionality as an “emoji button” but for the purposes of clarity, today, we describe …

  • “a” links … with a …
  • emoji innerHTML (ie. look) … eg. &#127381; 🆕 “New” emoji we’re using as a “Restart” piece of functionality … button-like, in that they have styling …
  • style=”cursor:pointer;text-decoration:none;” … lacking the underlining “a” links typically have

… as new “emoji links” … for …

  • New (restart) 🆕
  • Email 📧
  • Circular borders ⭕
  • Glow 🌟

… as well as some new functionality that when you click outside characters and media within the “button” elements, a new popup window hones in on this clicked element.

All this can be set and moves with the web application as it recalls itself.

See this with the fourth draft multipurpose_buttons.html live run link.


Previous relevant Multipurpose Buttons Media Content Tutorial is shown below.

Multipurpose Buttons Media Content Tutorial

Multipurpose Buttons Media Content Tutorial

Were you around for the Window SessionStorage Client Versus Server Tutorial? We found a place where we could differentiate between …

… regarding the combination of …

  • sessionStorage‘s “ephemeral” storage suits … as well as a mechanism to …
  • not need (ie. be a functional replacement for) HTML form method=POST (instead, using method=GET with extra argument being the sessionStorage name used (for that tiny period of time)) for large amounts of data that normally require action=[somePHPserverPage]

… and so can remain a totally client facing web application even though we are doing similar work to what we did with Dynamic Timer Web Browser Reminder Media Tutorial when we added media file browsing into the mix by starting to interface with client_browsing.htm‘s File API talents within an HTML iframe “child” element.

And so on top of the progress up to yesterday’s Multipurpose Buttons Content Tutorial, today we allow users to be able to append …

  • img (image)
  • audio
  • video

… media data contents within the “button” (but not input type=button) element buttons.

Yet again, feel free to try the third draft multipurpose_buttons.html live run link to see what we mean by the use of sessionStorage to store (for that tiny length of time) and restore of these media data sets just within the “client facing wooooooorrrrrrllllllldddd”.


Previous relevant Multipurpose Buttons Content Tutorial is shown below.

Multipurpose Buttons Content Tutorial

Multipurpose Buttons Content Tutorial

Yesterday’s proof of concept “Multipurpose Buttons” web application of Multipurpose Buttons Primer Tutorial was pretty typical of many “proof of concept”s out there, not rocking the boat with the messy woooooorrrrllllllddd of what a user might enter as the “content” of those buttons. But that “proof of concept” idea is important to establish …

  • what is crucial … as well as …
  • what is important
  • what needs attention when genericizing (which is today’s work) … and up above all this …
  • whether the whole concept is feasible for controlled data content
  • whether the whole concept is feasible for user entered data content

… and happily, though there are some cross-browser tweaks (always a bit of a genericization “sour puss” for us), we think that last option above is indeed possible. The whole exercise has certainly borne out how much more powerful is the HTML “button” element for this multipurpose thinking, than is the “input type=button” (older) HTML element type, that “button” element now truly a “container” type of element (for us, the HTML elements where the property innerHTML has a proper meaning).

Proof of this is that this genericization drive today hardly concerned itself with any HTML “button” element concerns, rather it was a constant battle to make the HTML “input type=button” “hang in there”.

Okay then, if we are allowing a “vertical dimension” to our contents and we offer you the choice of …

  • textarea … versus …
  • div contenteditable=true

… as your user interaction HTML element of choice, which do you think is better? Well, our choice was a no brainer, as we had decided the reasoning would be …

  • encase …
  • whatever element above is used …
  • within an HTML form action=[here’sLookingAtYouKid] method=GET navigational arrangement

… as our means of passing through user interaction findings. Well, this rules out “div contenteditable=true” as the “name” property of HTML “form” elements map from that element’s “value” property, something a “div contenteditable=true” lacks but a “textarea” element excels at (as well as its “innerHTML” initializing of data (ie. value) talents, as well).

This genericization drive also taught us that even if a monospaced font such as Courier New is enforced for the HTML “input type=button” there can be different “display looks” between data containing …

  • space (” “) character (as whitespace) … versus …
  • non-breaking space (“&nbsp;”) character

… the latter crucial for us to even up record lengths of the underlying “display data” used to make the “input type=button” elements “look” as the user would have intended, meaning that the non-breaking whitespace character (as one character) above is used for “display data” that is a “square block of text” so that “display:block” can work with CSS “font-size” and “width” and “height” to facilitate this HTML “input type=button” display look.

As you’d expect, coming back (ie. callback) via “action=[here’sLookingAtYouKid]” form navigation above means we need a document.body “onload” event function as way below to set up display settings and the creation of that “onclick” logic evaled “if logic” setting the global variable “gval” …


if (cnum != ("1 2 3 " + String.fromCharCode(10) + "4 5 6 " + String.fromCharCode(10) + "7 8 9 ")) { // true user interaction data here
gval='';
eval(ifstr); // for Horizontal and Vertical input type=button ... just Horizontal uses "ifstrone" variable instead
if (gval != '') { setTimeout(agval, 1000); }
}

… is set up at global initializations followed by the “function onl” document.body “onload” event logic below …


var gval='';
var cnum=location.search.split('content=')[1] ? decodeURIComponent(location.search.split('content=')[1].split('&')[0]).replace(/\+/g,' ') : "1 2 3 " + String.fromCharCode(10) + "4 5 6 " + String.fromCharCode(10) + "7 8 9 ";
while (cnum.indexOf(' ' + String.fromCharCode(13) + String.fromCharCode(10)) != -1) {
cnum=cnum.replace(' ' + String.fromCharCode(13) + String.fromCharCode(10), ' [13][10]');
}
while (cnum.indexOf(' ' + String.fromCharCode(10) + String.fromCharCode(13)) != -1) {
cnum=cnum.replace(' ' + String.fromCharCode(10) + String.fromCharCode(13), ' [10][13]');
}
while (cnum.indexOf(' ' + String.fromCharCode(10)) != -1) {
cnum=cnum.replace(' ' + String.fromCharCode(10), ' [10]');
}
while (cnum.indexOf(' ' + String.fromCharCode(13)) != -1) {
cnum=cnum.replace(' ' + String.fromCharCode(13), ' [13]');
}


while (cnum.indexOf(String.fromCharCode(13) + String.fromCharCode(10)) != -1) {
cnum=cnum.replace(String.fromCharCode(13) + String.fromCharCode(10), ' [13][10]');
}
while (cnum.indexOf(String.fromCharCode(10) + String.fromCharCode(13)) != -1) {
cnum=cnum.replace(String.fromCharCode(10) + String.fromCharCode(13), ' [10][13]');
}
while (cnum.indexOf(String.fromCharCode(10)) != -1) {
cnum=cnum.replace(String.fromCharCode(10), ' [10]');
}
while (cnum.indexOf(String.fromCharCode(13)) != -1) {
cnum=cnum.replace(String.fromCharCode(13), ' [13]');
}
cnum=cnum.replace(/\[13\]\[10\]/g, String.fromCharCode(13) + String.fromCharCode(10));
cnum=cnum.replace(/\[10\]\[13\]/g, String.fromCharCode(10) + String.fromCharCode(13));
cnum=cnum.replace(/\[13\]/g, String.fromCharCode(13));
cnum=cnum.replace(/\[10\]/g, String.fromCharCode(10));

var origcnumx=cnum; //.trim();
var cnumx=cnum; //.trim();

function onl() {
var ih='', jh=0, kh=0, lh=0, onelh=0, zero=0, eight=0;
maxlh=0;
if (cnum != ("1 2 3 " + String.fromCharCode(10) + "4 5 6 " + String.fromCharCode(10) + "7 8 9 ")) { // true user interaction data here
var ccnums=[];
if (origcnumx.indexOf(String.fromCharCode(13) + String.fromCharCode(10)) != -1) {
ccnums=origcnumx.split(String.fromCharCode(13) + String.fromCharCode(10));
document.getElementById('content').rows='' + ccnums.length;
} else if (origcnumx.indexOf(String.fromCharCode(10) + String.fromCharCode(13)) != -1) {
ccnums=origcnumx.split(String.fromCharCode(10) + String.fromCharCode(13));
document.getElementById('content').rows='' + ccnums.length;
} else if (origcnumx.indexOf(String.fromCharCode(13)) != -1) {
ccnums=origcnumx.split(String.fromCharCode(13));
document.getElementById('content').rows='' + ccnums.length;
} else {
ccnums=origcnumx.split(String.fromCharCode(10));
document.getElementById('content').rows='' + ccnums.length;
}
//alert(ccnums.length);
for (jh=1; jh<=ccnums.length; jh++) {
if (eval('' + ccnums[eval(-1 + jh)].length) > eval('' + maxlh)) { maxlh=ccnums[eval(-1 + jh)].length; }
}
for (jh=1; jh<=cnumx.length; jh++) {
ih+="<span class=bxandy onclick='gval=this.innerHTML;'>" + cnumx.substring(eval(-1 + jh)).substring(0,1) + "</span>";
//if (lh == 0) { alert(cnumx.substring(eval(-1 + jh)).substring(0,1)); }
if ((cnumx + ' ').substring(eval(0 + jh)).substring(0,1)) {
zero=eight;
if (eight > 0) { eight--; }
} else {
zero=0;
}
if (ifstrone.indexOf('if ') == -1) {
ifstrone+=" if (eval(propx) <= eval(" + eval(1 + onelh) + "." + zero + " / " + cnumx.length + ")) { gval='" + cnumx.substring(eval(-1 + jh)).substring(0,2) + "'; } ";
} else {
ifstrone+=" else if (eval(propx) <= eval(" + eval(1 + onelh) + "." + zero + " / " + cnumx.length + ")) { gval='" + cnumx.substring(eval(-1 + jh)).substring(0,2) + "'; } ";
}
if (ccnums.length == 1) {
if (ifstr.indexOf('if ') == -1) {
ifstr+=" if (eval(propx) <= eval(" + eval(1 + lh) + "." + zero + " / " + maxlh + ")) { gval='" + cnumx.substring(eval(-1 + jh)).substring(0,2) + "'; } ";
} else {
ifstr+=" else if (eval(propx) <= eval(" + eval(1 + lh) + "." + zero + " / " + maxlh + ")) { gval='" + cnumx.substring(eval(-1 + jh)).substring(0,2) + "'; } ";
}
} else {
if (ifstr.indexOf('if ') == -1) {
ifstr+=" if (eval(propx) <= eval(" + eval(1 + lh) + "." + zero + " / " + maxlh + ") && eval(propy) <= eval(" + eval(1 + kh) + ".0 / " + ccnums.length + ")) { gval='" + cnumx.substring(eval(-1 + jh)).substring(0,2) + "'; } ";
} else {
ifstr+=" else if (eval(propx) <= eval(" + eval(1 + lh) + "." + zero + " / " + maxlh + ") && eval(propy) <= eval(" + eval(1 + kh) + ".0 / " + ccnums.length + ")) { gval='" + cnumx.substring(eval(-1 + jh)).substring(0,2) + "'; } ";
}
}
lh++;
onelh++;
if (lh == ccnums[kh].length && kh < ccnums.length) {
if (lh < maxlh) {
while (lh < maxlh) {
ih+="<span class=bxandy onclick='gval=this.innerHTML;'> </span>";
if (ccnums.length == 1) {
if (ifstr.indexOf('if ') == -1) {
ifstr+=" if (eval(propx) <= eval(" + eval(1 + lh) + ".0 / " + maxlh + ")) { gval=' '; } ";
} else {
ifstr+=" else if (eval(propx) <= eval(" + eval(1 + lh) + ".0 / " + maxlh + ")) { gval=' '; } ";
}
} else {
if (ifstr.indexOf('if ') == -1) {
ifstr+=" if (eval(propx) <= eval(" + eval(1 + lh) + ".0 / " + maxlh + ") && eval(propy) <= eval(" + eval(1 + kh) + ".0 / " + ccnums.length + ")) { gval=' '; } ";
} else {
ifstr+=" else if (eval(propx) <= eval(" + eval(1 + lh) + ".0 / " + maxlh + ") && eval(propy) <= eval(" + eval(1 + kh) + ".0 / " + ccnums.length + ")) { gval=' '; } ";
}
}
lh++;
}
}
ih+="<br>";
kh++;
lh=0;
}
}
if (maxlh == 0) { maxlh=lh; }
//alert(ifstrone);
document.getElementById('ix').style.marginLeft='1px';
document.getElementById('ix').style.marginRight='3px';
if (/chrome/i.test( navigator.userAgent )) {
document.getElementById('ix').style.width='' + Math.round(eval(0 + cnumx.length) * 8.0) + 'px';
document.getElementById('ixandy').style.width='' + Math.round(eval(0 + maxlh) * 7.5) + 'px';
} else {
document.getElementById('ix').style.width='' + Math.round(eval(0 + cnumx.length) * 6.75) + 'px';
document.getElementById('ixandy').style.width='' + Math.round(eval(0 + maxlh) * 8.0) + 'px';
}
document.getElementById('ixandy').style.height='' + Math.floor(eval(eval('' + ccnums.length) * 14) + 4) + 'px';
document.getElementById('bxandy').innerHTML=ih.replace(/\>\ \<\/span\>/g, '>&nbsp;</span>');
document.getElementById('bx').innerHTML=ih.replace(/\<br\>/g,'');
document.getElementById('ix').title='Please click a character.';
document.getElementById('ixandy').title='Please click a character.';
} else {
document.getElementById('ix').style.marginLeft='1px';
document.getElementById('ix').style.marginRight='3px';
if (/chrome/i.test( navigator.userAgent )) {
document.getElementById('ix').style.width='' + Math.round(eval(0 + cnumx.length) * 8.0) + 'px';
document.getElementById('ixandy').style.width='' + Math.round(eval(0 + 6) * 7.5) + 'px';
} else {
document.getElementById('ix').style.width='' + Math.round(eval(0 + cnumx.length) * 6.75) + 'px';
document.getElementById('ixandy').style.width='' + Math.round(eval(0 + 6) * 8.0) + 'px';
}
document.getElementById('ixandy').style.height='' + Math.floor(eval(eval('' + '3') * 14) + 4) + 'px';
}
}

So, feel free to “use” the second draft multipurpose_buttons.html live run link to see what we mean.


Previous relevant Multipurpose Buttons Primer Tutorial is shown below.

Multipurpose Buttons Primer Tutorial

Multipurpose Buttons Primer Tutorial

At this blog we go hard at spruiking the qualities of HTML dropdown (ie. select) elements to do with …

  • the display brevity … as well as …
  • richness of content possibilities

… they can infer upon a webpage. At the expense of “the display brevity” we are keen to use a dropdown attribute “size” set so as to display all the content on the screen where …

  • it can sensibly fit on the screen … and …
  • it does not matter that mobile platforms do not recognize the “size” attribute “vertical expansion” of a dropdown that takes place on non-mobile platforms

Today, though, we’re here to show you that, with a bit of Javascript event logic, a …

  • button element … even better than an …
  • input type=button element

… can go some of the way to mimicking those qualities we like so much above, doing even better than the x (ie. horizontal) dimension limit of one that a dropdown has, to be able to fit more data content in horizontally, as a display mechanism you might say has “the display brevity” combined with content complexity you are after.

We wrote a proof of concept multipurpose_buttons.html, featuring the one Javascript “onclick” logic function as per …


var x=0, y=0, lastx=0,lasty=0;
var propx=0.0, propy=0.0;

function iclicked(event) {
var rectis=null, isok=true;;
if (('' + event.target.id) == 'bxandy') {
setTimeout(agval, 1000);
} else if (('' + event.target.className) == 'bxandy') {
setTimeout(agval, 1000);
} else if (('' + event.target.id) == 'bx') {
setTimeout(agval, 1000);
} else if (('' + event.target.className) == 'bx') {
setTimeout(agval, 1000);
} else if (('' + event.target.id) == 'ixandy') {
rectis=event.target.getBoundingClientRect();
if (event.touches) { // thanks to https://stackoverflow.com/questions/24567441/how-do-i-detect-two-fingers-at-touchstart-in-javascript
if (event.touches.length > 1) { isok=false; }
}
if (isok) {
if (event.touches) {
var touches1 = event.changedTouches;
var first1 = touches1[0];
x = first1.clientX;
y = first1.clientY;
} else if (event.clientX || event.clientY) {
x = event.clientX; // - elemLeft;
y = event.clientY; // - elemTop;
} else {
x = event.pageX; // - elemLeft;
y = event.pageY; // - elemTop;
}
lastx=x;
lasty=y;
propx=eval(eval(x - rectis.x) / rectis.width);
propy=eval(eval(y - rectis.y) / rectis.height);
if (eval(propx) <= 0.333 && eval(propy) <= 0.333) {
gval='1';
setTimeout(agval, 1000);
} else if (eval(propx) >= 0.666 && eval(propy) <= 0.333) {
gval='3';
setTimeout(agval, 1000);
} else if (eval(propy) <= 0.333) {
gval='2';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.333 && eval(propy) <= 0.666) {
gval='4';
setTimeout(agval, 1000);
} else if (eval(propx) >= 0.666 && eval(propy) <= 0.666) {
gval='6';
setTimeout(agval, 1000);
} else if (eval(propy) <= 0.666) {
gval='5';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.333) {
gval='7';
setTimeout(agval, 1000);
} else if (eval(propx) >= 0.666) {
gval='9';
setTimeout(agval, 1000);
} else {
gval='8';
setTimeout(agval, 1000);
}
}
} else if (('' + event.target.id) == 'ix') {
rectis=event.target.getBoundingClientRect();
if (event.touches) { // thanks to https://stackoverflow.com/questions/24567441/how-do-i-detect-two-fingers-at-touchstart-in-javascript
if (event.touches.length > 1) { isok=false; }
}
if (isok) {
if (event.touches) {
var touches1 = event.changedTouches;
var first1 = touches1[0];
x = first1.clientX;
y = first1.clientY;
} else if (event.clientX || event.clientY) {
x = event.clientX; // - elemLeft;
y = event.clientY; // - elemTop;
} else {
x = event.pageX; // - elemLeft;
y = event.pageY; // - elemTop;
}
lastx=x;
lasty=y;
propx=eval(eval(x - rectis.x) / rectis.width);
propy=eval(eval(y - rectis.y) / rectis.height);
if (eval(propx) <= 0.111) {
gval='1';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.222) {
gval='2';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.333) {
gval='3';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.444) {
gval='4';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.555) {
gval='5';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.666) {
gval='6';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.777) {
gval='7';
setTimeout(agval, 1000);
} else if (eval(propx) <= 0.888) {
gval='8';
setTimeout(agval, 1000);
} else {
gval='9';
setTimeout(agval, 1000);
}
}
}
}

function agval() {
if (gval != '') {
alert('You clicked ' + gval);
gval='';
}
}

live run linked web application you can try for yourself regarding this, or see, in action, below …

Did you know?

Regarding the input type=button “Horizontal and Vertical Dimensions” element “look” above we needed help from the internet, thanks, to stop some web browsers such as Firefox, Chrome and Opera not “fattening out” the element height so as to show three lines of numbers, as per the CSS (thanks to html – word-wrap break-word does not work in this example – Stack Overflow and Wrapping an HTML input button's text value over multiple lines – Stack Overflow and html – Button height on Chrome – Stack Overflow) …


<style>
#ixandy {
font-size: 12px;
width: 36px;
height: 44px;

overflow-wrap: break-word;
word-wrap: break-word;

-ms-word-break: break-all;
/* This is the dangerous one in WebKit, as it breaks things wherever */
word-break: break-all;
/* Instead use this non-standard one: */
word-break: break-word;

/* Adds a hyphen where the word breaks, if supported (No Blink) */
-ms-hyphens: auto;
-moz-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;

white-space: normal;

box-sizing: content-box;
-moz-box-sizing: content-box;
-ms-box-sizing: content-box;
-webkit-box-sizing: content-box;
}
</style>

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


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


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


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


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


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


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


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


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

This entry was posted in eLearning, Event-Driven Programming, Tutorials and tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>