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