[483] | 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 | }); |
---|