homepage Welcome to WebmasterWorld Guest from 54.237.249.10
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
Forum Library, Charter, Moderator: open

JavaScript and AJAX Forum

    
OO JavaScript and selects
jetboy




msg:1484726
 2:14 pm on Jan 20, 2006 (gmt 0)

I'm attempting to rewrite some JavaScript code that moves <option>s between <select>s and allows the addition and removal of <option>s. This time around it's an exercise in object-oriented JS, and I need a few clarifications:

1. If I instantiate a new object, I can add new methods such as 'add', 'isUnique' etc. using the prototype method. However, if I instantiate a new Select object I can't add new methods. Neither can I add methods to an existing Select object from my page. Is this correct?

2. If I use cloneNode to deep clone an existing Select, am I under the same set of above restrictions in regard to adding new methods?

3. If I clone a Select, I seem to lose the selectedIndex attribute (which kinda makes sense). Is there any way to keep this without copying it separately from one object to the other?

I've currently got a [code of questionable parentage]ised version running, which refers to newly instantiated objects for the new methods, and the actual on-page Select objects for things like selectedIndex. Not very elegant.

Edit: #*$!ing swear word editor!

 

Bernard Marx




msg:1484727
 2:59 pm on Jan 20, 2006 (gmt 0)

1) Element Prototypes

Mozilla: yes
Opera:
yes

No subtyping, of course, and no good for attaching events.
(See code below, and [mozilla.org...]

IE: no

Emulate the effect with HTCs (urgh)

2) Not sure what you mean.

3) Not that I can think of.


<script type="text/javascript">
if(this.HTMLParagraphElement)
{
alert("HTMLParagraphElement: Yes")
HTMLParagraphElement.prototype.doo = doo;
}
else
{
alert("HTMLParagraphElement: NO")
}

function doo()
{
alert(this.id)
}

/* Find out name of element's constructor */
window.onload = function()
{
alert(document.getElementById('p1'))
}

</script>
<p id="p1" onclick="this.doo()">I like to doo. Click me!</p>


jetboy




msg:1484728
 3:44 pm on Jan 20, 2006 (gmt 0)

Hmmm, I think I'm slightly out of my depth here - swiftly orders copy of JavaScript: The Definitive Guide from Amazon!

Working with the element constructors is something I've completely missed, but it looks like a very nice approach.

Bernard Marx




msg:1484729
 6:48 pm on Jan 20, 2006 (gmt 0)

but it looks like a very nice approach

It would be if the World's Favourite Browser supported it.


From post #1:

However, if I instantiate a new Select object I can't add new methods. Neither can I add methods to an existing Select object from my page. Is this correct?

In fact, No. Most browsers support "expando" properties on pretty much all browser objects (they behave, more or less, like native Javascript objects {Moz:"more",IE:"less"} )

So you can do:

function doo(){ alert(this.tagName)}

myElmRef.aMethod = doo;

Just try not to create circular references.

jetboy




msg:1484730
 6:03 pm on Jan 23, 2006 (gmt 0)

So it turns out I was doing what was suggested anyway, albeit with JS syntax instead of W3C DOM:

Select.prototype.newMethod

instead of:

HTMLSelectElement.prototype.newMethod

which as stated, borks in IE.

But if I were to pick a specific <select>, instead of the constructor:

mySelect = document.getElementById('selectName');

I can add methods using:

mySelect.newMethod

The main downside being that I need to add methods to every object I want to use them for, instead of just the constructor.

Thinking out loud; maybe creating a new 'select with methods', and adding them into the document onLoad might be a better route, copying the options from the existing HTML version before removing it. Possible?

Bernard Marx




msg:1484731
 10:00 pm on Jan 23, 2006 (gmt 0)

It's certainly possible, but it may be more bother than it's worth, and the initialisation will come with a time penalty. At the end of the day, the only thing that's gained is
(1) A cleaner coding style - after the methods have been attached.
(2) The possibility of creating a unified interface.

There is the other option of wrapping our elements in JS objects. This way, the benefits of prototype inheritance become available. This technique used to be used a lot for the more advanced cross-browser DHTML libraries. It's not used so much now, if at all. Among the problems here are

(1) It is very hard to set up such a system that can pass element events up to the wrapper, without also creating circular references between JS objects and elements. These cause memory leaks that can remain for the life of the browser instance - not just the page.

(2) The set of element methods and properties is now much more enhanced. Accessing these properties from the wrapper involves going back down to the wrapped element again.

I would only bother using wrappers if I need the elements to be really "intelligent" (usually some Javascript game, nothing functional), or for larger groupings of elements - a draggable image window perhaps.

jetboy




msg:1484732
 10:38 pm on Jan 23, 2006 (gmt 0)

A wrapper? Adding a method-rich child node to the <select>'s parent, appending the <select> to that node, and using the added one as a kind of API to the <select>? Or something similar?

I wouldn't have thought of that approach, but I can see the attraction. If you have any URLs you can drop/sticky that'd help me investigate this it'd be appreciated. The same goes for using HTCs.

gph




msg:1484733
 6:12 am on Jan 24, 2006 (gmt 0)

I didn't write this, it's from another js forum. I'm posting it just for an htc example.

I agree with Bernard, it's messy, but I can't wait. One day, all browsers will be made this way :)

HTMLElement.htc
<PUBLIC:COMPONENT>
<script type="text/javascript">
for(i in HTMLElement.prototype)element[i]=HTMLElement.prototype[i];
</script>
</PUBLIC:COMPONENT>

test.htm

<html>
<head>
<title>IE HTMLElement.prototype</title>

<!--[if lte IE 6]>
<style type="text/css">
*{behavior:url(HTMLElement.htc)}
</style>
<![endif]-->

<script type="text/javascript">

if(!("HTMLElement" in window))window.HTMLElement=function(){};

HTMLElement.prototype.foo=function(){
alert(this.value)
};

</script>

</head>

<body>
<input type="button" onclick="this.foo()" value="click">
</body>
</html>


Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved