ListItem.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. define("dojox/mobile/ListItem", [
  2. "dojo/_base/array",
  3. "dojo/_base/connect",
  4. "dojo/_base/declare",
  5. "dojo/_base/lang",
  6. "dojo/dom-class",
  7. "dojo/dom-construct",
  8. "dojo/has",
  9. "./common",
  10. "./_ItemBase",
  11. "./TransitionEvent"
  12. ], function(array, connect, declare, lang, domClass, domConstruct, has, common, ItemBase, TransitionEvent){
  13. /*=====
  14. var ItemBase = dojox.mobile._ItemBase;
  15. =====*/
  16. // module:
  17. // dojox/mobile/ListItem
  18. // summary:
  19. // An item of either RoundRectList or EdgeToEdgeList.
  20. return declare("dojox.mobile.ListItem", ItemBase, {
  21. // summary:
  22. // An item of either RoundRectList or EdgeToEdgeList.
  23. // description:
  24. // ListItem represents an item of either RoundRectList or
  25. // EdgeToEdgeList. There are three ways to move to a different
  26. // view, moveTo, href, and url. You can choose only one of them.
  27. // rightText: String
  28. // A right-aligned text to display on the item.
  29. rightText: "",
  30. // rightIcon: String
  31. // An icon to display at the right hand side of the item. The value
  32. // can be either a path for an image file or a class name of a DOM
  33. // button.
  34. rightIcon: "",
  35. // rightIcon2: String
  36. // An icon to display at the left of the rightIcon. The value can
  37. // be either a path for an image file or a class name of a DOM
  38. // button.
  39. rightIcon2: "",
  40. // anchorLabel: Boolean
  41. // If true, the label text becomes a clickable anchor text. When
  42. // the user clicks on the text, the onAnchorLabelClicked handler is
  43. // called. You can override or connect to the handler and implement
  44. // any action. The handler has no default action.
  45. anchorLabel: false,
  46. // noArrow: Boolean
  47. // If true, the right hand side arrow is not displayed.
  48. noArrow: false,
  49. // selected: Boolean
  50. // If true, the item is highlighted to indicate it is selected.
  51. selected: false,
  52. // checked: Boolean
  53. // If true, a check mark is displayed at the right of the item.
  54. checked: false,
  55. // arrowClass: String
  56. // An icon to display as an arrow. The value can be either a path
  57. // for an image file or a class name of a DOM button.
  58. arrowClass: "mblDomButtonArrow",
  59. // checkClass: String
  60. // An icon to display as a check mark. The value can be either a
  61. // path for an image file or a class name of a DOM button.
  62. checkClass: "mblDomButtonCheck",
  63. // variableHeight: Boolean
  64. // If true, the height of the item varies according to its
  65. // content. In dojo 1.6 or older, the "mblVariableHeight" class was
  66. // used for this purpose. In dojo 1.7, adding the mblVariableHeight
  67. // class still works for backward compatibility.
  68. variableHeight: false,
  69. // rightIconTitle: String
  70. // An alt text for the right icon.
  71. rightIconTitle: "",
  72. // rightIcon2Title: String
  73. // An alt text for the right icon2.
  74. rightIcon2Title: "",
  75. // btnClass: String
  76. // Deprecated. For backward compatibility.
  77. btnClass: "",
  78. // btnClass2: String
  79. // Deprecated. For backward compatibility.
  80. btnClass2: "",
  81. // tag: String
  82. // A name of html tag to create as domNode.
  83. tag: "li",
  84. postMixInProperties: function(){
  85. // for backward compatibility
  86. if(this.btnClass){
  87. this.rightIcon = this.btnClass;
  88. }
  89. this._setBtnClassAttr = this._setRightIconAttr;
  90. this._setBtnClass2Attr = this._setRightIcon2Attr;
  91. },
  92. buildRendering: function(){
  93. this.domNode = this.srcNodeRef || domConstruct.create(this.tag);
  94. this.inherited(arguments);
  95. this.domNode.className = "mblListItem" + (this.selected ? " mblItemSelected" : "");
  96. // label
  97. var box = this.box = domConstruct.create("DIV");
  98. box.className = "mblListItemTextBox";
  99. if(this.anchorLabel){
  100. box.style.cursor = "pointer";
  101. }
  102. var r = this.srcNodeRef;
  103. if(r && !this.label){
  104. this.label = "";
  105. for(var i = 0, len = r.childNodes.length; i < len; i++){
  106. var n = r.firstChild;
  107. if(n.nodeType === 3 && lang.trim(n.nodeValue) !== ""){
  108. n.nodeValue = this._cv ? this._cv(n.nodeValue) : n.nodeValue;
  109. this.labelNode = domConstruct.create("SPAN", {className:"mblListItemLabel"});
  110. this.labelNode.appendChild(n);
  111. n = this.labelNode;
  112. }
  113. box.appendChild(n);
  114. }
  115. }
  116. if(!this.labelNode){
  117. this.labelNode = domConstruct.create("SPAN", {className:"mblListItemLabel"}, box);
  118. }
  119. if(this.anchorLabel){
  120. box.style.display = "inline"; // to narrow the text region
  121. }
  122. var a = this.anchorNode = domConstruct.create("A");
  123. a.className = "mblListItemAnchor";
  124. this.domNode.appendChild(a);
  125. a.appendChild(box);
  126. },
  127. startup: function(){
  128. if(this._started){ return; }
  129. this.inheritParams();
  130. var parent = this.getParent();
  131. if(this.moveTo || this.href || this.url || this.clickable || (parent && parent.select)){
  132. this._onClickHandle = this.connect(this.anchorNode, "onclick", "onClick");
  133. }
  134. this.setArrow();
  135. if(domClass.contains(this.domNode, "mblVariableHeight")){
  136. this.variableHeight = true;
  137. }
  138. if(this.variableHeight){
  139. domClass.add(this.domNode, "mblVariableHeight");
  140. setTimeout(lang.hitch(this, "layoutVariableHeight"));
  141. }
  142. this.set("icon", this.icon); // _setIconAttr may be called twice but this is necessary for offline instantiation
  143. if(!this.checked && this.checkClass.indexOf(',') !== -1){
  144. this.set("checked", this.checked);
  145. }
  146. this.inherited(arguments);
  147. },
  148. resize: function(){
  149. if(this.variableHeight){
  150. this.layoutVariableHeight();
  151. }
  152. },
  153. onClick: function(e){
  154. var a = e.currentTarget;
  155. var li = a.parentNode;
  156. if(domClass.contains(li, "mblItemSelected")){ return; } // already selected
  157. if(this.anchorLabel){
  158. for(var p = e.target; p.tagName !== this.tag.toUpperCase(); p = p.parentNode){
  159. if(p.className == "mblListItemTextBox"){
  160. domClass.add(p, "mblListItemTextBoxSelected");
  161. setTimeout(function(){
  162. domClass.remove(p, "mblListItemTextBoxSelected");
  163. }, has("android") ? 300 : 1000);
  164. this.onAnchorLabelClicked(e);
  165. return;
  166. }
  167. }
  168. }
  169. var parent = this.getParent();
  170. if(parent.select){
  171. if(parent.select === "single"){
  172. if(!this.checked){
  173. this.set("checked", true);
  174. }
  175. }else if(parent.select === "multiple"){
  176. this.set("checked", !this.checked);
  177. }
  178. }
  179. this.select();
  180. if (this.href && this.hrefTarget) {
  181. common.openWindow(this.href, this.hrefTarget);
  182. return;
  183. }
  184. var transOpts;
  185. if(this.moveTo || this.href || this.url || this.scene){
  186. transOpts = {moveTo: this.moveTo, href: this.href, url: this.url, scene: this.scene, transition: this.transition, transitionDir: this.transitionDir};
  187. }else if(this.transitionOptions){
  188. transOpts = this.transitionOptions;
  189. }
  190. if(transOpts){
  191. this.setTransitionPos(e);
  192. return new TransitionEvent(this.domNode,transOpts,e).dispatch();
  193. }
  194. },
  195. select: function(){
  196. // summary:
  197. // Makes this widget in the selected state.
  198. var parent = this.getParent();
  199. if(parent.stateful){
  200. parent.deselectAll();
  201. }else{
  202. var _this = this;
  203. setTimeout(function(){
  204. _this.deselect();
  205. }, has("android") ? 300 : 1000);
  206. }
  207. domClass.add(this.domNode, "mblItemSelected");
  208. },
  209. deselect: function(){
  210. // summary:
  211. // Makes this widget in the deselected state.
  212. domClass.remove(this.domNode, "mblItemSelected");
  213. },
  214. onAnchorLabelClicked: function(e){
  215. // summary:
  216. // Stub function to connect to from your application.
  217. },
  218. layoutVariableHeight: function(){
  219. var h = this.anchorNode.offsetHeight;
  220. if(h === this.anchorNodeHeight){ return; }
  221. this.anchorNodeHeight = h;
  222. array.forEach([
  223. this.rightTextNode,
  224. this.rightIcon2Node,
  225. this.rightIconNode,
  226. this.iconNode
  227. ], function(n){
  228. if(n){
  229. var t = Math.round((h - n.offsetHeight) / 2);
  230. n.style.marginTop = t + "px";
  231. }
  232. });
  233. },
  234. setArrow: function(){
  235. // summary:
  236. // Sets the arrow icon if necessary.
  237. if(this.checked){ return; }
  238. var c = "";
  239. var parent = this.getParent();
  240. if(this.moveTo || this.href || this.url || this.clickable){
  241. if(!this.noArrow && !(parent && parent.stateful)){
  242. c = this.arrowClass;
  243. }
  244. }
  245. if(c){
  246. this._setRightIconAttr(c);
  247. }
  248. },
  249. _setIconAttr: function(icon){
  250. if(!this.getParent()){ return; } // icon may be invalid because inheritParams is not called yet
  251. this.icon = icon;
  252. var a = this.anchorNode;
  253. if(!this.iconNode){
  254. if(icon){
  255. var ref = this.rightIconNode || this.rightIcon2Node || this.rightTextNode || this.box;
  256. this.iconNode = domConstruct.create("DIV", {className:"mblListItemIcon"}, ref, "before");
  257. }
  258. }else{
  259. domConstruct.empty(this.iconNode);
  260. }
  261. if(icon && icon !== "none"){
  262. common.createIcon(icon, this.iconPos, null, this.alt, this.iconNode);
  263. if(this.iconPos){
  264. domClass.add(this.iconNode.firstChild, "mblListItemSpriteIcon");
  265. }
  266. domClass.remove(a, "mblListItemAnchorNoIcon");
  267. }else{
  268. domClass.add(a, "mblListItemAnchorNoIcon");
  269. }
  270. },
  271. _setCheckedAttr: function(/*Boolean*/checked){
  272. var parent = this.getParent();
  273. if(parent && parent.select === "single" && checked){
  274. array.forEach(parent.getChildren(), function(child){
  275. child.set("checked", false);
  276. });
  277. }
  278. this._setRightIconAttr(this.checkClass);
  279. var icons = this.rightIconNode.childNodes;
  280. if(icons.length === 1){
  281. this.rightIconNode.style.display = checked ? "" : "none";
  282. }else{
  283. icons[0].style.display = checked ? "" : "none";
  284. icons[1].style.display = !checked ? "" : "none";
  285. }
  286. domClass.toggle(this.domNode, "mblListItemChecked", checked);
  287. if(parent && this.checked !== checked){
  288. parent.onCheckStateChanged(this, checked);
  289. }
  290. this.checked = checked;
  291. },
  292. _setRightTextAttr: function(/*String*/text){
  293. if(!this.rightTextNode){
  294. this.rightTextNode = domConstruct.create("DIV", {className:"mblListItemRightText"}, this.box, "before");
  295. }
  296. this.rightText = text;
  297. this.rightTextNode.innerHTML = this._cv ? this._cv(text) : text;
  298. },
  299. _setRightIconAttr: function(/*String*/icon){
  300. if(!this.rightIconNode){
  301. var ref = this.rightIcon2Node || this.rightTextNode || this.box;
  302. this.rightIconNode = domConstruct.create("DIV", {className:"mblListItemRightIcon"}, ref, "before");
  303. }else{
  304. domConstruct.empty(this.rightIconNode);
  305. }
  306. this.rightIcon = icon;
  307. var arr = (icon || "").split(/,/);
  308. if(arr.length === 1){
  309. common.createIcon(icon, null, null, this.rightIconTitle, this.rightIconNode);
  310. }else{
  311. common.createIcon(arr[0], null, null, this.rightIconTitle, this.rightIconNode);
  312. common.createIcon(arr[1], null, null, this.rightIconTitle, this.rightIconNode);
  313. }
  314. },
  315. _setRightIcon2Attr: function(/*String*/icon){
  316. if(!this.rightIcon2Node){
  317. var ref = this.rightTextNode || this.box;
  318. this.rightIcon2Node = domConstruct.create("DIV", {className:"mblListItemRightIcon2"}, ref, "before");
  319. }else{
  320. domConstruct.empty(this.rightIcon2Node);
  321. }
  322. this.rightIcon2 = icon;
  323. common.createIcon(icon, null, null, this.rightIcon2Title, this.rightIcon2Node);
  324. },
  325. _setLabelAttr: function(/*String*/text){
  326. this.label = text;
  327. this.labelNode.innerHTML = this._cv ? this._cv(text) : text;
  328. }
  329. });
  330. });