5e0bf2a69f2d8f61d11982262bffac66f31022bd
[WebKit-https.git] / WebCore / bindings / js / kjs_html.cpp
1 // -*- c-basic-offset: 4 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "kjs_html.h"
24
25 #include "DocLoader.h"
26 #include "EventNames.h"
27 #include "Frame.h"
28 #include "HTMLAppletElement.h"
29 #include "HTMLAreaElement.h"
30 #include "HTMLBRElement.h"
31 #include "HTMLBaseFontElement.h"
32 #include "HTMLBlockquoteElement.h"
33 #include "HTMLBodyElement.h"
34 #include "HTMLDocument.h"
35 #include "HTMLEmbedElement.h"
36 #include "HTMLFieldSetElement.h"
37 #include "HTMLFontElement.h"
38 #include "HTMLFormElement.h"
39 #include "HTMLFrameSetElement.h"
40 #include "HTMLHRElement.h"
41 #include "HTMLHeadingElement.h"
42 #include "HTMLHtmlElement.h"
43 #include "HTMLIFrameElement.h"
44 #include "HTMLImageElement.h"
45 #include "HTMLIsIndexElement.h"
46 #include "HTMLLIElement.h"
47 #include "HTMLLabelElement.h"
48 #include "HTMLLegendElement.h"
49 #include "HTMLMapElement.h"
50 #include "HTMLMenuElement.h"
51 #include "HTMLModElement.h"
52 #include "HTMLNames.h"
53 #include "HTMLObjectElement.h"
54 #include "HTMLOptionElement.h"
55 #include "HTMLOptionsCollection.h"
56 #include "HTMLParagraphElement.h"
57 #include "HTMLParamElement.h"
58 #include "HTMLPreElement.h"
59 #include "HTMLQuoteElement.h"
60 #include "HTMLScriptElement.h"
61 #include "HTMLSelectElement.h"
62 #include "HTMLTableCaptionElement.h"
63 #include "HTMLTableCellElement.h"
64 #include "HTMLTableColElement.h"
65 #include "HTMLTableElement.h"
66 #include "HTMLTableRowElement.h"
67 #include "HTMLTableSectionElement.h"
68 #include "JSHTMLImageElement.h"
69 #include "JSHTMLOptionsCollection.h"
70 #include "NameNodeList.h"
71 #include "RenderLayer.h"
72 #include "Text.h"
73 #include "kjs_css.h"
74 #include "kjs_events.h"
75 #include "kjs_proxy.h"
76 #include "kjs_window.h"
77 #include <math.h>
78
79 #include "kjs_html.lut.h"
80
81 using namespace WebCore;
82 using namespace HTMLNames;
83 using namespace EventNames;
84
85 namespace KJS {
86
87 class HTMLElementFunction : public InternalFunctionImp {
88 public:
89   HTMLElementFunction(ExecState* exec, int i, int len, const Identifier& name);
90   virtual JSValue *callAsFunction(ExecState* exec, JSObject* thisObj, const List&args);
91 private:
92   int id;
93 };
94
95 /* 
96 @begin JSHTMLDocumentProtoTable 8
97 clear                 JSHTMLDocument::Clear             DontDelete|Function 0
98 open                  JSHTMLDocument::Open              DontDelete|Function 0
99 close                 JSHTMLDocument::Close             DontDelete|Function 0
100 write                 JSHTMLDocument::Write             DontDelete|Function 1
101 writeln               JSHTMLDocument::WriteLn           DontDelete|Function 1
102 getElementsByName     JSHTMLDocument::GetElementsByName DontDelete|Function 1
103 captureEvents         JSHTMLDocument::CaptureEvents     DontDelete|Function 0
104 releaseEvents         JSHTMLDocument::ReleaseEvents     DontDelete|Function 0
105 @end
106 */
107 KJS_IMPLEMENT_PROTOFUNC(JSHTMLDocumentProtoFunc)
108 KJS_IMPLEMENT_PROTOTYPE("HTMLDocument", JSHTMLDocumentProto, JSHTMLDocumentProtoFunc)
109
110 JSValue *JSHTMLDocumentProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
111 {
112     if (!thisObj->inherits(&JSHTMLDocument::info))
113         return throwError(exec, TypeError);
114     HTMLDocument &doc = *static_cast<HTMLDocument*>(static_cast<JSHTMLDocument*>(thisObj)->impl());
115     
116     switch (id) {
117         case JSHTMLDocument::Clear: // even IE doesn't support that one...
118                                     //doc.clear(); // TODO
119             return jsUndefined();
120         case JSHTMLDocument::Open:
121             // For compatibility with other browsers, pass open calls with more than 2 parameters to the window.
122             if (args.size() > 2) {
123                 Frame *frame = doc.frame();
124                 if (frame) {
125                     Window *window = Window::retrieveWindow(frame);
126                     if (window) {
127                         JSObject* functionObject = window->get(exec, "open")->getObject();
128                         if (!functionObject || !functionObject->implementsCall())
129                             return throwError(exec, TypeError);
130                         return functionObject->call(exec, window, args);
131                     }
132                 }
133                 return jsUndefined();
134             }
135             // In the case of two parameters or fewer, do a normal document open.
136             doc.open();
137             return jsUndefined();
138         case JSHTMLDocument::Close:
139             doc.close();
140             return jsUndefined();
141         case JSHTMLDocument::Write:
142         case JSHTMLDocument::WriteLn: {
143             // DOM only specifies single string argument, but NS & IE allow multiple
144             // or no arguments
145             String str = "";
146             for (int i = 0; i < args.size(); i++)
147                 str += args[i]->toString(exec);
148             if (id == JSHTMLDocument::WriteLn)
149                 str += "\n";
150             doc.write(str);
151             return jsUndefined();
152         }
153         case JSHTMLDocument::GetElementsByName:
154             return toJS(exec, doc.getElementsByName(args[0]->toString(exec)).get());
155         case JSHTMLDocument::CaptureEvents:
156         case JSHTMLDocument::ReleaseEvents:
157             // Do nothing for now. These are NS-specific legacy calls.
158             break;
159     }
160     
161     return jsUndefined();
162 }
163
164
165 // FIXME: functions should be in the prototype
166 const ClassInfo JSHTMLDocument::info =
167   { "HTMLDocument", &JSDocument::info, &HTMLDocumentTable, 0 };
168 /* Source for HTMLDocumentTable. Use "make hashtables" to regenerate.
169 @begin HTMLDocumentTable 30
170   title                 JSHTMLDocument::Title             DontDelete
171   referrer              JSHTMLDocument::Referrer          DontDelete|ReadOnly
172   domain                JSHTMLDocument::Domain            DontDelete
173   URL                   JSHTMLDocument::URL               DontDelete|ReadOnly
174   body                  JSHTMLDocument::Body              DontDelete
175   location              JSHTMLDocument::Location          DontDelete
176   cookie                JSHTMLDocument::Cookie            DontDelete
177   images                JSHTMLDocument::Images            DontDelete|ReadOnly
178   embeds                JSHTMLDocument::Embeds            DontDelete|ReadOnly
179   plugins               JSHTMLDocument::Embeds            DontDelete|ReadOnly
180   applets               JSHTMLDocument::Applets           DontDelete|ReadOnly
181   links                 JSHTMLDocument::Links             DontDelete|ReadOnly
182   forms                 JSHTMLDocument::Forms             DontDelete|ReadOnly
183   anchors               JSHTMLDocument::Anchors           DontDelete|ReadOnly
184   scripts               JSHTMLDocument::Scripts           DontDelete|ReadOnly
185   all                   JSHTMLDocument::All               
186   bgColor               JSHTMLDocument::BgColor           DontDelete
187   fgColor               JSHTMLDocument::FgColor           DontDelete
188   alinkColor            JSHTMLDocument::AlinkColor        DontDelete
189   linkColor             JSHTMLDocument::LinkColor         DontDelete
190   vlinkColor            JSHTMLDocument::VlinkColor        DontDelete
191   lastModified          JSHTMLDocument::LastModified      DontDelete|ReadOnly
192   height                JSHTMLDocument::Height            DontDelete|ReadOnly
193   width                 JSHTMLDocument::Width             DontDelete|ReadOnly
194   dir                   JSHTMLDocument::Dir               DontDelete
195   designMode            JSHTMLDocument::DesignMode        DontDelete
196 #potentially obsolete array properties
197 # layers
198 # plugins
199 # tags
200 #potentially obsolete properties
201 # embeds
202 # ids
203 @end
204 */
205
206 JSHTMLDocument::JSHTMLDocument(ExecState* exec, HTMLDocument *d)
207   : JSDocument(exec, d)
208 {
209     setPrototype(JSHTMLDocumentProto::self(exec));
210 }
211
212 JSValue *JSHTMLDocument::namedItemGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
213 {
214   JSHTMLDocument *thisObj = static_cast<JSHTMLDocument*>(slot.slotBase());
215   HTMLDocument &doc = *static_cast<HTMLDocument*>(thisObj->impl());
216
217   String name = propertyName;
218   RefPtr<WebCore::HTMLCollection> collection = doc.documentNamedItems(name);
219
220   if (collection->length() == 1) {
221     WebCore::Node* node = collection->firstItem();
222     Frame *frame;
223     if (node->hasTagName(iframeTag) && (frame = static_cast<WebCore::HTMLIFrameElement*>(node)->contentFrame()))
224       return Window::retrieve(frame);
225     return toJS(exec, node);
226   }
227
228   return getHTMLCollection(exec, collection.get());
229 }
230
231 JSValue *JSHTMLDocument::getValueProperty(ExecState* exec, int token) const
232 {
233   HTMLDocument& doc = *static_cast<HTMLDocument*>(impl());
234
235   FrameView* view = doc.view();
236   Frame* frame = doc.frame();
237
238   HTMLElement* body = doc.body();
239   HTMLBodyElement* bodyElement = (body && body->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(body) : 0;
240     
241   switch (token) {
242   case Title:
243     return jsString(doc.title());
244   case Referrer:
245     return jsString(doc.referrer());
246   case Domain:
247     return jsString(doc.domain());
248   case URL:
249     return jsString(doc.URL());
250   case Body:
251     return toJS(exec, body);
252   case Location:
253     if (Window* win = Window::retrieveWindow(frame))
254       return win->location();
255     return jsUndefined();
256   case Cookie:
257     return jsString(doc.cookie());
258   case Images:
259     return getHTMLCollection(exec, doc.images().get());
260   case Embeds:
261     return getHTMLCollection(exec, doc.embeds().get());
262   case Applets:
263     return getHTMLCollection(exec, doc.applets().get());
264   case Links:
265     return getHTMLCollection(exec, doc.links().get());
266   case Forms:
267     return getHTMLCollection(exec, doc.forms().get());
268   case Anchors:
269     return getHTMLCollection(exec, doc.anchors().get());
270   case Scripts:
271     return getHTMLCollection(exec, doc.scripts().get());
272   case All:
273     // If "all" has been overwritten, return the overwritten value
274     if (JSValue *v = getDirect("all"))
275       return v;
276     else
277       return getAllHTMLCollection(exec, doc.all().get());
278   case BgColor:
279     if (!bodyElement)
280       return jsUndefined();
281     return jsString(bodyElement->bgColor());
282   case FgColor:
283     if (!bodyElement)
284       return jsUndefined();
285     return jsString(bodyElement->text());
286   case AlinkColor:
287     if (!bodyElement)
288       return jsUndefined();
289     return jsString(bodyElement->aLink());
290   case LinkColor:
291     if (!bodyElement)
292       return jsUndefined();
293     return jsString(bodyElement->link());
294   case VlinkColor:
295     if (!bodyElement)
296       return jsUndefined();
297     return jsString(bodyElement->vLink());
298   case LastModified:
299     return jsString(doc.lastModified());
300   case Height:
301     return jsNumber(view ? view->contentsHeight() : 0);
302   case Width:
303     return jsNumber(view ? view->contentsWidth() : 0);
304   case Dir:
305     if (!body)
306       return jsString("");
307     return jsString(body->dir());
308   case DesignMode:
309     return jsString(doc.inDesignMode() ? "on" : "off");
310   default:
311     assert(0);
312     return jsUndefined();
313   }
314 }
315
316 bool JSHTMLDocument::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
317 {
318   HTMLDocument &doc = *static_cast<HTMLDocument*>(impl());
319
320   String name = propertyName;
321   if (doc.hasNamedItem(name) || doc.hasDocExtraNamedItem(name)) {
322     slot.setCustom(this, namedItemGetter);
323     return true;
324   }
325
326   return getStaticValueSlot<JSHTMLDocument, JSDocument>(exec, &HTMLDocumentTable, this, propertyName, slot);
327 }
328
329 void JSHTMLDocument::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
330 {
331     lookupPut<JSHTMLDocument, JSDocument>(exec, propertyName, value, attr, &HTMLDocumentTable, this);
332 }
333
334 void JSHTMLDocument::putValueProperty(ExecState* exec, int token, JSValue *value, int /*attr*/)
335 {
336   DOMExceptionTranslator exception(exec);
337   HTMLDocument &doc = *static_cast<HTMLDocument*>(impl());
338   HTMLElement* body = doc.body();
339   HTMLBodyElement* bodyElement = (body && body->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(body) : 0;
340
341   switch (token) {
342   case Title:
343     doc.setTitle(value->toString(exec));
344     break;
345   case Body:
346     doc.setBody(toHTMLElement(value), exception);
347     break;
348   case Domain: // not part of the DOM
349     doc.setDomain(value->toString(exec));
350     break;
351   case Cookie:
352     doc.setCookie(value->toString(exec));
353     break;
354   case Location: {
355     Frame *frame = doc.frame();
356     if (frame)
357     {
358       DeprecatedString str = value->toString(exec);
359
360       // When assigning location, IE and Mozilla both resolve the URL
361       // relative to the frame where the JavaScript is executing not
362       // the target frame.
363       Frame *activePart = static_cast<ScriptInterpreter*>( exec->dynamicInterpreter() )->frame();
364       if (activePart)
365         str = activePart->document()->completeURL(str);
366
367       // We want a new history item if this JS was called via a user gesture
368       bool userGesture = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->wasRunByUserGesture();
369       frame->scheduleLocationChange(str, activePart->referrer(), !userGesture);
370     }
371     break;
372   }
373   case BgColor:
374     if (bodyElement)
375       bodyElement->setBgColor(value->toString(exec));
376     break;
377   case FgColor:
378     if (bodyElement)
379       bodyElement->setText(value->toString(exec));
380     break;
381   case AlinkColor:
382     if (bodyElement) {
383       // this check is a bit silly, but some benchmarks like to set the
384       // document's link colors over and over to the same value and we
385       // don't want to incur a style update each time.
386       String newColor = value->toString(exec);
387       if (bodyElement->aLink() != newColor)
388         bodyElement->setALink(newColor);
389     }
390     break;
391   case LinkColor:
392     if (bodyElement) {
393       // this check is a bit silly, but some benchmarks like to set the
394       // document's link colors over and over to the same value and we
395       // don't want to incur a style update each time.
396       String newColor = value->toString(exec);
397       if (bodyElement->link() != newColor)
398         bodyElement->setLink(newColor);
399     }
400     break;
401   case VlinkColor:
402     if (bodyElement) {
403       // this check is a bit silly, but some benchmarks like to set the
404       // document's link colors over and over to the same value and we
405       // don't want to incur a style update each time.
406       String newColor = value->toString(exec);
407       if (bodyElement->vLink() != newColor)
408         bodyElement->setVLink(newColor);
409     }
410     break;
411   case Dir:
412     if (body)
413       body->setDir(value->toString(exec));
414     break;
415   case DesignMode:
416     {
417       String modeString = value->toString(exec);
418       Document::InheritedBool mode;
419       if (equalIgnoringCase(modeString, "on"))
420         mode = Document::on;
421       else if (equalIgnoringCase(modeString, "off"))
422         mode = Document::off;
423       else
424         mode = Document::inherit;
425       doc.setDesignMode(mode);
426       break;
427     }
428   case All:
429     // Add "all" to the property map.
430     putDirect("all", value);
431     break;
432   }
433 }
434
435 // -------------------------------------------------------------------------
436
437 const ClassInfo JSHTMLElement::caption_info = { "HTMLTableCaptionElement", &JSHTMLElement::info, &HTMLTableCaptionElementTable, 0 };
438 const ClassInfo JSHTMLElement::col_info = { "HTMLTableColElement", &JSHTMLElement::info, &HTMLTableColElementTable, 0 };
439 const ClassInfo JSHTMLElement::embed_info = { "HTMLEmbedElement", &JSHTMLElement::info, &HTMLEmbedElementTable, 0 };
440 const ClassInfo JSHTMLElement::frameSet_info = { "HTMLFrameSetElement", &JSHTMLElement::info, &HTMLFrameSetElementTable, 0 };
441 const ClassInfo JSHTMLElement::frame_info = { "HTMLFrameElement", &JSHTMLElement::info, &HTMLFrameElementTable, 0 };
442 const ClassInfo JSHTMLElement::iFrame_info = { "HTMLIFrameElement", &JSHTMLElement::info, &HTMLIFrameElementTable, 0 };
443 const ClassInfo JSHTMLElement::info = { "HTMLElement", &JSElement::info, &HTMLElementTable, 0 };
444 const ClassInfo JSHTMLElement::marquee_info = { "HTMLMarqueeElement", &JSHTMLElement::info, &HTMLMarqueeElementTable, 0 };
445 const ClassInfo JSHTMLElement::object_info = { "HTMLObjectElement", &JSHTMLElement::info, &HTMLObjectElementTable, 0 };
446 const ClassInfo JSHTMLElement::select_info = { "HTMLSelectElement", &JSHTMLElement::info, &HTMLSelectElementTable, 0 };
447 const ClassInfo JSHTMLElement::table_info = { "HTMLTableElement", &JSHTMLElement::info, &HTMLTableElementTable, 0 };
448 const ClassInfo JSHTMLElement::tablecell_info = { "HTMLTableCellElement", &JSHTMLElement::info, &HTMLTableCellElementTable, 0 };
449 const ClassInfo JSHTMLElement::tablesection_info = { "HTMLTableSectionElement", &JSHTMLElement::info, &HTMLTableSectionElementTable, 0 };
450 const ClassInfo JSHTMLElement::tr_info = { "HTMLTableRowElement", &JSHTMLElement::info, &HTMLTableRowElementTable, 0 };
451
452 const ClassInfo* JSHTMLElement::classInfo() const
453 {
454     static HashMap<WebCore::AtomicStringImpl*, const ClassInfo*> classInfoMap;
455     if (classInfoMap.isEmpty()) {
456         classInfoMap.set(captionTag.localName().impl(), &caption_info);
457         classInfoMap.set(colTag.localName().impl(), &col_info);
458         classInfoMap.set(colgroupTag.localName().impl(), &col_info);
459         classInfoMap.set(embedTag.localName().impl(), &embed_info);
460         classInfoMap.set(frameTag.localName().impl(), &frame_info);
461         classInfoMap.set(framesetTag.localName().impl(), &frameSet_info);
462         classInfoMap.set(iframeTag.localName().impl(), &iFrame_info);
463         classInfoMap.set(marqueeTag.localName().impl(), &marquee_info);
464         classInfoMap.set(objectTag.localName().impl(), &object_info);
465         classInfoMap.set(selectTag.localName().impl(), &select_info);
466         classInfoMap.set(tableTag.localName().impl(), &table_info);
467         classInfoMap.set(tbodyTag.localName().impl(), &tablesection_info);
468         classInfoMap.set(tdTag.localName().impl(), &tablecell_info);
469         classInfoMap.set(tfootTag.localName().impl(), &tablesection_info);
470         classInfoMap.set(thTag.localName().impl(), &tablecell_info);
471         classInfoMap.set(theadTag.localName().impl(), &tablesection_info);
472         classInfoMap.set(trTag.localName().impl(), &tr_info);
473     }
474     
475     HTMLElement* element = static_cast<HTMLElement*>(impl());
476     const ClassInfo* result = classInfoMap.get(element->localName().impl());
477     if (result)
478         return result;
479     return &info;
480 }
481
482 const JSHTMLElement::Accessors JSHTMLElement::select_accessors = { &JSHTMLElement::selectGetter, &JSHTMLElement::selectSetter };
483 const JSHTMLElement::Accessors JSHTMLElement::object_accessors = { &JSHTMLElement::objectGetter, &JSHTMLElement::objectSetter };
484 const JSHTMLElement::Accessors JSHTMLElement::embed_accessors = { &JSHTMLElement::embedGetter, &JSHTMLElement::embedSetter };
485 const JSHTMLElement::Accessors JSHTMLElement::table_accessors = { &JSHTMLElement::tableGetter, &JSHTMLElement::tableSetter };
486 const JSHTMLElement::Accessors JSHTMLElement::caption_accessors = { &JSHTMLElement::tableCaptionGetter, &JSHTMLElement::tableCaptionSetter };
487 const JSHTMLElement::Accessors JSHTMLElement::col_accessors = { &JSHTMLElement::tableColGetter, &JSHTMLElement::tableColSetter };
488 const JSHTMLElement::Accessors JSHTMLElement::tablesection_accessors = { &JSHTMLElement::tableSectionGetter, &JSHTMLElement::tableSectionSetter };
489 const JSHTMLElement::Accessors JSHTMLElement::tr_accessors = { &JSHTMLElement::tableRowGetter, &JSHTMLElement::tableRowSetter };
490 const JSHTMLElement::Accessors JSHTMLElement::tablecell_accessors = { &JSHTMLElement::tableCellGetter, &JSHTMLElement::tableCellSetter };
491 const JSHTMLElement::Accessors JSHTMLElement::frameSet_accessors = { &JSHTMLElement::frameSetGetter, &JSHTMLElement::frameSetSetter };
492 const JSHTMLElement::Accessors JSHTMLElement::frame_accessors = { &JSHTMLElement::frameGetter, &JSHTMLElement::frameSetter };
493 const JSHTMLElement::Accessors JSHTMLElement::iFrame_accessors = { &JSHTMLElement::iFrameGetter, &JSHTMLElement::iFrameSetter };
494 const JSHTMLElement::Accessors JSHTMLElement::marquee_accessors = { &JSHTMLElement::marqueeGetter, &JSHTMLElement::marqueeSetter };
495
496 const JSHTMLElement::Accessors* JSHTMLElement::accessors() const
497 {
498     static HashMap<WebCore::AtomicStringImpl*, const Accessors*> accessorMap;
499     if (accessorMap.isEmpty()) {
500         accessorMap.add(captionTag.localName().impl(), &caption_accessors);
501         accessorMap.add(colTag.localName().impl(), &col_accessors);
502         accessorMap.add(colgroupTag.localName().impl(), &col_accessors);
503         accessorMap.add(embedTag.localName().impl(), &embed_accessors);
504         accessorMap.add(frameTag.localName().impl(), &frame_accessors);
505         accessorMap.add(framesetTag.localName().impl(), &frameSet_accessors);
506         accessorMap.add(iframeTag.localName().impl(), &iFrame_accessors);
507         accessorMap.add(marqueeTag.localName().impl(), &marquee_accessors);
508         accessorMap.add(objectTag.localName().impl(), &object_accessors);
509         accessorMap.add(selectTag.localName().impl(), &select_accessors);
510         accessorMap.add(tableTag.localName().impl(), &table_accessors);
511         accessorMap.add(tbodyTag.localName().impl(), &tablesection_accessors);
512         accessorMap.add(tdTag.localName().impl(), &tablecell_accessors);
513         accessorMap.add(thTag.localName().impl(), &tablecell_accessors);
514         accessorMap.add(theadTag.localName().impl(), &tablesection_accessors);
515         accessorMap.add(tfootTag.localName().impl(), &tablesection_accessors);
516         accessorMap.add(trTag.localName().impl(), &tr_accessors);
517     }
518     
519     HTMLElement* element = static_cast<HTMLElement*>(impl());
520     return accessorMap.get(element->localName().impl());
521 }
522
523 /*
524
525 @begin JSHTMLElementProtoTable 0
526 @end
527
528 @begin HTMLElementTable 14
529   id            KJS::JSHTMLElement::ElementId     DontDelete
530   lang          KJS::JSHTMLElement::ElementLang   DontDelete
531   dir           KJS::JSHTMLElement::ElementDir    DontDelete
532 ### isn't this "class" in the HTML spec?
533   className     KJS::JSHTMLElement::ElementClassName DontDelete
534   innerHTML     KJS::JSHTMLElement::ElementInnerHTML DontDelete
535   innerText     KJS::JSHTMLElement::ElementInnerText DontDelete
536   outerHTML     KJS::JSHTMLElement::ElementOuterHTML DontDelete
537   outerText     KJS::JSHTMLElement::ElementOuterText DontDelete
538   document      KJS::JSHTMLElement::ElementDocument  DontDelete|ReadOnly
539 # IE extension
540   children      KJS::JSHTMLElement::ElementChildren  DontDelete|ReadOnly
541   contentEditable   KJS::JSHTMLElement::ElementContentEditable  DontDelete
542   isContentEditable KJS::JSHTMLElement::ElementIsContentEditable  DontDelete|ReadOnly
543 @end
544 @begin HTMLSelectElementTable 11
545 # Also supported, by index
546   type          KJS::JSHTMLElement::SelectType    DontDelete|ReadOnly
547   selectedIndex KJS::JSHTMLElement::SelectSelectedIndex   DontDelete
548   value         KJS::JSHTMLElement::SelectValue   DontDelete
549   length        KJS::JSHTMLElement::SelectLength  DontDelete
550   form          KJS::JSHTMLElement::SelectForm    DontDelete|ReadOnly
551   options       KJS::JSHTMLElement::SelectOptions DontDelete|ReadOnly
552   namedItem     KJS::JSHTMLElement::SelectNamedItem       DontDelete|Function 1
553   disabled      KJS::JSHTMLElement::SelectDisabled        DontDelete
554   multiple      KJS::JSHTMLElement::SelectMultiple        DontDelete
555   name          KJS::JSHTMLElement::SelectName    DontDelete
556   size          KJS::JSHTMLElement::SelectSize    DontDelete
557   tabIndex      KJS::JSHTMLElement::SelectTabIndex        DontDelete
558   add           KJS::JSHTMLElement::SelectAdd     DontDelete|Function 2
559   remove        KJS::JSHTMLElement::SelectRemove  DontDelete|Function 1
560   blur          KJS::JSHTMLElement::SelectBlur    DontDelete|Function 0
561   focus         KJS::JSHTMLElement::SelectFocus   DontDelete|Function 0
562 @end
563 @begin HTMLObjectElementTable 20
564   form            KJS::JSHTMLElement::ObjectForm            DontDelete|ReadOnly
565   code            KJS::JSHTMLElement::ObjectCode            DontDelete
566   align           KJS::JSHTMLElement::ObjectAlign           DontDelete
567   archive         KJS::JSHTMLElement::ObjectArchive         DontDelete
568   border          KJS::JSHTMLElement::ObjectBorder          DontDelete
569   codeBase        KJS::JSHTMLElement::ObjectCodeBase        DontDelete
570   codeType        KJS::JSHTMLElement::ObjectCodeType        DontDelete
571   contentDocument KJS::JSHTMLElement::ObjectContentDocument DontDelete|ReadOnly
572   data            KJS::JSHTMLElement::ObjectData            DontDelete
573   declare         KJS::JSHTMLElement::ObjectDeclare         DontDelete
574   height          KJS::JSHTMLElement::ObjectHeight          DontDelete
575   hspace          KJS::JSHTMLElement::ObjectHspace          DontDelete
576   name            KJS::JSHTMLElement::ObjectName            DontDelete
577   standby         KJS::JSHTMLElement::ObjectStandby         DontDelete
578   tabIndex        KJS::JSHTMLElement::ObjectTabIndex        DontDelete
579   type            KJS::JSHTMLElement::ObjectType            DontDelete
580   useMap          KJS::JSHTMLElement::ObjectUseMap          DontDelete
581   vspace          KJS::JSHTMLElement::ObjectVspace          DontDelete
582   width           KJS::JSHTMLElement::ObjectWidth           DontDelete
583 @end
584 @begin HTMLEmbedElementTable 6
585   align         KJS::JSHTMLElement::EmbedAlign           DontDelete
586   height        KJS::JSHTMLElement::EmbedHeight          DontDelete
587   name          KJS::JSHTMLElement::EmbedName            DontDelete
588   src           KJS::JSHTMLElement::EmbedSrc             DontDelete
589   type          KJS::JSHTMLElement::EmbedType            DontDelete
590   width         KJS::JSHTMLElement::EmbedWidth           DontDelete
591 @end
592 @begin HTMLTableElementTable 23
593   caption       KJS::JSHTMLElement::TableCaption          DontDelete
594   tHead         KJS::JSHTMLElement::TableTHead            DontDelete
595   tFoot         KJS::JSHTMLElement::TableTFoot            DontDelete
596   rows          KJS::JSHTMLElement::TableRows             DontDelete|ReadOnly
597   tBodies       KJS::JSHTMLElement::TableTBodies          DontDelete|ReadOnly
598   align         KJS::JSHTMLElement::TableAlign            DontDelete
599   bgColor       KJS::JSHTMLElement::TableBgColor          DontDelete
600   border        KJS::JSHTMLElement::TableBorder           DontDelete
601   cellPadding   KJS::JSHTMLElement::TableCellPadding      DontDelete
602   cellSpacing   KJS::JSHTMLElement::TableCellSpacing      DontDelete
603   frame         KJS::JSHTMLElement::TableFrame            DontDelete
604   rules         KJS::JSHTMLElement::TableRules            DontDelete
605   summary       KJS::JSHTMLElement::TableSummary          DontDelete
606   width         KJS::JSHTMLElement::TableWidth            DontDelete
607   createTHead   KJS::JSHTMLElement::TableCreateTHead      DontDelete|Function 0
608   deleteTHead   KJS::JSHTMLElement::TableDeleteTHead      DontDelete|Function 0
609   createTFoot   KJS::JSHTMLElement::TableCreateTFoot      DontDelete|Function 0
610   deleteTFoot   KJS::JSHTMLElement::TableDeleteTFoot      DontDelete|Function 0
611   createCaption KJS::JSHTMLElement::TableCreateCaption    DontDelete|Function 0
612   deleteCaption KJS::JSHTMLElement::TableDeleteCaption    DontDelete|Function 0
613   insertRow     KJS::JSHTMLElement::TableInsertRow        DontDelete|Function 1
614   deleteRow     KJS::JSHTMLElement::TableDeleteRow        DontDelete|Function 1
615 @end
616 @begin HTMLTableCaptionElementTable 1
617   align         KJS::JSHTMLElement::TableCaptionAlign     DontDelete
618 @end
619 @begin HTMLTableColElementTable 7
620   align         KJS::JSHTMLElement::TableColAlign         DontDelete
621   ch            KJS::JSHTMLElement::TableColCh            DontDelete
622   chOff         KJS::JSHTMLElement::TableColChOff         DontDelete
623   span          KJS::JSHTMLElement::TableColSpan          DontDelete
624   vAlign        KJS::JSHTMLElement::TableColVAlign        DontDelete
625   width         KJS::JSHTMLElement::TableColWidth         DontDelete
626 @end
627 @begin HTMLTableSectionElementTable 7
628   align         KJS::JSHTMLElement::TableSectionAlign             DontDelete
629   ch            KJS::JSHTMLElement::TableSectionCh                DontDelete
630   chOff         KJS::JSHTMLElement::TableSectionChOff             DontDelete
631   vAlign        KJS::JSHTMLElement::TableSectionVAlign            DontDelete
632   rows          KJS::JSHTMLElement::TableSectionRows              DontDelete|ReadOnly
633   insertRow     KJS::JSHTMLElement::TableSectionInsertRow         DontDelete|Function 1
634   deleteRow     KJS::JSHTMLElement::TableSectionDeleteRow         DontDelete|Function 1
635 @end
636 @begin HTMLTableRowElementTable 11
637   rowIndex      KJS::JSHTMLElement::TableRowRowIndex              DontDelete|ReadOnly
638   sectionRowIndex KJS::JSHTMLElement::TableRowSectionRowIndex     DontDelete|ReadOnly
639   cells         KJS::JSHTMLElement::TableRowCells                 DontDelete|ReadOnly
640   align         KJS::JSHTMLElement::TableRowAlign                 DontDelete
641   bgColor       KJS::JSHTMLElement::TableRowBgColor               DontDelete
642   ch            KJS::JSHTMLElement::TableRowCh                    DontDelete
643   chOff         KJS::JSHTMLElement::TableRowChOff                 DontDelete
644   vAlign        KJS::JSHTMLElement::TableRowVAlign                DontDelete
645   insertCell    KJS::JSHTMLElement::TableRowInsertCell            DontDelete|Function 1
646   deleteCell    KJS::JSHTMLElement::TableRowDeleteCell            DontDelete|Function 1
647 @end
648 @begin HTMLTableCellElementTable 15
649   cellIndex     KJS::JSHTMLElement::TableCellCellIndex            DontDelete|ReadOnly
650   abbr          KJS::JSHTMLElement::TableCellAbbr                 DontDelete
651   align         KJS::JSHTMLElement::TableCellAlign                DontDelete
652   axis          KJS::JSHTMLElement::TableCellAxis                 DontDelete
653   bgColor       KJS::JSHTMLElement::TableCellBgColor              DontDelete
654   ch            KJS::JSHTMLElement::TableCellCh                   DontDelete
655   chOff         KJS::JSHTMLElement::TableCellChOff                DontDelete
656   colSpan       KJS::JSHTMLElement::TableCellColSpan              DontDelete
657   headers       KJS::JSHTMLElement::TableCellHeaders              DontDelete
658   height        KJS::JSHTMLElement::TableCellHeight               DontDelete
659   noWrap        KJS::JSHTMLElement::TableCellNoWrap               DontDelete
660   rowSpan       KJS::JSHTMLElement::TableCellRowSpan              DontDelete
661   scope         KJS::JSHTMLElement::TableCellScope                DontDelete
662   vAlign        KJS::JSHTMLElement::TableCellVAlign               DontDelete
663   width         KJS::JSHTMLElement::TableCellWidth                DontDelete
664 @end
665 @begin HTMLFrameSetElementTable 2
666 cols          KJS::JSHTMLElement::FrameSetCols                  DontDelete
667 rows          KJS::JSHTMLElement::FrameSetRows                  DontDelete
668 @end
669 @begin HTMLFrameElementTable 9
670   contentDocument KJS::JSHTMLElement::FrameContentDocument        DontDelete|ReadOnly
671   contentWindow   KJS::JSHTMLElement::FrameContentWindow          DontDelete|ReadOnly
672   frameBorder     KJS::JSHTMLElement::FrameFrameBorder            DontDelete
673   longDesc        KJS::JSHTMLElement::FrameLongDesc               DontDelete
674   marginHeight    KJS::JSHTMLElement::FrameMarginHeight           DontDelete
675   marginWidth     KJS::JSHTMLElement::FrameMarginWidth            DontDelete
676   name            KJS::JSHTMLElement::FrameName                   DontDelete
677   noResize        KJS::JSHTMLElement::FrameNoResize               DontDelete
678   width           KJS::JSHTMLElement::FrameWidth                  DontDelete|ReadOnly
679   height          KJS::JSHTMLElement::FrameHeight                 DontDelete|ReadOnly
680   scrolling       KJS::JSHTMLElement::FrameScrolling              DontDelete
681   src             KJS::JSHTMLElement::FrameSrc                    DontDelete
682   location        KJS::JSHTMLElement::FrameLocation               DontDelete
683 @end
684 @begin HTMLIFrameElementTable 12
685   align           KJS::JSHTMLElement::IFrameAlign                 DontDelete
686   contentDocument KJS::JSHTMLElement::IFrameContentDocument       DontDelete|ReadOnly
687   contentWindow   KJS::JSHTMLElement::IFrameContentWindow         DontDelete|ReadOnly
688   document        KJS::JSHTMLElement::IFrameDocument              DontDelete|ReadOnly
689   frameBorder     KJS::JSHTMLElement::IFrameFrameBorder           DontDelete
690   height          KJS::JSHTMLElement::IFrameHeight                DontDelete
691   longDesc        KJS::JSHTMLElement::IFrameLongDesc              DontDelete
692   marginHeight    KJS::JSHTMLElement::IFrameMarginHeight          DontDelete
693   marginWidth     KJS::JSHTMLElement::IFrameMarginWidth           DontDelete
694   name            KJS::JSHTMLElement::IFrameName                  DontDelete
695   scrolling       KJS::JSHTMLElement::IFrameScrolling             DontDelete
696   src             KJS::JSHTMLElement::IFrameSrc                   DontDelete
697   width           KJS::JSHTMLElement::IFrameWidth                 DontDelete
698 @end
699
700 @begin HTMLMarqueeElementTable 2
701   start           KJS::JSHTMLElement::MarqueeStart                DontDelete|Function 0
702   stop            KJS::JSHTMLElement::MarqueeStop                 DontDelete|Function 0
703 @end
704 */
705
706 KJS_IMPLEMENT_PROTOFUNC(JSHTMLElementProtoFunc)
707 KJS_IMPLEMENT_PROTOTYPE("HTMLElement", JSHTMLElementProto, JSHTMLElementProtoFunc)
708
709 JSValue* JSHTMLElementProtoFunc::callAsFunction(ExecState*, JSObject*, const List&)
710 {
711     return 0;
712 }
713
714 JSHTMLElement::JSHTMLElement(ExecState* exec, HTMLElement* e)
715     : WebCore::JSHTMLElement(exec, e)
716 {
717     setPrototype(JSHTMLElementProto::self(exec));
718 }
719
720 JSValue *JSHTMLElement::selectIndexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
721 {
722     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
723     HTMLSelectElement* select = static_cast<HTMLSelectElement*>(thisObj->impl());
724
725     return toJS(exec, select->options()->item(slot.index()));
726 }
727
728 JSValue *JSHTMLElement::framesetNameGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
729 {
730     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
731     HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl());
732
733     WebCore::Node *frame = element->children()->namedItem(propertyName);
734     if (Document* doc = static_cast<HTMLFrameElement*>(frame)->contentDocument())
735         if (Window *window = Window::retrieveWindow(doc->frame()))
736             return window;
737
738     return jsUndefined();
739 }
740
741 JSValue *JSHTMLElement::runtimeObjectGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
742 {
743     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
744     HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl());
745
746     return getRuntimeObject(exec, element);
747 }
748
749 JSValue *JSHTMLElement::runtimeObjectPropertyGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
750 {
751     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
752     HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl());
753
754     if (JSValue *runtimeObject = getRuntimeObject(exec, element))
755         return static_cast<JSObject*>(runtimeObject)->get(exec, propertyName);
756     return jsUndefined();
757 }
758
759 bool JSHTMLElement::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
760 {
761     HTMLElement &element = *static_cast<HTMLElement*>(impl());
762
763     // First look at dynamic properties
764     if (element.hasLocalName(selectTag)) {
765         bool ok;
766         unsigned u = propertyName.toUInt32(&ok);
767         if (ok) {
768             // not specified by DOM(?) but supported in netscape/IE
769             slot.setCustomIndex(this, u, selectIndexGetter);
770             return true;
771         }
772     } else if (element.hasLocalName(framesetTag)) {
773         WebCore::Node *frame = element.children()->namedItem(propertyName);
774         if (frame && frame->hasTagName(frameTag)) {
775             slot.setCustom(this, framesetNameGetter);
776             return true;
777         }
778     } else if (element.hasLocalName(embedTag) || element.hasLocalName(objectTag) || element.hasLocalName(appletTag)) {
779         if (propertyName == "__apple_runtime_object") {
780             slot.setCustom(this, runtimeObjectGetter);
781             return true;
782         }
783         JSValue *runtimeObject = getRuntimeObject(exec,&element);
784         if (runtimeObject) {
785             JSObject* imp = static_cast<JSObject*>(runtimeObject);
786             if (imp->hasProperty(exec, propertyName)) {
787                 slot.setCustom(this, runtimeObjectPropertyGetter);
788                 return true;
789             }
790         }
791     }
792
793     const HashTable* table = classInfo()->propHashTable; // get the right hashtable
794     const HashEntry* entry = Lookup::findEntry(table, propertyName);
795     if (entry) {
796         if (entry->attr & Function)
797             slot.setStaticEntry(this, entry, staticFunctionGetter<HTMLElementFunction>); 
798         else
799             slot.setStaticEntry(this, entry, staticValueGetter<JSHTMLElement>);
800         return true;
801     }
802
803     // Base JSHTMLElement stuff or parent class forward, as usual
804     return getStaticPropertySlot<HTMLElementFunction, JSHTMLElement, WebCore::JSHTMLElement>(exec, &HTMLElementTable, this, propertyName, slot);
805 }
806
807 bool JSHTMLElement::implementsCall() const
808 {
809     HTMLElement* element = static_cast<HTMLElement*>(impl());
810     if (element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) {
811         Document* doc = element->document();
812         KJSProxy *proxy = doc->frame()->jScript();
813         ExecState* exec = proxy->interpreter()->globalExec();
814         if (JSValue *runtimeObject = getRuntimeObject(exec, element))
815             return static_cast<JSObject*>(runtimeObject)->implementsCall();
816     }
817     return false;
818 }
819
820 JSValue *JSHTMLElement::callAsFunction(ExecState* exec, JSObject* thisObj, const List&args)
821 {
822     HTMLElement* element = static_cast<HTMLElement*>(impl());
823     if (element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) {
824         if (JSValue *runtimeObject = getRuntimeObject(exec, element))
825             return static_cast<JSObject*>(runtimeObject)->call(exec, thisObj, args);
826     }
827     return jsUndefined();
828 }
829
830 JSValue *JSHTMLElement::selectGetter(ExecState* exec, int token) const
831 {
832     HTMLSelectElement& select = *static_cast<HTMLSelectElement*>(impl());
833     switch (token) {
834         case SelectType:            return jsString(select.type());
835         case SelectSelectedIndex:   return jsNumber(select.selectedIndex());
836         case SelectValue:           return jsString(select.value());
837         case SelectLength:          return jsNumber(select.length());
838         case SelectForm:            return toJS(exec, select.form()); // type HTMLFormElement
839         case SelectOptions:         return getHTMLOptionsCollection(exec, select.options().get());
840         case SelectDisabled:        return jsBoolean(select.disabled());
841         case SelectMultiple:        return jsBoolean(select.multiple());
842         case SelectName:            return jsString(select.name());
843         case SelectSize:            return jsNumber(select.size());
844         case SelectTabIndex:        return jsNumber(select.tabIndex());
845     }
846     return jsUndefined();
847 }
848
849 JSValue *JSHTMLElement::objectGetter(ExecState* exec, int token) const
850 {
851     HTMLObjectElement& object = *static_cast<HTMLObjectElement*>(impl());
852     switch (token) {
853         case ObjectForm:            return toJS(exec,object.form()); // type HTMLFormElement
854         case ObjectCode:            return jsString(object.code());
855         case ObjectAlign:           return jsString(object.align());
856         case ObjectArchive:         return jsString(object.archive());
857         case ObjectBorder:          return jsString(object.border());
858         case ObjectCodeBase:        return jsString(object.codeBase());
859         case ObjectCodeType:        return jsString(object.codeType());
860         case ObjectContentDocument: return checkNodeSecurity(exec,object.contentDocument()) ? 
861                                            toJS(exec, object.contentDocument()) : jsUndefined();
862         case ObjectData:            return jsString(object.data());
863         case ObjectDeclare:         return jsBoolean(object.declare());
864         case ObjectHeight:          return jsString(object.height());
865         case ObjectHspace:          return jsString(object.hspace());
866         case ObjectName:            return jsString(object.name());
867         case ObjectStandby:         return jsString(object.standby());
868         case ObjectTabIndex:        return jsNumber(object.tabIndex());
869         case ObjectType:            return jsString(object.type());
870         case ObjectUseMap:          return jsString(object.useMap());
871         case ObjectVspace:          return jsString(object.vspace());
872         case ObjectWidth:           return jsString(object.width());
873     }
874     return jsUndefined();
875 }
876
877 JSValue *JSHTMLElement::embedGetter(ExecState* exec, int token) const
878 {
879     HTMLEmbedElement& embed = *static_cast<HTMLEmbedElement*>(impl());
880     switch (token) {
881         case EmbedAlign:           return jsString(embed.align());
882         case EmbedHeight:          return jsString(embed.height());
883         case EmbedName:            return jsString(embed.name());
884         case EmbedSrc:             return jsString(embed.src());
885         case EmbedType:            return jsString(embed.type());
886         case EmbedWidth:           return jsString(embed.width());
887     }
888     return jsUndefined();
889 }
890
891 #ifdef FIXME
892     HTMLAreaElement& area = *static_cast<HTMLAreaElement*>(impl());
893     switch (token) {
894         case AreaAccessKey:       return jsString(area.accessKey());
895         case AreaAlt:             return jsString(area.alt());
896         case AreaCoords:          return jsString(area.coords());
897         case AreaHref:            return jsString(area.href());
898         case AreaHash:            return jsString('#'+KURL(area.href().deprecatedString()).ref());
899         case AreaHost:            return jsString(KURL(area.href().deprecatedString()).host());
900         case AreaHostName: {
901             KURL url(area.href().deprecatedString());
902             if (url.port()==0)
903                 return jsString(url.host());
904             else
905                 return jsString(url.host() + ":" + DeprecatedString::number(url.port()));
906         }
907         case AreaPathName:        return jsString(KURL(area.href().deprecatedString()).path());
908         case AreaPort:            return jsString(DeprecatedString::number(KURL(area.href().deprecatedString()).port()));
909         case AreaProtocol:        return jsString(KURL(area.href().deprecatedString()).protocol()+":");
910         case AreaSearch:          return jsString(KURL(area.href().deprecatedString()).query());
911         case AreaNoHref:          return jsBoolean(area.noHref());
912         case AreaShape:           return jsString(area.shape());
913         case AreaTabIndex:        return jsNumber(area.tabIndex());
914         case AreaTarget:          return jsString(area.target());
915     }
916 #endif
917
918 JSValue *JSHTMLElement::tableGetter(ExecState* exec, int token) const
919 {
920     HTMLTableElement& table = *static_cast<HTMLTableElement*>(impl());
921     switch (token) {
922         case TableCaption:         return toJS(exec,table.caption()); // type HTMLTableCaptionElement
923         case TableTHead:           return toJS(exec,table.tHead()); // type HTMLTableSectionElement
924         case TableTFoot:           return toJS(exec,table.tFoot()); // type HTMLTableSectionElement
925         case TableRows:            return getHTMLCollection(exec, table.rows().get()); // type JSHTMLCollection
926         case TableTBodies:         return getHTMLCollection(exec, table.tBodies().get()); // type JSHTMLCollection
927         case TableAlign:           return jsString(table.align());
928         case TableBgColor:         return jsString(table.bgColor());
929         case TableBorder:          return jsString(table.border());
930         case TableCellPadding:     return jsString(table.cellPadding());
931         case TableCellSpacing:     return jsString(table.cellSpacing());
932         case TableFrame:           return jsString(table.frame());
933         case TableRules:           return jsString(table.rules());
934         case TableSummary:         return jsString(table.summary());
935         case TableWidth:           return jsString(table.width());
936     }
937     return jsUndefined();
938 }
939
940 JSValue *JSHTMLElement::tableCaptionGetter(ExecState* exec, int token) const
941 {
942     HTMLTableCaptionElement& tableCaption = *static_cast<HTMLTableCaptionElement*>(impl());
943     if (token == TableCaptionAlign)
944         return jsString(tableCaption.align());
945     return jsUndefined();
946 }
947
948 JSValue *JSHTMLElement::tableColGetter(ExecState* exec, int token) const
949 {
950     HTMLTableColElement& tableCol = *static_cast<HTMLTableColElement*>(impl());
951     switch (token) {
952         case TableColAlign:           return jsString(tableCol.align());
953         case TableColCh:              return jsString(tableCol.ch());
954         case TableColChOff:           return jsString(tableCol.chOff());
955         case TableColSpan:            return jsNumber(tableCol.span());
956         case TableColVAlign:          return jsString(tableCol.vAlign());
957         case TableColWidth:           return jsString(tableCol.width());
958     }
959     return jsUndefined();
960 }
961
962 JSValue *JSHTMLElement::tableSectionGetter(ExecState* exec, int token) const
963 {
964     HTMLTableSectionElement& tableSection = *static_cast<HTMLTableSectionElement*>(impl());
965     switch (token) {
966         case TableSectionAlign:           return jsString(tableSection.align());
967         case TableSectionCh:              return jsString(tableSection.ch());
968         case TableSectionChOff:           return jsString(tableSection.chOff());
969         case TableSectionVAlign:          return jsString(tableSection.vAlign());
970         case TableSectionRows:            return getHTMLCollection(exec, tableSection.rows().get()); // type JSHTMLCollection
971     }
972     return jsUndefined();
973 }
974
975 JSValue *JSHTMLElement::tableRowGetter(ExecState* exec, int token) const
976 {
977     HTMLTableRowElement& tableRow = *static_cast<HTMLTableRowElement*>(impl());
978     switch (token) {
979         case TableRowRowIndex:        return jsNumber(tableRow.rowIndex());
980         case TableRowSectionRowIndex: return jsNumber(tableRow.sectionRowIndex());
981         case TableRowCells:           return getHTMLCollection(exec, tableRow.cells().get()); // type JSHTMLCollection
982         case TableRowAlign:           return jsString(tableRow.align());
983         case TableRowBgColor:         return jsString(tableRow.bgColor());
984         case TableRowCh:              return jsString(tableRow.ch());
985         case TableRowChOff:           return jsString(tableRow.chOff());
986         case TableRowVAlign:          return jsString(tableRow.vAlign());
987     }
988     return jsUndefined();
989 }
990
991 JSValue *JSHTMLElement::tableCellGetter(ExecState* exec, int token) const
992 {
993     HTMLTableCellElement& tableCell = *static_cast<HTMLTableCellElement*>(impl());
994     switch (token) {
995         case TableCellCellIndex:       return jsNumber(tableCell.cellIndex());
996         case TableCellAbbr:            return jsString(tableCell.abbr());
997         case TableCellAlign:           return jsString(tableCell.align());
998         case TableCellAxis:            return jsString(tableCell.axis());
999         case TableCellBgColor:         return jsString(tableCell.bgColor());
1000         case TableCellCh:              return jsString(tableCell.ch());
1001         case TableCellChOff:           return jsString(tableCell.chOff());
1002         case TableCellColSpan:         return jsNumber(tableCell.colSpan());
1003         case TableCellHeaders:         return jsString(tableCell.headers());
1004         case TableCellHeight:          return jsString(tableCell.height());
1005         case TableCellNoWrap:          return jsBoolean(tableCell.noWrap());
1006         case TableCellRowSpan:         return jsNumber(tableCell.rowSpan());
1007         case TableCellScope:           return jsString(tableCell.scope());
1008         case TableCellVAlign:          return jsString(tableCell.vAlign());
1009         case TableCellWidth:           return jsString(tableCell.width());
1010     }
1011     return jsUndefined();
1012 }
1013
1014 JSValue *JSHTMLElement::frameSetGetter(ExecState* exec, int token) const
1015 {
1016     HTMLFrameSetElement& frameSet = *static_cast<HTMLFrameSetElement*>(impl());
1017     switch (token) {
1018         case FrameSetCols:            return jsString(frameSet.cols());
1019         case FrameSetRows:            return jsString(frameSet.rows());
1020     }
1021     return jsUndefined();
1022 }
1023
1024 JSValue *JSHTMLElement::frameGetter(ExecState* exec, int token) const
1025 {
1026     HTMLFrameElement& frameElement = *static_cast<HTMLFrameElement*>(impl());
1027     switch (token) {
1028         case FrameContentDocument: return checkNodeSecurity(exec,frameElement.contentDocument()) ? 
1029                                           toJS(exec, frameElement.contentDocument()) : jsUndefined();
1030         case FrameContentWindow:   return checkNodeSecurity(exec,frameElement.contentDocument())
1031                                         ? Window::retrieve(frameElement.contentFrame())
1032                                         : jsUndefined();
1033         case FrameFrameBorder:     return jsString(frameElement.frameBorder());
1034         case FrameLongDesc:        return jsString(frameElement.longDesc());
1035         case FrameMarginHeight:    return jsString(frameElement.marginHeight());
1036         case FrameMarginWidth:     return jsString(frameElement.marginWidth());
1037         case FrameName:            return jsString(frameElement.name());
1038         case FrameNoResize:        return jsBoolean(frameElement.noResize());
1039         case FrameWidth:           return jsNumber(frameElement.frameWidth());
1040         case FrameHeight:          return jsNumber(frameElement.frameHeight());
1041         case FrameScrolling:       return jsString(frameElement.scrolling());
1042         case FrameSrc:
1043         case FrameLocation:        return jsString(frameElement.src());
1044     }
1045     return jsUndefined();
1046 }
1047
1048 JSValue *JSHTMLElement::iFrameGetter(ExecState* exec, int token) const
1049 {
1050     HTMLIFrameElement& iFrame = *static_cast<HTMLIFrameElement*>(impl());
1051     switch (token) {
1052         case IFrameAlign:                return jsString(iFrame.align());
1053           // ### security check ?
1054         case IFrameDocument: // non-standard, mapped to contentDocument
1055         case IFrameContentDocument: return checkNodeSecurity(exec,iFrame.contentDocument()) ? 
1056                                       toJS(exec, iFrame.contentDocument()) : jsUndefined();
1057         case IFrameContentWindow:   return checkNodeSecurity(exec,iFrame.contentDocument()) 
1058                                         ? Window::retrieve(iFrame.contentFrame())
1059                                         : jsUndefined();
1060         case IFrameFrameBorder:     return jsString(iFrame.frameBorder());
1061         case IFrameHeight:          return jsString(iFrame.height());
1062         case IFrameLongDesc:        return jsString(iFrame.longDesc());
1063         case IFrameMarginHeight:    return jsString(iFrame.marginHeight());
1064         case IFrameMarginWidth:     return jsString(iFrame.marginWidth());
1065         case IFrameName:            return jsString(iFrame.name());
1066         case IFrameScrolling:       return jsString(iFrame.scrolling());
1067         case IFrameSrc:             return jsString(iFrame.src());
1068         case IFrameWidth:           return jsString(iFrame.width());
1069     }
1070     return jsUndefined();
1071 }
1072
1073 JSValue *JSHTMLElement::marqueeGetter(ExecState* exec, int token) const
1074 {
1075     // FIXME: Find out what WinIE exposes as properties and implement this.
1076     return jsUndefined();
1077 }
1078
1079 JSValue *JSHTMLElement::getValueProperty(ExecState* exec, int token) const
1080 {
1081     // Check our set of generic properties first.
1082     HTMLElement &element = *static_cast<HTMLElement*>(impl());
1083     switch (token) {
1084         case ElementId:
1085             // iht.com relies on this value being "" when no id is present. Other browsers do this as well.
1086             // So we use jsString() instead of jsStringOrNull() here.
1087             return jsString(element.id());
1088         case ElementLang:
1089             return jsString(element.lang());
1090         case ElementDir:
1091             return jsString(element.dir());
1092         case ElementClassName:
1093             return jsString(element.className());
1094         case ElementInnerHTML:
1095             return jsString(element.innerHTML());
1096         case ElementInnerText:
1097             impl()->document()->updateLayoutIgnorePendingStylesheets();
1098             return jsString(element.innerText());
1099         case ElementOuterHTML:
1100             return jsString(element.outerHTML());
1101         case ElementOuterText:
1102             return jsString(element.outerText());
1103         case ElementDocument:
1104             return toJS(exec,element.ownerDocument());
1105         case ElementChildren:
1106             return getHTMLCollection(exec, element.children().get());
1107         case ElementContentEditable:
1108             return jsString(element.contentEditable());
1109         case ElementIsContentEditable:
1110             return jsBoolean(element.isContentEditable());
1111     }
1112
1113     // Now check the properties specific to our element type.
1114     const Accessors* access = accessors();
1115     if (access && access->m_getter)
1116         return (this->*(access->m_getter))(exec, token);
1117     return jsUndefined();
1118 }
1119
1120 UString JSHTMLElement::toString(ExecState* exec) const
1121 {
1122     if (impl()->hasTagName(aTag))
1123         return UString(static_cast<const HTMLAnchorElement*>(impl())->href());
1124     else
1125         return JSElement::toString(exec);
1126 }
1127
1128 static HTMLFormElement* getForm(HTMLElement* element)
1129 {
1130     if (element->isGenericFormElement())
1131         return static_cast<HTMLGenericFormElement*>(element)->form();
1132     if (element->hasTagName(labelTag))
1133         return static_cast<HTMLLabelElement*>(element)->form();
1134     if (element->hasTagName(objectTag))
1135         return static_cast<HTMLObjectElement*>(element)->form();
1136
1137     return 0;
1138 }
1139
1140 void JSHTMLElement::pushEventHandlerScope(ExecState* exec, ScopeChain &scope) const
1141 {
1142   HTMLElement* element = static_cast<HTMLElement*>(impl());
1143
1144   // The document is put on first, fall back to searching it only after the element and form.
1145   scope.push(static_cast<JSObject*>(toJS(exec, element->ownerDocument())));
1146
1147   // The form is next, searched before the document, but after the element itself.
1148   
1149   // First try to obtain the form from the element itself.  We do this to deal with
1150   // the malformed case where <form>s aren't in our parent chain (e.g., when they were inside 
1151   // <table> or <tbody>.
1152   HTMLFormElement* form = getForm(element);
1153   if (form)
1154     scope.push(static_cast<JSObject*>(toJS(exec, form)));
1155   else {
1156     WebCore::Node* form = element->parentNode();
1157     while (form && !form->hasTagName(formTag))
1158       form = form->parentNode();
1159     
1160     if (form)
1161       scope.push(static_cast<JSObject*>(toJS(exec, form)));
1162   }
1163   
1164   // The element is on top, searched first.
1165   scope.push(static_cast<JSObject*>(toJS(exec, element)));
1166 }
1167
1168 HTMLElementFunction::HTMLElementFunction(ExecState* exec, int i, int len, const Identifier& name)
1169   : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
1170   , id(i)
1171 {
1172   put(exec,lengthPropertyName,jsNumber(len),DontDelete|ReadOnly|DontEnum);
1173 }
1174
1175 JSValue *HTMLElementFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
1176 {
1177     if (!thisObj->inherits(&JSHTMLElement::info))
1178         return throwError(exec, TypeError);
1179     DOMExceptionTranslator exception(exec);
1180     HTMLElement &element = *static_cast<HTMLElement*>(static_cast<JSHTMLElement*>(thisObj)->impl());
1181
1182     if (element.hasLocalName(selectTag)) {
1183         HTMLSelectElement &select = static_cast<HTMLSelectElement &>(element);
1184         if (id == JSHTMLElement::SelectAdd) {
1185             select.add(toHTMLElement(args[0]), toHTMLElement(args[1]), exception);
1186             return jsUndefined();
1187         }
1188         else if (id == JSHTMLElement::SelectRemove) {
1189             // we support both options index and options objects
1190             HTMLElement* element = toHTMLElement(args[0]);
1191             if (element && element->hasTagName(optionTag))
1192                 select.remove(((HTMLOptionElement*)element)->index());
1193             else
1194                 select.remove(int(args[0]->toNumber(exec)));
1195             return jsUndefined();
1196         }
1197         else if (id == JSHTMLElement::SelectBlur) {
1198             select.blur();
1199             return jsUndefined();
1200         }
1201         else if (id == JSHTMLElement::SelectFocus) {
1202             select.focus();
1203             return jsUndefined();
1204         }
1205         else if (id == JSHTMLElement::SelectNamedItem) {
1206             return toJS(exec, select.namedItem(Identifier(args[0]->toString(exec))));
1207         }
1208     }
1209     else if (element.hasLocalName(tableTag)) {
1210         HTMLTableElement &table = static_cast<HTMLTableElement &>(element);
1211         if (id == JSHTMLElement::TableCreateTHead)
1212             return toJS(exec,table.createTHead());
1213         else if (id == JSHTMLElement::TableDeleteTHead) {
1214             table.deleteTHead();
1215             return jsUndefined();
1216         }
1217         else if (id == JSHTMLElement::TableCreateTFoot)
1218             return toJS(exec,table.createTFoot());
1219         else if (id == JSHTMLElement::TableDeleteTFoot) {
1220             table.deleteTFoot();
1221             return jsUndefined();
1222         }
1223         else if (id == JSHTMLElement::TableCreateCaption)
1224             return toJS(exec,table.createCaption());
1225         else if (id == JSHTMLElement::TableDeleteCaption) {
1226             table.deleteCaption();
1227             return jsUndefined();
1228         }
1229         else if (id == JSHTMLElement::TableInsertRow)
1230             return toJS(exec,table.insertRow(args[0]->toInt32(exec), exception));
1231         else if (id == JSHTMLElement::TableDeleteRow) {
1232             table.deleteRow(args[0]->toInt32(exec), exception);
1233             return jsUndefined();
1234         }
1235     }
1236     else if (element.hasLocalName(theadTag) ||
1237              element.hasLocalName(tbodyTag) ||
1238              element.hasLocalName(tfootTag)) {
1239         HTMLTableSectionElement &tableSection = static_cast<HTMLTableSectionElement &>(element);
1240         if (id == JSHTMLElement::TableSectionInsertRow)
1241             return toJS(exec, tableSection.insertRow(args[0]->toInt32(exec), exception));
1242         else if (id == JSHTMLElement::TableSectionDeleteRow) {
1243             tableSection.deleteRow(args[0]->toInt32(exec), exception);
1244             return jsUndefined();
1245         }
1246     }
1247     else if (element.hasLocalName(trTag)) {
1248         HTMLTableRowElement &tableRow = static_cast<HTMLTableRowElement &>(element);
1249         if (id == JSHTMLElement::TableRowInsertCell)
1250             return toJS(exec,tableRow.insertCell(args[0]->toInt32(exec), exception));
1251         else if (id == JSHTMLElement::TableRowDeleteCell) {
1252             tableRow.deleteCell(args[0]->toInt32(exec), exception);
1253             return jsUndefined();
1254         }
1255     }
1256     else if (element.hasLocalName(marqueeTag)) {
1257         if (id == JSHTMLElement::MarqueeStart && element.renderer() && 
1258             element.renderer()->layer() &&
1259             element.renderer()->layer()->marquee()) {
1260             element.renderer()->layer()->marquee()->start();
1261             return jsUndefined();
1262         }
1263         if (id == JSHTMLElement::MarqueeStop && element.renderer() && 
1264             element.renderer()->layer() &&
1265             element.renderer()->layer()->marquee()) {
1266             element.renderer()->layer()->marquee()->stop();
1267             return jsUndefined();
1268         }
1269     }
1270
1271     return jsUndefined();
1272 }
1273
1274 void JSHTMLElement::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
1275 {
1276     HTMLElement &element = *static_cast<HTMLElement*>(impl());
1277     // First look at dynamic properties
1278     if (element.hasLocalName(selectTag)) {
1279         HTMLSelectElement &select = static_cast<HTMLSelectElement &>(element);
1280         bool ok;
1281         /*unsigned u =*/ propertyName.toUInt32(&ok);
1282         if (ok) {
1283             JSObject* coll = static_cast<JSObject*>(getHTMLOptionsCollection(exec, select.options().get()));
1284             coll->put(exec,propertyName,value);
1285             return;
1286         }
1287     }
1288     else if (element.hasLocalName(embedTag) || element.hasLocalName(objectTag) || element.hasLocalName(appletTag)) {
1289         if (JSValue *runtimeObject = getRuntimeObject(exec, &element)) {
1290             JSObject* imp = static_cast<JSObject*>(runtimeObject);
1291             if (imp->canPut(exec, propertyName))
1292                 return imp->put(exec, propertyName, value);
1293         }
1294     }
1295
1296     const HashTable* table = classInfo()->propHashTable; // get the right hashtable
1297     const HashEntry* entry = Lookup::findEntry(table, propertyName);
1298     if (entry) {
1299         if (entry->attr & Function) { // function: put as override property
1300             JSObject::put(exec, propertyName, value, attr);
1301             return;
1302         } else if (!(entry->attr & ReadOnly)) { // let lookupPut print the warning if read-only
1303             putValueProperty(exec, entry->value, value, attr);
1304             return;
1305         }
1306     }
1307
1308     lookupPut<JSHTMLElement, WebCore::JSHTMLElement>(exec, propertyName, value, attr, &HTMLElementTable, this);
1309 }
1310
1311 void JSHTMLElement::selectSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1312 {
1313     HTMLSelectElement& select = *static_cast<HTMLSelectElement*>(impl());
1314     switch (token) {
1315         // read-only: type
1316         case SelectSelectedIndex:   { select.setSelectedIndex(value->toInt32(exec)); return; }
1317         case SelectValue:           { select.setValue(str); return; }
1318         case SelectLength:          { // read-only according to the NS spec, but webpages need it writeable
1319                                         JSObject* coll = static_cast<JSObject*>(getHTMLOptionsCollection(exec, select.options().get()));
1320                                         coll->put(exec,lengthPropertyName,value);
1321                                         return;
1322                                     }
1323         // read-only: form
1324         // read-only: options
1325         case SelectDisabled:        { select.setDisabled(value->toBoolean(exec)); return; }
1326         case SelectMultiple:        { select.setMultiple(value->toBoolean(exec)); return; }
1327         case SelectName:            { select.setName(AtomicString(str)); return; }
1328         case SelectSize:            { select.setSize(value->toInt32(exec)); return; }
1329         case SelectTabIndex:        { select.setTabIndex(value->toInt32(exec)); return; }
1330     }
1331 }
1332
1333 void JSHTMLElement::objectSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1334 {
1335     HTMLObjectElement& object = *static_cast<HTMLObjectElement*>(impl());
1336     switch (token) {
1337         // read-only: form
1338         case ObjectCode:            { object.setCode(str); return; }
1339         case ObjectAlign:           { object.setAlign(str); return; }
1340         case ObjectArchive:         { object.setArchive(str); return; }
1341         case ObjectBorder:          { object.setBorder(str); return; }
1342         case ObjectCodeBase:        { object.setCodeBase(str); return; }
1343         case ObjectCodeType:        { object.setCodeType(str); return; }
1344         // read-only: ObjectContentDocument
1345         case ObjectData:            { object.setData(str); return; }
1346         case ObjectDeclare:         { object.setDeclare(value->toBoolean(exec)); return; }
1347         case ObjectHeight:          { object.setHeight(str); return; }
1348         case ObjectHspace:          { object.setHspace(str); return; }
1349         case ObjectName:            { object.setName(str); return; }
1350         case ObjectStandby:         { object.setStandby(str); return; }
1351         case ObjectTabIndex:        { object.setTabIndex(value->toInt32(exec)); return; }
1352         case ObjectType:            { object.setType(str); return; }
1353         case ObjectUseMap:          { object.setUseMap(str); return; }
1354         case ObjectVspace:          { object.setVspace(str); return; }
1355         case ObjectWidth:           { object.setWidth(str); return; }
1356     }
1357 }
1358
1359 void JSHTMLElement::embedSetter(ExecState*, int token, JSValue*, const WebCore::String& str)
1360 {
1361     HTMLEmbedElement& embed = *static_cast<HTMLEmbedElement*>(impl());
1362     switch (token) {
1363         case EmbedAlign:           { embed.setAlign(str); return; }
1364         case EmbedHeight:          { embed.setHeight(str); return; }
1365         case EmbedName:            { embed.setName(str); return; }
1366         case EmbedSrc:             { embed.setSrc(str); return; }
1367         case EmbedType:            { embed.setType(str); return; }
1368         case EmbedWidth:           { embed.setWidth(str); return; }
1369     }
1370 }
1371
1372 void JSHTMLElement::tableSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1373 {
1374     HTMLTableElement& table = *static_cast<HTMLTableElement*>(impl());
1375     switch (token) {
1376         case TableCaption:         { table.setCaption(toHTMLTableCaptionElement(value)); return; }
1377         case TableTHead:           { table.setTHead(toHTMLTableSectionElement(value)); return; }
1378         case TableTFoot:           { table.setTFoot(toHTMLTableSectionElement(value)); return; }
1379         // read-only: rows
1380         // read-only: tbodies
1381         case TableAlign:           { table.setAlign(str); return; }
1382         case TableBgColor:         { table.setBgColor(str); return; }
1383         case TableBorder:          { table.setBorder(str); return; }
1384         case TableCellPadding:     { table.setCellPadding(str); return; }
1385         case TableCellSpacing:     { table.setCellSpacing(str); return; }
1386         case TableFrame:           { table.setFrame(str); return; }
1387         case TableRules:           { table.setRules(str); return; }
1388         case TableSummary:         { table.setSummary(str); return; }
1389         case TableWidth:           { table.setWidth(str); return; }
1390     }
1391 }
1392
1393 void JSHTMLElement::tableCaptionSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1394 {
1395     HTMLTableCaptionElement& tableCaption = *static_cast<HTMLTableCaptionElement*>(impl());
1396     if (token == TableCaptionAlign)
1397         tableCaption.setAlign(str);
1398 }
1399
1400 void JSHTMLElement::tableColSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1401 {
1402     HTMLTableColElement& tableCol = *static_cast<HTMLTableColElement*>(impl());
1403     switch (token) {
1404         case TableColAlign:           { tableCol.setAlign(str); return; }
1405         case TableColCh:              { tableCol.setCh(str); return; }
1406         case TableColChOff:           { tableCol.setChOff(str); return; }
1407         case TableColSpan:            { tableCol.setSpan(value->toInt32(exec)); return; }
1408         case TableColVAlign:          { tableCol.setVAlign(str); return; }
1409         case TableColWidth:           { tableCol.setWidth(str); return; }
1410     }
1411 }
1412
1413 void JSHTMLElement::tableSectionSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1414 {
1415     HTMLTableSectionElement& tableSection = *static_cast<HTMLTableSectionElement*>(impl());
1416     switch (token) {
1417         case TableSectionAlign:           { tableSection.setAlign(str); return; }
1418         case TableSectionCh:              { tableSection.setCh(str); return; }
1419         case TableSectionChOff:           { tableSection.setChOff(str); return; }
1420         case TableSectionVAlign:          { tableSection.setVAlign(str); return; }
1421         // read-only: rows
1422     }
1423 }
1424
1425 void JSHTMLElement::tableRowSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1426 {
1427     HTMLTableRowElement& tableRow = *static_cast<HTMLTableRowElement*>(impl());
1428     switch (token) {
1429         // read-only: rowIndex
1430         // read-only: sectionRowIndex
1431         // read-only: cells
1432         case TableRowAlign:           { tableRow.setAlign(str); return; }
1433         case TableRowBgColor:         { tableRow.setBgColor(str); return; }
1434         case TableRowCh:              { tableRow.setCh(str); return; }
1435         case TableRowChOff:           { tableRow.setChOff(str); return; }
1436         case TableRowVAlign:          { tableRow.setVAlign(str); return; }
1437     }
1438 }
1439
1440 void JSHTMLElement::tableCellSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1441 {
1442     HTMLTableCellElement& tableCell = *static_cast<HTMLTableCellElement*>(impl());
1443     switch (token) {
1444         // read-only: cellIndex
1445         case TableCellAbbr:            { tableCell.setAbbr(str); return; }
1446         case TableCellAlign:           { tableCell.setAlign(str); return; }
1447         case TableCellAxis:            { tableCell.setAxis(str); return; }
1448         case TableCellBgColor:         { tableCell.setBgColor(str); return; }
1449         case TableCellCh:              { tableCell.setCh(str); return; }
1450         case TableCellChOff:           { tableCell.setChOff(str); return; }
1451         case TableCellColSpan:         { tableCell.setColSpan(value->toInt32(exec)); return; }
1452         case TableCellHeaders:         { tableCell.setHeaders(str); return; }
1453         case TableCellHeight:          { tableCell.setHeight(str); return; }
1454         case TableCellNoWrap:          { tableCell.setNoWrap(value->toBoolean(exec)); return; }
1455         case TableCellRowSpan:         { tableCell.setRowSpan(value->toInt32(exec)); return; }
1456         case TableCellScope:           { tableCell.setScope(str); return; }
1457         case TableCellVAlign:          { tableCell.setVAlign(str); return; }
1458         case TableCellWidth:           { tableCell.setWidth(str); return; }
1459     }
1460 }
1461
1462 void JSHTMLElement::frameSetSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1463 {
1464     HTMLFrameSetElement& frameSet = *static_cast<HTMLFrameSetElement*>(impl());
1465     switch (token) {
1466         case FrameSetCols:            { frameSet.setCols(str); return; }
1467         case FrameSetRows:            { frameSet.setRows(str); return; }
1468     }
1469 }
1470
1471 void JSHTMLElement::frameSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1472 {
1473     HTMLFrameElement& frameElement = *static_cast<HTMLFrameElement*>(impl());
1474     switch (token) {
1475         // read-only: FrameContentDocument:
1476         case FrameFrameBorder:     { frameElement.setFrameBorder(str); return; }
1477         case FrameLongDesc:        { frameElement.setLongDesc(str); return; }
1478         case FrameMarginHeight:    { frameElement.setMarginHeight(str); return; }
1479         case FrameMarginWidth:     { frameElement.setMarginWidth(str); return; }
1480         case FrameName:            { frameElement.setName(str); return; }
1481         case FrameNoResize:        { frameElement.setNoResize(value->toBoolean(exec)); return; }
1482         case FrameScrolling:       { frameElement.setScrolling(str); return; }
1483         case FrameSrc:             { frameElement.setSrc(str); return; }
1484         case FrameLocation:        { frameElement.setLocation(str); return; }
1485     }
1486 }
1487
1488 void JSHTMLElement::iFrameSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1489 {
1490     HTMLIFrameElement& iFrame = *static_cast<HTMLIFrameElement*>(impl());
1491     switch (token) {
1492         case IFrameAlign:           { iFrame.setAlign(str); return; }
1493         // read-only: IFrameContentDocument
1494         case IFrameFrameBorder:     { iFrame.setFrameBorder(str); return; }
1495         case IFrameHeight:          { iFrame.setHeight(str); return; }
1496         case IFrameLongDesc:        { iFrame.setLongDesc(str); return; }
1497         case IFrameMarginHeight:    { iFrame.setMarginHeight(str); return; }
1498         case IFrameMarginWidth:     { iFrame.setMarginWidth(str); return; }
1499         case IFrameName:            { iFrame.setName(str); return; }
1500         case IFrameScrolling:       { iFrame.setScrolling(str); return; }
1501         case IFrameSrc:             { iFrame.setSrc(str); return; }
1502         case IFrameWidth:           { iFrame.setWidth(str); return; }
1503     }
1504 }
1505
1506 void JSHTMLElement::marqueeSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1507 {
1508     // FIXME: Find out what WinIE supports and implement it.
1509 }
1510
1511 void JSHTMLElement::putValueProperty(ExecState* exec, int token, JSValue *value, int)
1512 {
1513     DOMExceptionTranslator exception(exec);
1514     WebCore::String str = value->toString(exec);
1515  
1516     // Check our set of generic properties first.
1517     HTMLElement &element = *static_cast<HTMLElement*>(impl());
1518     switch (token) {
1519         case ElementId:
1520             element.setId(str);
1521             return;
1522         case ElementLang:
1523             element.setLang(str);
1524             return;
1525         case ElementDir:
1526             element.setDir(str);
1527             return;
1528         case ElementClassName:
1529             element.setClassName(str);
1530             return;
1531         case ElementInnerHTML:
1532             element.setInnerHTML(str, exception);
1533             return;
1534         case ElementInnerText:
1535             element.setInnerText(str, exception);
1536             return;
1537         case ElementOuterHTML:
1538             element.setOuterHTML(str, exception);
1539             return;
1540         case ElementOuterText:
1541             element.setOuterText(str, exception);
1542             return;
1543         case ElementContentEditable:
1544             element.setContentEditable(str);
1545             return;
1546     }
1547
1548     // Now check for properties that apply to a specific element type.
1549     const Accessors* access = accessors();
1550     if (access && access->m_setter)
1551         return (this->*(access->m_setter))(exec, token, value, str);  
1552 }
1553
1554 HTMLElement* toHTMLElement(JSValue *val)
1555 {
1556     if (!val || !val->isObject(&JSHTMLElement::info))
1557         return 0;
1558     return static_cast<HTMLElement*>(static_cast<JSHTMLElement*>(val)->impl());
1559 }
1560
1561 HTMLTableCaptionElement* toHTMLTableCaptionElement(JSValue *val)
1562 {
1563     HTMLElement* e = toHTMLElement(val);
1564     if (e && e->hasTagName(captionTag))
1565         return static_cast<HTMLTableCaptionElement*>(e);
1566     return 0;
1567 }
1568
1569 HTMLTableSectionElement* toHTMLTableSectionElement(JSValue *val)
1570 {
1571     HTMLElement* e = toHTMLElement(val);
1572     if (e && (e->hasTagName(theadTag) || e->hasTagName(tbodyTag) || e->hasTagName(tfootTag)))
1573         return static_cast<HTMLTableSectionElement*>(e);
1574     return 0;
1575 }
1576
1577 // -------------------------------------------------------------------------
1578 /* Source for JSHTMLCollectionProtoTable. Use "make hashtables" to regenerate.
1579 @begin JSHTMLCollectionProtoTable 3
1580   item          JSHTMLCollection::Item            DontDelete|Function 1
1581   namedItem     JSHTMLCollection::NamedItem       DontDelete|Function 1
1582   tags          JSHTMLCollection::Tags            DontDelete|Function 1
1583 @end
1584 */
1585 KJS_IMPLEMENT_PROTOFUNC(JSHTMLCollectionProtoFunc)
1586 KJS_IMPLEMENT_PROTOTYPE("HTMLCollection",JSHTMLCollectionProto,JSHTMLCollectionProtoFunc)
1587
1588 const ClassInfo JSHTMLCollection::info = { "Collection", 0, 0, 0 };
1589
1590 JSHTMLCollection::JSHTMLCollection(ExecState* exec, HTMLCollection* c)
1591   : m_impl(c) 
1592 {
1593   setPrototype(JSHTMLCollectionProto::self(exec));
1594 }
1595
1596 JSHTMLCollection::~JSHTMLCollection()
1597 {
1598   ScriptInterpreter::forgetDOMObject(m_impl.get());
1599 }
1600
1601 JSValue *JSHTMLCollection::lengthGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
1602 {
1603     JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase());
1604     return jsNumber(thisObj->m_impl->length());
1605 }
1606
1607 JSValue *JSHTMLCollection::indexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
1608 {
1609     JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase());
1610     return toJS(exec, thisObj->m_impl->item(slot.index()));
1611 }
1612
1613 JSValue *JSHTMLCollection::nameGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
1614 {
1615     JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase());
1616     return thisObj->getNamedItems(exec, propertyName);
1617 }
1618
1619 bool JSHTMLCollection::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
1620 {
1621   if (propertyName == lengthPropertyName) {
1622       slot.setCustom(this, lengthGetter);
1623       return true;
1624   } else {
1625     // Look in the prototype (for functions) before assuming it's an item's name
1626     JSValue *proto = prototype();
1627     if (proto->isObject() && static_cast<JSObject*>(proto)->hasProperty(exec, propertyName))
1628       return false;
1629
1630     // name or index ?
1631     bool ok;
1632     unsigned int u = propertyName.toUInt32(&ok);
1633     if (ok) {
1634       slot.setCustomIndex(this, u, indexGetter);
1635       return true;
1636     }
1637
1638     if (!getNamedItems(exec, propertyName)->isUndefined()) {
1639       slot.setCustom(this, nameGetter);
1640       return true;
1641     }
1642   }
1643
1644   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
1645 }
1646
1647 // HTMLCollections are strange objects, they support both get and call,
1648 // so that document.forms.item(0) and document.forms(0) both work.
1649 JSValue *JSHTMLCollection::callAsFunction(ExecState* exec, JSObject* , const List &args)
1650 {
1651   // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case.
1652   HTMLCollection &collection = *m_impl;
1653
1654   // Also, do we need the TypeError test here ?
1655
1656   if (args.size() == 1) {
1657     // support for document.all(<index>) etc.
1658     bool ok;
1659     UString s = args[0]->toString(exec);
1660     unsigned int u = s.toUInt32(&ok);
1661     if (ok)
1662       return toJS(exec, collection.item(u));
1663     // support for document.images('<name>') etc.
1664     return getNamedItems(exec, Identifier(s));
1665   }
1666   else if (args.size() >= 1) // the second arg, if set, is the index of the item we want
1667   {
1668     bool ok;
1669     UString s = args[0]->toString(exec);
1670     unsigned int u = args[1]->toString(exec).toUInt32(&ok);
1671     if (ok)
1672     {
1673       WebCore::String pstr = s;
1674       WebCore::Node *node = collection.namedItem(pstr);
1675       while (node) {
1676         if (!u)
1677           return toJS(exec,node);
1678         node = collection.nextNamedItem(pstr);
1679         --u;
1680       }
1681     }
1682   }
1683   return jsUndefined();
1684 }
1685
1686 JSValue *JSHTMLCollection::getNamedItems(ExecState* exec, const Identifier &propertyName) const
1687 {
1688     DeprecatedValueList< RefPtr<WebCore::Node> > namedItems = m_impl->namedItems(propertyName);
1689
1690     if (namedItems.isEmpty())
1691         return jsUndefined();
1692
1693     if (namedItems.count() == 1)
1694         return toJS(exec, namedItems[0].get());
1695
1696     return new DOMNamedNodesCollection(exec, namedItems);
1697 }
1698
1699 JSValue* JSHTMLCollectionProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
1700 {
1701   if (!thisObj->inherits(&JSHTMLCollection::info))
1702     return throwError(exec, TypeError);
1703   HTMLCollection &coll = *static_cast<JSHTMLCollection*>(thisObj)->impl();
1704
1705   switch (id) {
1706   case JSHTMLCollection::Item:
1707     return toJS(exec,coll.item(args[0]->toUInt32(exec)));
1708   case JSHTMLCollection::Tags:
1709     return toJS(exec, coll.base()->getElementsByTagName(args[0]->toString(exec)).get());
1710   case JSHTMLCollection::NamedItem:
1711     return static_cast<JSHTMLCollection*>(thisObj)->getNamedItems(exec, Identifier(args[0]->toString(exec)));
1712   default:
1713     return jsUndefined();
1714   }
1715 }
1716
1717 ////////////////////// Image Object ////////////////////////
1718
1719 ImageConstructorImp::ImageConstructorImp(ExecState* exec, Document* d)
1720     : m_doc(d)
1721 {
1722     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1723 }
1724
1725 bool ImageConstructorImp::implementsConstruct() const
1726 {
1727   return true;
1728 }
1729
1730 JSObject* ImageConstructorImp::construct(ExecState*  exec, const List & list)
1731 {
1732     bool widthSet = false, heightSet = false;
1733     int width = 0, height = 0;
1734     if (list.size() > 0) {
1735         widthSet = true;
1736         JSValue *w = list.at(0);
1737         width = w->toInt32(exec);
1738     }
1739     if (list.size() > 1) {
1740         heightSet = true;
1741         JSValue *h = list.at(1);
1742         height = h->toInt32(exec);
1743     }
1744         
1745     HTMLImageElement* result = new HTMLImageElement(m_doc.get());
1746     
1747     if (widthSet)
1748         result->setWidth(width);
1749     if (heightSet)
1750         result->setHeight(height);
1751     
1752     return static_cast<JSObject*>(toJS(exec, result));
1753 }
1754
1755 ////////////////////////////////////////////////////////////////
1756                      
1757 JSValue* getAllHTMLCollection(ExecState* exec, HTMLCollection* c)
1758 {
1759     return cacheDOMObject<HTMLCollection, HTMLAllCollection>(exec, c);
1760 }
1761
1762 JSValue* getHTMLCollection(ExecState* exec, HTMLCollection* c)
1763 {
1764     return cacheDOMObject<HTMLCollection, JSHTMLCollection>(exec, c);
1765 }
1766
1767 JSValue* getHTMLOptionsCollection(ExecState* exec, HTMLOptionsCollection* c)
1768 {
1769   DOMObject* ret;
1770   if (!c)
1771     return jsNull();
1772   ScriptInterpreter* interp = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter());
1773   if ((ret = interp->getDOMObject(c)))
1774     return ret;
1775   else {
1776     ret = new JSHTMLOptionsCollection(exec, c);
1777     interp->putDOMObject(c, ret);
1778     return ret;
1779   }
1780 }
1781
1782 } // namespace