1
2
3
4
5
6
7
8
9
10
11
12
13
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
70 hack_timer_workaround_bug_button = None
71
72
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)
98 evt = get_main_frame().gobject_wrap(evt)
99 except:
100 pass
101 listener = None
102 curElem = sender
103
104
105 cap = getCaptureElement()
106 listener = get_listener(cap)
107 if cap and listener:
108
109 dispatchEvent(evt, cap, listener)
110 evt.stopPropagation()
111 return
112
113 while curElem and not get_listener(curElem):
114
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
133
134
150
151
172
173
182
183
186
187
191
192
198
199
201 if hasattr(elem1, "isSameNode"):
202 return elem1.isSameNode(elem2)
203 return elem1 == elem2
204
205
208
209
212
213
216
217
220
221
224
225
228
229
232
233
236
237
240
241
244
245
250
251
254
255
260
261
264
265
268
269
272
273
276
277
280
281
284
285
288
289
291 return createElement("tbody")
292
293
296
297
299 return createElement("textarea")
300
301
304
305
308
309
311 evt.stopPropagation()
312
313
316
317
320
321
324
325
328
329
332
333
336
337
339 try:
340 return evt.fromElement
341 except:
342 return None
343
344
346 return evt.which or evt.keyCode or 0
347
348
351
352
355
356
359
360
363
364
366 return event.currentTarget
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
413
414
417
418
421
422
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
460 mf = get_main_frame()
461 return str(getattr(elem, attr))
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
472 mf = get_main_frame()
473 return bool(getattr(elem, mf.mash_attrib(attr)))
474
475
477 if not elem.hasAttribute(attr):
478 return None
479 return bool(elem.getAttribute(attr))
480
481
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
542 """
543 See setEventListener() for more information.
544 """
545 return get_listener(element)
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
570
571
572 -def getInnerText(element):
573
574
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
587 mf = get_main_frame()
588 return int(getattr(elem, attr))
589
590
592 if not elem.hasAttribute(attr):
593 return None
594 return int(elem.getAttribute(attr))
595
596
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
652 self.parent = elem
653 self.child = elem.firstChild
654 self.lastChild = None
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
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
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
738
739
742
743
746
747
750
751
753 return elem.offsetHeight
754
755
757 return elem.offsetWidth
758
759
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
819 mf = get_main_frame()
820 setattr(elem, mf.mash_attrib(attr), value)
821
822
826
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
842 except:
843 element.innerHTML = html
844
845
846 -def setInnerText(elem, text):
847
848 while elem.firstChild:
849 elem.removeChild(elem.firstChild)
850 elem.appendChild(doc().createTextNode(text or ''))
851
852
855
856
858 setattr(elem, attr, int(value))
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
869 -def setOptionText(select, text, index):
870 option = select.options.item(index)
871 option.textContent = text
872
873
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
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
945
946
947
950
951
966
967
968
971
972 currentEvent = None
973
974
986
987
990
991
1001
1002
1005
1006
1009
1010
1011 if sys.platform in ['mozilla', 'ie6', 'opera', 'oldmoz', 'safari']:
1012 init()
1013