PageRenderTime 22ms CodeModel.GetById 3ms RepoModel.GetById 0ms app.codeStats 0ms

/tsjepublisher/static/qooxdoo/framework/source/class/qx/ui/mobile/container/ScrollComposite.js

http://hackathon.codeplex.com
JavaScript | 345 lines | 157 code | 71 blank | 117 comment | 10 complexity | c0278062899a85e8a72e73f715eb4db1 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-3.0, LGPL-2.1
  1. /* ************************************************************************
  2. qooxdoo - the new era of web development
  3. http://qooxdoo.org
  4. Copyright:
  5. 2004-2011 1&1 Internet AG, Germany, http://www.1und1.de
  6. License:
  7. LGPL: http://www.gnu.org/licenses/lgpl.html
  8. EPL: http://www.eclipse.org/org/documents/epl-v10.php
  9. See the LICENSE file in the project's top-level directory for details.
  10. Authors:
  11. * Christopher Zuendorf (czuendorf)
  12. ************************************************************************ */
  13. /**
  14. * The ScrollComposite is a extension of {@linkqx.ui.mobile.container.Composite},
  15. * and makes it possible to scroll vertically, if content size is greater than
  16. * scrollComposite's size.
  17. *
  18. * Every widget will be added to child's composite.
  19. *
  20. * *Example*
  21. *
  22. * Here is a little example of how to use the widget.
  23. *
  24. * <pre class='javascript'>
  25. * // create the composite
  26. * var scrollComposite = new qx.ui.mobile.container.ScrollComposite();
  27. *
  28. * scrollComposite.setLayout(new qx.ui.mobile.layout.HBox());
  29. *
  30. * // add some children
  31. * scrollComposite.add(new qx.ui.mobile.basic.Label("Name: "), {flex:1});
  32. * scrollComposite.add(new qx.ui.mobile.form.TextField());
  33. *
  34. * this.getRoot().add(scrollComposite);
  35. * </pre>
  36. *
  37. * This example horizontally groups a label and text field by using a
  38. * Composite configured with a horizontal box layout as a container.
  39. */
  40. qx.Class.define("qx.ui.mobile.container.ScrollComposite",
  41. {
  42. extend : qx.ui.mobile.container.Composite,
  43. /*
  44. *****************************************************************************
  45. CONSTRUCTOR
  46. *****************************************************************************
  47. */
  48. /**
  49. * @param layout {qx.ui.mobile.layout.Abstract?null} The layout that should be used for this
  50. * container
  51. */
  52. construct : function(layout)
  53. {
  54. this.base(arguments);
  55. this.__targetOffset = [0,0];
  56. this.__currentOffset = [0,0];
  57. this.__touchStartPoints = [0,0];
  58. this.addCssClass("scrollableBottom");
  59. this.__scrollContainer = new qx.ui.mobile.container.Composite();
  60. this.__scrollContainer.addCssClass("scrollContainerChild");
  61. this.__scrollContainer.addListener("touchstart",this._onTouchStart,this);
  62. this.__scrollContainer.addListener("touchmove",this._onTouchMove,this);
  63. this.__scrollContainer.addListener("touchend",this._onTouchEnd,this);
  64. this._setLayout(new qx.ui.mobile.layout.VBox());
  65. this._add(this.__scrollContainer, {flex:1});
  66. },
  67. /*
  68. *****************************************************************************
  69. PROPERTIES
  70. *****************************************************************************
  71. */
  72. properties :
  73. {
  74. // overridden
  75. defaultCssClass :
  76. {
  77. refine : true,
  78. init : "scrollContainer"
  79. }
  80. },
  81. members :
  82. {
  83. __scrollContainer : null,
  84. __touchStartPoints : null,
  85. __targetOffset : null,
  86. __currentOffset : null,
  87. __scrollTopOnStart : 0,
  88. __targetScrollTop : 0,
  89. /**
  90. * TouchHandler for scrollContainer
  91. * @param evt {qx.event.type.Touch} The touch event
  92. */
  93. _onTouchStart : function(evt){
  94. var touchX = evt.getScreenLeft();
  95. var touchY = evt.getScreenTop();
  96. qx.bom.element.Style.set(this.__scrollContainer.getContainerElement(),"transition-duration","0s");
  97. this.__touchStartPoints[0] = touchX;
  98. this.__touchStartPoints[1] = touchY;
  99. evt.stopPropagation();
  100. },
  101. /**
  102. * Handler for touch move events on scrollContainer
  103. * @param evt {qx.event.type.Touch} The touch event
  104. */
  105. _onTouchMove : function(evt) {
  106. var touchX = evt.getScreenLeft();
  107. var touchY = evt.getScreenTop();
  108. var distanceX = touchX - this.__touchStartPoints[0];
  109. var distanceY = touchY - this.__touchStartPoints[1];
  110. var targetElement = this.__scrollContainer.getContainerElement();
  111. var lowerLimit = targetElement.scrollHeight - targetElement.offsetHeight-4;
  112. // Upper Limit
  113. if(this.__currentOffset[1] >= 0) {
  114. this.removeCssClass("scrollableTop");
  115. } else {
  116. this.addCssClass("scrollableTop");
  117. }
  118. // Lower Limit
  119. if(this.__currentOffset[1] < -lowerLimit) {
  120. this.removeCssClass("scrollableBottom");
  121. } else {
  122. this.addCssClass("scrollableBottom");
  123. }
  124. // X
  125. this.__currentOffset[0] = this.__targetOffset[0] + distanceX;
  126. // Y
  127. this.__currentOffset[1] = this.__targetOffset[1] + distanceY;
  128. this.__scrollContainer.setTranslateY(this.__currentOffset[1]);
  129. evt.stopPropagation();
  130. },
  131. /**
  132. * TouchHandler for scrollContainer
  133. * @param evt {qx.event.type.Touch} The touch event
  134. */
  135. _onTouchEnd : function(evt) {
  136. var targetElement = this.__scrollContainer.getContainerElement();
  137. var lowerLimit = targetElement.scrollHeight - targetElement.offsetHeight-4;
  138. // Upper Limit
  139. if(this.__currentOffset[1] >= 0) {
  140. this.__currentOffset[1] = 0;
  141. }
  142. // Lower Limit
  143. if(this.__currentOffset[1] < -lowerLimit) {
  144. this.__currentOffset[1] = -lowerLimit;
  145. }
  146. qx.bom.element.Style.set(targetElement,"transition-duration",".2s");
  147. this.__scrollContainer.setTranslateY(this.__currentOffset[1]);
  148. this.__targetOffset[0] = this.__currentOffset[0];
  149. this.__targetOffset[1] = this.__currentOffset[1];
  150. evt.stopPropagation();
  151. },
  152. //overridden
  153. add : function(child, options) {
  154. this.__scrollContainer.add(child,options);
  155. this._handleSize(child);
  156. },
  157. // overridden
  158. addAfter : function(child, after, layoutProperties) {
  159. this.__scrollContainer.addAfter(child, after, layoutProperties);
  160. this._handleSize(child);
  161. },
  162. // overridden
  163. addAt : function(child, index, options) {
  164. this.__scrollContainer.addAt(child, index, options);
  165. this._handleSize(child);
  166. },
  167. // overridden
  168. addBefore : function(child, before, layoutProperties) {
  169. this.__scrollContainer.addBefore(child, before, layoutProperties);
  170. this._handleSize(child);
  171. },
  172. // overridden
  173. getChildren : function() {
  174. return this.__scrollContainer.getChildren();
  175. },
  176. // overridden
  177. getLayout : function() {
  178. return this.__scrollContainer.getLayout();
  179. },
  180. // overridden
  181. setLayout : function(layout) {
  182. this.__scrollContainer.setLayout(layout);
  183. },
  184. // overridden
  185. hasChildren : function() {
  186. return this.__scrollContainer.getLayout();
  187. },
  188. indexOf : function(child) {
  189. this.__scrollContainer.indexOf(child);
  190. },
  191. // overridden
  192. remove : function(child) {
  193. this._unhandleSize(child);
  194. this.__scrollContainer.remove(child);
  195. },
  196. // overridden
  197. removeAll : function() {
  198. var children = this.getChildren();
  199. for(var i = 0; i < children.length; i++) {
  200. this._unhandleSize(children[i]);
  201. }
  202. this.__scrollContainer.removeAll();
  203. },
  204. // overridden
  205. removeAt : function(index) {
  206. var children = this.getChildren();
  207. this._unhandleSize(children[index]);
  208. this.__scrollContainer.removeAt(index);
  209. },
  210. /**
  211. * Checks if size handling is needed:
  212. * if true, it adds all listener which are needed for synchronizing the scrollHeight to
  213. * elements height.
  214. * @param child {qx.ui.mobile.core.Widget} target child widget.
  215. */
  216. _handleSize : function(child) {
  217. // If item is a text area, then it needs a special treatment.
  218. // Install listener to the textArea, for syncing the scrollHeight to
  219. // textAreas height.
  220. if(child instanceof qx.ui.mobile.form.TextArea) {
  221. // Check for Listener TODO
  222. child.addListener("appear", this._fixChildElementsHeight, child);
  223. child.addListener("input", this._fixChildElementsHeight, child);
  224. child.addListener("changeValue", this._fixChildElementsHeight, child);
  225. }
  226. },
  227. /**
  228. * Removes Listeners from a child if necessary.
  229. * @param child {qx.ui.mobile.core.Widget} target child widget.
  230. */
  231. _unhandleSize : function(child) {
  232. // If item is a text area, then it needs a special treatment.
  233. // Install listener to the textArea, for syncing the scrollHeight to
  234. // textAreas height.
  235. if(child instanceof qx.ui.mobile.form.TextArea) {
  236. // Check for Listener TODO
  237. child.removeListener("appear", this._fixChildElementsHeight, child);
  238. child.removeListener("input", this._fixChildElementsHeight, child);
  239. child.removeListener("changeValue", this._fixChildElementsHeight, child);
  240. }
  241. },
  242. /**
  243. * Synchronizes the elements.scrollHeight and its height.
  244. * Needed for making textArea scrollable.
  245. * @param evt {qx.event.type.Data} a custom event.
  246. */
  247. _fixChildElementsHeight : function(evt) {
  248. this.getContainerElement().style.height = 'auto';
  249. this.getContainerElement().style.height = this.getContainerElement().scrollHeight+'px';
  250. }
  251. },
  252. /*
  253. *****************************************************************************
  254. DESTRUCTOR
  255. *****************************************************************************
  256. */
  257. destruct : function()
  258. {
  259. this.__scrollContainer.removeListener("touchstart",this._onTouchStart,this);
  260. this.__scrollContainer.removeListener("touchmove",this._onTouchMove,this);
  261. this.__scrollContainer.removeListener("touchend",this._onTouchEnd,this);
  262. var children = this.getChildren();
  263. for(var i = 0; i < children.length; i++) {
  264. this._unhandleSize(children[i]);
  265. }
  266. this._disposeObjects("__scrollContainer");
  267. }
  268. });