...

HTMLElement prototyping in Safari

jkd
06-03-2005, 08:41 PM
We all know (and love!) the fact that Mozilla exposes element constructors (HTMLParagraphElement, for example) for prototyping. Turns out Opera 8 allows you do to the same thing.

So this leaves Safari, which has actually allowed you to do this since 1.0, *but* doesn't publicly expose the constructors. The below code exports constructors into public variables matching those in Mozilla and Opera 8:

/*
HTMLElement Prototyping in KHTML and WebCore
Copyright (C) 2005 Jason Davis, www.jasonkarldavis.com
Additional thanks to Brothercake, www.brothercake.com

This code is licensed under the LGPL:
http://www.gnu.org/licenses/lgpl.html
*/

if (navigator.vendor == "Apple Computer, Inc." || navigator.vendor == "KDE") { // WebCore/KHTML
function(HTMLConstructors) {
for (var i in HTMLConstructors) {
window["HTML" + i + "Element"] = document.createElement(HTMLConstructors[i]).constructor;
}
}({
Html: "html", Head: "head", Link: "link", Title: "title", Meta: "meta",
Base: "base", IsIndex: "isindex", Style: "style", Body: "body", Form: "form",
Select: "select", OptGroup: "optgroup", Option: "option", Input: "input",
TextArea: "textarea", Button: "button", Label: "label", FieldSet: "fieldset",
Legend: "legend", UList: "ul", OList: "ol", DList: "dl", Directory: "dir",
Menu: "menu", LI: "li", Div: "div", Paragraph: "p", Heading: "h1", Quote: "q",
Pre: "pre", BR: "br", BaseFont: "basefont", Font: "font", HR: "hr", Mod: "ins",

Anchor: "a", Image: "img", Object: "object", Param: "param", Applet: "applet",
Map: "map", Area: "area", Script: "script", Table: "table", TableCaption: "caption",
TableCol: "col", TableSection: "tbody", TableRow: "tr", TableCell: "td",
FrameSet: "frameset", Frame: "frame", IFrame: "iframe"
});

function HTMLElement() {}
HTMLElement.prototype = HTMLHtmlElement.__proto__.__proto__;
var HTMLDocument = document.constructor;
var HTMLCollection = document.links.constructor;
var HTMLOptionsCollection = document.createElement("select").options.constructor;
var Text = document.createTextNode("").constructor;
var Node = Text;
}



In Opera < 8, all elements inherit directly from Object(), so you can still prototype Object() if you need to do element prototyping. Internet Explorer's elements *don't* inherit from Object, oddly enough, so who knows with that browser. In any case, there you go. It also happens to work in Konqueror (AFAIK).

brothercake
06-05-2005, 06:55 PM
Interesting stuff :) So with this as a base, it's a simple as:

HTMLWhateverElement.prototype.whatever

And your library will handle the conversions?

Remind me why it didn't work in Opera 7, and can you give an example of what could be done? Presumably it's not possible to emulate the behavior you're talking about within your library - to pick up on collection prototypes and create Object prototypes from them?

jkd
06-05-2005, 08:30 PM
For Safari and Konq, the script will handle the conversion.

In Opera < 8, elements inherit directly from Object, not HTMLSomethingElement. So you can still prototype:

Object.prototype.test = function() { return this.innerHTML }

And that will show up on the individual elements, however, it will also show up on Array objects, Strings, etc etc. Prototyping Object for this also works in everything *but* Win/IE (haven't checked Mac/IE).

warteschlange
08-09-2005, 02:12 PM
really great Code. :thumbsup:
It works - but - Firefox stops every thing on this line:
function(HTMLConstructors) {
no chance to put an if condition around.
Any ideas, (beside of controlling it from the server) ?
Andres

jkd
08-09-2005, 03:50 PM
Oops, use the code here:
http://blog.codingforums.com/index.php/main/blogentry/element_prototyping_in_safari_konqueror_and_opera/

Needed to wrap the anonymous function in parantheses.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum