Wrox Home  
Search P2P Archive for: Go

  Return to Index  

asp_web_howto thread: Combo Dropdown Typing


Message #1 by "Chris R. Thompson" <cthompson@n...> on Thu, 14 Mar 2002 10:39:32 -0700
This is a multi-part message in MIME format.

------_=_NextPart_001_01C1CB7F.3374ED1C
Content-Type: text/plain;
	charset="US-ASCII"
Content-Transfer-Encoding: quoted-printable

In VB there are several types of combo boxes.  In ASP there seems to be
only 1 type.  The user can hit the first letter of the item in a box and
continue to hit the letter to scroll it within that character on the
drop down list.  Is there any way to let the user type in what they want
on the list and have it drill down in the list.  Under the current way,
it they typed in "DG" they would first jump to D's then jump to the G's.
I want to be able to jump to the "DG's" if they type "DG".





Any help would be much appreciated.



Chris




Message #2 by "Brian Lowe" <brian.lowe@i...> on Mon, 18 Mar 2002 20:50:31
> In VB there are several types of combo boxes.  In ASP there seems to be
> only 1 type.  The user can hit the first letter of the item in a box and
> continue to hit the letter to scroll it within that character on the
> drop down list.  Is there any way to let the user type in what they want
> on the list and have it drill down in the list.  Under the current way,
> it they typed in "DG" they would first jump to D's then jump to the G's.
> I want to be able to jump to the "DG's" if they type "DG".

Annoying isn't it?

I had exactly the same problem with users needing a drop-down of 2000 
values and to quickly jump to one by starting to type in the string.

I used server-side ASP to generate a client-side JavaScript array filled 
with the values, then used the onKeyUp() event on the client to kick off a 
JavaScript function to filter the SELECT contents to only those entries 
matching the string in the textbox.

With 2000 entires it's a bit slow, but it soon speeds up when the list is 
filtered.

Brian Lowe
---------@

Message #3 by william.sze@s... on Mon, 18 Mar 2002 16:31:59 -0500
Hi Brian,

I'm very interested in the combobox, do you mind post the javascript code?

Thanks
William


                                                                                                                   
                    "Brian Lowe"                                                                                   
                    <brian.lowe@i...       To:     "ASP Web HowTo" <asp_web_howto@p...>                      
                    odia.com>            cc:                                                                       
                                         Subject:     [asp_web_howto] Re: Combo Dropdown Typing                    
                    03/18/2002                                                                                     
                    03:50 PM                                                                                       
                    Please respond                                                                                 
                    to "ASP Web                                                                                    
                    HowTo"                                                                                         
                                                                                                                   
                                                                                                                   




> In VB there are several types of combo boxes.  In ASP there seems to be
> only 1 type.  The user can hit the first letter of the item in a box and
> continue to hit the letter to scroll it within that character on the
> drop down list.  Is there any way to let the user type in what they want
> on the list and have it drill down in the list.  Under the current way,
> it they typed in "DG" they would first jump to D's then jump to the G's.
> I want to be able to jump to the "DG's" if they type "DG".

Annoying isn't it?

I had exactly the same problem with users needing a drop-down of 2000
values and to quickly jump to one by starting to type in the string.

I used server-side ASP to generate a client-side JavaScript array filled
with the values, then used the onKeyUp() event on the client to kick off a
JavaScript function to filter the SELECT contents to only those entries
matching the string in the textbox.

With 2000 entires it's a bit slow, but it soon speeds up when the list is
filtered.

Brian Lowe
---------@





Message #4 by "Phil Frigo" <philfrigo@a...> on Mon, 18 Mar 2002 15:07:14 -0600
In my view, 2000 entries don't really belong in a drop down list.  Waste
of dbase read time and memory.  As far as drop down lists that use the
drill down with sequential lettering goes, I have found that a simple
keyboard error can really through the search algorithms out of wack,
leading to user frustration.

The defacto standard for these drop-down lists now seem to be;

  * You want Indiana, type I for Idaho, Illinois and I again for
Indiana.

It's really not so bad.

Phil Frigo.


-----Original Message-----
From: Brian Lowe [mailto:brian.lowe@i...] 
Sent: Monday, March 18, 2002 8:51 PM
To: ASP Web HowTo
Subject: [asp_web_howto] Re: Combo Dropdown Typing

> In VB there are several types of combo boxes.  In ASP there seems to
be
> only 1 type.  The user can hit the first letter of the item in a box
and
> continue to hit the letter to scroll it within that character on the
> drop down list.  Is there any way to let the user type in what they
want
> on the list and have it drill down in the list.  Under the current
way,
> it they typed in "DG" they would first jump to D's then jump to the
G's.
> I want to be able to jump to the "DG's" if they type "DG".

Annoying isn't it?

I had exactly the same problem with users needing a drop-down of 2000 
values and to quickly jump to one by starting to type in the string.

I used server-side ASP to generate a client-side JavaScript array filled

with the values, then used the onKeyUp() event on the client to kick off
a 
JavaScript function to filter the SELECT contents to only those entries 
matching the string in the textbox.

With 2000 entires it's a bit slow, but it soon speeds up when the list
is 
filtered.

Brian Lowe
---------@


Message #5 by "Brian Lowe" <brian.lowe@i...> on Tue, 19 Mar 2002 09:44:56
> I'm very interested in the combobox, do you mind post the javascript

JavaScript goes in the <HEAD> section of your HTML...
<script language="JavaScript1.2">
function findValue(v) {
  selectedValue.innerText = 'Searching...';
  filterSelect(v)	
}

function reportValue(v) {
  selectedValue.innerText = v;
}

function fillSelect() {
  var oInput = document.getElementById("inputBox");
  oInput.value = ''; // clear it out
  var oSelect = document.getElementById("selectBox");
  oSelect.innerHTML = ''; // clear it out
  var oSelected = document.getElementById("selectedValue");
  oSelected.innerText = 'None selected...';
  for(var i = 0; i<aStrings.length;i++) {
    var oOption = document.createElement("Option");
    oOption.value = aStrings[i];
    oOption.text = aStrings[i];
    oSelect.add(oOption)
  }
}

function filterSelect(s) {
  var oSelect = document.getElementById("selectBox");
  var iCount = 0;
  var iSingle;
  oSelect.innerHTML = ''; // clear it out
  for(var i = 0; i<aStrings.length;i++) {
    if (s.toLowerCase() == aStrings[i].substr(0,s.length).toLowerCase()) {
      var oOption = document.createElement("Option");
      oOption.value = aStrings[i];
      oOption.text = aStrings[i];
      oSelect.add(oOption);
      iCount++;
      iSingle = i
    }
  }
  if (iCount == 1) {
    oSelect.selectedIndex = 0;
    reportValue('Selected value: ' + aStrings[iSingle])
  } else if (iCount == 0) {
    reportValue('No match found');
  } else {
    reportValue('Multiple matches found');
  }
}
</script>

This goes in the <BODY> of your HTML

<form action="#">
<table>
<tr><td colspan=2>Excuse the delay while the page loads.<br>
It's pulling data from a SQL table.<br>
When it's got the data it sends the lot to the client as a JavaScript 
array, then the client fills the select box with all the strings.<br>
As you type in the text box JavaScript watches.<br>
After each key stroke it applies the filter to the list.<br>
If it gets to exactly 1 record, then that's the selection.<br>
If it gets to 0 records you'll have to backspace to kick off the filter 
mechanism again.<br>
You can also click the selected item when it comes into view.</td></tr>
<tr><td>
<input ID="inputBox" value="" onKeyUp="findValue(this.value)"></td>
<td>Choose...</td></tr>
<tr valign=top><td rowspan=2>
<select ID="selectBox" onChange="reportValue('Selected value: ' + 
this.value)" size="15">
<option>Options will</option>
<option>be filled</option>
<option>by JavaScript</option>
<option>in the</option>
<option>onLoad() event.</option>
</select>
</td>
<td ID="selectedValue">None selected...</td></tr>
<tr><td><a href="javascript:fillSelect()">RESET</a><br>
<br>
Resetting causes the list box to be refilled<br>using the unfiltered 
JavaScript array.<br>
It does not requery the server but still takes a while...</td></tr>
<tr><td colspan=2 class="brag"><a href="mailto:brian.lowe@i...?
subject=listSearch.asp">Brian Lowe</a> &copy; Feb 2002</td></tr>
</table>
</form>

and this in your asp code after the body has been sent (so that the user 
gets to see something before the delay while the code fills the array then 
the select list)

<script language="JavaScript1.2">
var aStrings = Array(<%
Response.Write "'" & oRs("ListValue") & "'"
oRs.MoveNext
Do While NOT oRs.EOF
  Response.Write ", '" & oRs("ListValue") & "'"  
  oRs.MoveNext
Loop	%>);
</script>


No doubt someone will come up with a much more efficient and/or elegant 
way to do this.

I had an immediate need and resolved it as quickly as I could. In real 
life you probably want a key value and a different displayed string in the 
list. This just needs a different recordsource and slight change to the 
JavaScript array to be pairs of items rather than individuals.

I'd welcome any feedback to make this more streamlined, cross-browser, etc.

Brian Lowe
---------@
Message #6 by "Tim Morford" <tmorford@n...> on Tue, 19 Mar 2002 09:11:53 -0500
--------------html/asp code ---------------------------------------
<span size="20" name="Form_ID" style="behavior:url(combobox.htc)">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</span>
-------------------end --------------------------------------------




-----------combobox.htc-------------------------------------------

<PUBLIC:COMPONENT tagName="COMBOBOX">
<PUBLIC:property name="textfield" />
<PUBLIC:property name="popup" />
<PUBLIC:attach event="ondocumentready" handler="setUpComboBox" />

<SCRIPT language="JavaScript">
	function setUpComboBox() {
		if (null == popup) {
			element.innerHTML="<select>" + element.innerHTML + "</select>";
			popup = element.children(0);
			element.appendChild(popup);
			var prop;
			for (prop in element) {
				var val = element.getAttribute(prop,3);
				if (val != null && val != "" && prop != "name" && prop != "size") {
					popup.setAttribute(prop,val);
				}
			}
			popup.id = element.name + "_popup";
			popup.attachEvent("onchange", takeValueFromPopup);
			popup.attachEvent("onfocus", popupfocus);
			popup.attachEvent("onblur", popupblur);
		}
		if (null == textfield) {
			textfield = document.createElement("INPUT");
			textfield.id = element.name + '_text';
			textfield.name = element.name;
			textfield.associatedPopup = popup;
			popup.textfield = textfield;
			if (element.size != null && element.size > 0 && popup.currentStyle.width
== "auto") {
				textfield.size=element.size;
			} else {
				textfield.style.posWidth=element.clientWidth-16;
			}
			textfield.attachEvent("onchange",takeValueFromTextfield);
			textfield.attachEvent("onkeyup",completeTyping);
			textfield.attachEvent("onkeydown",txtkeydown);
			element.parentElement.insertBefore(textfield, element);
			textfield.style.marginRight='16px';
			takeValueFromPopupAt(popup);
		}
		popup.style.position="absolute";
		popup.tabIndex=-1;
		popup.style.setExpression("posWidth", "textfield.clientWidth+20",
"JavaScript");
		popup.style.left = '1px';
		popup.findLeftOffset=findLeftOffset;
		popup.style.setExpression("posLeft", "findLeftOffset(textfield)",
"JavaScript");
		popup.style.top = '1px';
		popup.findTopOffset=findTopOffset;
		popup.style.setExpression("posTop", "findTopOffset(textfield)",
"JavaScript");
		popup.style.setExpression("posHeight", "textfield.clientHeight",
"JavaScript");
		popup.style.setExpression("clip","'rect(auto auto auto
'+(textfield.clientWidth+2)+')'", "JavaScript");
		popup.needsblur=false;
	}
	function takeValueFromPopup() {
		takeValueFromPopupAt(event.srcElement);
	}
	function takeValueFromPopupAt(popup) {
		var idx=popup.selectedIndex;
		var textfield=popup.textfield;
		if (idx != null && idx >= 0) {
			textfield.value = popup.options[idx].text;
		}
		if (popup.needsblur) {
			textfield.focus();
			textfield.select();
		}
	}
	function takeValueFromTextfield() {
		var txt = event.srcElement;
		var popup = txt.associatedPopup;
		var idx;
		for(idx=0;idx<popup.options.length;idx++) {
			if (popup.options[idx].text == txt.value) {
				popup.selectedIndex=idx;
				return;
			}
		}
		popup.selectedIndex=-1;
	}
	function popupblur() {
		var popup = event.srcElement;
		popup.needsblur=false;
	}
	function popupfocus() {
		var popup = event.srcElement;
		popup.needsblur=true;
	}
	function txtkeydown() {
		if (event.keyCode == 40) {
			if (popup.selectedIndex < popup.options.length-1)
				popup.selectedIndex += 1;
			takeValueFromPopupAt(popup);
		}
		// Up Arrow
		if (event.keyCode == 38) {
			if (popup.selectedIndex > 0)
				popup.selectedIndex -= 1;
			else if (popup.selectedIndex == -1)
				popup.selectedIndex = popup.options.length-1;
			takeValueFromPopupAt(popup);
		}
	}
	function completeTyping() {
		if (event.keyCode < 0x2f && event.keyCode != 32)
			return;
		var text = event.srcElement.value;
		var popup = event.srcElement.associatedPopup;
		var options = popup.options;
		var i;
		var utext = text.toUpperCase();
		for(i=0;i<options.length;i++) {
			var newtxt = options[i].text;
			var uopt = newtxt.toUpperCase();
			if (uopt != utext && 0 == uopt.indexOf(utext)) {
				var txtrange = event.srcElement.createTextRange();
				event.srcElement.value = text + newtxt.substr(text.length);
				txtrange.moveStart("character", text.length);
				txtrange.select();
				takeValueFromTextfield();
				break;
			}
		}
	}
	function findLeftOffset(elem) {
		var left = 0;
		while (elem.tagName != "BODY") {
			left += elem.offsetLeft;
			elem = elem.offsetParent;
		}
		return left;
	}
	function findTopOffset(elem) {
		var top = 0;
		while (elem.tagName != "BODY") {
			top += elem.offsetTop;
			elem = elem.offsetParent;
		}
		return top;
	}
</SCRIPT>

</PUBLIC:COMPONENT>
---------------------------------end ---------------------------------------
-

Tim Morford
http://www.aspalliance.com/tmorford







> In VB there are several types of combo boxes.  In ASP there seems to be
> only 1 type.  The user can hit the first letter of the item in a box and
> continue to hit the letter to scroll it within that character on the
> drop down list.  Is there any way to let the user type in what they want
> on the list and have it drill down in the list.  Under the current way,
> it they typed in "DG" they would first jump to D's then jump to the G's.
> I want to be able to jump to the "DG's" if they type "DG".





  Return to Index