ComboBox Form Tutorial

ComboBox Form Tutorial

ComboBox Form Tutorial

Yesterday’s ComboBox Primer Tutorial got us working with new ComboBox div/select elements, but that was just a display mechanism, and not a “collection of data” mechanism. We could code for dynamic select “onchange” event and div “onblur” event logics, which we may allow for into the future, but today’s work is to have our external Javascript work with a parent HTML that has a …

  • form method=GET action=[“here’s looking at you kid”]
  • table with a header (ie. th cells) row … and
  • row with empty data cells (ie. td cells) …

    <table border=20>
    <tr><th>Integer</th><th>Lowercase</th><th>Uppercase</th></tr>
    <tr><td></td><td></td><td></td></tr>
    </table>
  • form submit button

… that can parrot back what a user selected for their ComboBox(es). The external Javascript changes ensure …

  • a mechanism now exists for multiple calls of the external Javascript from the parent HTML … exemplified by …

    <script type='text/javascript' src='combobox.js?ddlist=1,2,3,4' defer></script>
    <script type='text/javascript' src='combobox.js?ddlist=a,b,c,d' defer></script>
    <script type='text/javascript' src='combobox.js?ddlist=A,B,C,D' defer></script>
  • and the default place to hold those resultant ComboBox div/select elements is to empty innerHTML elements (such as those td data cells above) … and …
  • ComboBox div/select elements now get created with a “name” attribute (meaning selections are passed back to [here’s looking at you kid”]
  • ComboBox div/select elements now get class “combobox” applied to them to aid with parent HTML styling CSS such as …

    <style>
    div.combobox { background-color:yellow; }
    select.combobox { background-color:pink; width:95%; }
    </style>

    … means they slot into place into the parent HTML form and be self-returnable (ie. action=[“here’s looking at you kid”])

… so that there can be better practical use made of these ComboBox div/select elements used by our changed external Javascript combobox.js called by our changed parent HTML combobox.htm web application


Previous relevant ComboBox Primer Tutorial is shown below.

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.


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

This entry was posted in eLearning, GUI, Tutorials and tagged , , , , , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

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

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