ui.scroll_view.native.swipe_down.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * DevExtreme (ui/scroll_view/ui.scroll_view.native.swipe_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 eventUtils = require("../../events/utils");
  14. var NativeStrategy = require("./ui.scrollable.native");
  15. var LoadIndicator = require("../load_indicator");
  16. var Deferred = require("../../core/utils/deferred").Deferred;
  17. var SCROLLVIEW_PULLDOWN_DOWN_LOADING_CLASS = "dx-scrollview-pull-down-loading";
  18. var SCROLLVIEW_PULLDOWN_INDICATOR_CLASS = "dx-scrollview-pull-down-indicator";
  19. var SCROLLVIEW_PULLDOWN_REFRESHING_CLASS = "dx-scrollview-pull-down-refreshing";
  20. var PULLDOWN_ICON_CLASS = "dx-icon-pulldown";
  21. var STATE_RELEASED = 0;
  22. var STATE_READY = 1;
  23. var STATE_REFRESHING = 2;
  24. var STATE_TOUCHED = 4;
  25. var STATE_PULLED = 5;
  26. var SwipeDownNativeScrollViewStrategy = NativeStrategy.inherit({
  27. _init: function(scrollView) {
  28. this.callBase(scrollView);
  29. this._$topPocket = scrollView._$topPocket;
  30. this._$bottomPocket = scrollView._$bottomPocket;
  31. this._$pullDown = scrollView._$pullDown;
  32. this._$scrollViewContent = scrollView.content();
  33. this._initCallbacks();
  34. this._location = 0
  35. },
  36. _initCallbacks: function() {
  37. this.pullDownCallbacks = Callbacks();
  38. this.releaseCallbacks = Callbacks();
  39. this.reachBottomCallbacks = Callbacks()
  40. },
  41. render: function() {
  42. this.callBase();
  43. this._renderPullDown();
  44. this._releaseState()
  45. },
  46. _renderPullDown: function() {
  47. var $loadContainer = $("<div>").addClass(SCROLLVIEW_PULLDOWN_INDICATOR_CLASS);
  48. var $loadIndicator = new LoadIndicator($("<div>")).$element();
  49. this._$icon = $("<div>").addClass(PULLDOWN_ICON_CLASS);
  50. this._$pullDown.empty().append(this._$icon).append($loadContainer.append($loadIndicator))
  51. },
  52. _releaseState: function() {
  53. this._state = STATE_RELEASED;
  54. this._releasePullDown();
  55. this._updateDimensions()
  56. },
  57. _releasePullDown: function() {
  58. this._$pullDown.css({
  59. opacity: 0
  60. })
  61. },
  62. _updateDimensions: function() {
  63. this.callBase();
  64. this._topPocketSize = this._$topPocket.height();
  65. this._bottomPocketSize = this._$bottomPocket.height();
  66. this._scrollOffset = this._$container.height() - this._$content.height()
  67. },
  68. _allowedDirections: function() {
  69. var allowedDirections = this.callBase();
  70. allowedDirections.vertical = allowedDirections.vertical || this._pullDownEnabled;
  71. return allowedDirections
  72. },
  73. handleInit: function(e) {
  74. this.callBase(e);
  75. if (this._state === STATE_RELEASED && 0 === this._location) {
  76. this._startClientY = eventUtils.eventData(e.originalEvent).y;
  77. this._state = STATE_TOUCHED
  78. }
  79. },
  80. handleMove: function(e) {
  81. this.callBase(e);
  82. this._deltaY = eventUtils.eventData(e.originalEvent).y - this._startClientY;
  83. if (this._state === STATE_TOUCHED) {
  84. if (this._pullDownEnabled && this._deltaY > 0) {
  85. this._state = STATE_PULLED
  86. } else {
  87. this._complete()
  88. }
  89. }
  90. if (this._state === STATE_PULLED) {
  91. e.preventDefault();
  92. this._movePullDown()
  93. }
  94. },
  95. _movePullDown: function() {
  96. var pullDownHeight = this._getPullDownHeight();
  97. var top = Math.min(3 * pullDownHeight, this._deltaY + this._getPullDownStartPosition());
  98. var angle = 180 * top / pullDownHeight / 3;
  99. this._$pullDown.css({
  100. opacity: 1
  101. }).toggleClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS, top < pullDownHeight);
  102. translator.move(this._$pullDown, {
  103. top: top
  104. });
  105. this._$icon.css({
  106. transform: "rotate(" + angle + "deg)"
  107. })
  108. },
  109. _isPullDown: function() {
  110. return this._pullDownEnabled && this._state === STATE_PULLED && this._deltaY >= this._getPullDownHeight() - this._getPullDownStartPosition()
  111. },
  112. _getPullDownHeight: function() {
  113. return Math.round(.05 * this._$element.outerHeight())
  114. },
  115. _getPullDownStartPosition: function() {
  116. return -Math.round(1.5 * this._$pullDown.outerHeight())
  117. },
  118. handleEnd: function() {
  119. if (this._isPullDown()) {
  120. this._pullDownRefreshing()
  121. }
  122. this._complete()
  123. },
  124. handleStop: function() {
  125. this._complete()
  126. },
  127. _complete: function() {
  128. if (this._state === STATE_TOUCHED || this._state === STATE_PULLED) {
  129. this._releaseState()
  130. }
  131. },
  132. handleScroll: function(e) {
  133. this.callBase(e);
  134. if (this._state === STATE_REFRESHING) {
  135. return
  136. }
  137. var currentLocation = this.location().top;
  138. var scrollDelta = this._location - currentLocation;
  139. this._location = currentLocation;
  140. if (scrollDelta > 0 && this._isReachBottom()) {
  141. this._reachBottom()
  142. } else {
  143. this._stateReleased()
  144. }
  145. },
  146. _isReachBottom: function() {
  147. return this._reachBottomEnabled && this._location <= this._scrollOffset + this._bottomPocketSize
  148. },
  149. _reachBottom: function() {
  150. this.reachBottomCallbacks.fire()
  151. },
  152. _stateReleased: function() {
  153. if (this._state === STATE_RELEASED) {
  154. return
  155. }
  156. this._$pullDown.removeClass(SCROLLVIEW_PULLDOWN_DOWN_LOADING_CLASS);
  157. this._releaseState()
  158. },
  159. _pullDownRefreshing: function() {
  160. this._state = STATE_REFRESHING;
  161. this._pullDownRefreshHandler()
  162. },
  163. _pullDownRefreshHandler: function() {
  164. this._refreshPullDown();
  165. this.pullDownCallbacks.fire()
  166. },
  167. _refreshPullDown: function() {
  168. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_DOWN_LOADING_CLASS);
  169. translator.move(this._$pullDown, {
  170. top: this._getPullDownHeight()
  171. })
  172. },
  173. pullDownEnable: function(enabled) {
  174. this._$topPocket.toggle(enabled);
  175. this._pullDownEnabled = enabled
  176. },
  177. reachBottomEnable: function(enabled) {
  178. this._reachBottomEnabled = enabled
  179. },
  180. pendingRelease: function() {
  181. this._state = STATE_READY
  182. },
  183. release: function() {
  184. var deferred = new Deferred;
  185. this._updateDimensions();
  186. clearTimeout(this._releaseTimeout);
  187. this._releaseTimeout = setTimeout(function() {
  188. this._stateReleased();
  189. this.releaseCallbacks.fire();
  190. this._updateAction();
  191. deferred.resolve()
  192. }.bind(this), 800);
  193. return deferred.promise()
  194. },
  195. dispose: function() {
  196. clearTimeout(this._pullDownRefreshTimeout);
  197. clearTimeout(this._releaseTimeout);
  198. this.callBase()
  199. }
  200. });
  201. module.exports = SwipeDownNativeScrollViewStrategy;