| // -*- c-basic-offset: 4 -*- |
| /* |
| * This file is part of the KDE libraries |
| * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) |
| * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include "config.h" |
| #include "kjs_html.h" |
| |
| #include "DocLoader.h" |
| #include "EventNames.h" |
| #include "Frame.h" |
| #include "HTMLAppletElement.h" |
| #include "HTMLAreaElement.h" |
| #include "HTMLBRElement.h" |
| #include "HTMLBaseFontElement.h" |
| #include "HTMLBlockquoteElement.h" |
| #include "HTMLBodyElement.h" |
| #include "HTMLDocument.h" |
| #include "HTMLEmbedElement.h" |
| #include "HTMLFieldSetElement.h" |
| #include "HTMLFontElement.h" |
| #include "HTMLFormElement.h" |
| #include "HTMLFrameSetElement.h" |
| #include "HTMLHRElement.h" |
| #include "HTMLHeadingElement.h" |
| #include "HTMLHtmlElement.h" |
| #include "HTMLIFrameElement.h" |
| #include "HTMLImageElement.h" |
| #include "HTMLIsIndexElement.h" |
| #include "HTMLLIElement.h" |
| #include "HTMLLabelElement.h" |
| #include "HTMLLegendElement.h" |
| #include "HTMLMapElement.h" |
| #include "HTMLMenuElement.h" |
| #include "HTMLModElement.h" |
| #include "HTMLNames.h" |
| #include "HTMLObjectElement.h" |
| #include "HTMLOptionElement.h" |
| #include "HTMLOptionsCollection.h" |
| #include "HTMLParagraphElement.h" |
| #include "HTMLParamElement.h" |
| #include "HTMLPreElement.h" |
| #include "HTMLQuoteElement.h" |
| #include "HTMLScriptElement.h" |
| #include "HTMLSelectElement.h" |
| #include "HTMLTableCaptionElement.h" |
| #include "HTMLTableCellElement.h" |
| #include "HTMLTableColElement.h" |
| #include "HTMLTableElement.h" |
| #include "HTMLTableRowElement.h" |
| #include "HTMLTableSectionElement.h" |
| #include "JSHTMLImageElement.h" |
| #include "NameNodeList.h" |
| #include "RenderLayer.h" |
| #include "Text.h" |
| #include "kjs_css.h" |
| #include "kjs_events.h" |
| #include "kjs_proxy.h" |
| #include "kjs_window.h" |
| |
| #include "kjs_html.lut.h" |
| |
| using namespace WebCore; |
| using namespace HTMLNames; |
| using namespace EventNames; |
| |
| namespace KJS { |
| |
| class HTMLElementFunction : public InternalFunctionImp { |
| public: |
| HTMLElementFunction(ExecState* exec, int i, int len, const Identifier& name); |
| virtual JSValue *callAsFunction(ExecState* exec, JSObject* thisObj, const List&args); |
| private: |
| int id; |
| }; |
| |
| /* |
| @begin JSHTMLDocumentProtoTable 8 |
| clear JSHTMLDocument::Clear DontDelete|Function 0 |
| open JSHTMLDocument::Open DontDelete|Function 0 |
| close JSHTMLDocument::Close DontDelete|Function 0 |
| write JSHTMLDocument::Write DontDelete|Function 1 |
| writeln JSHTMLDocument::WriteLn DontDelete|Function 1 |
| getElementsByName JSHTMLDocument::GetElementsByName DontDelete|Function 1 |
| captureEvents JSHTMLDocument::CaptureEvents DontDelete|Function 0 |
| releaseEvents JSHTMLDocument::ReleaseEvents DontDelete|Function 0 |
| @end |
| */ |
| KJS_IMPLEMENT_PROTOFUNC(JSHTMLDocumentProtoFunc) |
| KJS_IMPLEMENT_PROTOTYPE("HTMLDocument", JSHTMLDocumentProto, JSHTMLDocumentProtoFunc) |
| |
| JSValue *JSHTMLDocumentProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args) |
| { |
| if (!thisObj->inherits(&JSHTMLDocument::info)) |
| return throwError(exec, TypeError); |
| HTMLDocument &doc = *static_cast<HTMLDocument*>(static_cast<JSHTMLDocument*>(thisObj)->impl()); |
| |
| switch (id) { |
| case JSHTMLDocument::Clear: // even IE doesn't support that one... |
| //doc.clear(); // TODO |
| return jsUndefined(); |
| case JSHTMLDocument::Open: |
| // For compatibility with other browsers, pass open calls with more than 2 parameters to the window. |
| if (args.size() > 2) { |
| Frame *frame = doc.frame(); |
| if (frame) { |
| Window *window = Window::retrieveWindow(frame); |
| if (window) { |
| JSObject* functionObject = window->get(exec, "open")->getObject(); |
| if (!functionObject || !functionObject->implementsCall()) |
| return throwError(exec, TypeError); |
| return functionObject->call(exec, window, args); |
| } |
| } |
| return jsUndefined(); |
| } |
| // In the case of two parameters or fewer, do a normal document open. |
| doc.open(); |
| return jsUndefined(); |
| case JSHTMLDocument::Close: |
| doc.close(); |
| return jsUndefined(); |
| case JSHTMLDocument::Write: |
| case JSHTMLDocument::WriteLn: { |
| // DOM only specifies single string argument, but NS & IE allow multiple |
| // or no arguments |
| String str = ""; |
| for (int i = 0; i < args.size(); i++) |
| str += args[i]->toString(exec); |
| if (id == JSHTMLDocument::WriteLn) |
| str += "\n"; |
| doc.write(str); |
| return jsUndefined(); |
| } |
| case JSHTMLDocument::GetElementsByName: |
| return toJS(exec, doc.getElementsByName(args[0]->toString(exec)).get()); |
| case JSHTMLDocument::CaptureEvents: |
| case JSHTMLDocument::ReleaseEvents: |
| // Do nothing for now. These are NS-specific legacy calls. |
| break; |
| } |
| |
| return jsUndefined(); |
| } |
| |
| |
| // FIXME: functions should be in the prototype |
| const ClassInfo JSHTMLDocument::info = |
| { "HTMLDocument", &JSDocument::info, &HTMLDocumentTable, 0 }; |
| /* Source for HTMLDocumentTable. Use "make hashtables" to regenerate. |
| @begin HTMLDocumentTable 30 |
| title JSHTMLDocument::Title DontDelete |
| referrer JSHTMLDocument::Referrer DontDelete|ReadOnly |
| domain JSHTMLDocument::Domain DontDelete |
| URL JSHTMLDocument::URL DontDelete|ReadOnly |
| body JSHTMLDocument::Body DontDelete |
| location JSHTMLDocument::Location DontDelete |
| cookie JSHTMLDocument::Cookie DontDelete |
| images JSHTMLDocument::Images DontDelete|ReadOnly |
| embeds JSHTMLDocument::Embeds DontDelete|ReadOnly |
| plugins JSHTMLDocument::Embeds DontDelete|ReadOnly |
| applets JSHTMLDocument::Applets DontDelete|ReadOnly |
| links JSHTMLDocument::Links DontDelete|ReadOnly |
| forms JSHTMLDocument::Forms DontDelete|ReadOnly |
| anchors JSHTMLDocument::Anchors DontDelete|ReadOnly |
| scripts JSHTMLDocument::Scripts DontDelete|ReadOnly |
| all JSHTMLDocument::All |
| bgColor JSHTMLDocument::BgColor DontDelete |
| fgColor JSHTMLDocument::FgColor DontDelete |
| alinkColor JSHTMLDocument::AlinkColor DontDelete |
| linkColor JSHTMLDocument::LinkColor DontDelete |
| vlinkColor JSHTMLDocument::VlinkColor DontDelete |
| lastModified JSHTMLDocument::LastModified DontDelete|ReadOnly |
| height JSHTMLDocument::Height DontDelete|ReadOnly |
| width JSHTMLDocument::Width DontDelete|ReadOnly |
| dir JSHTMLDocument::Dir DontDelete |
| designMode JSHTMLDocument::DesignMode DontDelete |
| #potentially obsolete array properties |
| # layers |
| # plugins |
| # tags |
| #potentially obsolete properties |
| # embeds |
| # ids |
| @end |
| */ |
| |
| JSHTMLDocument::JSHTMLDocument(ExecState* exec, HTMLDocument *d) |
| : JSDocument(exec, d) |
| { |
| setPrototype(JSHTMLDocumentProto::self(exec)); |
| } |
| |
| JSValue *JSHTMLDocument::namedItemGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLDocument *thisObj = static_cast<JSHTMLDocument*>(slot.slotBase()); |
| HTMLDocument &doc = *static_cast<HTMLDocument*>(thisObj->impl()); |
| |
| String name = propertyName; |
| RefPtr<WebCore::HTMLCollection> collection = doc.documentNamedItems(name); |
| |
| if (collection->length() == 1) { |
| WebCore::Node* node = collection->firstItem(); |
| Frame *frame; |
| if (node->hasTagName(iframeTag) && (frame = static_cast<WebCore::HTMLIFrameElement*>(node)->contentFrame())) |
| return Window::retrieve(frame); |
| return toJS(exec, node); |
| } |
| |
| return getHTMLCollection(exec, collection.get()); |
| } |
| |
| JSValue *JSHTMLDocument::getValueProperty(ExecState* exec, int token) const |
| { |
| HTMLDocument& doc = *static_cast<HTMLDocument*>(impl()); |
| |
| FrameView* view = doc.view(); |
| Frame* frame = doc.frame(); |
| |
| HTMLElement* body = doc.body(); |
| HTMLBodyElement* bodyElement = (body && body->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(body) : 0; |
| |
| switch (token) { |
| case Title: |
| return jsString(doc.title()); |
| case Referrer: |
| return jsString(doc.referrer()); |
| case Domain: |
| return jsString(doc.domain()); |
| case URL: |
| return jsString(doc.URL()); |
| case Body: |
| return toJS(exec, body); |
| case Location: |
| if (Window* win = Window::retrieveWindow(frame)) |
| return win->location(); |
| return jsUndefined(); |
| case Cookie: |
| return jsString(doc.cookie()); |
| case Images: |
| return getHTMLCollection(exec, doc.images().get()); |
| case Embeds: |
| return getHTMLCollection(exec, doc.embeds().get()); |
| case Applets: |
| return getHTMLCollection(exec, doc.applets().get()); |
| case Links: |
| return getHTMLCollection(exec, doc.links().get()); |
| case Forms: |
| return getHTMLCollection(exec, doc.forms().get()); |
| case Anchors: |
| return getHTMLCollection(exec, doc.anchors().get()); |
| case Scripts: |
| return getHTMLCollection(exec, doc.scripts().get()); |
| case All: |
| // If "all" has been overwritten, return the overwritten value |
| if (JSValue *v = getDirect("all")) |
| return v; |
| else |
| return getAllHTMLCollection(exec, doc.all().get()); |
| case BgColor: |
| if (!bodyElement) |
| return jsUndefined(); |
| return jsString(bodyElement->bgColor()); |
| case FgColor: |
| if (!bodyElement) |
| return jsUndefined(); |
| return jsString(bodyElement->text()); |
| case AlinkColor: |
| if (!bodyElement) |
| return jsUndefined(); |
| return jsString(bodyElement->aLink()); |
| case LinkColor: |
| if (!bodyElement) |
| return jsUndefined(); |
| return jsString(bodyElement->link()); |
| case VlinkColor: |
| if (!bodyElement) |
| return jsUndefined(); |
| return jsString(bodyElement->vLink()); |
| case LastModified: |
| return jsString(doc.lastModified()); |
| case Height: |
| return jsNumber(view ? view->contentsHeight() : 0); |
| case Width: |
| return jsNumber(view ? view->contentsWidth() : 0); |
| case Dir: |
| if (!bodyElement) |
| return jsUndefined(); |
| return jsString(bodyElement->dir()); |
| case DesignMode: |
| return jsString(doc.inDesignMode() ? "on" : "off"); |
| default: |
| assert(0); |
| return jsUndefined(); |
| } |
| } |
| |
| bool JSHTMLDocument::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) |
| { |
| HTMLDocument &doc = *static_cast<HTMLDocument*>(impl()); |
| |
| String name = propertyName; |
| if (doc.hasNamedItem(name) || doc.hasDocExtraNamedItem(name)) { |
| slot.setCustom(this, namedItemGetter); |
| return true; |
| } |
| |
| return getStaticValueSlot<JSHTMLDocument, JSDocument>(exec, &HTMLDocumentTable, this, propertyName, slot); |
| } |
| |
| void JSHTMLDocument::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr) |
| { |
| lookupPut<JSHTMLDocument, JSDocument>(exec, propertyName, value, attr, &HTMLDocumentTable, this); |
| } |
| |
| void JSHTMLDocument::putValueProperty(ExecState* exec, int token, JSValue *value, int /*attr*/) |
| { |
| DOMExceptionTranslator exception(exec); |
| HTMLDocument &doc = *static_cast<HTMLDocument*>(impl()); |
| HTMLElement* body = doc.body(); |
| HTMLBodyElement* bodyElement = (body && body->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(body) : 0; |
| |
| switch (token) { |
| case Title: |
| doc.setTitle(value->toString(exec)); |
| break; |
| case Body: |
| doc.setBody(toHTMLElement(value), exception); |
| break; |
| case Domain: // not part of the DOM |
| doc.setDomain(value->toString(exec)); |
| break; |
| case Cookie: |
| doc.setCookie(value->toString(exec)); |
| break; |
| case Location: { |
| Frame *frame = doc.frame(); |
| if (frame) |
| { |
| DeprecatedString str = value->toString(exec); |
| |
| // When assigning location, IE and Mozilla both resolve the URL |
| // relative to the frame where the JavaScript is executing not |
| // the target frame. |
| Frame *activePart = static_cast<ScriptInterpreter*>( exec->dynamicInterpreter() )->frame(); |
| if (activePart) |
| str = activePart->document()->completeURL(str); |
| |
| // We want a new history item if this JS was called via a user gesture |
| bool userGesture = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->wasRunByUserGesture(); |
| frame->scheduleLocationChange(str, activePart->referrer(), !userGesture); |
| } |
| break; |
| } |
| case BgColor: |
| if (bodyElement) |
| bodyElement->setBgColor(value->toString(exec)); |
| break; |
| case FgColor: |
| if (bodyElement) |
| bodyElement->setText(value->toString(exec)); |
| break; |
| case AlinkColor: |
| if (bodyElement) { |
| // this check is a bit silly, but some benchmarks like to set the |
| // document's link colors over and over to the same value and we |
| // don't want to incur a style update each time. |
| String newColor = value->toString(exec); |
| if (bodyElement->aLink() != newColor) |
| bodyElement->setALink(newColor); |
| } |
| break; |
| case LinkColor: |
| if (bodyElement) { |
| // this check is a bit silly, but some benchmarks like to set the |
| // document's link colors over and over to the same value and we |
| // don't want to incur a style update each time. |
| String newColor = value->toString(exec); |
| if (bodyElement->link() != newColor) |
| bodyElement->setLink(newColor); |
| } |
| break; |
| case VlinkColor: |
| if (bodyElement) { |
| // this check is a bit silly, but some benchmarks like to set the |
| // document's link colors over and over to the same value and we |
| // don't want to incur a style update each time. |
| String newColor = value->toString(exec); |
| if (bodyElement->vLink() != newColor) |
| bodyElement->setVLink(newColor); |
| } |
| break; |
| case Dir: |
| body->setDir(value->toString(exec)); |
| break; |
| case DesignMode: |
| { |
| String modeString = value->toString(exec); |
| Document::InheritedBool mode; |
| if (equalIgnoringCase(modeString, "on")) |
| mode = Document::on; |
| else if (equalIgnoringCase(modeString, "off")) |
| mode = Document::off; |
| else |
| mode = Document::inherit; |
| doc.setDesignMode(mode); |
| break; |
| } |
| case All: |
| // Add "all" to the property map. |
| putDirect("all", value); |
| break; |
| } |
| } |
| |
| // ------------------------------------------------------------------------- |
| |
| const ClassInfo JSHTMLElement::caption_info = { "HTMLTableCaptionElement", &JSHTMLElement::info, &HTMLTableCaptionElementTable, 0 }; |
| const ClassInfo JSHTMLElement::col_info = { "HTMLTableColElement", &JSHTMLElement::info, &HTMLTableColElementTable, 0 }; |
| const ClassInfo JSHTMLElement::embed_info = { "HTMLEmbedElement", &JSHTMLElement::info, &HTMLEmbedElementTable, 0 }; |
| const ClassInfo JSHTMLElement::frameSet_info = { "HTMLFrameSetElement", &JSHTMLElement::info, &HTMLFrameSetElementTable, 0 }; |
| const ClassInfo JSHTMLElement::frame_info = { "HTMLFrameElement", &JSHTMLElement::info, &HTMLFrameElementTable, 0 }; |
| const ClassInfo JSHTMLElement::iFrame_info = { "HTMLIFrameElement", &JSHTMLElement::info, &HTMLIFrameElementTable, 0 }; |
| const ClassInfo JSHTMLElement::info = { "HTMLElement", &JSElement::info, &HTMLElementTable, 0 }; |
| const ClassInfo JSHTMLElement::marquee_info = { "HTMLMarqueeElement", &JSHTMLElement::info, &HTMLMarqueeElementTable, 0 }; |
| const ClassInfo JSHTMLElement::object_info = { "HTMLObjectElement", &JSHTMLElement::info, &HTMLObjectElementTable, 0 }; |
| const ClassInfo JSHTMLElement::select_info = { "HTMLSelectElement", &JSHTMLElement::info, &HTMLSelectElementTable, 0 }; |
| const ClassInfo JSHTMLElement::table_info = { "HTMLTableElement", &JSHTMLElement::info, &HTMLTableElementTable, 0 }; |
| const ClassInfo JSHTMLElement::tablecell_info = { "HTMLTableCellElement", &JSHTMLElement::info, &HTMLTableCellElementTable, 0 }; |
| const ClassInfo JSHTMLElement::tablesection_info = { "HTMLTableSectionElement", &JSHTMLElement::info, &HTMLTableSectionElementTable, 0 }; |
| const ClassInfo JSHTMLElement::tr_info = { "HTMLTableRowElement", &JSHTMLElement::info, &HTMLTableRowElementTable, 0 }; |
| |
| const ClassInfo* JSHTMLElement::classInfo() const |
| { |
| static HashMap<WebCore::AtomicStringImpl*, const ClassInfo*> classInfoMap; |
| if (classInfoMap.isEmpty()) { |
| classInfoMap.set(captionTag.localName().impl(), &caption_info); |
| classInfoMap.set(colTag.localName().impl(), &col_info); |
| classInfoMap.set(colgroupTag.localName().impl(), &col_info); |
| classInfoMap.set(embedTag.localName().impl(), &embed_info); |
| classInfoMap.set(frameTag.localName().impl(), &frame_info); |
| classInfoMap.set(framesetTag.localName().impl(), &frameSet_info); |
| classInfoMap.set(iframeTag.localName().impl(), &iFrame_info); |
| classInfoMap.set(marqueeTag.localName().impl(), &marquee_info); |
| classInfoMap.set(objectTag.localName().impl(), &object_info); |
| classInfoMap.set(selectTag.localName().impl(), &select_info); |
| classInfoMap.set(tableTag.localName().impl(), &table_info); |
| classInfoMap.set(tbodyTag.localName().impl(), &tablesection_info); |
| classInfoMap.set(tdTag.localName().impl(), &tablecell_info); |
| classInfoMap.set(tfootTag.localName().impl(), &tablesection_info); |
| classInfoMap.set(thTag.localName().impl(), &tablecell_info); |
| classInfoMap.set(theadTag.localName().impl(), &tablesection_info); |
| classInfoMap.set(trTag.localName().impl(), &tr_info); |
| } |
| |
| HTMLElement* element = static_cast<HTMLElement*>(impl()); |
| const ClassInfo* result = classInfoMap.get(element->localName().impl()); |
| if (result) |
| return result; |
| return &info; |
| } |
| |
| const JSHTMLElement::Accessors JSHTMLElement::select_accessors = { &JSHTMLElement::selectGetter, &JSHTMLElement::selectSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::object_accessors = { &JSHTMLElement::objectGetter, &JSHTMLElement::objectSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::embed_accessors = { &JSHTMLElement::embedGetter, &JSHTMLElement::embedSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::table_accessors = { &JSHTMLElement::tableGetter, &JSHTMLElement::tableSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::caption_accessors = { &JSHTMLElement::tableCaptionGetter, &JSHTMLElement::tableCaptionSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::col_accessors = { &JSHTMLElement::tableColGetter, &JSHTMLElement::tableColSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::tablesection_accessors = { &JSHTMLElement::tableSectionGetter, &JSHTMLElement::tableSectionSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::tr_accessors = { &JSHTMLElement::tableRowGetter, &JSHTMLElement::tableRowSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::tablecell_accessors = { &JSHTMLElement::tableCellGetter, &JSHTMLElement::tableCellSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::frameSet_accessors = { &JSHTMLElement::frameSetGetter, &JSHTMLElement::frameSetSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::frame_accessors = { &JSHTMLElement::frameGetter, &JSHTMLElement::frameSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::iFrame_accessors = { &JSHTMLElement::iFrameGetter, &JSHTMLElement::iFrameSetter }; |
| const JSHTMLElement::Accessors JSHTMLElement::marquee_accessors = { &JSHTMLElement::marqueeGetter, &JSHTMLElement::marqueeSetter }; |
| |
| const JSHTMLElement::Accessors* JSHTMLElement::accessors() const |
| { |
| static HashMap<WebCore::AtomicStringImpl*, const Accessors*> accessorMap; |
| if (accessorMap.isEmpty()) { |
| accessorMap.add(captionTag.localName().impl(), &caption_accessors); |
| accessorMap.add(colTag.localName().impl(), &col_accessors); |
| accessorMap.add(colgroupTag.localName().impl(), &col_accessors); |
| accessorMap.add(embedTag.localName().impl(), &embed_accessors); |
| accessorMap.add(frameTag.localName().impl(), &frame_accessors); |
| accessorMap.add(framesetTag.localName().impl(), &frameSet_accessors); |
| accessorMap.add(iframeTag.localName().impl(), &iFrame_accessors); |
| accessorMap.add(marqueeTag.localName().impl(), &marquee_accessors); |
| accessorMap.add(objectTag.localName().impl(), &object_accessors); |
| accessorMap.add(selectTag.localName().impl(), &select_accessors); |
| accessorMap.add(tableTag.localName().impl(), &table_accessors); |
| accessorMap.add(tbodyTag.localName().impl(), &tablesection_accessors); |
| accessorMap.add(tdTag.localName().impl(), &tablecell_accessors); |
| accessorMap.add(thTag.localName().impl(), &tablecell_accessors); |
| accessorMap.add(theadTag.localName().impl(), &tablesection_accessors); |
| accessorMap.add(tfootTag.localName().impl(), &tablesection_accessors); |
| accessorMap.add(trTag.localName().impl(), &tr_accessors); |
| } |
| |
| HTMLElement* element = static_cast<HTMLElement*>(impl()); |
| return accessorMap.get(element->localName().impl()); |
| } |
| |
| /* |
| |
| @begin JSHTMLElementProtoTable 0 |
| @end |
| |
| @begin HTMLElementTable 14 |
| id KJS::JSHTMLElement::ElementId DontDelete |
| lang KJS::JSHTMLElement::ElementLang DontDelete |
| dir KJS::JSHTMLElement::ElementDir DontDelete |
| ### isn't this "class" in the HTML spec? |
| className KJS::JSHTMLElement::ElementClassName DontDelete |
| innerHTML KJS::JSHTMLElement::ElementInnerHTML DontDelete |
| innerText KJS::JSHTMLElement::ElementInnerText DontDelete |
| outerHTML KJS::JSHTMLElement::ElementOuterHTML DontDelete |
| outerText KJS::JSHTMLElement::ElementOuterText DontDelete |
| document KJS::JSHTMLElement::ElementDocument DontDelete|ReadOnly |
| # IE extension |
| children KJS::JSHTMLElement::ElementChildren DontDelete|ReadOnly |
| contentEditable KJS::JSHTMLElement::ElementContentEditable DontDelete |
| isContentEditable KJS::JSHTMLElement::ElementIsContentEditable DontDelete|ReadOnly |
| @end |
| @begin HTMLSelectElementTable 11 |
| # Also supported, by index |
| type KJS::JSHTMLElement::SelectType DontDelete|ReadOnly |
| selectedIndex KJS::JSHTMLElement::SelectSelectedIndex DontDelete |
| value KJS::JSHTMLElement::SelectValue DontDelete |
| length KJS::JSHTMLElement::SelectLength DontDelete |
| form KJS::JSHTMLElement::SelectForm DontDelete|ReadOnly |
| options KJS::JSHTMLElement::SelectOptions DontDelete|ReadOnly |
| namedItem KJS::JSHTMLElement::SelectNamedItem DontDelete|Function 1 |
| disabled KJS::JSHTMLElement::SelectDisabled DontDelete |
| multiple KJS::JSHTMLElement::SelectMultiple DontDelete |
| name KJS::JSHTMLElement::SelectName DontDelete |
| size KJS::JSHTMLElement::SelectSize DontDelete |
| tabIndex KJS::JSHTMLElement::SelectTabIndex DontDelete |
| add KJS::JSHTMLElement::SelectAdd DontDelete|Function 2 |
| remove KJS::JSHTMLElement::SelectRemove DontDelete|Function 1 |
| blur KJS::JSHTMLElement::SelectBlur DontDelete|Function 0 |
| focus KJS::JSHTMLElement::SelectFocus DontDelete|Function 0 |
| @end |
| @begin HTMLObjectElementTable 20 |
| form KJS::JSHTMLElement::ObjectForm DontDelete|ReadOnly |
| code KJS::JSHTMLElement::ObjectCode DontDelete |
| align KJS::JSHTMLElement::ObjectAlign DontDelete |
| archive KJS::JSHTMLElement::ObjectArchive DontDelete |
| border KJS::JSHTMLElement::ObjectBorder DontDelete |
| codeBase KJS::JSHTMLElement::ObjectCodeBase DontDelete |
| codeType KJS::JSHTMLElement::ObjectCodeType DontDelete |
| contentDocument KJS::JSHTMLElement::ObjectContentDocument DontDelete|ReadOnly |
| data KJS::JSHTMLElement::ObjectData DontDelete |
| declare KJS::JSHTMLElement::ObjectDeclare DontDelete |
| height KJS::JSHTMLElement::ObjectHeight DontDelete |
| hspace KJS::JSHTMLElement::ObjectHspace DontDelete |
| name KJS::JSHTMLElement::ObjectName DontDelete |
| standby KJS::JSHTMLElement::ObjectStandby DontDelete |
| tabIndex KJS::JSHTMLElement::ObjectTabIndex DontDelete |
| type KJS::JSHTMLElement::ObjectType DontDelete |
| useMap KJS::JSHTMLElement::ObjectUseMap DontDelete |
| vspace KJS::JSHTMLElement::ObjectVspace DontDelete |
| width KJS::JSHTMLElement::ObjectWidth DontDelete |
| @end |
| @begin HTMLEmbedElementTable 6 |
| align KJS::JSHTMLElement::EmbedAlign DontDelete |
| height KJS::JSHTMLElement::EmbedHeight DontDelete |
| name KJS::JSHTMLElement::EmbedName DontDelete |
| src KJS::JSHTMLElement::EmbedSrc DontDelete |
| type KJS::JSHTMLElement::EmbedType DontDelete |
| width KJS::JSHTMLElement::EmbedWidth DontDelete |
| @end |
| @begin HTMLTableElementTable 23 |
| caption KJS::JSHTMLElement::TableCaption DontDelete |
| tHead KJS::JSHTMLElement::TableTHead DontDelete |
| tFoot KJS::JSHTMLElement::TableTFoot DontDelete |
| rows KJS::JSHTMLElement::TableRows DontDelete|ReadOnly |
| tBodies KJS::JSHTMLElement::TableTBodies DontDelete|ReadOnly |
| align KJS::JSHTMLElement::TableAlign DontDelete |
| bgColor KJS::JSHTMLElement::TableBgColor DontDelete |
| border KJS::JSHTMLElement::TableBorder DontDelete |
| cellPadding KJS::JSHTMLElement::TableCellPadding DontDelete |
| cellSpacing KJS::JSHTMLElement::TableCellSpacing DontDelete |
| frame KJS::JSHTMLElement::TableFrame DontDelete |
| rules KJS::JSHTMLElement::TableRules DontDelete |
| summary KJS::JSHTMLElement::TableSummary DontDelete |
| width KJS::JSHTMLElement::TableWidth DontDelete |
| createTHead KJS::JSHTMLElement::TableCreateTHead DontDelete|Function 0 |
| deleteTHead KJS::JSHTMLElement::TableDeleteTHead DontDelete|Function 0 |
| createTFoot KJS::JSHTMLElement::TableCreateTFoot DontDelete|Function 0 |
| deleteTFoot KJS::JSHTMLElement::TableDeleteTFoot DontDelete|Function 0 |
| createCaption KJS::JSHTMLElement::TableCreateCaption DontDelete|Function 0 |
| deleteCaption KJS::JSHTMLElement::TableDeleteCaption DontDelete|Function 0 |
| insertRow KJS::JSHTMLElement::TableInsertRow DontDelete|Function 1 |
| deleteRow KJS::JSHTMLElement::TableDeleteRow DontDelete|Function 1 |
| @end |
| @begin HTMLTableCaptionElementTable 1 |
| align KJS::JSHTMLElement::TableCaptionAlign DontDelete |
| @end |
| @begin HTMLTableColElementTable 7 |
| align KJS::JSHTMLElement::TableColAlign DontDelete |
| ch KJS::JSHTMLElement::TableColCh DontDelete |
| chOff KJS::JSHTMLElement::TableColChOff DontDelete |
| span KJS::JSHTMLElement::TableColSpan DontDelete |
| vAlign KJS::JSHTMLElement::TableColVAlign DontDelete |
| width KJS::JSHTMLElement::TableColWidth DontDelete |
| @end |
| @begin HTMLTableSectionElementTable 7 |
| align KJS::JSHTMLElement::TableSectionAlign DontDelete |
| ch KJS::JSHTMLElement::TableSectionCh DontDelete |
| chOff KJS::JSHTMLElement::TableSectionChOff DontDelete |
| vAlign KJS::JSHTMLElement::TableSectionVAlign DontDelete |
| rows KJS::JSHTMLElement::TableSectionRows DontDelete|ReadOnly |
| insertRow KJS::JSHTMLElement::TableSectionInsertRow DontDelete|Function 1 |
| deleteRow KJS::JSHTMLElement::TableSectionDeleteRow DontDelete|Function 1 |
| @end |
| @begin HTMLTableRowElementTable 11 |
| rowIndex KJS::JSHTMLElement::TableRowRowIndex DontDelete|ReadOnly |
| sectionRowIndex KJS::JSHTMLElement::TableRowSectionRowIndex DontDelete|ReadOnly |
| cells KJS::JSHTMLElement::TableRowCells DontDelete|ReadOnly |
| align KJS::JSHTMLElement::TableRowAlign DontDelete |
| bgColor KJS::JSHTMLElement::TableRowBgColor DontDelete |
| ch KJS::JSHTMLElement::TableRowCh DontDelete |
| chOff KJS::JSHTMLElement::TableRowChOff DontDelete |
| vAlign KJS::JSHTMLElement::TableRowVAlign DontDelete |
| insertCell KJS::JSHTMLElement::TableRowInsertCell DontDelete|Function 1 |
| deleteCell KJS::JSHTMLElement::TableRowDeleteCell DontDelete|Function 1 |
| @end |
| @begin HTMLTableCellElementTable 15 |
| cellIndex KJS::JSHTMLElement::TableCellCellIndex DontDelete|ReadOnly |
| abbr KJS::JSHTMLElement::TableCellAbbr DontDelete |
| align KJS::JSHTMLElement::TableCellAlign DontDelete |
| axis KJS::JSHTMLElement::TableCellAxis DontDelete |
| bgColor KJS::JSHTMLElement::TableCellBgColor DontDelete |
| ch KJS::JSHTMLElement::TableCellCh DontDelete |
| chOff KJS::JSHTMLElement::TableCellChOff DontDelete |
| colSpan KJS::JSHTMLElement::TableCellColSpan DontDelete |
| headers KJS::JSHTMLElement::TableCellHeaders DontDelete |
| height KJS::JSHTMLElement::TableCellHeight DontDelete |
| noWrap KJS::JSHTMLElement::TableCellNoWrap DontDelete |
| rowSpan KJS::JSHTMLElement::TableCellRowSpan DontDelete |
| scope KJS::JSHTMLElement::TableCellScope DontDelete |
| vAlign KJS::JSHTMLElement::TableCellVAlign DontDelete |
| width KJS::JSHTMLElement::TableCellWidth DontDelete |
| @end |
| @begin HTMLFrameSetElementTable 2 |
| cols KJS::JSHTMLElement::FrameSetCols DontDelete |
| rows KJS::JSHTMLElement::FrameSetRows DontDelete |
| @end |
| @begin HTMLFrameElementTable 9 |
| contentDocument KJS::JSHTMLElement::FrameContentDocument DontDelete|ReadOnly |
| contentWindow KJS::JSHTMLElement::FrameContentWindow DontDelete|ReadOnly |
| frameBorder KJS::JSHTMLElement::FrameFrameBorder DontDelete |
| longDesc KJS::JSHTMLElement::FrameLongDesc DontDelete |
| marginHeight KJS::JSHTMLElement::FrameMarginHeight DontDelete |
| marginWidth KJS::JSHTMLElement::FrameMarginWidth DontDelete |
| name KJS::JSHTMLElement::FrameName DontDelete |
| noResize KJS::JSHTMLElement::FrameNoResize DontDelete |
| width KJS::JSHTMLElement::FrameWidth DontDelete|ReadOnly |
| height KJS::JSHTMLElement::FrameHeight DontDelete|ReadOnly |
| scrolling KJS::JSHTMLElement::FrameScrolling DontDelete |
| src KJS::JSHTMLElement::FrameSrc DontDelete |
| location KJS::JSHTMLElement::FrameLocation DontDelete |
| @end |
| @begin HTMLIFrameElementTable 12 |
| align KJS::JSHTMLElement::IFrameAlign DontDelete |
| contentDocument KJS::JSHTMLElement::IFrameContentDocument DontDelete|ReadOnly |
| contentWindow KJS::JSHTMLElement::IFrameContentWindow DontDelete|ReadOnly |
| document KJS::JSHTMLElement::IFrameDocument DontDelete|ReadOnly |
| frameBorder KJS::JSHTMLElement::IFrameFrameBorder DontDelete |
| height KJS::JSHTMLElement::IFrameHeight DontDelete |
| longDesc KJS::JSHTMLElement::IFrameLongDesc DontDelete |
| marginHeight KJS::JSHTMLElement::IFrameMarginHeight DontDelete |
| marginWidth KJS::JSHTMLElement::IFrameMarginWidth DontDelete |
| name KJS::JSHTMLElement::IFrameName DontDelete |
| scrolling KJS::JSHTMLElement::IFrameScrolling DontDelete |
| src KJS::JSHTMLElement::IFrameSrc DontDelete |
| width KJS::JSHTMLElement::IFrameWidth DontDelete |
| @end |
| |
| @begin HTMLMarqueeElementTable 2 |
| start KJS::JSHTMLElement::MarqueeStart DontDelete|Function 0 |
| stop KJS::JSHTMLElement::MarqueeStop DontDelete|Function 0 |
| @end |
| */ |
| |
| KJS_IMPLEMENT_PROTOFUNC(JSHTMLElementProtoFunc) |
| KJS_IMPLEMENT_PROTOTYPE("HTMLElement", JSHTMLElementProto, JSHTMLElementProtoFunc) |
| |
| JSValue* JSHTMLElementProtoFunc::callAsFunction(ExecState*, JSObject*, const List&) |
| { |
| return 0; |
| } |
| |
| JSHTMLElement::JSHTMLElement(ExecState* exec, HTMLElement* e) |
| : WebCore::JSHTMLElement(exec, e) |
| { |
| setPrototype(JSHTMLElementProto::self(exec)); |
| } |
| |
| JSValue *JSHTMLElement::selectIndexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase()); |
| HTMLSelectElement* select = static_cast<HTMLSelectElement*>(thisObj->impl()); |
| |
| return toJS(exec, select->options()->item(slot.index())); |
| } |
| |
| JSValue *JSHTMLElement::framesetNameGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase()); |
| HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl()); |
| |
| WebCore::Node *frame = element->children()->namedItem(propertyName); |
| if (Document* doc = static_cast<HTMLFrameElement*>(frame)->contentDocument()) |
| if (Window *window = Window::retrieveWindow(doc->frame())) |
| return window; |
| |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::runtimeObjectGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase()); |
| HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl()); |
| |
| return getRuntimeObject(exec, element); |
| } |
| |
| JSValue *JSHTMLElement::runtimeObjectPropertyGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase()); |
| HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl()); |
| |
| if (JSValue *runtimeObject = getRuntimeObject(exec, element)) |
| return static_cast<JSObject*>(runtimeObject)->get(exec, propertyName); |
| return jsUndefined(); |
| } |
| |
| bool JSHTMLElement::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) |
| { |
| HTMLElement &element = *static_cast<HTMLElement*>(impl()); |
| |
| // First look at dynamic properties |
| if (element.hasLocalName(selectTag)) { |
| bool ok; |
| unsigned u = propertyName.toUInt32(&ok); |
| if (ok) { |
| // not specified by DOM(?) but supported in netscape/IE |
| slot.setCustomIndex(this, u, selectIndexGetter); |
| return true; |
| } |
| } else if (element.hasLocalName(framesetTag)) { |
| WebCore::Node *frame = element.children()->namedItem(propertyName); |
| if (frame && frame->hasTagName(frameTag)) { |
| slot.setCustom(this, framesetNameGetter); |
| return true; |
| } |
| } else if (element.hasLocalName(embedTag) || element.hasLocalName(objectTag) || element.hasLocalName(appletTag)) { |
| if (propertyName == "__apple_runtime_object") { |
| slot.setCustom(this, runtimeObjectGetter); |
| return true; |
| } |
| JSValue *runtimeObject = getRuntimeObject(exec,&element); |
| if (runtimeObject) { |
| JSObject* imp = static_cast<JSObject*>(runtimeObject); |
| if (imp->hasProperty(exec, propertyName)) { |
| slot.setCustom(this, runtimeObjectPropertyGetter); |
| return true; |
| } |
| } |
| } |
| |
| const HashTable* table = classInfo()->propHashTable; // get the right hashtable |
| const HashEntry* entry = Lookup::findEntry(table, propertyName); |
| if (entry) { |
| if (entry->attr & Function) |
| slot.setStaticEntry(this, entry, staticFunctionGetter<HTMLElementFunction>); |
| else |
| slot.setStaticEntry(this, entry, staticValueGetter<JSHTMLElement>); |
| return true; |
| } |
| |
| // Base JSHTMLElement stuff or parent class forward, as usual |
| return getStaticPropertySlot<HTMLElementFunction, JSHTMLElement, WebCore::JSHTMLElement>(exec, &HTMLElementTable, this, propertyName, slot); |
| } |
| |
| bool JSHTMLElement::implementsCall() const |
| { |
| HTMLElement* element = static_cast<HTMLElement*>(impl()); |
| if (element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) { |
| Document* doc = element->document(); |
| KJSProxy *proxy = doc->frame()->jScript(); |
| ExecState* exec = proxy->interpreter()->globalExec(); |
| if (JSValue *runtimeObject = getRuntimeObject(exec, element)) |
| return static_cast<JSObject*>(runtimeObject)->implementsCall(); |
| } |
| return false; |
| } |
| |
| JSValue *JSHTMLElement::callAsFunction(ExecState* exec, JSObject* thisObj, const List&args) |
| { |
| HTMLElement* element = static_cast<HTMLElement*>(impl()); |
| if (element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) { |
| if (JSValue *runtimeObject = getRuntimeObject(exec, element)) |
| return static_cast<JSObject*>(runtimeObject)->call(exec, thisObj, args); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::selectGetter(ExecState* exec, int token) const |
| { |
| HTMLSelectElement& select = *static_cast<HTMLSelectElement*>(impl()); |
| switch (token) { |
| case SelectType: return jsString(select.type()); |
| case SelectSelectedIndex: return jsNumber(select.selectedIndex()); |
| case SelectValue: return jsString(select.value()); |
| case SelectLength: return jsNumber(select.length()); |
| case SelectForm: return toJS(exec, select.form()); // type HTMLFormElement |
| case SelectOptions: return getSelectHTMLCollection(exec, select.options().get(), &select); // type JSHTMLCollection |
| case SelectDisabled: return jsBoolean(select.disabled()); |
| case SelectMultiple: return jsBoolean(select.multiple()); |
| case SelectName: return jsString(select.name()); |
| case SelectSize: return jsNumber(select.size()); |
| case SelectTabIndex: return jsNumber(select.tabIndex()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::objectGetter(ExecState* exec, int token) const |
| { |
| HTMLObjectElement& object = *static_cast<HTMLObjectElement*>(impl()); |
| switch (token) { |
| case ObjectForm: return toJS(exec,object.form()); // type HTMLFormElement |
| case ObjectCode: return jsString(object.code()); |
| case ObjectAlign: return jsString(object.align()); |
| case ObjectArchive: return jsString(object.archive()); |
| case ObjectBorder: return jsString(object.border()); |
| case ObjectCodeBase: return jsString(object.codeBase()); |
| case ObjectCodeType: return jsString(object.codeType()); |
| case ObjectContentDocument: return checkNodeSecurity(exec,object.contentDocument()) ? |
| toJS(exec, object.contentDocument()) : jsUndefined(); |
| case ObjectData: return jsString(object.data()); |
| case ObjectDeclare: return jsBoolean(object.declare()); |
| case ObjectHeight: return jsString(object.height()); |
| case ObjectHspace: return jsString(object.hspace()); |
| case ObjectName: return jsString(object.name()); |
| case ObjectStandby: return jsString(object.standby()); |
| case ObjectTabIndex: return jsNumber(object.tabIndex()); |
| case ObjectType: return jsString(object.type()); |
| case ObjectUseMap: return jsString(object.useMap()); |
| case ObjectVspace: return jsString(object.vspace()); |
| case ObjectWidth: return jsString(object.width()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::embedGetter(ExecState* exec, int token) const |
| { |
| HTMLEmbedElement& embed = *static_cast<HTMLEmbedElement*>(impl()); |
| switch (token) { |
| case EmbedAlign: return jsString(embed.align()); |
| case EmbedHeight: return jsString(embed.height()); |
| case EmbedName: return jsString(embed.name()); |
| case EmbedSrc: return jsString(embed.src()); |
| case EmbedType: return jsString(embed.type()); |
| case EmbedWidth: return jsString(embed.width()); |
| } |
| return jsUndefined(); |
| } |
| |
| #ifdef FIXME |
| HTMLAreaElement& area = *static_cast<HTMLAreaElement*>(impl()); |
| switch (token) { |
| case AreaAccessKey: return jsString(area.accessKey()); |
| case AreaAlt: return jsString(area.alt()); |
| case AreaCoords: return jsString(area.coords()); |
| case AreaHref: return jsString(area.href()); |
| case AreaHash: return jsString('#'+KURL(area.href().deprecatedString()).ref()); |
| case AreaHost: return jsString(KURL(area.href().deprecatedString()).host()); |
| case AreaHostName: { |
| KURL url(area.href().deprecatedString()); |
| if (url.port()==0) |
| return jsString(url.host()); |
| else |
| return jsString(url.host() + ":" + DeprecatedString::number(url.port())); |
| } |
| case AreaPathName: return jsString(KURL(area.href().deprecatedString()).path()); |
| case AreaPort: return jsString(DeprecatedString::number(KURL(area.href().deprecatedString()).port())); |
| case AreaProtocol: return jsString(KURL(area.href().deprecatedString()).protocol()+":"); |
| case AreaSearch: return jsString(KURL(area.href().deprecatedString()).query()); |
| case AreaNoHref: return jsBoolean(area.noHref()); |
| case AreaShape: return jsString(area.shape()); |
| case AreaTabIndex: return jsNumber(area.tabIndex()); |
| case AreaTarget: return jsString(area.target()); |
| } |
| #endif |
| |
| JSValue *JSHTMLElement::tableGetter(ExecState* exec, int token) const |
| { |
| HTMLTableElement& table = *static_cast<HTMLTableElement*>(impl()); |
| switch (token) { |
| case TableCaption: return toJS(exec,table.caption()); // type HTMLTableCaptionElement |
| case TableTHead: return toJS(exec,table.tHead()); // type HTMLTableSectionElement |
| case TableTFoot: return toJS(exec,table.tFoot()); // type HTMLTableSectionElement |
| case TableRows: return getHTMLCollection(exec, table.rows().get()); // type JSHTMLCollection |
| case TableTBodies: return getHTMLCollection(exec, table.tBodies().get()); // type JSHTMLCollection |
| case TableAlign: return jsString(table.align()); |
| case TableBgColor: return jsString(table.bgColor()); |
| case TableBorder: return jsString(table.border()); |
| case TableCellPadding: return jsString(table.cellPadding()); |
| case TableCellSpacing: return jsString(table.cellSpacing()); |
| case TableFrame: return jsString(table.frame()); |
| case TableRules: return jsString(table.rules()); |
| case TableSummary: return jsString(table.summary()); |
| case TableWidth: return jsString(table.width()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::tableCaptionGetter(ExecState* exec, int token) const |
| { |
| HTMLTableCaptionElement& tableCaption = *static_cast<HTMLTableCaptionElement*>(impl()); |
| if (token == TableCaptionAlign) |
| return jsString(tableCaption.align()); |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::tableColGetter(ExecState* exec, int token) const |
| { |
| HTMLTableColElement& tableCol = *static_cast<HTMLTableColElement*>(impl()); |
| switch (token) { |
| case TableColAlign: return jsString(tableCol.align()); |
| case TableColCh: return jsString(tableCol.ch()); |
| case TableColChOff: return jsString(tableCol.chOff()); |
| case TableColSpan: return jsNumber(tableCol.span()); |
| case TableColVAlign: return jsString(tableCol.vAlign()); |
| case TableColWidth: return jsString(tableCol.width()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::tableSectionGetter(ExecState* exec, int token) const |
| { |
| HTMLTableSectionElement& tableSection = *static_cast<HTMLTableSectionElement*>(impl()); |
| switch (token) { |
| case TableSectionAlign: return jsString(tableSection.align()); |
| case TableSectionCh: return jsString(tableSection.ch()); |
| case TableSectionChOff: return jsString(tableSection.chOff()); |
| case TableSectionVAlign: return jsString(tableSection.vAlign()); |
| case TableSectionRows: return getHTMLCollection(exec, tableSection.rows().get()); // type JSHTMLCollection |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::tableRowGetter(ExecState* exec, int token) const |
| { |
| HTMLTableRowElement& tableRow = *static_cast<HTMLTableRowElement*>(impl()); |
| switch (token) { |
| case TableRowRowIndex: return jsNumber(tableRow.rowIndex()); |
| case TableRowSectionRowIndex: return jsNumber(tableRow.sectionRowIndex()); |
| case TableRowCells: return getHTMLCollection(exec, tableRow.cells().get()); // type JSHTMLCollection |
| case TableRowAlign: return jsString(tableRow.align()); |
| case TableRowBgColor: return jsString(tableRow.bgColor()); |
| case TableRowCh: return jsString(tableRow.ch()); |
| case TableRowChOff: return jsString(tableRow.chOff()); |
| case TableRowVAlign: return jsString(tableRow.vAlign()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::tableCellGetter(ExecState* exec, int token) const |
| { |
| HTMLTableCellElement& tableCell = *static_cast<HTMLTableCellElement*>(impl()); |
| switch (token) { |
| case TableCellCellIndex: return jsNumber(tableCell.cellIndex()); |
| case TableCellAbbr: return jsString(tableCell.abbr()); |
| case TableCellAlign: return jsString(tableCell.align()); |
| case TableCellAxis: return jsString(tableCell.axis()); |
| case TableCellBgColor: return jsString(tableCell.bgColor()); |
| case TableCellCh: return jsString(tableCell.ch()); |
| case TableCellChOff: return jsString(tableCell.chOff()); |
| case TableCellColSpan: return jsNumber(tableCell.colSpan()); |
| case TableCellHeaders: return jsString(tableCell.headers()); |
| case TableCellHeight: return jsString(tableCell.height()); |
| case TableCellNoWrap: return jsBoolean(tableCell.noWrap()); |
| case TableCellRowSpan: return jsNumber(tableCell.rowSpan()); |
| case TableCellScope: return jsString(tableCell.scope()); |
| case TableCellVAlign: return jsString(tableCell.vAlign()); |
| case TableCellWidth: return jsString(tableCell.width()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::frameSetGetter(ExecState* exec, int token) const |
| { |
| HTMLFrameSetElement& frameSet = *static_cast<HTMLFrameSetElement*>(impl()); |
| switch (token) { |
| case FrameSetCols: return jsString(frameSet.cols()); |
| case FrameSetRows: return jsString(frameSet.rows()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::frameGetter(ExecState* exec, int token) const |
| { |
| HTMLFrameElement& frameElement = *static_cast<HTMLFrameElement*>(impl()); |
| switch (token) { |
| case FrameContentDocument: return checkNodeSecurity(exec,frameElement.contentDocument()) ? |
| toJS(exec, frameElement.contentDocument()) : jsUndefined(); |
| case FrameContentWindow: return checkNodeSecurity(exec,frameElement.contentDocument()) |
| ? Window::retrieve(frameElement.contentFrame()) |
| : jsUndefined(); |
| case FrameFrameBorder: return jsString(frameElement.frameBorder()); |
| case FrameLongDesc: return jsString(frameElement.longDesc()); |
| case FrameMarginHeight: return jsString(frameElement.marginHeight()); |
| case FrameMarginWidth: return jsString(frameElement.marginWidth()); |
| case FrameName: return jsString(frameElement.name()); |
| case FrameNoResize: return jsBoolean(frameElement.noResize()); |
| case FrameWidth: return jsNumber(frameElement.frameWidth()); |
| case FrameHeight: return jsNumber(frameElement.frameHeight()); |
| case FrameScrolling: return jsString(frameElement.scrolling()); |
| case FrameSrc: |
| case FrameLocation: return jsString(frameElement.src()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::iFrameGetter(ExecState* exec, int token) const |
| { |
| HTMLIFrameElement& iFrame = *static_cast<HTMLIFrameElement*>(impl()); |
| switch (token) { |
| case IFrameAlign: return jsString(iFrame.align()); |
| // ### security check ? |
| case IFrameDocument: // non-standard, mapped to contentDocument |
| case IFrameContentDocument: return checkNodeSecurity(exec,iFrame.contentDocument()) ? |
| toJS(exec, iFrame.contentDocument()) : jsUndefined(); |
| case IFrameContentWindow: return checkNodeSecurity(exec,iFrame.contentDocument()) |
| ? Window::retrieve(iFrame.contentFrame()) |
| : jsUndefined(); |
| case IFrameFrameBorder: return jsString(iFrame.frameBorder()); |
| case IFrameHeight: return jsString(iFrame.height()); |
| case IFrameLongDesc: return jsString(iFrame.longDesc()); |
| case IFrameMarginHeight: return jsString(iFrame.marginHeight()); |
| case IFrameMarginWidth: return jsString(iFrame.marginWidth()); |
| case IFrameName: return jsString(iFrame.name()); |
| case IFrameScrolling: return jsString(iFrame.scrolling()); |
| case IFrameSrc: return jsString(iFrame.src()); |
| case IFrameWidth: return jsString(iFrame.width()); |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::marqueeGetter(ExecState* exec, int token) const |
| { |
| // FIXME: Find out what WinIE exposes as properties and implement this. |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLElement::getValueProperty(ExecState* exec, int token) const |
| { |
| // Check our set of generic properties first. |
| HTMLElement &element = *static_cast<HTMLElement*>(impl()); |
| switch (token) { |
| case ElementId: |
| // iht.com relies on this value being "" when no id is present. Other browsers do this as well. |
| // So we use jsString() instead of jsStringOrNull() here. |
| return jsString(element.id()); |
| case ElementLang: |
| return jsString(element.lang()); |
| case ElementDir: |
| return jsString(element.dir()); |
| case ElementClassName: |
| return jsString(element.className()); |
| case ElementInnerHTML: |
| return jsString(element.innerHTML()); |
| case ElementInnerText: |
| impl()->document()->updateLayoutIgnorePendingStylesheets(); |
| return jsString(element.innerText()); |
| case ElementOuterHTML: |
| return jsString(element.outerHTML()); |
| case ElementOuterText: |
| return jsString(element.outerText()); |
| case ElementDocument: |
| return toJS(exec,element.ownerDocument()); |
| case ElementChildren: |
| return getHTMLCollection(exec, element.children().get()); |
| case ElementContentEditable: |
| return jsString(element.contentEditable()); |
| case ElementIsContentEditable: |
| return jsBoolean(element.isContentEditable()); |
| } |
| |
| // Now check the properties specific to our element type. |
| const Accessors* access = accessors(); |
| if (access && access->m_getter) |
| return (this->*(access->m_getter))(exec, token); |
| return jsUndefined(); |
| } |
| |
| UString JSHTMLElement::toString(ExecState* exec) const |
| { |
| if (impl()->hasTagName(aTag)) |
| return UString(static_cast<const HTMLAnchorElement*>(impl())->href()); |
| else |
| return JSElement::toString(exec); |
| } |
| |
| static HTMLFormElement* getForm(HTMLElement* element) |
| { |
| if (element->isGenericFormElement()) |
| return static_cast<HTMLGenericFormElement*>(element)->form(); |
| if (element->hasTagName(labelTag)) |
| return static_cast<HTMLLabelElement*>(element)->form(); |
| if (element->hasTagName(objectTag)) |
| return static_cast<HTMLObjectElement*>(element)->form(); |
| |
| return 0; |
| } |
| |
| void JSHTMLElement::pushEventHandlerScope(ExecState* exec, ScopeChain &scope) const |
| { |
| HTMLElement* element = static_cast<HTMLElement*>(impl()); |
| |
| // The document is put on first, fall back to searching it only after the element and form. |
| scope.push(static_cast<JSObject*>(toJS(exec, element->ownerDocument()))); |
| |
| // The form is next, searched before the document, but after the element itself. |
| |
| // First try to obtain the form from the element itself. We do this to deal with |
| // the malformed case where <form>s aren't in our parent chain (e.g., when they were inside |
| // <table> or <tbody>. |
| HTMLFormElement* form = getForm(element); |
| if (form) |
| scope.push(static_cast<JSObject*>(toJS(exec, form))); |
| else { |
| WebCore::Node* form = element->parentNode(); |
| while (form && !form->hasTagName(formTag)) |
| form = form->parentNode(); |
| |
| if (form) |
| scope.push(static_cast<JSObject*>(toJS(exec, form))); |
| } |
| |
| // The element is on top, searched first. |
| scope.push(static_cast<JSObject*>(toJS(exec, element))); |
| } |
| |
| HTMLElementFunction::HTMLElementFunction(ExecState* exec, int i, int len, const Identifier& name) |
| : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name) |
| , id(i) |
| { |
| put(exec,lengthPropertyName,jsNumber(len),DontDelete|ReadOnly|DontEnum); |
| } |
| |
| JSValue *HTMLElementFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args) |
| { |
| if (!thisObj->inherits(&JSHTMLElement::info)) |
| return throwError(exec, TypeError); |
| DOMExceptionTranslator exception(exec); |
| HTMLElement &element = *static_cast<HTMLElement*>(static_cast<JSHTMLElement*>(thisObj)->impl()); |
| |
| if (element.hasLocalName(selectTag)) { |
| HTMLSelectElement &select = static_cast<HTMLSelectElement &>(element); |
| if (id == JSHTMLElement::SelectAdd) { |
| select.add(toHTMLElement(args[0]), toHTMLElement(args[1]), exception); |
| return jsUndefined(); |
| } |
| else if (id == JSHTMLElement::SelectRemove) { |
| // we support both options index and options objects |
| HTMLElement* element = toHTMLElement(args[0]); |
| if (element && element->hasTagName(optionTag)) |
| select.remove(((HTMLOptionElement*)element)->index()); |
| else |
| select.remove(int(args[0]->toNumber(exec))); |
| return jsUndefined(); |
| } |
| else if (id == JSHTMLElement::SelectBlur) { |
| select.blur(); |
| return jsUndefined(); |
| } |
| else if (id == JSHTMLElement::SelectFocus) { |
| select.focus(); |
| return jsUndefined(); |
| } |
| else if (id == JSHTMLElement::SelectNamedItem) { |
| return toJS(exec, select.namedItem(Identifier(args[0]->toString(exec)))); |
| } |
| } |
| else if (element.hasLocalName(tableTag)) { |
| HTMLTableElement &table = static_cast<HTMLTableElement &>(element); |
| if (id == JSHTMLElement::TableCreateTHead) |
| return toJS(exec,table.createTHead()); |
| else if (id == JSHTMLElement::TableDeleteTHead) { |
| table.deleteTHead(); |
| return jsUndefined(); |
| } |
| else if (id == JSHTMLElement::TableCreateTFoot) |
| return toJS(exec,table.createTFoot()); |
| else if (id == JSHTMLElement::TableDeleteTFoot) { |
| table.deleteTFoot(); |
| return jsUndefined(); |
| } |
| else if (id == JSHTMLElement::TableCreateCaption) |
| return toJS(exec,table.createCaption()); |
| else if (id == JSHTMLElement::TableDeleteCaption) { |
| table.deleteCaption(); |
| return jsUndefined(); |
| } |
| else if (id == JSHTMLElement::TableInsertRow) |
| return toJS(exec,table.insertRow(args[0]->toInt32(exec), exception)); |
| else if (id == JSHTMLElement::TableDeleteRow) { |
| table.deleteRow(args[0]->toInt32(exec), exception); |
| return jsUndefined(); |
| } |
| } |
| else if (element.hasLocalName(theadTag) || |
| element.hasLocalName(tbodyTag) || |
| element.hasLocalName(tfootTag)) { |
| HTMLTableSectionElement &tableSection = static_cast<HTMLTableSectionElement &>(element); |
| if (id == JSHTMLElement::TableSectionInsertRow) |
| return toJS(exec, tableSection.insertRow(args[0]->toInt32(exec), exception)); |
| else if (id == JSHTMLElement::TableSectionDeleteRow) { |
| tableSection.deleteRow(args[0]->toInt32(exec), exception); |
| return jsUndefined(); |
| } |
| } |
| else if (element.hasLocalName(trTag)) { |
| HTMLTableRowElement &tableRow = static_cast<HTMLTableRowElement &>(element); |
| if (id == JSHTMLElement::TableRowInsertCell) |
| return toJS(exec,tableRow.insertCell(args[0]->toInt32(exec), exception)); |
| else if (id == JSHTMLElement::TableRowDeleteCell) { |
| tableRow.deleteCell(args[0]->toInt32(exec), exception); |
| return jsUndefined(); |
| } |
| } |
| else if (element.hasLocalName(marqueeTag)) { |
| if (id == JSHTMLElement::MarqueeStart && element.renderer() && |
| element.renderer()->layer() && |
| element.renderer()->layer()->marquee()) { |
| element.renderer()->layer()->marquee()->start(); |
| return jsUndefined(); |
| } |
| if (id == JSHTMLElement::MarqueeStop && element.renderer() && |
| element.renderer()->layer() && |
| element.renderer()->layer()->marquee()) { |
| element.renderer()->layer()->marquee()->stop(); |
| return jsUndefined(); |
| } |
| } |
| |
| return jsUndefined(); |
| } |
| |
| void JSHTMLElement::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr) |
| { |
| HTMLElement &element = *static_cast<HTMLElement*>(impl()); |
| // First look at dynamic properties |
| if (element.hasLocalName(selectTag)) { |
| HTMLSelectElement &select = static_cast<HTMLSelectElement &>(element); |
| bool ok; |
| /*unsigned u =*/ propertyName.toUInt32(&ok); |
| if (ok) { |
| JSObject* coll = static_cast<JSObject*>(getSelectHTMLCollection(exec, select.options().get(), &select)); |
| coll->put(exec,propertyName,value); |
| return; |
| } |
| } |
| else if (element.hasLocalName(embedTag) || element.hasLocalName(objectTag) || element.hasLocalName(appletTag)) { |
| if (JSValue *runtimeObject = getRuntimeObject(exec, &element)) { |
| JSObject* imp = static_cast<JSObject*>(runtimeObject); |
| if (imp->canPut(exec, propertyName)) |
| return imp->put(exec, propertyName, value); |
| } |
| } |
| |
| const HashTable* table = classInfo()->propHashTable; // get the right hashtable |
| const HashEntry* entry = Lookup::findEntry(table, propertyName); |
| if (entry) { |
| if (entry->attr & Function) { // function: put as override property |
| JSObject::put(exec, propertyName, value, attr); |
| return; |
| } else if (!(entry->attr & ReadOnly)) { // let lookupPut print the warning if read-only |
| putValueProperty(exec, entry->value, value, attr); |
| return; |
| } |
| } |
| |
| lookupPut<JSHTMLElement, WebCore::JSHTMLElement>(exec, propertyName, value, attr, &HTMLElementTable, this); |
| } |
| |
| void JSHTMLElement::selectSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLSelectElement& select = *static_cast<HTMLSelectElement*>(impl()); |
| switch (token) { |
| // read-only: type |
| case SelectSelectedIndex: { select.setSelectedIndex(value->toInt32(exec)); return; } |
| case SelectValue: { select.setValue(str); return; } |
| case SelectLength: { // read-only according to the NS spec, but webpages need it writeable |
| JSObject* coll = static_cast<JSObject*>(getSelectHTMLCollection(exec, select.options().get(), &select)); |
| coll->put(exec,lengthPropertyName,value); |
| return; |
| } |
| // read-only: form |
| // read-only: options |
| case SelectDisabled: { select.setDisabled(value->toBoolean(exec)); return; } |
| case SelectMultiple: { select.setMultiple(value->toBoolean(exec)); return; } |
| case SelectName: { select.setName(AtomicString(str)); return; } |
| case SelectSize: { select.setSize(value->toInt32(exec)); return; } |
| case SelectTabIndex: { select.setTabIndex(value->toInt32(exec)); return; } |
| } |
| } |
| |
| void JSHTMLElement::objectSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLObjectElement& object = *static_cast<HTMLObjectElement*>(impl()); |
| switch (token) { |
| // read-only: form |
| case ObjectCode: { object.setCode(str); return; } |
| case ObjectAlign: { object.setAlign(str); return; } |
| case ObjectArchive: { object.setArchive(str); return; } |
| case ObjectBorder: { object.setBorder(str); return; } |
| case ObjectCodeBase: { object.setCodeBase(str); return; } |
| case ObjectCodeType: { object.setCodeType(str); return; } |
| // read-only: ObjectContentDocument |
| case ObjectData: { object.setData(str); return; } |
| case ObjectDeclare: { object.setDeclare(value->toBoolean(exec)); return; } |
| case ObjectHeight: { object.setHeight(str); return; } |
| case ObjectHspace: { object.setHspace(str); return; } |
| case ObjectName: { object.setName(str); return; } |
| case ObjectStandby: { object.setStandby(str); return; } |
| case ObjectTabIndex: { object.setTabIndex(value->toInt32(exec)); return; } |
| case ObjectType: { object.setType(str); return; } |
| case ObjectUseMap: { object.setUseMap(str); return; } |
| case ObjectVspace: { object.setVspace(str); return; } |
| case ObjectWidth: { object.setWidth(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::embedSetter(ExecState*, int token, JSValue*, const WebCore::String& str) |
| { |
| HTMLEmbedElement& embed = *static_cast<HTMLEmbedElement*>(impl()); |
| switch (token) { |
| case EmbedAlign: { embed.setAlign(str); return; } |
| case EmbedHeight: { embed.setHeight(str); return; } |
| case EmbedName: { embed.setName(str); return; } |
| case EmbedSrc: { embed.setSrc(str); return; } |
| case EmbedType: { embed.setType(str); return; } |
| case EmbedWidth: { embed.setWidth(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::tableSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLTableElement& table = *static_cast<HTMLTableElement*>(impl()); |
| switch (token) { |
| case TableCaption: { table.setCaption(toHTMLTableCaptionElement(value)); return; } |
| case TableTHead: { table.setTHead(toHTMLTableSectionElement(value)); return; } |
| case TableTFoot: { table.setTFoot(toHTMLTableSectionElement(value)); return; } |
| // read-only: rows |
| // read-only: tbodies |
| case TableAlign: { table.setAlign(str); return; } |
| case TableBgColor: { table.setBgColor(str); return; } |
| case TableBorder: { table.setBorder(str); return; } |
| case TableCellPadding: { table.setCellPadding(str); return; } |
| case TableCellSpacing: { table.setCellSpacing(str); return; } |
| case TableFrame: { table.setFrame(str); return; } |
| case TableRules: { table.setRules(str); return; } |
| case TableSummary: { table.setSummary(str); return; } |
| case TableWidth: { table.setWidth(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::tableCaptionSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLTableCaptionElement& tableCaption = *static_cast<HTMLTableCaptionElement*>(impl()); |
| if (token == TableCaptionAlign) |
| tableCaption.setAlign(str); |
| } |
| |
| void JSHTMLElement::tableColSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLTableColElement& tableCol = *static_cast<HTMLTableColElement*>(impl()); |
| switch (token) { |
| case TableColAlign: { tableCol.setAlign(str); return; } |
| case TableColCh: { tableCol.setCh(str); return; } |
| case TableColChOff: { tableCol.setChOff(str); return; } |
| case TableColSpan: { tableCol.setSpan(value->toInt32(exec)); return; } |
| case TableColVAlign: { tableCol.setVAlign(str); return; } |
| case TableColWidth: { tableCol.setWidth(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::tableSectionSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLTableSectionElement& tableSection = *static_cast<HTMLTableSectionElement*>(impl()); |
| switch (token) { |
| case TableSectionAlign: { tableSection.setAlign(str); return; } |
| case TableSectionCh: { tableSection.setCh(str); return; } |
| case TableSectionChOff: { tableSection.setChOff(str); return; } |
| case TableSectionVAlign: { tableSection.setVAlign(str); return; } |
| // read-only: rows |
| } |
| } |
| |
| void JSHTMLElement::tableRowSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLTableRowElement& tableRow = *static_cast<HTMLTableRowElement*>(impl()); |
| switch (token) { |
| // read-only: rowIndex |
| // read-only: sectionRowIndex |
| // read-only: cells |
| case TableRowAlign: { tableRow.setAlign(str); return; } |
| case TableRowBgColor: { tableRow.setBgColor(str); return; } |
| case TableRowCh: { tableRow.setCh(str); return; } |
| case TableRowChOff: { tableRow.setChOff(str); return; } |
| case TableRowVAlign: { tableRow.setVAlign(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::tableCellSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLTableCellElement& tableCell = *static_cast<HTMLTableCellElement*>(impl()); |
| switch (token) { |
| // read-only: cellIndex |
| case TableCellAbbr: { tableCell.setAbbr(str); return; } |
| case TableCellAlign: { tableCell.setAlign(str); return; } |
| case TableCellAxis: { tableCell.setAxis(str); return; } |
| case TableCellBgColor: { tableCell.setBgColor(str); return; } |
| case TableCellCh: { tableCell.setCh(str); return; } |
| case TableCellChOff: { tableCell.setChOff(str); return; } |
| case TableCellColSpan: { tableCell.setColSpan(value->toInt32(exec)); return; } |
| case TableCellHeaders: { tableCell.setHeaders(str); return; } |
| case TableCellHeight: { tableCell.setHeight(str); return; } |
| case TableCellNoWrap: { tableCell.setNoWrap(value->toBoolean(exec)); return; } |
| case TableCellRowSpan: { tableCell.setRowSpan(value->toInt32(exec)); return; } |
| case TableCellScope: { tableCell.setScope(str); return; } |
| case TableCellVAlign: { tableCell.setVAlign(str); return; } |
| case TableCellWidth: { tableCell.setWidth(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::frameSetSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLFrameSetElement& frameSet = *static_cast<HTMLFrameSetElement*>(impl()); |
| switch (token) { |
| case FrameSetCols: { frameSet.setCols(str); return; } |
| case FrameSetRows: { frameSet.setRows(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::frameSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLFrameElement& frameElement = *static_cast<HTMLFrameElement*>(impl()); |
| switch (token) { |
| // read-only: FrameContentDocument: |
| case FrameFrameBorder: { frameElement.setFrameBorder(str); return; } |
| case FrameLongDesc: { frameElement.setLongDesc(str); return; } |
| case FrameMarginHeight: { frameElement.setMarginHeight(str); return; } |
| case FrameMarginWidth: { frameElement.setMarginWidth(str); return; } |
| case FrameName: { frameElement.setName(str); return; } |
| case FrameNoResize: { frameElement.setNoResize(value->toBoolean(exec)); return; } |
| case FrameScrolling: { frameElement.setScrolling(str); return; } |
| case FrameSrc: { frameElement.setSrc(str); return; } |
| case FrameLocation: { frameElement.setLocation(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::iFrameSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| HTMLIFrameElement& iFrame = *static_cast<HTMLIFrameElement*>(impl()); |
| switch (token) { |
| case IFrameAlign: { iFrame.setAlign(str); return; } |
| // read-only: IFrameContentDocument |
| case IFrameFrameBorder: { iFrame.setFrameBorder(str); return; } |
| case IFrameHeight: { iFrame.setHeight(str); return; } |
| case IFrameLongDesc: { iFrame.setLongDesc(str); return; } |
| case IFrameMarginHeight: { iFrame.setMarginHeight(str); return; } |
| case IFrameMarginWidth: { iFrame.setMarginWidth(str); return; } |
| case IFrameName: { iFrame.setName(str); return; } |
| case IFrameScrolling: { iFrame.setScrolling(str); return; } |
| case IFrameSrc: { iFrame.setSrc(str); return; } |
| case IFrameWidth: { iFrame.setWidth(str); return; } |
| } |
| } |
| |
| void JSHTMLElement::marqueeSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str) |
| { |
| // FIXME: Find out what WinIE supports and implement it. |
| } |
| |
| void JSHTMLElement::putValueProperty(ExecState* exec, int token, JSValue *value, int) |
| { |
| DOMExceptionTranslator exception(exec); |
| WebCore::String str = value->toString(exec); |
| |
| // Check our set of generic properties first. |
| HTMLElement &element = *static_cast<HTMLElement*>(impl()); |
| switch (token) { |
| case ElementId: |
| element.setId(str); |
| return; |
| case ElementLang: |
| element.setLang(str); |
| return; |
| case ElementDir: |
| element.setDir(str); |
| return; |
| case ElementClassName: |
| element.setClassName(str); |
| return; |
| case ElementInnerHTML: |
| element.setInnerHTML(str, exception); |
| return; |
| case ElementInnerText: |
| element.setInnerText(str, exception); |
| return; |
| case ElementOuterHTML: |
| element.setOuterHTML(str, exception); |
| return; |
| case ElementOuterText: |
| element.setOuterText(str, exception); |
| return; |
| case ElementContentEditable: |
| element.setContentEditable(str); |
| return; |
| } |
| |
| // Now check for properties that apply to a specific element type. |
| const Accessors* access = accessors(); |
| if (access && access->m_setter) |
| return (this->*(access->m_setter))(exec, token, value, str); |
| } |
| |
| HTMLElement* toHTMLElement(JSValue *val) |
| { |
| if (!val || !val->isObject(&JSHTMLElement::info)) |
| return 0; |
| return static_cast<HTMLElement*>(static_cast<JSHTMLElement*>(val)->impl()); |
| } |
| |
| HTMLTableCaptionElement* toHTMLTableCaptionElement(JSValue *val) |
| { |
| HTMLElement* e = toHTMLElement(val); |
| if (e && e->hasTagName(captionTag)) |
| return static_cast<HTMLTableCaptionElement*>(e); |
| return 0; |
| } |
| |
| HTMLTableSectionElement* toHTMLTableSectionElement(JSValue *val) |
| { |
| HTMLElement* e = toHTMLElement(val); |
| if (e && (e->hasTagName(theadTag) || e->hasTagName(tbodyTag) || e->hasTagName(tfootTag))) |
| return static_cast<HTMLTableSectionElement*>(e); |
| return 0; |
| } |
| |
| // ------------------------------------------------------------------------- |
| /* Source for HTMLCollectionProtoTable. Use "make hashtables" to regenerate. |
| @begin HTMLCollectionProtoTable 3 |
| item JSHTMLCollection::Item DontDelete|Function 1 |
| namedItem JSHTMLCollection::NamedItem DontDelete|Function 1 |
| tags JSHTMLCollection::Tags DontDelete|Function 1 |
| @end |
| */ |
| KJS_DEFINE_PROTOTYPE(HTMLCollectionProto) |
| KJS_IMPLEMENT_PROTOFUNC(HTMLCollectionProtoFunc) |
| KJS_IMPLEMENT_PROTOTYPE("HTMLCollection",HTMLCollectionProto,HTMLCollectionProtoFunc) |
| |
| const ClassInfo JSHTMLCollection::info = { "Collection", 0, 0, 0 }; |
| |
| JSHTMLCollection::JSHTMLCollection(ExecState* exec, HTMLCollection *c) |
| : m_impl(c) |
| { |
| setPrototype(HTMLCollectionProto::self(exec)); |
| } |
| |
| JSHTMLCollection::~JSHTMLCollection() |
| { |
| ScriptInterpreter::forgetDOMObject(m_impl.get()); |
| } |
| |
| JSValue *JSHTMLCollection::lengthGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase()); |
| return jsNumber(thisObj->m_impl->length()); |
| } |
| |
| JSValue *JSHTMLCollection::indexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase()); |
| return toJS(exec, thisObj->m_impl->item(slot.index())); |
| } |
| |
| JSValue *JSHTMLCollection::nameGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase()); |
| return thisObj->getNamedItems(exec, propertyName); |
| } |
| |
| bool JSHTMLCollection::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) |
| { |
| if (propertyName == lengthPropertyName) { |
| slot.setCustom(this, lengthGetter); |
| return true; |
| } else { |
| // Look in the prototype (for functions) before assuming it's an item's name |
| JSValue *proto = prototype(); |
| if (proto->isObject() && static_cast<JSObject*>(proto)->hasProperty(exec, propertyName)) |
| return false; |
| |
| // name or index ? |
| bool ok; |
| unsigned int u = propertyName.toUInt32(&ok); |
| if (ok) { |
| slot.setCustomIndex(this, u, indexGetter); |
| return true; |
| } |
| |
| if (!getNamedItems(exec, propertyName)->isUndefined()) { |
| slot.setCustom(this, nameGetter); |
| return true; |
| } |
| } |
| |
| return DOMObject::getOwnPropertySlot(exec, propertyName, slot); |
| } |
| |
| // HTMLCollections are strange objects, they support both get and call, |
| // so that document.forms.item(0) and document.forms(0) both work. |
| JSValue *JSHTMLCollection::callAsFunction(ExecState* exec, JSObject* , const List &args) |
| { |
| // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case. |
| HTMLCollection &collection = *m_impl; |
| |
| // Also, do we need the TypeError test here ? |
| |
| if (args.size() == 1) { |
| // support for document.all(<index>) etc. |
| bool ok; |
| UString s = args[0]->toString(exec); |
| unsigned int u = s.toUInt32(&ok); |
| if (ok) |
| return toJS(exec, collection.item(u)); |
| // support for document.images('<name>') etc. |
| return getNamedItems(exec, Identifier(s)); |
| } |
| else if (args.size() >= 1) // the second arg, if set, is the index of the item we want |
| { |
| bool ok; |
| UString s = args[0]->toString(exec); |
| unsigned int u = args[1]->toString(exec).toUInt32(&ok); |
| if (ok) |
| { |
| WebCore::String pstr = s; |
| WebCore::Node *node = collection.namedItem(pstr); |
| while (node) { |
| if (!u) |
| return toJS(exec,node); |
| node = collection.nextNamedItem(pstr); |
| --u; |
| } |
| } |
| } |
| return jsUndefined(); |
| } |
| |
| JSValue *JSHTMLCollection::getNamedItems(ExecState* exec, const Identifier &propertyName) const |
| { |
| DeprecatedValueList< RefPtr<WebCore::Node> > namedItems = m_impl->namedItems(propertyName); |
| |
| if (namedItems.isEmpty()) |
| return jsUndefined(); |
| |
| if (namedItems.count() == 1) |
| return toJS(exec, namedItems[0].get()); |
| |
| return new DOMNamedNodesCollection(exec, namedItems); |
| } |
| |
| JSValue *HTMLCollectionProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args) |
| { |
| if (!thisObj->inherits(&JSHTMLCollection::info)) |
| return throwError(exec, TypeError); |
| HTMLCollection &coll = *static_cast<JSHTMLCollection*>(thisObj)->impl(); |
| |
| switch (id) { |
| case JSHTMLCollection::Item: |
| return toJS(exec,coll.item(args[0]->toUInt32(exec))); |
| case JSHTMLCollection::Tags: |
| return toJS(exec, coll.base()->getElementsByTagName(args[0]->toString(exec)).get()); |
| case JSHTMLCollection::NamedItem: |
| return static_cast<JSHTMLCollection*>(thisObj)->getNamedItems(exec, Identifier(args[0]->toString(exec))); |
| default: |
| return jsUndefined(); |
| } |
| } |
| |
| // ------------------------------------------------------------------------- |
| |
| JSHTMLSelectCollection::JSHTMLSelectCollection(ExecState* exec, HTMLCollection *c, HTMLSelectElement* e) |
| : JSHTMLCollection(exec, c), m_element(e) |
| { |
| } |
| |
| JSValue *JSHTMLSelectCollection::selectedIndexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot) |
| { |
| JSHTMLSelectCollection *thisObj = static_cast<JSHTMLSelectCollection*>(slot.slotBase()); |
| return jsNumber(thisObj->m_element->selectedIndex()); |
| } |
| |
| bool JSHTMLSelectCollection::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) |
| { |
| if (propertyName == "selectedIndex") { |
| slot.setCustom(this, selectedIndexGetter); |
| //result = jsNumber(m_element->selectedIndex()); |
| return true; |
| } |
| |
| return JSHTMLCollection::getOwnPropertySlot(exec, propertyName, slot); |
| } |
| |
| void JSHTMLSelectCollection::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int) |
| { |
| #ifdef KJS_VERBOSE |
| kdDebug(6070) << "JSHTMLSelectCollection::put " << propertyName.deprecatedString() << endl; |
| #endif |
| if ( propertyName == "selectedIndex" ) |
| m_element->setSelectedIndex(value->toInt32(exec)); |
| else if (propertyName == lengthPropertyName) { |
| // resize ? |
| if (value->isNumber()) { |
| double newLen; |
| if (value->getNumber(newLen)) { |
| int exception = 0; |
| if (newLen >= 0) { |
| m_element->setLength(unsigned(floor(newLen)), exception); |
| setDOMException(exec, exception); |
| } |
| } |
| } else { |
| int exception = 0; |
| m_element->setLength(0, exception); |
| setDOMException(exec, exception); |
| } |
| } else { |
| // an index ? |
| bool ok; |
| unsigned i = propertyName.toUInt32(&ok); |
| if (ok) { |
| if (value->isUndefinedOrNull()) { |
| // null and undefined delete. others, too ? |
| m_element->remove(i); |
| } else { |
| WebCore::Node *option = toNode(value); |
| // is v an option element ? |
| if (!option || !option->hasTagName(optionTag)) |
| return; |
| |
| int exception = 0; |
| m_element->setOption(i, static_cast<HTMLOptionElement*>(option), exception); |
| setDOMException(exec, exception); |
| } |
| } |
| } |
| } |
| |
| ////////////////////// Image Object //////////////////////// |
| |
| ImageConstructorImp::ImageConstructorImp(ExecState* exec, Document* d) |
| : m_doc(d) |
| { |
| setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype()); |
| } |
| |
| bool ImageConstructorImp::implementsConstruct() const |
| { |
| return true; |
| } |
| |
| JSObject* ImageConstructorImp::construct(ExecState* exec, const List & list) |
| { |
| bool widthSet = false, heightSet = false; |
| int width = 0, height = 0; |
| if (list.size() > 0) { |
| widthSet = true; |
| JSValue *w = list.at(0); |
| width = w->toInt32(exec); |
| } |
| if (list.size() > 1) { |
| heightSet = true; |
| JSValue *h = list.at(1); |
| height = h->toInt32(exec); |
| } |
| |
| HTMLImageElement* result = new HTMLImageElement(m_doc.get()); |
| |
| if (widthSet) |
| result->setWidth(width); |
| if (heightSet) |
| result->setHeight(height); |
| |
| return static_cast<JSObject*>(toJS(exec, result)); |
| } |
| |
| //////////////////////////////////////////////////////////////// |
| |
| JSValue* getAllHTMLCollection(ExecState* exec, HTMLCollection* c) |
| { |
| return cacheDOMObject<HTMLCollection, HTMLAllCollection>(exec, c); |
| } |
| |
| JSValue* getHTMLCollection(ExecState* exec, HTMLCollection* c) |
| { |
| return cacheDOMObject<HTMLCollection, JSHTMLCollection>(exec, c); |
| } |
| |
| JSValue *getSelectHTMLCollection(ExecState* exec, HTMLCollection *c, HTMLSelectElement* e) |
| { |
| DOMObject *ret; |
| if (!c) |
| return jsNull(); |
| ScriptInterpreter* interp = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter()); |
| if ((ret = interp->getDOMObject(c))) |
| return ret; |
| else { |
| ret = new JSHTMLSelectCollection(exec, c, e); |
| interp->putDOMObject(c,ret); |
| return ret; |
| } |
| } |
| |
| } // namespace |