Value driven web development

We've extended the Autocomplete.Local from Scriptaculous to implement the autocomplete to: field mimicing the Facebook's features. This was a little challenging at the start, but prototype.js and scriptaculous have just made it so much easier.


Concepts

  • json - array of contacts with names and email address and any other fields you wish to search
  • The input box changes size dynamically and reposition itself according to the keystrokes
  • Each 'token' created is an input field, submitting the id of the user or an email address

Straight to the source

Syntax


new Autocompleter.LocalAdvanced(id_of_text_field, id_of_div_to_populate, json_array, options)

The constructor takes four parameters. The first two are, as usual, the id of the monitored textbox, and id of the autocompletion menu. The third is an array of strings that you want to autocomplete from, and the fourth is the options block.

Extra local autocompletion options

Option Default Value Description
search_field "name" Which attribute to search in the json array.
choices 10 How many autocompletion choices to offer
partialSearch off If false, the autocompleter will match entered text only at the beginning of strings in the autocomplete array. Defaults to true, which will match text at the beginning of any word in the strings in the autocomplete array. If you want to search anywhere in the string, additionally set the option fullSearch to true
fullSearch false Search anywhere in autocomplete array strings.
partialChars 2 How many characters to enter before triggering a partial match (unlike minChars, which defines how many characters are required to do any match at all).
ignoreCase true Whether to ignore case when autocompleting

Example

HTML

1
2
3
4
5
6
7
8
9
10
 <div tabindex="-1" id="ids" class="clearfix tokenizer" onclick="$('autocomplete_input').focus()">
<span class="tokenizer_stretcher">^_^</span><span class="tab_stop"><input type="text" id="hidden_input" tabindex="-1"></span>
 <div id="autocomplete_display" class="tokenizer_input"> 
 <input type="text" size="1" tabindex="" id="autocomplete_input"   />
 </div>                                                                          
 </div>

<div id="autocomplete_populate" class="clearfix autocomplete typeahead_list" style="width: 358px; height: auto; overflow-y: hidden;display:none">
 <div class="typeahead_message">Type the name of a friend, friend list, or email address</div>                       
 </div>  

Javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
               (new Image()).src='/inbox/images/token.gif';
                        (new Image()).src='/inbox/images/token_selected.gif';
                        (new Image()).src='/inbox/images/token_hover.gif';
                        (new Image()).src='/inbox/images/token_x.gif';

                        var contacts = [
                        {name:"phoenix zhuang",email:"phoenix@rorcraft.com"}, 
                        {name:"jian xie",email:"jan.xie@rorcraft.com"}, 
                        {name:"isaiah peng",email:"isaiah.peng@rorcraft.com"}, 
                        {name:"chris chan",email:"chris.chan@rorcraft.com"}, 
                        {name:"rex chung",email:"rex@rorcraft.com"},
                        {name:"chung rex",email:"chung@rorcraft.com"},
                        {name:"chan chris",email:"chan@rorcraft.com"},
                        {name:"peng isaiah",email:"peng@rorcraft.com"} ];


                        var typeahead = new Autocompleter.LocalAdvanced('autocomplete_input', 'autocomplete_populate', contacts, {                                                  
                            frequency: 0.1,
                            updateElement: addContactToList,
                            search_field: "name"
                        });
                        var hidden_input = new HiddenInput('hidden_input',typeahead);

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* autcompleter.advancedlocal css */
.tokenizer{min-height:5px;padding:0px 0px 3px 3px;width:100%;background:#fff;font-size:11px;}
.tokenizer_locked{background:#f4f4f4;}
.tokenizer,
.tokenizer *{cursor:text}
.tokenizer input{width:100%;}
.tokenizer .tokenizer_input,
.tokenizer .token{float:left;margin-right:3px;margin-top:3px;}
.tokenizer .tab_stop,
.tokenizer .tokenizer_stretcher{display:block;float:left;overflow:hidden;width:0px;}
.tokenizer .tab_stop{height:0px;}
.tokenizer .tokenizer_stretcher{padding-top:7px;}
#autocomplete_input{width:20px;}
#facebook .tokenizer .tab_stop input{border:0px solid black;display:inline;position:relative;left:-500px;}
#facebook .tokenizer .tokenizer_input_borderless {left:4px;margin-left:-1px;overflow:hidden;position:relative;}
#facebook .tokenizer_input_borderless  #autocomplete_input{border:3px solid white!important;border-left:none;display:block;margin:-3px 3px -4px -2px;padding:0px!important;}
/*IE6-/Win only*/
/*\*/ * html#facebook .tokenizer_input_borderless #autocomplete_input { border:3px solid black;margin: -3px 3px -4px 14px:padding-left:10px; } /**/
.tokenizer div:-moz-first-node{padding-top:1px!important;}
.tokenizer_input{max-width:450px;overflow:hidden;padding:1px 0px;}
#facebook .tokenizer_input input,
.tokenizer_input_shadow{border:0px solid black;outline:0;font-family:'lucida grande', tahoma, verdana, arial, sans-serif;font-size:11px;padding:0px 5px;margin:0 0 -1px 0;white-space:pre;}
.tokenizer_input_shadow{display:inline;left:-10000px;position:absolute;top:-10000px;}
.tokenizer .tokenizer_input_shadow{height:0px;display:block;left:0px;overflow:hidden;position:relative;top:0px;}
div.tokenizer .token{background-image:url('/inbox/images/token.gif');background-repeat:no-repeat;color:black;white-space:nowrap;}
div.tokenizer .token span{background-image:url('/inbox/images/token.gif');background-position:top right;background-repeat:no-repeat;display:block;}
div.tokenizer .token span span{background-position:bottom right;}
div.tokenizer .token span span span{background-position:bottom left;}
div.tokenizer .token span span span span{background-image:none;padding:2px 3px 2px 5px;}
div.tokenizer.tokenizer_locked .token span span span span{padding-right:5px;}
html div.tokenizer_locked .token:hover,
html div.tokenizer_locked .token:hover span{background-image:url('/inbox/images/token.gif');}
div.tokenizer .token:hover,
div.tokenizer .token:hover span{background-image:url('/inbox/images/token_hover.gif');text-decoration:none;}
div.tokenizer .token_selected,
div.tokenizer .token_selected span,
div.tokenizer .token_selected:hover,
div.tokenizer .token_selected:hover span{background-image:url('/inbox/images/token_selected.gif');color:white;text-decoration:none;}
div.tokenizer .token span.x,
div.tokenizer .token span.x_hover,
div.tokenizer .token:hover span.x,
div.tokenizer .token:hover span.x_hover{background-image:url('/inbox/images/token_x.gif');background-position:4px 2px;cursor:pointer;display:inline;padding:0px 6px 0px 5px;}
div.tokenizer.tokenizer_locked .token span.x,
div.tokenizer.tokenizer_locked .token span.x_hover{display:none;}
div.autocomplete {  position:absolute;  width:355px;  background-color:white;  border:1px solid #888;  margin-top:-2px;  padding:0px;}
div.autocomplete ul {  list-style-type:none;margin:0px; padding:0px;}
div.autocomplete ul li.selected { background-color: #ffb;}
div.autocomplete ul li {  list-style-type:none;  display:block;  margin:0;  padding:2px;  height:32px;cursor:pointer;}
/* end of autcompleter.advancedlocal css */

Download the full source

Autocomplete_AdvancedLocal.zip

[update] We've forked a version of the control.js and changed all reference to element.style to setStyle(). It was causing script errors in IE.
http://github.com/rorcraft/scriptaculous/tree/master/src/controls.js

8 Responses to “The Facebook autocomplete address to: field.”

  1. Kyle Says:
    Nice. Any plans on being able to use a web service with this?
  2. Cedric Says:
    Wow, great piece of script. Is it possible to easily limitate the number of "tokens" that a user can add? BR Cedric
  3. Tommy Says:
    This would be useful if I could use JSON for options. Please consider make a Ajax version :-)
  4. Raul Riera Says:
    Is it possible for this to be a Server Side request? instead of a hardcoded list of names?
  5. Raul Riera Says:
    Server side lookup would be ideal here :(
  6. Morten Says:
    Nice Rex. Did you issue a pull request for your style fix? As for the people asking for server side support, there's one here http://www.interiders.com/ but be aware that it spawns a lot of HTTP requests and is quite slow. You should rather try and cache your users in a JS file and work on that using this complete (IMO).
  7. imdad Says:
    is possible to trigger an event when an option from the list of possible options is selected (li.selected)
  8. antonio reuter Says:
    How i get the values of all emails typed?

Sorry, comments are closed for this article.