Anonymous
Domino 2.0 Rich Internet Applications with IBM Lotus Notes/Domino
You are here: Today » Input control with type-ahead
« The VIEW Lotus Developer2007 Europe
Latest version of the StringBuffer class »

Input control with type-ahead

Making an input field with type-ahead was quite a challenge, but very useful when you want to allow users to enter their own values, but suggest already existing. First I decided to use some clever HTML: the className 'tah' of the span will trigger the JavaScript; the div to show the items found is already present and the span in the span contains the options that already exist. For bigger lists, you would have to retrieve parts of it with Ajax.

The HTML

<span class="tah">
<input id="fDocTags" />
<div></div>
<span>one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,
thirteen,fourteen,fifteen,sixteen</span>
</span>

The CSS

Then I added a little CSS to model the tags:

/* typeahead */
.tah{position:relative}
.tah span{display:none}
.tah div{position:absolute;top:22px;left:0;width:200px;border:solid 1px #ccc;padding:2px;display:none}
.tah div b{display:block;width:100%;cursor:pointer}

'G', my JavaScript global namespace

It has become a habit of mine: collecting all the generic JavaScript functions I need in a global namespace 'G', accompagned by the ever-present $ and $$ shortcuts:

var G={
init:function(){var o=G,n;for(n in o)if(o[n].init)o[n].init()},
set:function(a,b){for(var o in b)a[o]=b[o];return a},
mid:function(a,b,c){var o=a.split(b);return(o.length<2)?'':o[1].split(c)[0]},
last:function(a,b){var o=a.split(b);return o[o.length-1]},
create:function(a,b,c,d){var o=(d||document).createElement(a);G.set(o,b);G.set(o.style,c);return o},
append:function(a,b,c,d){var o=b.tagName?b:G.create(b,c,d);a.appendChild(o);return o}
},
$=function(a){return document.getElementById(a)},
$$=function(a,b){return (b||document).getElementsByTagName(a)}
window.onload=G.init

The 'auto' JavaScript object

I know 'auto' is a bit weird, but I think it stood for Auto Complete at first. Instead of trapping keyboard strokes, I use an observer to check the value of the input field from time to time once this field gets focus. Pay special attention to the 'setCursor' function: it moves the cursor to the end of the field.

G.auto={
init:function(){
    var m=this,o=$$('span'),i
    for(i=0;i<o.length;i++){if(o[i].className=='tah')m.prepare(o[i])}
},
prepare:function(a){var m=this,o=$$('input',a)[0];o.onfocus=m.focus;o.onblur=m.blur},
focus:function(){
    var m=G.auto,o=this,op=this.parentNode
    m.target=o
    m.items=','+$$('span',op)[0].innerHTML+','
    m.div=$$('div',op)[0]
    m.observer=setInterval(m.observe,500)
},
blur:function(){var m=G.auto;clearInterval(m.observer);setTimeout(m.done,100)},
done:function(){G.auto.div.style.display=''},
observe:function(){
    var m=G.auto,v=G.last(m.target.value,','),o,i,q=[],t=m.div
    if(v!='')o=m.items.match(new RegExp(','+v+'[^,]*','gi'))
    if(!o){t.style.display='';return}
    t.innerHTML=''
    for(i=0;i<o.length;i++)G.append(t,'b',{innerHTML:o[i].substr(1),onclick:m.click})
    m.div.style.display='block'
},
click:function(){
    var m=G.auto,o=m.target,v=o.value.split(','),n
    v[v.length-1]=this.innerHTML
    o.value=v.join(',')
    n=o.value.length
    m.setCursor(o,n,n)
},
setCursor:function(a,b,c){
    var r,q='character'
    if(a.setSelectionRange){
        a.setSelectionRange(b,c)
        a.focus()
    }
    else if(a.createTextRange){
        r=a.createTextRange()
        r.collapse(true)
        r.moveEnd(q,c)
        r.moveStart(q,b)
        r.select()
    }
}
}

The result

Here's the sample page. You can test by typing number names like 'seven', 'twelve' separated by commas.

Star rating

20%

Comments

  1. 21.11.2007 00:23:54, Jan Schulz

    Tried it (using opera 9.5beta): tried 'sev' and 'down' -> does not work, I have to use the mouse :-( -> would be great if you could listen for down and up and select the right one. Also: I can get one tag, but not two, the comma does not put the box into 'suggeste-mode' again :-(

    Anyway: nice one :-)

  2. 19/02/2008 14:52:27, Erwin Heeren

    When I try it, the Type Ahead list is displayed, but I cannot select a value from that list :-( Is it just me?

  3. 19/02/2008 19:19:10, Michel Van der Meiren

    You have to click on one with your mouse. That doesn't work?

  4. 20/02/2008 10:18:02, Erwin Heeren

    Works now (sometimes) ... You must click at the exact location and not anywhere in the list.

To add a comment, log in or register as new user. It's free and safe.