| Home | Trees | Indices | Help |
|
|---|
|
|
1 # Copyright 2006 James Tauber and contributors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """
15 DOM implements the core of Pjamas-Desktop, providing access to
16 and management of the DOM model of the PyWebkitGtk window.
17 """
18
19 import sys
20 if sys.platform not in ['mozilla', 'ie6', 'opera', 'oldmoz', 'safari']:
21 from pyjamas.Window import onResize, onClosing, onClosed
22 from __pyjamas__ import JS, doc, get_main_frame, wnd
23
24 currentEvent = None
25
26 sCaptureElem = None
27 sEventPreviewStack = []
28
29 listeners = {}
30
31 from pyjamas.ui.Event import (
32 ONBLUR,
33 ONCHANGE,
34 ONCLICK,
35 ONCONTEXTMENU,
36 ONDBLCLICK,
37 ONERROR,
38 ONFOCUS,
39 ONKEYDOWN,
40 ONKEYPRESS,
41 ONKEYUP,
42 ONLOAD,
43 ONLOSECAPTURE,
44 ONMOUSEDOWN,
45 ONMOUSEMOVE,
46 ONMOUSEOUT,
47 ONMOUSEOVER,
48 ONMOUSEUP,
49 ONSCROLL
50 )
51
52
54 if item is None:
55 return None
56 if hasattr(item, "__instance__"):
57 ret = listeners.get(item.__instance__)
58 else:
59 ret = listeners.get(hash(item))
60 return ret
61
62
64 if hasattr(item, "__instance__"):
65 listeners[item.__instance__] = listener
66 else:
67 listeners[hash(item)] = listener
68
69 # ugh, *spew*, *hurl* http://code.google.com/p/pyjamas/issues/detail?id=213
70 hack_timer_workaround_bug_button = None
71
72
74
75 mf = get_main_frame()
76 mf._addWindowEventListener("click", browser_event_cb)
77 mf._addWindowEventListener("change", browser_event_cb)
78 mf._addWindowEventListener("mouseout", browser_event_cb)
79 mf._addWindowEventListener("mousedown", browser_event_cb)
80 mf._addWindowEventListener("mouseup", browser_event_cb)
81 mf._addWindowEventListener("resize", browser_event_cb)
82 mf._addWindowEventListener("keyup", browser_event_cb)
83 mf._addWindowEventListener("keydown", browser_event_cb)
84 mf._addWindowEventListener("keypress", browser_event_cb)
85
86
89
90
92
93 if evt is None:
94 evt = wnd().event
95 else:
96 try:
97 sender = get_main_frame().gobject_wrap(sender) # webkit HACK!
98 evt = get_main_frame().gobject_wrap(evt) # webkit HACK!
99 except:
100 pass
101 listener = None
102 curElem = sender
103
104 #print "_dispatchEvent", sender, evt, evt.type
105 cap = getCaptureElement()
106 listener = get_listener(cap)
107 if cap and listener:
108 #print "_dispatchEvent", cap, listener
109 dispatchEvent(evt, cap, listener)
110 evt.stopPropagation()
111 return
112
113 while curElem and not get_listener(curElem):
114 #print "no parent listener", curElem, getParent(curElem)
115 curElem = getParent(curElem)
116 if curElem and getNodeType(curElem) != 1:
117 curElem = None
118
119 listener = get_listener(curElem)
120 if listener:
121 dispatchEvent(evt, curElem, listener)
122
123
125
126 if (_dispatchCapturedEvent(evt)):
127 cap = getCaptureElement()
128 listener = get_listener(cap)
129 if cap and listener:
130 dispatchEvent(evt, cap, listener)
131 #print "dcmsev, stop propagation"
132 evt.stopPropagation()
133
134
136 cap = getCaptureElement()
137 if cap:
138 #print "cap", dir(evt), cap
139 if not eventGetToElement(evt):
140 #print "synthesise", cap
141 #When the mouse leaves the window during capture, release capture
142 #and synthesize an 'onlosecapture' event.
143 setCapture(None)
144 listener = get_listener(cap)
145 if listener:
146 # this should be interesting...
147 lcEvent = doc().createEvent('UIEvent')
148 lcEvent.initUIEvent('losecapture', False, False, wnd(), 0)
149 dispatchEvent(lcEvent, cap, listener)
150
151
153
154 try:
155 event = get_main_frame().gobject_wrap(event) # webkit HACK!
156 except:
157 pass
158 #print "browser_event_cb", event
159 et = eventGetType(event)
160 #print "browser_event_cb", event, et
161 if et == "resize":
162 onResize()
163 return
164 elif et == 'mouseout':
165 #print "mouse out", event
166 return _dispatchCapturedMouseoutEvent(event)
167 elif (et == 'keyup' or et == 'keydown' or
168 et == 'keypress' or et == 'change'):
169 return _dispatchCapturedEvent(event)
170 else:
171 return _dispatchCapturedMouseEvent(event)
172
173
175
176 if not previewEvent(event):
177 #print "dce, stop propagation"
178 event.stopPropagation()
179 eventPreventDefault(event)
180 return False
181 return True
182
183
186
187
191
192
198
199
204
205
207 return createElement("A")
208
209
211 return createElement("button")
212
213
215 return createElement("col")
216
217
219 return createElement("div")
220
221
223 return doc().createElement(tag)
224
225
227 return createElement("fieldset")
228
229
231 return createElement("form")
232
233
235 return createElement("iframe")
236
237
239 return createElement("img")
240
241
243 return createInputElement("checkbox")
244
245
250
251
253 return createInputElement("password")
254
255
260
261
263 return createInputElement("text")
264
265
267 return createElement("label")
268
269
271 return createElement("legend")
272
273
275 return createElement("options")
276
277
279 return createElement("select")
280
281
283 return createElement("span")
284
285
287 return createElement("table")
288
289
291 return createElement("tbody")
292
293
295 return createElement("td")
296
297
299 return createElement("textarea")
300
301
303 return createElement("th")
304
305
307 return createElement("tr")
308
309
312
313
315 evt.cancelBubble = cancel
316
317
320
321
324
325
328
329
332
333
336
337
343
344
347
348
351
352
355
356
359
360
363
364
367
368
371
372
374 type = eventGetType(evt)
375 if type == 'mouseout':
376 return evt.relatedTarget
377 elif type == 'mouseover':
378 return evt.target
379 return None
380
381
384
385 eventmap = {
386 "blur": 0x01000,
387 "change": 0x00400,
388 "click": 0x00001,
389 "dblclick": 0x00002,
390 "focus": 0x00800,
391 "keydown": 0x00080,
392 "keypress": 0x00100,
393 "keyup": 0x00200,
394 "load": 0x08000,
395 "losecapture": 0x02000,
396 "mousedown": 0x00004,
397 "mousemove": 0x00040,
398 "mouseout": 0x00020,
399 "mouseover": 0x00010,
400 "mouseup": 0x00008,
401 "scroll": 0x04000,
402 "error": 0x10000,
403 "contextmenu": 0x20000,
404 }
405
406
409
410
412 return eventGetType(event)
413
414
417
418
421
422
424 return evt.toString()
425
426
429
430
432 left = 0
433 curr = elem
434 while curr.offsetParent:
435 left -= curr.scrollLeft
436 curr = curr.parentNode
437
438 while elem:
439 left += elem.offsetLeft - elem.scrollLeft
440 elem = elem.offsetParent
441
442 return left
443
444
446 top = 0
447 curr = elem
448 while curr.offsetParent:
449 top -= curr.scrollTop
450 curr = curr.parentNode
451
452 while elem:
453 top += elem.offsetTop - elem.scrollTop
454 elem = elem.offsetParent
455
456 return top
457
458
462
463
465 mf = get_main_frame()
466 if not elem.hasAttribute(attr):
467 return str(getattr(elem, mf.mash_attrib(attr)))
468 return str(elem.getAttribute(attr))
469
470
474
475
480
481
483 return sCaptureElem
484
485
487 """
488 Get a child of the DOM element by specifying an index.
489 """
490 count = 0
491 child = elem.firstChild
492 while child:
493 next = child.nextSibling
494 if child.nodeType == 1:
495 if index == count:
496 return child
497 count += 1
498 child = next
499 return None
500
501
503 """
504 Calculate the number of children the given element has. This loops
505 over all the children of that element and counts them.
506 """
507 count = 0
508 child = elem.firstChild
509 while child:
510 if child.nodeType == 1:
511 count += 1
512 child = child.nextSibling
513 return count
514
515
517 """
518 Return the index of the given child in the given parent.
519
520 This performs a linear search.
521 """
522 count = 0
523 child = parent.firstChild
524 while child:
525 if child == toFind:
526 return count
527 if child.nodeType == 1:
528 count += 1
529 child = child.nextSibling
530
531 return -1
532
533
535 """
536 Return the element in the document's DOM tree with the given id.
537 """
538 return doc().getElementById(id)
539
540
546
547 eventbitsmap = {}
548
549
551 """
552 Return which events are currently "sunk" for a given DOM node. See
553 sinkEvents() for more information.
554 """
555 return eventbitsmap.get(element, 0)
556
557
559 child = elem and elem.firstChild
560 while child and child.nodeType != 1:
561 child = child.nextSibling
562 return child
563
564
566 try:
567 return element and element.innerHtml # webkit. erk.
568 except:
569 return element and element.innerHTML # hulahop / xul. yuk.
570
571
573 # To mimic IE's 'innerText' property in the W3C DOM, we need to recursively
574 # concatenate all child text nodes (depth first).
575 text = ''
576 child = element.firstChild
577 while child:
578 if child.nodeType == 1:
579 text += child.getInnerText()
580 elif child.nodeValue:
581 text += child.nodeValue
582 child = child.nextSibling
583 return text
584
585
589
590
595
596
598 return getIntAttribute(elem.style, attr)
599
600
602 sib = elem.nextSibling
603 while sib and sib.nodeType != 1:
604 sib = sib.nextSibling
605 return sib
606
607
610
611
613 parent = elem.parentNode
614 if parent is None:
615 return None
616 if getNodeType(parent) != 1:
617 return None
618 return parent
619
620
622 try:
623 if hasattr(elem.style, 'getProperty'):
624 return elem.style.getProperty(mash_name_for_glib(attr))
625 return elem.style.getAttribute(attr)
626 except AttributeError:
627 return getattr(elem.style, attr, None)
628
629
631 count = 0
632 child = parent.firstChild
633 before = None
634 while child:
635 if child.nodeType == 1:
636 if (count == index):
637 before = child
638 break
639
640 count += 1
641 child = child.nextSibling
642
643 if before is None:
644 parent.appendChild(toAdd)
645 else:
646 parent.insertBefore(toAdd, before)
647
648
650
655
657 if not self.child:
658 raise StopIteration
659 self.lastChild = self.child
660 self.child = getNextSibling(self.child)
661 return self.lastChild
662
664 self.parent.removeChild(self.lastChild)
665
668
669
671 """
672 Returns an iterator over all the children of the given
673 DOM node.
674 """
675 return IterChildrenClass(elem)
676
677
679
681 self.parent = elem
682 self.child = getFirstChild(elem)
683 self.lastChild = None
684 self.stack = []
685
687 if not self.child:
688 raise StopIteration
689 self.lastChild = self.child
690 firstChild = getFirstChild(self.child)
691 nextSibling = getNextSibling(self.child)
692 if firstChild is not None:
693 if nextSibling is not None:
694 self.stack.append((nextSibling, self.parent))
695 self.parent = self.child
696 self.child = firstChild
697 elif nextSibling is not None:
698 self.child = nextSibling
699 elif len(self.stack) > 0:
700 (self.child, self.parent) = self.stack.pop()
701 else:
702 self.child = None
703 return self.lastChild
704
706 self.parent.removeChild(self.lastChild)
707
710
711
713 """
714 Walk an entire subtree of the DOM. This returns an
715 iterator/iterable which performs a pre-order traversal
716 of all the children of the given element.
717 """
718 return IterWalkChildren(elem)
719
720
722 while child:
723 if compare(parent, child):
724 return True
725 child = child.parentNode
726 if not child:
727 return False
728 if child.nodeType != 1:
729 child = None
730 return False
731
732
734 global sCaptureElem
735 if sCaptureElem and compare(elem, sCaptureElem):
736 sCaptureElem = None
737 return
738
739
741 parent.removeChild(child)
742
743
745 parent.replaceChild(newChild, oldChild)
746
747
750
751
754
755
758
759
761 left = elem.offsetLeft
762 top = elem.offsetTop
763 width = elem.offsetWidth
764 height = elem.offsetHeight
765
766 if elem.parentNode != elem.offsetParent:
767 left -= elem.parentNode.offsetLeft
768 top -= elem.parentNode.offsetTop
769
770 cur = elem.parentNode
771 while cur and cur.nodeType == 1:
772 if hasattr(cur, 'style') and hasattr(cur.style, 'overflow') and \
773 (cur.style.overflow == 'auto' or cur.style.overflow == 'scroll'):
774 if left < cur.scrollLeft:
775 cur.scrollLeft = left
776 if left + width > cur.scrollLeft + cur.clientWidth:
777 cur.scrollLeft = (left + width) - cur.clientWidth
778 if top < cur.scrollTop:
779 cur.scrollTop = top
780 if top + height > cur.scrollTop + cur.clientHeight:
781 cur.scrollTop = (top + height) - cur.clientHeight
782
783 offsetLeft = cur.offsetLeft
784 offsetTop = cur.offsetTop
785 if cur.parentNode != cur.offsetParent:
786 if hasattr(cur.parentNode, "offsetLeft"):
787 offsetLeft -= cur.parentNode.offsetLeft
788 if hasattr(cur.parentNode, "offsetTop"):
789 offsetTop -= cur.parentNode.offsetTop
790
791 left += offsetLeft - cur.scrollLeft
792 top += offsetTop - cur.scrollTop
793 cur = cur.parentNode
794
795
797 res = ''
798 for c in name:
799 if c.isupper():
800 res += joiner + c.lower()
801 else:
802 res += c
803 return res
804
805
808
809
811 setattr(element, attribute, value)
812
813
816
817
821
822
826 #print "setCapture", sCaptureElem
827
828
830 """
831 Register an object to receive event notifications for the given
832 element. The listener's onBrowserEvent() method will be called
833 when a captured event occurs. To set which events are captured,
834 use sinkEvents().
835 """
836 set_listener(element, listener)
837
838
840 try:
841 element.innerHtml = html # webkit. yuk.
842 except:
843 element.innerHTML = html # hulahop / xul. yukk.
844
845
847 #Remove all children first.
848 while elem.firstChild:
849 elem.removeChild(elem.firstChild)
850 elem.appendChild(doc().createTextNode(text or ''))
851
852
854 elem.setAttribute(attr, str(value))
855
856
859
860
862 mf = get_main_frame()
863 if hasattr(elem.style, 'setProperty'):
864 elem.style.setProperty(mf.mash_attrib(attr), str(value), "")
865 else:
866 elem.style.setAttribute(mf.mash_attrib(attr), str(value), "")
867
868
872
873
875 if hasattr(element.style, 'setProperty'):
876 element.style.setProperty(mash_name_for_glib(name), value, "")
877 else:
878 element.style.setAttribute(name, value, "")
879
880
882 """
883 Set which events should be captured on a given element and passed to the
884 registered listener. To set the listener, use setEventListener().
885
886 @param bits: A combination of bits; see ui.Event for bit values
887 """
888 mask = getEventsSunk(element) ^ bits
889 eventbitsmap[element] = bits
890 if not mask:
891 return
892
893 bits = mask
894
895 if not bits:
896 return
897 #cb = lambda x,y,z: _dispatchEvent(y)
898 cb = _dispatchEvent
899 mf = get_main_frame()
900 if (bits & 0x00001):
901 mf.addEventListener(element, "click", cb)
902 if (bits & 0x00002):
903 mf.addEventListener(element, "dblclick", cb)
904 if (bits & 0x00004):
905 mf.addEventListener(element, "mousedown", cb)
906 if (bits & 0x00008):
907 mf.addEventListener(element, "mouseup", cb)
908 if (bits & 0x00010):
909 mf.addEventListener(element, "mouseover", cb)
910 if (bits & 0x00020):
911 mf.addEventListener(element, "mouseout", cb)
912 if (bits & 0x00040):
913 mf.addEventListener(element, "mousemove", cb)
914 if (bits & 0x00080):
915 mf.addEventListener(element, "keydown", cb)
916 if (bits & 0x00100):
917 mf.addEventListener(element, "keypress", cb)
918 if (bits & 0x00200):
919 mf.addEventListener(element, "keyup", cb)
920 if (bits & 0x00400):
921 mf.addEventListener(element, "change", cb)
922 if (bits & 0x00800):
923 mf.addEventListener(element, "focus", cb)
924 if (bits & 0x01000):
925 mf.addEventListener(element, "blur", cb)
926 if (bits & 0x02000):
927 mf.addEventListener(element, "losecapture", cb)
928 if (bits & 0x04000):
929 mf.addEventListener(element, "scroll", cb)
930 if (bits & 0x08000):
931 mf.addEventListener(element, "load", cb)
932 if (bits & 0x10000):
933 mf.addEventListener(element, "error", cb)
934 if (bits & 0x20000):
935 mf.addEventListener(element, "contextmenu", cb)
936
937
939 temp = elem.cloneNode(True)
940 tempDiv = createDiv()
941 tempDiv.appendChild(temp)
942 outer = getInnerHTML(tempDiv)
943 setInnerHTML(temp, "")
944 return outer
945
946
947 # TODO: missing dispatchEventAndCatch
950
951
953 ret = True
954 #print sEventPreviewStack
955 if len(sEventPreviewStack) > 0:
956 preview = sEventPreviewStack[len(sEventPreviewStack) - 1]
957
958 ret = preview.onEventPreview(evt)
959 if not ret:
960
961 #print "previewEvent, cancel, prevent default"
962 eventCancelBubble(evt, True)
963 eventPreventDefault(evt)
964
965 return ret
966
967
968 # TODO
971
972 currentEvent = None
973
974
976 global sCaptureElem
977 global currentEvent
978 if element == sCaptureElem:
979 if eventGetType(event) == "losecapture":
980 sCaptureElem = None
981 #print "dispatchEventImpl", listener, eventGetType(event)
982 prevCurrentEvent = currentEvent
983 currentEvent = event
984 listener.onBrowserEvent(event)
985 currentEvent = prevCurrentEvent
986
987
989 return currentEvent
990
991
993 option = createElement("OPTION")
994 setInnerText(option, item)
995 if value is not None:
996 setAttribute(option, "value", value)
997 if index == -1:
998 appendChild(select, option)
999 else:
1000 insertChild(select, option, index)
1001
1002
1005
1006
1009
1010
1011 if sys.platform in ['mozilla', 'ie6', 'opera', 'oldmoz', 'safari']:
1012 init()
1013
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Wed Jun 16 12:42:32 2010 | http://epydoc.sourceforge.net |