ui.scroll_view.simulated.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /**
  2. * DevExtreme (ui/scroll_view/ui.scroll_view.simulated.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var $ = require("../../core/renderer");
  11. var Callbacks = require("../../core/utils/callbacks");
  12. var each = require("../../core/utils/iterator").each;
  13. var commonUtils = require("../../core/utils/common");
  14. var extend = require("../../core/utils/extend").extend;
  15. var math = Math;
  16. var simulatedStrategy = require("./ui.scrollable.simulated");
  17. var LoadIndicator = require("../load_indicator");
  18. var SCROLLVIEW_PULLDOWN_REFRESHING_CLASS = "dx-scrollview-pull-down-loading";
  19. var SCROLLVIEW_PULLDOWN_READY_CLASS = "dx-scrollview-pull-down-ready";
  20. var SCROLLVIEW_PULLDOWN_IMAGE_CLASS = "dx-scrollview-pull-down-image";
  21. var SCROLLVIEW_PULLDOWN_INDICATOR_CLASS = "dx-scrollview-pull-down-indicator";
  22. var SCROLLVIEW_PULLDOWN_TEXT_CLASS = "dx-scrollview-pull-down-text";
  23. var SCROLLVIEW_PULLDOWN_VISIBLE_TEXT_CLASS = "dx-scrollview-pull-down-text-visible";
  24. var STATE_RELEASED = 0;
  25. var STATE_READY = 1;
  26. var STATE_REFRESHING = 2;
  27. var STATE_LOADING = 3;
  28. var ScrollViewScroller = simulatedStrategy.Scroller.inherit({
  29. ctor: function() {
  30. this._topPocketSize = 0;
  31. this.callBase.apply(this, arguments);
  32. this._initCallbacks();
  33. this._releaseState()
  34. },
  35. _releaseState: function() {
  36. this._state = STATE_RELEASED;
  37. this._refreshPullDownText()
  38. },
  39. _refreshPullDownText: function() {
  40. var that = this;
  41. var pullDownTextItems = [{
  42. element: this._$pullingDownText,
  43. visibleState: STATE_RELEASED
  44. }, {
  45. element: this._$pulledDownText,
  46. visibleState: STATE_READY
  47. }, {
  48. element: this._$refreshingText,
  49. visibleState: STATE_REFRESHING
  50. }];
  51. each(pullDownTextItems, function(_, item) {
  52. var action = that._state === item.visibleState ? "addClass" : "removeClass";
  53. item.element[action](SCROLLVIEW_PULLDOWN_VISIBLE_TEXT_CLASS)
  54. })
  55. },
  56. _initCallbacks: function() {
  57. this.pullDownCallbacks = Callbacks();
  58. this.releaseCallbacks = Callbacks();
  59. this.reachBottomCallbacks = Callbacks()
  60. },
  61. _updateBounds: function() {
  62. var considerPockets = "horizontal" !== this._direction;
  63. this._topPocketSize = considerPockets ? Math.round(this._$topPocket[this._dimension]()) : 0;
  64. this._bottomPocketSize = considerPockets ? Math.round(this._$bottomPocket[this._dimension]()) : 0;
  65. this.callBase();
  66. this._bottomBound = this._minOffset + this._bottomPocketSize
  67. },
  68. _updateScrollbar: function() {
  69. this._scrollbar.option({
  70. containerSize: this._containerSize(),
  71. contentSize: this._contentSize() - this._topPocketSize - this._bottomPocketSize,
  72. scaleRatio: this._getScaleRatio()
  73. })
  74. },
  75. _moveContent: function() {
  76. this.callBase();
  77. if (this._isPullDown()) {
  78. this._pullDownReady()
  79. } else {
  80. if (this._isReachBottom()) {
  81. this._reachBottomReady()
  82. } else {
  83. if (this._state !== STATE_RELEASED) {
  84. this._stateReleased()
  85. }
  86. }
  87. }
  88. },
  89. _moveScrollbar: function() {
  90. this._scrollbar.moveTo(this._topPocketSize + this._location)
  91. },
  92. _isPullDown: function() {
  93. return this._pullDownEnabled && this._location >= 0
  94. },
  95. _isReachBottom: function() {
  96. return this._reachBottomEnabled && this._location - this._bottomBound <= .5
  97. },
  98. _scrollComplete: function() {
  99. if (this._inBounds() && this._state === STATE_READY) {
  100. this._pullDownRefreshing()
  101. } else {
  102. if (this._inBounds() && this._state === STATE_LOADING) {
  103. this._reachBottomLoading()
  104. } else {
  105. this.callBase()
  106. }
  107. }
  108. },
  109. _reachBottomReady: function() {
  110. if (this._state === STATE_LOADING) {
  111. return
  112. }
  113. this._state = STATE_LOADING;
  114. this._minOffset = this._getMinOffset()
  115. },
  116. _getMaxOffset: function() {
  117. return -this._topPocketSize
  118. },
  119. _getMinOffset: function() {
  120. return math.min(this.callBase(), -this._topPocketSize)
  121. },
  122. _reachBottomLoading: function() {
  123. this.reachBottomCallbacks.fire()
  124. },
  125. _pullDownReady: function() {
  126. if (this._state === STATE_READY) {
  127. return
  128. }
  129. this._state = STATE_READY;
  130. this._maxOffset = 0;
  131. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  132. this._refreshPullDownText()
  133. },
  134. _stateReleased: function() {
  135. if (this._state === STATE_RELEASED) {
  136. return
  137. }
  138. this._releaseState();
  139. this._updateBounds();
  140. this._$pullDown.removeClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  141. this.releaseCallbacks.fire()
  142. },
  143. _pullDownRefreshing: function() {
  144. if (this._state === STATE_REFRESHING) {
  145. return
  146. }
  147. this._state = STATE_REFRESHING;
  148. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  149. this._refreshPullDownText();
  150. this.pullDownCallbacks.fire()
  151. },
  152. _releaseHandler: function() {
  153. if (this._state === STATE_RELEASED) {
  154. this._moveToBounds()
  155. }
  156. this._update();
  157. if (this._releaseTask) {
  158. this._releaseTask.abort()
  159. }
  160. this._releaseTask = commonUtils.executeAsync(this._release.bind(this));
  161. return this._releaseTask.promise
  162. },
  163. _release: function() {
  164. this._stateReleased();
  165. this._scrollComplete()
  166. },
  167. _reachBottomEnablingHandler: function(enabled) {
  168. if (this._reachBottomEnabled === enabled) {
  169. return
  170. }
  171. this._reachBottomEnabled = enabled;
  172. this._updateBounds()
  173. },
  174. _pullDownEnablingHandler: function(enabled) {
  175. if (this._pullDownEnabled === enabled) {
  176. return
  177. }
  178. this._pullDownEnabled = enabled;
  179. this._considerTopPocketChange();
  180. this._updateHandler()
  181. },
  182. _considerTopPocketChange: function() {
  183. this._location -= this._$topPocket.height() || -this._topPocketSize;
  184. this._maxOffset = 0;
  185. this._move()
  186. },
  187. _pendingReleaseHandler: function() {
  188. this._state = STATE_READY
  189. },
  190. dispose: function() {
  191. if (this._releaseTask) {
  192. this._releaseTask.abort()
  193. }
  194. this.callBase()
  195. }
  196. });
  197. var SimulatedScrollViewStrategy = simulatedStrategy.SimulatedStrategy.inherit({
  198. _init: function(scrollView) {
  199. this.callBase(scrollView);
  200. this._$pullDown = scrollView._$pullDown;
  201. this._$topPocket = scrollView._$topPocket;
  202. this._$bottomPocket = scrollView._$bottomPocket;
  203. this._initCallbacks()
  204. },
  205. _initCallbacks: function() {
  206. this.pullDownCallbacks = Callbacks();
  207. this.releaseCallbacks = Callbacks();
  208. this.reachBottomCallbacks = Callbacks()
  209. },
  210. render: function() {
  211. this._renderPullDown();
  212. this.callBase()
  213. },
  214. _renderPullDown: function() {
  215. var $image = $("<div>").addClass(SCROLLVIEW_PULLDOWN_IMAGE_CLASS);
  216. var $loadContainer = $("<div>").addClass(SCROLLVIEW_PULLDOWN_INDICATOR_CLASS);
  217. var $loadIndicator = new LoadIndicator($("<div>")).$element();
  218. var $text = this._$pullDownText = $("<div>").addClass(SCROLLVIEW_PULLDOWN_TEXT_CLASS);
  219. this._$pullingDownText = $("<div>").text(this.option("pullingDownText")).appendTo($text);
  220. this._$pulledDownText = $("<div>").text(this.option("pulledDownText")).appendTo($text);
  221. this._$refreshingText = $("<div>").text(this.option("refreshingText")).appendTo($text);
  222. this._$pullDown.empty().append($image).append($loadContainer.append($loadIndicator)).append($text)
  223. },
  224. pullDownEnable: function(enabled) {
  225. this._eventHandler("pullDownEnabling", enabled)
  226. },
  227. reachBottomEnable: function(enabled) {
  228. this._eventHandler("reachBottomEnabling", enabled)
  229. },
  230. _createScroller: function(direction) {
  231. var that = this;
  232. var scroller = that._scrollers[direction] = new ScrollViewScroller(that._scrollerOptions(direction));
  233. scroller.pullDownCallbacks.add(function() {
  234. that.pullDownCallbacks.fire()
  235. });
  236. scroller.releaseCallbacks.add(function() {
  237. that.releaseCallbacks.fire()
  238. });
  239. scroller.reachBottomCallbacks.add(function() {
  240. that.reachBottomCallbacks.fire()
  241. })
  242. },
  243. _scrollerOptions: function(direction) {
  244. return extend(this.callBase(direction), {
  245. $topPocket: this._$topPocket,
  246. $bottomPocket: this._$bottomPocket,
  247. $pullDown: this._$pullDown,
  248. $pullDownText: this._$pullDownText,
  249. $pullingDownText: this._$pullingDownText,
  250. $pulledDownText: this._$pulledDownText,
  251. $refreshingText: this._$refreshingText
  252. })
  253. },
  254. pendingRelease: function() {
  255. this._eventHandler("pendingRelease")
  256. },
  257. release: function() {
  258. return this._eventHandler("release").done(this._updateAction)
  259. },
  260. location: function location() {
  261. var location = this.callBase();
  262. location.top += this._$topPocket.height();
  263. return location
  264. },
  265. dispose: function() {
  266. each(this._scrollers, function() {
  267. this.dispose()
  268. });
  269. this.callBase()
  270. }
  271. });
  272. module.exports = SimulatedScrollViewStrategy;