We wanted to build on the methodologies of the recent ComboBox Primer Tutorial as a basis for an HTML inhouse “combo” element combining …
- div contenteditable=true … nesting a …
- meter element
… because we think adding keyboard functionality to a meter element (which, as we showed with yesterday’s CSS Outline and Border via Javascript jQuery Tutorial can be an interactive clickable tool just within its own onclick event logic) might be quite useful as a “numerical readout” tool. We have a few ideas for it, but as of today … well … it’s a first draft and needs more work. But this does not mean it is not worth trying as you can do below for HTML supervisor combometer.htm of external Javascript combometer.js‘s live run below …
Previous relevant ComboBox Primer Tutorial is shown below.
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.
If this was interesting you may be interested in this too.