ui.scroll_view.native.pull_down.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * DevExtreme (ui/scroll_view/ui.scroll_view.native.pull_down.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 translator = require("../../animation/translator");
  13. var NativeStrategy = require("./ui.scrollable.native");
  14. var LoadIndicator = require("../load_indicator");
  15. var each = require("../../core/utils/iterator").each;
  16. var browser = require("../../core/utils/browser");
  17. var Deferred = require("../../core/utils/deferred").Deferred;
  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 PULLDOWN_RELEASE_TIME = 400;
  29. var PullDownNativeScrollViewStrategy = NativeStrategy.inherit({
  30. _init: function(scrollView) {
  31. this.callBase(scrollView);
  32. this._$topPocket = scrollView._$topPocket;
  33. this._$pullDown = scrollView._$pullDown;
  34. this._$bottomPocket = scrollView._$bottomPocket;
  35. this._$refreshingText = scrollView._$refreshingText;
  36. this._$scrollViewContent = $(scrollView.content());
  37. this._initCallbacks()
  38. },
  39. _initCallbacks: function() {
  40. this.pullDownCallbacks = Callbacks();
  41. this.releaseCallbacks = Callbacks();
  42. this.reachBottomCallbacks = Callbacks()
  43. },
  44. render: function() {
  45. this.callBase();
  46. this._renderPullDown();
  47. this._releaseState()
  48. },
  49. _renderPullDown: function() {
  50. var $image = $("<div>").addClass(SCROLLVIEW_PULLDOWN_IMAGE_CLASS);
  51. var $loadContainer = $("<div>").addClass(SCROLLVIEW_PULLDOWN_INDICATOR_CLASS);
  52. var $loadIndicator = new LoadIndicator($("<div>")).$element();
  53. var $text = this._$pullDownText = $("<div>").addClass(SCROLLVIEW_PULLDOWN_TEXT_CLASS);
  54. this._$pullingDownText = $("<div>").text(this.option("pullingDownText")).appendTo($text);
  55. this._$pulledDownText = $("<div>").text(this.option("pulledDownText")).appendTo($text);
  56. this._$refreshingText = $("<div>").text(this.option("refreshingText")).appendTo($text);
  57. this._$pullDown.empty().append($image).append($loadContainer.append($loadIndicator)).append($text)
  58. },
  59. _releaseState: function() {
  60. this._state = STATE_RELEASED;
  61. this._refreshPullDownText()
  62. },
  63. _pushBackFromBoundary: function() {
  64. if (!this._isLocked() && !this._component.isEmpty()) {
  65. this.callBase()
  66. }
  67. },
  68. _refreshPullDownText: function() {
  69. var that = this;
  70. var pullDownTextItems = [{
  71. element: this._$pullingDownText,
  72. visibleState: STATE_RELEASED
  73. }, {
  74. element: this._$pulledDownText,
  75. visibleState: STATE_READY
  76. }, {
  77. element: this._$refreshingText,
  78. visibleState: STATE_REFRESHING
  79. }];
  80. each(pullDownTextItems, function(_, item) {
  81. var action = that._state === item.visibleState ? "addClass" : "removeClass";
  82. item.element[action](SCROLLVIEW_PULLDOWN_VISIBLE_TEXT_CLASS)
  83. })
  84. },
  85. update: function() {
  86. this.callBase();
  87. this._setTopPocketOffset()
  88. },
  89. _updateDimensions: function() {
  90. this.callBase();
  91. this._topPocketSize = this._$topPocket.height();
  92. this._bottomPocketSize = this._$bottomPocket.height();
  93. if (browser.msie) {
  94. this._scrollOffset = Math.round(100 * (this._$container.height() - this._$content.height())) / 100
  95. } else {
  96. this._scrollOffset = this._$container.height() - this._$content.height()
  97. }
  98. },
  99. _allowedDirections: function() {
  100. var allowedDirections = this.callBase();
  101. allowedDirections.vertical = allowedDirections.vertical || this._pullDownEnabled;
  102. return allowedDirections
  103. },
  104. _setTopPocketOffset: function() {
  105. this._$topPocket.css({
  106. top: -this._topPocketSize
  107. })
  108. },
  109. handleEnd: function() {
  110. this.callBase();
  111. this._complete()
  112. },
  113. handleStop: function() {
  114. this.callBase();
  115. this._complete()
  116. },
  117. _complete: function() {
  118. if (this._state === STATE_READY) {
  119. this._setPullDownOffset(this._topPocketSize);
  120. clearTimeout(this._pullDownRefreshTimeout);
  121. this._pullDownRefreshTimeout = setTimeout(function() {
  122. this._pullDownRefreshing()
  123. }.bind(this), 400)
  124. }
  125. },
  126. _setPullDownOffset: function(offset) {
  127. translator.move(this._$topPocket, {
  128. top: offset
  129. });
  130. translator.move(this._$scrollViewContent, {
  131. top: offset
  132. })
  133. },
  134. handleScroll: function(e) {
  135. this.callBase(e);
  136. if (this._state === STATE_REFRESHING) {
  137. return
  138. }
  139. var currentLocation = this.location().top;
  140. var scrollDelta = (this._location || 0) - currentLocation;
  141. this._location = currentLocation;
  142. if (this._isPullDown()) {
  143. this._pullDownReady()
  144. } else {
  145. if (scrollDelta > 0 && this._isReachBottom()) {
  146. this._reachBottom()
  147. } else {
  148. this._stateReleased()
  149. }
  150. }
  151. },
  152. _isPullDown: function() {
  153. return this._pullDownEnabled && this._location >= this._topPocketSize
  154. },
  155. _isReachBottom: function() {
  156. return this._reachBottomEnabled && this._location - (this._scrollOffset + this._bottomPocketSize) <= .5
  157. },
  158. _reachBottom: function() {
  159. if (this._state === STATE_LOADING) {
  160. return
  161. }
  162. this._state = STATE_LOADING;
  163. this.reachBottomCallbacks.fire()
  164. },
  165. _pullDownReady: function() {
  166. if (this._state === STATE_READY) {
  167. return
  168. }
  169. this._state = STATE_READY;
  170. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  171. this._refreshPullDownText()
  172. },
  173. _stateReleased: function() {
  174. if (this._state === STATE_RELEASED) {
  175. return
  176. }
  177. this._$pullDown.removeClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  178. this._releaseState()
  179. },
  180. _pullDownRefreshing: function() {
  181. if (this._state === STATE_REFRESHING) {
  182. return
  183. }
  184. this._state = STATE_REFRESHING;
  185. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  186. this._refreshPullDownText();
  187. this.pullDownCallbacks.fire()
  188. },
  189. pullDownEnable: function(enabled) {
  190. if (enabled) {
  191. this._updateDimensions();
  192. this._setTopPocketOffset()
  193. }
  194. this._pullDownEnabled = enabled
  195. },
  196. reachBottomEnable: function(enabled) {
  197. this._reachBottomEnabled = enabled
  198. },
  199. pendingRelease: function() {
  200. this._state = STATE_READY
  201. },
  202. release: function() {
  203. var deferred = new Deferred;
  204. this._updateDimensions();
  205. clearTimeout(this._releaseTimeout);
  206. if (this._state === STATE_LOADING) {
  207. this._state = STATE_RELEASED
  208. }
  209. this._releaseTimeout = setTimeout(function() {
  210. this._setPullDownOffset(0);
  211. this._stateReleased();
  212. this.releaseCallbacks.fire();
  213. this._updateAction();
  214. deferred.resolve()
  215. }.bind(this), PULLDOWN_RELEASE_TIME);
  216. return deferred.promise()
  217. },
  218. dispose: function() {
  219. clearTimeout(this._pullDownRefreshTimeout);
  220. clearTimeout(this._releaseTimeout);
  221. this.callBase()
  222. }
  223. });
  224. module.exports = PullDownNativeScrollViewStrategy;