1 #!/usr/bin/env python 2 3 """ 4 DOM Level 3 Events support, with SVG Tiny 1.2 implementation additions. 5 See: http://www.w3.org/TR/DOM-Level-3-Events/events.html 6 7 Copyright (C) 2007 Paul Boddie <paul@boddie.org.uk> 8 9 This library is free software; you can redistribute it and/or 10 modify it under the terms of the GNU Lesser General Public 11 License as published by the Free Software Foundation; either 12 version 2.1 of the License, or (at your option) any later version. 13 14 This library is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 Lesser General Public License for more details. 18 19 You should have received a copy of the GNU Lesser General Public 20 License along with this library; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 22 """ 23 24 import xml.dom 25 import time 26 27 XML_EVENTS_NAMESPACE = "http://www.w3.org/2001/xml-events" 28 29 class EventException(Exception): 30 31 UNSPECIFIED_EVENT_TYPE_ERR = 0 32 DISPATCH_REQUEST_ERR = 1 33 34 class DocumentEvent: 35 36 """ 37 An event interface supportable by documents. 38 See: http://www.w3.org/TR/DOM-Level-3-Events/events.html#Events-DocumentEvent 39 """ 40 41 def canDispatch(self, namespaceURI, type): 42 return namespaceURI is None and event_types.has_key(type) 43 44 def createEvent(self, eventType): 45 try: 46 return event_types[eventType]() 47 except KeyError: 48 raise xml.dom.DOMException(xml.dom.NOT_SUPPORTED_ERR) 49 50 class Event: 51 52 "An event class." 53 54 CAPTURING_PHASE = 1 55 AT_TARGET = 2 56 BUBBLING_PHASE = 3 57 58 def __init__(self): 59 60 "Initialise the event." 61 62 # Initialised later: 63 64 self.target = None 65 self.currentTarget = None 66 self.defaultPrevented = 0 67 self.type = None 68 self.namespaceURI = None 69 70 # DOM Level 3 Events: 71 72 self.bubbles = None 73 self.eventPhase = self.CAPTURING_PHASE 74 self.timeStamp = time.time() 75 76 def initEvent(self, eventTypeArg, canBubbleArg, cancelableArg): 77 self.initEventNS(None, eventTypeArg, canBubbleArg, cancelableArg) 78 79 def initEventNS(self, namespaceURIArg, eventTypeArg, canBubbleArg, cancelableArg): 80 self.namespaceURI = namespaceURIArg 81 self.type = eventTypeArg 82 self.bubbles = canBubbleArg 83 self.cancelable = cancelableArg 84 85 def preventDefault(self): 86 self.defaultPrevented = 1 87 88 def stopPropagation(self): 89 pass 90 91 def stopImmediatePropagation(self): 92 pass 93 94 class UIEvent(Event): 95 96 "A user interface event." 97 98 def __init__(self): 99 Event.__init__(self) 100 self.detail = None 101 102 class MouseEvent(UIEvent): 103 104 "A mouse-related event." 105 106 def __init__(self): 107 Event.__init__(self) 108 self.screenX, self.screenY, self.clientX, self.clientY, self.button = None, None, None, None, None 109 110 # Event types registry. 111 112 event_types = { 113 "Event" : Event, 114 "UIEvent" : UIEvent, 115 "MouseEvent" : MouseEvent 116 } 117 118 class EventTarget: 119 120 "An event target class." 121 122 def addEventListener(self, type, listener, useCapture): 123 self.addEventListenerNS(None, type, listener, useCapture) 124 125 def addEventListenerNS(self, namespaceURI, type, listener, useCapture, group=None): # NOTE: group ignored 126 listeners = self.ownerDocument.global_.listeners 127 if not listeners.has_key(self): 128 listeners[self] = {} 129 if not listeners[self].has_key((namespaceURI, type)): 130 listeners[self][(namespaceURI, type)] = [] 131 listeners[self][(namespaceURI, type)].append((listener, useCapture)) 132 133 def dispatchEvent(self, evt): 134 listeners = self.ownerDocument.global_.listeners 135 if not evt.type: 136 raise EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR) 137 # Dispatch on namespaceURI, type. 138 for listener, useCapture in listeners.get(self, {}).get((evt.namespaceURI, evt.type), []): 139 listener.handleEvent(evt) 140 return evt.defaultPrevented 141 142 def removeEventListener(self, type, listener, useCapture): 143 self.removeEventListenerNS(None, type, listener, useCapture) 144 145 def removeEventListenerNS(self, namespaceURI, type, listener, useCapture): 146 listeners = self.ownerDocument.global_.listeners 147 if listeners.has_key(self) and listeners[self].has_key((namespaceURI, type)): 148 try: 149 listeners[self][(namespaceURI, type)].remove((listener, useCapture)) 150 except ValueError: 151 pass 152 153 # vim: tabstop=4 expandtab shiftwidth=4