473,699 Members | 2,628 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

extending a select list

Hi,

The function I've put together below is a rough idea to extend a SELECT
list, starting from:

<body>
<form name="bambam">
<select id="fred">
<option value="1">1</option>
<option value="2">2</option>
</select>

<a onclick="DOMext endSelect('fred ',1000);">exten d</a>
</form>
</body>
....and although it works I'm not convinced I'm doing it correctly. The
intention is to copy the existing list, extend the copy, then replace
the original with the copy.

Any help would be appreciated.

Ian
function DOMextendSelect (id,extent) {

var old = document.getEle mentById(id);
var replacement = old;

// to get the maximum value;
var maxV = Number(replacem ent.options[replacement.opt ions.length-1].value);

var ok = (maxV < extent);

switch(ok) {

case true:

var newOption;
var newOptionText;
var temp;
while(maxV < extent) {
maxV ++;
temp = String(maxV);
newOption = document.create Element("option ");
newOptionText = document.create TextNode(temp);
newOption.value = temp;
replacement.app endChild(newOpt ion.appendChild (newOptionText) .parentNode);
}
old.replaceChil d(replacement.f irstChild,old.f irstChild);
}
Jul 3 '06 #1
4 2270
Ian Richardson wrote:
Hi,

The function I've put together below is a rough idea to extend a SELECT
list, starting from:
You mean add options to a select element.

<body>
<form name="bambam">
<select id="fred">
<option value="1">1</option>
<option value="2">2</option>
</select>

<a onclick="DOMext endSelect('fred ',1000);">exten d</a>
</form>
</body>
...and although it works I'm not convinced I'm doing it correctly. The
intention is to copy the existing list, extend the copy, then replace
the original with the copy.
Why not just add new options?
function DOMextendSelect (id,extent) {

var old = document.getEle mentById(id);
var replacement = old;

// to get the maximum value;
var maxV = Number(replacem ent.options[replacement.opt ions.length-1].value);
There is no need to create a number object, the length property is a
number already. Even if it wasn't, the subtraction operation will
convert it to a number if possible:

var maxV = replacement.opt ions.length - 1;

You don't need to do that, nor do you want to subtract one from the
length. You want the number of options equal to extent, don't you?.

var ok = (maxV < extent);

switch(ok) {

case true:
What? why not:

if (! maxV < extent) return;
But that logic can be encapsulated in a while loop, see below...

var newOption;
var newOptionText;
var temp;
while(maxV < extent) {
maxV ++;
while(maxV++ < extent){
temp = String(maxV);
There is no need to create a string object here, nor to store it in
temp.

newOption = document.create Element("option ");
newOptionText = document.create TextNode(temp);
That will cause problems in at least one well known but buggy browser.
Use the DOM 0's new Option() method, it is better supported:

old.options[old.length] = new Option(maxV);
It's been fully document here many times, search the archives.

newOption.value = temp;
replacement.app endChild(newOpt ion.appendChild (newOptionText) .parentNode);
}
There is no point in copying the existing elements using a very
circuitous method - if it was required at all (and it isn't here), use
cloneNode. You have now added an option to the end of your existing
select element.
old.replaceChil d(replacement.f irstChild,old.f irstChild);
The new option is *not* the first child, it is the last one. The above
will simply replace the firstChild with itself - old.firstChild and
replacement.fir stChild are the same element, since old and replacement
reference the same object.

You've already added the new option to the element - well, you would
have if not for the bugs in the script.
}
There seems little point in replacing an element with a 'copy' of
itself as a child of exactly the same DOM object it is already a child
of.

var replacement = old;
replacement and old already reference the same object, the above does
nothing of use. If they referenced different objects, then might want
to do:

old.parentNode. replaceChild(re placement, old);

But again, you're replacing an element with itself. I think what you
are trying to do is:
function DOMextendSelect (id,extent)
{
if (!document.getE lementById) return;

var sel = document.getEle mentById(id);
var i = sel.length;
while (i < extent){
sel.options[i] = new Option('text ' + i, 'value ' + i);
++i;
}
}
--
Rob

Jul 4 '06 #2
RobG wrote:
Ian Richardson wrote:
>Hi,

The function I've put together below is a rough idea to extend a SELECT
list, starting from:

You mean add options to a select element.
Fair enough - I was writing this email in a hurry.

<snip>
Why not just add new options?
....because when adding options to a select element using the DOM, Opera
is _blindingly_ fast... The application I'm developing could have
hundreds or thousands of options needing to be added.

>function DOMextendSelect (id,extent) {

var old = document.getEle mentById(id);
var replacement = old;

// to get the maximum value;
var maxV = Number(replacem ent.options[replacement.opt ions.length-1].value);

There is no need to create a number object, the length property is a
number already. Even if it wasn't, the subtraction operation will
convert it to a number if possible:
1. The list may not have a first value (and its text), at any
pre-determined value, so it's easier to read the final value.

2. I know Javascript will type convert all over the place. I choose not
to be equally sloppy.
var maxV = replacement.opt ions.length - 1;

You don't need to do that, nor do you want to subtract one from the
length. You want the number of options equal to extent, don't you?.
Not always.

If the list starts at 17 and I was the final entry to be 23...
>var ok = (maxV < extent);

switch(ok) {

case true:

What? why not:

if (! maxV < extent) return;
I could have done without the switch statement, but:

1. I will not have multiple exits from a function.

2. If I'm trying to extend a list which is already at least that long,
the switch statement will skip that code in the fastest way possible,
and only define the other variables and proceed if necessary.

But that logic can be encapsulated in a while loop, see below...
....and it is.

<snip>
>temp = String(maxV);

There is no need to create a string object here, nor to store it in
temp.
There is a perfectly good reason: type conversion. It's slow. Why do it
twice when it can be done once? If you're adding lots of options, why
waste as much time as possible being sloppy?

<snip>
Use the DOM 0's new Option() method, it is better supported:

old.options[old.length] = new Option(maxV);
It's been fully document here many times, search the archives.
I've seen it, I've done it myself. It's in the other half of the code I
didn't include, written for my timing comparisons. It's nice and quick
in Firefox, damnably slow in Internet Exploiter, and Opera can be
measured using a geological clock.

I'm trying top find a faster method for obvious reasons, but I've never
used any of this appendChild, parentNode, etc... stuff before.
>newOption.valu e = temp;
replacement.ap pendChild(newOp tion.appendChil d(newOptionText ).parentNode);
}

There is no point in copying the existing elements using a very
circuitous method - if it was required at all (and it isn't here), use
cloneNode. You have now added an option to the end of your existing
select element.
>old.replaceChi ld(replacement. firstChild,old. firstChild);

The new option is *not* the first child, it is the last one. The above
will simply replace the firstChild with itself - old.firstChild and
replacement.fir stChild are the same element, since old and replacement
reference the same object.
OK, now we've got past the criticism of programming practice and now
down to the core of the issue I'd raised.

I'm now creating the copy of the select list using:

var replacement = old.cloneNode(t rue);

(which I thought I need in the first place!)

....and the value of the last option in the select list using:

var maxV = Number(replacem ent.lastChild.v alue);

....but while the following line works in IE, it fails without error in
Firefox and generates a huge error in Opera 9.

old.replaceNode (replacement,ol d);

Any further help?

Thanks,

Ian
Jul 4 '06 #3

Ian Richardson wrote:
RobG wrote:
Ian Richardson wrote:
[...]
...because when adding options to a select element using the DOM, Opera
is _blindingly_ fast... The application I'm developing could have
hundreds or thousands of options needing to be added.
That sounds disasterous - thousands of options? Oh well...

function DOMextendSelect (id,extent) {

var old = document.getEle mentById(id);
var replacement = old;

// to get the maximum value;
var maxV = Number(replacem ent.options[replacement.opt ions.length-1].value);
There is no need to create a number object, the length property is a
number already. Even if it wasn't, the subtraction operation will
convert it to a number if possible:

1. The list may not have a first value (and its text), at any
pre-determined value, so it's easier to read the final value.
An empty select is invalid HTML, you may have issues on that front -
should a browser render a select that has no options? As far as I
know, they all do. But who's to say they all will, and if they don't
they aren't (strictly) at fault - or are they? What sense will a user
make of a select with no options?

2. I know Javascript will type convert all over the place. I choose not
to be equally sloppy.
How? There is no type conversion, the length property is defined in
the specification as being a number. Converting it from a primitive to
a Number object is simply unnecessary. I suspect that it's slower than
implicit conversion anyway, but in either case the time taken is
infintesimally small and utterly insignificant - it only happens once
per call to the function.

var maxV = replacement.opt ions.length - 1;

You don't need to do that, nor do you want to subtract one from the
length. You want the number of options equal to extent, don't you?.

Not always.

If the list starts at 17 and I was the final entry to be 23...
Then you just want to add options 18 to 23 inclusive - anyhow, I'll
leave that logic to you. I think you've left out too much for me to
know what you are doing here.

var ok = (maxV < extent);

switch(ok) {

case true:
What? why not:

if (! maxV < extent) return;

I could have done without the switch statement, but:

1. I will not have multiple exits from a function.
Then use if - which provides exactly the same functionality as a switch
with only one condition (unless I'm missing something).

if (maxV < extent) {
// add options...
}

2. If I'm trying to extend a list which is already at least that long,
the switch statement will skip that code in the fastest way possible,
and only define the other variables and proceed if necessary.
As will an if, while or do. I think in absolute terms, any of them
will be faster than switch - but we're talking nano seconds here. See
how many loops you need to do with a test harness to get meainingful
timed results.

The general strategy is to write simple, maintainable code avoiding
obvious performance traps. If it then runs slowly, find out where the
slowness is and optimise (if you can) until it's fast enough. Don't
try to optimise what isn't a problem.

[...]
Use the DOM 0's new Option() method, it is better supported:

old.options[old.length] = new Option(maxV);
It's been fully document here many times, search the archives.

I've seen it, I've done it myself. It's in the other half of the code I
didn't include, written for my timing comparisons. It's nice and quick
in Firefox, damnably slow in Internet Exploiter, and Opera can be
measured using a geological clock.

I'm trying top find a faster method for obvious reasons, but I've never
used any of this appendChild, parentNode, etc... stuff before.
Ah, so what you really want is a faster method than new Option()? I'm
not sure there is one specific method that is faster in all browsers.
You can't use createElement in IE, you don't want to use new Option()
because Opera is too slow and if you use innerHTML I'll bet some other
browser drags the chain. Test it and see.

Incidentally, if you decide to do that, don't use the += operator to
concatenate strings in IE, it is very slow (when used thousands of
times in a loop). Better to put the option HTML strings in an array
and use join().

newOption.value = temp;
replacement.app endChild(newOpt ion.appendChild (newOptionText) .parentNode);
}
There is no point in copying the existing elements using a very
circuitous method - if it was required at all (and it isn't here), use
cloneNode. You have now added an option to the end of your existing
select element.
old.replaceChil d(replacement.f irstChild,old.f irstChild);
The new option is *not* the first child, it is the last one. The above
will simply replace the firstChild with itself - old.firstChild and
replacement.fir stChild are the same element, since old and replacement
reference the same object.

OK, now we've got past the criticism of programming practice and now
down to the core of the issue I'd raised.

I'm now creating the copy of the select list using:

var replacement = old.cloneNode(t rue);

(which I thought I need in the first place!)

...and the value of the last option in the select list using:

var maxV = Number(replacem ent.lastChild.v alue);

...but while the following line works in IE, it fails without error in
Firefox and generates a huge error in Opera 9.

old.replaceNode (replacement,ol d);

Any further help?
If you want to use cloneNode (and I don't know that it will be any
faster cross-browser), then as a general case:

var sel = <a select element reference>;
sel.options.len gth = 0; // remove all existing options

// can also replace it with a shallow clone of itself - very fast
but will
// break in older Safari at lest:
sel.parentNode. replaceChild(se l.cloneNode(fal se), sel);

var dummyOpt = new Option(text, value);

while ( <some condition){
sel.options[ i ] = dummyOpt.cloneN ode(true);
}
>From memory that doesn't work properly in IE either, please test...
Using innerHTML:

var optHTML = [];
while ( <some condition){

// You don't need closing tags on option elements in HTML 4
optHTML.push('< option value="' + value + '">' + text;
}
sel.innerHTML = optHTML.join('' );

Previous testing showed innerHTML to be fastest generally. You might
also try testing for outerHTML, and if supported (probably IE, +
Opera?) use that, if not, use new Option. Gets worse the further you
read, huh? :-)

if (sel.outerHTML) {
// similar to innerHTML loop but using outerHTML
} else {
// new option loop...
}

HTH
--
Rob

Jul 4 '06 #4
RobG wrote:
Ian Richardson wrote:
>RobG wrote:
>>Ian Richardson wrote:
[...]
>...because when adding options to a select element using the DOM, Opera
is _blindingly_ fast... The application I'm developing could have
hundreds or thousands of options needing to be added.

That sounds disasterous - thousands of options? Oh well...
The application allows for setting of the start of an event, either by
an explicit date or an offset. Changing any aspect of one keeps
everything together. If the date is changed such that one of the offset
menus needs to explode in size, the user is warned of this and given the
option to roll back the change if necessary.

However, there are certain date restrictions I perhaps should impose,
like maybe limiting the maximum date to 100 or 150 years in the future.

<snip>
>1. The list may not have a first value (and its text), at any
pre-determined value, so it's easier to read the final value.

An empty select is invalid HTML, you may have issues on that front -
should a browser render a select that has no options? As far as I
know, they all do. But who's to say they all will, and if they don't
they aren't (strictly) at fault - or are they? What sense will a user
make of a select with no options?
1. Did I say at any point that I'd have a select list with no options?
No I didn't.

2. I didn't bother to check previously, but now I know why a select list
with no options has a dummy entry added by some browsers!

>2. I know Javascript will type convert all over the place. I choose not
to be equally sloppy.

How? There is no type conversion, the length property is defined in
the specification as being a number. Converting it from a primitive to
a Number object is simply unnecessary. I suspect that it's slower than
implicit conversion anyway, but in either case the time taken is
infintesimally small and utterly insignificant - it only happens once
per call to the function.
In the example I initially provided, it just so happened that the list
started from 1 and each entry had the text and value one higher than the
one before... so in that special case, the numeric value of the last
option was the same as the numeric length.

The length (i.e. number of options) is a number, yet the values of any
attributes are of type string. To be safe when using this string in any
numeric calculations, I'd convert to a number. I've had these sort of
type-related problems before and I'm not going to change my defensive
coding based on your comments.
>> var maxV = replacement.opt ions.length - 1;

You don't need to do that, nor do you want to subtract one from the
length. You want the number of options equal to extent, don't you?.
Not always.

If the list starts at 17 and I was the final entry to be 23...

Then you just want to add options 18 to 23 inclusive - anyhow, I'll
leave that logic to you. I think you've left out too much for me to
know what you are doing here.
Now you're just giving up. I'll explain for you again:

1. Assumption: the list (both the text and value) are integers.

2. Assumption: the numeric gap between each option in the list is 1.

3. Lists can start at any value.

4. For some reason (see above), there is a requirement to add further
options to the end of the list.

5. Adding options should be done in the fastest manner possible, not
only to reduce the time the user is held up, but also because there may
be a large number of options to add.

6. Adding options in a manner which doesn't halt user interaction causes
problems in the browser when the user attempts to interact with the
select list being extended.
Mind you, I thought the idea of providing an explanation (as I did,
albeit nothing like as verbose as this one), together with example code
illustrating what I was trying to do was for people to assist me rather
than attempt to criticise at every opportunity or think I want them to
write it from scratch. I've read enough postings from people who have
not even bothered to show code as evidence they've tried, and the terse
responses.

So much for co-operation.

<snip>
>1. I will not have multiple exits from a function.

Then use if - which provides exactly the same functionality as a switch
with only one condition (unless I'm missing something).
....which you are. if() may be easier to code, but switch is faster. I'd
previously made this claim.

<snip>
As will an if, while or do. I think in absolute terms, any of them
will be faster than switch - but we're talking nano seconds here. See
how many loops you need to do with a test harness to get meainingful
timed results.
The main killers of my application at the moment are:

1. Some unbelievably long string handling.
2. Extending options.

I've recently discovered that long string handling is a bad bad thing,
and I'll be looking at using a big array of short(ish) strings and a join().

I was looking at extending options as I had originally described as both
an exercise in programming, and as trying to find out if it would give
me any speed advantage.

The short answer is it appears to be up to 10% slower than the DOM 0
method in IE and Firefox, but it's around 30 times quicker in Opera!

<snip>
Ah, so what you really want is a faster method than new Option()? I'm
not sure there is one specific method that is faster in all browsers.
You can't use createElement in IE, you don't want to use new Option()
because Opera is too slow and if you use innerHTML I'll bet some other
browser drags the chain. Test it and see.
I wasn't necessarily looking for or expecting to find one method that's
faster for all browsers, but being able to optimise this area for one
browser is a good thing.
Incidentally, if you decide to do that, don't use the += operator to
concatenate strings in IE, it is very slow (when used thousands of
times in a loop). Better to put the option HTML strings in an array
and use join().
I wasn't doing that but, as I've mentioned above, I will be looking at
join() for some other string handling.

<snip>

As you can probably gather, I've now found a solution that works (and
only two lines needed changing from my original posting). It's only a
(huge) speed improvement for Opera (and for IE it gets exponentially
slower - I may look at extending a chunk at a time), but it proves the
point to me.

Ian
Jul 4 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
5615
by: NadaHombre | last post by:
Hello, If I want to make a class which is a stack of objects of some specific type (not just "Objects"), what is the best way to do it? I wonder if there is some generally accepted "best" way to do this, because it must come up a lot. I personally create a new class which mimics all the methods of java.util.Stack , and keeps a java.util.Stack as a private instance variable. The new class changes the return types of pop and peek and...
4
2783
by: Alicia Haumann | last post by:
I accidentally sent this to webmaster@python.org, so this could be a duplicate if "webmaster" forwards it to this list. :{ Hi, there. Thanks for any help that can be offered. I've been working with Python for a year or more now, but only doing simple extending in C/C++. I'm now attempting some embedding and several questions have come to mind. BTW - I'm running Windows 2000 with Python23 and VisualC++ developers
8
5435
by: Mark Olbert | last post by:
I'm writing a custom MembershipProvider which uses a custom class derived from MembershipUser (basically, the derived class adds a field to the MembershipUser base class). When I try to configure my website using the ASP.NET Configuration tool, and go to the Security page, I get the following error: Could not load type 'OMLMembershipUser' from assembly 'App_Code.olsckwwk, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Yet...
20
1513
by: Keith Elder | last post by:
I ran into a unique situation today whereby I have a core library that uses generics to return users from Active Directory. Example: List<ADUser> users = ADUser.GetByName("First", "Last"); This works great. However, what I need to do is extend the ADUser object like so: class DataGridUser : ADUser {
5
3827
by: vbgunz | last post by:
Hello everyone. I own two books. Learning Python and Python in a nutshell. When cross referencing the two books to try and clarify the ideas behind extending methods and delegates, this is where confusion veered it's ugly head :( Learning Python explains on page 324: Class Interface Techniques (21.3.3 in the ebook) the following is an extender method. ''' #################################### '''
1
1856
by: jeremito | last post by:
I am trying to learn how to extend and/or embed Python. I have looked at the document "Extending and Embedding the Python Interpreter" and also "Python/C API Reference Manual. In the examples shown in "Extending..." there are some things I ma not familiar with so I turn to the index in the Reference Manual, but they are not listed. For example, PyEval_CallObject and PyDict_GetAttrString. My question is this: Is the documentation out of...
3
1890
by: Jeff | last post by:
Hey ASP.NET 2.0 I'm trying to extend the MembershipUser class, and have encounter a problem: << See in the middle of this post for info about why I do this >> << See below of this post for the source code of Contact class >> public class Contact : MembershipUser
3
3675
by: katis | last post by:
Hi all :) Is it posible in xsd to change only minOccurs value of element in complex type by extending this type? The problem I'm trying to solve is this: I have two complex types - "TextField" and "FileChooser". Here is definition of "TextField" <xsd:complexType name="TextField">
0
2109
by: Tim Spens | last post by:
--- On Fri, 6/27/08, Tim Spens <t_spens@yahoo.comwrote: I think I know where the problem is but I'm unsure how to fix it. When I call Register_Handler(...) from python via callback.setHandler1(callback1) this only seems to affect pythons ability to trigger an "event" in c. PyObject *Handler is always NULL even after I call Register_Handler(...). I thought there was some magic here that was assigning the pointer *Handler to my python...
0
8613
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9172
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9032
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8908
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8880
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
4374
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4626
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3054
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2344
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.