pullup.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. define(function(require, exports, module) {
  2. "use strict";
  3. var Util = require('../util');
  4. var Base = require('../base');
  5. var clsPrefix;
  6. var containerCls;
  7. var loadingContent = "Loading...";
  8. var upContent = "Pull Up To Refresh";
  9. var downContent = "Release To Refresh";
  10. var PULL_UP_HEIGHT = 60;
  11. var HEIGHT = 40;
  12. /**
  13. * A pullup to load plugin for xscroll.
  14. * @constructor
  15. * @param {object} cfg
  16. * @param {number} cfg.height
  17. * @param {string} cfg.downContent
  18. * @param {string} cfg.upContent
  19. * @param {string} cfg.loadingContent
  20. * @param {string} cfg.clsPrefix class prefix which default value is "xs-plugin-pullup-"
  21. * @param {number} cfg.bufferHeight preload data before scrolling to the bottom of the boundry
  22. * @extends {Base}
  23. */
  24. var PullUp = function(cfg) {
  25. PullUp.superclass.constructor.call(this);
  26. this.userConfig = Util.mix({
  27. upContent: upContent,
  28. downContent: downContent,
  29. pullUpHeight: PULL_UP_HEIGHT,
  30. height: HEIGHT,
  31. loadingContent: loadingContent,
  32. bufferHeight: 0,
  33. clsPrefix: "xs-plugin-pullup-"
  34. }, cfg);
  35. }
  36. Util.extend(PullUp, Base, {
  37. /**
  38. * a pluginId
  39. * @memberOf PullUp
  40. * @type {string}
  41. */
  42. pluginId: "pullup",
  43. /**
  44. * plugin initializer
  45. * @memberOf PullUp
  46. * @override Base
  47. * @return {PullUp}
  48. */
  49. pluginInitializer: function(xscroll) {
  50. var self = this;
  51. self.xscroll = xscroll.render();
  52. clsPrefix = self.userConfig.clsPrefix;
  53. self.render();
  54. return self;
  55. },
  56. /**
  57. * detroy the plugin
  58. * @memberOf PullUp
  59. * @override Base
  60. * @return {PullUp}
  61. */
  62. pluginDestructor: function() {
  63. var self = this;
  64. Util.remove(self.pullup);
  65. self.xscroll.off("scrollend", self._scrollEndHandler, self);
  66. self.xscroll.off("scroll", self._scrollHandler, self);
  67. self.xscroll.off("pan", self._panHandler, self);
  68. self.xscroll.boundry.resetBottom();
  69. self.__isRender = false;
  70. self._evtBinded = false;
  71. },
  72. /**
  73. * disable the plugin
  74. * @memberOf PullUp
  75. * @override Base
  76. * @return {PullUp}
  77. */
  78. pluginDisable: function() {
  79. var self = this;
  80. self.userConfig.container || Util.remove(self.pullup)
  81. self.xscroll.off("scrollend", self._scrollEndHandler, self);
  82. self.xscroll.off("scroll", self._scrollHandler, self);
  83. self.xscroll.off("pan", self._panHandler, self);
  84. self.xscroll.boundry.resetBottom();
  85. self.__isRender = false;
  86. self._evtBinded = false;
  87. },
  88. /**
  89. * render pullup plugin
  90. * @memberOf PullUp
  91. * @return {PullUp}
  92. */
  93. render: function() {
  94. var self = this;
  95. if (self.__isRender) return;
  96. self.__isRender = true;
  97. if (!self.userConfig.container) {
  98. var containerCls = clsPrefix + "container";
  99. var height = self.userConfig.height;
  100. var pullup = self.pullup = document.createElement("div");
  101. pullup.className = containerCls;
  102. pullup.style.position = "absolute";
  103. pullup.style.width = "100%";
  104. pullup.style.height = height + "px";
  105. pullup.style.bottom = -height + "px";
  106. pullup.style.textAlign = "center";
  107. self.xscroll.container.appendChild(pullup);
  108. Util.addClass(pullup, clsPrefix + self.status);
  109. pullup.innerHTML = self.userConfig[self.status + "Content"] || self.userConfig.content;
  110. } else {
  111. self.pullup = self.userConfig.container
  112. }
  113. self.xscroll.boundry.expandBottom(self.userConfig.height);
  114. self.status = 'up';
  115. self._bindEvt();
  116. return self;
  117. },
  118. _bindEvt: function() {
  119. var self = this;
  120. if (self._evtBinded) return;
  121. self._evtBinded = true;
  122. var pullup = self.pullup;
  123. var xscroll = self.xscroll;
  124. xscroll.on("pan", self._panHandler, self);
  125. //load width a buffer
  126. if (self.userConfig.bufferHeight > 0) {
  127. xscroll.on("scroll", self._scrollHandler, self);
  128. }
  129. //bounce bottom
  130. xscroll.on("scrollend", self._scrollEndHandler, self);
  131. return self;
  132. },
  133. _scrollEndHandler: function(e) {
  134. var self = this,
  135. xscroll = self.xscroll,
  136. scrollTop = xscroll.getScrollTop();
  137. if (scrollTop == xscroll.containerHeight - xscroll.height + self.userConfig.height) {
  138. self._changeStatus("loading");
  139. }
  140. return self;
  141. },
  142. _scrollHandler: function(e) {
  143. var self = this,
  144. xscroll = self.xscroll;
  145. if (!self.isLoading && Math.abs(e.scrollTop) + xscroll.height + self.userConfig.height + self.userConfig.bufferHeight >= xscroll.containerHeight + xscroll.boundry._xtop + xscroll.boundry._xbottom) {
  146. self._changeStatus("loading");
  147. }
  148. return self;
  149. },
  150. _panHandler: function(e) {
  151. var self = this;
  152. var xscroll = self.xscroll;
  153. var offsetTop = -xscroll.getScrollTop();
  154. if (offsetTop < xscroll.height - xscroll.containerHeight - self.userConfig.pullUpHeight) {
  155. self._changeStatus("down")
  156. } else {
  157. self._changeStatus("up");
  158. }
  159. return self;
  160. },
  161. _changeStatus: function(status) {
  162. if (status != "loading" && this.isLoading) return;
  163. var prevVal = this.status;
  164. this.status = status;
  165. if (!this.userConfig.container) {
  166. Util.removeClass(this.pullup, clsPrefix + prevVal)
  167. Util.addClass(this.pullup, clsPrefix + status);
  168. this.pullup.innerHTML = this.userConfig[status + "Content"];
  169. }
  170. if (prevVal != status) {
  171. this.trigger("statuschange", {
  172. prevVal: prevVal,
  173. newVal: status
  174. });
  175. if (status == "loading") {
  176. this.isLoading = true;
  177. this.trigger("loading");
  178. }
  179. }
  180. return this;
  181. },
  182. /**
  183. * notify pullup plugin to complete state after a remote data request
  184. * @memberOf PullUp
  185. * @return {PullUp}
  186. */
  187. complete: function() {
  188. var self = this;
  189. var xscroll = self.xscroll;
  190. self.isLoading = false;
  191. self._changeStatus("up");
  192. return self;
  193. },
  194. stop: function() {
  195. var xscroll = this.xscroll;
  196. this.isLoading = false;
  197. this._changeStatus("stop");
  198. this.pluginDisable()
  199. return this;
  200. },
  201. restart: function() {
  202. var xscroll = this.xscroll;
  203. this.isLoading = false;
  204. this._changeStatus("default");
  205. this.render()
  206. return this;
  207. }
  208. });
  209. if (typeof module == 'object' && module.exports) {
  210. module.exports = PullUp;
  211. }
  212. /** ignored by jsdoc **/
  213. else if (window.XScroll && window.XScroll.Plugins) {
  214. return XScroll.Plugins.PullUp = PullUp;
  215. }
  216. });