Heading.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. define("dojox/mobile/Heading", [
  2. "dojo/_base/array",
  3. "dojo/_base/connect",
  4. "dojo/_base/declare",
  5. "dojo/_base/lang",
  6. "dojo/_base/window",
  7. "dojo/dom-class",
  8. "dojo/dom-construct",
  9. "dojo/dom-style",
  10. "dijit/registry", // registry.byId
  11. "dijit/_Contained",
  12. "dijit/_Container",
  13. "dijit/_WidgetBase",
  14. "./View"
  15. ], function(array, connect, declare, lang, win, domClass, domConstruct, domStyle, registry, Contained, Container, WidgetBase, View){
  16. var dm = lang.getObject("dojox.mobile", true);
  17. /*=====
  18. var Contained = dijit._Contained;
  19. var Container = dijit._Container;
  20. var WidgetBase = dijit._WidgetBase;
  21. =====*/
  22. // module:
  23. // dojox/mobile/Heading
  24. // summary:
  25. // A widget that represents a navigation bar.
  26. return declare("dojox.mobile.Heading", [WidgetBase, Container, Contained],{
  27. // summary:
  28. // A widget that represents a navigation bar.
  29. // description:
  30. // Heading is a widget that represents a navigation bar, which
  31. // usually appears at the top of an application. It usually
  32. // displays the title of the current view and can contain a
  33. // navigational control. If you use it with
  34. // dojox.mobile.ScrollableView, it can also be used as a fixed
  35. // header bar or a fixed footer bar. In such cases, specify the
  36. // fixed="top" attribute to be a fixed header bar or the
  37. // fixed="bottom" attribute to be a fixed footer bar. Heading can
  38. // have one or more ToolBarButton widgets as its children.
  39. // back: String
  40. // A label for the navigational control to return to the previous
  41. // View.
  42. back: "",
  43. // href: String
  44. // A URL to open when the navigational control is pressed.
  45. href: "",
  46. // moveTo: String
  47. // The id of the transition destination view which resides in the
  48. // current page.
  49. //
  50. // If the value has a hash sign ('#') before the id (e.g. #view1)
  51. // and the dojo.hash module is loaded by the user application, the
  52. // view transition updates the hash in the browser URL so that the
  53. // user can bookmark the destination view. In this case, the user
  54. // can also use the browser's back/forward button to navigate
  55. // through the views in the browser history.
  56. //
  57. // If null, transitions to a blank view.
  58. // If '#', returns immediately without transition.
  59. moveTo: "",
  60. // transition: String
  61. // A type of animated transition effect. You can choose from the
  62. // standard transition types, "slide", "fade", "flip", or from the
  63. // extended transition types, "cover", "coverv", "dissolve",
  64. // "reveal", "revealv", "scaleIn", "scaleOut", "slidev",
  65. // "swirl", "zoomIn", "zoomOut". If "none" is specified, transition
  66. // occurs immediately without animation.
  67. transition: "slide",
  68. // label: String
  69. // A title text of the heading. If the label is not specified, the
  70. // innerHTML of the node is used as a label.
  71. label: "",
  72. // iconBase: String
  73. // The default icon path for child items.
  74. iconBase: "",
  75. // backProp: Object
  76. // Properties for the back button.
  77. backProp: {className: "mblArrowButton"},
  78. // tag: String
  79. // A name of html tag to create as domNode.
  80. tag: "H1",
  81. buildRendering: function(){
  82. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement(this.tag);
  83. this.domNode.className = "mblHeading";
  84. if(!this.label){
  85. array.forEach(this.domNode.childNodes, function(n){
  86. if(n.nodeType == 3){
  87. var v = lang.trim(n.nodeValue);
  88. if(v){
  89. this.label = v;
  90. this.labelNode = domConstruct.create("SPAN", {innerHTML:v}, n, "replace");
  91. }
  92. }
  93. }, this);
  94. }
  95. if(!this.labelNode){
  96. this.labelNode = domConstruct.create("SPAN", null, this.domNode);
  97. }
  98. this.labelNode.className = "mblHeadingSpanTitle";
  99. this.labelDivNode = domConstruct.create("DIV", {
  100. className: "mblHeadingDivTitle",
  101. innerHTML: this.labelNode.innerHTML
  102. }, this.domNode);
  103. },
  104. startup: function(){
  105. if(this._started){ return; }
  106. var parent = this.getParent && this.getParent();
  107. if(!parent || !parent.resize){ // top level widget
  108. var _this = this;
  109. setTimeout(function(){ // necessary to render correctly
  110. _this.resize();
  111. }, 0);
  112. }
  113. this.inherited(arguments);
  114. },
  115. resize: function(){
  116. if(this._btn){
  117. this._btn.style.width = this._body.offsetWidth + this._head.offsetWidth + "px";
  118. }
  119. if(this.labelNode){
  120. // find the rightmost left button (B), and leftmost right button (C)
  121. // +-----------------------------+
  122. // | |A| |B| |C| |D| |
  123. // +-----------------------------+
  124. var leftBtn, rightBtn;
  125. var children = this.containerNode.childNodes;
  126. for(var i = children.length - 1; i >= 0; i--){
  127. var c = children[i];
  128. if(c.nodeType === 1){
  129. if(!rightBtn && domClass.contains(c, "mblToolBarButton") && domStyle.get(c, "float") === "right"){
  130. rightBtn = c;
  131. }
  132. if(!leftBtn && (domClass.contains(c, "mblToolBarButton") && domStyle.get(c, "float") === "left" || c === this._btn)){
  133. leftBtn = c;
  134. }
  135. }
  136. }
  137. if(!this.labelNodeLen && this.label){
  138. this.labelNode.style.display = "inline";
  139. this.labelNodeLen = this.labelNode.offsetWidth;
  140. this.labelNode.style.display = "";
  141. }
  142. var bw = this.domNode.offsetWidth; // bar width
  143. var rw = rightBtn ? bw - rightBtn.offsetLeft + 5 : 0; // rightBtn width
  144. var lw = leftBtn ? leftBtn.offsetLeft + leftBtn.offsetWidth + 5 : 0; // leftBtn width
  145. var tw = this.labelNodeLen || 0; // title width
  146. domClass[bw - Math.max(rw,lw)*2 > tw ? "add" : "remove"](this.domNode, "mblHeadingCenterTitle");
  147. }
  148. array.forEach(this.getChildren(), function(child){
  149. if(child.resize){ child.resize(); }
  150. });
  151. },
  152. _setBackAttr: function(/*String*/back){
  153. if (!back){
  154. domConstruct.destroy(this._btn);
  155. this._btn = null;
  156. this.back = "";
  157. }else{
  158. if(!this._btn){
  159. var btn = domConstruct.create("DIV", this.backProp, this.domNode, "first");
  160. var head = domConstruct.create("DIV", {className:"mblArrowButtonHead"}, btn);
  161. var body = domConstruct.create("DIV", {className:"mblArrowButtonBody mblArrowButtonText"}, btn);
  162. this._body = body;
  163. this._head = head;
  164. this._btn = btn;
  165. this.backBtnNode = btn;
  166. this.connect(body, "onclick", "onClick");
  167. }
  168. this.back = back;
  169. this._body.innerHTML = this._cv ? this._cv(this.back) : this.back;
  170. }
  171. this.resize();
  172. },
  173. _setLabelAttr: function(/*String*/label){
  174. this.label = label;
  175. this.labelNode.innerHTML = this.labelDivNode.innerHTML = this._cv ? this._cv(label) : label;
  176. },
  177. findCurrentView: function(){
  178. // summary:
  179. // Search for the view widget that contains this widget.
  180. var w = this;
  181. while(true){
  182. w = w.getParent();
  183. if(!w){ return null; }
  184. if(w instanceof View){ break; }
  185. }
  186. return w;
  187. },
  188. onClick: function(e){
  189. var h1 = this.domNode;
  190. domClass.add(h1, "mblArrowButtonSelected");
  191. setTimeout(function(){
  192. domClass.remove(h1, "mblArrowButtonSelected");
  193. }, 1000);
  194. if(this.back && !this.moveTo && !this.href && history){
  195. history.back();
  196. return;
  197. }
  198. // keep the clicked position for transition animations
  199. var view = this.findCurrentView();
  200. if(view){
  201. view.clickedPosX = e.clientX;
  202. view.clickedPosY = e.clientY;
  203. }
  204. this.goTo(this.moveTo, this.href);
  205. },
  206. goTo: function(moveTo, href){
  207. // summary:
  208. // Given the destination, makes a view transition.
  209. var view = this.findCurrentView();
  210. if(!view){ return; }
  211. if(href){
  212. view.performTransition(null, -1, this.transition, this, function(){location.href = href;});
  213. }else{
  214. if(dm.app && dm.app.STAGE_CONTROLLER_ACTIVE){
  215. // If in a full mobile app, then use its mechanisms to move back a scene
  216. connect.publish("/dojox/mobile/app/goback");
  217. }else{
  218. // Basically transition should be performed between two
  219. // siblings that share the same parent.
  220. // However, when views are nested and transition occurs from
  221. // an inner view, search for an ancestor view that is a sibling
  222. // of the target view, and use it as a source view.
  223. var node = registry.byId(view.convertToId(moveTo));
  224. if(node){
  225. var parent = node.getParent();
  226. while(view){
  227. var myParent = view.getParent();
  228. if(parent === myParent){
  229. break;
  230. }
  231. view = myParent;
  232. }
  233. }
  234. if(view){
  235. view.performTransition(moveTo, -1, this.transition);
  236. }
  237. }
  238. }
  239. }
  240. });
  241. });