Anyone know a work around?
P.S I do not want to use a text field to solve this, I want this to be
solved within the selection box
Thanks
I find Firefox 1.5 does exactly the same thing.
> Anyone know a work around?
You can use script to 'work around' it, but it's a standard browser
behaviour so modifying it may confuse/annoy your users. Normally
attempting such modification has you chasing your tail to get consistent
behaviour across a reasonable selection of browsers.
> P.S I do not want to use a text field to solve this, I want this to be
> solved within the selection box
A text input is the most common solution (and likely the best) since the
user can see the text being matched and can modify it easily - search
for 'select type ahead' or similar in the CLJ archives.
Below is an example script that does what you ask, it can be optimised
significantly if you have long lists. Lightly tested in Firefox and IE.
<script type="text/javascript">
// Global to remember characters entered
var charsInput = null;
function textMatch(e, sel)
{
var currentSelIdx = sel.selectedIndex;
var e = e || window.event;
var let = String.fromCharCode(e.keyCode);
if (/[\w\d]/.test(let)){
charsInput = (charsInput)? charsInput + let : let;
}
var opts = sel.options;
var re = new RegExp('^' + charsInput,'i');;
for (var i=0, len=opts.length; i<len; ++i){
if (re.test(opts[i].text)){
sel.selectedIndex = i;
return;
}
}
sel.selectedIndex = currentSelIdx;
}
function cleanUp()
{
charsInput = null;
}
</script>
<form action="">
<div>
<select onkeyup="textMatch(event, this);"
onblur="cleanUp();" onclick="cleanUp();">
<option>Aardvarrk
<option>Adam
<option>Aden
<option>Adrian
<option>Ahmed
<option>Arthur
<option>Eve
<option>Evelyn
</select>
</div>
</form>
--
Rob
If a user selects(with a click) Jon, the code will stay on Jon or find
matches around it, so that works. Once that is done, the user has to
click another option in order for the script to restart, so to speak.
Is there a way, to restart the script without a click event?
Let me show you using your code
<form action="">
<div>
<select onkeyup="textMatch(event, this);"
onblur="cleanUp();" onclick="cleanUp();">
<option>Aardvarrk
<option>Adam
<option>Aden
<option>Adrian
<option>Ahmed
<option>Arthur
<option>Eve
<option>Evelyn
</select>
</div>
</form>
if I click Adam...I can cycle through and get to any name, once that is
done the script ends. Lets say the user ends up with Adrian, but
realized after the event that they wanted Eve...they would have to
click again if they did not want to search the list
Know a way around this?
If not, thank you for your Reply Rob, you gave a very helpful start
http://www.oreillynet.com/pub/a/javascript/2003/09/03/dannygoodman.html
Thanks again Rob, for the great start
Goodman's stuff is generally not held in high regard (that is not to say
that mine is any better ;-) ). The typeahead function you linked to
specifically works only in browsers supporting the IE event model. There
is no good reason for that, you could adapt my code to do much the same
thing by adding a timeout to clear the search string if no keys are
pressed within a certain timespan.
You'll have a cross-browser solution that uses less than half the code
that Goodman's solution does.
--
Rob
What the heck. Maybe not half the code, but the stuff below works better
and in Firefox too. Note that it is a bit jerky in IE, that is because
IE will do its own match first, then fire the keyup. So each time you
press a key, IE moves to that option, then calls the function which
likely changes the option based on the search string at that point.
I've added lots of comments to help out.
<script type="text/javascript">
// Global to remember keystrokes
var taObj = {
charsIn : '',
lastIdx : 0,
delay : 1000,
timer : null,
// Sets a timer that will clear the search string if no
// keys pressed before delay ends
setTimer : function(){
clearTimeout(this.timer);
this.timer = setTimeout('taObj.cleanUp()',this.delay);
},
cleanUp : function(){this.charsIn = '';}
}
function typeAhead(e, sel)
{
// Get a reference to the event so can check character entered
var e = e || window.event;
// Get the character entered
var let = String.fromCharCode(e.keyCode);
// If it's a word character or digit, add it to the search string
if (/[\w\d]/.test(let)){
taObj.charsIn += let; //(''==taObj.charsIn)? let : taObj.charsIn;
// Start/restart the timer
taObj.setTimer();
} else {
return;
}
// Get a reference to the list of options
var opts = sel.options;
// Build a regular expression to check with
var re = new RegExp('^' + taObj.charsIn,'i');
// Find a matching option
for (var i=0, len=opts.length; i<len; ++i){
// If find a match, make it selected & return
if (re.test(opts[i].text)){
sel.selectedIndex = i;
// Remember last selected
taObj.lastIdx = i;
return;
}
}
// If no match found, keep last match
sel.selectedIndex = taObj.lastIdx;
}
</script>
<form action="">
<div>
<select onkeyup="typeAhead(event, this);">
<option>Aardvarrk
<option>Adam
<option>Aden
<option>Adrian
<option>Ahmed
<option>Arthur
<option>Eve
<option>EveEve
<option>Evelyn
<option>Terry
<option>Thomas
<option>Trevor