SwapView.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. define("dojox/mobile/SwapView", [
  2. "dojo/_base/array",
  3. "dojo/_base/connect",
  4. "dojo/_base/declare",
  5. "dojo/dom",
  6. "dojo/dom-class",
  7. "dijit/registry", // registry.byNode
  8. "./View",
  9. "./_ScrollableMixin"
  10. ], function(array, connect, declare, dom, domClass, registry, View, ScrollableMixin){
  11. /*=====
  12. var View = dojox.mobile.View;
  13. var ScrollableMixin = dojox.mobile._ScrollableMixin;
  14. =====*/
  15. // module:
  16. // dojox/mobile/SwapView
  17. // summary:
  18. // A container that can be flipped horizontally.
  19. return declare("dojox.mobile.SwapView", [View, ScrollableMixin], {
  20. // summary:
  21. // A container that can be flipped horizontally.
  22. // description:
  23. // SwapView is a container widget that represents entire mobile
  24. // device screen, and can be swiped horizontally. (In dojo-1.6, it
  25. // was called 'FlippableView'.) SwapView is a subclass of
  26. // dojox.mobile.View. SwapView allows the user to swipe the screen
  27. // left or right to move between the views. When SwapView is
  28. // swiped, it finds an adjacent SwapView to open it.
  29. /* internal properties */
  30. scrollDir: "f",
  31. weight: 1.2,
  32. buildRendering: function(){
  33. this.inherited(arguments);
  34. domClass.add(this.domNode, "mblSwapView");
  35. this.setSelectable(this.domNode, false);
  36. this.containerNode = this.domNode;
  37. connect.subscribe("/dojox/mobile/nextPage", this, "handleNextPage");
  38. connect.subscribe("/dojox/mobile/prevPage", this, "handlePrevPage");
  39. this.findAppBars();
  40. },
  41. resize: function(){
  42. // summary:
  43. // Calls resize() of each child widget.
  44. this.inherited(arguments); // scrollable#resize() will be called
  45. array.forEach(this.getChildren(), function(child){
  46. if(child.resize){ child.resize(); }
  47. });
  48. },
  49. onTouchStart: function(e){
  50. // summary:
  51. // Internal function to handle touchStart events.
  52. var fromTop = this.domNode.offsetTop;
  53. var nextView = this.nextView(this.domNode);
  54. if(nextView){
  55. nextView.stopAnimation();
  56. domClass.add(nextView.domNode, "mblIn");
  57. // Temporarily add padding to align with the fromNode while transition
  58. nextView.containerNode.style.paddingTop = fromTop + "px";
  59. }
  60. var prevView = this.previousView(this.domNode);
  61. if(prevView){
  62. prevView.stopAnimation();
  63. domClass.add(prevView.domNode, "mblIn");
  64. // Temporarily add padding to align with the fromNode while transition
  65. prevView.containerNode.style.paddingTop = fromTop + "px";
  66. }
  67. this.inherited(arguments);
  68. },
  69. handleNextPage: function(/*Widget*/w){
  70. // summary:
  71. // Called when the "/dojox/mobile/nextPage" topic is published.
  72. var refNode = w.refId && dom.byId(w.refId) || w.domNode;
  73. if(this.domNode.parentNode !== refNode.parentNode){ return; }
  74. if(this.getShowingView() !== this){ return; }
  75. this.goTo(1);
  76. },
  77. handlePrevPage: function(/*Widget*/w){
  78. // summary:
  79. // Called when the "/dojox/mobile/prevPage" topic is published.
  80. var refNode = w.refId && dom.byId(w.refId) || w.domNode;
  81. if(this.domNode.parentNode !== refNode.parentNode){ return; }
  82. if(this.getShowingView() !== this){ return; }
  83. this.goTo(-1);
  84. },
  85. goTo: function(/*Number*/dir){
  86. // summary:
  87. // Moves to the next or previous view.
  88. var w = this.domNode.offsetWidth;
  89. var view = (dir == 1) ? this.nextView(this.domNode) : this.previousView(this.domNode);
  90. if(!view){ return; }
  91. view._beingFlipped = true;
  92. view.scrollTo({x:w*dir});
  93. view._beingFlipped = false;
  94. view.domNode.style.display = "";
  95. domClass.add(view.domNode, "mblIn");
  96. this.slideTo({x:0}, 0.5, "ease-out", {x:-w*dir});
  97. },
  98. isSwapView: function(node){
  99. // summary:
  100. // Returns true if the given node is a SwapView widget.
  101. return (node && node.nodeType === 1 && domClass.contains(node, "mblSwapView"));
  102. },
  103. nextView: function(node){
  104. // summary:
  105. // Returns the next view.
  106. for(var n = node.nextSibling; n; n = n.nextSibling){
  107. if(this.isSwapView(n)){ return registry.byNode(n); }
  108. }
  109. return null;
  110. },
  111. previousView: function(node){
  112. // summary:
  113. // Returns the previous view.
  114. for(var n = node.previousSibling; n; n = n.previousSibling){
  115. if(this.isSwapView(n)){ return registry.byNode(n); }
  116. }
  117. return null;
  118. },
  119. scrollTo: function(/*Object*/to){
  120. // summary:
  121. // Overrides dojox.mobile.scrollable.scrollTo().
  122. if(!this._beingFlipped){
  123. var newView, x;
  124. if(to.x < 0){
  125. newView = this.nextView(this.domNode);
  126. x = to.x + this.domNode.offsetWidth;
  127. }else{
  128. newView = this.previousView(this.domNode);
  129. x = to.x - this.domNode.offsetWidth;
  130. }
  131. if(newView){
  132. newView.domNode.style.display = "";
  133. newView._beingFlipped = true;
  134. newView.scrollTo({x:x});
  135. newView._beingFlipped = false;
  136. }
  137. }
  138. this.inherited(arguments);
  139. },
  140. slideTo: function(/*Object*/to, /*Number*/duration, /*String*/easing, fake_pos){
  141. // summary:
  142. // Overrides dojox.mobile.scrollable.slideTo().
  143. if(!this._beingFlipped){
  144. var w = this.domNode.offsetWidth;
  145. var pos = fake_pos || this.getPos();
  146. var newView, newX;
  147. if(pos.x < 0){ // moving to left
  148. newView = this.nextView(this.domNode);
  149. if(pos.x < -w/4){ // slide to next
  150. if(newView){
  151. to.x = -w;
  152. newX = 0;
  153. }
  154. }else{ // go back
  155. if(newView){
  156. newX = w;
  157. }
  158. }
  159. }else{ // moving to right
  160. newView = this.previousView(this.domNode);
  161. if(pos.x > w/4){ // slide to previous
  162. if(newView){
  163. to.x = w;
  164. newX = 0;
  165. }
  166. }else{ // go back
  167. if(newView){
  168. newX = -w;
  169. }
  170. }
  171. }
  172. if(newView){
  173. newView._beingFlipped = true;
  174. newView.slideTo({x:newX}, duration, easing);
  175. newView._beingFlipped = false;
  176. if(newX === 0){ // moving to another view
  177. dojox.mobile.currentView = newView;
  178. }
  179. newView.domNode._isShowing = (newView && newX === 0);
  180. }
  181. this.domNode._isShowing = !(newView && newX === 0);
  182. }
  183. this.inherited(arguments);
  184. },
  185. onFlickAnimationEnd: function(e){
  186. // summary:
  187. // Overrides dojox.mobile.scrollable.onFlickAnimationEnd().
  188. if(e && e.animationName && e.animationName !== "scrollableViewScroll2"){ return; }
  189. // Hide all the views other than the currently showing one.
  190. // Otherwise, when the orientation is changed, other views
  191. // may appear unexpectedly.
  192. var children = this.domNode.parentNode.childNodes;
  193. for(var i = 0; i < children.length; i++){
  194. var c = children[i];
  195. if(this.isSwapView(c)){
  196. domClass.remove(c, "mblIn");
  197. if(!c._isShowing){
  198. c.style.display = "none";
  199. }
  200. }
  201. }
  202. this.inherited(arguments);
  203. if(this.getShowingView() === this){
  204. connect.publish("/dojox/mobile/viewChanged", [this]);
  205. // Reset the temporary padding
  206. this.containerNode.style.paddingTop = "";
  207. }
  208. }
  209. });
  210. });