By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,900 Members | 1,370 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,900 IT Pros & Developers. It's quick & easy.

Searching a drop-down box with JS. (code sample)

P: n/a
I put this together yesterday, and I thought I'd share it.
It works in both IE and Mozilla Firefox. I posted something
similar to this months back, but it was much longer, and only
worked in IE.

Shawn

function searchList(inText, drpBox){

var iCount;
var regEx = new RegExp(inText, 'i');

for (iCount=0; iCount<drpBox.length; iCount++){
if (drpBox[iCount].value.match(regEx)){
drpBox.selectedIndex = iCount;
break;
}
}

}


Put this on the form near the drop-down box:

<input type="text" name="txtSearch" id="txtSearch" value="search list"
onfocus="if (this.value == 'search list'){ this.value='';}"
onkeyup="searchList(this.value, document.forms['frmAdd'].drpSponsor);"
/><br/>
Jul 23 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a

"Shawn Milo" <ne********@linurati.net> wrote in message
news:c2**************************@posting.google.c om...
for (iCount=0; iCount<drpBox.length; iCount++){
if (drpBox[iCount].value.match(regEx)){
drpBox.selectedIndex = iCount;
break;
}

Don't use break to terminate a loop; make the test condition fail - that's
why it's there:

for (iCount=0; iCount<drpBox.length &&
!drpBox[iCount].value.match(regEx); iCount++)
;
if( iCount != drpBox.length )
drpBox.selectedIndex = iCount;

--
S.C.

Jul 23 '05 #2

P: n/a
Stephen Chalmers wrote:
"Shawn Milo" <ne********@linurati.net> wrote in message
news:c2**************************@posting.google.c om...
for (iCount=0; iCount<drpBox.length; iCount++){
if (drpBox[iCount].value.match(regEx)){
drpBox.selectedIndex = iCount;
break;
}


Don't use break to terminate a loop; make the test condition fail - that's
why it's there:

for (iCount=0; iCount<drpBox.length &&
!drpBox[iCount].value.match(regEx); iCount++)
;
if( iCount != drpBox.length )
drpBox.selectedIndex = iCount;

--
S.C.


break; is perfectly acceptable the way it was used.

Your code works as well, but in my mind, isn't nearly as clear. The first
example says when the match is successful, record the value and leave the
loop. As well, your loop does a wasted assignment every pass through the loop
and has to do one more test of iCount < drpBox.length before exiting. It also
requires a second (redundant) test of drpBox.length inside the loop, which
could lead to odd bugs if it were further away from the loop definition and
you made changes without realizing the dependancy within the loop. If you want
to avoid break; use:

var selectedIndex = null;
for (iCount = 0; iCount < drpBox.length && selectedIndex == null; iCount++) {
if (drpBox[iCount].value.match(regEx)) {
selectedIndex = iCount;
}
}
if (selectedIndex != null) {
drpBox.selectedIndex = selectedIndex;
}

However, I doubt many professional programmers would argue with the use of
break; in the first example. Only those who think break; and continue; should
_never_ be used would object to it. Sometimes you want to use break; or
continue; to make code clearer and easier to read:

for (var i = 0; i < list.length; i++) {
a = list[i];
if (a == null) {
continue;
}
b = a.someProperty;
if (!b) {
continue;
}
c = b.anotherProperty;
if (!c) {
continue;
}
// etc
}

With a loop like the one above, if you nested multiple conditions, you'd soon
be writing code beyond the 40th column, leaving almost no room for real code
before the 80th column. Doing it as a variation on the gauntlet (<url:
http://mindprod.com/jgloss/gauntlet.html />) leaves everything near the left
margin, and makes the exclusion conditions very clear as you read the code.

Loop; Test; Assignment; break; is just another variation on the gauntlet.

--
| Grant Wagner <gw*****@agricoreunited.com>

* Client-side Javascript and Netscape 4 DOM Reference available at:
*
http://devedge.netscape.com/library/...ce/frames.html

* Internet Explorer DOM Reference available at:
*
http://msdn.microsoft.com/workshop/a...ence_entry.asp

* Netscape 6/7 DOM Reference available at:
* http://www.mozilla.org/docs/dom/domref/
* Tips for upgrading JavaScript for Netscape 7 / Mozilla
* http://www.mozilla.org/docs/web-deve...upgrade_2.html
Jul 23 '05 #3

P: n/a
Stephen Chalmers wrote:
"Shawn Milo" <ne********@linurati.net> wrote in message
news:c2**************************@posting.google.c om...


Please do not write attribution novels.
for (iCount=0; iCount<drpBox.length; iCount++){
if (drpBox[iCount].value.match(regEx)){
drpBox.selectedIndex = iCount;
break;
}


Don't use break to terminate a loop; make the test condition fail -
that's why it's there:


Nonsense. That's what the "break" statement is good for: exiting loops
without knowing the test condition and breaking switch()es if the next
case-condition should not be matched or its default statements should
not be executed. I suggest you read on the language we are discussing
about.

Besides, you are disregarding Netiquette and violating Internet/Usenet
standards as well as the Acceptable Use Policy of your Usenet Service
Provider[1] as me@here.com which you use in your "From:" header is not
an e-mail address.
PointedEars
___________
[1] <http://www.tiscali.co.uk/aboutus/aup.html>
Jul 23 '05 #4

P: n/a

"Thomas 'PointedEars' Lahn" <Po************@nurfuerspam.de> wrote in message
news:40**************@PointedEars.de...
Stephen Chalmers wrote:
"Shawn Milo" <ne********@linurati.net> wrote in message
news:c2**************************@posting.google.c om...
Please do not write attribution novels.
for (iCount=0; iCount<drpBox.length; iCount++){
if (drpBox[iCount].value.match(regEx)){
drpBox.selectedIndex = iCount;
break;
}


Don't use break to terminate a loop; make the test condition fail -
that's why it's there:


Nonsense. That's what the "break" statement is good for: exiting loops
without knowing the test condition and breaking switch()es if the next
case-condition should not be matched or its default statements should
not be executed. I suggest you read on the language we are discussing
about.

What exactly might I learn should I read-up on this Mickey Mouse variant of
the proper languages I have been using for years? If you read any reputable
text book on any C-derived language (assuming you can still find one), it
will tell you that 'break' and 'continue' are frowned upon by programmers,
save for the use in the switch statement for which it was designed.
Nonsense. That's what the "break" statement is good for: exiting loops
without knowing the test condition


If you wrote the code, how can you not know the test condition?
To any code-maintainer, the test condition should indicate the only
reason(s) for a loop to end or not start. If one or more actions within the
loop need to terminate further iterations, this should be done by setting
the value of a tested variable, which could be the counter, if there is one
and its final value isn't critical to later statements. Embedded break
statements only confuse the debugging process.
If one were to follow your logic, why not make everything a forever loop and
break out whenever desired conditions are met?
What you advocate, has very similar implications that other vomit-inducing
practice of placing return statements anywhere other than at the end of a
function, which is the only place they will ever belong. I wouldn't be
surprised if you peddle that doctrine also.
While it's unfortunate that you have clearly descended into common
malpractices, it's no reason to have the temerity to accuse others of
talking nonsense.
--
S.C.
Jul 23 '05 #5

P: n/a
Lee
Stephen Chalmers said:


"Thomas 'PointedEars' Lahn" <Po************@nurfuerspam.de> wrote in message
news:40**************@PointedEars.de...
Stephen Chalmers wrote:
> "Shawn Milo" <ne********@linurati.net> wrote in message
> news:c2**************************@posting.google.c om...
Please do not write attribution novels.
>> for (iCount=0; iCount<drpBox.length; iCount++){
>> if (drpBox[iCount].value.match(regEx)){
>> drpBox.selectedIndex = iCount;
>> break;
>> }
>
> Don't use break to terminate a loop; make the test condition fail -
> that's why it's there:


Nonsense. That's what the "break" statement is good for: exiting loops
without knowing the test condition and breaking switch()es if the next
case-condition should not be matched or its default statements should
not be executed. I suggest you read on the language we are discussing
about.

What exactly might I learn should I read-up on this Mickey Mouse variant of
the proper languages I have been using for years? If you read any reputable
text book on any C-derived language (assuming you can still find one), it
will tell you that 'break' and 'continue' are frowned upon by programmers,
save for the use in the switch statement for which it was designed.
Nonsense. That's what the "break" statement is good for: exiting loops
without knowing the test condition

To any code-maintainer, the test condition should indicate the only
reason(s) for a loop to end or not start. If one or more actions within the
loop need to terminate further iterations, this should be done by setting
the value of a tested variable, which could be the counter, if there is one
and its final value isn't critical to later statements. Embedded break
statements only confuse the debugging process. What you advocate, has very similar implications that other vomit-inducing
practice of placing return statements anywhere other than at the end of a
function, which is the only place they will ever belong. I wouldn't be
surprised if you peddle that doctrine also.


If you read a few more text books, you'll find that the
disdain for "break" isn't as complete as you seem to
believe. The more important factor is readability.

I don't know where you got the idea that break wasn't
originally intended for use in loops. Languages that
are much older than C have had the equivalent, even
without a switch equivalent.

Setting the value of the counter other than in the main
loop control is generally a worse practice than using
break. I've used languages where it was forbidden.

Jul 23 '05 #6

P: n/a
Stephen Chalmers wrote:
"Thomas 'PointedEars' Lahn" <Po************@nurfuerspam.de> wrote in message
news:40**************@PointedEars.de...
Stephen Chalmers wrote:
"Shawn Milo" <ne********@linurati.net> wrote in message
news:c2**************************@posting.google.c om...


Please do not write attribution novels.
> for (iCount=0; iCount<drpBox.length; iCount++){
> if (drpBox[iCount].value.match(regEx)){
> drpBox.selectedIndex = iCount;
> break;
> }

Don't use break to terminate a loop; make the test condition fail -
that's why it's there:


Nonsense. That's what the "break" statement is good for: exiting loops
without knowing the test condition and breaking switch()es if the next
case-condition should not be matched or its default statements should
not be executed. I suggest you read on the language we are discussing
about.

What exactly might I learn should I read-up on this Mickey Mouse variant of
the proper languages I have been using for years? If you read any reputable
text book on any C-derived language (assuming you can still find one), it
will tell you that 'break' and 'continue' are frowned upon by programmers,
save for the use in the switch statement for which it was designed.


O'Reilly beg to differ:

"In a simple loop, the test expression is the sole factor that determines when
the loop stops. When the test expression of a simple loop yields false, the loop
terminates. However, as loops become more complex, we may need to arbitrarily
terminate a running loop regardless of the value of the test expression. To do
so, we use the break and continue statements."

<url:
http://skaiste.elekta.lt/Books/O'Reilly/Bookshelfs/books/webdesign/action/ch08_06.htm
/>

As does Sun:

<url: http://java.sun.com/docs/books/tutor...ts/branch.html />

Nonsense. That's what the "break" statement is good for: exiting loops
without knowing the test condition


If you wrote the code, how can you not know the test condition?
To any code-maintainer, the test condition should indicate the only
reason(s) for a loop to end or not start. If one or more actions within the
loop need to terminate further iterations, this should be done by setting
the value of a tested variable, which could be the counter, if there is one
and its final value isn't critical to later statements. Embedded break
statements only confuse the debugging process.
If one were to follow your logic, why not make everything a forever loop and
break out whenever desired conditions are met?
What you advocate, has very similar implications that other vomit-inducing
practice of placing return statements anywhere other than at the end of a
function, which is the only place they will ever belong. I wouldn't be
surprised if you peddle that doctrine also.
While it's unfortunate that you have clearly descended into common
malpractices, it's no reason to have the temerity to accuse others of
talking nonsense.


Quite frankly I find loops with explicit break conditions much easier to
understand then:

for (iCount=0; iCount<drpBox.length && !drpBox[iCount].value.match(regEx);
iCount++)
;
if( iCount != drpBox.length )
drpBox.selectedIndex = iCount;

Your example requires an additional test against the upper-boundary condition to
ensure that you aren't setting selectedIndex to the wrong thing. This means that
if you refactor the loop to use a variable other then iCount, you'll have to
watch out for side effects elsewhere in your code. It also means the scope of
the loop variable needs to be larger then it has to be to still be available
after the loop terminates.

Not to mention that ";" hanging out there, easily deleted by an inexperienced
programmer or missed when reading the source, turning your code into this:

for (iCount=0; iCount<drpBox.length && !drpBox[iCount].value.match(regEx);
iCount++)
if( iCount != drpBox.length )
drpBox.selectedIndex = iCount;

If early returns and break were not meant to be used in these ways, then they
wouldn't work in these ways. If every function/method _required_ a single entry
and exit point, then the (jit) compiler would enforce that requirement. The fact
that no C-based language has such a restriction indicates that early return and
break/continue are meant to be used the way they are used.

If he is "talking nonsense" then I guess O'Reilly and Sun are as well. There's a
whole discussion on this at <url:
http://www.gamedev.net/community/for...opic_id=208237 /> and the
general consensus is that if break/continue are good enough for K&R, they're
good enough for us. I know K&R used break liberally, I just can't find a Web
resource at the moment to demonstrate it.

--
| Grant Wagner <gw*****@agricoreunited.com>

* Client-side Javascript and Netscape 4 DOM Reference available at:
*
http://devedge.netscape.com/library/...ce/frames.html

* Internet Explorer DOM Reference available at:
*
http://msdn.microsoft.com/workshop/a...ence_entry.asp

* Netscape 6/7 DOM Reference available at:
* http://www.mozilla.org/docs/dom/domref/
* Tips for upgrading JavaScript for Netscape 7 / Mozilla
* http://www.mozilla.org/docs/web-deve...upgrade_2.html
Jul 23 '05 #7

P: n/a
Stephen Chalmers wrote:
Embedded break statements only confuse the debugging process.
They also potentially speed up operation. In a client-side language, it can
be important to exit loops and functions at the earliest possible moment, as
soon as you know it's acceptable.
vomit-inducing practice of placing return statements anywhere other
than at the end of a function, which is the only place they will ever
belong. I wouldn't be surprised if you peddle that doctrine also.
While it's unfortunate that you have clearly descended into common
malpractices, it's no reason to have the temerity to accuse others of
talking nonsense.


Returning early is also a "good thing". If, at the top of a function, you
immediately know that you want to exit, why run through the rest of the
function's statements just to reach the end to return a value?

function getSelectValue(sel) {
if (sel==null || sel.options==null || sel.options.length<1) { return
null; }
...

The above is a good example. Right away, we can determine that the value is
not possible to retrieve. Exit immediately. Otherwise we have to do
something like:

function getSelectValue(sel) {
if (sel!=null && sel.options!=null && sel.options.length>0) {
// do the rest of the function
}
}

The first is much easier to read and more efficient.

The whole "only have one return statement" philosophy is old-fashioned, IMO.

--
Matt Kruse
Javascript Toolbox: http://www.JavascriptToolbox.com/
Jul 23 '05 #8

P: n/a
Matt Kruse wrote:
Stephen Chalmers wrote:
Embedded break statements only confuse the debugging process.
They also potentially speed up operation. In a client-side language, it can
be important to exit loops and functions at the earliest possible moment, as
soon as you know it's acceptable.


I doubt there is any significant speed difference between:

function setNodeCssClass(nodeId, cssClass) {
if (!document.getElementById || !nodeId || !cssClass) return false;
var node = document.getElementById(nodeId);
if (!node) return false;
node.className = cssClass;
return (node.className == cssClass);
}

and

function setNodeCssClass(nodeId, cssClass) {
var returnValue = false;
if (document.getElementById && nodeId && cssClass) {
var node = document.getElementById(nodeId);
if (node) {
node.className = cssClass;
returnValue = (node.className == cssClass);
}
}
return returnValue;
}

But I do agree that the first example is (to me at least) much more clear in
it's intent. I do not have to mentally evaluate the nested /if/ structure to see
when and under what possible conditions "returnValue" might be set to true. The
first is a simple early return gauntlet. If each condition along the way isn't
met, false is returned. This continues until the end of the function, at which
point the results of attempting to set node.className are returned.
vomit-inducing practice of placing return statements anywhere other
than at the end of a function, which is the only place they will ever
belong. I wouldn't be surprised if you peddle that doctrine also.
While it's unfortunate that you have clearly descended into common
malpractices, it's no reason to have the temerity to accuse others of
talking nonsense.


Returning early is also a "good thing". If, at the top of a function, you
immediately know that you want to exit, why run through the rest of the
function's statements just to reach the end to return a value?

function getSelectValue(sel) {
if (sel!=null && sel.options!=null && sel.options.length>0) {
// do the rest of the function
}
}


Actually, it would be:

function getSelectValue(sel) {
var returnValue = null;
if (sel!=null && sel.options!=null && sel.options.length>0) {
// do the rest of the function that might set returnValue
}
return returnValue;
}
The first is much easier to read and more efficient.
The problem isn't so much with such a simple example, but when you have multiple
gauntlet conditions guarding the successful completion of the function/method,
you can end up with multiple nested /if/ structures that if they are all
indented even 4 characters quickly use up all the useful space available for
coding before the 80th column.
The whole "only have one return statement" philosophy is old-fashioned, IMO.


Indeed. I used to believe it was important for functions to have a single exit
point, then I discovered that having multiple early returns easier to code,
debug and maintain. Ultimately it's a geek-religion argument, much like the use
of:

while ((line = readLine()) != EOF) {
// use "line"
}

In fact, if the OP is so concerned about keeping everything inside the loop:

for (
var i=0,found=false;
i<sel.options.length && !found;
sel.selectedIndex=(found=regex.test(sel.options[i].value)?i:sel.selectedIndex),i++

);

Gee, that's easy to understand... not.
There's more discussion about gauntlet styles at <url:
http://mindprod.com/jgloss/gauntlet.html />

--
| Grant Wagner <gw*****@agricoreunited.com>

* Client-side Javascript and Netscape 4 DOM Reference available at:
*
http://devedge.netscape.com/library/...ce/frames.html

* Internet Explorer DOM Reference available at:
*
http://msdn.microsoft.com/workshop/a...ence_entry.asp

* Netscape 6/7 DOM Reference available at:
* http://www.mozilla.org/docs/dom/domref/
* Tips for upgrading JavaScript for Netscape 7 / Mozilla
* http://www.mozilla.org/docs/web-deve...upgrade_2.html
Jul 23 '05 #9

P: n/a

"Matt Kruse" <ne********@mattkruse.com> wrote in message
news:cb*********@news4.newsguy.com...----- Original Message -----
From: "Matt Kruse" <ne********@mattkruse.com>

Returning early is also a "good thing". If, at the top of a function, you
immediately know that you want to exit, why run through the rest of the
function's statements just to reach the end to return a value?
I never suggested doing that. To abandon execution of subsequent statements,
you set a flag variable and place all subsequent statements in a sub-block,
which is entered only if the flag is not set.

function getSelectValue(sel) {
if (sel==null || sel.options==null || sel.options.length<1) { return
null; }
...

The above is a good example. Right away, we can determine that the value is not possible to retrieve. Exit immediately. Otherwise we have to do
something like:

function getSelectValue(sel) {
if (sel!=null && sel.options!=null && sel.options.length>0) {
// do the rest of the function
}
}

The first is much easier to read and more efficient.
I do not see how it's more readable, but perhaps that's because in my own
work I'm accustomed to the latter.
The efficiency depends upon how many of the tests end up having to be
performed. However, I would write:

if (sel==null || sel.options==null || sel.options.length<1)
returnValue=null;
else
{
// Do the rest, setting returnValue if applicable.
}

return returnValue;

In any case, that is a comparatively innocuous example. When there is only a
return statement at the end of a function, it is far easier to follow the
flow of the code and determine the reason for termination. When a function
contains several return statements, it becomes like sieve, with one entrance
and several exits, each of which may have to be followed meticulously before
determining the reason for termination. Clearly that practice is never going
to aid readability.

The whole "only have one return statement" philosophy is old-fashioned,

IMO.

If it's old-fashioned then there must have been a time when it wasn't; so
I'd like to know what's changed since then, other than the proliferation of
slapdash coding styles.

--
S.C.
Jul 23 '05 #10

P: n/a
Stephen Chalmers wrote:
I never suggested doing that. To abandon execution of subsequent
statements, you set a flag variable and place all subsequent
statements in a sub-block, which is entered only if the flag is not
set.
So, near the top of your function you determine what the final value will
be, but someone reading your code doesn't know this. You set the return
value, but it might be changed later. You would have to scan all the rest of
the function code to determine what the real return value is. That's
confusing, IMO.

It also opens the door to bugs. If a condition is not coded correctly, the
execution could fall through to the block and the return value accidently
changed, making a hard-to-find bug. In languages like C where you're
allocating memory and have to worry about cleaning up after yourself,
executing early may not be practical in many cases. But in languages like
javascript, you can exit early and leave the cleanup to the garbage
collector, which is easier.
I do not see how it's more readable, but perhaps that's because in my
own work I'm accustomed to the latter.
It's more readable because you don't have to scan more code to figure out
what the return value is, or if there is some block lower in the function
that will execute and change the value. It returns - it's done.
In any case, that is a comparatively innocuous example. When there is
only a return statement at the end of a function, it is far easier to
follow the flow of the code and determine the reason for termination.


That's a matter of opinion, obviously ;)
The whole "only have one return statement" philosophy is
old-fashioned, IMO.

If it's old-fashioned then there must have been a time when it
wasn't; so I'd like to know what's changed since then, other than the
proliferation of slapdash coding styles.


Writing code is like art - not everyone will agree on what is good or bad.
Do a search on this topic and you'll find lots of opinions on the web and
newsgroups. A lot of the opinion depends on the language in question, and
scripting languages like javascript and perl usually prefer exiting early,
while compiled languages like C and C++ tend to prefer single exit points. I
think. :)

--
Matt Kruse
Javascript Toolbox: http://www.JavascriptToolbox.com/
Jul 23 '05 #11

P: n/a
Sorry to disturb with this message, but I'm looking for a certai
"Stephen Chalmers" who's related to the site:

http://www.chalmers.freeserve.co.uk/

(about optic experiments)

Thanks to email me if you're the right "Stephen Chalmers
(ab*@magic.fr)

L. Ab
-
egam

Jul 23 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.