1 | define([ |
---|
2 | "dojo/_base/declare", |
---|
3 | "dojo/_base/lang", |
---|
4 | "dojo/sniff", |
---|
5 | "dojo/_base/window", |
---|
6 | "dojo/dom-class", |
---|
7 | "dojo/dom-geometry", |
---|
8 | "dojo/dom-style", |
---|
9 | "dojo/window", |
---|
10 | "dijit/_WidgetBase", |
---|
11 | "dojo/_base/array", |
---|
12 | "dijit/registry", |
---|
13 | "dojo/touch", |
---|
14 | "./viewRegistry", |
---|
15 | "./_css3" |
---|
16 | ], function(declare, lang, has, win, domClass, domGeometry, domStyle, windowUtils, WidgetBase, array, registry, touch, viewRegistry, css3){ |
---|
17 | |
---|
18 | return declare("dojox.mobile.Overlay", WidgetBase, { |
---|
19 | // summary: |
---|
20 | // A non-templated widget that animates up from the bottom, |
---|
21 | // overlaying the current content. |
---|
22 | |
---|
23 | // baseClass: String |
---|
24 | // The name of the CSS class of this widget. |
---|
25 | baseClass: "mblOverlay mblOverlayHidden", |
---|
26 | |
---|
27 | buildRendering: function(){ |
---|
28 | this.inherited(arguments); |
---|
29 | if(!this.containerNode){ |
---|
30 | // set containerNode so that getChildren() works |
---|
31 | this.containerNode = this.domNode; |
---|
32 | } |
---|
33 | }, |
---|
34 | |
---|
35 | _reposition: function(){ |
---|
36 | // summary: |
---|
37 | // Position the overlay at the bottom |
---|
38 | // tags: |
---|
39 | // private |
---|
40 | var popupPos = domGeometry.position(this.domNode); |
---|
41 | var vp = windowUtils.getBox(); |
---|
42 | // search for the scrollable parent if any |
---|
43 | var scrollableParent = viewRegistry.getEnclosingScrollable(this.domNode); |
---|
44 | // update vp scroll position if the overlay is inside a scrollable |
---|
45 | if(scrollableParent){ |
---|
46 | vp.t -= scrollableParent.getPos().y; |
---|
47 | } |
---|
48 | // reposition if needed |
---|
49 | if((popupPos.y+popupPos.h) != vp.h // TODO: should be a has() test for position:fixed not scrolling |
---|
50 | || (domStyle.get(this.domNode, 'position') != 'absolute' && has('android') < 3)){ // android 2.x supports position:fixed but child transforms don't persist |
---|
51 | popupPos.y = vp.t + vp.h - popupPos.h; |
---|
52 | domStyle.set(this.domNode, { position: "absolute", top: popupPos.y + "px", bottom: "auto" }); |
---|
53 | } |
---|
54 | return popupPos; |
---|
55 | }, |
---|
56 | |
---|
57 | show: function(/*DomNode?*/aroundNode){ |
---|
58 | // summary: |
---|
59 | // Scroll the overlay up into view |
---|
60 | array.forEach(registry.findWidgets(this.domNode), function(w){ |
---|
61 | if(w && w.height == "auto" && typeof w.resize == "function"){ |
---|
62 | w.resize(); |
---|
63 | } |
---|
64 | }); |
---|
65 | var popupPos = this._reposition(); |
---|
66 | if(aroundNode){ |
---|
67 | var aroundPos = domGeometry.position(aroundNode); |
---|
68 | if(popupPos.y < aroundPos.y){ // if the aroundNode is under the popup, try to scroll it up |
---|
69 | // TODO: if this widget has a scrollable parent, use its scrollTo method to make sure the aroundNode is visible? |
---|
70 | win.global.scrollBy(0, aroundPos.y + aroundPos.h - popupPos.y); |
---|
71 | this._reposition(); |
---|
72 | } |
---|
73 | } |
---|
74 | var _domNode = this.domNode; |
---|
75 | domClass.replace(_domNode, ["mblCoverv", "mblIn"], ["mblOverlayHidden", "mblRevealv", "mblOut", "mblReverse", "mblTransition"]); |
---|
76 | this.defer(function(){ |
---|
77 | var handler = this.connect(_domNode, css3.name("transitionEnd"), function(){ |
---|
78 | this.disconnect(handler); |
---|
79 | domClass.remove(_domNode, ["mblCoverv", "mblIn", "mblTransition"]); |
---|
80 | this._reposition(); |
---|
81 | }); |
---|
82 | domClass.add(_domNode, "mblTransition"); |
---|
83 | }, 100); |
---|
84 | var skipReposition = false; |
---|
85 | |
---|
86 | this._moveHandle = this.connect(win.doc.documentElement, touch.move, |
---|
87 | function(){ |
---|
88 | skipReposition = true; |
---|
89 | } |
---|
90 | ); |
---|
91 | this._repositionTimer = setInterval(lang.hitch(this, function(){ |
---|
92 | if(skipReposition){ // don't reposition if busy |
---|
93 | skipReposition = false; |
---|
94 | return; |
---|
95 | } |
---|
96 | this._reposition(); |
---|
97 | }), 50); // yield a short time to allow for consolidation for better CPU throughput |
---|
98 | return popupPos; |
---|
99 | }, |
---|
100 | |
---|
101 | hide: function(){ |
---|
102 | // summary: |
---|
103 | // Scroll the overlay down and then make it invisible |
---|
104 | var _domNode = this.domNode; |
---|
105 | if(this._moveHandle){ |
---|
106 | this.disconnect(this._moveHandle); |
---|
107 | this._moveHandle = null; |
---|
108 | clearInterval(this._repositionTimer); |
---|
109 | this._repositionTimer = null; |
---|
110 | } |
---|
111 | if(has("css3-animations")){ |
---|
112 | domClass.replace(_domNode, ["mblRevealv", "mblOut", "mblReverse"], ["mblCoverv", "mblIn", "mblOverlayHidden", "mblTransition"]); |
---|
113 | this.defer(function(){ |
---|
114 | var handler = this.connect(_domNode, css3.name("transitionEnd"), function(){ |
---|
115 | this.disconnect(handler); |
---|
116 | domClass.replace(_domNode, ["mblOverlayHidden"], ["mblRevealv", "mblOut", "mblReverse", "mblTransition"]); |
---|
117 | }); |
---|
118 | domClass.add(_domNode, "mblTransition"); |
---|
119 | }, 100); |
---|
120 | }else{ |
---|
121 | domClass.replace(_domNode, ["mblOverlayHidden"], ["mblCoverv", "mblIn", "mblRevealv", "mblOut", "mblReverse"]); |
---|
122 | } |
---|
123 | }, |
---|
124 | |
---|
125 | onBlur: function(/*Event*/e){ |
---|
126 | return false; // touching outside the overlay area does not call hide() |
---|
127 | } |
---|
128 | }); |
---|
129 | }); |
---|