WebKit DOM Event (一)
DOM Event 規范
DOM Event 主要定義了三類接口:
EventTarget, 所有DOM節點和XMLHttpRequest?都實現EventTarget接口
? ? class EventTarget? {
? ? ? ? void addEventListener(in DOMString type,inEventListener listener, in boolean useCapture);
? ? ? ? void removeEventListener(in DOMString type,in EventListener listener, in boolean useCapture);
? ? ? ? boolean dispatchEvent(in Event event)
? ? };這個類是一個純虛基類,因此是一個接口類
1.添加和刪除Listener,這些是虛函數,子類中可以重新實現
2.分發Event,有一個虛函數,和一個函數,這樣子類可以有自己的個性
3.添加,刪除和獲取屬性Listener
4.fire觸發Listener函數,這個函數不需要有子類的實現
EventListener, 用戶實現該接口,并且在一個EventTarget上注冊,使用addEventListener 完成注冊;
void?handleEvent(in Event evt);
EventListener::Type {
? ? ? ? ? ? JSEventListenerType,?
? ? ? ? ? ? ImageEventListenerType,?
? ? ? ? ? ? InspectorDOMAgentType,
? ? ? ? ? ? InspectorDOMStorageResourceType,
? ? ? ? ? ? ObjCEventListenerType,
? ? ? ? ? ? CPPEventListenerType,
? ? ? ? ? ? ConditionEventListenerType,
? ? ? ? ? ? GObjectEventListenerType,
? ? ? ? ? ? NativeEventListenerType
? ? ? ? };
Event 給EventHandle提供上下文信息
readonly attribute DOMString??????? type;
readonly attribute EventTarget????? target;
readonly attribute EventTarget????? currentTarget;
readonly attribute unsigned short?? eventPhase;
readonly attribute boolean????????? bubbles;
readonly attribute boolean????????? cancelable;
readonly attribute DOMTimeStamp???? timeStamp;
?
void?????????????? stopPropagation();
void?????????????? preventDefault();
[OldStyleObjC] void initEvent(in DOMStringeventTypeArg,
in boolean canBubbleArg,
in boolean cancelableArg);
?
// DOM Level 3 Additions.
readonly attribute boolean defaultPrevented;
void stopImmediatePropagation();
?
// IE Extensions
readonly attribute EventTarget????? srcElement;
attribute boolean????????? returnValue;
attribute boolean????????? cancelBubble;
?
#if defined(LANGUAGE_JAVASCRIPT) &&LANGUAGE_JAVASCRIPT
readonly attribute [Custom] Clipboard??????? clipboardData;
#endif
事件流
- 基本事件流
每個事件都對應一個事件目標(EventTarget)(也是一個node 節點),EventTarget 有event 的target 屬性指定。 每個事件目標注冊有若干事件監聽者(EventListerner), 這些監聽者在事件到達后激活,激活的順序在DOM規范中沒有定義。如果沒有定義事件capture或者bubbling,則當事件目標上的所有事件監聽者響應完畢后,則這個事件處理完畢。
- 事件捕獲
事件捕獲發生在如下情況下: 一個事件監聽者注冊在某個事件的目標節點的祖先節點上,當該事件發生后,在其到達目標節點之前,祖先節點的事件監聽者首先捕獲并處理,然后將事件逐級下傳,直到目標節點。
- 事件冒泡
事件冒泡初始階段同基本事件流相同,然而在事件的目標節點所有事件監聽者響應完畢后,是將將會沿著節點向其祖先方向上傳,直到document點,上傳過程中將會逐級激發在遇到節點上注冊的的所有事件監聽者(捕獲事件除外)。
- 事件取消
一些事件可以規定為可取消的,這些事件一般都會應有一個缺省的動作。當此類事件發生時,首先傳遞給目標節點上的事件監聽者,事件監聽者可以選擇是否取消該事件的缺省動作。
下面兩圖為事件流圖:
WebKit DOM Event 類圖
WebKit 實現邏輯
實現邏輯(以鼠標事件為例):
- 鼠標事件發生
- 根據鼠標事件發生的位置, 找到對應的EventTarget 節點
- 在EventTarget的 dispatchGenericEvent函數中,獲取到所有的父節點,保存到list中;
- 進入事件捕獲階段
- 觸發當前EventTarget的當前事件的EventListen
- 進入事件冒泡階段
bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event>e, ExceptionCode&, bool tempEvent)
{
??? RefPtr<Event>evt(e);
???ASSERT(!eventDispatchForbidden());
???ASSERT(evt->target());
???ASSERT(!evt->type().isNull()); // JavaScript code could create anevent with an empty name
??? //work out what nodes to send event to
???DeprecatedPtrList<Node> nodeChain;
?
??? if(inDocument()) {
???????for (Node* n = this; n; n = n->eventParentNode()) {
???????????n->ref();
???????????nodeChain.prepend(n);
???????}
??? }else {
???????// if node is not in the document just send event to itself
???????ref();
???????nodeChain.prepend(this);
??? }
?
???DeprecatedPtrListIterator<Node> it(nodeChain);
???? //Before we begin dispatching events, give the target node a chance to do somework prior
??? //to the DOM event handlers getting a crack.
??? void*data = preDispatchEventHandler(evt.get());
??? //trigger any capturing event handlers on our way down
???evt->setEventPhase(Event::CAPTURING_PHASE);
???it.toFirst();
??? //Handle window events for capture phase, except load events, this quirk isneeded
??? //because Mozilla used to never propagate load events to the window object
??? if(evt->type() != loadEvent && it.current()->isDocumentNode() &&!evt->propagationStopped())
???????static_cast<Document*>(it.current())->handleWindowEvent(evt.get(),true);
??? for(; it.current() && it.current() != this && !evt->propagationStopped();++it) {
???????evt->setCurrentTarget(EventTargetNodeCast(it.current()));
??????EventTargetNodeCast(it.current())->handleLocalEvents(evt.get(), true);
??? }??
?
??? //dispatch to the actual target node
???it.toLast();
??? if(!evt->propagationStopped()) {
???????evt->setEventPhase(Event::AT_TARGET);
???????evt->setCurrentTarget(EventTargetNodeCast(it.current()));
???????// We do want capturing event listeners to be invoked here, even though
???????// that violates the specification since Mozilla does it.
???????EventTargetNodeCast(it.current())->handleLocalEvents(evt.get(), true);
???????EventTargetNodeCast(it.current())->handleLocalEvents(evt.get(), false);
??? }
??? --it;
?? //ok, now bubble up again (only non-capturing event handlers will be called)
??? //### recalculate the node chain here? (e.g. if target node moved in document byprevious event handlers)
??? //no. the DOM specs says:
??? //The chain of EventTargets from the event target to the top of the tree
??? //is determined before the initial dispatch of the event.
??? //If modifications occur to the tree during event processing,
??? //event flow will proceed based on the initial state of the tree.
??? //
??? //since the initial dispatch is before the capturing phase,
??? //there's no need to recalculate the node chain.
??? //(tobias)
??? if(evt->bubbles()) {
???????evt->setEventPhase(Event::BUBBLING_PHASE);
???????for (; it.current() && !evt->propagationStopped() && !evt->cancelBubble();--it) {
???????????evt->setCurrentTarget(EventTargetNodeCast(it.current()));
???????????EventTargetNodeCast(it.current())->handleLocalEvents(evt.get(), false);
???????}
???????// Handle window events for bubbling phase, except load events, thisquirk is needed
???????// because Mozilla used to never propagate load events at all
???????it.toFirst();
???????if (evt->type() != loadEvent && it.current()->isDocumentNode()&& !evt->propagationStopped() && !evt->cancelBubble()) {
???????????evt->setCurrentTarget(EventTargetNodeCast(it.current()));
???????????static_cast<Document*>(it.current())->handleWindowEvent(evt.get(),false);
???????}
??? }
???evt->setCurrentTarget(0);
???evt->setEventPhase(0); // I guess this is correct, the spec does notseem to say
?????????????????????????? // anything aboutthe default event handler phase.
??? //Now call the post dispatch.
???postDispatchEventHandler(evt.get(), data);
? //now we call all default event handlers (this is not part of DOM - it isinternal to khtml)
???it.toLast();
??? if(evt->bubbles())
???????for (; it.current() && !evt->defaultPrevented() && !evt->defaultHandled();--it)
???????????EventTargetNodeCast(it.current())->defaultEventHandler(evt.get());
??? elseif (!evt->defaultPrevented() && !evt->defaultHandled())
???????EventTargetNodeCast(it.current())->defaultEventHandler(evt.get());
??? //deref all nodes in chain
???it.toFirst();
??? for(; it.current(); ++it)
???????it.current()->deref(); // this may delete us
???Document::updateDocumentsRendering();
??? //If tempEvent is true, this means that the DOM implementation
??? //will not be storing a reference to the event, i.e.? there is no
??? //way to retrieve it from javascript if a script does not already
??? //have a reference to it in a variable.? Sothere is no need for
??? //the interpreter to keep the event in it's cache
???Frame *frame = document()->frame();
??? if(tempEvent && frame && frame->scriptProxy())
???????frame->scriptProxy()->finishedWithEvent(evt.get());
??? return!evt->defaultPrevented(); // ### what if defaultPrevented was called beforedispatchEvent?
}Event::Type {
? ???abort ??
??? ?beforecopy ??
??? ?beforecut ??
??? ?beforeload ??
??? ?beforepaste ??
??? ?beforeprocess ??
??? ?beforeunload ??
??? ?blocked ??
??? ?blur ??
??? ?cached ??
??? ?change ??
??? ?checking ??
??? ?click ??
??? ?close ??
??? ?complete ??
??? ?compositionend ??
??? ?compositionstart ??
??? ?compositionupdate ??
??? ?connect ??
??? ?contextmenu ??
??? ?copy ??
??? ?cut ??
??? ?dblclick ??
??? ?devicemotion ??
??? ?deviceorientation ??
??? ?display ??
??? ?downloading ??
??? ?drag ??
??? ?dragend ??
??? ?dragenter ??
??? ?dragleave ??
??? ?dragover ??
??? ?dragstart ??
??? ?drop ??
??? ?error ??
??? ?focus ??
??? ?focusin ??
??? ?focusout ??
??? ?hashchange ??
??? ?input ??
??? ?invalid ??
??? ?keydown ??
??? ?keypress ??
??? ?keyup ??
??? ?load ??
??? ?loadstart ??
??? ?message ??
??? ?mousedown ??
??? ?mousemove ??
??? ?mouseout ??
??? ?mouseover ??
??? ?mouseup ??
??? ?mousewheel ??
??? ?noupdate ??
??? ?obsolete ??
??? ?offline ??
??? ?online ??
??? ?open ??
??? ?overflowchanged ??
??? ?pagehide ??
??? ?pageshow ??
??? ?paste ??
??? ?popstate ??
??? ?readystatechange ??
??? ?reset ??
??? ?resize ??
??? ?scroll ??
??? ?search ??
??? ?select ??
??? ?selectstart ??
??? ?selectionchange ??
??? ?storage ??
??? ?submit ??
??? ?textInput ??
??? ?unload ??
??? ?updateready ??
??? ?versionchange ??
??? ?write ??
??? ?writeend ??
??? ?writestart ??
??? ?zoom ??
??? ?
??? ?DOMActivate ??
??? ?DOMFocusIn ??
??? ?DOMFocusOut ??
??? ?DOMAttrModified ??
??? ?DOMCharacterDataModified ??
??? ?DOMNodeInserted ??
??? ?DOMNodeInsertedIntoDocument ??
??? ?DOMNodeRemoved ??
??? ?DOMNodeRemovedFromDocument ??
??? ?DOMSubtreeModified ??
??? ?DOMContentLoaded ??
??? ?
??? ?webkitBeforeTextInserted ??
??? ?webkitEditableContentChanged ??
??? ?
??? ?canplay ??
??? ?canplaythrough ??
??? ?durationchange ??
??? ?emptied ??
??? ?ended ??
??? ?loadeddata ??
??? ?loadedmetadata ??
??? ?pause ??
??? ?play ??
??? ?playing ??
??? ?ratechange ??
??? ?seeked ??
??? ?seeking ??
??? ?timeupdate ??
??? ?volumechange ??
??? ?waiting ??
??? ?
??? ?webkitbeginfullscreen ??
??? ?webkitendfullscreen ??
??? ?
??? ?progress ??
??? ?stalled ??
??? ?suspend ??
??? ?
??? ?webkitAnimationEnd ??
??? ?webkitAnimationStart ??
??? ?webkitAnimationIteration ??
??? ?
??? ?webkitTransitionEnd ??
??? ?
??? ?orientationchange ??
??? ?
??? ?timeout ??
??? ?
??? ?touchstart ??
??? ?touchmove ??
??? ?touchend ??
??? ?touchcancel ??
?*#if PLATFORM(ANDROID)
??? ?touchlongpress ??
??? ?touchdoubletap ??
?*#endif * ??
??? ?
??? ?success ??
??? ?
??? ?loadend ??
??? ?
??? ?webkitfullscreenchange ??
??? ?
??? ?webkitspeechchange ??
??? ?
??? ?webglcontextlost ??
??? ?webglcontextrestored ??
??? ?webglcontextcreationerror ??
??? ?
??? ?audioprocess}
總結
以上是生活随笔為你收集整理的WebKit DOM Event (一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android root概念
- 下一篇: WebKit Event