You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

720 lines
20 KiB

6 days ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. //
  2. // SmoothScroll for websites v1.4.0 (Balazs Galambosi)
  3. // http://www.smoothscroll.net/
  4. //
  5. // Licensed under the terms of the MIT license.
  6. //
  7. // You may use it in your theme if you credit me.
  8. // It is also free to use on any individual website.
  9. //
  10. // Exception:
  11. // The only restriction is to not publish any
  12. // extension for browsers or native application
  13. // without getting a written permission first.
  14. //
  15. (function () {
  16. // Scroll Variables (tweakable)
  17. var defaultOptions = {
  18. // Scrolling Core
  19. frameRate : 150, // [Hz]
  20. animationTime : 400, // [ms]
  21. stepSize : 100, // [px]
  22. // Pulse (less tweakable)
  23. // ratio of "tail" to "acceleration"
  24. pulseAlgorithm : true,
  25. pulseScale : 4,
  26. pulseNormalize : 1,
  27. // Acceleration
  28. accelerationDelta : 50, // 50
  29. accelerationMax : 3, // 3
  30. // Keyboard Settings
  31. keyboardSupport : true, // option
  32. arrowScroll : 50, // [px]
  33. // Other
  34. touchpadSupport : false, // ignore touchpad by default
  35. fixedBackground : true,
  36. excluded : ''
  37. };
  38. var options = defaultOptions;
  39. // Other Variables
  40. var isExcluded = false;
  41. var isFrame = false;
  42. var direction = { x: 0, y: 0 };
  43. var initDone = false;
  44. var root = document.documentElement;
  45. var activeElement;
  46. var observer;
  47. var refreshSize;
  48. var deltaBuffer = [];
  49. var isMac = /^Mac/.test(navigator.platform);
  50. var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32,
  51. pageup: 33, pagedown: 34, end: 35, home: 36 };
  52. /***********************************************
  53. * INITIALIZE
  54. ***********************************************/
  55. /**
  56. * Tests if smooth scrolling is allowed. Shuts down everything if not.
  57. */
  58. function initTest() {
  59. if (options.keyboardSupport) {
  60. addEvent('keydown', keydown);
  61. }
  62. }
  63. /**
  64. * Sets up scrolls array, determines if frames are involved.
  65. */
  66. function init() {
  67. if (initDone || !document.body) return;
  68. initDone = true;
  69. var body = document.body;
  70. var html = document.documentElement;
  71. var windowHeight = window.innerHeight;
  72. var scrollHeight = body.scrollHeight;
  73. // check compat mode for root element
  74. root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
  75. activeElement = body;
  76. initTest();
  77. // Checks if this script is running in a frame
  78. if (top != self) {
  79. isFrame = true;
  80. }
  81. /**
  82. * Please duplicate this radar for a Safari fix!
  83. * rdar://22376037
  84. * https://openradar.appspot.com/radar?id=4965070979203072
  85. *
  86. * Only applies to Safari now, Chrome fixed it in v45:
  87. * This fixes a bug where the areas left and right to
  88. * the content does not trigger the onmousewheel event
  89. * on some pages. e.g.: html, body { height: 100% }
  90. */
  91. else if (scrollHeight > windowHeight &&
  92. (body.offsetHeight <= windowHeight ||
  93. html.offsetHeight <= windowHeight)) {
  94. var fullPageElem = document.createElement('div');
  95. fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' +
  96. 'top:0; left:0; right:0; height:' +
  97. root.scrollHeight + 'px';
  98. document.body.appendChild(fullPageElem);
  99. // DOM changed (throttled) to fix height
  100. var pendingRefresh;
  101. refreshSize = function () {
  102. if (pendingRefresh) return; // could also be: clearTimeout(pendingRefresh);
  103. pendingRefresh = setTimeout(function () {
  104. if (isExcluded) return; // could be running after cleanup
  105. fullPageElem.style.height = '0';
  106. fullPageElem.style.height = root.scrollHeight + 'px';
  107. pendingRefresh = null;
  108. }, 500); // act rarely to stay fast
  109. };
  110. setTimeout(refreshSize, 10);
  111. addEvent('resize', refreshSize);
  112. // TODO: attributeFilter?
  113. var config = {
  114. attributes: true,
  115. childList: true,
  116. characterData: false
  117. // subtree: true
  118. };
  119. observer = new MutationObserver(refreshSize);
  120. observer.observe(body, config);
  121. if (root.offsetHeight <= windowHeight) {
  122. var clearfix = document.createElement('div');
  123. clearfix.style.clear = 'both';
  124. body.appendChild(clearfix);
  125. }
  126. }
  127. // disable fixed background
  128. if (!options.fixedBackground && !isExcluded) {
  129. body.style.backgroundAttachment = 'scroll';
  130. html.style.backgroundAttachment = 'scroll';
  131. }
  132. }
  133. /**
  134. * Removes event listeners and other traces left on the page.
  135. */
  136. function cleanup() {
  137. observer && observer.disconnect();
  138. removeEvent(wheelEvent, wheel);
  139. removeEvent('mousedown', mousedown);
  140. removeEvent('keydown', keydown);
  141. removeEvent('resize', refreshSize);
  142. removeEvent('load', init);
  143. }
  144. /************************************************
  145. * SCROLLING
  146. ************************************************/
  147. var que = [];
  148. var pending = false;
  149. var lastScroll = Date.now();
  150. /**
  151. * Pushes scroll actions to the scrolling queue.
  152. */
  153. function scrollArray(elem, left, top) {
  154. directionCheck(left, top);
  155. if (options.accelerationMax != 1) {
  156. var now = Date.now();
  157. var elapsed = now - lastScroll;
  158. if (elapsed < options.accelerationDelta) {
  159. var factor = (1 + (50 / elapsed)) / 2;
  160. if (factor > 1) {
  161. factor = Math.min(factor, options.accelerationMax);
  162. left *= factor;
  163. top *= factor;
  164. }
  165. }
  166. lastScroll = Date.now();
  167. }
  168. // push a scroll command
  169. que.push({
  170. x: left,
  171. y: top,
  172. lastX: (left < 0) ? 0.99 : -0.99,
  173. lastY: (top < 0) ? 0.99 : -0.99,
  174. start: Date.now()
  175. });
  176. // don't act if there's a pending queue
  177. if (pending) {
  178. return;
  179. }
  180. var scrollWindow = (elem === document.body);
  181. var step = function (time) {
  182. var now = Date.now();
  183. var scrollX = 0;
  184. var scrollY = 0;
  185. for (var i = 0; i < que.length; i++) {
  186. var item = que[i];
  187. var elapsed = now - item.start;
  188. var finished = (elapsed >= options.animationTime);
  189. // scroll position: [0, 1]
  190. var position = (finished) ? 1 : elapsed / options.animationTime;
  191. // easing [optional]
  192. if (options.pulseAlgorithm) {
  193. position = pulse(position);
  194. }
  195. // only need the difference
  196. var x = (item.x * position - item.lastX) >> 0;
  197. var y = (item.y * position - item.lastY) >> 0;
  198. // add this to the total scrolling
  199. scrollX += x;
  200. scrollY += y;
  201. // update last values
  202. item.lastX += x;
  203. item.lastY += y;
  204. // delete and step back if it's over
  205. if (finished) {
  206. que.splice(i, 1); i--;
  207. }
  208. }
  209. // scroll left and top
  210. if (scrollWindow) {
  211. window.scrollBy(scrollX, scrollY);
  212. }
  213. else {
  214. if (scrollX) elem.scrollLeft += scrollX;
  215. if (scrollY) elem.scrollTop += scrollY;
  216. }
  217. // clean up if there's nothing left to do
  218. if (!left && !top) {
  219. que = [];
  220. }
  221. if (que.length) {
  222. requestFrame(step, elem, (1000 / options.frameRate + 1));
  223. } else {
  224. pending = false;
  225. }
  226. };
  227. // start a new queue of actions
  228. requestFrame(step, elem, 0);
  229. pending = true;
  230. }
  231. /***********************************************
  232. * EVENTS
  233. ***********************************************/
  234. /**
  235. * Mouse wheel handler.
  236. * @param {Object} event
  237. */
  238. function wheel(event) {
  239. if (!initDone) {
  240. init();
  241. }
  242. var target = event.target;
  243. var overflowing = overflowingAncestor(target);
  244. // use default if there's no overflowing
  245. // element or default action is prevented
  246. // or it's a zooming event with CTRL
  247. if (!overflowing || event.defaultPrevented || event.ctrlKey) {
  248. return true;
  249. }
  250. // leave embedded content alone (flash & pdf)
  251. if (isNodeName(activeElement, 'embed') ||
  252. (isNodeName(target, 'embed') && /\.pdf/i.test(target.src)) ||
  253. isNodeName(activeElement, 'object')) {
  254. return true;
  255. }
  256. var deltaX = -event.wheelDeltaX || event.deltaX || 0;
  257. var deltaY = -event.wheelDeltaY || event.deltaY || 0;
  258. if (isMac) {
  259. if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) {
  260. deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX));
  261. }
  262. if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) {
  263. deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY));
  264. }
  265. }
  266. // use wheelDelta if deltaX/Y is not available
  267. if (!deltaX && !deltaY) {
  268. deltaY = -event.wheelDelta || 0;
  269. }
  270. // line based scrolling (Firefox mostly)
  271. if (event.deltaMode === 1) {
  272. deltaX *= 40;
  273. deltaY *= 40;
  274. }
  275. // check if it's a touchpad scroll that should be ignored
  276. if (!options.touchpadSupport && isTouchpad(deltaY)) {
  277. return true;
  278. }
  279. // scale by step size
  280. // delta is 120 most of the time
  281. // synaptics seems to send 1 sometimes
  282. if (Math.abs(deltaX) > 1.2) {
  283. deltaX *= options.stepSize / 120;
  284. }
  285. if (Math.abs(deltaY) > 1.2) {
  286. deltaY *= options.stepSize / 120;
  287. }
  288. scrollArray(overflowing, deltaX, deltaY);
  289. event.preventDefault();
  290. scheduleClearCache();
  291. }
  292. /**
  293. * Keydown event handler.
  294. * @param {Object} event
  295. */
  296. function keydown(event) {
  297. var target = event.target;
  298. var modifier = event.ctrlKey || event.altKey || event.metaKey ||
  299. (event.shiftKey && event.keyCode !== key.spacebar);
  300. // our own tracked active element could've been removed from the DOM
  301. if (!document.contains(activeElement)) {
  302. activeElement = document.activeElement;
  303. }
  304. // do nothing if user is editing text
  305. // or using a modifier key (except shift)
  306. // or in a dropdown
  307. // or inside interactive elements
  308. var inputNodeNames = /^(textarea|select|embed|object)$/i;
  309. var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i;
  310. if ( inputNodeNames.test(target.nodeName) ||
  311. isNodeName(target, 'input') && !buttonTypes.test(target.type) ||
  312. isNodeName(activeElement, 'video') ||
  313. isInsideYoutubeVideo(event) ||
  314. target.isContentEditable ||
  315. event.defaultPrevented ||
  316. modifier ) {
  317. return true;
  318. }
  319. // spacebar should trigger button press
  320. if ((isNodeName(target, 'button') ||
  321. isNodeName(target, 'input') && buttonTypes.test(target.type)) &&
  322. event.keyCode === key.spacebar) {
  323. return true;
  324. }
  325. var shift, x = 0, y = 0;
  326. var elem = overflowingAncestor(activeElement);
  327. var clientHeight = elem.clientHeight;
  328. if (elem == document.body) {
  329. clientHeight = window.innerHeight;
  330. }
  331. switch (event.keyCode) {
  332. case key.up:
  333. y = -options.arrowScroll;
  334. break;
  335. case key.down:
  336. y = options.arrowScroll;
  337. break;
  338. case key.spacebar: // (+ shift)
  339. shift = event.shiftKey ? 1 : -1;
  340. y = -shift * clientHeight * 0.9;
  341. break;
  342. case key.pageup:
  343. y = -clientHeight * 0.9;
  344. break;
  345. case key.pagedown:
  346. y = clientHeight * 0.9;
  347. break;
  348. case key.home:
  349. y = -elem.scrollTop;
  350. break;
  351. case key.end:
  352. var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
  353. y = (damt > 0) ? damt+10 : 0;
  354. break;
  355. case key.left:
  356. x = -options.arrowScroll;
  357. break;
  358. case key.right:
  359. x = options.arrowScroll;
  360. break;
  361. default:
  362. return true; // a key we don't care about
  363. }
  364. scrollArray(elem, x, y);
  365. event.preventDefault();
  366. scheduleClearCache();
  367. }
  368. /**
  369. * Mousedown event only for updating activeElement
  370. */
  371. function mousedown(event) {
  372. activeElement = event.target;
  373. }
  374. /***********************************************
  375. * OVERFLOW
  376. ***********************************************/
  377. var uniqueID = (function () {
  378. var i = 0;
  379. return function (el) {
  380. return el.uniqueID || (el.uniqueID = i++);
  381. };
  382. })();
  383. var cache = {}; // cleared out after a scrolling session
  384. var clearCacheTimer;
  385. //setInterval(function () { cache = {}; }, 10 * 1000);
  386. function scheduleClearCache() {
  387. clearTimeout(clearCacheTimer);
  388. clearCacheTimer = setInterval(function () { cache = {}; }, 1*1000);
  389. }
  390. function setCache(elems, overflowing) {
  391. for (var i = elems.length; i--;)
  392. cache[uniqueID(elems[i])] = overflowing;
  393. return overflowing;
  394. }
  395. // (body) (root)
  396. // | hidden | visible | scroll | auto |
  397. // hidden | no | no | YES | YES |
  398. // visible | no | YES | YES | YES |
  399. // scroll | no | YES | YES | YES |
  400. // auto | no | YES | YES | YES |
  401. function overflowingAncestor(el) {
  402. var elems = [];
  403. var body = document.body;
  404. var rootScrollHeight = root.scrollHeight;
  405. do {
  406. var cached = cache[uniqueID(el)];
  407. if (cached) {
  408. return setCache(elems, cached);
  409. }
  410. elems.push(el);
  411. if (rootScrollHeight === el.scrollHeight) {
  412. var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body);
  413. var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root);
  414. if (isFrame && isContentOverflowing(root) ||
  415. !isFrame && isOverflowCSS) {
  416. return setCache(elems, getScrollRoot());
  417. }
  418. } else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) {
  419. return setCache(elems, el);
  420. }
  421. } while (el = el.parentElement);
  422. }
  423. function isContentOverflowing(el) {
  424. return (el.clientHeight + 10 < el.scrollHeight);
  425. }
  426. // typically for <body> and <html>
  427. function overflowNotHidden(el) {
  428. var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
  429. return (overflow !== 'hidden');
  430. }
  431. // for all other elements
  432. function overflowAutoOrScroll(el) {
  433. var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
  434. return (overflow === 'scroll' || overflow === 'auto');
  435. }
  436. /***********************************************
  437. * HELPERS
  438. ***********************************************/
  439. function addEvent(type, fn) {
  440. window.addEventListener(type, fn, false);
  441. }
  442. function removeEvent(type, fn) {
  443. window.removeEventListener(type, fn, false);
  444. }
  445. function isNodeName(el, tag) {
  446. return (el.nodeName||'').toLowerCase() === tag.toLowerCase();
  447. }
  448. function directionCheck(x, y) {
  449. x = (x > 0) ? 1 : -1;
  450. y = (y > 0) ? 1 : -1;
  451. if (direction.x !== x || direction.y !== y) {
  452. direction.x = x;
  453. direction.y = y;
  454. que = [];
  455. lastScroll = 0;
  456. }
  457. }
  458. var deltaBufferTimer;
  459. if (window.localStorage && localStorage.SS_deltaBuffer) {
  460. deltaBuffer = localStorage.SS_deltaBuffer.split(',');
  461. }
  462. function isTouchpad(deltaY) {
  463. if (!deltaY) return;
  464. if (!deltaBuffer.length) {
  465. deltaBuffer = [deltaY, deltaY, deltaY];
  466. }
  467. deltaY = Math.abs(deltaY)
  468. deltaBuffer.push(deltaY);
  469. deltaBuffer.shift();
  470. clearTimeout(deltaBufferTimer);
  471. deltaBufferTimer = setTimeout(function () {
  472. if (window.localStorage) {
  473. localStorage.SS_deltaBuffer = deltaBuffer.join(',');
  474. }
  475. }, 1000);
  476. return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100);
  477. }
  478. function isDivisible(n, divisor) {
  479. return (Math.floor(n / divisor) == n / divisor);
  480. }
  481. function allDeltasDivisableBy(divisor) {
  482. return (isDivisible(deltaBuffer[0], divisor) &&
  483. isDivisible(deltaBuffer[1], divisor) &&
  484. isDivisible(deltaBuffer[2], divisor));
  485. }
  486. function isInsideYoutubeVideo(event) {
  487. var elem = event.target;
  488. var isControl = false;
  489. if (document.URL.indexOf ('www.youtube.com/watch') != -1) {
  490. do {
  491. isControl = (elem.classList &&
  492. elem.classList.contains('html5-video-controls'));
  493. if (isControl) break;
  494. } while (elem = elem.parentNode);
  495. }
  496. return isControl;
  497. }
  498. var requestFrame = (function () {
  499. return (window.requestAnimationFrame ||
  500. window.webkitRequestAnimationFrame ||
  501. window.mozRequestAnimationFrame ||
  502. function (callback, element, delay) {
  503. window.setTimeout(callback, delay || (1000/60));
  504. });
  505. })();
  506. var MutationObserver = (window.MutationObserver ||
  507. window.WebKitMutationObserver ||
  508. window.MozMutationObserver);
  509. var getScrollRoot = (function() {
  510. var SCROLL_ROOT;
  511. return function() {
  512. if (!SCROLL_ROOT) {
  513. var dummy = document.createElement('div');
  514. dummy.style.cssText = 'height:10000px;width:1px;';
  515. document.body.appendChild(dummy);
  516. var bodyScrollTop = document.body.scrollTop;
  517. var docElScrollTop = document.documentElement.scrollTop;
  518. window.scrollBy(0, 3);
  519. if (document.body.scrollTop != bodyScrollTop)
  520. (SCROLL_ROOT = document.body);
  521. else
  522. (SCROLL_ROOT = document.documentElement);
  523. window.scrollBy(0, -3);
  524. document.body.removeChild(dummy);
  525. }
  526. return SCROLL_ROOT;
  527. };
  528. })();
  529. /***********************************************
  530. * PULSE (by Michael Herf)
  531. ***********************************************/
  532. /**
  533. * Viscous fluid with a pulse for part and decay for the rest.
  534. * - Applies a fixed force over an interval (a damped acceleration), and
  535. * - Lets the exponential bleed away the velocity over a longer interval
  536. * - Michael Herf, http://stereopsis.com/stopping/
  537. */
  538. function pulse_(x) {
  539. var val, start, expx;
  540. // test
  541. x = x * options.pulseScale;
  542. if (x < 1) { // acceleartion
  543. val = x - (1 - Math.exp(-x));
  544. } else { // tail
  545. // the previous animation ended here:
  546. start = Math.exp(-1);
  547. // simple viscous drag
  548. x -= 1;
  549. expx = 1 - Math.exp(-x);
  550. val = start + (expx * (1 - start));
  551. }
  552. return val * options.pulseNormalize;
  553. }
  554. function pulse(x) {
  555. if (x >= 1) return 1;
  556. if (x <= 0) return 0;
  557. if (options.pulseNormalize == 1) {
  558. options.pulseNormalize /= pulse_(1);
  559. }
  560. return pulse_(x);
  561. }
  562. /***********************************************
  563. * FIRST RUN
  564. ***********************************************/
  565. var userAgent = window.navigator.userAgent;
  566. var isEdge = /Edge/.test(userAgent); // thank you MS
  567. var isChrome = /chrome/i.test(userAgent) && !isEdge;
  568. var isSafari = /safari/i.test(userAgent) && !isEdge;
  569. var isMobile = /mobile/i.test(userAgent);
  570. var isEnabledForBrowser = (isChrome || isSafari) && !isMobile;
  571. var wheelEvent;
  572. if ('onwheel' in document.createElement('div'))
  573. wheelEvent = 'wheel';
  574. else if ('onmousewheel' in document.createElement('div'))
  575. wheelEvent = 'mousewheel';
  576. if (wheelEvent && isEnabledForBrowser) {
  577. addEvent(wheelEvent, wheel);
  578. addEvent('mousedown', mousedown);
  579. addEvent('load', init);
  580. }
  581. /***********************************************
  582. * PUBLIC INTERFACE
  583. ***********************************************/
  584. function SmoothScroll(optionsToSet) {
  585. for (var key in optionsToSet)
  586. if (defaultOptions.hasOwnProperty(key))
  587. options[key] = optionsToSet[key];
  588. }
  589. SmoothScroll.destroy = cleanup;
  590. if (window.SmoothScrollOptions) // async API
  591. SmoothScroll(window.SmoothScrollOptions)
  592. if (typeof define === 'function' && define.amd)
  593. define(function() {
  594. return SmoothScroll;
  595. });
  596. else if ('object' == typeof exports)
  597. module.exports = SmoothScroll;
  598. else
  599. window.SmoothScroll = SmoothScroll;
  600. })();