ComboBox Primer Tutorial

ComboBox Primer Tutorial

ComboBox Primer Tutorial

Do you remember a blog posting a couple of days ago called Favourites Poll Email Moderation Contenteditable Tutorial featuring …

contenteditable global attribute magic

? Well, that started me rethinking on a very long-running personal desire with our web application work. In the Windows early GUI desktop applications going back to VB.Net and C++ in the latter 1900 years there was a GUI control called “ComboBox” (class) that never failed to impress me. It matches a lot of needs to be presented with a static list of choices in mind, but then want to extend that list as time and situation changes over time. A “ComboBox” can handle it, it being that combination of …

  • dropdown (static) list … and …
  • textbox “extender”

… all manageable sounding in today’s web application wooooorrrrrlllllld, especially, in our minds, having defer
and contenteditable as useful concepts for the latter item above. And so a …

  • dropdown (select) element … nested within a …
  • div contenteditable=true

… paradigm is the basis for our combobox.js external Javascript to feature an Object Oriented looking Javascript Class …


// combobox.js
// External Javascript to extend some HTML like combobox.html allowing for a dynamically created HTML div element "combobox" (ie. dropdown + div contenteditable=true)
// November, 2020
// Called via ...
// <script type='text/javascript' src='combobox.js' defer></script>
// ... or dropdown populated example as per ...
// <script type='text/javascript' src='combobox.js?ddlist=Asia,Africa,Europe,North%20America,South%20America,Australia,Antarctica' defer></script>

class Droptext {
constructor(combobox) {
this.ele = document.createElement('div');
this.ele.id = ('' + combobox).split(';')[0];
if (('' + combobox).indexOf(';') != -1) {
this.ele.setAttribute('data-dropinnards', ('' + combobox).split(';')[1]);
this.ele.setAttribute('data-optionval', "<option value=''></option>");
this.ele.setAttribute('data-focusaway', "<input style=position:absolute;top:-200px;left:-200px; type=text value=></input>");
this.ele.setAttribute('contenteditable', true);
this.ele.innerHTML = ('' + combobox).split(';')[1]; // + "<input style=position:absolute;top:-200px;left:-200px; type=text value=></input>";
}
}
present() {
return this.ele.outerHTML.replace('><select', ' onblur=" var odiv=event.target; var optval=event.target.getAttribute(' + "'" + 'data-optionval' + "'" + '); var fway=event.target.getAttribute(' + "'" + 'data-focusaway' + "'" + '); var umytype=event.target.innerHTML; var alltogether=event.target.getAttribute(' + "'" + 'data-dropinnards' + "'" + ').split(String.fromCharCode(60) + ' + "'" + '/select' + "'" + ')[0]; if (umytype.trim().length == 0) { odiv.innerHTML = event.target.getAttribute(' + "'" + 'data-dropinnards' + "'" + '); } else if (alltogether.indexOf(String.fromCharCode(62) + umytype + String.fromCharCode(60)) != -1) { odiv.innerHTML = alltogether.replace(String.fromCharCode(62) + umytype + String.fromCharCode(60), ' + "' selected'" + ' + String.fromCharCode(62) + umytype + String.fromCharCode(60)) + event.target.getAttribute(' + "'" + 'data-focusaway' + "'" + '); } else { alltogether+=optval.replace(String.fromCharCode(39), String.fromCharCode(39) + umytype).replace(String.fromCharCode(62), String.fromCharCode(62) + umytype); alltogether+=String.fromCharCode(60) + ' + "'" + '/select' + "'" + ' + String.fromCharCode(62); odiv.innerHTML = fway; odiv.innerHTML = alltogether.replace(String.fromCharCode(62) + umytype + String.fromCharCode(60), ' + "' selected'" + ' + String.fromCharCode(62) + umytype + String.fromCharCode(60)) + event.target.getAttribute(' + "'" + 'data-focusaway' + "'" + '); odiv.setAttribute(' + "'" + 'data-dropinnards' + "'" + ',alltogether); } " onkeypress=" event.target.setAttribute(' + "'" + 'data-sofar' + "'" + ', event.target.innerHTML); " onkeydown=" if (event.target.innerHTML.indexOf(String.fromCharCode(60)) != -1) { event.target.innerHTML=' + "''" + '; } "><select');
}
}

class Contents extends Droptext {
constructor(combobox, mod) {
if (('' + combobox) == '') {
var iinn=0;
while (document.getElementById('combobox' + iinn)) {
iinn++;
}
combobox = 'combobox' + iinn;
}
super((combobox + ';' + mod));
this.dropinnards = mod;
}
show() {
return this.present() + "<input style=position:absolute;top:-200px;left:-200px; type=text value=></input>"; // + ', it is a ' + this.dropinnards;
}
}

… and middlemanperson external Javascript …


var ihs = "";
var selconts = location.search.split('ddlist=')[1] ? (ihs + decodeURIComponent(location.search.split('ddlist=')[1].split('&')[0])).split(',') : (ihs + "<select><option value=''></option><option value='Red'>Red</option><option value='Blue'>Blue</option><option value='Yellow'>Yellow</option></select>").split(',');
if (document.head.innerHTML.replace('&ddlist=','?ddlist=').indexOf('?ddlist=') != -1) {
ihs = decodeURIComponent(document.head.replace('&ddlist=','?ddlist=').innerHTML.split('?ddlist=')[1].split('&')[0].split('"')[0].split("'")[0]); // + ',';
if (ihs.trim() != '') { selconts = ihs.split(','); }
}
if (selconts[0].indexOf('<select') != 0) {
var selcont = "<select>";
for (var jiip=0; jiip<selconts.length; jiip++) {
if (selconts[jiip].indexOf('<select') != 0) {
selcont += '<option value="' + selconts[jiip] + '">' + selconts[jiip] + '</option>';
}
}
selcont += "</select>";
mycombobox = new Contents("", selcont);
} else {
mycombobox = new Contents("", selconts[0]);
}
var obody = document.body;
if (document.getElementById('demo')) {
obody = document.getElementById('demo');
} else {
var ofound = false;
var obs = document.getElementsByTagName('div');
for (var iip=0; iip<obs.length; iip++) {
if (obs[iip].innerHTML == '') {
obody = obs[iip];
ofound = true;
}
}
if (!ofound) {
obody.innerHTML += '<div id=demo></div>';
obody = document.getElementById('demo');
}
}
obody.innerHTML += mycombobox.show();

… that suits the need of our proof of concept calling HTML combobox.html live run code …


<!doctype html>
<html>
<head>
<script type='text/javascript' src='combobox.js' defer></script>
</head>
<body>
<div id='demo'></div>
</body>
</html>

Intervening at the “onkeydown” event of the hosting HTML div contenteditable=true is the essence of why the “ComboBox” can be (quite a bit, but not totally) like that forerunner “ComboBox” VB.Net GUI control.

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

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

Leave a Reply

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