Javascript Map Array Destructuring Tutorial

Javascript Map Array Destructuiring Tutorial

Javascript Map Array Destructuring Tutorial

Structured data makes lots of programmers happy, in a similar way the “order” in “law and order” makes people happy. But, often, complexity works well with storage, but in analyzing what the data means, the programmer wants to break it back down into simpler forms.

We came across this excellent link from W3schools, thanks, regarding this, and while we had data at the ready to do with our current Javascript Array and Map project from yesterday’s Javascript Map Array Aggregates Tutorial, we decided to try out, or let the user try out, some of these Destructuring concepts and breakdowns for themselves, with the …

  • array … and Javascript …
  • Map object … data

… they build up, perhaps via CSV input data, accessed via double clicks of “and” … yes … “and” … and …


function destructuringfun(evt) {
evt.stopPropagation();
var kcommands=[];
var answ=null, xinterim='', zone=1, zinterim='', ioff=0, joff=1, soff=',';
var arestmore='', fruitymap;
var abstr='', iab=0, othera="a", lastchar="", prefixer="";
var ione=0, itwo=0, iones=[];
var dfun=prompt('Destructuring ( thanks to https://www.w3schools.com/js/js_destructuring.asp ) ideas with arrays and maps behind this data. Enter prefixing suggestion text (all uppercase for quantity based), then your relevant numericals ... via examples presented ...' + String.fromCharCode(10) + 'Rest after 3' + String.fromCharCode(10) + 'Rest after 1,2' + String.fromCharCode(10) + 'Rest after 1,,2' + String.fromCharCode(10) + 'Key via 1,2' + String.fromCharCode(10), '');
if (dfun == null) { dfun=''; }
if (dfun.toLowerCase().indexOf('key via ') == 0) {
iones=(dfun.toLowerCase() + ' ').split('key via ')[1].split(',');
if (eval('' + iones.length) < 1) {
iones[0]='1';
iones.push('' + fruitymap.length);
} else if (eval('' + iones.length) <= 1) {
if (iones[0].trim() == '') {
iones[0]='1';
iones.push('' + fruity.length);
} else {
iones.push('' + eval(eval('' + fruity.length) - eval('' + iones[0])));
iones[1]=eval(eval('' + iones[0]) + eval('' + iones[1]));
}
} else {
joff=1;
while (('' + iones[joff]).trim() == '') { joff++; ioff++; soff+='' + eval(eval('' + ioff) + eval('' + iones[0])) + ','; }
iones[joff]=eval(eval('' + iones[0]) - 1 + ioff + eval('' + iones[joff]));
}

fruitymap=new Map();
for (iab=1; iab<=fruity.length; iab++) {
if (soff.indexOf(',' + iab + ',') == -1) {
if (dfun.indexOf('KEY VIA ') == 0) {
if (iab >= eval('' + iones[0]) && iab <= eval('' + iones[joff])) {
fruitymap.set('quantity' + eval(0 + iab),fruity[-1 + iab].quantity);
}
} else {
if (iab >= eval('' + iones[0]) && iab <= eval('' + iones[joff])) {
fruitymap.set('name' + eval(0 + iab),fruity[-1 + iab].name);
}
}
}
}

kcommands=['gtext=""; /' + '/ using representative Javascript Map object data below '];
kcommands.push('for (var [gkey, gvalue] of fruitymap) { gtext+=gkey + " is " + gvalue + String.fromCharCode(10); }');

eval(kcommands[0]);
eval(kcommands[1]);
answ=prompt(kcommands[0] + String.fromCharCode(10) + kcommands[1] + String.fromCharCode(10) + ' ... got us to ... ' + String.fromCharCode(10) + String.fromCharCode(10) + 'gtext="' + gtext + '"', gtext);

} else if (dfun.toLowerCase().indexOf('rest after ') == 0) {
fruitything=[];
for (iab=0; iab<fruity.length; iab++) {
if (dfun.indexOf('REST AFTER ') == 0) {
fruitything.push(fruity[iab].quantity);
} else {
fruitything.push(fruity[iab].name);
}
}
ione=(dfun.toLowerCase() + ' ').split('rest after ')[1].split(',')[0].split(' ')[0];
iones=(dfun.toLowerCase() + ' ').split('rest after ')[1].split(',');
abstr='';
for (iab=0; iab<ione; iab++) {
abstr+=othera + ',';
if (othera.slice(-1) == 'z') { prefixer=othera; othera+='a'; } else { lastchar=String.fromCharCode(1 + othera.slice(-1).charCodeAt(0)); othera=prefixer + lastchar; }
}
//alert("var [" + abstr + " ...rest] = fruitything");
eval("var [" + abstr + " ...rest] = fruitything");
answ=prompt("var [" + abstr + " ...rest] = fruitything; /" + "/ using representative Javascript array data here " + String.fromCharCode(10) + String.fromCharCode(10) + ' ... got us to ... ' + String.fromCharCode(10) + String.fromCharCode(10) + 'rest=' + rest, '' + rest);

if (eval('' + iones.length) > 1) {
abstr='';
arestmore='';
xinterim='';
zinterim='';
zone=1;
while (iones[zone] == '') {
xinterim+=' "," + ';
zinterim+=',';
zone++;
}
othera="a";
for (iab=0; iab<iones[zone]; iab++) {
if (arestmore == '') {
arestmore=othera;
//xinterim='';
} else {
arestmore+=' + "," + ' + othera;
//xinterim='';
}
abstr+=othera + ',' + zinterim;
xinterim='';
zinterim='';
if (othera.slice(-1) == 'z') { prefixer=othera; othera+='a'; } else { lastchar=String.fromCharCode(1 + othera.slice(-1).charCodeAt(0)); othera=prefixer + lastchar; }
}
//alert("var [" + abstr.replace(/\,$/g,'') + "] = rest");
eval("var [" + abstr.replace(/\,$/g,'') + "] = rest");
answ=prompt("var [" + abstr.replace(/\,$/g,'') + "] = rest" + String.fromCharCode(10) + String.fromCharCode(10) + ' ... and then ... got us to ... ' + String.fromCharCode(10) + String.fromCharCode(10) + abstr.replace(/\,$/g,'') + '=' + eval(arestmore), '' + eval(arestmore));

}

}
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Aggregates Tutorial is shown below.

Javascript Map Array Aggregates Tutorial

Javascript Map Array Aggregates Tutorial

The SQL emphasis, recently, regarding our current Arrays and Map web application talked about in yesterday’s Javascript Map Array Delimiter Tutorial had us thinking about if we could incorporate those …

  • count(*)
  • sum(*)
  • min(*)
  • max(*)
  • avg(*)

SQL aggregate function concepts in some way shape or form. Given we’ve gone down the “delimiters logic” road so far, we decided on a pre-emptive approach, where we calculate all the “aggregate” concept values we could think of, ahead of the user even wondering about them, and display them as they are seeing the other data be displayed. Sounds good? We hope so.

Well, see this in action, along with Median and Mode and Standard deviation calculations, as well, in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Delimiter Tutorial is shown below.

Javascript Map Array Delimiter Tutorial

Javascript Map Array Delimiter Tutorial

Regular readers will have tweaked to the “largely delimiter based” logic surrounding the workings of the Array and Map web application of yesterday’s Javascript Map Array SQL Tutorial. To explain our changes, it’s back to a modified blurb

xenterall=prompt(‘Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below where +-*^%/ (maths) and !<>= (conditions) and ~` (for ascending descending order) and | (for OR rather than AND conditions). ‘ + String.fromCharCode(10) + ‘Examples …’ + String.fromCharCode(10) + ‘#1,3&2&4’ + String.fromCharCode(10) + ‘#4,2*3’ + String.fromCharCode(10) + ‘#1&4,3+2’ + String.fromCharCode(10) + ‘#1&4,3&2,2>100|2<-100,`2‘, ”);

… giving a “one role per interesting delimiter” paradigm we’d like to keep, if possible (though behind the scenes we have incorporated backward compatibility).

Can such a delimiter approach handle everything SQL can do? Not a chance, but by the same token, we are not reinventing any wheels with all this, but rather opening up ideas you might want to pick up and run with yourself … or not.

In the changed map_test.html Array and Map Tester web application you can also try below, you may notice other nuances, with logic now supporting …

  1. logic change …
    • OR … WHERE clause parts logic (using that | delimiter mentioned above) … in addition to pre-existing …
    • AND … WHERE clause default logic
  2. changes allowing for yellow cell report toggling between default two column data format and, perhaps, a more extensive report, via a newly introduced ondblclick (on double click) Javascript event function … the changing of which flows through to …
  3. appropriately catering logic to pass this through to email and SMS functionality (and the clicking of links within these)

… nuances pretty critical for many real data set scenarios, we figure.


Previous relevant Javascript Map Array SQL Tutorial is shown below.

Javascript Map Array SQL Tutorial

Javascript Map Array SQL Tutorial

Finishing off the SQL work start that yesterday’s Javascript Map Array Conditions Tutorial represents, today a user can follow the advice

xenterall=prompt(‘Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below where +-*^%/ (maths) and !<>= (conditions) and ~| (for ascending descending order). ‘ + String.fromCharCode(10) + ‘Examples …’ + String.fromCharCode(10) + ‘#1,3&2&4’ + String.fromCharCode(10) + ‘#4,2*3’ + String.fromCharCode(10) + ‘#1&4,3+2’ + String.fromCharCode(10) + ‘#1&4,3&2,2>100,|2‘, ”);

… to facilitate WHERE and ORDER BY processing foreshadowed yesterday.

The ORDER BY solution featured tailored Javascript sort functionality nuances …


function maybesort(rh) {
var recsare=[], newc='', ijk=0, exa='', zero=0, ipo=0;
headrec='';
if (eval('' + orderbys.length) > 0) {
recsare=rh.split(String.fromCharCode(10));
if (recsare[0].indexOf('0') == -1 && recsare[0].indexOf('1') == -1 && recsare[0].indexOf('2') == -1 && recsare[0].indexOf('3') == -1 && recsare[0].indexOf('4') == -1 && recsare[0].indexOf('5') == -1 && recsare[0].indexOf('6') == -1 && recsare[0].indexOf('7') == -1 && recsare[0].indexOf('8') == -1 && recsare[0].indexOf('9') == -1) {
headrec=recsare[0];
zero=1;
efields=headrec.replace(/\"/g,'').split(',');
for (var ke=0; ke<efields.length; ke++) {
eval('mappings.unshift({ from: "' + eval(ke + 1) + '", to: "' + efields[ke] + '"})');
}
document.getElementById('topic').innerHTML=headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1);
document.getElementById('thname').innerHTML=maybenotdefn(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1));
document.getElementById('thquantity').innerHTML=maybenotdefq(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(1));
analwheres();
}


for (ipo=0; ipo<orderbys.length; ipo++) {


if (orderbys[ipo].indexOf('~1 ') != -1) {
recsare.sort();

} else if (orderbys[ipo].indexOf('|1 ') != -1) {
recsare.sort(function(x, y) {
if (y < x) {
return -1;
}
if (y > x) {
return 1;
}
return 0;
});

} else if (orderbys[ipo].indexOf('|') != -1) {
icol=eval(-1 + eval('' + orderbys[ipo].split('|')[1].split(' ')[0]));
//alert('icol=' + icol);
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
//alert('exa=' + exa);
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
//alert('is a number');
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return 1; }
if (x == headrec && y != headrec) { return -1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + y.split(',')[icol]) < eval('' + x.split(',')[icol])) {
return -1;
}
if (eval('' + y.split(',')[icol]) > eval('' + x.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (y.split(',')[icol] < x.split(',')[icol]) {
return -1;
}
if (y.split(',')[icol] > x.split(',')[icol]) {
return 1;
}
return 0;
});
}

} else if (orderbys[ipo].indexOf('~') != -1) {

icol=eval(-1 + eval('' + orderbys[ipo].split('~')[1].split(' ')[0]));
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return -1; }
if (x == headrec && y != headrec) { return 1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + x.split(',')[icol]) < eval('' + y.split(',')[icol])) {
return -1;
}
if (eval('' + x.split(',')[icol]) > eval('' + y.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (x.split(',')[icol] < y.split(',')[icol]) {
return -1;
}
if (x.split(',')[icol] > y.split(',')[icol]) {
return 1;
}
return 0;
});
}

}


newc='';
if (headrec != '') {
newc+=headrec + String.fromCharCode(10);
}
for (ijk=0; ijk<recsare.length; ijk++) {
if (recsare[ijk] != headrec) {
newc+=recsare[ijk] + String.fromCharCode(10);
}
}
//alert(newc);
rh=newc;
}
}
//alert(rh);
return rh;
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Conditions Tutorial is shown below.

Javascript Map Array Conditions Tutorial

Javascript Map Array Conditions Tutorial

Onto yesterday’s Javascript Map Array Field Tutorial we wanted to extend functionality by starting on a “more than one day” project of thinking …

  • SQL … with it’s … SELECT … statements involving …
  • FROM … clause … representing the input (perhaps) CSV data source … filtered via …
  • WHERE … clauses, for sure … and pretty sure we can manage …
  • ORDER BY … record sorting

… people familiar with working with relative databases will understand.

So far we’re just doing the work to construct the scenario’s SQL “pseudo SELECT statement”. In doing this, we used a new mapping array that could end up looking like …

{from: ‘2’, to: ‘(Longitude+Latitude) as field2’}
{from: ‘4’, to: ‘name’}
{from: ‘3’, to: ‘longitude’}
{from: ‘2’, to: ‘latitude’}
{from: ‘1’, to: ‘country’}
{from: ‘1’, to: ‘Name’}
{from: ‘2’, to: ‘Quantity’}

… where we found building it up via the usual mapping.push() we would use to append data was some of the story, but it’s opposite number mapping.unshift() was really useful to prioritize a changing better to member data item into the mix, as the program flow progesses in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Field Tutorial is shown below.

Javascript Map Array Field Tutorial

Javascript Map Array Field Tutorial

The way the inhouse Javascript Map Array web application worked as of the day before yesterday’s Javascript Map Array Hashtag Tutorial involved …

  • a whole of file (or your entered string) processing of CSV data where the first two fields (comma separated) of records became the name,quantity data basis … but as all Spreadsheet afficianados will tell you, it can be very useful “to drill down” into fields (or “columns”, in Spreadsheet parlance) … so …
  • as of today’s work … well, we’ll let our “blurb”, coming off an H1 tag double click event, to try to explain it …

    var compositename='';
    var compositequantity='';
    var enterall='';

    function anal() {
    enterall=prompt('Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below. ' + String.fromCharCode(10) + String.fromCharCode(10) + 'Examples ...' + String.fromCharCode(10) + '#1,3&2&4' + String.fromCharCode(10) + '#4,2*3' + String.fromCharCode(10) + '#1&4,3+2', '');
    if (enterall.split('#')[0].indexOf(',') == -1 && enterall.trim() != '' && enterall.indexOf('~`~') == -1) {
    compositename='';
    compositequantity='';
    if (enterall.indexOf('#') != -1) {
    var compstuff=enterall.split('#')[1];
    enterall=enterall.split('#')[0];
    var csfs=compstuff.split(',');
    compositename=csfs[0];
    if (compositename != '') {
    if (eval(('' + compositename).split('&')[0].split('+')[0].split('/')[0].split('*')[0].split('-')[0].split('%')[0].split('^')[0]) > 1 && eval('' + csfs.length) <= 1) {
    compositequantity='1';
    } else if (eval('' + csfs.length) > 1) {
    compositequantity=csfs[1];
    }
    }
    }
    enterall='';
    }
    enterall='';
    }

… to allow for some simple mathematical operations (ie. + / – * % ^) of the right hand quantity data item, or concatenation (ie. &) on either left or right (delimited by , comma), as possibilities via user defined field (or “column”) numbering system (starting from 1) means.

Applied to our testing with country.csv here, we started getting scenarios where the Google Chart Geo Chart should turn into “markers mode”, and the statistical Google Chart Area/Bar/Column/Line Charts would have multiple Y axis items for the “name” data item X axis relationship.

More flexibility, we figure, in the extensively changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Hashtag Tutorial is shown below.

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Regular readers will know of our ever increasing fondness, out of webpage navigational ideas …

  • form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages but apt to cause error 414 due to data size restrictions) … or …
  • form method=POST URL navigation (suitable for server recipient webpages only, but able to handle much more data) … or …
  • hybrid arrangement that is essentially form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages) with error 414 avoided by most data forming the location.hash (client understood) hashtagged data

… for the last hashtagging arrangement when the data size precludes the first arrangement, and we see benefits regarding “a” “mailto:” and/or “sms:” sharing links becoming involved (rather than relying on any PHP server mail function calling).

Our Google Chart interfacing is no exception here, and yes, once we’ve completed our sweep of Google Chart inhouse functionality interfacers, on top of today’s …

… list we got keen to attend to today, with a most (when needed) strategy …

First “data” label value is method=GET
Rest of “data” value items are hashtagged

… (having the benefit that the intervention point is consistent and reliable) on top of yesterday’s Javascript Map Array Chart Tutorial, in this regard, as helper outerers for our changed map_test.html Array and Map Tester web application you can also try below, we’ll be able to further genericize Sharing and Collaboration Google Chart interfacing functionality when the amounts of data involved exceed server based (error 414) limits.

Along the way, testing on iOS mobile platforms, we were gobsmacked by the possibility of location.hash (ie. # hashtagging) not being recognized, always, at the recipient, and so a failsafe we introduced was to also store hashtagged data in a parent textbox the recipient can reference …

<?php echo ”

if (window.top) {
if (parent.document.getElementById('lhashis')) {
if (decodeURIComponent(('' + parent.document.getElementById('lhashis').value)).indexOf(',') != -1) {
location.hash=parent.document.getElementById('lhashis').value;
}
}
}

“; ?>

… even before “recipient document.body onload” timing, happily, to get around the restrictiveness of this location.hash lack of acceptance, at times.

Which brings us to …

Why is Geo Chart in that list above?

Well, it’s a bit unlikely, but it just so happens our best CSV file to hand, around here, contained ISO-3166 2 character country codes with a representative latitude and longitude (as you can see with, the now publicly shared, country.csv … thanks to Google) and this data is right up the alley of use by the Google Chart Geo Chart (which you might recall we had a different hashtag arrangement going on already …

… believe it or not, never causing any iOS mobile platform issues up to now … go figure!)

To get this “sharing of that CSV” to be any way useful, and illustrative, if you double click the “topic” word and get to the Javascript prompt window that follows, we tweak you to this, but if you enter …

https://www.rjmprogramming.com.au/HTMLCSS/country.csv

… at that prompt window, now, we’ll attempt an Ajax call of whatever URL you enter to try to glean data content to suit our …

label name to numerical quantity relationship

… this web application is hankering for.

And there, the amount of data (in size) is far too big for non-hybrid method=GET scenarios, and we need to turn to our new hybrid ideas to proceed with our quest to take over “Lower Middle Mordor South Lowlands as seen from Mirkwood“.

This may all bore, but believe me if you offer users a piece of functionality, they’ll want to push it to limits, and in that “push” could come most of your work, and concern, with regard to a project you are working on, so we figure it is best to cater for this before it is asked for.

TwoThree sentences ending in for? Okay, Grammarly, we give up!

Each Google Chart interfacer has individual nuances, but PHP code changes like below …

<?php

echo ' if (decodeURIComponent(("" + location.hash).replace(/^undefined/g,"")).trim().indexOf(",") != -1) { ' . "\n";
echo ' var xwert="data=google.visualization.arrayToDataTable([ [' . "'" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'" . '],"; ' . "\n";
echo " xwert+=\"" . str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata))))) . "\" + ('' + location.hash).replace(/^\#/g,'').replace(/\%20/g,'').replace(/\,\]/g,\",0\").replace(/\[\~/g,\"['\").replace(/\~\,/g,\"',\"); " . "\n";
echo ' xwert+=" ])"; xwert=xwert.replace(",,",","); ' . "\n";
echo ' eval(xwert); ' . "\n";
echo ' } else { ' . "\n";

echo ' data = google.visualization.arrayToDataTable([ ' . "\n";
echo " ['" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'] \n";
echo str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata)))));
echo " ]);\n";
echo " } \n";

?>

… typify our interventional strategy to make these improvements happen. Good ol’ (much maligned) eval … huh?! And good ol’ Javascript undefined bizzos! And good ol’ hashtagging! Aaaaaaaaaaal drink to all youse guys and gals (if one might be so forward, that is).


Previous relevant Javascript Map Array Chart Tutorial is shown below.

Javascript Map Array Chart Tutorial

Javascript Map Array Chart Tutorial

Does the data behind yesterday’s Javascript Map Array Import Tutorial remind you of anything? Relative database data? Spreadsheets?

That last one has lots of synergy, we reckon. And lots of us know, in spreadsheet software products like Microsoft Excel, once a …

  • spreadsheet is involved
  • charts are often offered as a graphical stand in display (to the tabular looking spreadsheet, that is)

And in this respect, looking back on our interfacing work to Google Charts when you have a label name to numerical quantity relationship two Google Chart types (we know of) are useful …

… and we’d like to offer some optional interfacing to these (to improve functionality, that is) … the Javascript for this leaning on the new …


function datait(oselv) {
var outv=oselv, kk=0, firstdelim='';
//alert(outv);
if (outv != '') {
if (oselv.indexOf('PHP/Pie') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
if (('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]').indexOf('-') == -1) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
}
} else if (oselv.indexOf('PHP/Histogram') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
//alert(outv);
} else if (oselv.indexOf('PHP/Geo') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=firstdelim + '%20[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]') + '%20';
firstdelim=',';
}
if (('' + outv).length > 600) { return toolong(outv.replace('&data=%20', '&data=%20#')); }
}
}
if (('' + outv).length > 600) {
document.getElementById('data').value=',' + outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='POST';
document.getElementById('myform').action=outv.split('?')[0] + '#pleasenolocationhref';
outv='./map_test.html';
//var xx=prompt(document.getElementById('myform').outerHTML,document.getElementById('myform').innerHTML);
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
} else if (2 == 2) {
document.getElementById('data').value=outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='GET';
document.getElementById('myform').action=outv.split('?')[0];
//outv='./map_test.html';
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
}
return outv;
}

function selit(osel) {
if (osel.value != '') {
geovalis=osel.value;
document.getElementById('defopt').innerText='Google Chart display of ... relevant ' + osel.value.split('PHP/')[1].split('/')[0].replace('Chart',' Chart') + ' below ...';
document.getElementById('dif').innerHTML='<br><br><a id=atop href="#myh1">Back to top ...</a><br><br><iframe name=myifis id=myifis src="' + datait(osel.value) + '" style="width:100%;height:700px;"></iframe>';
document.getElementById('dif').style.display='block';
}
osel.value='';
location.href='#atop';
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Import Tutorial is shown below.

Javascript Map Array Import Tutorial

Javascript Map Array Import Tutorial

Is it …

  • the extension of import capabilities … or …
  • the sharing capabilities

… of most interest in today’s work, extending that of yesterday’s Javascript Map Array Genericization Tutorial?

Well …

  • the extension of import capabilities …

    function askall(preenterall) {
    var isfirst=true;
    var delall=false;
    var enterall=('' + preenterall).replace(/^undefined$/g,'');
    if (enterall == '') {
    enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    } //else {
    //alert(enterall);
    //}
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(1);
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(2);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(3);
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(4);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(5);
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(6);
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(7);
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(8);
    if (isfirst && ((elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) < '0' || (elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) > '9')) {
    document.getElementById('topic').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thname').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thquantity').innerHTML=elines[ie].substring(0).split(',')[1].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[1].substring(1);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    isfirst=false;
    }
    beadjustable();
    }
    }

    function yesthreethree(restis) {
    if (restis.indexOf(';base64,') != -1) {
    var icontent=window.atob(restis.split(';base64,')[1]);
    if ((('' + icontent).trim() + ' ').replace(/^\[caption/g,'<').substring(0,1) == '<') {
    askall(extractContent(icontent,true));
    } else {
    askall(icontent);
    }
    } else {
    askall(restis);
    }
    }

    …asked for tweaks to our changed client_browsing.htm client side HTML and Javascript inhouse file browsing interfacer showing a “first time” scenario, for us with our “first cab off the rank” CSV (comma separated values) trial file …

    user@MacBook-Air htdocs % head -10 country.csv
    country,latitude,longitude,name // Thanks to https://developers.google.com/public-data/docs/canonical/countries_csv
    AD,42.546245,1.601554,Andorra
    AE,23.424076,53.847818,United Arab Emirates
    AF,33.93911,67.709953,Afghanistan
    AG,17.060816,-61.796428,Antigua and Barbuda
    AI,18.220554,-63.068615,Anguilla
    AL,41.153332,20.168331,Albania
    AM,40.069099,45.038189,Armenia
    AN,12.226079,-69.060087,Netherlands Antilles
    AO,-11.202692,17.873887,Angola
    user@MacBook-Air htdocs %

    … which is of interest … or …
  • the sharing capabilities, of the report, where we allow for the usual onclick of an emoji button fed through to “a” mailto: (email) or sms: (SMS) conduits to sharing, and for the first time, for us, a drag and drop way (we thank both https://www.w3schools.com/howto/howto_js_draggable.asp and https://www.w3schools.com/html/html5_draganddrop.asp regarding) …

    function dragElement(elmnt) { // thanks to https://www.w3schools.com/howto/howto_js_draggable.asp
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
    } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    alert('Here');
    }

    function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
    }
    }

    function allowDrop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.preventDefault();
    }

    function drag(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.dataTransfer.setData("text", ev.target.id);
    }

    function doemail(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    var subjis=(document.getElementById('threport').innerText || document.getElementById('threport').contentWindow || document.getElementById('threport').contentDocument);
    a.href='mailto:?subject=' + encodeURIComponent(topicis) + '%20' + encodeURIComponent(subjis) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function dosms(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    a.href='sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function drop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    var ssrect=null, isemail=true, a=null;
    ssrect=document.getElementById('droppable').getBoundingClientRect();
    if (eval(ssrect.right - ev.clientX) < eval(ev.clientX - ssrect.left)) { isemail=false; }
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    if (isemail) {
    //a = document.createElement("a");
    //a.href='mailto:?subject=' + encodeURIComponent(document.getElementById('topic').innerHTML) + '%20Report%20of%20Inventory&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    doemail(data);
    } else if (!isemail) {
    //a = document.createElement("a");
    //a.href='sms:&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    dosms(data);
    } else {
    ev.target.appendChild(document.getElementById(data));
    }
    }

    … where the drop position tells us which “conduit” to go with

… and so, both are of some interest, we figure in a changed map_test.html Array and Map Tester web application you can also try below.

Did you know?

In Object Oriented Programming, methods (ie. object functions) can be named similarly with different argument patterns and/or return values, but now, with three functions in this current project we’ve coalesced this idea into single calls and used the Javascript undefined return for non-defined arguments as our way to “keep it brief” …

  • function askall(preenterall) { } … as above
  • function alteredstate(indemo, readd) { }
  • function addone(knownname, knownquantity) { }


Previous relevant Javascript Map Array Genericization Tutorial is shown below.

Javascript Map Array Genericization Tutorial

Javascript Map Array Genericization Tutorial

We think yesterday’s Javascript Map Array Primer Tutorial could benefit from …

  • aspects that make the Inventory aspects to the web application feel more like a “tool” …
  • aspects that make the Inventory aspects to the web application feel more “generic”

… and, you may notice, fixes for the way “Map.groupBy” functionality does not appear to work on the mobile platforms my iPhone has for web browsers …


var text="";

function thecall() {
var kk=0;

// Group by ok and low
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
try {
const result = Map.groupBy(fruits, myCallback);

// Display Results
try {
for (let x of result.get("ok")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
} catch(ebad) { }
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
try {
for (let x of result.get("low")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
console.log(result.get("ok"));
} catch(ebad) { }
} catch(overebad) {
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'ok') {
//alert(fruits[kk].name);
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
//alert('2:' + fruits[kk].name);
if (!m.has(fruits[kk].name)) {
//alert('3:' + fruits[kk].name);
m.set(fruits[kk].name, fruits[kk].quantity);
//alert('4:' + fruits[kk].name);
}
}
}
}
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'low') {
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
if (!m.has(fruits[kk].name)) {
m.set(fruits[kk].name, fruits[kk].quantity);
}
}
}
}

}

document.getElementById("demo").innerHTML = text;

}

With this in mind, we honed in on a “topic” concept, where yesterday’s “topic” would have been “Fruit”. There are two aspects …

  1. allow a contenteditable way for user to change the displayed (what used to be) hardcoding

    <span title='Double click to be able to enter CSV data' id=topic contenteditable=true onblur=beadjustable(); ondblclick=askall();>Fruit</span>

    … as well as …
  2. add ondblclick (ie. on double click) means by which a user can use a Javascript prompt window means by which they can enter all the CSV (ie. comma separated values) data for an Inventory application of the user’s choosing (including a means by which they can also enter the “topic” at the same time) …

    function askall() {
    var delall=false;
    var enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    beadjustable();
    }
    }

… in a changed map_test.html “proof of concept” Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Primer Tutorial is shown below.

Javascript Map Array Primer Tutorial

Javascript Map Array Primer Tutorial

We’ve got yet another “map” idea for you today, coming from the wooooorrrrlllllddd of Javascript clientside data structures, if you like.

We got onto this topic via reading https://www.w3schools.com/js/tryit.asp?filename=tryjs_map_groupby and https://medium.com/@sotoer/your-foreach-example-has-the-wrong-order-of-params-which-you-are-also-demonstrating-in-your-sample-42f5491b604e which both helped us enormously put together a rudimentary Fruit Inventory web application featuring …

  • array with structure

    // Create an Array
    const fruits = [
    {name:"apples", quantity:300},
    {name:"bananas", quantity:500},
    {name:"oranges", quantity:200},
    {name:"kiwi", quantity:150}
    ];
  • map object

    var m = new Map();
  • use of map.set() …

    function addone() {
    doadd=true;
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    doadd=false;
    beadjustable();
    }

    … and Map.groupBy()

    function thecall() {
    // Group by ok and low
    const result = Map.groupBy(fruits, myCallback);

    // Display Results
    let text ="These fruits are Ok: <br>";
    try {
    for (let x of result.get("ok")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    text += "<br>These fruits are low: <br>";
    try {
    for (let x of result.get("low")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    document.getElementById("demo").innerHTML = text;

    console.log(result.get("ok"));
    }
  • contenteditable=true

    function consolelog(inrec) {
    if (rspan == 0) {
    document.getElementById("tdname").innerHTML=inrec.split('value:')[1].split(' key:')[0].split(' map:')[0];
    document.getElementById("tdquantity").innerHTML=inrec.split('key:')[1].split(' value:')[0].split(' map:')[0];
    rspan=1;
    } else if (inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] == '') {
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    } else {
    tabletds+='<tr><td contenteditable=false id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    }
    //alert(inrec);
    if (doadd) {
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);></td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>0</td></tr>';
    rspan++;
    doadd=false;
    }
    }
  • array.push()

… in map_test.html “proof of concept” Array and Map Tester web application …

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


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


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


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


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


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


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


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


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

Javascript Map Array Aggregates Tutorial

Javascript Map Array Aggregates Tutorial

Javascript Map Array Aggregates Tutorial

The SQL emphasis, recently, regarding our current Arrays and Map web application talked about in yesterday’s Javascript Map Array Delimiter Tutorial had us thinking about if we could incorporate those …

  • count(*)
  • sum(*)
  • min(*)
  • max(*)
  • avg(*)

SQL aggregate function concepts in some way shape or form. Given we’ve gone down the “delimiters logic” road so far, we decided on a pre-emptive approach, where we calculate all the “aggregate” concept values we could think of, ahead of the user even wondering about them, and display them as they are seeing the other data be displayed. Sounds good? We hope so.

Well, see this in action, along with Median and Mode and Standard deviation calculations, as well, in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Delimiter Tutorial is shown below.

Javascript Map Array Delimiter Tutorial

Javascript Map Array Delimiter Tutorial

Regular readers will have tweaked to the “largely delimiter based” logic surrounding the workings of the Array and Map web application of yesterday’s Javascript Map Array SQL Tutorial. To explain our changes, it’s back to a modified blurb

xenterall=prompt(‘Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below where +-*^%/ (maths) and !<>= (conditions) and ~` (for ascending descending order) and | (for OR rather than AND conditions). ‘ + String.fromCharCode(10) + ‘Examples …’ + String.fromCharCode(10) + ‘#1,3&2&4’ + String.fromCharCode(10) + ‘#4,2*3’ + String.fromCharCode(10) + ‘#1&4,3+2’ + String.fromCharCode(10) + ‘#1&4,3&2,2>100|2<-100,`2‘, ”);

… giving a “one role per interesting delimiter” paradigm we’d like to keep, if possible (though behind the scenes we have incorporated backward compatibility).

Can such a delimiter approach handle everything SQL can do? Not a chance, but by the same token, we are not reinventing any wheels with all this, but rather opening up ideas you might want to pick up and run with yourself … or not.

In the changed map_test.html Array and Map Tester web application you can also try below, you may notice other nuances, with logic now supporting …

  1. logic change …
    • OR … WHERE clause parts logic (using that | delimiter mentioned above) … in addition to pre-existing …
    • AND … WHERE clause default logic
  2. changes allowing for yellow cell report toggling between default two column data format and, perhaps, a more extensive report, via a newly introduced ondblclick (on double click) Javascript event function … the changing of which flows through to …
  3. appropriately catering logic to pass this through to email and SMS functionality (and the clicking of links within these)

… nuances pretty critical for many real data set scenarios, we figure.


Previous relevant Javascript Map Array SQL Tutorial is shown below.

Javascript Map Array SQL Tutorial

Javascript Map Array SQL Tutorial

Finishing off the SQL work start that yesterday’s Javascript Map Array Conditions Tutorial represents, today a user can follow the advice

xenterall=prompt(‘Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below where +-*^%/ (maths) and !<>= (conditions) and ~| (for ascending descending order). ‘ + String.fromCharCode(10) + ‘Examples …’ + String.fromCharCode(10) + ‘#1,3&2&4’ + String.fromCharCode(10) + ‘#4,2*3’ + String.fromCharCode(10) + ‘#1&4,3+2’ + String.fromCharCode(10) + ‘#1&4,3&2,2>100,|2‘, ”);

… to facilitate WHERE and ORDER BY processing foreshadowed yesterday.

The ORDER BY solution featured tailored Javascript sort functionality nuances …


function maybesort(rh) {
var recsare=[], newc='', ijk=0, exa='', zero=0, ipo=0;
headrec='';
if (eval('' + orderbys.length) > 0) {
recsare=rh.split(String.fromCharCode(10));
if (recsare[0].indexOf('0') == -1 && recsare[0].indexOf('1') == -1 && recsare[0].indexOf('2') == -1 && recsare[0].indexOf('3') == -1 && recsare[0].indexOf('4') == -1 && recsare[0].indexOf('5') == -1 && recsare[0].indexOf('6') == -1 && recsare[0].indexOf('7') == -1 && recsare[0].indexOf('8') == -1 && recsare[0].indexOf('9') == -1) {
headrec=recsare[0];
zero=1;
efields=headrec.replace(/\"/g,'').split(',');
for (var ke=0; ke<efields.length; ke++) {
eval('mappings.unshift({ from: "' + eval(ke + 1) + '", to: "' + efields[ke] + '"})');
}
document.getElementById('topic').innerHTML=headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1);
document.getElementById('thname').innerHTML=maybenotdefn(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1));
document.getElementById('thquantity').innerHTML=maybenotdefq(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(1));
analwheres();
}


for (ipo=0; ipo<orderbys.length; ipo++) {


if (orderbys[ipo].indexOf('~1 ') != -1) {
recsare.sort();

} else if (orderbys[ipo].indexOf('|1 ') != -1) {
recsare.sort(function(x, y) {
if (y < x) {
return -1;
}
if (y > x) {
return 1;
}
return 0;
});

} else if (orderbys[ipo].indexOf('|') != -1) {
icol=eval(-1 + eval('' + orderbys[ipo].split('|')[1].split(' ')[0]));
//alert('icol=' + icol);
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
//alert('exa=' + exa);
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
//alert('is a number');
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return 1; }
if (x == headrec && y != headrec) { return -1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + y.split(',')[icol]) < eval('' + x.split(',')[icol])) {
return -1;
}
if (eval('' + y.split(',')[icol]) > eval('' + x.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (y.split(',')[icol] < x.split(',')[icol]) {
return -1;
}
if (y.split(',')[icol] > x.split(',')[icol]) {
return 1;
}
return 0;
});
}

} else if (orderbys[ipo].indexOf('~') != -1) {

icol=eval(-1 + eval('' + orderbys[ipo].split('~')[1].split(' ')[0]));
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return -1; }
if (x == headrec && y != headrec) { return 1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + x.split(',')[icol]) < eval('' + y.split(',')[icol])) {
return -1;
}
if (eval('' + x.split(',')[icol]) > eval('' + y.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (x.split(',')[icol] < y.split(',')[icol]) {
return -1;
}
if (x.split(',')[icol] > y.split(',')[icol]) {
return 1;
}
return 0;
});
}

}


newc='';
if (headrec != '') {
newc+=headrec + String.fromCharCode(10);
}
for (ijk=0; ijk<recsare.length; ijk++) {
if (recsare[ijk] != headrec) {
newc+=recsare[ijk] + String.fromCharCode(10);
}
}
//alert(newc);
rh=newc;
}
}
//alert(rh);
return rh;
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Conditions Tutorial is shown below.

Javascript Map Array Conditions Tutorial

Javascript Map Array Conditions Tutorial

Onto yesterday’s Javascript Map Array Field Tutorial we wanted to extend functionality by starting on a “more than one day” project of thinking …

  • SQL … with it’s … SELECT … statements involving …
  • FROM … clause … representing the input (perhaps) CSV data source … filtered via …
  • WHERE … clauses, for sure … and pretty sure we can manage …
  • ORDER BY … record sorting

… people familiar with working with relative databases will understand.

So far we’re just doing the work to construct the scenario’s SQL “pseudo SELECT statement”. In doing this, we used a new mapping array that could end up looking like …

{from: ‘2’, to: ‘(Longitude+Latitude) as field2’}
{from: ‘4’, to: ‘name’}
{from: ‘3’, to: ‘longitude’}
{from: ‘2’, to: ‘latitude’}
{from: ‘1’, to: ‘country’}
{from: ‘1’, to: ‘Name’}
{from: ‘2’, to: ‘Quantity’}

… where we found building it up via the usual mapping.push() we would use to append data was some of the story, but it’s opposite number mapping.unshift() was really useful to prioritize a changing better to member data item into the mix, as the program flow progesses in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Field Tutorial is shown below.

Javascript Map Array Field Tutorial

Javascript Map Array Field Tutorial

The way the inhouse Javascript Map Array web application worked as of the day before yesterday’s Javascript Map Array Hashtag Tutorial involved …

  • a whole of file (or your entered string) processing of CSV data where the first two fields (comma separated) of records became the name,quantity data basis … but as all Spreadsheet afficianados will tell you, it can be very useful “to drill down” into fields (or “columns”, in Spreadsheet parlance) … so …
  • as of today’s work … well, we’ll let our “blurb”, coming off an H1 tag double click event, to try to explain it …

    var compositename='';
    var compositequantity='';
    var enterall='';

    function anal() {
    enterall=prompt('Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below. ' + String.fromCharCode(10) + String.fromCharCode(10) + 'Examples ...' + String.fromCharCode(10) + '#1,3&2&4' + String.fromCharCode(10) + '#4,2*3' + String.fromCharCode(10) + '#1&4,3+2', '');
    if (enterall.split('#')[0].indexOf(',') == -1 && enterall.trim() != '' && enterall.indexOf('~`~') == -1) {
    compositename='';
    compositequantity='';
    if (enterall.indexOf('#') != -1) {
    var compstuff=enterall.split('#')[1];
    enterall=enterall.split('#')[0];
    var csfs=compstuff.split(',');
    compositename=csfs[0];
    if (compositename != '') {
    if (eval(('' + compositename).split('&')[0].split('+')[0].split('/')[0].split('*')[0].split('-')[0].split('%')[0].split('^')[0]) > 1 && eval('' + csfs.length) <= 1) {
    compositequantity='1';
    } else if (eval('' + csfs.length) > 1) {
    compositequantity=csfs[1];
    }
    }
    }
    enterall='';
    }
    enterall='';
    }

… to allow for some simple mathematical operations (ie. + / – * % ^) of the right hand quantity data item, or concatenation (ie. &) on either left or right (delimited by , comma), as possibilities via user defined field (or “column”) numbering system (starting from 1) means.

Applied to our testing with country.csv here, we started getting scenarios where the Google Chart Geo Chart should turn into “markers mode”, and the statistical Google Chart Area/Bar/Column/Line Charts would have multiple Y axis items for the “name” data item X axis relationship.

More flexibility, we figure, in the extensively changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Hashtag Tutorial is shown below.

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Regular readers will know of our ever increasing fondness, out of webpage navigational ideas …

  • form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages but apt to cause error 414 due to data size restrictions) … or …
  • form method=POST URL navigation (suitable for server recipient webpages only, but able to handle much more data) … or …
  • hybrid arrangement that is essentially form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages) with error 414 avoided by most data forming the location.hash (client understood) hashtagged data

… for the last hashtagging arrangement when the data size precludes the first arrangement, and we see benefits regarding “a” “mailto:” and/or “sms:” sharing links becoming involved (rather than relying on any PHP server mail function calling).

Our Google Chart interfacing is no exception here, and yes, once we’ve completed our sweep of Google Chart inhouse functionality interfacers, on top of today’s …

… list we got keen to attend to today, with a most (when needed) strategy …

First “data” label value is method=GET
Rest of “data” value items are hashtagged

… (having the benefit that the intervention point is consistent and reliable) on top of yesterday’s Javascript Map Array Chart Tutorial, in this regard, as helper outerers for our changed map_test.html Array and Map Tester web application you can also try below, we’ll be able to further genericize Sharing and Collaboration Google Chart interfacing functionality when the amounts of data involved exceed server based (error 414) limits.

Along the way, testing on iOS mobile platforms, we were gobsmacked by the possibility of location.hash (ie. # hashtagging) not being recognized, always, at the recipient, and so a failsafe we introduced was to also store hashtagged data in a parent textbox the recipient can reference …

<?php echo ”

if (window.top) {
if (parent.document.getElementById('lhashis')) {
if (decodeURIComponent(('' + parent.document.getElementById('lhashis').value)).indexOf(',') != -1) {
location.hash=parent.document.getElementById('lhashis').value;
}
}
}

“; ?>

… even before “recipient document.body onload” timing, happily, to get around the restrictiveness of this location.hash lack of acceptance, at times.

Which brings us to …

Why is Geo Chart in that list above?

Well, it’s a bit unlikely, but it just so happens our best CSV file to hand, around here, contained ISO-3166 2 character country codes with a representative latitude and longitude (as you can see with, the now publicly shared, country.csv … thanks to Google) and this data is right up the alley of use by the Google Chart Geo Chart (which you might recall we had a different hashtag arrangement going on already …

… believe it or not, never causing any iOS mobile platform issues up to now … go figure!)

To get this “sharing of that CSV” to be any way useful, and illustrative, if you double click the “topic” word and get to the Javascript prompt window that follows, we tweak you to this, but if you enter …

https://www.rjmprogramming.com.au/HTMLCSS/country.csv

… at that prompt window, now, we’ll attempt an Ajax call of whatever URL you enter to try to glean data content to suit our …

label name to numerical quantity relationship

… this web application is hankering for.

And there, the amount of data (in size) is far too big for non-hybrid method=GET scenarios, and we need to turn to our new hybrid ideas to proceed with our quest to take over “Lower Middle Mordor South Lowlands as seen from Mirkwood“.

This may all bore, but believe me if you offer users a piece of functionality, they’ll want to push it to limits, and in that “push” could come most of your work, and concern, with regard to a project you are working on, so we figure it is best to cater for this before it is asked for.

TwoThree sentences ending in for? Okay, Grammarly, we give up!

Each Google Chart interfacer has individual nuances, but PHP code changes like below …

<?php

echo ' if (decodeURIComponent(("" + location.hash).replace(/^undefined/g,"")).trim().indexOf(",") != -1) { ' . "\n";
echo ' var xwert="data=google.visualization.arrayToDataTable([ [' . "'" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'" . '],"; ' . "\n";
echo " xwert+=\"" . str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata))))) . "\" + ('' + location.hash).replace(/^\#/g,'').replace(/\%20/g,'').replace(/\,\]/g,\",0\").replace(/\[\~/g,\"['\").replace(/\~\,/g,\"',\"); " . "\n";
echo ' xwert+=" ])"; xwert=xwert.replace(",,",","); ' . "\n";
echo ' eval(xwert); ' . "\n";
echo ' } else { ' . "\n";

echo ' data = google.visualization.arrayToDataTable([ ' . "\n";
echo " ['" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'] \n";
echo str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata)))));
echo " ]);\n";
echo " } \n";

?>

… typify our interventional strategy to make these improvements happen. Good ol’ (much maligned) eval … huh?! And good ol’ Javascript undefined bizzos! And good ol’ hashtagging! Aaaaaaaaaaal drink to all youse guys and gals (if one might be so forward, that is).


Previous relevant Javascript Map Array Chart Tutorial is shown below.

Javascript Map Array Chart Tutorial

Javascript Map Array Chart Tutorial

Does the data behind yesterday’s Javascript Map Array Import Tutorial remind you of anything? Relative database data? Spreadsheets?

That last one has lots of synergy, we reckon. And lots of us know, in spreadsheet software products like Microsoft Excel, once a …

  • spreadsheet is involved
  • charts are often offered as a graphical stand in display (to the tabular looking spreadsheet, that is)

And in this respect, looking back on our interfacing work to Google Charts when you have a label name to numerical quantity relationship two Google Chart types (we know of) are useful …

… and we’d like to offer some optional interfacing to these (to improve functionality, that is) … the Javascript for this leaning on the new …


function datait(oselv) {
var outv=oselv, kk=0, firstdelim='';
//alert(outv);
if (outv != '') {
if (oselv.indexOf('PHP/Pie') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
if (('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]').indexOf('-') == -1) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
}
} else if (oselv.indexOf('PHP/Histogram') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
//alert(outv);
} else if (oselv.indexOf('PHP/Geo') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=firstdelim + '%20[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]') + '%20';
firstdelim=',';
}
if (('' + outv).length > 600) { return toolong(outv.replace('&data=%20', '&data=%20#')); }
}
}
if (('' + outv).length > 600) {
document.getElementById('data').value=',' + outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='POST';
document.getElementById('myform').action=outv.split('?')[0] + '#pleasenolocationhref';
outv='./map_test.html';
//var xx=prompt(document.getElementById('myform').outerHTML,document.getElementById('myform').innerHTML);
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
} else if (2 == 2) {
document.getElementById('data').value=outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='GET';
document.getElementById('myform').action=outv.split('?')[0];
//outv='./map_test.html';
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
}
return outv;
}

function selit(osel) {
if (osel.value != '') {
geovalis=osel.value;
document.getElementById('defopt').innerText='Google Chart display of ... relevant ' + osel.value.split('PHP/')[1].split('/')[0].replace('Chart',' Chart') + ' below ...';
document.getElementById('dif').innerHTML='<br><br><a id=atop href="#myh1">Back to top ...</a><br><br><iframe name=myifis id=myifis src="' + datait(osel.value) + '" style="width:100%;height:700px;"></iframe>';
document.getElementById('dif').style.display='block';
}
osel.value='';
location.href='#atop';
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Import Tutorial is shown below.

Javascript Map Array Import Tutorial

Javascript Map Array Import Tutorial

Is it …

  • the extension of import capabilities … or …
  • the sharing capabilities

… of most interest in today’s work, extending that of yesterday’s Javascript Map Array Genericization Tutorial?

Well …

  • the extension of import capabilities …

    function askall(preenterall) {
    var isfirst=true;
    var delall=false;
    var enterall=('' + preenterall).replace(/^undefined$/g,'');
    if (enterall == '') {
    enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    } //else {
    //alert(enterall);
    //}
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(1);
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(2);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(3);
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(4);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(5);
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(6);
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(7);
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(8);
    if (isfirst && ((elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) < '0' || (elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) > '9')) {
    document.getElementById('topic').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thname').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thquantity').innerHTML=elines[ie].substring(0).split(',')[1].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[1].substring(1);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    isfirst=false;
    }
    beadjustable();
    }
    }

    function yesthreethree(restis) {
    if (restis.indexOf(';base64,') != -1) {
    var icontent=window.atob(restis.split(';base64,')[1]);
    if ((('' + icontent).trim() + ' ').replace(/^\[caption/g,'<').substring(0,1) == '<') {
    askall(extractContent(icontent,true));
    } else {
    askall(icontent);
    }
    } else {
    askall(restis);
    }
    }

    …asked for tweaks to our changed client_browsing.htm client side HTML and Javascript inhouse file browsing interfacer showing a “first time” scenario, for us with our “first cab off the rank” CSV (comma separated values) trial file …

    user@MacBook-Air htdocs % head -10 country.csv
    country,latitude,longitude,name // Thanks to https://developers.google.com/public-data/docs/canonical/countries_csv
    AD,42.546245,1.601554,Andorra
    AE,23.424076,53.847818,United Arab Emirates
    AF,33.93911,67.709953,Afghanistan
    AG,17.060816,-61.796428,Antigua and Barbuda
    AI,18.220554,-63.068615,Anguilla
    AL,41.153332,20.168331,Albania
    AM,40.069099,45.038189,Armenia
    AN,12.226079,-69.060087,Netherlands Antilles
    AO,-11.202692,17.873887,Angola
    user@MacBook-Air htdocs %

    … which is of interest … or …
  • the sharing capabilities, of the report, where we allow for the usual onclick of an emoji button fed through to “a” mailto: (email) or sms: (SMS) conduits to sharing, and for the first time, for us, a drag and drop way (we thank both https://www.w3schools.com/howto/howto_js_draggable.asp and https://www.w3schools.com/html/html5_draganddrop.asp regarding) …

    function dragElement(elmnt) { // thanks to https://www.w3schools.com/howto/howto_js_draggable.asp
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
    } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    alert('Here');
    }

    function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
    }
    }

    function allowDrop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.preventDefault();
    }

    function drag(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.dataTransfer.setData("text", ev.target.id);
    }

    function doemail(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    var subjis=(document.getElementById('threport').innerText || document.getElementById('threport').contentWindow || document.getElementById('threport').contentDocument);
    a.href='mailto:?subject=' + encodeURIComponent(topicis) + '%20' + encodeURIComponent(subjis) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function dosms(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    a.href='sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function drop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    var ssrect=null, isemail=true, a=null;
    ssrect=document.getElementById('droppable').getBoundingClientRect();
    if (eval(ssrect.right - ev.clientX) < eval(ev.clientX - ssrect.left)) { isemail=false; }
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    if (isemail) {
    //a = document.createElement("a");
    //a.href='mailto:?subject=' + encodeURIComponent(document.getElementById('topic').innerHTML) + '%20Report%20of%20Inventory&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    doemail(data);
    } else if (!isemail) {
    //a = document.createElement("a");
    //a.href='sms:&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    dosms(data);
    } else {
    ev.target.appendChild(document.getElementById(data));
    }
    }

    … where the drop position tells us which “conduit” to go with

… and so, both are of some interest, we figure in a changed map_test.html Array and Map Tester web application you can also try below.

Did you know?

In Object Oriented Programming, methods (ie. object functions) can be named similarly with different argument patterns and/or return values, but now, with three functions in this current project we’ve coalesced this idea into single calls and used the Javascript undefined return for non-defined arguments as our way to “keep it brief” …

  • function askall(preenterall) { } … as above
  • function alteredstate(indemo, readd) { }
  • function addone(knownname, knownquantity) { }


Previous relevant Javascript Map Array Genericization Tutorial is shown below.

Javascript Map Array Genericization Tutorial

Javascript Map Array Genericization Tutorial

We think yesterday’s Javascript Map Array Primer Tutorial could benefit from …

  • aspects that make the Inventory aspects to the web application feel more like a “tool” …
  • aspects that make the Inventory aspects to the web application feel more “generic”

… and, you may notice, fixes for the way “Map.groupBy” functionality does not appear to work on the mobile platforms my iPhone has for web browsers …


var text="";

function thecall() {
var kk=0;

// Group by ok and low
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
try {
const result = Map.groupBy(fruits, myCallback);

// Display Results
try {
for (let x of result.get("ok")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
} catch(ebad) { }
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
try {
for (let x of result.get("low")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
console.log(result.get("ok"));
} catch(ebad) { }
} catch(overebad) {
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'ok') {
//alert(fruits[kk].name);
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
//alert('2:' + fruits[kk].name);
if (!m.has(fruits[kk].name)) {
//alert('3:' + fruits[kk].name);
m.set(fruits[kk].name, fruits[kk].quantity);
//alert('4:' + fruits[kk].name);
}
}
}
}
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'low') {
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
if (!m.has(fruits[kk].name)) {
m.set(fruits[kk].name, fruits[kk].quantity);
}
}
}
}

}

document.getElementById("demo").innerHTML = text;

}

With this in mind, we honed in on a “topic” concept, where yesterday’s “topic” would have been “Fruit”. There are two aspects …

  1. allow a contenteditable way for user to change the displayed (what used to be) hardcoding

    <span title='Double click to be able to enter CSV data' id=topic contenteditable=true onblur=beadjustable(); ondblclick=askall();>Fruit</span>

    … as well as …
  2. add ondblclick (ie. on double click) means by which a user can use a Javascript prompt window means by which they can enter all the CSV (ie. comma separated values) data for an Inventory application of the user’s choosing (including a means by which they can also enter the “topic” at the same time) …

    function askall() {
    var delall=false;
    var enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    beadjustable();
    }
    }

… in a changed map_test.html “proof of concept” Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Primer Tutorial is shown below.

Javascript Map Array Primer Tutorial

Javascript Map Array Primer Tutorial

We’ve got yet another “map” idea for you today, coming from the wooooorrrrlllllddd of Javascript clientside data structures, if you like.

We got onto this topic via reading https://www.w3schools.com/js/tryit.asp?filename=tryjs_map_groupby and https://medium.com/@sotoer/your-foreach-example-has-the-wrong-order-of-params-which-you-are-also-demonstrating-in-your-sample-42f5491b604e which both helped us enormously put together a rudimentary Fruit Inventory web application featuring …

  • array with structure

    // Create an Array
    const fruits = [
    {name:"apples", quantity:300},
    {name:"bananas", quantity:500},
    {name:"oranges", quantity:200},
    {name:"kiwi", quantity:150}
    ];
  • map object

    var m = new Map();
  • use of map.set() …

    function addone() {
    doadd=true;
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    doadd=false;
    beadjustable();
    }

    … and Map.groupBy()

    function thecall() {
    // Group by ok and low
    const result = Map.groupBy(fruits, myCallback);

    // Display Results
    let text ="These fruits are Ok: <br>";
    try {
    for (let x of result.get("ok")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    text += "<br>These fruits are low: <br>";
    try {
    for (let x of result.get("low")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    document.getElementById("demo").innerHTML = text;

    console.log(result.get("ok"));
    }
  • contenteditable=true

    function consolelog(inrec) {
    if (rspan == 0) {
    document.getElementById("tdname").innerHTML=inrec.split('value:')[1].split(' key:')[0].split(' map:')[0];
    document.getElementById("tdquantity").innerHTML=inrec.split('key:')[1].split(' value:')[0].split(' map:')[0];
    rspan=1;
    } else if (inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] == '') {
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    } else {
    tabletds+='<tr><td contenteditable=false id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    }
    //alert(inrec);
    if (doadd) {
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);></td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>0</td></tr>';
    rspan++;
    doadd=false;
    }
    }
  • array.push()

… in map_test.html “proof of concept” Array and Map Tester web application …

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


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


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


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


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


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


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


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

Javascript Map Array Delimiter Tutorial

Javascript Map Array Delimiter Tutorial

Javascript Map Array Delimiter Tutorial

Regular readers will have tweaked to the “largely delimiter based” logic surrounding the workings of the Array and Map web application of yesterday’s Javascript Map Array SQL Tutorial. To explain our changes, it’s back to a modified blurb

xenterall=prompt(‘Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below where +-*^%/ (maths) and !<>= (conditions) and ~` (for ascending descending order) and | (for OR rather than AND conditions). ‘ + String.fromCharCode(10) + ‘Examples …’ + String.fromCharCode(10) + ‘#1,3&2&4’ + String.fromCharCode(10) + ‘#4,2*3’ + String.fromCharCode(10) + ‘#1&4,3+2’ + String.fromCharCode(10) + ‘#1&4,3&2,2>100|2<-100,`2‘, ”);

… giving a “one role per interesting delimiter” paradigm we’d like to keep, if possible (though behind the scenes we have incorporated backward compatibility).

Can such a delimiter approach handle everything SQL can do? Not a chance, but by the same token, we are not reinventing any wheels with all this, but rather opening up ideas you might want to pick up and run with yourself … or not.

In the changed map_test.html Array and Map Tester web application you can also try below, you may notice other nuances, with logic now supporting …

  1. logic change …
    • OR … WHERE clause parts logic (using that | delimiter mentioned above) … in addition to pre-existing …
    • AND … WHERE clause default logic
  2. changes allowing for yellow cell report toggling between default two column data format and, perhaps, a more extensive report, via a newly introduced ondblclick (on double click) Javascript event function … the changing of which flows through to …
  3. appropriately catering logic to pass this through to email and SMS functionality (and the clicking of links within these)

… nuances pretty critical for many real data set scenarios, we figure.


Previous relevant Javascript Map Array SQL Tutorial is shown below.

Javascript Map Array SQL Tutorial

Javascript Map Array SQL Tutorial

Finishing off the SQL work start that yesterday’s Javascript Map Array Conditions Tutorial represents, today a user can follow the advice

xenterall=prompt(‘Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below where +-*^%/ (maths) and !<>= (conditions) and ~| (for ascending descending order). ‘ + String.fromCharCode(10) + ‘Examples …’ + String.fromCharCode(10) + ‘#1,3&2&4’ + String.fromCharCode(10) + ‘#4,2*3’ + String.fromCharCode(10) + ‘#1&4,3+2’ + String.fromCharCode(10) + ‘#1&4,3&2,2>100,|2‘, ”);

… to facilitate WHERE and ORDER BY processing foreshadowed yesterday.

The ORDER BY solution featured tailored Javascript sort functionality nuances …


function maybesort(rh) {
var recsare=[], newc='', ijk=0, exa='', zero=0, ipo=0;
headrec='';
if (eval('' + orderbys.length) > 0) {
recsare=rh.split(String.fromCharCode(10));
if (recsare[0].indexOf('0') == -1 && recsare[0].indexOf('1') == -1 && recsare[0].indexOf('2') == -1 && recsare[0].indexOf('3') == -1 && recsare[0].indexOf('4') == -1 && recsare[0].indexOf('5') == -1 && recsare[0].indexOf('6') == -1 && recsare[0].indexOf('7') == -1 && recsare[0].indexOf('8') == -1 && recsare[0].indexOf('9') == -1) {
headrec=recsare[0];
zero=1;
efields=headrec.replace(/\"/g,'').split(',');
for (var ke=0; ke<efields.length; ke++) {
eval('mappings.unshift({ from: "' + eval(ke + 1) + '", to: "' + efields[ke] + '"})');
}
document.getElementById('topic').innerHTML=headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1);
document.getElementById('thname').innerHTML=maybenotdefn(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1));
document.getElementById('thquantity').innerHTML=maybenotdefq(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(1));
analwheres();
}


for (ipo=0; ipo<orderbys.length; ipo++) {


if (orderbys[ipo].indexOf('~1 ') != -1) {
recsare.sort();

} else if (orderbys[ipo].indexOf('|1 ') != -1) {
recsare.sort(function(x, y) {
if (y < x) {
return -1;
}
if (y > x) {
return 1;
}
return 0;
});

} else if (orderbys[ipo].indexOf('|') != -1) {
icol=eval(-1 + eval('' + orderbys[ipo].split('|')[1].split(' ')[0]));
//alert('icol=' + icol);
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
//alert('exa=' + exa);
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
//alert('is a number');
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return 1; }
if (x == headrec && y != headrec) { return -1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + y.split(',')[icol]) < eval('' + x.split(',')[icol])) {
return -1;
}
if (eval('' + y.split(',')[icol]) > eval('' + x.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (y.split(',')[icol] < x.split(',')[icol]) {
return -1;
}
if (y.split(',')[icol] > x.split(',')[icol]) {
return 1;
}
return 0;
});
}

} else if (orderbys[ipo].indexOf('~') != -1) {

icol=eval(-1 + eval('' + orderbys[ipo].split('~')[1].split(' ')[0]));
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return -1; }
if (x == headrec && y != headrec) { return 1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + x.split(',')[icol]) < eval('' + y.split(',')[icol])) {
return -1;
}
if (eval('' + x.split(',')[icol]) > eval('' + y.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (x.split(',')[icol] < y.split(',')[icol]) {
return -1;
}
if (x.split(',')[icol] > y.split(',')[icol]) {
return 1;
}
return 0;
});
}

}


newc='';
if (headrec != '') {
newc+=headrec + String.fromCharCode(10);
}
for (ijk=0; ijk<recsare.length; ijk++) {
if (recsare[ijk] != headrec) {
newc+=recsare[ijk] + String.fromCharCode(10);
}
}
//alert(newc);
rh=newc;
}
}
//alert(rh);
return rh;
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Conditions Tutorial is shown below.

Javascript Map Array Conditions Tutorial

Javascript Map Array Conditions Tutorial

Onto yesterday’s Javascript Map Array Field Tutorial we wanted to extend functionality by starting on a “more than one day” project of thinking …

  • SQL … with it’s … SELECT … statements involving …
  • FROM … clause … representing the input (perhaps) CSV data source … filtered via …
  • WHERE … clauses, for sure … and pretty sure we can manage …
  • ORDER BY … record sorting

… people familiar with working with relative databases will understand.

So far we’re just doing the work to construct the scenario’s SQL “pseudo SELECT statement”. In doing this, we used a new mapping array that could end up looking like …

{from: ‘2’, to: ‘(Longitude+Latitude) as field2’}
{from: ‘4’, to: ‘name’}
{from: ‘3’, to: ‘longitude’}
{from: ‘2’, to: ‘latitude’}
{from: ‘1’, to: ‘country’}
{from: ‘1’, to: ‘Name’}
{from: ‘2’, to: ‘Quantity’}

… where we found building it up via the usual mapping.push() we would use to append data was some of the story, but it’s opposite number mapping.unshift() was really useful to prioritize a changing better to member data item into the mix, as the program flow progesses in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Field Tutorial is shown below.

Javascript Map Array Field Tutorial

Javascript Map Array Field Tutorial

The way the inhouse Javascript Map Array web application worked as of the day before yesterday’s Javascript Map Array Hashtag Tutorial involved …

  • a whole of file (or your entered string) processing of CSV data where the first two fields (comma separated) of records became the name,quantity data basis … but as all Spreadsheet afficianados will tell you, it can be very useful “to drill down” into fields (or “columns”, in Spreadsheet parlance) … so …
  • as of today’s work … well, we’ll let our “blurb”, coming off an H1 tag double click event, to try to explain it …

    var compositename='';
    var compositequantity='';
    var enterall='';

    function anal() {
    enterall=prompt('Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below. ' + String.fromCharCode(10) + String.fromCharCode(10) + 'Examples ...' + String.fromCharCode(10) + '#1,3&2&4' + String.fromCharCode(10) + '#4,2*3' + String.fromCharCode(10) + '#1&4,3+2', '');
    if (enterall.split('#')[0].indexOf(',') == -1 && enterall.trim() != '' && enterall.indexOf('~`~') == -1) {
    compositename='';
    compositequantity='';
    if (enterall.indexOf('#') != -1) {
    var compstuff=enterall.split('#')[1];
    enterall=enterall.split('#')[0];
    var csfs=compstuff.split(',');
    compositename=csfs[0];
    if (compositename != '') {
    if (eval(('' + compositename).split('&')[0].split('+')[0].split('/')[0].split('*')[0].split('-')[0].split('%')[0].split('^')[0]) > 1 && eval('' + csfs.length) <= 1) {
    compositequantity='1';
    } else if (eval('' + csfs.length) > 1) {
    compositequantity=csfs[1];
    }
    }
    }
    enterall='';
    }
    enterall='';
    }

… to allow for some simple mathematical operations (ie. + / – * % ^) of the right hand quantity data item, or concatenation (ie. &) on either left or right (delimited by , comma), as possibilities via user defined field (or “column”) numbering system (starting from 1) means.

Applied to our testing with country.csv here, we started getting scenarios where the Google Chart Geo Chart should turn into “markers mode”, and the statistical Google Chart Area/Bar/Column/Line Charts would have multiple Y axis items for the “name” data item X axis relationship.

More flexibility, we figure, in the extensively changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Hashtag Tutorial is shown below.

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Regular readers will know of our ever increasing fondness, out of webpage navigational ideas …

  • form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages but apt to cause error 414 due to data size restrictions) … or …
  • form method=POST URL navigation (suitable for server recipient webpages only, but able to handle much more data) … or …
  • hybrid arrangement that is essentially form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages) with error 414 avoided by most data forming the location.hash (client understood) hashtagged data

… for the last hashtagging arrangement when the data size precludes the first arrangement, and we see benefits regarding “a” “mailto:” and/or “sms:” sharing links becoming involved (rather than relying on any PHP server mail function calling).

Our Google Chart interfacing is no exception here, and yes, once we’ve completed our sweep of Google Chart inhouse functionality interfacers, on top of today’s …

… list we got keen to attend to today, with a most (when needed) strategy …

First “data” label value is method=GET
Rest of “data” value items are hashtagged

… (having the benefit that the intervention point is consistent and reliable) on top of yesterday’s Javascript Map Array Chart Tutorial, in this regard, as helper outerers for our changed map_test.html Array and Map Tester web application you can also try below, we’ll be able to further genericize Sharing and Collaboration Google Chart interfacing functionality when the amounts of data involved exceed server based (error 414) limits.

Along the way, testing on iOS mobile platforms, we were gobsmacked by the possibility of location.hash (ie. # hashtagging) not being recognized, always, at the recipient, and so a failsafe we introduced was to also store hashtagged data in a parent textbox the recipient can reference …

<?php echo ”

if (window.top) {
if (parent.document.getElementById('lhashis')) {
if (decodeURIComponent(('' + parent.document.getElementById('lhashis').value)).indexOf(',') != -1) {
location.hash=parent.document.getElementById('lhashis').value;
}
}
}

“; ?>

… even before “recipient document.body onload” timing, happily, to get around the restrictiveness of this location.hash lack of acceptance, at times.

Which brings us to …

Why is Geo Chart in that list above?

Well, it’s a bit unlikely, but it just so happens our best CSV file to hand, around here, contained ISO-3166 2 character country codes with a representative latitude and longitude (as you can see with, the now publicly shared, country.csv … thanks to Google) and this data is right up the alley of use by the Google Chart Geo Chart (which you might recall we had a different hashtag arrangement going on already …

… believe it or not, never causing any iOS mobile platform issues up to now … go figure!)

To get this “sharing of that CSV” to be any way useful, and illustrative, if you double click the “topic” word and get to the Javascript prompt window that follows, we tweak you to this, but if you enter …

https://www.rjmprogramming.com.au/HTMLCSS/country.csv

… at that prompt window, now, we’ll attempt an Ajax call of whatever URL you enter to try to glean data content to suit our …

label name to numerical quantity relationship

… this web application is hankering for.

And there, the amount of data (in size) is far too big for non-hybrid method=GET scenarios, and we need to turn to our new hybrid ideas to proceed with our quest to take over “Lower Middle Mordor South Lowlands as seen from Mirkwood“.

This may all bore, but believe me if you offer users a piece of functionality, they’ll want to push it to limits, and in that “push” could come most of your work, and concern, with regard to a project you are working on, so we figure it is best to cater for this before it is asked for.

TwoThree sentences ending in for? Okay, Grammarly, we give up!

Each Google Chart interfacer has individual nuances, but PHP code changes like below …

<?php

echo ' if (decodeURIComponent(("" + location.hash).replace(/^undefined/g,"")).trim().indexOf(",") != -1) { ' . "\n";
echo ' var xwert="data=google.visualization.arrayToDataTable([ [' . "'" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'" . '],"; ' . "\n";
echo " xwert+=\"" . str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata))))) . "\" + ('' + location.hash).replace(/^\#/g,'').replace(/\%20/g,'').replace(/\,\]/g,\",0\").replace(/\[\~/g,\"['\").replace(/\~\,/g,\"',\"); " . "\n";
echo ' xwert+=" ])"; xwert=xwert.replace(",,",","); ' . "\n";
echo ' eval(xwert); ' . "\n";
echo ' } else { ' . "\n";

echo ' data = google.visualization.arrayToDataTable([ ' . "\n";
echo " ['" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'] \n";
echo str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata)))));
echo " ]);\n";
echo " } \n";

?>

… typify our interventional strategy to make these improvements happen. Good ol’ (much maligned) eval … huh?! And good ol’ Javascript undefined bizzos! And good ol’ hashtagging! Aaaaaaaaaaal drink to all youse guys and gals (if one might be so forward, that is).


Previous relevant Javascript Map Array Chart Tutorial is shown below.

Javascript Map Array Chart Tutorial

Javascript Map Array Chart Tutorial

Does the data behind yesterday’s Javascript Map Array Import Tutorial remind you of anything? Relative database data? Spreadsheets?

That last one has lots of synergy, we reckon. And lots of us know, in spreadsheet software products like Microsoft Excel, once a …

  • spreadsheet is involved
  • charts are often offered as a graphical stand in display (to the tabular looking spreadsheet, that is)

And in this respect, looking back on our interfacing work to Google Charts when you have a label name to numerical quantity relationship two Google Chart types (we know of) are useful …

… and we’d like to offer some optional interfacing to these (to improve functionality, that is) … the Javascript for this leaning on the new …


function datait(oselv) {
var outv=oselv, kk=0, firstdelim='';
//alert(outv);
if (outv != '') {
if (oselv.indexOf('PHP/Pie') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
if (('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]').indexOf('-') == -1) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
}
} else if (oselv.indexOf('PHP/Histogram') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
//alert(outv);
} else if (oselv.indexOf('PHP/Geo') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=firstdelim + '%20[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]') + '%20';
firstdelim=',';
}
if (('' + outv).length > 600) { return toolong(outv.replace('&data=%20', '&data=%20#')); }
}
}
if (('' + outv).length > 600) {
document.getElementById('data').value=',' + outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='POST';
document.getElementById('myform').action=outv.split('?')[0] + '#pleasenolocationhref';
outv='./map_test.html';
//var xx=prompt(document.getElementById('myform').outerHTML,document.getElementById('myform').innerHTML);
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
} else if (2 == 2) {
document.getElementById('data').value=outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='GET';
document.getElementById('myform').action=outv.split('?')[0];
//outv='./map_test.html';
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
}
return outv;
}

function selit(osel) {
if (osel.value != '') {
geovalis=osel.value;
document.getElementById('defopt').innerText='Google Chart display of ... relevant ' + osel.value.split('PHP/')[1].split('/')[0].replace('Chart',' Chart') + ' below ...';
document.getElementById('dif').innerHTML='<br><br><a id=atop href="#myh1">Back to top ...</a><br><br><iframe name=myifis id=myifis src="' + datait(osel.value) + '" style="width:100%;height:700px;"></iframe>';
document.getElementById('dif').style.display='block';
}
osel.value='';
location.href='#atop';
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Import Tutorial is shown below.

Javascript Map Array Import Tutorial

Javascript Map Array Import Tutorial

Is it …

  • the extension of import capabilities … or …
  • the sharing capabilities

… of most interest in today’s work, extending that of yesterday’s Javascript Map Array Genericization Tutorial?

Well …

  • the extension of import capabilities …

    function askall(preenterall) {
    var isfirst=true;
    var delall=false;
    var enterall=('' + preenterall).replace(/^undefined$/g,'');
    if (enterall == '') {
    enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    } //else {
    //alert(enterall);
    //}
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(1);
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(2);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(3);
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(4);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(5);
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(6);
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(7);
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(8);
    if (isfirst && ((elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) < '0' || (elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) > '9')) {
    document.getElementById('topic').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thname').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thquantity').innerHTML=elines[ie].substring(0).split(',')[1].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[1].substring(1);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    isfirst=false;
    }
    beadjustable();
    }
    }

    function yesthreethree(restis) {
    if (restis.indexOf(';base64,') != -1) {
    var icontent=window.atob(restis.split(';base64,')[1]);
    if ((('' + icontent).trim() + ' ').replace(/^\[caption/g,'<').substring(0,1) == '<') {
    askall(extractContent(icontent,true));
    } else {
    askall(icontent);
    }
    } else {
    askall(restis);
    }
    }

    …asked for tweaks to our changed client_browsing.htm client side HTML and Javascript inhouse file browsing interfacer showing a “first time” scenario, for us with our “first cab off the rank” CSV (comma separated values) trial file …

    user@MacBook-Air htdocs % head -10 country.csv
    country,latitude,longitude,name // Thanks to https://developers.google.com/public-data/docs/canonical/countries_csv
    AD,42.546245,1.601554,Andorra
    AE,23.424076,53.847818,United Arab Emirates
    AF,33.93911,67.709953,Afghanistan
    AG,17.060816,-61.796428,Antigua and Barbuda
    AI,18.220554,-63.068615,Anguilla
    AL,41.153332,20.168331,Albania
    AM,40.069099,45.038189,Armenia
    AN,12.226079,-69.060087,Netherlands Antilles
    AO,-11.202692,17.873887,Angola
    user@MacBook-Air htdocs %

    … which is of interest … or …
  • the sharing capabilities, of the report, where we allow for the usual onclick of an emoji button fed through to “a” mailto: (email) or sms: (SMS) conduits to sharing, and for the first time, for us, a drag and drop way (we thank both https://www.w3schools.com/howto/howto_js_draggable.asp and https://www.w3schools.com/html/html5_draganddrop.asp regarding) …

    function dragElement(elmnt) { // thanks to https://www.w3schools.com/howto/howto_js_draggable.asp
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
    } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    alert('Here');
    }

    function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
    }
    }

    function allowDrop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.preventDefault();
    }

    function drag(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.dataTransfer.setData("text", ev.target.id);
    }

    function doemail(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    var subjis=(document.getElementById('threport').innerText || document.getElementById('threport').contentWindow || document.getElementById('threport').contentDocument);
    a.href='mailto:?subject=' + encodeURIComponent(topicis) + '%20' + encodeURIComponent(subjis) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function dosms(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    a.href='sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function drop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    var ssrect=null, isemail=true, a=null;
    ssrect=document.getElementById('droppable').getBoundingClientRect();
    if (eval(ssrect.right - ev.clientX) < eval(ev.clientX - ssrect.left)) { isemail=false; }
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    if (isemail) {
    //a = document.createElement("a");
    //a.href='mailto:?subject=' + encodeURIComponent(document.getElementById('topic').innerHTML) + '%20Report%20of%20Inventory&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    doemail(data);
    } else if (!isemail) {
    //a = document.createElement("a");
    //a.href='sms:&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    dosms(data);
    } else {
    ev.target.appendChild(document.getElementById(data));
    }
    }

    … where the drop position tells us which “conduit” to go with

… and so, both are of some interest, we figure in a changed map_test.html Array and Map Tester web application you can also try below.

Did you know?

In Object Oriented Programming, methods (ie. object functions) can be named similarly with different argument patterns and/or return values, but now, with three functions in this current project we’ve coalesced this idea into single calls and used the Javascript undefined return for non-defined arguments as our way to “keep it brief” …

  • function askall(preenterall) { } … as above
  • function alteredstate(indemo, readd) { }
  • function addone(knownname, knownquantity) { }


Previous relevant Javascript Map Array Genericization Tutorial is shown below.

Javascript Map Array Genericization Tutorial

Javascript Map Array Genericization Tutorial

We think yesterday’s Javascript Map Array Primer Tutorial could benefit from …

  • aspects that make the Inventory aspects to the web application feel more like a “tool” …
  • aspects that make the Inventory aspects to the web application feel more “generic”

… and, you may notice, fixes for the way “Map.groupBy” functionality does not appear to work on the mobile platforms my iPhone has for web browsers …


var text="";

function thecall() {
var kk=0;

// Group by ok and low
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
try {
const result = Map.groupBy(fruits, myCallback);

// Display Results
try {
for (let x of result.get("ok")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
} catch(ebad) { }
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
try {
for (let x of result.get("low")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
console.log(result.get("ok"));
} catch(ebad) { }
} catch(overebad) {
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'ok') {
//alert(fruits[kk].name);
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
//alert('2:' + fruits[kk].name);
if (!m.has(fruits[kk].name)) {
//alert('3:' + fruits[kk].name);
m.set(fruits[kk].name, fruits[kk].quantity);
//alert('4:' + fruits[kk].name);
}
}
}
}
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'low') {
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
if (!m.has(fruits[kk].name)) {
m.set(fruits[kk].name, fruits[kk].quantity);
}
}
}
}

}

document.getElementById("demo").innerHTML = text;

}

With this in mind, we honed in on a “topic” concept, where yesterday’s “topic” would have been “Fruit”. There are two aspects …

  1. allow a contenteditable way for user to change the displayed (what used to be) hardcoding

    <span title='Double click to be able to enter CSV data' id=topic contenteditable=true onblur=beadjustable(); ondblclick=askall();>Fruit</span>

    … as well as …
  2. add ondblclick (ie. on double click) means by which a user can use a Javascript prompt window means by which they can enter all the CSV (ie. comma separated values) data for an Inventory application of the user’s choosing (including a means by which they can also enter the “topic” at the same time) …

    function askall() {
    var delall=false;
    var enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    beadjustable();
    }
    }

… in a changed map_test.html “proof of concept” Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Primer Tutorial is shown below.

Javascript Map Array Primer Tutorial

Javascript Map Array Primer Tutorial

We’ve got yet another “map” idea for you today, coming from the wooooorrrrlllllddd of Javascript clientside data structures, if you like.

We got onto this topic via reading https://www.w3schools.com/js/tryit.asp?filename=tryjs_map_groupby and https://medium.com/@sotoer/your-foreach-example-has-the-wrong-order-of-params-which-you-are-also-demonstrating-in-your-sample-42f5491b604e which both helped us enormously put together a rudimentary Fruit Inventory web application featuring …

  • array with structure

    // Create an Array
    const fruits = [
    {name:"apples", quantity:300},
    {name:"bananas", quantity:500},
    {name:"oranges", quantity:200},
    {name:"kiwi", quantity:150}
    ];
  • map object

    var m = new Map();
  • use of map.set() …

    function addone() {
    doadd=true;
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    doadd=false;
    beadjustable();
    }

    … and Map.groupBy()

    function thecall() {
    // Group by ok and low
    const result = Map.groupBy(fruits, myCallback);

    // Display Results
    let text ="These fruits are Ok: <br>";
    try {
    for (let x of result.get("ok")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    text += "<br>These fruits are low: <br>";
    try {
    for (let x of result.get("low")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    document.getElementById("demo").innerHTML = text;

    console.log(result.get("ok"));
    }
  • contenteditable=true

    function consolelog(inrec) {
    if (rspan == 0) {
    document.getElementById("tdname").innerHTML=inrec.split('value:')[1].split(' key:')[0].split(' map:')[0];
    document.getElementById("tdquantity").innerHTML=inrec.split('key:')[1].split(' value:')[0].split(' map:')[0];
    rspan=1;
    } else if (inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] == '') {
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    } else {
    tabletds+='<tr><td contenteditable=false id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    }
    //alert(inrec);
    if (doadd) {
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);></td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>0</td></tr>';
    rspan++;
    doadd=false;
    }
    }
  • array.push()

… in map_test.html “proof of concept” Array and Map Tester web application …

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


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


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


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


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


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


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

Javascript Map Array SQL Tutorial

Javascript Map Array SQL Tutorial

Javascript Map Array SQL Tutorial

Finishing off the SQL work start that yesterday’s Javascript Map Array Conditions Tutorial represents, today a user can follow the advice

xenterall=prompt(‘Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below where +-*^%/ (maths) and !<>= (conditions) and ~| (for ascending descending order). ‘ + String.fromCharCode(10) + ‘Examples …’ + String.fromCharCode(10) + ‘#1,3&2&4’ + String.fromCharCode(10) + ‘#4,2*3’ + String.fromCharCode(10) + ‘#1&4,3+2’ + String.fromCharCode(10) + ‘#1&4,3&2,2>100,|2‘, ”);

… to facilitate WHERE and ORDER BY processing foreshadowed yesterday.

The ORDER BY solution featured tailored Javascript sort functionality nuances …


function maybesort(rh) {
var recsare=[], newc='', ijk=0, exa='', zero=0, ipo=0;
headrec='';
if (eval('' + orderbys.length) > 0) {
recsare=rh.split(String.fromCharCode(10));
if (recsare[0].indexOf('0') == -1 && recsare[0].indexOf('1') == -1 && recsare[0].indexOf('2') == -1 && recsare[0].indexOf('3') == -1 && recsare[0].indexOf('4') == -1 && recsare[0].indexOf('5') == -1 && recsare[0].indexOf('6') == -1 && recsare[0].indexOf('7') == -1 && recsare[0].indexOf('8') == -1 && recsare[0].indexOf('9') == -1) {
headrec=recsare[0];
zero=1;
efields=headrec.replace(/\"/g,'').split(',');
for (var ke=0; ke<efields.length; ke++) {
eval('mappings.unshift({ from: "' + eval(ke + 1) + '", to: "' + efields[ke] + '"})');
}
document.getElementById('topic').innerHTML=headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1);
document.getElementById('thname').innerHTML=maybenotdefn(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[1].substring(1));
document.getElementById('thquantity').innerHTML=maybenotdefq(headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(0,1).toUpperCase() + headrec.replace(/^\"/g,'').substring(0).split('"')[0].split(',')[0].substring(1));
analwheres();
}


for (ipo=0; ipo<orderbys.length; ipo++) {


if (orderbys[ipo].indexOf('~1 ') != -1) {
recsare.sort();

} else if (orderbys[ipo].indexOf('|1 ') != -1) {
recsare.sort(function(x, y) {
if (y < x) {
return -1;
}
if (y > x) {
return 1;
}
return 0;
});

} else if (orderbys[ipo].indexOf('|') != -1) {
icol=eval(-1 + eval('' + orderbys[ipo].split('|')[1].split(' ')[0]));
//alert('icol=' + icol);
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
//alert('exa=' + exa);
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
//alert('is a number');
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return 1; }
if (x == headrec && y != headrec) { return -1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + y.split(',')[icol]) < eval('' + x.split(',')[icol])) {
return -1;
}
if (eval('' + y.split(',')[icol]) > eval('' + x.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (y.split(',')[icol] < x.split(',')[icol]) {
return -1;
}
if (y.split(',')[icol] > x.split(',')[icol]) {
return 1;
}
return 0;
});
}

} else if (orderbys[ipo].indexOf('~') != -1) {

icol=eval(-1 + eval('' + orderbys[ipo].split('~')[1].split(' ')[0]));
exa='' + rh.split(String.fromCharCode(10))[zero].split(',')[icol];
if (exa != '' && exa.replace(/0/g,'').replace(/2/g,'').replace(/3/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'').replace(/\-/g,'').replace(/\./g,'').trim() == '') {
recsare.sort(function(x, y) {
if (x != headrec && y == headrec) { return -1; }
if (x == headrec && y != headrec) { return 1; }
if (x == headrec && y == headrec) { return 0; }
if (eval('' + x.split(',')[icol]) < eval('' + y.split(',')[icol])) {
return -1;
}
if (eval('' + x.split(',')[icol]) > eval('' + y.split(',')[icol])) {
return 1;
}
return 0;
});
} else {
recsare.sort(function(x, y) {
if (x.split(',')[icol] < y.split(',')[icol]) {
return -1;
}
if (x.split(',')[icol] > y.split(',')[icol]) {
return 1;
}
return 0;
});
}

}


newc='';
if (headrec != '') {
newc+=headrec + String.fromCharCode(10);
}
for (ijk=0; ijk<recsare.length; ijk++) {
if (recsare[ijk] != headrec) {
newc+=recsare[ijk] + String.fromCharCode(10);
}
}
//alert(newc);
rh=newc;
}
}
//alert(rh);
return rh;
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Conditions Tutorial is shown below.

Javascript Map Array Conditions Tutorial

Javascript Map Array Conditions Tutorial

Onto yesterday’s Javascript Map Array Field Tutorial we wanted to extend functionality by starting on a “more than one day” project of thinking …

  • SQL … with it’s … SELECT … statements involving …
  • FROM … clause … representing the input (perhaps) CSV data source … filtered via …
  • WHERE … clauses, for sure … and pretty sure we can manage …
  • ORDER BY … record sorting

… people familiar with working with relative databases will understand.

So far we’re just doing the work to construct the scenario’s SQL “pseudo SELECT statement”. In doing this, we used a new mapping array that could end up looking like …

{from: ‘2’, to: ‘(Longitude+Latitude) as field2’}
{from: ‘4’, to: ‘name’}
{from: ‘3’, to: ‘longitude’}
{from: ‘2’, to: ‘latitude’}
{from: ‘1’, to: ‘country’}
{from: ‘1’, to: ‘Name’}
{from: ‘2’, to: ‘Quantity’}

… where we found building it up via the usual mapping.push() we would use to append data was some of the story, but it’s opposite number mapping.unshift() was really useful to prioritize a changing better to member data item into the mix, as the program flow progesses in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Field Tutorial is shown below.

Javascript Map Array Field Tutorial

Javascript Map Array Field Tutorial

The way the inhouse Javascript Map Array web application worked as of the day before yesterday’s Javascript Map Array Hashtag Tutorial involved …

  • a whole of file (or your entered string) processing of CSV data where the first two fields (comma separated) of records became the name,quantity data basis … but as all Spreadsheet afficianados will tell you, it can be very useful “to drill down” into fields (or “columns”, in Spreadsheet parlance) … so …
  • as of today’s work … well, we’ll let our “blurb”, coming off an H1 tag double click event, to try to explain it …

    var compositename='';
    var compositequantity='';
    var enterall='';

    function anal() {
    enterall=prompt('Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below. ' + String.fromCharCode(10) + String.fromCharCode(10) + 'Examples ...' + String.fromCharCode(10) + '#1,3&2&4' + String.fromCharCode(10) + '#4,2*3' + String.fromCharCode(10) + '#1&4,3+2', '');
    if (enterall.split('#')[0].indexOf(',') == -1 && enterall.trim() != '' && enterall.indexOf('~`~') == -1) {
    compositename='';
    compositequantity='';
    if (enterall.indexOf('#') != -1) {
    var compstuff=enterall.split('#')[1];
    enterall=enterall.split('#')[0];
    var csfs=compstuff.split(',');
    compositename=csfs[0];
    if (compositename != '') {
    if (eval(('' + compositename).split('&')[0].split('+')[0].split('/')[0].split('*')[0].split('-')[0].split('%')[0].split('^')[0]) > 1 && eval('' + csfs.length) <= 1) {
    compositequantity='1';
    } else if (eval('' + csfs.length) > 1) {
    compositequantity=csfs[1];
    }
    }
    }
    enterall='';
    }
    enterall='';
    }

… to allow for some simple mathematical operations (ie. + / – * % ^) of the right hand quantity data item, or concatenation (ie. &) on either left or right (delimited by , comma), as possibilities via user defined field (or “column”) numbering system (starting from 1) means.

Applied to our testing with country.csv here, we started getting scenarios where the Google Chart Geo Chart should turn into “markers mode”, and the statistical Google Chart Area/Bar/Column/Line Charts would have multiple Y axis items for the “name” data item X axis relationship.

More flexibility, we figure, in the extensively changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Hashtag Tutorial is shown below.

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Regular readers will know of our ever increasing fondness, out of webpage navigational ideas …

  • form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages but apt to cause error 414 due to data size restrictions) … or …
  • form method=POST URL navigation (suitable for server recipient webpages only, but able to handle much more data) … or …
  • hybrid arrangement that is essentially form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages) with error 414 avoided by most data forming the location.hash (client understood) hashtagged data

… for the last hashtagging arrangement when the data size precludes the first arrangement, and we see benefits regarding “a” “mailto:” and/or “sms:” sharing links becoming involved (rather than relying on any PHP server mail function calling).

Our Google Chart interfacing is no exception here, and yes, once we’ve completed our sweep of Google Chart inhouse functionality interfacers, on top of today’s …

… list we got keen to attend to today, with a most (when needed) strategy …

First “data” label value is method=GET
Rest of “data” value items are hashtagged

… (having the benefit that the intervention point is consistent and reliable) on top of yesterday’s Javascript Map Array Chart Tutorial, in this regard, as helper outerers for our changed map_test.html Array and Map Tester web application you can also try below, we’ll be able to further genericize Sharing and Collaboration Google Chart interfacing functionality when the amounts of data involved exceed server based (error 414) limits.

Along the way, testing on iOS mobile platforms, we were gobsmacked by the possibility of location.hash (ie. # hashtagging) not being recognized, always, at the recipient, and so a failsafe we introduced was to also store hashtagged data in a parent textbox the recipient can reference …

<?php echo ”

if (window.top) {
if (parent.document.getElementById('lhashis')) {
if (decodeURIComponent(('' + parent.document.getElementById('lhashis').value)).indexOf(',') != -1) {
location.hash=parent.document.getElementById('lhashis').value;
}
}
}

“; ?>

… even before “recipient document.body onload” timing, happily, to get around the restrictiveness of this location.hash lack of acceptance, at times.

Which brings us to …

Why is Geo Chart in that list above?

Well, it’s a bit unlikely, but it just so happens our best CSV file to hand, around here, contained ISO-3166 2 character country codes with a representative latitude and longitude (as you can see with, the now publicly shared, country.csv … thanks to Google) and this data is right up the alley of use by the Google Chart Geo Chart (which you might recall we had a different hashtag arrangement going on already …

… believe it or not, never causing any iOS mobile platform issues up to now … go figure!)

To get this “sharing of that CSV” to be any way useful, and illustrative, if you double click the “topic” word and get to the Javascript prompt window that follows, we tweak you to this, but if you enter …

https://www.rjmprogramming.com.au/HTMLCSS/country.csv

… at that prompt window, now, we’ll attempt an Ajax call of whatever URL you enter to try to glean data content to suit our …

label name to numerical quantity relationship

… this web application is hankering for.

And there, the amount of data (in size) is far too big for non-hybrid method=GET scenarios, and we need to turn to our new hybrid ideas to proceed with our quest to take over “Lower Middle Mordor South Lowlands as seen from Mirkwood“.

This may all bore, but believe me if you offer users a piece of functionality, they’ll want to push it to limits, and in that “push” could come most of your work, and concern, with regard to a project you are working on, so we figure it is best to cater for this before it is asked for.

TwoThree sentences ending in for? Okay, Grammarly, we give up!

Each Google Chart interfacer has individual nuances, but PHP code changes like below …

<?php

echo ' if (decodeURIComponent(("" + location.hash).replace(/^undefined/g,"")).trim().indexOf(",") != -1) { ' . "\n";
echo ' var xwert="data=google.visualization.arrayToDataTable([ [' . "'" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'" . '],"; ' . "\n";
echo " xwert+=\"" . str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata))))) . "\" + ('' + location.hash).replace(/^\#/g,'').replace(/\%20/g,'').replace(/\,\]/g,\",0\").replace(/\[\~/g,\"['\").replace(/\~\,/g,\"',\"); " . "\n";
echo ' xwert+=" ])"; xwert=xwert.replace(",,",","); ' . "\n";
echo ' eval(xwert); ' . "\n";
echo ' } else { ' . "\n";

echo ' data = google.visualization.arrayToDataTable([ ' . "\n";
echo " ['" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'] \n";
echo str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata)))));
echo " ]);\n";
echo " } \n";

?>

… typify our interventional strategy to make these improvements happen. Good ol’ (much maligned) eval … huh?! And good ol’ Javascript undefined bizzos! And good ol’ hashtagging! Aaaaaaaaaaal drink to all youse guys and gals (if one might be so forward, that is).


Previous relevant Javascript Map Array Chart Tutorial is shown below.

Javascript Map Array Chart Tutorial

Javascript Map Array Chart Tutorial

Does the data behind yesterday’s Javascript Map Array Import Tutorial remind you of anything? Relative database data? Spreadsheets?

That last one has lots of synergy, we reckon. And lots of us know, in spreadsheet software products like Microsoft Excel, once a …

  • spreadsheet is involved
  • charts are often offered as a graphical stand in display (to the tabular looking spreadsheet, that is)

And in this respect, looking back on our interfacing work to Google Charts when you have a label name to numerical quantity relationship two Google Chart types (we know of) are useful …

… and we’d like to offer some optional interfacing to these (to improve functionality, that is) … the Javascript for this leaning on the new …


function datait(oselv) {
var outv=oselv, kk=0, firstdelim='';
//alert(outv);
if (outv != '') {
if (oselv.indexOf('PHP/Pie') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
if (('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]').indexOf('-') == -1) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
}
} else if (oselv.indexOf('PHP/Histogram') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
//alert(outv);
} else if (oselv.indexOf('PHP/Geo') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=firstdelim + '%20[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]') + '%20';
firstdelim=',';
}
if (('' + outv).length > 600) { return toolong(outv.replace('&data=%20', '&data=%20#')); }
}
}
if (('' + outv).length > 600) {
document.getElementById('data').value=',' + outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='POST';
document.getElementById('myform').action=outv.split('?')[0] + '#pleasenolocationhref';
outv='./map_test.html';
//var xx=prompt(document.getElementById('myform').outerHTML,document.getElementById('myform').innerHTML);
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
} else if (2 == 2) {
document.getElementById('data').value=outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='GET';
document.getElementById('myform').action=outv.split('?')[0];
//outv='./map_test.html';
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
}
return outv;
}

function selit(osel) {
if (osel.value != '') {
geovalis=osel.value;
document.getElementById('defopt').innerText='Google Chart display of ... relevant ' + osel.value.split('PHP/')[1].split('/')[0].replace('Chart',' Chart') + ' below ...';
document.getElementById('dif').innerHTML='<br><br><a id=atop href="#myh1">Back to top ...</a><br><br><iframe name=myifis id=myifis src="' + datait(osel.value) + '" style="width:100%;height:700px;"></iframe>';
document.getElementById('dif').style.display='block';
}
osel.value='';
location.href='#atop';
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Import Tutorial is shown below.

Javascript Map Array Import Tutorial

Javascript Map Array Import Tutorial

Is it …

  • the extension of import capabilities … or …
  • the sharing capabilities

… of most interest in today’s work, extending that of yesterday’s Javascript Map Array Genericization Tutorial?

Well …

  • the extension of import capabilities …

    function askall(preenterall) {
    var isfirst=true;
    var delall=false;
    var enterall=('' + preenterall).replace(/^undefined$/g,'');
    if (enterall == '') {
    enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    } //else {
    //alert(enterall);
    //}
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(1);
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(2);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(3);
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(4);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(5);
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(6);
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(7);
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(8);
    if (isfirst && ((elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) < '0' || (elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) > '9')) {
    document.getElementById('topic').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thname').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thquantity').innerHTML=elines[ie].substring(0).split(',')[1].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[1].substring(1);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    isfirst=false;
    }
    beadjustable();
    }
    }

    function yesthreethree(restis) {
    if (restis.indexOf(';base64,') != -1) {
    var icontent=window.atob(restis.split(';base64,')[1]);
    if ((('' + icontent).trim() + ' ').replace(/^\[caption/g,'<').substring(0,1) == '<') {
    askall(extractContent(icontent,true));
    } else {
    askall(icontent);
    }
    } else {
    askall(restis);
    }
    }

    …asked for tweaks to our changed client_browsing.htm client side HTML and Javascript inhouse file browsing interfacer showing a “first time” scenario, for us with our “first cab off the rank” CSV (comma separated values) trial file …

    user@MacBook-Air htdocs % head -10 country.csv
    country,latitude,longitude,name // Thanks to https://developers.google.com/public-data/docs/canonical/countries_csv
    AD,42.546245,1.601554,Andorra
    AE,23.424076,53.847818,United Arab Emirates
    AF,33.93911,67.709953,Afghanistan
    AG,17.060816,-61.796428,Antigua and Barbuda
    AI,18.220554,-63.068615,Anguilla
    AL,41.153332,20.168331,Albania
    AM,40.069099,45.038189,Armenia
    AN,12.226079,-69.060087,Netherlands Antilles
    AO,-11.202692,17.873887,Angola
    user@MacBook-Air htdocs %

    … which is of interest … or …
  • the sharing capabilities, of the report, where we allow for the usual onclick of an emoji button fed through to “a” mailto: (email) or sms: (SMS) conduits to sharing, and for the first time, for us, a drag and drop way (we thank both https://www.w3schools.com/howto/howto_js_draggable.asp and https://www.w3schools.com/html/html5_draganddrop.asp regarding) …

    function dragElement(elmnt) { // thanks to https://www.w3schools.com/howto/howto_js_draggable.asp
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
    } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    alert('Here');
    }

    function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
    }
    }

    function allowDrop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.preventDefault();
    }

    function drag(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.dataTransfer.setData("text", ev.target.id);
    }

    function doemail(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    var subjis=(document.getElementById('threport').innerText || document.getElementById('threport').contentWindow || document.getElementById('threport').contentDocument);
    a.href='mailto:?subject=' + encodeURIComponent(topicis) + '%20' + encodeURIComponent(subjis) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function dosms(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    a.href='sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function drop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    var ssrect=null, isemail=true, a=null;
    ssrect=document.getElementById('droppable').getBoundingClientRect();
    if (eval(ssrect.right - ev.clientX) < eval(ev.clientX - ssrect.left)) { isemail=false; }
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    if (isemail) {
    //a = document.createElement("a");
    //a.href='mailto:?subject=' + encodeURIComponent(document.getElementById('topic').innerHTML) + '%20Report%20of%20Inventory&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    doemail(data);
    } else if (!isemail) {
    //a = document.createElement("a");
    //a.href='sms:&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    dosms(data);
    } else {
    ev.target.appendChild(document.getElementById(data));
    }
    }

    … where the drop position tells us which “conduit” to go with

… and so, both are of some interest, we figure in a changed map_test.html Array and Map Tester web application you can also try below.

Did you know?

In Object Oriented Programming, methods (ie. object functions) can be named similarly with different argument patterns and/or return values, but now, with three functions in this current project we’ve coalesced this idea into single calls and used the Javascript undefined return for non-defined arguments as our way to “keep it brief” …

  • function askall(preenterall) { } … as above
  • function alteredstate(indemo, readd) { }
  • function addone(knownname, knownquantity) { }


Previous relevant Javascript Map Array Genericization Tutorial is shown below.

Javascript Map Array Genericization Tutorial

Javascript Map Array Genericization Tutorial

We think yesterday’s Javascript Map Array Primer Tutorial could benefit from …

  • aspects that make the Inventory aspects to the web application feel more like a “tool” …
  • aspects that make the Inventory aspects to the web application feel more “generic”

… and, you may notice, fixes for the way “Map.groupBy” functionality does not appear to work on the mobile platforms my iPhone has for web browsers …


var text="";

function thecall() {
var kk=0;

// Group by ok and low
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
try {
const result = Map.groupBy(fruits, myCallback);

// Display Results
try {
for (let x of result.get("ok")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
} catch(ebad) { }
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
try {
for (let x of result.get("low")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
console.log(result.get("ok"));
} catch(ebad) { }
} catch(overebad) {
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'ok') {
//alert(fruits[kk].name);
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
//alert('2:' + fruits[kk].name);
if (!m.has(fruits[kk].name)) {
//alert('3:' + fruits[kk].name);
m.set(fruits[kk].name, fruits[kk].quantity);
//alert('4:' + fruits[kk].name);
}
}
}
}
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'low') {
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
if (!m.has(fruits[kk].name)) {
m.set(fruits[kk].name, fruits[kk].quantity);
}
}
}
}

}

document.getElementById("demo").innerHTML = text;

}

With this in mind, we honed in on a “topic” concept, where yesterday’s “topic” would have been “Fruit”. There are two aspects …

  1. allow a contenteditable way for user to change the displayed (what used to be) hardcoding

    <span title='Double click to be able to enter CSV data' id=topic contenteditable=true onblur=beadjustable(); ondblclick=askall();>Fruit</span>

    … as well as …
  2. add ondblclick (ie. on double click) means by which a user can use a Javascript prompt window means by which they can enter all the CSV (ie. comma separated values) data for an Inventory application of the user’s choosing (including a means by which they can also enter the “topic” at the same time) …

    function askall() {
    var delall=false;
    var enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    beadjustable();
    }
    }

… in a changed map_test.html “proof of concept” Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Primer Tutorial is shown below.

Javascript Map Array Primer Tutorial

Javascript Map Array Primer Tutorial

We’ve got yet another “map” idea for you today, coming from the wooooorrrrlllllddd of Javascript clientside data structures, if you like.

We got onto this topic via reading https://www.w3schools.com/js/tryit.asp?filename=tryjs_map_groupby and https://medium.com/@sotoer/your-foreach-example-has-the-wrong-order-of-params-which-you-are-also-demonstrating-in-your-sample-42f5491b604e which both helped us enormously put together a rudimentary Fruit Inventory web application featuring …

  • array with structure

    // Create an Array
    const fruits = [
    {name:"apples", quantity:300},
    {name:"bananas", quantity:500},
    {name:"oranges", quantity:200},
    {name:"kiwi", quantity:150}
    ];
  • map object

    var m = new Map();
  • use of map.set() …

    function addone() {
    doadd=true;
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    doadd=false;
    beadjustable();
    }

    … and Map.groupBy()

    function thecall() {
    // Group by ok and low
    const result = Map.groupBy(fruits, myCallback);

    // Display Results
    let text ="These fruits are Ok: <br>";
    try {
    for (let x of result.get("ok")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    text += "<br>These fruits are low: <br>";
    try {
    for (let x of result.get("low")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    document.getElementById("demo").innerHTML = text;

    console.log(result.get("ok"));
    }
  • contenteditable=true

    function consolelog(inrec) {
    if (rspan == 0) {
    document.getElementById("tdname").innerHTML=inrec.split('value:')[1].split(' key:')[0].split(' map:')[0];
    document.getElementById("tdquantity").innerHTML=inrec.split('key:')[1].split(' value:')[0].split(' map:')[0];
    rspan=1;
    } else if (inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] == '') {
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    } else {
    tabletds+='<tr><td contenteditable=false id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    }
    //alert(inrec);
    if (doadd) {
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);></td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>0</td></tr>';
    rspan++;
    doadd=false;
    }
    }
  • array.push()

… in map_test.html “proof of concept” Array and Map Tester web application …

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


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


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


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


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


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

Javascript Map Array Conditions Tutorial

Javascript Map Array Conditions Tutorial

Javascript Map Array Conditions Tutorial

Onto yesterday’s Javascript Map Array Field Tutorial we wanted to extend functionality by starting on a “more than one day” project of thinking …

  • SQL … with it’s … SELECT … statements involving …
  • FROM … clause … representing the input (perhaps) CSV data source … filtered via …
  • WHERE … clauses, for sure … and pretty sure we can manage …
  • ORDER BY … record sorting

… people familiar with working with relative databases will understand.

So far we’re just doing the work to construct the scenario’s SQL “pseudo SELECT statement”. In doing this, we used a new mapping array that could end up looking like …

{from: ‘2’, to: ‘(Longitude+Latitude) as field2’}
{from: ‘4’, to: ‘name’}
{from: ‘3’, to: ‘longitude’}
{from: ‘2’, to: ‘latitude’}
{from: ‘1’, to: ‘country’}
{from: ‘1’, to: ‘Name’}
{from: ‘2’, to: ‘Quantity’}

… where we found building it up via the usual mapping.push() we would use to append data was some of the story, but it’s opposite number mapping.unshift() was really useful to prioritize a changing better to member data item into the mix, as the program flow progesses in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Field Tutorial is shown below.

Javascript Map Array Field Tutorial

Javascript Map Array Field Tutorial

The way the inhouse Javascript Map Array web application worked as of the day before yesterday’s Javascript Map Array Hashtag Tutorial involved …

  • a whole of file (or your entered string) processing of CSV data where the first two fields (comma separated) of records became the name,quantity data basis … but as all Spreadsheet afficianados will tell you, it can be very useful “to drill down” into fields (or “columns”, in Spreadsheet parlance) … so …
  • as of today’s work … well, we’ll let our “blurb”, coming off an H1 tag double click event, to try to explain it …

    var compositename='';
    var compositequantity='';
    var enterall='';

    function anal() {
    enterall=prompt('Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below. ' + String.fromCharCode(10) + String.fromCharCode(10) + 'Examples ...' + String.fromCharCode(10) + '#1,3&2&4' + String.fromCharCode(10) + '#4,2*3' + String.fromCharCode(10) + '#1&4,3+2', '');
    if (enterall.split('#')[0].indexOf(',') == -1 && enterall.trim() != '' && enterall.indexOf('~`~') == -1) {
    compositename='';
    compositequantity='';
    if (enterall.indexOf('#') != -1) {
    var compstuff=enterall.split('#')[1];
    enterall=enterall.split('#')[0];
    var csfs=compstuff.split(',');
    compositename=csfs[0];
    if (compositename != '') {
    if (eval(('' + compositename).split('&')[0].split('+')[0].split('/')[0].split('*')[0].split('-')[0].split('%')[0].split('^')[0]) > 1 && eval('' + csfs.length) <= 1) {
    compositequantity='1';
    } else if (eval('' + csfs.length) > 1) {
    compositequantity=csfs[1];
    }
    }
    }
    enterall='';
    }
    enterall='';
    }

… to allow for some simple mathematical operations (ie. + / – * % ^) of the right hand quantity data item, or concatenation (ie. &) on either left or right (delimited by , comma), as possibilities via user defined field (or “column”) numbering system (starting from 1) means.

Applied to our testing with country.csv here, we started getting scenarios where the Google Chart Geo Chart should turn into “markers mode”, and the statistical Google Chart Area/Bar/Column/Line Charts would have multiple Y axis items for the “name” data item X axis relationship.

More flexibility, we figure, in the extensively changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Hashtag Tutorial is shown below.

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Regular readers will know of our ever increasing fondness, out of webpage navigational ideas …

  • form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages but apt to cause error 414 due to data size restrictions) … or …
  • form method=POST URL navigation (suitable for server recipient webpages only, but able to handle much more data) … or …
  • hybrid arrangement that is essentially form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages) with error 414 avoided by most data forming the location.hash (client understood) hashtagged data

… for the last hashtagging arrangement when the data size precludes the first arrangement, and we see benefits regarding “a” “mailto:” and/or “sms:” sharing links becoming involved (rather than relying on any PHP server mail function calling).

Our Google Chart interfacing is no exception here, and yes, once we’ve completed our sweep of Google Chart inhouse functionality interfacers, on top of today’s …

… list we got keen to attend to today, with a most (when needed) strategy …

First “data” label value is method=GET
Rest of “data” value items are hashtagged

… (having the benefit that the intervention point is consistent and reliable) on top of yesterday’s Javascript Map Array Chart Tutorial, in this regard, as helper outerers for our changed map_test.html Array and Map Tester web application you can also try below, we’ll be able to further genericize Sharing and Collaboration Google Chart interfacing functionality when the amounts of data involved exceed server based (error 414) limits.

Along the way, testing on iOS mobile platforms, we were gobsmacked by the possibility of location.hash (ie. # hashtagging) not being recognized, always, at the recipient, and so a failsafe we introduced was to also store hashtagged data in a parent textbox the recipient can reference …

<?php echo ”

if (window.top) {
if (parent.document.getElementById('lhashis')) {
if (decodeURIComponent(('' + parent.document.getElementById('lhashis').value)).indexOf(',') != -1) {
location.hash=parent.document.getElementById('lhashis').value;
}
}
}

“; ?>

… even before “recipient document.body onload” timing, happily, to get around the restrictiveness of this location.hash lack of acceptance, at times.

Which brings us to …

Why is Geo Chart in that list above?

Well, it’s a bit unlikely, but it just so happens our best CSV file to hand, around here, contained ISO-3166 2 character country codes with a representative latitude and longitude (as you can see with, the now publicly shared, country.csv … thanks to Google) and this data is right up the alley of use by the Google Chart Geo Chart (which you might recall we had a different hashtag arrangement going on already …

… believe it or not, never causing any iOS mobile platform issues up to now … go figure!)

To get this “sharing of that CSV” to be any way useful, and illustrative, if you double click the “topic” word and get to the Javascript prompt window that follows, we tweak you to this, but if you enter …

https://www.rjmprogramming.com.au/HTMLCSS/country.csv

… at that prompt window, now, we’ll attempt an Ajax call of whatever URL you enter to try to glean data content to suit our …

label name to numerical quantity relationship

… this web application is hankering for.

And there, the amount of data (in size) is far too big for non-hybrid method=GET scenarios, and we need to turn to our new hybrid ideas to proceed with our quest to take over “Lower Middle Mordor South Lowlands as seen from Mirkwood“.

This may all bore, but believe me if you offer users a piece of functionality, they’ll want to push it to limits, and in that “push” could come most of your work, and concern, with regard to a project you are working on, so we figure it is best to cater for this before it is asked for.

TwoThree sentences ending in for? Okay, Grammarly, we give up!

Each Google Chart interfacer has individual nuances, but PHP code changes like below …

<?php

echo ' if (decodeURIComponent(("" + location.hash).replace(/^undefined/g,"")).trim().indexOf(",") != -1) { ' . "\n";
echo ' var xwert="data=google.visualization.arrayToDataTable([ [' . "'" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'" . '],"; ' . "\n";
echo " xwert+=\"" . str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata))))) . "\" + ('' + location.hash).replace(/^\#/g,'').replace(/\%20/g,'').replace(/\,\]/g,\",0\").replace(/\[\~/g,\"['\").replace(/\~\,/g,\"',\"); " . "\n";
echo ' xwert+=" ])"; xwert=xwert.replace(",,",","); ' . "\n";
echo ' eval(xwert); ' . "\n";
echo ' } else { ' . "\n";

echo ' data = google.visualization.arrayToDataTable([ ' . "\n";
echo " ['" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'] \n";
echo str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata)))));
echo " ]);\n";
echo " } \n";

?>

… typify our interventional strategy to make these improvements happen. Good ol’ (much maligned) eval … huh?! And good ol’ Javascript undefined bizzos! And good ol’ hashtagging! Aaaaaaaaaaal drink to all youse guys and gals (if one might be so forward, that is).


Previous relevant Javascript Map Array Chart Tutorial is shown below.

Javascript Map Array Chart Tutorial

Javascript Map Array Chart Tutorial

Does the data behind yesterday’s Javascript Map Array Import Tutorial remind you of anything? Relative database data? Spreadsheets?

That last one has lots of synergy, we reckon. And lots of us know, in spreadsheet software products like Microsoft Excel, once a …

  • spreadsheet is involved
  • charts are often offered as a graphical stand in display (to the tabular looking spreadsheet, that is)

And in this respect, looking back on our interfacing work to Google Charts when you have a label name to numerical quantity relationship two Google Chart types (we know of) are useful …

… and we’d like to offer some optional interfacing to these (to improve functionality, that is) … the Javascript for this leaning on the new …


function datait(oselv) {
var outv=oselv, kk=0, firstdelim='';
//alert(outv);
if (outv != '') {
if (oselv.indexOf('PHP/Pie') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
if (('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]').indexOf('-') == -1) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
}
} else if (oselv.indexOf('PHP/Histogram') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
//alert(outv);
} else if (oselv.indexOf('PHP/Geo') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=firstdelim + '%20[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]') + '%20';
firstdelim=',';
}
if (('' + outv).length > 600) { return toolong(outv.replace('&data=%20', '&data=%20#')); }
}
}
if (('' + outv).length > 600) {
document.getElementById('data').value=',' + outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='POST';
document.getElementById('myform').action=outv.split('?')[0] + '#pleasenolocationhref';
outv='./map_test.html';
//var xx=prompt(document.getElementById('myform').outerHTML,document.getElementById('myform').innerHTML);
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
} else if (2 == 2) {
document.getElementById('data').value=outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='GET';
document.getElementById('myform').action=outv.split('?')[0];
//outv='./map_test.html';
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
}
return outv;
}

function selit(osel) {
if (osel.value != '') {
geovalis=osel.value;
document.getElementById('defopt').innerText='Google Chart display of ... relevant ' + osel.value.split('PHP/')[1].split('/')[0].replace('Chart',' Chart') + ' below ...';
document.getElementById('dif').innerHTML='<br><br><a id=atop href="#myh1">Back to top ...</a><br><br><iframe name=myifis id=myifis src="' + datait(osel.value) + '" style="width:100%;height:700px;"></iframe>';
document.getElementById('dif').style.display='block';
}
osel.value='';
location.href='#atop';
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Import Tutorial is shown below.

Javascript Map Array Import Tutorial

Javascript Map Array Import Tutorial

Is it …

  • the extension of import capabilities … or …
  • the sharing capabilities

… of most interest in today’s work, extending that of yesterday’s Javascript Map Array Genericization Tutorial?

Well …

  • the extension of import capabilities …

    function askall(preenterall) {
    var isfirst=true;
    var delall=false;
    var enterall=('' + preenterall).replace(/^undefined$/g,'');
    if (enterall == '') {
    enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    } //else {
    //alert(enterall);
    //}
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(1);
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(2);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(3);
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(4);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(5);
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(6);
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(7);
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(8);
    if (isfirst && ((elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) < '0' || (elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) > '9')) {
    document.getElementById('topic').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thname').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thquantity').innerHTML=elines[ie].substring(0).split(',')[1].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[1].substring(1);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    isfirst=false;
    }
    beadjustable();
    }
    }

    function yesthreethree(restis) {
    if (restis.indexOf(';base64,') != -1) {
    var icontent=window.atob(restis.split(';base64,')[1]);
    if ((('' + icontent).trim() + ' ').replace(/^\[caption/g,'<').substring(0,1) == '<') {
    askall(extractContent(icontent,true));
    } else {
    askall(icontent);
    }
    } else {
    askall(restis);
    }
    }

    …asked for tweaks to our changed client_browsing.htm client side HTML and Javascript inhouse file browsing interfacer showing a “first time” scenario, for us with our “first cab off the rank” CSV (comma separated values) trial file …

    user@MacBook-Air htdocs % head -10 country.csv
    country,latitude,longitude,name // Thanks to https://developers.google.com/public-data/docs/canonical/countries_csv
    AD,42.546245,1.601554,Andorra
    AE,23.424076,53.847818,United Arab Emirates
    AF,33.93911,67.709953,Afghanistan
    AG,17.060816,-61.796428,Antigua and Barbuda
    AI,18.220554,-63.068615,Anguilla
    AL,41.153332,20.168331,Albania
    AM,40.069099,45.038189,Armenia
    AN,12.226079,-69.060087,Netherlands Antilles
    AO,-11.202692,17.873887,Angola
    user@MacBook-Air htdocs %

    … which is of interest … or …
  • the sharing capabilities, of the report, where we allow for the usual onclick of an emoji button fed through to “a” mailto: (email) or sms: (SMS) conduits to sharing, and for the first time, for us, a drag and drop way (we thank both https://www.w3schools.com/howto/howto_js_draggable.asp and https://www.w3schools.com/html/html5_draganddrop.asp regarding) …

    function dragElement(elmnt) { // thanks to https://www.w3schools.com/howto/howto_js_draggable.asp
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
    } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    alert('Here');
    }

    function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
    }
    }

    function allowDrop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.preventDefault();
    }

    function drag(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.dataTransfer.setData("text", ev.target.id);
    }

    function doemail(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    var subjis=(document.getElementById('threport').innerText || document.getElementById('threport').contentWindow || document.getElementById('threport').contentDocument);
    a.href='mailto:?subject=' + encodeURIComponent(topicis) + '%20' + encodeURIComponent(subjis) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function dosms(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    a.href='sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function drop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    var ssrect=null, isemail=true, a=null;
    ssrect=document.getElementById('droppable').getBoundingClientRect();
    if (eval(ssrect.right - ev.clientX) < eval(ev.clientX - ssrect.left)) { isemail=false; }
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    if (isemail) {
    //a = document.createElement("a");
    //a.href='mailto:?subject=' + encodeURIComponent(document.getElementById('topic').innerHTML) + '%20Report%20of%20Inventory&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    doemail(data);
    } else if (!isemail) {
    //a = document.createElement("a");
    //a.href='sms:&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    dosms(data);
    } else {
    ev.target.appendChild(document.getElementById(data));
    }
    }

    … where the drop position tells us which “conduit” to go with

… and so, both are of some interest, we figure in a changed map_test.html Array and Map Tester web application you can also try below.

Did you know?

In Object Oriented Programming, methods (ie. object functions) can be named similarly with different argument patterns and/or return values, but now, with three functions in this current project we’ve coalesced this idea into single calls and used the Javascript undefined return for non-defined arguments as our way to “keep it brief” …

  • function askall(preenterall) { } … as above
  • function alteredstate(indemo, readd) { }
  • function addone(knownname, knownquantity) { }


Previous relevant Javascript Map Array Genericization Tutorial is shown below.

Javascript Map Array Genericization Tutorial

Javascript Map Array Genericization Tutorial

We think yesterday’s Javascript Map Array Primer Tutorial could benefit from …

  • aspects that make the Inventory aspects to the web application feel more like a “tool” …
  • aspects that make the Inventory aspects to the web application feel more “generic”

… and, you may notice, fixes for the way “Map.groupBy” functionality does not appear to work on the mobile platforms my iPhone has for web browsers …


var text="";

function thecall() {
var kk=0;

// Group by ok and low
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
try {
const result = Map.groupBy(fruits, myCallback);

// Display Results
try {
for (let x of result.get("ok")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
} catch(ebad) { }
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
try {
for (let x of result.get("low")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
console.log(result.get("ok"));
} catch(ebad) { }
} catch(overebad) {
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'ok') {
//alert(fruits[kk].name);
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
//alert('2:' + fruits[kk].name);
if (!m.has(fruits[kk].name)) {
//alert('3:' + fruits[kk].name);
m.set(fruits[kk].name, fruits[kk].quantity);
//alert('4:' + fruits[kk].name);
}
}
}
}
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'low') {
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
if (!m.has(fruits[kk].name)) {
m.set(fruits[kk].name, fruits[kk].quantity);
}
}
}
}

}

document.getElementById("demo").innerHTML = text;

}

With this in mind, we honed in on a “topic” concept, where yesterday’s “topic” would have been “Fruit”. There are two aspects …

  1. allow a contenteditable way for user to change the displayed (what used to be) hardcoding

    <span title='Double click to be able to enter CSV data' id=topic contenteditable=true onblur=beadjustable(); ondblclick=askall();>Fruit</span>

    … as well as …
  2. add ondblclick (ie. on double click) means by which a user can use a Javascript prompt window means by which they can enter all the CSV (ie. comma separated values) data for an Inventory application of the user’s choosing (including a means by which they can also enter the “topic” at the same time) …

    function askall() {
    var delall=false;
    var enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    beadjustable();
    }
    }

… in a changed map_test.html “proof of concept” Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Primer Tutorial is shown below.

Javascript Map Array Primer Tutorial

Javascript Map Array Primer Tutorial

We’ve got yet another “map” idea for you today, coming from the wooooorrrrlllllddd of Javascript clientside data structures, if you like.

We got onto this topic via reading https://www.w3schools.com/js/tryit.asp?filename=tryjs_map_groupby and https://medium.com/@sotoer/your-foreach-example-has-the-wrong-order-of-params-which-you-are-also-demonstrating-in-your-sample-42f5491b604e which both helped us enormously put together a rudimentary Fruit Inventory web application featuring …

  • array with structure

    // Create an Array
    const fruits = [
    {name:"apples", quantity:300},
    {name:"bananas", quantity:500},
    {name:"oranges", quantity:200},
    {name:"kiwi", quantity:150}
    ];
  • map object

    var m = new Map();
  • use of map.set() …

    function addone() {
    doadd=true;
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    doadd=false;
    beadjustable();
    }

    … and Map.groupBy()

    function thecall() {
    // Group by ok and low
    const result = Map.groupBy(fruits, myCallback);

    // Display Results
    let text ="These fruits are Ok: <br>";
    try {
    for (let x of result.get("ok")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    text += "<br>These fruits are low: <br>";
    try {
    for (let x of result.get("low")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    document.getElementById("demo").innerHTML = text;

    console.log(result.get("ok"));
    }
  • contenteditable=true

    function consolelog(inrec) {
    if (rspan == 0) {
    document.getElementById("tdname").innerHTML=inrec.split('value:')[1].split(' key:')[0].split(' map:')[0];
    document.getElementById("tdquantity").innerHTML=inrec.split('key:')[1].split(' value:')[0].split(' map:')[0];
    rspan=1;
    } else if (inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] == '') {
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    } else {
    tabletds+='<tr><td contenteditable=false id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    }
    //alert(inrec);
    if (doadd) {
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);></td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>0</td></tr>';
    rspan++;
    doadd=false;
    }
    }
  • array.push()

… in map_test.html “proof of concept” Array and Map Tester web application …

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


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


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


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


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

Javascript Map Array Field Tutorial

Javascript Map Array Field Tutorial

Javascript Map Array Field Tutorial

The way the inhouse Javascript Map Array web application worked as of the day before yesterday’s Javascript Map Array Hashtag Tutorial involved …

  • a whole of file (or your entered string) processing of CSV data where the first two fields (comma separated) of records became the name,quantity data basis … but as all Spreadsheet afficianados will tell you, it can be very useful “to drill down” into fields (or “columns”, in Spreadsheet parlance) … so …
  • as of today’s work … well, we’ll let our “blurb”, coming off an H1 tag double click event, to try to explain it …

    var compositename='';
    var compositequantity='';
    var enterall='';

    function anal() {
    enterall=prompt('Optionally enter a # (hashtag) delimited composite field scenario to apply for next input data (perhaps CSV) file application, such as in examples below. ' + String.fromCharCode(10) + String.fromCharCode(10) + 'Examples ...' + String.fromCharCode(10) + '#1,3&2&4' + String.fromCharCode(10) + '#4,2*3' + String.fromCharCode(10) + '#1&4,3+2', '');
    if (enterall.split('#')[0].indexOf(',') == -1 && enterall.trim() != '' && enterall.indexOf('~`~') == -1) {
    compositename='';
    compositequantity='';
    if (enterall.indexOf('#') != -1) {
    var compstuff=enterall.split('#')[1];
    enterall=enterall.split('#')[0];
    var csfs=compstuff.split(',');
    compositename=csfs[0];
    if (compositename != '') {
    if (eval(('' + compositename).split('&')[0].split('+')[0].split('/')[0].split('*')[0].split('-')[0].split('%')[0].split('^')[0]) > 1 && eval('' + csfs.length) <= 1) {
    compositequantity='1';
    } else if (eval('' + csfs.length) > 1) {
    compositequantity=csfs[1];
    }
    }
    }
    enterall='';
    }
    enterall='';
    }

… to allow for some simple mathematical operations (ie. + / – * % ^) of the right hand quantity data item, or concatenation (ie. &) on either left or right (delimited by , comma), as possibilities via user defined field (or “column”) numbering system (starting from 1) means.

Applied to our testing with country.csv here, we started getting scenarios where the Google Chart Geo Chart should turn into “markers mode”, and the statistical Google Chart Area/Bar/Column/Line Charts would have multiple Y axis items for the “name” data item X axis relationship.

More flexibility, we figure, in the extensively changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Hashtag Tutorial is shown below.

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Regular readers will know of our ever increasing fondness, out of webpage navigational ideas …

  • form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages but apt to cause error 414 due to data size restrictions) … or …
  • form method=POST URL navigation (suitable for server recipient webpages only, but able to handle much more data) … or …
  • hybrid arrangement that is essentially form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages) with error 414 avoided by most data forming the location.hash (client understood) hashtagged data

… for the last hashtagging arrangement when the data size precludes the first arrangement, and we see benefits regarding “a” “mailto:” and/or “sms:” sharing links becoming involved (rather than relying on any PHP server mail function calling).

Our Google Chart interfacing is no exception here, and yes, once we’ve completed our sweep of Google Chart inhouse functionality interfacers, on top of today’s …

… list we got keen to attend to today, with a most (when needed) strategy …

First “data” label value is method=GET
Rest of “data” value items are hashtagged

… (having the benefit that the intervention point is consistent and reliable) on top of yesterday’s Javascript Map Array Chart Tutorial, in this regard, as helper outerers for our changed map_test.html Array and Map Tester web application you can also try below, we’ll be able to further genericize Sharing and Collaboration Google Chart interfacing functionality when the amounts of data involved exceed server based (error 414) limits.

Along the way, testing on iOS mobile platforms, we were gobsmacked by the possibility of location.hash (ie. # hashtagging) not being recognized, always, at the recipient, and so a failsafe we introduced was to also store hashtagged data in a parent textbox the recipient can reference …

<?php echo ”

if (window.top) {
if (parent.document.getElementById('lhashis')) {
if (decodeURIComponent(('' + parent.document.getElementById('lhashis').value)).indexOf(',') != -1) {
location.hash=parent.document.getElementById('lhashis').value;
}
}
}

“; ?>

… even before “recipient document.body onload” timing, happily, to get around the restrictiveness of this location.hash lack of acceptance, at times.

Which brings us to …

Why is Geo Chart in that list above?

Well, it’s a bit unlikely, but it just so happens our best CSV file to hand, around here, contained ISO-3166 2 character country codes with a representative latitude and longitude (as you can see with, the now publicly shared, country.csv … thanks to Google) and this data is right up the alley of use by the Google Chart Geo Chart (which you might recall we had a different hashtag arrangement going on already …

… believe it or not, never causing any iOS mobile platform issues up to now … go figure!)

To get this “sharing of that CSV” to be any way useful, and illustrative, if you double click the “topic” word and get to the Javascript prompt window that follows, we tweak you to this, but if you enter …

https://www.rjmprogramming.com.au/HTMLCSS/country.csv

… at that prompt window, now, we’ll attempt an Ajax call of whatever URL you enter to try to glean data content to suit our …

label name to numerical quantity relationship

… this web application is hankering for.

And there, the amount of data (in size) is far too big for non-hybrid method=GET scenarios, and we need to turn to our new hybrid ideas to proceed with our quest to take over “Lower Middle Mordor South Lowlands as seen from Mirkwood“.

This may all bore, but believe me if you offer users a piece of functionality, they’ll want to push it to limits, and in that “push” could come most of your work, and concern, with regard to a project you are working on, so we figure it is best to cater for this before it is asked for.

TwoThree sentences ending in for? Okay, Grammarly, we give up!

Each Google Chart interfacer has individual nuances, but PHP code changes like below …

<?php

echo ' if (decodeURIComponent(("" + location.hash).replace(/^undefined/g,"")).trim().indexOf(",") != -1) { ' . "\n";
echo ' var xwert="data=google.visualization.arrayToDataTable([ [' . "'" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'" . '],"; ' . "\n";
echo " xwert+=\"" . str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata))))) . "\" + ('' + location.hash).replace(/^\#/g,'').replace(/\%20/g,'').replace(/\,\]/g,\",0\").replace(/\[\~/g,\"['\").replace(/\~\,/g,\"',\"); " . "\n";
echo ' xwert+=" ])"; xwert=xwert.replace(",,",","); ' . "\n";
echo ' eval(xwert); ' . "\n";
echo ' } else { ' . "\n";

echo ' data = google.visualization.arrayToDataTable([ ' . "\n";
echo " ['" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'] \n";
echo str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata)))));
echo " ]);\n";
echo " } \n";

?>

… typify our interventional strategy to make these improvements happen. Good ol’ (much maligned) eval … huh?! And good ol’ Javascript undefined bizzos! And good ol’ hashtagging! Aaaaaaaaaaal drink to all youse guys and gals (if one might be so forward, that is).


Previous relevant Javascript Map Array Chart Tutorial is shown below.

Javascript Map Array Chart Tutorial

Javascript Map Array Chart Tutorial

Does the data behind yesterday’s Javascript Map Array Import Tutorial remind you of anything? Relative database data? Spreadsheets?

That last one has lots of synergy, we reckon. And lots of us know, in spreadsheet software products like Microsoft Excel, once a …

  • spreadsheet is involved
  • charts are often offered as a graphical stand in display (to the tabular looking spreadsheet, that is)

And in this respect, looking back on our interfacing work to Google Charts when you have a label name to numerical quantity relationship two Google Chart types (we know of) are useful …

… and we’d like to offer some optional interfacing to these (to improve functionality, that is) … the Javascript for this leaning on the new …


function datait(oselv) {
var outv=oselv, kk=0, firstdelim='';
//alert(outv);
if (outv != '') {
if (oselv.indexOf('PHP/Pie') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
if (('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]').indexOf('-') == -1) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
}
} else if (oselv.indexOf('PHP/Histogram') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
//alert(outv);
} else if (oselv.indexOf('PHP/Geo') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=firstdelim + '%20[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]') + '%20';
firstdelim=',';
}
if (('' + outv).length > 600) { return toolong(outv.replace('&data=%20', '&data=%20#')); }
}
}
if (('' + outv).length > 600) {
document.getElementById('data').value=',' + outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='POST';
document.getElementById('myform').action=outv.split('?')[0] + '#pleasenolocationhref';
outv='./map_test.html';
//var xx=prompt(document.getElementById('myform').outerHTML,document.getElementById('myform').innerHTML);
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
} else if (2 == 2) {
document.getElementById('data').value=outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='GET';
document.getElementById('myform').action=outv.split('?')[0];
//outv='./map_test.html';
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
}
return outv;
}

function selit(osel) {
if (osel.value != '') {
geovalis=osel.value;
document.getElementById('defopt').innerText='Google Chart display of ... relevant ' + osel.value.split('PHP/')[1].split('/')[0].replace('Chart',' Chart') + ' below ...';
document.getElementById('dif').innerHTML='<br><br><a id=atop href="#myh1">Back to top ...</a><br><br><iframe name=myifis id=myifis src="' + datait(osel.value) + '" style="width:100%;height:700px;"></iframe>';
document.getElementById('dif').style.display='block';
}
osel.value='';
location.href='#atop';
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Import Tutorial is shown below.

Javascript Map Array Import Tutorial

Javascript Map Array Import Tutorial

Is it …

  • the extension of import capabilities … or …
  • the sharing capabilities

… of most interest in today’s work, extending that of yesterday’s Javascript Map Array Genericization Tutorial?

Well …

  • the extension of import capabilities …

    function askall(preenterall) {
    var isfirst=true;
    var delall=false;
    var enterall=('' + preenterall).replace(/^undefined$/g,'');
    if (enterall == '') {
    enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    } //else {
    //alert(enterall);
    //}
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(1);
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(2);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(3);
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(4);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(5);
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(6);
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(7);
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(8);
    if (isfirst && ((elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) < '0' || (elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) > '9')) {
    document.getElementById('topic').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thname').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thquantity').innerHTML=elines[ie].substring(0).split(',')[1].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[1].substring(1);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    isfirst=false;
    }
    beadjustable();
    }
    }

    function yesthreethree(restis) {
    if (restis.indexOf(';base64,') != -1) {
    var icontent=window.atob(restis.split(';base64,')[1]);
    if ((('' + icontent).trim() + ' ').replace(/^\[caption/g,'<').substring(0,1) == '<') {
    askall(extractContent(icontent,true));
    } else {
    askall(icontent);
    }
    } else {
    askall(restis);
    }
    }

    …asked for tweaks to our changed client_browsing.htm client side HTML and Javascript inhouse file browsing interfacer showing a “first time” scenario, for us with our “first cab off the rank” CSV (comma separated values) trial file …

    user@MacBook-Air htdocs % head -10 country.csv
    country,latitude,longitude,name // Thanks to https://developers.google.com/public-data/docs/canonical/countries_csv
    AD,42.546245,1.601554,Andorra
    AE,23.424076,53.847818,United Arab Emirates
    AF,33.93911,67.709953,Afghanistan
    AG,17.060816,-61.796428,Antigua and Barbuda
    AI,18.220554,-63.068615,Anguilla
    AL,41.153332,20.168331,Albania
    AM,40.069099,45.038189,Armenia
    AN,12.226079,-69.060087,Netherlands Antilles
    AO,-11.202692,17.873887,Angola
    user@MacBook-Air htdocs %

    … which is of interest … or …
  • the sharing capabilities, of the report, where we allow for the usual onclick of an emoji button fed through to “a” mailto: (email) or sms: (SMS) conduits to sharing, and for the first time, for us, a drag and drop way (we thank both https://www.w3schools.com/howto/howto_js_draggable.asp and https://www.w3schools.com/html/html5_draganddrop.asp regarding) …

    function dragElement(elmnt) { // thanks to https://www.w3schools.com/howto/howto_js_draggable.asp
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
    } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    alert('Here');
    }

    function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
    }
    }

    function allowDrop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.preventDefault();
    }

    function drag(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.dataTransfer.setData("text", ev.target.id);
    }

    function doemail(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    var subjis=(document.getElementById('threport').innerText || document.getElementById('threport').contentWindow || document.getElementById('threport').contentDocument);
    a.href='mailto:?subject=' + encodeURIComponent(topicis) + '%20' + encodeURIComponent(subjis) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function dosms(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    a.href='sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function drop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    var ssrect=null, isemail=true, a=null;
    ssrect=document.getElementById('droppable').getBoundingClientRect();
    if (eval(ssrect.right - ev.clientX) < eval(ev.clientX - ssrect.left)) { isemail=false; }
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    if (isemail) {
    //a = document.createElement("a");
    //a.href='mailto:?subject=' + encodeURIComponent(document.getElementById('topic').innerHTML) + '%20Report%20of%20Inventory&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    doemail(data);
    } else if (!isemail) {
    //a = document.createElement("a");
    //a.href='sms:&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    dosms(data);
    } else {
    ev.target.appendChild(document.getElementById(data));
    }
    }

    … where the drop position tells us which “conduit” to go with

… and so, both are of some interest, we figure in a changed map_test.html Array and Map Tester web application you can also try below.

Did you know?

In Object Oriented Programming, methods (ie. object functions) can be named similarly with different argument patterns and/or return values, but now, with three functions in this current project we’ve coalesced this idea into single calls and used the Javascript undefined return for non-defined arguments as our way to “keep it brief” …

  • function askall(preenterall) { } … as above
  • function alteredstate(indemo, readd) { }
  • function addone(knownname, knownquantity) { }


Previous relevant Javascript Map Array Genericization Tutorial is shown below.

Javascript Map Array Genericization Tutorial

Javascript Map Array Genericization Tutorial

We think yesterday’s Javascript Map Array Primer Tutorial could benefit from …

  • aspects that make the Inventory aspects to the web application feel more like a “tool” …
  • aspects that make the Inventory aspects to the web application feel more “generic”

… and, you may notice, fixes for the way “Map.groupBy” functionality does not appear to work on the mobile platforms my iPhone has for web browsers …


var text="";

function thecall() {
var kk=0;

// Group by ok and low
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
try {
const result = Map.groupBy(fruits, myCallback);

// Display Results
try {
for (let x of result.get("ok")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
} catch(ebad) { }
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
try {
for (let x of result.get("low")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
console.log(result.get("ok"));
} catch(ebad) { }
} catch(overebad) {
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'ok') {
//alert(fruits[kk].name);
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
//alert('2:' + fruits[kk].name);
if (!m.has(fruits[kk].name)) {
//alert('3:' + fruits[kk].name);
m.set(fruits[kk].name, fruits[kk].quantity);
//alert('4:' + fruits[kk].name);
}
}
}
}
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'low') {
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
if (!m.has(fruits[kk].name)) {
m.set(fruits[kk].name, fruits[kk].quantity);
}
}
}
}

}

document.getElementById("demo").innerHTML = text;

}

With this in mind, we honed in on a “topic” concept, where yesterday’s “topic” would have been “Fruit”. There are two aspects …

  1. allow a contenteditable way for user to change the displayed (what used to be) hardcoding

    <span title='Double click to be able to enter CSV data' id=topic contenteditable=true onblur=beadjustable(); ondblclick=askall();>Fruit</span>

    … as well as …
  2. add ondblclick (ie. on double click) means by which a user can use a Javascript prompt window means by which they can enter all the CSV (ie. comma separated values) data for an Inventory application of the user’s choosing (including a means by which they can also enter the “topic” at the same time) …

    function askall() {
    var delall=false;
    var enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    beadjustable();
    }
    }

… in a changed map_test.html “proof of concept” Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Primer Tutorial is shown below.

Javascript Map Array Primer Tutorial

Javascript Map Array Primer Tutorial

We’ve got yet another “map” idea for you today, coming from the wooooorrrrlllllddd of Javascript clientside data structures, if you like.

We got onto this topic via reading https://www.w3schools.com/js/tryit.asp?filename=tryjs_map_groupby and https://medium.com/@sotoer/your-foreach-example-has-the-wrong-order-of-params-which-you-are-also-demonstrating-in-your-sample-42f5491b604e which both helped us enormously put together a rudimentary Fruit Inventory web application featuring …

  • array with structure

    // Create an Array
    const fruits = [
    {name:"apples", quantity:300},
    {name:"bananas", quantity:500},
    {name:"oranges", quantity:200},
    {name:"kiwi", quantity:150}
    ];
  • map object

    var m = new Map();
  • use of map.set() …

    function addone() {
    doadd=true;
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    doadd=false;
    beadjustable();
    }

    … and Map.groupBy()

    function thecall() {
    // Group by ok and low
    const result = Map.groupBy(fruits, myCallback);

    // Display Results
    let text ="These fruits are Ok: <br>";
    try {
    for (let x of result.get("ok")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    text += "<br>These fruits are low: <br>";
    try {
    for (let x of result.get("low")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    document.getElementById("demo").innerHTML = text;

    console.log(result.get("ok"));
    }
  • contenteditable=true

    function consolelog(inrec) {
    if (rspan == 0) {
    document.getElementById("tdname").innerHTML=inrec.split('value:')[1].split(' key:')[0].split(' map:')[0];
    document.getElementById("tdquantity").innerHTML=inrec.split('key:')[1].split(' value:')[0].split(' map:')[0];
    rspan=1;
    } else if (inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] == '') {
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    } else {
    tabletds+='<tr><td contenteditable=false id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    }
    //alert(inrec);
    if (doadd) {
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);></td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>0</td></tr>';
    rspan++;
    doadd=false;
    }
    }
  • array.push()

… in map_test.html “proof of concept” Array and Map Tester web application …

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


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


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


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

Dots and Boxes Game Tweaking Tutorial

Dots and Boxes Game Tweaking Tutorial

Dots and Boxes Game Tweaking Tutorial

Unlike the recent SOS Game Cursor Tutorial “revisit tweaking” via CSS, today we’re back to our more usual tweaking conduit, Javascript DOM with a smidge of CSS, improving on the Dots and Boxes Game work of Dots and Boxes Game Parameterization Tutorial with some Javascript tweaking …


$ diff dots_and_boxes_game.html---GETME dots_and_boxes_game.html--GETME
138c138
< var etoast_on=(navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i) ? true : false);
---
> var etoast_on=(navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i) ? true : false);
user@Users-Air htdocs % diff dots_and_boxes_game.html---GETME dots_and_boxes_game.html
6c6
<
---
>
113c113
< font-size: 16px;
---
> font-size: 20px;
117c117
< border: 2px dashed rgba(0,0,0,0.5);
---
> border: 1px dashed rgba(0,0,0,0.5);
146c146
< var bcols=['#0000ff','#00ff00','#ff0000','#ffff00','#ff00ff','#00ffff','#777777','#000077','#007700','#770000','#777700','#770077','#007777'];
---
> var bcols=['#ff0000','#73391d','#ff0000','#ffff00','#73391d','#00ffff','#777777','#000077','#007700','#770000','#777700','#770077','#007777'];
198c198
< document.write(brbr + "<table><tr><td><textarea id=mytao class=editor rows=" + ydown + " cols=" + xacross + ">" + ebye + "</textarea></td></TR><TR><td id=emailsms style=display:none;vertical-align:top;> <a target=_blank href='mailto:?subject=My%20Selection%20...&body=' id=aemail title=Email>&#128231;</a> <a target=_blank onmouseover=\"if (smsee.length == 0 && origsmsurl.indexOf('sms:&') != -1) { smsee=prompt('Please enter SMS number to send to.', ''); if (smsee == null) { smsee=''; } else { origsmsurl=origsmsurl.replace('sms:&','sms:' + smsee + '&'); asmsurl=asmsurl.replace('sms:&','sms:' + smsee + '&'); this.href=asmsurl; } }\" ontouchstart=\"if (smsee.length == 0 && origsmsurl.indexOf('sms:&') != -1) { smsee=prompt('Please enter SMS number to send to.', ''); if (smsee == null) { smsee=''; } else { origsmsurl=origsmsurl.replace('sms:&','sms:' + smsee + '&'); asmsurl=asmsurl.replace('sms:&','sms:' + smsee + '&'); this.href=asmsurl; } }\" href='sms:&body=My%20Selection%20...' id=asms title=SMS>&#128223;</a></td></tr></table>");
---
> document.write(brbr + "<table style='width:100%;'><tr><td><textarea id=mytao class=editor rows=" + ydown + " cols=" + xacross + ">" + ebye + "</textarea></td></TR><TR><td id=emailsms style=display:none;vertical-align:top;> <a target=_blank href='mailto:?subject=My%20Selection%20...&body=' id=aemail title=Email>&#128231;</a> <a target=_blank onmouseover=\"if (smsee.length == 0 && origsmsurl.indexOf('sms:&') != -1) { smsee=prompt('Please enter SMS number to send to.', ''); if (smsee == null) { smsee=''; } else { origsmsurl=origsmsurl.replace('sms:&','sms:' + smsee + '&'); asmsurl=asmsurl.replace('sms:&','sms:' + smsee + '&'); this.href=asmsurl; } }\" ontouchstart=\"if (smsee.length == 0 && origsmsurl.indexOf('sms:&') != -1) { smsee=prompt('Please enter SMS number to send to.', ''); if (smsee == null) { smsee=''; } else { origsmsurl=origsmsurl.replace('sms:&','sms:' + smsee + '&'); asmsurl=asmsurl.replace('sms:&','sms:' + smsee + '&'); this.href=asmsurl; } }\" href='sms:&body=My%20Selection%20...' id=asms title=SMS>&#128223;</a></td></tr></table>");
223c223
< sbs[isbs].style.outline='2px solid ' + bcols[curplayer];
---
> sbs[isbs].style.outline='1px solid ' + bcols[curplayer];
459c459
< thislet='border-left:2px solid ' + bcols[curplayer]; //alert(56);
---
> thislet='border-left:1px solid ' + bcols[curplayer]; //alert(56);
483c483
< thislet='border-right:2px solid ' + bcols[curplayer]; //alert(56);
---
> thislet='border-right:1px solid ' + bcols[curplayer]; //alert(56);
512c512
< thislet='border-bottom:2px solid ' + bcols[curplayer]; //alert(56);
---
> thislet='border-bottom:1px solid ' + bcols[curplayer]; //alert(56);
536c536
< thislet='border-top:2px solid ' + bcols[curplayer]; //alert(56);
---
> thislet='border-top:1px solid ' + bcols[curplayer]; //alert(56);
562c562
< spano.style.color='#0000ff';
---
> spano.style.color='#ff0000';
920a921
> document.getElementById('wunderlay').style.width='' + eval(-35 + screen.width) + 'px'; // new

… a font-size increase, counterintuitively (except when it comes to sizing emoji text), the way on non-mobile we resize the game squares to better fill the background elements, along with that last tweak using screen.width to define the game squares area width. We didn’t think any cursor changes were very relevant though.

Maybe you can retry the changed dots_and_boxes_game.html Dots and Boxes Game.

Stop Press

We also found that the keyboard and margin tweaking work we undertook in SOS Game Keyboard Tutorial was mostly directly applicable to our tweaked dots_and_boxes_game.html Dots and Boxes Game coding for characters …

  • L … for left border
  • R … for right border
  • T … for top border
  • B … for bottom border


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

Dots and Boxes Game Parameterization Tutorial

Dots and Boxes Game Parameterization Tutorial

We quite like …

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

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

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

… as per the device width dependant …


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

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

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

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

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


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

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

… in all of the recent …


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

Dots and Boxes Game Primer Tutorial

Dots and Boxes Game Primer Tutorial

Today, do you fancy …

Morphing a clone

… or should that be …

Cloning a morph

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

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

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

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


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

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


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


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


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

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

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


Previous relevant SOS Game Primer Tutorial is shown below.

SOS Game Primer Tutorial

SOS Game Primer Tutorial

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

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

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

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

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

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

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

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

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


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

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



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


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

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

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



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

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

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

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

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

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

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

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

<style>

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

</style>

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


Previous relevant Word Find Game Aesthetics Tutorial is shown below.

Word Find Game Aesthetics Tutorial

Word Find Game Aesthetics Tutorial

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

  • CSS animation … and …
  • CSS linear gradients

… we use, respectively, regarding …

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

    <style>

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

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

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

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

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


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

    }


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

    }
    </style>

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

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

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


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


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

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


Previous relevant Word Find Game Mobile Tutorial is shown below.

Word Find Game Mobile Tutorial

Word Find Game Mobile Tutorial

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

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

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


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

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

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


Previous relevant Word Find Game Personalization Tutorial is shown below.

Word Find Game Underlay Tutorial

Word Find Game Personalization Tutorial

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

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

… as per Javascript …


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

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


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

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


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

Word Find Game Underlay Tutorial

Word Find Game Modes of Use Tutorial

Online games often feature …

  • degree of difficulty
  • number of player(s)

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


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

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


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

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

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

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

}

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


Previous relevant Word Find Game Underlay Tutorial is shown below.

Word Find Game Underlay Tutorial

Word Find Game Underlay Tutorial

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

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

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

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

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

    }

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

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

    </style>

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

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


Previous relevant Word Find Game Primer Tutorial is shown below.

Word Find Game Primer Tutorial

Word Find Game Primer Tutorial

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

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

  • horizontal forwards
  • horizontal backwards

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

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

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


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


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


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


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


return outstris;
}


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


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


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

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


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

Selection API and Clipboard API Tutorial

Selection API and Clipboard API Tutorial

There’s the …

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

… using HTML changed code


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

… supported by new Javascript event interventional code …


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

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

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

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


Previous relevant Clipboard API Image Tutorial is shown below.

Clipboard API Image Tutorial

Clipboard API Image Tutorial

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

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

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

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


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

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


Previous relevant Clipboard API Primer Tutorial is shown below.

Clipboard API Primer Tutorial

Clipboard API Primer Tutorial

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

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

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

  • append
  • prepend
  • at cursor

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

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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Javascript Map Array Hashtag Tutorial

Regular readers will know of our ever increasing fondness, out of webpage navigational ideas …

  • form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages but apt to cause error 414 due to data size restrictions) … or …
  • form method=POST URL navigation (suitable for server recipient webpages only, but able to handle much more data) … or …
  • hybrid arrangement that is essentially form method=GET ? and & delimited argument style URL navigation (suitable for both client and server recipient webpages) with error 414 avoided by most data forming the location.hash (client understood) hashtagged data

… for the last hashtagging arrangement when the data size precludes the first arrangement, and we see benefits regarding “a” “mailto:” and/or “sms:” sharing links becoming involved (rather than relying on any PHP server mail function calling).

Our Google Chart interfacing is no exception here, and yes, once we’ve completed our sweep of Google Chart inhouse functionality interfacers, on top of today’s …

… list we got keen to attend to today, with a most (when needed) strategy …

First “data” label value is method=GET
Rest of “data” value items are hashtagged

… (having the benefit that the intervention point is consistent and reliable) on top of yesterday’s Javascript Map Array Chart Tutorial, in this regard, as helper outerers for our changed map_test.html Array and Map Tester web application you can also try below, we’ll be able to further genericize Sharing and Collaboration Google Chart interfacing functionality when the amounts of data involved exceed server based (error 414) limits.

Along the way, testing on iOS mobile platforms, we were gobsmacked by the possibility of location.hash (ie. # hashtagging) not being recognized, always, at the recipient, and so a failsafe we introduced was to also store hashtagged data in a parent textbox the recipient can reference …

<?php echo ”

if (window.top) {
if (parent.document.getElementById('lhashis')) {
if (decodeURIComponent(('' + parent.document.getElementById('lhashis').value)).indexOf(',') != -1) {
location.hash=parent.document.getElementById('lhashis').value;
}
}
}

“; ?>

… even before “recipient document.body onload” timing, happily, to get around the restrictiveness of this location.hash lack of acceptance, at times.

Which brings us to …

Why is Geo Chart in that list above?

Well, it’s a bit unlikely, but it just so happens our best CSV file to hand, around here, contained ISO-3166 2 character country codes with a representative latitude and longitude (as you can see with, the now publicly shared, country.csv … thanks to Google) and this data is right up the alley of use by the Google Chart Geo Chart (which you might recall we had a different hashtag arrangement going on already …

… believe it or not, never causing any iOS mobile platform issues up to now … go figure!)

To get this “sharing of that CSV” to be any way useful, and illustrative, if you double click the “topic” word and get to the Javascript prompt window that follows, we tweak you to this, but if you enter …

https://www.rjmprogramming.com.au/HTMLCSS/country.csv

… at that prompt window, now, we’ll attempt an Ajax call of whatever URL you enter to try to glean data content to suit our …

label name to numerical quantity relationship

… this web application is hankering for.

And there, the amount of data (in size) is far too big for non-hybrid method=GET scenarios, and we need to turn to our new hybrid ideas to proceed with our quest to take over “Lower Middle Mordor South Lowlands as seen from Mirkwood“.

This may all bore, but believe me if you offer users a piece of functionality, they’ll want to push it to limits, and in that “push” could come most of your work, and concern, with regard to a project you are working on, so we figure it is best to cater for this before it is asked for.

TwoThree sentences ending in for? Okay, Grammarly, we give up!

Each Google Chart interfacer has individual nuances, but PHP code changes like below …

<?php

echo ' if (decodeURIComponent(("" + location.hash).replace(/^undefined/g,"")).trim().indexOf(",") != -1) { ' . "\n";
echo ' var xwert="data=google.visualization.arrayToDataTable([ [' . "'" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'" . '],"; ' . "\n";
echo " xwert+=\"" . str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata))))) . "\" + ('' + location.hash).replace(/^\#/g,'').replace(/\%20/g,'').replace(/\,\]/g,\",0\").replace(/\[\~/g,\"['\").replace(/\~\,/g,\"',\"); " . "\n";
echo ' xwert+=" ])"; xwert=xwert.replace(",,",","); ' . "\n";
echo ' eval(xwert); ' . "\n";
echo ' } else { ' . "\n";

echo ' data = google.visualization.arrayToDataTable([ ' . "\n";
echo " ['" . $GETlabel . "','" . str_replace(",", "','", str_replace("'", "", $GETvalue)) . "'] \n";
echo str_replace("~,", "',", str_replace("[~", "['", str_replace(",]", ",0]", str_replace(",,", ",0,", str_replace(",]", ",0]", $GETdata)))));
echo " ]);\n";
echo " } \n";

?>

… typify our interventional strategy to make these improvements happen. Good ol’ (much maligned) eval … huh?! And good ol’ Javascript undefined bizzos! And good ol’ hashtagging! Aaaaaaaaaaal drink to all youse guys and gals (if one might be so forward, that is).


Previous relevant Javascript Map Array Chart Tutorial is shown below.

Javascript Map Array Chart Tutorial

Javascript Map Array Chart Tutorial

Does the data behind yesterday’s Javascript Map Array Import Tutorial remind you of anything? Relative database data? Spreadsheets?

That last one has lots of synergy, we reckon. And lots of us know, in spreadsheet software products like Microsoft Excel, once a …

  • spreadsheet is involved
  • charts are often offered as a graphical stand in display (to the tabular looking spreadsheet, that is)

And in this respect, looking back on our interfacing work to Google Charts when you have a label name to numerical quantity relationship two Google Chart types (we know of) are useful …

… and we’d like to offer some optional interfacing to these (to improve functionality, that is) … the Javascript for this leaning on the new …


function datait(oselv) {
var outv=oselv, kk=0, firstdelim='';
//alert(outv);
if (outv != '') {
if (oselv.indexOf('PHP/Pie') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
if (('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]').indexOf('-') == -1) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
}
} else if (oselv.indexOf('PHP/Histogram') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=',[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]');
}
//alert(outv);
} else if (oselv.indexOf('PHP/Geo') != -1) {
document.getElementById('title').value=document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report';
document.getElementById('popularity').value=document.getElementById('thquantity').innerHTML;
document.getElementById('task').value=document.getElementById('thquantity').innerHTML;
document.getElementById('country').value=document.getElementById('thname').innerHTML;
document.getElementById('desc').value=document.getElementById('thname').innerHTML;
outv=outv.replace('title=Title', 'title=' + encodeURIComponent(document.getElementById('topic').innerHTML + ' ' + document.getElementById('spanok').innerHTML + ' versus ' + document.getElementById('spanlow').innerHTML + ' Report'));
outv=outv.replace('popularity=Popularity', 'popularity=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('country=Country', 'country=' + encodeURIComponent(document.getElementById('thname').innerHTML));
outv=outv.replace('task=Popularity', 'task=' + encodeURIComponent(document.getElementById('thquantity').innerHTML));
outv=outv.replace('desc=Country', 'desc=' + encodeURIComponent(document.getElementById('thname').innerHTML));


for (kk=0; kk<fruits.length; kk++) {
outv+=firstdelim + '%20[~' + encodeURIComponent(fruits[kk].name) + ('~,' + fruits[kk].quantity + ']').replace(/\~\,\]/g,'~,0]') + '%20';
firstdelim=',';
}
if (('' + outv).length > 600) { return toolong(outv.replace('&data=%20', '&data=%20#')); }
}
}
if (('' + outv).length > 600) {
document.getElementById('data').value=',' + outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='POST';
document.getElementById('myform').action=outv.split('?')[0] + '#pleasenolocationhref';
outv='./map_test.html';
//var xx=prompt(document.getElementById('myform').outerHTML,document.getElementById('myform').innerHTML);
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
} else if (2 == 2) {
document.getElementById('data').value=outv.split('&data=')[1].replace(/\%20/g,' ');
document.getElementById('myform').method='GET';
document.getElementById('myform').action=outv.split('?')[0];
//outv='./map_test.html';
setTimeout(function(){ document.getElementById('mysub').click(); }, 3000);
}
return outv;
}

function selit(osel) {
if (osel.value != '') {
geovalis=osel.value;
document.getElementById('defopt').innerText='Google Chart display of ... relevant ' + osel.value.split('PHP/')[1].split('/')[0].replace('Chart',' Chart') + ' below ...';
document.getElementById('dif').innerHTML='<br><br><a id=atop href="#myh1">Back to top ...</a><br><br><iframe name=myifis id=myifis src="' + datait(osel.value) + '" style="width:100%;height:700px;"></iframe>';
document.getElementById('dif').style.display='block';
}
osel.value='';
location.href='#atop';
}

… in the changed map_test.html Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Import Tutorial is shown below.

Javascript Map Array Import Tutorial

Javascript Map Array Import Tutorial

Is it …

  • the extension of import capabilities … or …
  • the sharing capabilities

… of most interest in today’s work, extending that of yesterday’s Javascript Map Array Genericization Tutorial?

Well …

  • the extension of import capabilities …

    function askall(preenterall) {
    var isfirst=true;
    var delall=false;
    var enterall=('' + preenterall).replace(/^undefined$/g,'');
    if (enterall == '') {
    enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    } //else {
    //alert(enterall);
    //}
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(1);
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(2);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    //alert(3);
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    //alert(4);
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(5);
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(6);
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    //alert(7);
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    //alert(8);
    if (isfirst && ((elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) < '0' || (elines[ie].substring(0).split(',')[1] + ' ').replace('-','').substring(0,1) > '9')) {
    document.getElementById('topic').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thname').innerHTML=elines[ie].substring(0).split(',')[0].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[0].substring(1);
    document.getElementById('thquantity').innerHTML=elines[ie].substring(0).split(',')[1].substring(0,1).toUpperCase() + elines[ie].substring(0).split(',')[1].substring(1);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    isfirst=false;
    }
    beadjustable();
    }
    }

    function yesthreethree(restis) {
    if (restis.indexOf(';base64,') != -1) {
    var icontent=window.atob(restis.split(';base64,')[1]);
    if ((('' + icontent).trim() + ' ').replace(/^\[caption/g,'<').substring(0,1) == '<') {
    askall(extractContent(icontent,true));
    } else {
    askall(icontent);
    }
    } else {
    askall(restis);
    }
    }

    …asked for tweaks to our changed client_browsing.htm client side HTML and Javascript inhouse file browsing interfacer showing a “first time” scenario, for us with our “first cab off the rank” CSV (comma separated values) trial file …

    user@MacBook-Air htdocs % head -10 country.csv
    country,latitude,longitude,name // Thanks to https://developers.google.com/public-data/docs/canonical/countries_csv
    AD,42.546245,1.601554,Andorra
    AE,23.424076,53.847818,United Arab Emirates
    AF,33.93911,67.709953,Afghanistan
    AG,17.060816,-61.796428,Antigua and Barbuda
    AI,18.220554,-63.068615,Anguilla
    AL,41.153332,20.168331,Albania
    AM,40.069099,45.038189,Armenia
    AN,12.226079,-69.060087,Netherlands Antilles
    AO,-11.202692,17.873887,Angola
    user@MacBook-Air htdocs %

    … which is of interest … or …
  • the sharing capabilities, of the report, where we allow for the usual onclick of an emoji button fed through to “a” mailto: (email) or sms: (SMS) conduits to sharing, and for the first time, for us, a drag and drop way (we thank both https://www.w3schools.com/howto/howto_js_draggable.asp and https://www.w3schools.com/html/html5_draganddrop.asp regarding) …

    function dragElement(elmnt) { // thanks to https://www.w3schools.com/howto/howto_js_draggable.asp
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
    } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    alert('Here');
    }

    function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
    }
    }

    function allowDrop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.preventDefault();
    }

    function drag(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    ev.dataTransfer.setData("text", ev.target.id);
    }

    function doemail(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    var subjis=(document.getElementById('threport').innerText || document.getElementById('threport').contentWindow || document.getElementById('threport').contentDocument);
    a.href='mailto:?subject=' + encodeURIComponent(topicis) + '%20' + encodeURIComponent(subjis) + '&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function dosms(data) {
    var a=null;
    a = document.createElement("a");
    var contis=(document.getElementById('demo').innerText || document.getElementById('demo').contentWindow || document.getElementById('demo').contentDocument);
    var topicis=(document.getElementById('topic').innerText || document.getElementById('topic').contentWindow || document.getElementById('topic').contentDocument);
    a.href='sms:&body=' + encodeURIComponent(document.URL.split('?')[0].split('#')[0] + '?tippingvalue=' + moreencodeURIComponent(document.getElementById('itip').value) + '#data=') + encodeURIComponent(encodeURIComponent(contis.replace(/\<bJUNKr\>/g, String.fromCharCode(10))));
    a.click();
    }

    function drop(ev) { // thanks to https://www.w3schools.com/html/html5_draganddrop.asp
    var ssrect=null, isemail=true, a=null;
    ssrect=document.getElementById('droppable').getBoundingClientRect();
    if (eval(ssrect.right - ev.clientX) < eval(ev.clientX - ssrect.left)) { isemail=false; }
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    if (isemail) {
    //a = document.createElement("a");
    //a.href='mailto:?subject=' + encodeURIComponent(document.getElementById('topic').innerHTML) + '%20Report%20of%20Inventory&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    doemail(data);
    } else if (!isemail) {
    //a = document.createElement("a");
    //a.href='sms:&body=' + encodeURIComponent(document.getElementById(data).innerHTML.replace(/\<bJUNKr\>/g, String.fromCharCode(10)));
    //a.click();
    dosms(data);
    } else {
    ev.target.appendChild(document.getElementById(data));
    }
    }

    … where the drop position tells us which “conduit” to go with

… and so, both are of some interest, we figure in a changed map_test.html Array and Map Tester web application you can also try below.

Did you know?

In Object Oriented Programming, methods (ie. object functions) can be named similarly with different argument patterns and/or return values, but now, with three functions in this current project we’ve coalesced this idea into single calls and used the Javascript undefined return for non-defined arguments as our way to “keep it brief” …

  • function askall(preenterall) { } … as above
  • function alteredstate(indemo, readd) { }
  • function addone(knownname, knownquantity) { }


Previous relevant Javascript Map Array Genericization Tutorial is shown below.

Javascript Map Array Genericization Tutorial

Javascript Map Array Genericization Tutorial

We think yesterday’s Javascript Map Array Primer Tutorial could benefit from …

  • aspects that make the Inventory aspects to the web application feel more like a “tool” …
  • aspects that make the Inventory aspects to the web application feel more “generic”

… and, you may notice, fixes for the way “Map.groupBy” functionality does not appear to work on the mobile platforms my iPhone has for web browsers …


var text="";

function thecall() {
var kk=0;

// Group by ok and low
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
try {
const result = Map.groupBy(fruits, myCallback);

// Display Results
try {
for (let x of result.get("ok")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
} catch(ebad) { }
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
try {
for (let x of result.get("low")) {
if (x.name != '' || x.quantity != 0) {
text += "" + x.name + " " + x.quantity + "<br>";
}
if (!m.has(x.name)) {
m.set(x.name, x.quantity);
}
}
console.log(result.get("ok"));
} catch(ebad) { }
} catch(overebad) {
text="These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are Ok: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'ok') {
//alert(fruits[kk].name);
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
//alert('2:' + fruits[kk].name);
if (!m.has(fruits[kk].name)) {
//alert('3:' + fruits[kk].name);
m.set(fruits[kk].name, fruits[kk].quantity);
//alert('4:' + fruits[kk].name);
}
}
}
}
text += "<br>These " + document.getElementById('topic').innerHTML.toLowerCase() + "s are low: <br>";
for (kk=0; kk<fruits.length; kk++) {
if (('' + fruits[kk].quantity).replace('-','').substring(0,1) >= '0' && ('' + fruits[kk].quantity).replace('-','').substring(0,1) <= '9') {
if (mysimpleCallback(fruits[kk].quantity) == 'low') {
text += "" + fruits[kk].name + " " + fruits[kk].quantity + "<br>";
if (!m.has(fruits[kk].name)) {
m.set(fruits[kk].name, fruits[kk].quantity);
}
}
}
}

}

document.getElementById("demo").innerHTML = text;

}

With this in mind, we honed in on a “topic” concept, where yesterday’s “topic” would have been “Fruit”. There are two aspects …

  1. allow a contenteditable way for user to change the displayed (what used to be) hardcoding

    <span title='Double click to be able to enter CSV data' id=topic contenteditable=true onblur=beadjustable(); ondblclick=askall();>Fruit</span>

    … as well as …
  2. add ondblclick (ie. on double click) means by which a user can use a Javascript prompt window means by which they can enter all the CSV (ie. comma separated values) data for an Inventory application of the user’s choosing (including a means by which they can also enter the “topic” at the same time) …

    function askall() {
    var delall=false;
    var enterall=prompt('Optionally copy all your CSV (comma separated values) data to apply here (where ; or | can be record delimiters). Optionally prefix this CSV data with your topic followed by ~`~' + String.fromCharCode(10) + String.fromCharCode(10) + 'Example ...' + String.fromCharCode(10) + 'Fish~`~taylor,300;barramundi,400;perch,100;mullet,234', '');
    if (enterall == null) { enterall=''; }
    if (enterall.indexOf('~`~') != -1) { document.getElementById('topic').innerHTML=enterall.split('~`~')[0]; enterall=enterall.replace(enterall.split('~`~')[0] + '~`~', ''); }
    if (enterall.indexOf(',') != -1) {
    var elines=[];
    if (enterall.indexOf(String.fromCharCode(10)) != -1) {
    elines=enterall.split(String.fromCharCode(10));
    } else if (enterall.indexOf(';') != -1) {
    elines=enterall.split(';');
    } else if (enterall.indexOf('|') != -1) {
    elines=enterall.split('|');
    }
    for (var ie=0; ie<elines.length; ie++) {
    if (elines[ie].indexOf('","') != -1 && elines[ie].indexOf('","') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('","')[1].split('"')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('","')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf('",') != -1 && elines[ie].indexOf('",') < elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(1).replace('-','').substring(0,1) >= '0' && elines[ie].substring(1).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split('",')[1].split(',')[0], elines[ie].substring(1).split('"')[0]);
    } else {
    addone(elines[ie].substring(1).split('"')[0], elines[ie].split('",')[1].split(',')[0]);
    }
    } else if (elines[ie].indexOf(',"') != -1 && elines[ie].indexOf(',"') == elines[ie].indexOf(',')) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].split(',"')[1].split('"')[0], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].split(',"')[1].split('"')[0]);
    }
    } else if (elines[ie].indexOf(',') != -1) {
    if (!delall) {
    delall=true;
    fruits=[];
    m = new Map();
    }
    if (elines[ie].substring(0).replace('-','').substring(0,1) >= '0' && elines[ie].substring(0).replace('-','').substring(0,1) <= '9') {
    addone(elines[ie].substring(0).split(',')[1], elines[ie].substring(0).split(',')[0]);
    } else {
    addone(elines[ie].substring(0).split(',')[0], elines[ie].substring(0).split(',')[1]);
    }
    }
    }
    beadjustable();
    }
    }

… in a changed map_test.html “proof of concept” Array and Map Tester web application you can also try below.


Previous relevant Javascript Map Array Primer Tutorial is shown below.

Javascript Map Array Primer Tutorial

Javascript Map Array Primer Tutorial

We’ve got yet another “map” idea for you today, coming from the wooooorrrrlllllddd of Javascript clientside data structures, if you like.

We got onto this topic via reading https://www.w3schools.com/js/tryit.asp?filename=tryjs_map_groupby and https://medium.com/@sotoer/your-foreach-example-has-the-wrong-order-of-params-which-you-are-also-demonstrating-in-your-sample-42f5491b604e which both helped us enormously put together a rudimentary Fruit Inventory web application featuring …

  • array with structure

    // Create an Array
    const fruits = [
    {name:"apples", quantity:300},
    {name:"bananas", quantity:500},
    {name:"oranges", quantity:200},
    {name:"kiwi", quantity:150}
    ];
  • map object

    var m = new Map();
  • use of map.set() …

    function addone() {
    doadd=true;
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    doadd=false;
    beadjustable();
    }

    … and Map.groupBy()

    function thecall() {
    // Group by ok and low
    const result = Map.groupBy(fruits, myCallback);

    // Display Results
    let text ="These fruits are Ok: <br>";
    try {
    for (let x of result.get("ok")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    text += "<br>These fruits are low: <br>";
    try {
    for (let x of result.get("low")) {
    if (x.name != '' || x.quantity != 0) {
    text += x.name + " " + x.quantity + "<br>";
    }
    if (!m.has(x.name)) {
    m.set(x.name, x.quantity);
    }
    }
    } catch(ebad) { }
    document.getElementById("demo").innerHTML = text;

    console.log(result.get("ok"));
    }
  • contenteditable=true

    function consolelog(inrec) {
    if (rspan == 0) {
    document.getElementById("tdname").innerHTML=inrec.split('value:')[1].split(' key:')[0].split(' map:')[0];
    document.getElementById("tdquantity").innerHTML=inrec.split('key:')[1].split(' value:')[0].split(' map:')[0];
    rspan=1;
    } else if (inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] == '') {
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    } else {
    tabletds+='<tr><td contenteditable=false id=tdname' + rspan + ' onblur=fix(this);>' + inrec.split('value:')[1].split(' key:')[0].split(' map:')[0] + '</td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>' + inrec.split('key:')[1].split(' value:')[0].split(' map:')[0] + '</td></tr>';
    rspan++;
    }
    //alert(inrec);
    if (doadd) {
    fruits.push({name:"", quantity:0});
    m.set('', 0);
    tabletds+='<tr><td contenteditable=true id=tdname' + rspan + ' onblur=fix(this);></td><td contenteditable=true id=tdquantity' + rspan + ' onblur=fix(this);>0</td></tr>';
    rspan++;
    doadd=false;
    }
    }
  • array.push()

… in map_test.html “proof of concept” Array and Map Tester web application …

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


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


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