observe-dom.esm.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*!
  2. * better-scroll / observe-dom
  3. * (c) 2016-2021 ustbhuangyi
  4. * Released under the MIT License.
  5. */
  6. // ssr support
  7. var inBrowser = typeof window !== 'undefined';
  8. var ua = inBrowser && navigator.userAgent.toLowerCase();
  9. !!(ua && /wechatdevtools/.test(ua));
  10. ua && ua.indexOf('android') > 0;
  11. /* istanbul ignore next */
  12. ((function () {
  13. if (typeof ua === 'string') {
  14. var regex = /os (\d\d?_\d(_\d)?)/;
  15. var matches = regex.exec(ua);
  16. if (!matches)
  17. return false;
  18. var parts = matches[1].split('_').map(function (item) {
  19. return parseInt(item, 10);
  20. });
  21. // ios version >= 13.4 issue 982
  22. return !!(parts[0] === 13 && parts[1] >= 4);
  23. }
  24. return false;
  25. }))();
  26. /* istanbul ignore next */
  27. var supportsPassive = false;
  28. /* istanbul ignore next */
  29. if (inBrowser) {
  30. var EventName = 'test-passive';
  31. try {
  32. var opts = {};
  33. Object.defineProperty(opts, 'passive', {
  34. get: function () {
  35. supportsPassive = true;
  36. },
  37. }); // https://github.com/facebook/flow/issues/285
  38. window.addEventListener(EventName, function () { }, opts);
  39. }
  40. catch (e) { }
  41. }
  42. var elementStyle = (inBrowser &&
  43. document.createElement('div').style);
  44. var vendor = (function () {
  45. /* istanbul ignore if */
  46. if (!inBrowser) {
  47. return false;
  48. }
  49. var transformNames = [
  50. {
  51. key: 'standard',
  52. value: 'transform',
  53. },
  54. {
  55. key: 'webkit',
  56. value: 'webkitTransform',
  57. },
  58. {
  59. key: 'Moz',
  60. value: 'MozTransform',
  61. },
  62. {
  63. key: 'O',
  64. value: 'OTransform',
  65. },
  66. {
  67. key: 'ms',
  68. value: 'msTransform',
  69. },
  70. ];
  71. for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) {
  72. var obj = transformNames_1[_i];
  73. if (elementStyle[obj.value] !== undefined) {
  74. return obj.key;
  75. }
  76. }
  77. /* istanbul ignore next */
  78. return false;
  79. })();
  80. /* istanbul ignore next */
  81. function prefixStyle(style) {
  82. if (vendor === false) {
  83. return style;
  84. }
  85. if (vendor === 'standard') {
  86. if (style === 'transitionEnd') {
  87. return 'transitionend';
  88. }
  89. return style;
  90. }
  91. return vendor + style.charAt(0).toUpperCase() + style.substr(1);
  92. }
  93. vendor && vendor !== 'standard' ? '-' + vendor.toLowerCase() + '-' : '';
  94. var transform = prefixStyle('transform');
  95. var transition = prefixStyle('transition');
  96. inBrowser && prefixStyle('perspective') in elementStyle;
  97. ({
  98. transform: transform,
  99. transition: transition,
  100. transitionTimingFunction: prefixStyle('transitionTimingFunction'),
  101. transitionDuration: prefixStyle('transitionDuration'),
  102. transitionDelay: prefixStyle('transitionDelay'),
  103. transformOrigin: prefixStyle('transformOrigin'),
  104. transitionEnd: prefixStyle('transitionEnd'),
  105. transitionProperty: prefixStyle('transitionProperty'),
  106. });
  107. function getRect(el) {
  108. /* istanbul ignore if */
  109. if (el instanceof window.SVGElement) {
  110. var rect = el.getBoundingClientRect();
  111. return {
  112. top: rect.top,
  113. left: rect.left,
  114. width: rect.width,
  115. height: rect.height,
  116. };
  117. }
  118. else {
  119. return {
  120. top: el.offsetTop,
  121. left: el.offsetLeft,
  122. width: el.offsetWidth,
  123. height: el.offsetHeight,
  124. };
  125. }
  126. }
  127. var ObserveDOM = /** @class */ (function () {
  128. function ObserveDOM(scroll) {
  129. this.scroll = scroll;
  130. this.stopObserver = false;
  131. this.init();
  132. }
  133. ObserveDOM.prototype.init = function () {
  134. this.handleMutationObserver();
  135. this.handleHooks();
  136. };
  137. ObserveDOM.prototype.handleMutationObserver = function () {
  138. var _this = this;
  139. if (typeof MutationObserver !== 'undefined') {
  140. var timer_1 = 0;
  141. this.observer = new MutationObserver(function (mutations) {
  142. _this.mutationObserverHandler(mutations, timer_1);
  143. });
  144. this.startObserve(this.observer);
  145. }
  146. else {
  147. this.checkDOMUpdate();
  148. }
  149. };
  150. ObserveDOM.prototype.handleHooks = function () {
  151. var _this = this;
  152. this.hooksFn = [];
  153. this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.contentChanged, function () {
  154. _this.stopObserve();
  155. // launch a new mutationObserver
  156. _this.handleMutationObserver();
  157. });
  158. this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.enable, function () {
  159. if (_this.stopObserver) {
  160. _this.handleMutationObserver();
  161. }
  162. });
  163. this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.disable, function () {
  164. _this.stopObserve();
  165. });
  166. this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.destroy, function () {
  167. _this.destroy();
  168. });
  169. };
  170. ObserveDOM.prototype.mutationObserverHandler = function (mutations, timer) {
  171. var _this = this;
  172. if (this.shouldNotRefresh()) {
  173. return;
  174. }
  175. var immediateRefresh = false;
  176. var deferredRefresh = false;
  177. for (var i = 0; i < mutations.length; i++) {
  178. var mutation = mutations[i];
  179. if (mutation.type !== 'attributes') {
  180. immediateRefresh = true;
  181. break;
  182. }
  183. else {
  184. if (mutation.target !== this.scroll.scroller.content) {
  185. deferredRefresh = true;
  186. break;
  187. }
  188. }
  189. }
  190. if (immediateRefresh) {
  191. this.scroll.refresh();
  192. }
  193. else if (deferredRefresh) {
  194. // attributes changes too often
  195. clearTimeout(timer);
  196. timer = window.setTimeout(function () {
  197. if (!_this.shouldNotRefresh()) {
  198. _this.scroll.refresh();
  199. }
  200. }, 60);
  201. }
  202. };
  203. ObserveDOM.prototype.startObserve = function (observer) {
  204. var config = {
  205. attributes: true,
  206. childList: true,
  207. subtree: true,
  208. };
  209. observer.observe(this.scroll.scroller.content, config);
  210. };
  211. ObserveDOM.prototype.shouldNotRefresh = function () {
  212. var scroller = this.scroll.scroller;
  213. var scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY;
  214. var outsideBoundaries = scrollBehaviorX.currentPos > scrollBehaviorX.minScrollPos ||
  215. scrollBehaviorX.currentPos < scrollBehaviorX.maxScrollPos ||
  216. scrollBehaviorY.currentPos > scrollBehaviorY.minScrollPos ||
  217. scrollBehaviorY.currentPos < scrollBehaviorY.maxScrollPos;
  218. return scroller.animater.pending || outsideBoundaries;
  219. };
  220. ObserveDOM.prototype.checkDOMUpdate = function () {
  221. var _this = this;
  222. var content = this.scroll.scroller.content;
  223. var contentRect = getRect(content);
  224. var oldWidth = contentRect.width;
  225. var oldHeight = contentRect.height;
  226. var check = function () {
  227. if (_this.stopObserver) {
  228. return;
  229. }
  230. contentRect = getRect(content);
  231. var newWidth = contentRect.width;
  232. var newHeight = contentRect.height;
  233. if (oldWidth !== newWidth || oldHeight !== newHeight) {
  234. _this.scroll.refresh();
  235. }
  236. oldWidth = newWidth;
  237. oldHeight = newHeight;
  238. next();
  239. };
  240. var next = function () {
  241. setTimeout(function () {
  242. check();
  243. }, 1000);
  244. };
  245. next();
  246. };
  247. ObserveDOM.prototype.registerHooks = function (hooks, name, handler) {
  248. hooks.on(name, handler, this);
  249. this.hooksFn.push([hooks, name, handler]);
  250. };
  251. ObserveDOM.prototype.stopObserve = function () {
  252. this.stopObserver = true;
  253. if (this.observer) {
  254. this.observer.disconnect();
  255. }
  256. };
  257. ObserveDOM.prototype.destroy = function () {
  258. this.stopObserve();
  259. this.hooksFn.forEach(function (item) {
  260. var hooks = item[0];
  261. var hooksName = item[1];
  262. var handlerFn = item[2];
  263. hooks.off(hooksName, handlerFn);
  264. });
  265. this.hooksFn.length = 0;
  266. };
  267. ObserveDOM.pluginName = 'observeDOM';
  268. return ObserveDOM;
  269. }());
  270. export default ObserveDOM;