Javascript Map Array Chart Tutorial

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.

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

Javascript Map Array Import Tutorial

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.

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

Javascript Map Array Genericization Tutorial

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.

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

Javascript Map Array Primer Tutorial

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.

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

PHP Mbstring Multibyte String and Intl Class Tutorial

PHP Mbstring Multibyte String and Intl Class Tutorial

PHP Mbstring Multibyte String and Intl Class Tutorial

We’re revisiting the PHP Mbstring Multibyte String Primer Tutorial of the past to see where we stand now with PHP 8 and …

  • mbstring “Multibyte String” extension … and …
  • intl “Internationalization Functions” extension

… and discovered that we can happily now have a chance incorporating these functionalities into PHP serverside logic into the future. We tested this with a tweaked mbstring_test.php “old way” live run and “new way” live run via the writing of a couple of “proof of concepts” …


Previous relevant PHP Mbstring Multibyte String Primer Tutorial is shown below.

PHP Mbstring Multibyte String Primer Tutorial

PHP Mbstring Multibyte String Primer Tutorial

Our (Mac OS X laptop) local MAMP web server is an Apache/PHP/MySql web server. In this environment you can find out a lot with some PHP code as per …

<?php phpinfo(); ?>

… and if, in doing this, you find a reference to the “mbstring” Multibyte String Information functionality existing, you are a lucky candidate to introduce some internationalization code into your PHP code, for those occasions where the destination language uses a UTF-8 character set where individual characters can not be described by the ascii character set from decimal 0 to decimal 255. In other words, it takes more than one byte to describe each character of the language. There are many languages like this, a few being the Chinese languages, Japanese and Korean.

We followed a lot of the advice of the very useful link (thanks) to create some PHP called …

… where we show what we always suspected but were too shy to ask, and didn’t flesh it out before … doh! … you can’t split a Chinese phrase’s characters into their individual characters and expect those characters individually translated bring you back to the sense of the Chinese phrase to start with.

So we take the Chinese phrase 火车票 (which translates into English as “Train tickets” … and we thank Google Translate for help with all this) and use PHP mbstring’s mb_str_split to properly split the Chinese into its constituent multibyte (UTF-8) characters (and along the way, show that PHP str_split messes up this same task, as you’d probably guess would happen), and then translate all these into English using Google Translate, as an intellectual exercise.

If this exercise makes you …

  • a) fall on the floor laughing
  • b) hit a gong with a huge hammer
  • c) cook up some deep fried dumplings
  • d) put the left chopstick in the right ear and the right chopstick in the left ear (please ask for adult supervision) … translation: do not do this
  • e) while reading you sweep the cat under the rug (no animals were harmed in the making of this blog posting)

… then we’re here to tell you that you need to take a Bex and have a lie down.

We are just showing in PHP that if the mbstring functionality is available to you, that the mbstring library of functionality can help with some Internationalization issues you may be grappling with and that this PHP code you could try via this live run link.

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


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

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

Imagick PHP Class Primer Tutorial

Form Target Self Primer Tutorial

Imagick PHP Class Primer Tutorial

We’re talking “class” today. Up until now, regarding the great ImageMagick suite of software, and it’s interactions with PHP, we’ve …

… in a first draft not installed here on CentOS but okay here with AlmaLinux. Am sure most people would concur that this is much more integrated approach for PHP …


<?php
// oil_painting_thumbnail.php
// RJM Programming - August, 2024
// Start using PHP Imagick class
$image=null;
if (!isset($_GET['image']) && !isset($_POST['image'])) {
echo "<html><head><scr" . "ipt type=text/javascript> function ask() { var bsh=prompt('See the default brightness, saturation, hue settings, black point %, white point % and change as desired ... 100,0,100,90,95 is grayscale ... darkest 90% of pixels are turned black, the brightest 5% are made white, and those between 90% and 95% are grey-scaled', document.getElementById('brightness').value + ',' + document.getElementById('saturation').value + ',' + document.getElementById('hue').value + ',' + document.getElementById('blackpoint').value + ',' + document.getElementById('whitepoint').value); if (bsh != null) { if (eval('' + bsh.split(',').length) == 5) { document.getElementById('brightness').value=bsh.split(',')[0]; document.getElementById('saturation').value=bsh.split(',')[1]; document.getElementById('hue').value=bsh.split(',')[2]; document.getElementById('blackpoint').value=bsh.split(',')[3]; document.getElementById('whitepoint').value=bsh.split(',')[4]; } } return true; } </scr" . "ipt></head><body><h1>Imagick Ideas</h1><h3>RJM Programming - August, 2024 ... thanks to https://www.php.net/manual/en/book.imagick.php and https://www.php.net/manual/en/imagick.contraststretchimage.php</h3><br><br><form action='./oil_painting_thumbnail.php' id=myform method=GET><input type=hidden name=brightness value=100 id=brightness></input><input type=hidden name=saturation value=0 id=saturation></input><input type=hidden name=hue value=100 id=hue></input><input type=hidden name=blackpoint value=90 id=blackpoint></input><input type=hidden name=whitepoint value=95 id=whitepoint></input><input style='width:70%;' type=text placeholder='Image to process ...' name=image id=image value=''></input><br><br><input onclick=\" document.getElementById('myform').method='GET'; \" type=submit style=background-color:orange; value=Negate></input> <input style=background-color:yellow; onclick=\" if (ask()) { document.getElementById('myform').method='POST'; } \" type=submit value='Contrast Stretch'></input></form></body></html>";
} else {
if (isset($_GET['image'])) {

header('Content-type: image/jpeg');

//Instantiate a new Imagick object
$image = new Imagick(realpath(urldecode($_GET['image'])));
$image->negateImage(false);

// If 0 is provided as a width or height parameter,
// aspect ratio is maintained
$image->thumbnailImage(100, 0);

echo $image;
exit;

} else {
//Instantiate a new Imagick object
$image = new Imagick(realpath(urldecode($_POST['image'])));
list($width, $height) = array_values ($image->getImageGeometry());
$b=(isset($_POST['brightness']) ? $_POST['brightness'] : '100');
$s=(isset($_POST['saturation']) ? $_POST['saturation'] : '0');
$h=(isset($_POST['hue']) ? $_POST['hue'] : '100');
$bp=(isset($_POST['blackpoint']) ? $_POST['blackpoint'] : '90');
$wp=(isset($_POST['whitepoint']) ? $_POST['whitepoint'] : '95');
$image->modulateImage($b, $s, $h);
$image->contrastStretchImage($width * $height * ($bp / 100.0), $width * $height * ($wp / 100.0));
$image->writeImage('example_thumbnail.jpg');
echo "<html><body><p>My Changed Image " . urldecode($_POST['image']) . " ... brightness " . $b . ", saturation " . $s . ", hue " . $h . ", black point % " . $bp . "%, white point % " . $wp . "%</p><br><img src='./example_thumbnail.jpg'></img></body></html>";
exit;

}
}
?>

… to interface to the great ImageMagick image manipulation software.

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

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

AlmaLinux Web Server Malware Scanning Tutorial

AlmaLinux Web Server Malware Scanning Tutorial

AlmaLinux Web Server Malware Scanning Tutorial

If you maintain a computer it can be reassuring to have access to some quality Malware Scanning functionality (often part of an AntiVirus suite of functionality located, for us, in amongst the cPanel functionality of our AlmaLinux WHM Linux web server software parts). So it is with our “soon to be” RJM Programming AlmaLinux web server, which has provided us with ImunifyAV

ImunifyAV: Best Free Linux Server Antivirus

… 7.14.0 version, further to previous malware blog posting regarding laptop themed Malware Protection Primer Tutorial.

We’ve used ImunifyAV a few times, now, on our AlmaLinux web server, and find it easy to use, starting a session scanning …


/home*/*

… folder specification, which covers the public parts of the RJM Programming domain reach.

But we have come across some false positive Malware readings …

How do we know? It’s the combination of …

  • what it suspected was inhouse code … and …
  • we stopped it being flagged as “malware” via …
    1. copied the code to a newly created folder (for speed of scanning purposes)
    2. found that for two inhouse code examples, now, by changing codelines that used to look like …

      [some code statement]; // thanks to https://[domain]/[requestURI]

      … to …

      [some code statement]; // thanks to https [domain] [requestURI]

      … and the fact that this took the code off that “malware” suspicion list made us think that “signature based” malware checking can throw up very occasional false positives
  • delete this code and its temporary folder
  • make the changes to the original code
  • rerun the /home*/* (or subset) scanning run, to reassure

So, if a small number of these inhouse examples are found we recommend not panicking, and checking each one out for these “what must be signature based” Malware Scanning accidental “false positives”. Else if still flagged … panic! But seriously, you may need to examine further, or quarantine, via deletion perhaps, or purchase more ImunifyAV functionality that purports to fix such malware issues.


Previous relevant Malware Protection Primer Tutorial is shown below.

Malware Protection Primer Tutorial

Malware Protection Primer Tutorial

To quote Wikipedia, Malware is …

Malware (a portmanteau for malicious software) is any software intentionally designed to cause damage to a computer, server, client, or computer network.[1] Malware does the damage after it is implanted or introduced in some way into a target’s computer and can take the form of executable code, scripts, active content, and other software.[2]

… and as such, should not be confused with another security concern called “computer viruses” … Wikipedia again …

A computer virus is a type of malicious software that, when executed, replicates itself by modifying other computer programs and inserting its own code.[1] When this replication succeeds, the affected areas are then said to be “infected” with a computer virus.[2][3]

Confusion could mean that you think a “computer virus” scanning system will protect you from Malware. If the scanning product doesn’t say so, it doesn’t. On our MacBook Pro we got offered the chance to try out a Malware controlling piece of software called Malwarebytes, and we’ve been using its simple interface to scan for Malware at regular intervals. We like it, and think you may like it too … hence the blog posting, for your perspicacious self, like.

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


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

Posted in Coding, eLearning, Operating System, Software, Tutorials | Tagged , , , , , , , , , , , , , , , , | Leave a comment

Spotify and Sonos Bluetooth Speaker Tutorial

Spotify and Sonos Bluetooth Speaker Tutorial

Spotify and Sonos Bluetooth Speaker Tutorial

We can only sit back and admire the “hardware and networking and software aspects” to using a …

  1. Spotify music playing subscription iOS app software arrangement (paid for avoids advertisements) … played via Bluetooth through …
  2. Sonos (Era 100) single speaker

… combination of products. Once arranged, given we had the Spotify app and subscription organized already (as we alluded to with Spotify Bluetooth Speaker Volume Tutorial below), and that is pretty simple as far as Sonos goes (it’s Era 100 pamphlette describing it …

1 Connect the power cord
2 Download the Sonos app for setup

and we did not find it much worse than that (even with our FOBP (“Fear of Bluetooth Pairing”) phobia)), any day or hour of listening is just a case of

  • on our iPhone with the Spotify app associated with the subscription and used to set up the Sonos speaker (and we’re not even going into some additional Wi-Fi functionality available too) …
  • Settings -> Bluetooth … tap (hopefully) On >
  • as required, if Room Name (SONOS) “Not Connected” tap to make it “Connected”
  • open Spotify app
  • pick music to play and tap it’s icon …
  • tap the Play button (perhaps only this once, for the day (and as a sometime media interfacing iOS programmer, that is a feat!))

That’s it! But let’s just hope all those great and entertaining musicians are getting rewarded appropriately too.


Previous relevant Spotify Bluetooth Speaker Volume Tutorial is shown below.

Spotify Bluetooth Speaker Volume Tutorial

Spotify Bluetooth Speaker Volume Tutorial

Am wondering whether anybody else out there is like me and cannot commit to “day to day working memory” …

? Do you think I can nail that last step?! I mean, that last step confounds me every time! Maybe this blog posting can help me, and maybe you, to commit to memory, where on Spotify you can get to change the volume on those bluetooth speakers …


There's a bluetooth icon down near the bottom of the screen a little right of centre (with special consideration for people who think Spotify is all smoke and mirrors)

… which gets you to a draggable volume controller. Yayyyyyyyy!


Previous relevant Spotify Queue Album in Order Primer Tutorial is shown below.

Spotify Queue Album in Order Primer Tutorial

Spotify Queue Album in Order Primer Tutorial

Spotify has changed the way a lot of us listen to music online. The huge pull for its audience are the number of arrangements it has with music labels to be able to build a huge music repository publicly available online.

Using Spotify though, the easiest way to arrange the music playing is via a “Shuffle Play” of the songs of the sources you choose, whether that be by individual artist or podcast or album or genre. Some albums though, at least to our mind, are like a story, and they have been developed with a purpose or theme in mind, and as such, can be best played in the song order chosen by the artist or that artist’s agents, for that album. Don’t think there are any buttons as such for this on the Spotify app, today’s video showing the iOS app version on an iPhone. But this is possible, and the purpose of today’s tutorial is to talk about the Spotify “play queue” and in the process how to achieve this.

  1. Clear the existing queue first by …
    • Tap on song currently playing
    • Tap top right icon … shows songs on the queue
    • Check all the boxes on left
    • Tap “Remove” button at bottom left to clear the queue
    • Go back with down arrow top left icon tap
  2. Search for album name via bottom magnifying glass icon tap … type in album name in resultant textbox … go (swipe) down to Album section and tap the album
  3. Swipe to right on each song of that album in order … and a “Queued” message will briefly verify that operation
  4. Optionally choose more music to be queued up by returning to step 2 above
  5. Your choices will be played in that order after any currently playing song

Have a geek at this demonstrated by us, below …

We hope this might be of some use to some Spotify users out there! Happy listening!

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


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


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

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