Hide This text
This page shows off what the
searchBox widget can do and provides a brief overview
of how to use it and what features/drawbacks it has. It has been developed for inclusion in the
HTMLObject project.
For starters, it is derived from the cvs version of the php.net
search function feature.
We took their code and enhanced and modularized it to meet the purposes we had for a searchable input field, that had select box
tendencies. The php.net website code was designed for one purpose and that was to allow you to select a php function to lookup in their
documentation system. Since their interface was doing 90% of what we wanted and was better than the other search widgets we had seen,
we worked on turning the single purpose code into something that would work for multiple input fields on a page, and would provide a richer
user interface and allow the programmer to easily determine if the users input was an existing entry or something new.
What we developed meets all the goals we had, plus fixes and improves cross browser compatibility with IE, Opera and Konqueror. For the
best user experience, you should be using a recent version of Mozilla or
Mozilla Firefox.
Features:
- Multiple searchBoxes can be defined per page.
- searchBoxes can be defined in multiple forms with the same field name.
- The popup div is anchored to the input field and dynamically figures out its location and width. No need to hard code heights
or widths like the php.net version does.
- searchBoxes can work with a standard array (sorted or unsorted) or an associative array.
- searchBoxes by default will return the users input unaltered.
- searchBoxes can return the users input prefixed with + (for new entries) or = (for existing entries) stored in another form item.
- Supports picking up dynamically created entries to the global data array so that the user sees them the next time they work with the searchBox.
- Multiple searchBoxes can share the same global data array, so that the user can make multiple selections from the same pool of choices.
- searchBoxes allow commonly used user input mechanisms to allow the user to search for data:
- TAB - once, for tab completion (think of the bash shell). twice, moves to the next form item.
- ESC - closes the popup and stops tab completion.
- ENTER - closes the popup and stops tab completion.
- Arrow Up/Down - moves up/down in the popup.
- Page Up/Down - moves up/down in the popup by 5 entries.
- Mouse input - the user can select an entry from the popup using the mouse. If there are more entries
than will fit in the popup, Scroll Up/Down links will be provided at the top/bottom of the popup which
will scroll the entries up/down by 5 entries at a time. Clicking outside of the popup will close the popup.
- The user is not limited as to what they may type into the input field, thus allowing new entries to be specified by the user.
- searchBoxes can provide a help link that gives the user the keyboard and mouse interaction guidelines.
- searchBoxes can allow you to specify code to run in the onfocus event, the first time the searchBox gets focus.
- searchBoxes can allow you to specify code to run in the onblur event when focus is actually leaving the input field.
- The searchBox api provides for methods to dynamically create and delete the searchBox functionality from form fields in your document.
- The popup display code has been fixed to work with Mozilla, IE 5.5+, Konqueror and Opera (tested in 8.0) whereas the php.net version only
works with Mozilla and Opera (tested in 8.0) correctly.
- Keyboard interaction was improved so that regardless of the browser, if the user holds down the up/down arrow or page up/down it will
continue to do that interaction (other than Konqueror). The php.net code only did this in IE, but this is due to the fact that Mozilla does
not appear to re-fire the onkeydown handler whereas IE does. Since Mozilla did continue to fire the onkeypress handler, I was able to
detect the held down condition and react accordingly.
- The popup content was changed from a list of links to be an actual html document (for konqueror to allow the <style> tag to be output which mozilla requires to have the css work) with the entries in a table, where we are doing the onclick handler to detect when an entry has been selected. The code has been generalized so that it is not submitting anywhere when an entry is selected, so that the searchBox widget is more generally usefull (think user selection of accounts in an accounting application - xiwa is starting to use this widget for this purpose). Moving to the table layout allowed the mouse over and keyboard selection to hilight the entire row in the popup and thus provide a more select box looking interface.
Cross browser compatibility is limited in the following aspects:
- IE does not provide the mouse over hilighting of the popup entries - it did at one point but I have not been able to
re-create that and still have Mozilla work.
- Opera and Konqueror will only do the mouse over hilighting if the divs style sheet entries are made in the parent html document.
- Konqueror does not provide the arrow up/down, page up/down key codes, so keyboard interaction is highly limited. TAB, ESC and ENTER
do work though. If you have a textarea on your page and the popup extends over it, you will not be able to select any of the
entries that are over the textarea (at least observed in KDE 3.3.2 on Debian Sarge).
- Opera does not properly ignore the TAB key when instructed to not continue processing it and instead goes to the next form field.
Credit/Blame:
Hacking of php.net code and resulting searchBox widget creation done by:
James A. Pattie <james at pcxperience.com>. Usability ideas and
testing by
JT Moree <moreejt at pcxperience.com>.
Download:
You can get the javascript library
from www.pcxperience.org/searchbox/search-methods.js and use this html page as a sample driver for any applications you need. Alternatively, you can just link to
http://www.pcxperience.org/searchbox/search-methods.js from your application until the licensing issues are resolved and we determine if we can distribute the search-methods.js file as part of the HTMLObject package.
License:
The PHP.net site states this is released under the PHP license, but I need to clarify this with them since that license is dealing with php itself and does not talk about any non-php products that may be licensed under it. I'm hoping they will allow me to license the derived product under the GPL.
Hide This text
How it works and How to deploy it in your website:
The searchBox needs standard input/hidden fields to be defined in your webpage.
Then, in the onload event, you can instantiate
an instance of the searchBox widget to enable the searching features for the specified input field.
An example definition in your onload event handler:
// globally defined array outside your onload event handler function.
var searchItems = new Array(1, 2, 3, 4, 5, 6);
...
// define the testDisplay searchBox...
searchBox(document.testing.testDisplay, null, searchItems, true, false, true, true, '', '');
The meaning of the searchBox arguments:
- document.testing.testDisplay is the input field you want the searchBox functionality added to.
- null - indicates that we are not defining a hidden field or another text field that the users input would be
put into, prefixed with the + (for a new entry), = (for an existing entry from the data array). If you
were to specify a form item that you wanted the users input put into and the data array was an associative array,
the users input would be looked up in the data array and the result, if an entry was found, would be stored in
this field with the prefix of =. So if the data array had an entry 'one' = '1' and the user entered 'one', then
this field would have '=1'. If they entered 'one time', then this field would have '+one time'. If the user does
not enter anything, then this field will be empty and will not be +/= prefixed.
- searchItems is the array of entries the user can search through.
- true - indicates the data array (searchItems) is sorted.
- false - indicates the data array (searchItems) is not an Associative array.
- true - indicates we want to display all entries when the input field is empty. If false, then
when the user hasn't entered anything, no popup will be displayed to give them a clue as to what
entries are available to select from.
- true - indicates that the help link (?) should be output and the mouse handling code should handle the user
selecting the help link or canceling the help popup.
- '' - indicates that we do not want anything to be done in the onfocus handler when the user initially sets focus
to the searchBox form item. If you need something to be done to the searchBox field when the searchBox is initially
selected by the user, specify that code here.
- '' - indicates that we do not want anything to be done in the onblur handler when the user is going to another
form item. If you need something to be done with the users input after they have left the searchBox field,
specify your code here.
What happens when you call searchBox()?
- Your input field is checked to make sure it is a text field.
- If you specified the result field, it is checked to make sure it is a text or hidden field.
- Your data array is checked to make sure you passed something in.
- The popup div is created and attached to the body of your html document.
- The autocomplete feature of the text field is disabled.
- If Help was enabled, we create the div that contains the ? link and place it after the input field.
- If your data array is an associative array, we create a standard array from it, sorted, if you specified that
the data array was sorted; and store the original associative array for later data lookups.
- The onkeypress, onkeydown, onkeyup, onfocus and onblur event handlers are saved from the input field and then
replaced with the searchBox event handlers needed to make this widget work.
- The resulting searchBox object is then stored in the sb_searchBoxes associative array (as formname.fieldname) for use by the
searchBox methods. You should never have to touch this array directly. See below for a list of the
methods that are available for manipulating searchBox objects.
Now you want to know if your input field has searchBox capabilities?
if (searchBoxExists('testing.testDisplay')) { // do something }
Where 'testing.testDisplay' is the name of the input field that you are working with in the format formname.fieldname.
Now you want to delete the searchBox widget?
deleteSearchBox('testing.testDisplay');
Where testing.testDisplay is the name of the input field, in the format formname.fieldname, that we added the searchBox functionality to. This removes the popup div from
the html document and the help div (if help was enabled) and restores the original onkeypress, onkeydown, onkeyup, onfocus and
onblur event handlers that may have been defined for the input field.
What if you want to delete multiple searchBox widgets that are named similarly?
deleteSearchBoxes(/^testing\d?\.test\d?Display$/);
Would delete all searchBoxes that exist named testing.testDisplay, testing.test0Display, ... testing.test9Display. Try it now.
I want to change the data array a searchBox widget is working with, without deleting and re-creating, OR I just added an entry to an associative array and I want TAB completion to work with the new entry.
updateSearchBoxData('testing.testDisplay', test3SearchItems, false, true);
Where you specify the name of the input field to work with, the new data array and whether it is sorted and an associative array. If you just updated an associative array, then you want to just specify the array to update as the array already associated with the searchBox, otherwise the tab completion array won't be properly updated.
Make searchBox 1 use searchBox 2's data array Restore searchBox 1's data array to original
I need to rename the input field (I'm moving a row up/down and renaming fields as I go)
renameSearchBox('testing2.testDisplay', document.testing2.test2Display, document.testing2.test);
Would "move" the searchBox widget entry from testing2.testDisplay to testing2.test2Display and would proceed to setup the
necessary event handlers on the new testing2.test2Display input field, after making sure that testing2.test2Display and testing2.test are
valid - see the searchBox() documentation for more details. If you are not using the result field and thus don't need to know
if the users input is new or not, specify null for the third argument, just like if calling searchBox().
I want to parse the users input and seperate out the +/= prefix.
Use the sb_parseResult(string) function. It takes a string and returns the array
resulting from the regular expression match, where index 0 = the entire string matched,
index 1 = the +/= prefix, index 2 = the users input. If the regular expression match
failed, null is returned.
So if the users input was 'James is Cool!' and it was new and stored in the hidden field as '+James is Cool!', executing:
Try it now
var result = sb_parseResult('+James is Cool!');
alert(result[0]); = '+James is Cool!'
alert(result[1]); = '+'
alert(result[2]); = 'James is Cool!'
I want to know what array the searchBox is using
var result = getSearchBoxData('testing.testDisplay');
Would return null if the specified searchBox doesn't exist, or the data array that the
specified searchBox is currently working with.
I want to change the onblur/onfocus Callback code.
var result = updateSearchBoxHandler('testing.testDisplay', 'onblurCallback', '');
Would change the onblurCallback to be nothing for the testing.testDisplay searchBox field.
Valid values are onblurCallback and onfocusCallback for the second parameter.