📄 kjs_dom.cpp
字号:
// -*- c-basic-offset: 2 -*-/* * This file is part of the KDE libraries * Copyright (C) 2000 Harri Porten (porten@kde.org) * * 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 <stdio.h>#include <qptrdict.h>#include <kjs/operations.h>#include <khtmlview.h>#include <dom_string.h>#include <dom_xml.h>#include <xml/dom_nodeimpl.h>#include <xml/dom2_eventsimpl.h>#include <rendering/render_object.h>#include <htmltags.h>#include "kjs_text.h"#include "kjs_dom.h"#include "kjs_html.h"#include "kjs_css.h"#include "kjs_range.h"#include "kjs_traversal.h"#include "kjs_events.h"#include "kjs_views.h"#include "kjs_window.h"#include "dom/dom_exception.h"using namespace KJS;QPtrDict<DOMNode> nodes(1021);QPtrDict<DOMNamedNodeMap> namedNodeMaps;QPtrDict<DOMNodeList> nodeLists;QPtrDict<DOMDOMImplementation> domImplementations;// -------------------------------------------------------------------------const TypeInfo DOMNode::info = { "Node", HostType, 0, 0, 0 };DOMNode::~DOMNode(){ nodes.remove(node.handle());}Boolean DOMNode::toBoolean() const{ return Boolean(!node.isNull());}bool DOMNode::hasProperty(const UString &p, bool recursive) const{ if (p == "nodeName" || p == "nodeValue" || p == "nodeType" || p == "parentNode" || p == "childNodes" || p == "firstChild" || p == "lastChild" || p == "previousSibling" || p == "nextSibling" || p == "attributes" || /* new for DOM2 - not yet in khtml p == "namespaceURI" || p == "prefix" || p == "localName" || */ p == "ownerDocument" || p == "insertBefore" || p == "replaceChild" || p == "removeChild" || p == "appendChild" || p == "hasChildNodes" || p == "cloneNode" || /* moved here from Element in DOM2 p == "normalize" || p == "supports" */ // no DOM standard, found in IE only p == "offsetLeft" || p == "offsetTop" || p == "offsetWidth" || p == "offsetHeight" || p == "offsetParent" || p == "scrollLeft" || p == "scrollTop" || p == "addEventListener" || p == "removeEventListener" || p == "dispatchEvent") return true; return recursive && HostImp::hasProperty(p, true);}KJSO DOMNode::tryGet(const UString &p) const{ KJSO result; khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L; if (p == "nodeName") result = getString(node.nodeName()); else if (p == "nodeValue") result = getString(node.nodeValue()); else if (p == "nodeType") result = Number((unsigned int)node.nodeType()); else if (p == "parentNode") result = getDOMNode(node.parentNode()); else if (p == "childNodes") result = getDOMNodeList(node.childNodes()); else if (p == "firstChild") result = getDOMNode(node.firstChild()); else if (p == "lastChild") result = getDOMNode(node.lastChild()); else if (p == "previousSibling") result = getDOMNode(node.previousSibling()); else if (p == "nextSibling") result = getDOMNode(node.nextSibling()); else if (p == "attributes") result = getDOMNamedNodeMap(node.attributes());// else if (p == "namespaceURI") // new for DOM2 - not yet in khtml// result = getString(node.namespaceURI());// else if (p == "prefix") // new for DOM2 - not yet in khtml// result = getString(node.prefix());// else if (p == "localName") // new for DOM2 - not yet in khtml// result = getString(node.localName()); else if (p == "ownerDocument") result = getDOMNode(node.ownerDocument()); // methods else if (p == "insertBefore") result = new DOMNodeFunc(node, DOMNodeFunc::InsertBefore); else if (p == "replaceChild") result = new DOMNodeFunc(node, DOMNodeFunc::ReplaceChild); else if (p == "removeChild") result = new DOMNodeFunc(node, DOMNodeFunc::RemoveChild); else if (p == "appendChild") result = new DOMNodeFunc(node, DOMNodeFunc::AppendChild); else if (p == "hasChildNodes") result = new DOMNodeFunc(node, DOMNodeFunc::HasChildNodes); else if (p == "cloneNode") result = new DOMNodeFunc(node, DOMNodeFunc::CloneNode);// else if (p == "normalize") // moved here from Element in DOM2// result = new DOMNodeFunc(node, DOMNodeFunc::Normalize);// else if (p == "supports") // new for DOM2 - not yet in khtml// result = new DOMNodeFunc(node, DOMNodeFunc::Supports); else if (p == "addEventListener") // from the EventTarget interface result = new DOMNodeFunc(node, DOMNodeFunc::AddEventListener); else if (p == "removeEventListener") // from the EventTarget interface result = new DOMNodeFunc(node, DOMNodeFunc::RemoveEventListener); else if (p == "dispatchEvent") // from the EventTarget interface result = new DOMNodeFunc(node, DOMNodeFunc::DispatchEvent); else if (p == "onabort") result = getListener(DOM::EventImpl::ABORT_EVENT); else if (p == "onblur") result = getListener(DOM::EventImpl::BLUR_EVENT); else if (p == "onchange") result = getListener(DOM::EventImpl::CHANGE_EVENT); else if (p == "onclick") result = getListener(DOM::EventImpl::KHTML_CLICK_EVENT); else if (p == "ondblclick") result = getListener(DOM::EventImpl::KHTML_DBLCLICK_EVENT); else if (p == "ondragdrop") result = getListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT); else if (p == "onerror") result = getListener(DOM::EventImpl::KHTML_ERROR_EVENT); else if (p == "onfocus") result = getListener(DOM::EventImpl::FOCUS_EVENT); else if (p == "onkeydown") result = getListener(DOM::EventImpl::KHTML_KEYDOWN_EVENT); else if (p == "onkeypress") result = getListener(DOM::EventImpl::KHTML_KEYPRESS_EVENT); else if (p == "onkeyup") result = getListener(DOM::EventImpl::KHTML_KEYUP_EVENT); else if (p == "onload") result = getListener(DOM::EventImpl::LOAD_EVENT); else if (p == "onmousedown") result = getListener(DOM::EventImpl::MOUSEDOWN_EVENT); else if (p == "onmousemove") result = getListener(DOM::EventImpl::MOUSEMOVE_EVENT); else if (p == "onmouseout") result = getListener(DOM::EventImpl::MOUSEOUT_EVENT); else if (p == "onmouseover") result = getListener(DOM::EventImpl::MOUSEOVER_EVENT); else if (p == "onmouseup") result = getListener(DOM::EventImpl::MOUSEUP_EVENT); else if (p == "onmove") result = getListener(DOM::EventImpl::KHTML_MOVE_EVENT); else if (p == "onreset") result = getListener(DOM::EventImpl::RESET_EVENT); else if (p == "onresize") result = getListener(DOM::EventImpl::RESIZE_EVENT); else if (p == "onselect") result = getListener(DOM::EventImpl::SELECT_EVENT); else if (p == "onsubmit") result = getListener(DOM::EventImpl::SUBMIT_EVENT); else if (p == "onunload") result = getListener(DOM::EventImpl::UNLOAD_EVENT); else { // no DOM standard, found in IE only // make sure our rendering is up to date before // we allow a query on these attributes. // ### how often does it fall into the final else case ? if ( node.handle() && node.handle()->ownerDocument() ) node.handle()->ownerDocument()->updateRendering(); if (p == "offsetLeft") result = rend ? static_cast<KJSO>(Number(rend->xPos())) : KJSO(Undefined()); else if (p == "offsetTop") result = rend ? static_cast<KJSO>(Number(rend->yPos())) : KJSO(Undefined()); else if (p == "offsetWidth") result = rend ? static_cast<KJSO>(Number(rend->width()) ) : KJSO(Undefined()); else if (p == "offsetHeight") result = rend ? static_cast<KJSO>(Number(rend->height() ) ) : KJSO(Undefined()); else if (p == "offsetParent") result = getDOMNode(node.parentNode()); // not necessarily correct else if (p == "clientWidth") result = rend ? static_cast<KJSO>(Number(rend->contentWidth())) : KJSO(Undefined()); else if (p == "clientHeight") result = rend ? static_cast<KJSO>(Number(rend->contentHeight())) : KJSO(Undefined()); else if (p == "scrollLeft") result = rend ? static_cast<KJSO>(Number(-rend->xPos() + node.ownerDocument().view()->contentsX())) : KJSO(Undefined()); else if (p == "scrollTop") result = rend ? static_cast<KJSO>(Number(-rend->yPos() + node.ownerDocument().view()->contentsY())) : KJSO(Undefined()); else result = Imp::get(p); } return result;}void DOMNode::tryPut(const UString &p, const KJSO& v){ if (p == "nodeValue") { node.setNodeValue(v.toString().value().string()); }// else if (p == "prefix") { // new for DOM2 - not yet in khtml// node.setPrefix(v.toString().value().string());// } else if (p == "onabort") setListener(DOM::EventImpl::ABORT_EVENT,v); else if (p == "onblur") setListener(DOM::EventImpl::BLUR_EVENT,v); else if (p == "onchange") setListener(DOM::EventImpl::CHANGE_EVENT,v); else if (p == "onclick") setListener(DOM::EventImpl::KHTML_CLICK_EVENT,v); else if (p == "ondblclick") setListener(DOM::EventImpl::KHTML_DBLCLICK_EVENT,v); else if (p == "ondragdrop") setListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT,v); else if (p == "onerror") setListener(DOM::EventImpl::KHTML_ERROR_EVENT,v); else if (p == "onfocus") setListener(DOM::EventImpl::FOCUS_EVENT,v); else if (p == "onkeydown") setListener(DOM::EventImpl::KHTML_KEYDOWN_EVENT,v); else if (p == "onkeypress") setListener(DOM::EventImpl::KHTML_KEYPRESS_EVENT,v); else if (p == "onkeyup") setListener(DOM::EventImpl::KHTML_KEYUP_EVENT,v); else if (p == "onload") setListener(DOM::EventImpl::LOAD_EVENT,v); else if (p == "onmousedown") setListener(DOM::EventImpl::MOUSEDOWN_EVENT,v); else if (p == "onmousemove") setListener(DOM::EventImpl::MOUSEMOVE_EVENT,v); else if (p == "onmouseout") setListener(DOM::EventImpl::MOUSEOUT_EVENT,v); else if (p == "onmouseover") setListener(DOM::EventImpl::MOUSEOVER_EVENT,v); else if (p == "onmouseup") setListener(DOM::EventImpl::MOUSEUP_EVENT,v); else if (p == "onmove") setListener(DOM::EventImpl::KHTML_MOVE_EVENT,v); else if (p == "onreset") setListener(DOM::EventImpl::RESET_EVENT,v); else if (p == "onresize") setListener(DOM::EventImpl::RESIZE_EVENT,v); else if (p == "onselect") setListener(DOM::EventImpl::SELECT_EVENT,v); else if (p == "onsubmit") setListener(DOM::EventImpl::SUBMIT_EVENT,v); else if (p == "onunload") setListener(DOM::EventImpl::UNLOAD_EVENT,v); else Imp::put(p, v);}KJSO DOMNode::toPrimitive(Type /*preferred*/) const{ if (node.isNull()) return Null(); return toString();}String DOMNode::toString() const{ if (node.isNull()) return String("null"); DOM::DOMString s = "DOMNode"; // fallback DOM::Element e = node; if ( !e.isNull() ) { s = e.nodeName(); } return String("[object " + UString(s) + "]");}void DOMNode::setListener(int eventId,KJSO func) const{ node.handle()->setHTMLEventListener(eventId,Window::retrieveActive()->getJSEventListener(func,true));}KJSO DOMNode::getListener(int eventId) const{ DOM::EventListener *listener = node.handle()->getHTMLEventListener(eventId); if (listener) return static_cast<JSEventListener*>(listener)->listenerObj(); else return Null();}List *DOMNode::eventHandlerScope() const{ return 0;}Completion DOMNodeFunc::tryExecute(const List &args){ KJSO result; switch (id) { case HasChildNodes: result = Boolean(node.hasChildNodes()); break; case CloneNode: result = getDOMNode(node.cloneNode(args[0].toBoolean().value())); break; case AddEventListener: {// JSEventListener *listener = new JSEventListener(args[1]); // will get deleted when the node derefs it JSEventListener *listener = Window::retrieveActive()->getJSEventListener(args[1]); node.addEventListener(args[0].toString().value().string(),listener,args[2].toBoolean().value()); result = Undefined(); } break; case RemoveEventListener: { JSEventListener *listener = Window::retrieveActive()->getJSEventListener(args[1]); node.removeEventListener(args[0].toString().value().string(),listener,args[2].toBoolean().value()); result = Undefined(); } break; case DispatchEvent: result = Boolean(node.dispatchEvent(toEvent(args[0]))); break; case AppendChild: result = getDOMNode(node.appendChild(toNode(args[0]))); break; case RemoveChild: result = getDOMNode(node.removeChild(toNode(args[0]))); break; case InsertBefore: result = getDOMNode(node.insertBefore(toNode(args[0]), toNode(args[1]))); break; case ReplaceChild: result = getDOMNode(node.replaceChild(toNode(args[0]), toNode(args[1]))); break; } return Completion(ReturnValue, result);}// -------------------------------------------------------------------------const TypeInfo DOMNodeList::info = { "NodeList", HostType, 0, 0, 0 };DOMNodeList::~DOMNodeList(){ nodeLists.remove(list.handle());}KJSO DOMNodeList::tryGet(const UString &p) const{ KJSO result;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -