diff --git a/decls/__tests__/coordinate.browser.spec.d.ts b/decls/__tests__/coordinate.browser.spec.d.ts
index cb0ff5c..509db18 100644
--- a/decls/__tests__/coordinate.browser.spec.d.ts
+++ b/decls/__tests__/coordinate.browser.spec.d.ts
@@ -1 +1 @@
-export {};
+export {};
diff --git a/decls/__tests__/fixture.d.ts b/decls/__tests__/fixture.d.ts
index c423f94..9e12cfd 100644
--- a/decls/__tests__/fixture.d.ts
+++ b/decls/__tests__/fixture.d.ts
@@ -1 +1 @@
-export declare const fixture = "\n
\n";
+export declare const fixture = "\n\n";
diff --git a/decls/__tests__/index.browser.spec.d.ts b/decls/__tests__/index.browser.spec.d.ts
index cb0ff5c..509db18 100644
--- a/decls/__tests__/index.browser.spec.d.ts
+++ b/decls/__tests__/index.browser.spec.d.ts
@@ -1 +1 @@
-export {};
+export {};
diff --git a/decls/__tests__/index.node.spec.d.ts b/decls/__tests__/index.node.spec.d.ts
index cb0ff5c..509db18 100644
--- a/decls/__tests__/index.node.spec.d.ts
+++ b/decls/__tests__/index.node.spec.d.ts
@@ -1 +1 @@
-export {};
+export {};
diff --git a/decls/animation/easings.d.ts b/decls/animation/easings.d.ts
index e5466e5..4502ab8 100644
--- a/decls/animation/easings.d.ts
+++ b/decls/animation/easings.d.ts
@@ -1,7 +1,7 @@
-export interface EasingFunction {
- (x: number, t: number, b: number, c: number, d: number, s?: number): number;
-}
-export interface Easings {
- [name: string]: EasingFunction;
-}
-export declare const easings: Easings;
+export interface EasingFunction {
+ (x: number, t: number, b: number, c: number, d: number, s?: number): number;
+}
+export interface Easings {
+ [name: string]: EasingFunction;
+}
+export declare const easings: Easings;
diff --git a/decls/animation/requestAnimationFrame.d.ts b/decls/animation/requestAnimationFrame.d.ts
index 6e62755..a04ddb4 100644
--- a/decls/animation/requestAnimationFrame.d.ts
+++ b/decls/animation/requestAnimationFrame.d.ts
@@ -1,8 +1,8 @@
-export interface RequestAnimationFrame {
- (callback: (time: number) => void): number;
-}
-export interface CancelAnimationFrame {
- (handle: number): void;
-}
-export declare const raf: RequestAnimationFrame;
-export declare const caf: CancelAnimationFrame;
+export interface RequestAnimationFrame {
+ (callback: (time: number) => void): number;
+}
+export interface CancelAnimationFrame {
+ (handle: number): void;
+}
+export declare const raf: RequestAnimationFrame;
+export declare const caf: CancelAnimationFrame;
diff --git a/decls/coordinate.d.ts b/decls/coordinate.d.ts
index 8f754c9..51121b4 100644
--- a/decls/coordinate.d.ts
+++ b/decls/coordinate.d.ts
@@ -1,5 +1,5 @@
-import { Offset } from './dom/offsets';
-export interface Coordinate extends Offset {
- relative: boolean;
-}
-export declare const parseCoordinate: (coordinate: any, enableVertical: boolean) => Coordinate | null;
+import { Offset } from './dom/offsets';
+export interface Coordinate extends Offset {
+ relative: boolean;
+}
+export declare const parseCoordinate: (coordinate: any, enableVertical: boolean) => Coordinate | null;
diff --git a/decls/dom/dimensions.d.ts b/decls/dom/dimensions.d.ts
index 1e08aa4..4b8d561 100644
--- a/decls/dom/dimensions.d.ts
+++ b/decls/dom/dimensions.d.ts
@@ -1,9 +1,10 @@
-export interface Size {
- width: number;
- height: number;
-}
-export declare const getSize: ($el: HTMLElement) => Size;
-export declare const getViewportAndElementSizes: ($el: HTMLElement) => {
- viewport: Size;
- size: Size;
-};
+import { ScrollableElement } from 'src/types';
+export interface Size {
+ width: number;
+ height: number;
+}
+export declare const getSize: ($el: HTMLElement) => Size;
+export declare const getViewportAndElementSizes: ($el: ScrollableElement) => {
+ viewport: Size;
+ size: Size;
+};
diff --git a/decls/dom/events.d.ts b/decls/dom/events.d.ts
index d73452b..d610435 100644
--- a/decls/dom/events.d.ts
+++ b/decls/dom/events.d.ts
@@ -1,5 +1,6 @@
-export interface EventListener {
- (e: Event): void;
-}
-export declare const addEvent: ($el: Element, event: string, listener: EventListener, passive: boolean) => void;
-export declare const removeEvent: ($el: Element, event: string, listener: EventListener, passive: boolean) => void;
+import { ScrollableElement } from '../types';
+export interface EventListener {
+ (e: Event): void;
+}
+export declare const addEvent: ($el: ScrollableElement, event: string, listener: EventListener, passive: boolean) => void;
+export declare const removeEvent: ($el: ScrollableElement, event: string, listener: EventListener, passive: boolean) => void;
diff --git a/decls/dom/offsets.d.ts b/decls/dom/offsets.d.ts
index 5d6d54d..4ddb868 100644
--- a/decls/dom/offsets.d.ts
+++ b/decls/dom/offsets.d.ts
@@ -1,16 +1,15 @@
-export interface Offset {
- top: number;
- left: number;
-}
-export declare type Direction = 'x' | 'y';
-export declare const directionMethodMap: {
- y: string;
- x: string;
-};
-export declare const directionPropMap: {
- y: string;
- x: string;
-};
-export declare const getScroll: ($el: Element, direction: Direction) => number;
-export declare const setScroll: ($el: Element, offset: number, direction: Direction) => void;
-export declare const getOffset: ($el: Element, $context: Element) => Offset;
+import { ScrollableElement } from '../types';
+export interface Offset {
+ top: number;
+ left: number;
+}
+export declare type Direction = 'x' | 'y';
+export declare const directionMethodMap: {
+ [P in Direction]: 'scrollTop' | 'scrollLeft';
+};
+export declare const directionPropMap: {
+ [P in Direction]: 'pageXOffset' | 'pageYOffset';
+};
+export declare const getScroll: ($el: ScrollableElement, direction: Direction) => number;
+export declare const setScroll: ($el: ScrollableElement, offset: number, direction: Direction) => void;
+export declare const getOffset: ($el: Element, $context: ScrollableElement) => Offset;
diff --git a/decls/dom/selectors.d.ts b/decls/dom/selectors.d.ts
index b5d00fa..a8f9cb8 100644
--- a/decls/dom/selectors.d.ts
+++ b/decls/dom/selectors.d.ts
@@ -1,6 +1,7 @@
-import { Direction } from './offsets';
-export declare const $$: (selector: string) => Element[];
-export declare const $: (selector: string) => Element | null;
-export declare const matches: ($el: Element, selector: string | Element) => boolean;
-export declare const isRootContainer: ($el: Element) => boolean;
-export declare const findScrollable: (selectors: string | Element, direction: Direction) => Element | null;
+import { ScrollableElement } from '../types';
+export declare const $$: (selector: string) => Element[];
+export declare const $: (selector: string) => Element | null;
+export declare const isElement: (obj: any) => obj is Element;
+export declare const isWindow: ($el: ScrollableElement) => $el is Window;
+export declare const isRootContainer: ($el: ScrollableElement) => boolean;
+export declare const matches: ($el: Element, selector: string | Element) => boolean;
diff --git a/decls/index.d.ts b/decls/index.d.ts
index f898422..25b8ce9 100644
--- a/decls/index.d.ts
+++ b/decls/index.d.ts
@@ -1,94 +1,95 @@
-import { RequestAnimationFrame, CancelAnimationFrame } from './animation/requestAnimationFrame';
-import { EasingFunction } from './animation/easings';
-import { Offset } from './dom/offsets';
-import { Options, PartialOptions } from './options';
-export { Options, PartialOptions, EasingFunction, Offset, RequestAnimationFrame, CancelAnimationFrame };
-export default class SweetScroll {
- /**
- * You can set Polyfill (or Ponyfill) for browsers that do not support requestAnimationFrame.
- */
- static raf: RequestAnimationFrame;
- static caf: CancelAnimationFrame;
- /**
- * SweetScroll instance factory.
- */
- static create(options?: PartialOptions, container?: string | Element): SweetScroll;
- /**
- * Instance properties.
- */
- private opts;
- private $el;
- private ctx;
- /**
- * Constructor
- */
- constructor(options?: PartialOptions, container?: string | Element);
- /**
- * Scroll animation to the specified position.
- */
- to(distance: any, options?: PartialOptions): void;
- /**
- * Scroll animation to specified left position.
- */
- toTop(distance: any, options?: PartialOptions): void;
- /**
- * Scroll animation to specified top position.
- */
- toLeft(distance: any, options?: PartialOptions): void;
- /**
- * Scroll animation to specified element.
- */
- toElement($element: Element, options?: PartialOptions): void;
- /**
- * Stop the current scroll animation.
- */
- stop(gotoEnd?: boolean): void;
- /**
- * Update options.
- */
- update(options: PartialOptions): void;
- /**
- * Destroy instance.
- */
- destroy(): void;
- /**
- * Callback methods.
- */
- protected onBefore(_: Offset, __: Element | null): boolean | void;
- protected onStep(_: number): void;
- protected onAfter(_: Offset, __: Element | null): void;
- protected onCancel(): void;
- protected onComplete(_: boolean): void;
- /**
- * Start scrolling animation.
- */
- protected start(opts: Options): void;
- /**
- * Handle each frame of the animation.
- */
- protected loop: (time: number) => void;
- /**
- * Handle the completion of scrolling animation.
- */
- protected complete(): void;
- /**
- * Callback function and method call.
- */
- protected hook(options: Options, type: string, ...args: any[]): any;
- /**
- * Bind events of container element.
- */
- protected bind(click: boolean, stop: boolean): void;
- /**
- * Unbind events of container element.
- */
- protected unbind(click: boolean, stop: boolean): void;
- /**
- * Handling of container click event.
- */
- protected handleClick: (e: Event) => void;
- /**
- * Handling of container stop events.
- */
- protected handleStop: (e: Event) => void;
-}
+import { RequestAnimationFrame, CancelAnimationFrame } from './animation/requestAnimationFrame';
+import { EasingFunction } from './animation/easings';
+import { Offset } from './dom/offsets';
+import { Options, PartialOptions } from './options';
+import { ScrollableElement } from './types';
+export { Options, PartialOptions, EasingFunction, Offset, RequestAnimationFrame, CancelAnimationFrame, };
+export default class SweetScroll {
+ /**
+ * You can set Polyfill (or Ponyfill) for browsers that do not support requestAnimationFrame.
+ */
+ static raf: RequestAnimationFrame;
+ static caf: CancelAnimationFrame;
+ /**
+ * SweetScroll instance factory.
+ */
+ static create(options?: PartialOptions, container?: string | ScrollableElement): SweetScroll;
+ /**
+ * Instance properties.
+ */
+ private opts;
+ private $el;
+ private ctx;
+ /**
+ * Constructor
+ */
+ constructor(options?: PartialOptions, container?: string | ScrollableElement);
+ /**
+ * Scroll animation to the specified position.
+ */
+ to(distance: any, options?: PartialOptions): void;
+ /**
+ * Scroll animation to specified left position.
+ */
+ toTop(distance: any, options?: PartialOptions): void;
+ /**
+ * Scroll animation to specified top position.
+ */
+ toLeft(distance: any, options?: PartialOptions): void;
+ /**
+ * Scroll animation to specified element.
+ */
+ toElement($element: Element, options?: PartialOptions): void;
+ /**
+ * Stop the current scroll animation.
+ */
+ stop(gotoEnd?: boolean): void;
+ /**
+ * Update options.
+ */
+ update(options: PartialOptions): void;
+ /**
+ * Destroy instance.
+ */
+ destroy(): void;
+ /**
+ * Callback methods.
+ */
+ protected onBefore(_: Offset, __: Element | null): boolean | void;
+ protected onStep(_: number): void;
+ protected onAfter(_: Offset, __: Element | null): void;
+ protected onCancel(): void;
+ protected onComplete(_: boolean): void;
+ /**
+ * Start scrolling animation.
+ */
+ protected start(opts: Options): void;
+ /**
+ * Handle each frame of the animation.
+ */
+ protected loop: (time: number) => void;
+ /**
+ * Handle the completion of scrolling animation.
+ */
+ protected complete(): void;
+ /**
+ * Callback function and method call.
+ */
+ protected hook(options: Options, type: 'before' | 'after' | 'step' | 'cancel' | 'complete', ...args: any[]): any;
+ /**
+ * Bind events of container element.
+ */
+ protected bind(click: boolean, stop: boolean): void;
+ /**
+ * Unbind events of container element.
+ */
+ protected unbind(click: boolean, stop: boolean): void;
+ /**
+ * Handling of container click event.
+ */
+ protected handleClick: (e: Event) => void;
+ /**
+ * Handling of container stop events.
+ */
+ protected handleStop: (e: Event) => void;
+}
diff --git a/decls/options.d.ts b/decls/options.d.ts
index ef641c2..6215f4b 100644
--- a/decls/options.d.ts
+++ b/decls/options.d.ts
@@ -1,40 +1,39 @@
-import { EasingFunction } from './animation/easings';
-import { Offset } from './dom/offsets';
-import SweetScroll from './index';
-export interface BeforeHandler {
- (offset: Offset, $trigger: Element | null, scroller: SweetScroll): boolean | void;
-}
-export interface AfterHandler {
- (offset: Offset, $trigger: Element | null, scroller: SweetScroll): void;
-}
-export interface StepHandler {
- (time: number, scroller: SweetScroll): void;
-}
-export interface CancelHandler {
- (scroller: SweetScroll): void;
-}
-export interface CompleteHandler {
- (isCancel: boolean, scroller: SweetScroll): void;
-}
-export interface Options {
- trigger: string;
- header: string | Element;
- duration: number;
- easing: string | EasingFunction;
- offset: number;
- vertical: boolean;
- horizontal: boolean;
- cancellable: boolean;
- updateURL: boolean | string;
- preventDefault: boolean;
- stopPropagation: boolean;
- quickMode: boolean;
- before: BeforeHandler | null;
- after: AfterHandler | null;
- step: StepHandler | null;
- cancel: CancelHandler | null;
- complete: CompleteHandler | null;
-}
-export interface PartialOptions extends Partial {
-}
-export declare const defaultOptions: Options;
+import { EasingFunction } from './animation/easings';
+import { Offset } from './dom/offsets';
+import SweetScroll from './index';
+export interface BeforeHandler {
+ (offset: Offset, $trigger: Element | null, scroller: SweetScroll): boolean | void;
+}
+export interface AfterHandler {
+ (offset: Offset, $trigger: Element | null, scroller: SweetScroll): void;
+}
+export interface StepHandler {
+ (time: number, scroller: SweetScroll): void;
+}
+export interface CancelHandler {
+ (scroller: SweetScroll): void;
+}
+export interface CompleteHandler {
+ (isCancel: boolean, scroller: SweetScroll): void;
+}
+export interface Options {
+ trigger: string;
+ header: string | Element;
+ duration: number;
+ easing: string | EasingFunction;
+ offset: number;
+ vertical: boolean;
+ horizontal: boolean;
+ cancellable: boolean;
+ updateURL: boolean | string;
+ preventDefault: boolean;
+ stopPropagation: boolean;
+ before: BeforeHandler | null;
+ after: AfterHandler | null;
+ step: StepHandler | null;
+ cancel: CancelHandler | null;
+ complete: CompleteHandler | null;
+}
+export interface PartialOptions extends Partial {
+}
+export declare const defaultOptions: Options;
diff --git a/decls/utils/__tests__/supports.browser.spec.d.ts b/decls/utils/__tests__/supports.browser.spec.d.ts
index cb0ff5c..509db18 100644
--- a/decls/utils/__tests__/supports.browser.spec.d.ts
+++ b/decls/utils/__tests__/supports.browser.spec.d.ts
@@ -1 +1 @@
-export {};
+export {};
diff --git a/decls/utils/__tests__/supports.node.spec.d.ts b/decls/utils/__tests__/supports.node.spec.d.ts
index cb0ff5c..509db18 100644
--- a/decls/utils/__tests__/supports.node.spec.d.ts
+++ b/decls/utils/__tests__/supports.node.spec.d.ts
@@ -1 +1 @@
-export {};
+export {};
diff --git a/decls/utils/lang.d.ts b/decls/utils/lang.d.ts
index dce3fd0..efa8638 100644
--- a/decls/utils/lang.d.ts
+++ b/decls/utils/lang.d.ts
@@ -1,6 +1,5 @@
-export declare const isString: (obj: any) => obj is string;
-export declare const isFunction: (obj: any) => boolean;
-export declare const isArray: (obj: any) => boolean;
-export declare const isNumeric: (obj: any) => boolean;
-export declare const isElement: (obj: any) => obj is Element;
-export declare const hasProp: (obj: any, key: string) => boolean;
+export declare const isString: (obj: any) => obj is string;
+export declare const isFunction: (obj: any) => boolean;
+export declare const isArray: (obj: any) => obj is any[];
+export declare const isNumeric: (obj: any) => boolean;
+export declare const hasProp: (obj: any, key: string) => boolean;
diff --git a/decls/utils/supports.d.ts b/decls/utils/supports.d.ts
index eb51613..8edf2ca 100644
--- a/decls/utils/supports.d.ts
+++ b/decls/utils/supports.d.ts
@@ -1,3 +1,3 @@
-export declare const canUseDOM: boolean;
-export declare const canUseHistory: boolean;
-export declare const canUsePassiveOption: boolean;
+export declare const canUseDOM: boolean;
+export declare const canUseHistory: boolean;
+export declare const canUsePassiveOption: boolean;
diff --git a/sweet-scroll.d.ts b/sweet-scroll.d.ts
index ff1d71c..89ac340 100644
--- a/sweet-scroll.d.ts
+++ b/sweet-scroll.d.ts
@@ -5,7 +5,8 @@ declare module 'sweet-scroll' {
import { EasingFunction } from 'sweet-scroll/decls/animation/easings';
import { Offset } from 'sweet-scroll/decls/dom/offsets';
import { Options, PartialOptions } from 'sweet-scroll/decls/options';
- export { Options, PartialOptions, EasingFunction, Offset, RequestAnimationFrame, CancelAnimationFrame };
+ import { ScrollableElement } from 'sweet-scroll/decls/types';
+ export { Options, PartialOptions, EasingFunction, Offset, RequestAnimationFrame, CancelAnimationFrame, };
export default class SweetScroll {
/**
* You can set Polyfill (or Ponyfill) for browsers that do not support requestAnimationFrame.
@@ -15,11 +16,11 @@ declare module 'sweet-scroll' {
/**
* SweetScroll instance factory.
*/
- static create(options?: PartialOptions, container?: string | Element): SweetScroll;
+ static create(options?: PartialOptions, container?: string | ScrollableElement): SweetScroll;
/**
* Constructor
*/
- constructor(options?: PartialOptions, container?: string | Element);
+ constructor(options?: PartialOptions, container?: string | ScrollableElement);
/**
* Scroll animation to the specified position.
*/
@@ -71,7 +72,7 @@ declare module 'sweet-scroll' {
/**
* Callback function and method call.
*/
- protected hook(options: Options, type: string, ...args: any[]): any;
+ protected hook(options: Options, type: 'before' | 'after' | 'step' | 'cancel' | 'complete', ...args: any[]): any;
/**
* Bind events of container element.
*/
@@ -113,22 +114,21 @@ declare module 'sweet-scroll/decls/animation/easings' {
}
declare module 'sweet-scroll/decls/dom/offsets' {
+ import { ScrollableElement } from 'sweet-scroll/decls/types';
export interface Offset {
top: number;
left: number;
}
export type Direction = 'x' | 'y';
export const directionMethodMap: {
- y: string;
- x: string;
+ [P in Direction]: 'scrollTop' | 'scrollLeft';
};
export const directionPropMap: {
- y: string;
- x: string;
+ [P in Direction]: 'pageXOffset' | 'pageYOffset';
};
- export const getScroll: ($el: Element, direction: Direction) => number;
- export const setScroll: ($el: Element, offset: number, direction: Direction) => void;
- export const getOffset: ($el: Element, $context: Element) => Offset;
+ export const getScroll: ($el: ScrollableElement, direction: Direction) => number;
+ export const setScroll: ($el: ScrollableElement, offset: number, direction: Direction) => void;
+ export const getOffset: ($el: Element, $context: ScrollableElement) => Offset;
}
declare module 'sweet-scroll/decls/options' {
@@ -162,7 +162,6 @@ declare module 'sweet-scroll/decls/options' {
updateURL: boolean | string;
preventDefault: boolean;
stopPropagation: boolean;
- quickMode: boolean;
before: BeforeHandler | null;
after: AfterHandler | null;
step: StepHandler | null;
@@ -174,3 +173,7 @@ declare module 'sweet-scroll/decls/options' {
export const defaultOptions: Options;
}
+declare module 'sweet-scroll/decls/types' {
+ export type ScrollableElement = Element | Window;
+}
+
diff --git a/sweet-scroll.js b/sweet-scroll.js
index 93b33de..88d140c 100644
--- a/sweet-scroll.js
+++ b/sweet-scroll.js
@@ -1,9 +1,9 @@
-/*! @preserve sweet-scroll v3.0.1 - tsuyoshiwada | MIT License */
+/*! @preserve sweet-scroll v4.0.0 - tsuyoshiwada | MIT License */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
- (global.SweetScroll = factory());
-}(this, (function () { 'use strict';
+ (global = global || self, global.SweetScroll = factory());
+}(this, function () { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
@@ -20,670 +20,671 @@
and limitations under the License.
***************************************************************************** */
- var __assign = Object.assign || function __assign(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
- }
- return t;
+ var __assign = function() {
+ __assign = Object.assign || function __assign(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
};
- // @link https://github.com/JedWatson/exenv/blob/master/index.js
- var canUseDOM = !!(typeof window !== 'undefined' &&
- window.document &&
- window.document.createElement);
- var canUseHistory = !canUseDOM
- ? false
- : (window.history &&
- 'pushState' in window.history &&
- window.location.protocol !== 'file:');
- var canUsePassiveOption = (function () {
- var support = false;
- if (!canUseDOM) {
- return support;
- }
- /* tslint:disable:no-empty */
- try {
- window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
- get: function () {
- support = true;
- },
- }));
- }
- catch (e) { }
- /* tslint:enable */
- return support;
+ // @link https://github.com/JedWatson/exenv/blob/master/index.js
+ var canUseDOM = !!(typeof window !== 'undefined' &&
+ window.document &&
+ window.document.createElement);
+ var canUseHistory = !canUseDOM
+ ? false
+ : window.history && 'pushState' in window.history && window.location.protocol !== 'file:';
+ var canUsePassiveOption = (function () {
+ var support = false;
+ if (!canUseDOM) {
+ return support;
+ }
+ /* tslint:disable:no-empty */
+ try {
+ var win = window;
+ var opts = Object.defineProperty({}, 'passive', {
+ get: function () {
+ support = true;
+ },
+ });
+ win.addEventListener('test', null, opts);
+ win.removeEventListener('test', null, opts);
+ }
+ catch (e) { }
+ /* tslint:enable */
+ return support;
})();
- var isString = function (obj) { return typeof obj === 'string'; };
- var isFunction = function (obj) { return typeof obj === 'function'; };
- var isArray = function (obj) { return Array.isArray(obj); };
- var isNumeric = function (obj) { return !isArray(obj) && ((obj - parseFloat(obj)) + 1) >= 0; };
- var isElement = function (obj) { return obj instanceof Element; };
- var hasProp = function (obj, key) { return (obj && obj.hasOwnProperty(key)); };
+ var isString = function (obj) { return typeof obj === 'string'; };
+ var isFunction = function (obj) { return typeof obj === 'function'; };
+ var isArray = function (obj) { return Array.isArray(obj); };
+ var isNumeric = function (obj) { return !isArray(obj) && obj - parseFloat(obj) + 1 >= 0; };
+ var hasProp = function (obj, key) { return obj && obj.hasOwnProperty(key); };
- var raf = canUseDOM ? window.requestAnimationFrame.bind(window) : null;
- var caf = canUseDOM ? window.cancelAnimationFrame.bind(window) : null;
+ var raf = canUseDOM
+ ? window.requestAnimationFrame.bind(window)
+ : null;
+ var caf = canUseDOM
+ ? window.cancelAnimationFrame.bind(window)
+ : null;
- /* tslint:disable:curly */
- /* tslint:disable:no-conditional-assignment */
- var cos = Math.cos, sin = Math.sin, pow = Math.pow, sqrt = Math.sqrt, PI = Math.PI;
- var easings = {
- linear: function (p) { return p; },
- easeInQuad: function (_, t, b, c, d) { return (c * (t /= d) * t + b); },
- easeOutQuad: function (_, t, b, c, d) { return (-c * (t /= d) * (t - 2) + b); },
- easeInOutQuad: function (_, t, b, c, d) { return ((t /= d / 2) < 1 ? c / 2 * t * t + b : -c / 2 * ((--t) * (t - 2) - 1) + b); },
- easeInCubic: function (_, t, b, c, d) { return (c * (t /= d) * t * t + b); },
- easeOutCubic: function (_, t, b, c, d) { return (c * ((t = t / d - 1) * t * t + 1) + b); },
- easeInOutCubic: function (_, t, b, c, d) { return ((t /= d / 2) < 1 ? c / 2 * t * t * t + b : c / 2 * ((t -= 2) * t * t + 2) + b); },
- easeInQuart: function (_, t, b, c, d) { return (c * (t /= d) * t * t * t + b); },
- easeOutQuart: function (_, t, b, c, d) { return (-c * ((t = t / d - 1) * t * t * t - 1) + b); },
- easeInOutQuart: function (_, t, b, c, d) { return ((t /= d / 2) < 1 ? c / 2 * t * t * t * t + b : -c / 2 * ((t -= 2) * t * t * t - 2) + b); },
- easeInQuint: function (_, t, b, c, d) { return (c * (t /= d) * t * t * t * t + b); },
- easeOutQuint: function (_, t, b, c, d) { return (c * ((t = t / d - 1) * t * t * t * t + 1) + b); },
- easeInOutQuint: function (_, t, b, c, d) { return ((t /= d / 2) < 1 ? c / 2 * t * t * t * t * t + b : c / 2 * ((t -= 2) * t * t * t * t + 2) + b); },
- easeInSine: function (_, t, b, c, d) { return (-c * cos(t / d * (PI / 2)) + c + b); },
- easeOutSine: function (_, t, b, c, d) { return (c * sin(t / d * (PI / 2)) + b); },
- easeInOutSine: function (_, t, b, c, d) { return (-c / 2 * (cos(PI * t / d) - 1) + b); },
- easeInExpo: function (_, t, b, c, d) { return ((t === 0) ? b : c * pow(2, 10 * (t / d - 1)) + b); },
- easeOutExpo: function (_, t, b, c, d) { return ((t === d) ? b + c : c * (-pow(2, -10 * t / d) + 1) + b); },
- easeInOutExpo: function (_, t, b, c, d) {
- if (t === 0)
- return b;
- if (t === d)
- return b + c;
- if ((t /= d / 2) < 1)
- return c / 2 * pow(2, 10 * (t - 1)) + b;
- return c / 2 * (-pow(2, -10 * --t) + 2) + b;
- },
- easeInCirc: function (_, t, b, c, d) { return (-c * (sqrt(1 - (t /= d) * t) - 1) + b); },
- easeOutCirc: function (_, t, b, c, d) { return (c * sqrt(1 - (t = t / d - 1) * t) + b); },
- easeInOutCirc: function (_, t, b, c, d) { return ((t /= d / 2) < 1 ? -c / 2 * (sqrt(1 - t * t) - 1) + b : c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b); },
+ /* tslint:disable:curly */
+ /* tslint:disable:no-conditional-assignment */
+ var cos = Math.cos, sin = Math.sin, pow = Math.pow, sqrt = Math.sqrt, PI = Math.PI;
+ var easings = {
+ linear: function (p) { return p; },
+ easeInQuad: function (_, t, b, c, d) { return c * (t /= d) * t + b; },
+ easeOutQuad: function (_, t, b, c, d) { return -c * (t /= d) * (t - 2) + b; },
+ easeInOutQuad: function (_, t, b, c, d) {
+ return (t /= d / 2) < 1 ? (c / 2) * t * t + b : (-c / 2) * (--t * (t - 2) - 1) + b;
+ },
+ easeInCubic: function (_, t, b, c, d) { return c * (t /= d) * t * t + b; },
+ easeOutCubic: function (_, t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b; },
+ easeInOutCubic: function (_, t, b, c, d) {
+ return (t /= d / 2) < 1 ? (c / 2) * t * t * t + b : (c / 2) * ((t -= 2) * t * t + 2) + b;
+ },
+ easeInQuart: function (_, t, b, c, d) { return c * (t /= d) * t * t * t + b; },
+ easeOutQuart: function (_, t, b, c, d) { return -c * ((t = t / d - 1) * t * t * t - 1) + b; },
+ easeInOutQuart: function (_, t, b, c, d) {
+ return (t /= d / 2) < 1 ? (c / 2) * t * t * t * t + b : (-c / 2) * ((t -= 2) * t * t * t - 2) + b;
+ },
+ easeInQuint: function (_, t, b, c, d) { return c * (t /= d) * t * t * t * t + b; },
+ easeOutQuint: function (_, t, b, c, d) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b; },
+ easeInOutQuint: function (_, t, b, c, d) {
+ return (t /= d / 2) < 1
+ ? (c / 2) * t * t * t * t * t + b
+ : (c / 2) * ((t -= 2) * t * t * t * t + 2) + b;
+ },
+ easeInSine: function (_, t, b, c, d) { return -c * cos((t / d) * (PI / 2)) + c + b; },
+ easeOutSine: function (_, t, b, c, d) { return c * sin((t / d) * (PI / 2)) + b; },
+ easeInOutSine: function (_, t, b, c, d) { return (-c / 2) * (cos((PI * t) / d) - 1) + b; },
+ easeInExpo: function (_, t, b, c, d) { return (t === 0 ? b : c * pow(2, 10 * (t / d - 1)) + b); },
+ easeOutExpo: function (_, t, b, c, d) { return (t === d ? b + c : c * (-pow(2, (-10 * t) / d) + 1) + b); },
+ easeInOutExpo: function (_, t, b, c, d) {
+ if (t === 0)
+ return b;
+ if (t === d)
+ return b + c;
+ if ((t /= d / 2) < 1)
+ return (c / 2) * pow(2, 10 * (t - 1)) + b;
+ return (c / 2) * (-pow(2, -10 * --t) + 2) + b;
+ },
+ easeInCirc: function (_, t, b, c, d) { return -c * (sqrt(1 - (t /= d) * t) - 1) + b; },
+ easeOutCirc: function (_, t, b, c, d) { return c * sqrt(1 - (t = t / d - 1) * t) + b; },
+ easeInOutCirc: function (_, t, b, c, d) {
+ return (t /= d / 2) < 1
+ ? (-c / 2) * (sqrt(1 - t * t) - 1) + b
+ : (c / 2) * (sqrt(1 - (t -= 2) * t) + 1) + b;
+ },
};
- var directionMethodMap = {
- y: 'scrollTop',
- x: 'scrollLeft',
- };
- var directionPropMap = {
- y: 'pageYOffset',
- x: 'pageXOffset',
- };
- var getScroll = function ($el, direction) { return ($el[directionMethodMap[direction]]); };
- var setScroll = function ($el, offset, direction) {
- $el[directionMethodMap[direction]] = offset;
- };
- var getOffset = function ($el, $context) {
- var rect = $el.getBoundingClientRect();
- if (rect.width || rect.height) {
- var scroll_1 = { top: 0, left: 0 };
- var $ctx = void 0;
- if (isRootContainer($context)) {
- $ctx = document.documentElement;
- scroll_1.top = window[directionPropMap.y];
- scroll_1.left = window[directionPropMap.x];
- }
- else {
- $ctx = $context;
- var cRect = $ctx.getBoundingClientRect();
- scroll_1.top = (cRect.top * -1) + $ctx[directionMethodMap.y];
- scroll_1.left = (cRect.left * -1) + $ctx[directionMethodMap.x];
- }
- return {
- top: (rect.top + scroll_1.top) - $ctx.clientTop,
- left: (rect.left + scroll_1.left) - $ctx.clientLeft,
- };
- }
- return rect;
+ var $$ = function (selector) {
+ return Array.prototype.slice.call((!selector ? [] : document.querySelectorAll(selector)));
+ };
+ var $ = function (selector) { return $$(selector).shift() || null; };
+ var isElement = function (obj) { return obj instanceof Element; };
+ var isWindow = function ($el) { return $el === window; };
+ var isRootContainer = function ($el) {
+ return $el === document.documentElement || $el === document.body;
+ };
+ var matches = function ($el, selector) {
+ if (isElement(selector)) {
+ return $el === selector;
+ }
+ var results = $$(selector);
+ var i = results.length;
+ // tslint:disable-next-line no-empty
+ while (--i >= 0 && results[i] !== $el) { }
+ return i > -1;
};
- var $$ = function (selector) { return (Array.prototype.slice.call((!selector ? [] : document.querySelectorAll(selector)))); };
- var $ = function (selector) { return ($$(selector).shift() || null); };
- var matches = function ($el, selector) {
- if (isElement(selector)) {
- return $el === selector;
- }
- var results = $$(selector);
- var i = results.length;
- // tslint:disable-next-line no-empty
- while (--i >= 0 && results[i] !== $el) { }
- return i > -1;
- };
- var isRootContainer = function ($el) { return ($el === document.documentElement || $el === document.body); };
- var findScrollable = function (selectors, direction) {
- var method = directionMethodMap[direction];
- var $elements = isElement(selectors) ? [selectors] : $$(selectors);
- var $div = document.createElement('div');
- for (var i = 0; i < $elements.length; i += 1) {
- var $el = $elements[i];
- var $result = null;
- if ($el[method] > 0) {
- $result = $el;
- }
- else {
- var outerWidth_1 = window.outerWidth, innerWidth_1 = window.innerWidth;
- var zoom = outerWidth_1 ? outerWidth_1 / innerWidth_1 : 1;
- $div.style.width = $el.clientWidth + 1 + "px";
- $div.style.height = $el.clientHeight + 1 + "px";
- $el.appendChild($div);
- $el[method] = Math.max(1, 1.5 / zoom);
- if ($el[method] > 0) {
- $result = $el;
- }
- $el[method] = 0;
- $el.removeChild($div);
- }
- if ($result) {
- return $result;
- }
- }
- return null;
+ var getHeight = function ($el) {
+ return Math.max($el.scrollHeight, $el.clientHeight, $el.offsetHeight);
+ };
+ var getWidth = function ($el) {
+ return Math.max($el.scrollWidth, $el.clientWidth, $el.offsetWidth);
+ };
+ var getSize = function ($el) { return ({
+ width: getWidth($el),
+ height: getHeight($el),
+ }); };
+ var getViewportAndElementSizes = function ($el) {
+ var isRoot = isWindow($el) || isRootContainer($el);
+ return {
+ viewport: {
+ width: isRoot
+ ? Math.min(window.innerWidth, document.documentElement.clientWidth)
+ : $el.clientWidth,
+ height: isRoot ? window.innerHeight : $el.clientHeight,
+ },
+ size: isRoot
+ ? {
+ width: Math.max(getWidth(document.body), getWidth(document.documentElement)),
+ height: Math.max(getHeight(document.body), getHeight(document.documentElement)),
+ }
+ : getSize($el),
+ };
};
- var getHeight = function ($el) { return (Math.max($el.scrollHeight, $el.clientHeight, $el.offsetHeight)); };
- var getWidth = function ($el) { return (Math.max($el.scrollWidth, $el.clientWidth, $el.offsetWidth)); };
- var getSize = function ($el) { return ({
- width: getWidth($el),
- height: getHeight($el),
- }); };
- var getViewportAndElementSizes = function ($el) {
- var isRoot = isRootContainer($el);
- return {
- viewport: {
- width: isRoot
- ? Math.min(window.innerWidth, document.documentElement.clientWidth)
- : $el.clientWidth,
- height: isRoot ? window.innerHeight : $el.clientHeight,
- },
- size: isRoot
- ? {
- width: Math.max(getWidth(document.body), getWidth(document.documentElement)),
- height: Math.max(getHeight(document.body), getHeight(document.documentElement)),
- }
- : getSize($el),
- };
+ var directionMethodMap = {
+ y: 'scrollTop',
+ x: 'scrollLeft',
+ };
+ var directionPropMap = {
+ y: 'pageYOffset',
+ x: 'pageXOffset',
+ };
+ var getScroll = function ($el, direction) {
+ return isWindow($el) ? $el[directionPropMap[direction]] : $el[directionMethodMap[direction]];
+ };
+ var setScroll = function ($el, offset, direction) {
+ if (isWindow($el)) {
+ var top_1 = direction === 'y';
+ $el.scrollTo(!top_1 ? offset : $el.pageXOffset, top_1 ? offset : $el.pageYOffset);
+ }
+ else {
+ $el[directionMethodMap[direction]] = offset;
+ }
+ };
+ var getOffset = function ($el, $context) {
+ var rect = $el.getBoundingClientRect();
+ if (rect.width || rect.height) {
+ var scroll_1 = { top: 0, left: 0 };
+ var $ctx = void 0;
+ if (isWindow($context) || isRootContainer($context)) {
+ $ctx = document.documentElement;
+ scroll_1.top = window[directionPropMap.y];
+ scroll_1.left = window[directionPropMap.x];
+ }
+ else {
+ $ctx = $context;
+ var cRect = $ctx.getBoundingClientRect();
+ scroll_1.top = cRect.top * -1 + $ctx[directionMethodMap.y];
+ scroll_1.left = cRect.left * -1 + $ctx[directionMethodMap.x];
+ }
+ return {
+ top: rect.top + scroll_1.top - $ctx.clientTop,
+ left: rect.left + scroll_1.left - $ctx.clientLeft,
+ };
+ }
+ return rect;
};
- var wheelEventName = (function () {
- if (!canUseDOM) {
- return 'wheel';
- }
- return 'onwheel' in document ? 'wheel' : 'mousewheel';
- })();
- var eventName = function (name) { return (name === 'wheel' ? wheelEventName : name); };
- var apply = function ($el, method, event, listener, passive) {
- event.split(' ').forEach(function (name) {
- $el[method](eventName(name), listener, canUsePassiveOption ? { passive: passive } : false);
- });
- };
- var addEvent = function ($el, event, listener, passive) {
- apply($el, 'addEventListener', event, listener, passive);
- };
- var removeEvent = function ($el, event, listener, passive) {
- apply($el, 'removeEventListener', event, listener, passive);
- };
+ var wheelEventName = (function () {
+ if (!canUseDOM) {
+ return 'wheel';
+ }
+ return 'onwheel' in document ? 'wheel' : 'mousewheel';
+ })();
+ var eventName = function (name) { return (name === 'wheel' ? wheelEventName : name); };
+ var apply = function ($el, method, event, listener, passive) {
+ event.split(' ').forEach(function (name) {
+ $el[method](eventName(name), listener, canUsePassiveOption ? { passive: passive } : false);
+ });
+ };
+ var addEvent = function ($el, event, listener, passive) { return apply($el, 'addEventListener', event, listener, passive); };
+ var removeEvent = function ($el, event, listener, passive) { return apply($el, 'removeEventListener', event, listener, passive); };
- var reRelativeToken = /^(\+|-)=(\d+(?:\.\d+)?)$/;
- var parseCoordinate = function (coordinate, enableVertical) {
- var res = { top: 0, left: 0, relative: false };
- // Object ({ top: {n}, left: {n} })
- if (hasProp(coordinate, 'top') || hasProp(coordinate, 'left')) {
- res = __assign({}, res, coordinate);
- // Array ([{n}, [{n}])
- }
- else if (isArray(coordinate)) {
- if (coordinate.length > 1) {
- res.top = coordinate[0];
- res.left = coordinate[1];
- }
- else if (coordinate.length === 1) {
- res.top = enableVertical ? coordinate[0] : 0;
- res.left = !enableVertical ? coordinate[0] : 0;
- }
- else {
- return null;
- }
- // Number
- }
- else if (isNumeric(coordinate)) {
- if (enableVertical) {
- res.top = coordinate;
- }
- else {
- res.left = coordinate;
- }
- // String ('+={n}', '-={n}')
- }
- else if (isString(coordinate)) {
- var m = coordinate.trim().match(reRelativeToken);
- if (!m) {
- return null;
- }
- var op = m[1];
- var val = parseInt(m[2], 10);
- if (op === '+') {
- res.top = enableVertical ? val : 0;
- res.left = !enableVertical ? val : 0;
- }
- else {
- res.top = enableVertical ? -val : 0;
- res.left = !enableVertical ? -val : 0;
- }
- res.relative = true;
- }
- else {
- return null;
- }
- return res;
+ var reRelativeToken = /^(\+|-)=(\d+(?:\.\d+)?)$/;
+ var parseCoordinate = function (coordinate, enableVertical) {
+ var res = { top: 0, left: 0, relative: false };
+ // Object ({ top: {n}, left: {n} })
+ if (hasProp(coordinate, 'top') || hasProp(coordinate, 'left')) {
+ res = __assign({}, res, coordinate);
+ // Array ([{n}, [{n}])
+ }
+ else if (isArray(coordinate)) {
+ if (coordinate.length > 1) {
+ res.top = coordinate[0];
+ res.left = coordinate[1];
+ }
+ else if (coordinate.length === 1) {
+ res.top = enableVertical ? coordinate[0] : 0;
+ res.left = !enableVertical ? coordinate[0] : 0;
+ }
+ else {
+ return null;
+ }
+ // Number
+ }
+ else if (isNumeric(coordinate)) {
+ if (enableVertical) {
+ res.top = coordinate;
+ }
+ else {
+ res.left = coordinate;
+ }
+ // String ('+={n}', '-={n}')
+ }
+ else if (isString(coordinate)) {
+ var m = coordinate.trim().match(reRelativeToken);
+ if (!m) {
+ return null;
+ }
+ var op = m[1];
+ var val = parseInt(m[2], 10);
+ if (op === '+') {
+ res.top = enableVertical ? val : 0;
+ res.left = !enableVertical ? val : 0;
+ }
+ else {
+ res.top = enableVertical ? -val : 0;
+ res.left = !enableVertical ? -val : 0;
+ }
+ res.relative = true;
+ }
+ else {
+ return null;
+ }
+ return res;
};
- var defaultOptions = {
- trigger: '[data-scroll]',
- header: '[data-scroll-header]',
- duration: 1000,
- easing: 'easeOutQuint',
- offset: 0,
- vertical: true,
- horizontal: false,
- cancellable: true,
- updateURL: false,
- preventDefault: true,
- stopPropagation: true,
- quickMode: false,
- // Callbacks
- before: null,
- after: null,
- cancel: null,
- complete: null,
- step: null,
+ var defaultOptions = {
+ trigger: '[data-scroll]',
+ header: '[data-scroll-header]',
+ duration: 1000,
+ easing: 'easeOutQuint',
+ offset: 0,
+ vertical: true,
+ horizontal: false,
+ cancellable: true,
+ updateURL: false,
+ preventDefault: true,
+ stopPropagation: true,
+ // Callbacks
+ before: null,
+ after: null,
+ cancel: null,
+ complete: null,
+ step: null,
};
- var CONTAINER_CLICK_EVENT = 'click';
- var CONTAINER_STOP_EVENT = 'wheel touchstart touchmove';
- var SweetScroll = /** @class */ (function () {
- /**
- * Constructor
- */
- function SweetScroll(options, container) {
- var _this = this;
- this.ctx = {
- $trigger: null,
- opts: null,
- progress: false,
- pos: null,
- startPos: null,
- easing: null,
- start: 0,
- id: 0,
- cancel: false,
- hash: null,
- };
- /**
- * Handle each frame of the animation.
- */
- this.loop = function (time) {
- var _a = _this, $el = _a.$el, ctx = _a.ctx;
- if (!ctx.start) {
- ctx.start = time;
- }
- if (!ctx.progress || !$el) {
- _this.stop();
- return;
- }
- var options = ctx.opts;
- var offset = ctx.pos;
- var start = ctx.start;
- var startOffset = ctx.startPos;
- var easing = ctx.easing;
- var duration = options.duration;
- var directionMap = { top: 'y', left: 'x' };
- var timeElapsed = time - start;
- var t = Math.min(1, Math.max(timeElapsed / duration, 0));
- Object.keys(offset).forEach(function (key) {
- var value = offset[key];
- var initial = startOffset[key];
- var delta = value - initial;
- if (delta !== 0) {
- var val = easing(t, duration * t, 0, 1, duration);
- setScroll($el, Math.round(initial + delta * val), directionMap[key]);
- }
- });
- if (timeElapsed <= duration) {
- _this.hook(options, 'step', t);
- ctx.id = SweetScroll.raf(_this.loop);
- }
- else {
- _this.stop(true);
- }
- };
- /**
- * Handling of container click event.
- */
- this.handleClick = function (e) {
- var opts = _this.opts;
- var $el = e.target;
- for (; $el && $el !== document; $el = $el.parentNode) {
- if (!matches($el, opts.trigger)) {
- continue;
- }
- var dataOptions = JSON.parse($el.getAttribute('data-scroll-options') || '{}');
- var data = $el.getAttribute('data-scroll');
- var to = data || $el.getAttribute('href');
- var options = __assign({}, opts, dataOptions);
- var preventDefault = options.preventDefault, stopPropagation = options.stopPropagation, vertical = options.vertical, horizontal = options.horizontal;
- if (preventDefault) {
- e.preventDefault();
- }
- if (stopPropagation) {
- e.stopPropagation();
- }
- // Passes the trigger element to callback
- _this.ctx.$trigger = $el;
- if (horizontal && vertical) {
- _this.to(to, options);
- }
- else if (vertical) {
- _this.toTop(to, options);
- }
- else if (horizontal) {
- _this.toLeft(to, options);
- }
- }
- };
- /**
- * Handling of container stop events.
- */
- this.handleStop = function (e) {
- var ctx = _this.ctx;
- var opts = ctx.opts;
- if (opts && opts.cancellable) {
- ctx.cancel = true;
- _this.stop();
- }
- else {
- e.preventDefault();
- }
- };
- var opts = __assign({}, defaultOptions, (options || {}));
- var vertical = opts.vertical, horizontal = opts.horizontal;
- var selector = container === undefined ? 'body,html' : container;
- var $container = null;
- if (canUseDOM) {
- if (vertical) {
- $container = findScrollable(selector, 'y');
- }
- if (!$container && horizontal) {
- $container = findScrollable(selector, 'x');
- }
- }
- if ($container) {
- this.opts = opts;
- this.$el = $container;
- this.bind(true, false);
- }
- }
- /**
- * SweetScroll instance factory.
- */
- SweetScroll.create = function (options, container) {
- return new SweetScroll(options, container);
- };
- /**
- * Scroll animation to the specified position.
- */
- SweetScroll.prototype.to = function (distance, options) {
- if (!canUseDOM) {
- return;
- }
- var _a = this, $el = _a.$el, ctx = _a.ctx, currentOptions = _a.opts;
- var $trigger = ctx.$trigger;
- var opts = __assign({}, currentOptions, options || {});
- var optOffset = opts.offset, vertical = opts.vertical, horizontal = opts.horizontal;
- var $header = isElement(opts.header) ? opts.header : $(opts.header);
- var hash = isString(distance) && /^#/.test(distance) ? distance : null;
- ctx.opts = opts; // Temporary options
- ctx.cancel = false; // Disable the call flag of `cancel`
- ctx.hash = hash;
- // Stop current animation
- this.stop();
- // Does not move if the container is not found
- if (!$el) {
- return;
- }
- // Get scroll offset
- var offset = parseCoordinate(optOffset, vertical);
- var coordinate = parseCoordinate(distance, vertical);
- var scroll = { top: 0, left: 0 };
- if (coordinate) {
- if (coordinate.relative) {
- var current = getScroll($el, vertical ? 'y' : 'x');
- scroll.top = vertical ? current + coordinate.top : coordinate.top;
- scroll.left = !vertical ? current + coordinate.left : coordinate.left;
- }
- else {
- scroll = coordinate;
- }
- }
- else if (isString(distance) && distance !== '#') {
- var $target = $(distance);
- if (!$target) {
- return;
- }
- scroll = getOffset($target, $el);
- }
- if (offset) {
- scroll.top += offset.top;
- scroll.left += offset.left;
- }
- if ($header) {
- scroll.top = Math.max(0, scroll.top - getSize($header).height);
- }
- // Normalize scroll offset
- var _b = getViewportAndElementSizes($el), viewport = _b.viewport, size = _b.size;
- scroll.top = vertical
- ? Math.max(0, Math.min(size.height - viewport.height, scroll.top))
- : getScroll($el, 'y');
- scroll.left = horizontal
- ? Math.max(0, Math.min(size.width - viewport.width, scroll.left))
- : getScroll($el, 'x');
- // Call `before`
- // Stop scrolling when it returns false
- if (this.hook(opts, 'before', scroll, $trigger) === false) {
- ctx.opts = null;
- return;
- }
- // Set offset
- ctx.pos = scroll;
- // Run animation!!
- this.start(opts);
- // Bind stop events
- this.bind(false, true);
- };
- /**
- * Scroll animation to specified left position.
- */
- SweetScroll.prototype.toTop = function (distance, options) {
- this.to(distance, __assign({}, options || {}, { vertical: true, horizontal: false }));
- };
- /**
- * Scroll animation to specified top position.
- */
- SweetScroll.prototype.toLeft = function (distance, options) {
- this.to(distance, __assign({}, options || {}, { vertical: false, horizontal: true }));
- };
- /**
- * Scroll animation to specified element.
- */
- SweetScroll.prototype.toElement = function ($element, options) {
- var $el = this.$el;
- if (!canUseDOM || !$el) {
- return;
- }
- this.to(getOffset($element, $el), options || {});
- };
- /**
- * Stop the current scroll animation.
- */
- SweetScroll.prototype.stop = function (gotoEnd) {
- if (gotoEnd === void 0) { gotoEnd = false; }
- var _a = this, $el = _a.$el, ctx = _a.ctx;
- var pos = ctx.pos;
- if (!$el || !ctx.progress) {
- return;
- }
- SweetScroll.caf(ctx.id);
- ctx.progress = false;
- ctx.start = 0;
- ctx.id = 0;
- if (gotoEnd && pos) {
- setScroll($el, pos.left, 'x');
- setScroll($el, pos.top, 'y');
- }
- this.complete();
- };
- /**
- * Update options.
- */
- SweetScroll.prototype.update = function (options) {
- if (this.$el) {
- var opts = __assign({}, this.opts, options);
- this.stop();
- this.unbind(true, true);
- this.opts = opts;
- this.bind(true, false);
- }
- };
- /**
- * Destroy instance.
- */
- SweetScroll.prototype.destroy = function () {
- if (this.$el) {
- this.stop();
- this.unbind(true, true);
- this.$el = null;
- }
- };
- /**
- * Callback methods.
- */
- /* tslint:disable:no-empty */
- SweetScroll.prototype.onBefore = function (_, __) { return true; };
- SweetScroll.prototype.onStep = function (_) { };
- SweetScroll.prototype.onAfter = function (_, __) { };
- SweetScroll.prototype.onCancel = function () { };
- SweetScroll.prototype.onComplete = function (_) { };
- /* tslint:enable */
- /**
- * Start scrolling animation.
- */
- SweetScroll.prototype.start = function (opts) {
- var ctx = this.ctx;
- ctx.opts = opts;
- ctx.progress = true;
- ctx.easing = isFunction(opts.easing)
- ? opts.easing
- : easings[opts.easing];
- // Update start offset.
- var $container = this.$el;
- var offset = ctx.pos;
- var start = {
- top: getScroll($container, 'y'),
- left: getScroll($container, 'x'),
- };
- if (opts.quickMode) {
- var _a = getViewportAndElementSizes($container).viewport, width = _a.width, height = _a.height;
- if (Math.abs(start.top - offset.top) > height) {
- start.top = start.top > offset.top ? offset.top + height : offset.top - height;
- }
- if (Math.abs(start.left - offset.left) > width) {
- start.left = start.left > offset.left ? offset.left + width : offset.left - width;
- }
- }
- ctx.startPos = start;
- // Loop
- ctx.id = SweetScroll.raf(this.loop);
- };
- /**
- * Handle the completion of scrolling animation.
- */
- SweetScroll.prototype.complete = function () {
- var _a = this, $el = _a.$el, ctx = _a.ctx;
- var hash = ctx.hash, cancel = ctx.cancel, opts = ctx.opts, pos = ctx.pos, $trigger = ctx.$trigger;
- if (!$el || !opts) {
- return;
- }
- if (hash != null && hash !== window.location.hash) {
- var updateURL = opts.updateURL;
- if (canUseDOM && canUseHistory && updateURL !== false) {
- window.history[updateURL === 'replace' ? 'replaceState' : 'pushState'](null, '', hash);
- }
- }
- this.unbind(false, true);
- ctx.opts = null;
- ctx.$trigger = null;
- if (cancel) {
- this.hook(opts, 'cancel');
- }
- else {
- this.hook(opts, 'after', pos, $trigger);
- }
- this.hook(opts, 'complete', cancel);
- };
- /**
- * Callback function and method call.
- */
- SweetScroll.prototype.hook = function (options, type) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- var callback = options[type];
- var callbackResult;
- var methodResult;
- // callback
- if (isFunction(callback)) {
- callbackResult = callback.apply(this, args.concat([this]));
- }
- // method
- methodResult = this["on" + (type[0].toUpperCase() + type.slice(1))].apply(this, args);
- return callbackResult !== undefined ? callbackResult : methodResult;
- };
- /**
- * Bind events of container element.
- */
- SweetScroll.prototype.bind = function (click, stop) {
- var _a = this, $el = _a.$el, opts = _a.ctx.opts;
- if ($el) {
- if (click) {
- addEvent($el, CONTAINER_CLICK_EVENT, this.handleClick, false);
- }
- if (stop) {
- addEvent($el, CONTAINER_STOP_EVENT, this.handleStop, opts ? opts.cancellable : true);
- }
- }
- };
- /**
- * Unbind events of container element.
- */
- SweetScroll.prototype.unbind = function (click, stop) {
- var _a = this, $el = _a.$el, opts = _a.ctx.opts;
- if ($el) {
- if (click) {
- removeEvent($el, CONTAINER_CLICK_EVENT, this.handleClick, false);
- }
- if (stop) {
- removeEvent($el, CONTAINER_STOP_EVENT, this.handleStop, opts ? opts.cancellable : true);
- }
- }
- };
- /**
- * You can set Polyfill (or Ponyfill) for browsers that do not support requestAnimationFrame.
- */
- SweetScroll.raf = raf;
- SweetScroll.caf = caf;
- return SweetScroll;
+ var CONTAINER_CLICK_EVENT = 'click';
+ var CONTAINER_STOP_EVENT = 'wheel touchstart touchmove';
+ var SweetScroll = /** @class */ (function () {
+ /**
+ * Constructor
+ */
+ function SweetScroll(options, container) {
+ var _this = this;
+ this.$el = null;
+ this.ctx = {
+ $trigger: null,
+ opts: null,
+ progress: false,
+ pos: null,
+ startPos: null,
+ easing: null,
+ start: 0,
+ id: 0,
+ cancel: false,
+ hash: null,
+ };
+ /**
+ * Handle each frame of the animation.
+ */
+ this.loop = function (time) {
+ var _a = _this, $el = _a.$el, ctx = _a.ctx;
+ if (!ctx.start) {
+ ctx.start = time;
+ }
+ if (!ctx.progress || !$el) {
+ _this.stop();
+ return;
+ }
+ var options = ctx.opts;
+ var offset = ctx.pos;
+ var start = ctx.start;
+ var startOffset = ctx.startPos;
+ var easing = ctx.easing;
+ var duration = options.duration;
+ var directionMap = { top: 'y', left: 'x' };
+ var timeElapsed = time - start;
+ var t = Math.min(1, Math.max(timeElapsed / duration, 0));
+ Object.keys(offset).forEach(function (key) {
+ var value = offset[key];
+ var initial = startOffset[key];
+ var delta = value - initial;
+ if (delta !== 0) {
+ var val = easing(t, duration * t, 0, 1, duration);
+ setScroll($el, Math.round(initial + delta * val), directionMap[key]);
+ }
+ });
+ if (timeElapsed <= duration) {
+ _this.hook(options, 'step', t);
+ ctx.id = SweetScroll.raf(_this.loop);
+ }
+ else {
+ _this.stop(true);
+ }
+ };
+ /**
+ * Handling of container click event.
+ */
+ this.handleClick = function (e) {
+ var opts = _this.opts;
+ var $el = e.target;
+ for (; $el && $el !== document; $el = $el.parentNode) {
+ if (!matches($el, opts.trigger)) {
+ continue;
+ }
+ var dataOptions = JSON.parse($el.getAttribute('data-scroll-options') || '{}');
+ var data = $el.getAttribute('data-scroll');
+ var to = data || $el.getAttribute('href');
+ var options = __assign({}, opts, dataOptions);
+ var preventDefault = options.preventDefault, stopPropagation = options.stopPropagation, vertical = options.vertical, horizontal = options.horizontal;
+ if (preventDefault) {
+ e.preventDefault();
+ }
+ if (stopPropagation) {
+ e.stopPropagation();
+ }
+ // Passes the trigger element to callback
+ _this.ctx.$trigger = $el;
+ if (horizontal && vertical) {
+ _this.to(to, options);
+ }
+ else if (vertical) {
+ _this.toTop(to, options);
+ }
+ else if (horizontal) {
+ _this.toLeft(to, options);
+ }
+ break;
+ }
+ };
+ /**
+ * Handling of container stop events.
+ */
+ this.handleStop = function (e) {
+ var ctx = _this.ctx;
+ var opts = ctx.opts;
+ if (opts && opts.cancellable) {
+ ctx.cancel = true;
+ _this.stop();
+ }
+ else {
+ e.preventDefault();
+ }
+ };
+ this.opts = __assign({}, defaultOptions, (options || {}));
+ var $container = null;
+ if (canUseDOM) {
+ if (typeof container === 'string') {
+ $container = $(container);
+ }
+ else if (container != null) {
+ $container = container;
+ }
+ else {
+ $container = window;
+ }
+ }
+ this.$el = $container;
+ if ($container) {
+ this.bind(true, false);
+ }
+ }
+ /**
+ * SweetScroll instance factory.
+ */
+ SweetScroll.create = function (options, container) {
+ return new SweetScroll(options, container);
+ };
+ /**
+ * Scroll animation to the specified position.
+ */
+ SweetScroll.prototype.to = function (distance, options) {
+ if (!canUseDOM) {
+ return;
+ }
+ var _a = this, $el = _a.$el, ctx = _a.ctx, currentOptions = _a.opts;
+ var $trigger = ctx.$trigger;
+ var opts = __assign({}, currentOptions, (options || {}));
+ var optOffset = opts.offset, vertical = opts.vertical, horizontal = opts.horizontal;
+ var $header = isElement(opts.header) ? opts.header : $(opts.header);
+ var reg = /^#/;
+ var hash = isString(distance) && reg.test(distance) ? distance : null;
+ ctx.opts = opts; // Temporary options
+ ctx.cancel = false; // Disable the call flag of `cancel`
+ ctx.hash = hash;
+ // Stop current animation
+ this.stop();
+ // Does not move if the container is not found
+ if (!$el) {
+ return;
+ }
+ // Get scroll offset
+ var offset = parseCoordinate(optOffset, vertical);
+ var coordinate = parseCoordinate(distance, vertical);
+ var scroll = { top: 0, left: 0 };
+ if (coordinate) {
+ if (coordinate.relative) {
+ var current = getScroll($el, vertical ? 'y' : 'x');
+ scroll.top = vertical ? current + coordinate.top : coordinate.top;
+ scroll.left = !vertical ? current + coordinate.left : coordinate.left;
+ }
+ else {
+ scroll = coordinate;
+ }
+ }
+ else if (isString(distance) && distance !== '#') {
+ var $target = $(distance);
+ if (!$target) {
+ return;
+ }
+ scroll = getOffset($target, $el);
+ }
+ if (offset) {
+ scroll.top += offset.top;
+ scroll.left += offset.left;
+ }
+ if ($header) {
+ scroll.top = Math.max(0, scroll.top - getSize($header).height);
+ }
+ // Normalize scroll offset
+ var _b = getViewportAndElementSizes($el), viewport = _b.viewport, size = _b.size;
+ scroll.top = vertical
+ ? Math.max(0, Math.min(size.height - viewport.height, scroll.top))
+ : getScroll($el, 'y');
+ scroll.left = horizontal
+ ? Math.max(0, Math.min(size.width - viewport.width, scroll.left))
+ : getScroll($el, 'x');
+ // Call `before`
+ // Stop scrolling when it returns false
+ if (this.hook(opts, 'before', scroll, $trigger) === false) {
+ ctx.opts = null;
+ return;
+ }
+ // Set offset
+ ctx.pos = scroll;
+ // Run animation!!
+ this.start(opts);
+ // Bind stop events
+ this.bind(false, true);
+ };
+ /**
+ * Scroll animation to specified left position.
+ */
+ SweetScroll.prototype.toTop = function (distance, options) {
+ this.to(distance, __assign({}, (options || {}), { vertical: true, horizontal: false }));
+ };
+ /**
+ * Scroll animation to specified top position.
+ */
+ SweetScroll.prototype.toLeft = function (distance, options) {
+ this.to(distance, __assign({}, (options || {}), { vertical: false, horizontal: true }));
+ };
+ /**
+ * Scroll animation to specified element.
+ */
+ SweetScroll.prototype.toElement = function ($element, options) {
+ var $el = this.$el;
+ if (!canUseDOM || !$el) {
+ return;
+ }
+ this.to(getOffset($element, $el), options || {});
+ };
+ /**
+ * Stop the current scroll animation.
+ */
+ SweetScroll.prototype.stop = function (gotoEnd) {
+ if (gotoEnd === void 0) { gotoEnd = false; }
+ var _a = this, $el = _a.$el, ctx = _a.ctx;
+ var pos = ctx.pos;
+ if (!$el || !ctx.progress) {
+ return;
+ }
+ SweetScroll.caf(ctx.id);
+ ctx.progress = false;
+ ctx.start = 0;
+ ctx.id = 0;
+ if (gotoEnd && pos) {
+ setScroll($el, pos.left, 'x');
+ setScroll($el, pos.top, 'y');
+ }
+ this.complete();
+ };
+ /**
+ * Update options.
+ */
+ SweetScroll.prototype.update = function (options) {
+ if (this.$el) {
+ var opts = __assign({}, this.opts, options);
+ this.stop();
+ this.unbind(true, true);
+ this.opts = opts;
+ this.bind(true, false);
+ }
+ };
+ /**
+ * Destroy instance.
+ */
+ SweetScroll.prototype.destroy = function () {
+ if (this.$el) {
+ this.stop();
+ this.unbind(true, true);
+ this.$el = null;
+ }
+ };
+ /**
+ * Callback methods.
+ */
+ /* tslint:disable:no-empty */
+ SweetScroll.prototype.onBefore = function (_, __) {
+ return true;
+ };
+ SweetScroll.prototype.onStep = function (_) { };
+ SweetScroll.prototype.onAfter = function (_, __) { };
+ SweetScroll.prototype.onCancel = function () { };
+ SweetScroll.prototype.onComplete = function (_) { };
+ /* tslint:enable */
+ /**
+ * Start scrolling animation.
+ */
+ SweetScroll.prototype.start = function (opts) {
+ var ctx = this.ctx;
+ ctx.opts = opts;
+ ctx.progress = true;
+ ctx.easing = isFunction(opts.easing)
+ ? opts.easing
+ : easings[opts.easing];
+ // Update start offset.
+ var $container = this.$el;
+ var start = {
+ top: getScroll($container, 'y'),
+ left: getScroll($container, 'x'),
+ };
+ ctx.startPos = start;
+ // Loop
+ ctx.id = SweetScroll.raf(this.loop);
+ };
+ /**
+ * Handle the completion of scrolling animation.
+ */
+ SweetScroll.prototype.complete = function () {
+ var _a = this, $el = _a.$el, ctx = _a.ctx;
+ var hash = ctx.hash, cancel = ctx.cancel, opts = ctx.opts, pos = ctx.pos, $trigger = ctx.$trigger;
+ if (!$el || !opts) {
+ return;
+ }
+ if (hash != null && hash !== window.location.hash) {
+ var updateURL = opts.updateURL;
+ if (canUseDOM && canUseHistory && updateURL !== false) {
+ window.history[updateURL === 'replace' ? 'replaceState' : 'pushState'](null, '', hash);
+ }
+ }
+ this.unbind(false, true);
+ ctx.opts = null;
+ ctx.$trigger = null;
+ if (cancel) {
+ this.hook(opts, 'cancel');
+ }
+ else {
+ this.hook(opts, 'after', pos, $trigger);
+ }
+ this.hook(opts, 'complete', cancel);
+ };
+ /**
+ * Callback function and method call.
+ */
+ SweetScroll.prototype.hook = function (options, type) {
+ var args = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ args[_i - 2] = arguments[_i];
+ }
+ var _a;
+ var callback = options[type];
+ var callbackResult;
+ var methodResult;
+ // callback
+ if (isFunction(callback)) {
+ callbackResult = callback.apply(this, args.concat([this]));
+ }
+ // method
+ methodResult = (_a = this)["on" + (type[0].toUpperCase() + type.slice(1))].apply(_a, args);
+ return callbackResult !== undefined ? callbackResult : methodResult;
+ };
+ /**
+ * Bind events of container element.
+ */
+ SweetScroll.prototype.bind = function (click, stop) {
+ var _a = this, $el = _a.$el, opts = _a.ctx.opts;
+ if ($el) {
+ if (click) {
+ addEvent($el, CONTAINER_CLICK_EVENT, this.handleClick, false);
+ }
+ if (stop) {
+ addEvent($el, CONTAINER_STOP_EVENT, this.handleStop, opts ? opts.cancellable : true);
+ }
+ }
+ };
+ /**
+ * Unbind events of container element.
+ */
+ SweetScroll.prototype.unbind = function (click, stop) {
+ var _a = this, $el = _a.$el, opts = _a.ctx.opts;
+ if ($el) {
+ if (click) {
+ removeEvent($el, CONTAINER_CLICK_EVENT, this.handleClick, false);
+ }
+ if (stop) {
+ removeEvent($el, CONTAINER_STOP_EVENT, this.handleStop, opts ? opts.cancellable : true);
+ }
+ }
+ };
+ /**
+ * You can set Polyfill (or Ponyfill) for browsers that do not support requestAnimationFrame.
+ */
+ SweetScroll.raf = raf;
+ SweetScroll.caf = caf;
+ return SweetScroll;
}());
return SweetScroll;
-})));
+}));
diff --git a/sweet-scroll.min.js b/sweet-scroll.min.js
index 91d27d5..1180000 100644
--- a/sweet-scroll.min.js
+++ b/sweet-scroll.min.js
@@ -1,2 +1,2 @@
-/*! @preserve sweet-scroll v3.0.1 - tsuyoshiwada | MIT License */
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.SweetScroll=e()}(this,function(){"use strict";var t=Object.assign||function(t){for(var e,n=1,o=arguments.length;n=0&&n[o]!==t;);return o>-1},C=function(t){return t===document.documentElement||t===document.body},I=function(t,e){for(var n=m[e],o=a(t)?[t]:M(t),i=document.createElement("div"),r=0;r0)u=l;else{var s=window.outerWidth,c=window.innerWidth,f=s?s/c:1;i.style.width=l.clientWidth+1+"px",i.style.height=l.clientHeight+1+"px",l.appendChild(i),l[n]=Math.max(1,1.5/f),l[n]>0&&(u=l),l[n]=0,l.removeChild(i)}if(u)return u}return null},k=function(t){return Math.max(t.scrollHeight,t.clientHeight,t.offsetHeight)},S=function(t){return Math.max(t.scrollWidth,t.clientWidth,t.offsetWidth)},A=function(t){return{width:S(t),height:k(t)}},P=function(t){var e=C(t);return{viewport:{width:e?Math.min(window.innerWidth,document.documentElement.clientWidth):t.clientWidth,height:e?window.innerHeight:t.clientHeight},size:e?{width:Math.max(S(document.body),S(document.documentElement)),height:Math.max(k(document.body),k(document.documentElement))}:A(t)}},Q=e?"onwheel"in document?"wheel":"mousewheel":"wheel",L=function(t,e,n,i,r){n.split(" ").forEach(function(n){t[e](function(t){return"wheel"===t?Q:t}(n),i,!!o&&{passive:r})})},W=function(t,e,n,o){L(t,"addEventListener",e,n,o)},z=function(t,e,n,o){L(t,"removeEventListener",e,n,o)},H=/^(\+|-)=(\d+(?:\.\d+)?)$/,j=function(e,n){var o,r={top:0,left:0,relative:!1};if(u(e,"top")||u(e,"left"))r=t({},r,e);else if(l(e))if(e.length>1)r.top=e[0],r.left=e[1];else{if(1!==e.length)return null;r.top=n?e[0]:0,r.left=n?0:e[0]}else if(!l(o=e)&&o-parseFloat(o)+1>=0)n?r.top=e:r.left=e;else{if(!i(e))return null;var a=e.trim().match(H);if(!a)return null;var s=a[1],c=parseInt(a[2],10);"+"===s?(r.top=n?c:0,r.left=n?0:c):(r.top=n?-c:0,r.left=n?0:-c),r.relative=!0}return r},q={trigger:"[data-scroll]",header:"[data-scroll-header]",duration:1e3,easing:"easeOutQuint",offset:0,vertical:!0,horizontal:!1,cancellable:!0,updateURL:!1,preventDefault:!0,stopPropagation:!0,quickMode:!1,before:null,after:null,cancel:null,complete:null,step:null};return function(){function o(n,i){var r=this;this.ctx={$trigger:null,opts:null,progress:!1,pos:null,startPos:null,easing:null,start:0,id:0,cancel:!1,hash:null},this.loop=function(t){var e=r,n=e.$el,i=e.ctx;if(i.start||(i.start=t),i.progress&&n){var l=i.opts,a=i.pos,u=i.start,s=i.startPos,c=i.easing,f=l.duration,h={top:"y",left:"x"},p=t-u,d=Math.min(1,Math.max(p/f,0));Object.keys(a).forEach(function(t){var e=a[t],o=s[t],i=e-o;if(0!==i){var r=c(d,f*d,0,1,f);b(n,Math.round(o+i*r),h[t])}}),p<=f?(r.hook(l,"step",d),i.id=o.raf(r.loop)):r.stop(!0)}else r.stop()},this.handleClick=function(e){for(var n=r.opts,o=e.target;o&&o!==document;o=o.parentNode)if(E(o,n.trigger)){var i=JSON.parse(o.getAttribute("data-scroll-options")||"{}"),l=o.getAttribute("data-scroll")||o.getAttribute("href"),a=t({},n,i),u=a.preventDefault,s=a.stopPropagation,c=a.vertical,f=a.horizontal;u&&e.preventDefault(),s&&e.stopPropagation(),r.ctx.$trigger=o,f&&c?r.to(l,a):c?r.toTop(l,a):f&&r.toLeft(l,a)}},this.handleStop=function(t){var e=r.ctx,n=e.opts;n&&n.cancellable?(e.cancel=!0,r.stop()):t.preventDefault()};var l=t({},q,n||{}),a=l.vertical,u=l.horizontal,s=void 0===i?"body,html":i,c=null;e&&(a&&(c=I(s,"y")),!c&&u&&(c=I(s,"x"))),c&&(this.opts=l,this.$el=c,this.bind(!0,!1))}return o.create=function(t,e){return new o(t,e)},o.prototype.to=function(n,o){if(e){var r=this.$el,l=this.ctx,u=this.opts,s=l.$trigger,c=t({},u,o||{}),f=c.offset,h=c.vertical,p=c.horizontal,d=a(c.header)?c.header:$(c.header),v=i(n)&&/^#/.test(n)?n:null;if(l.opts=c,l.cancel=!1,l.hash=v,this.stop(),r){var g=j(f,h),m=j(n,h),w={top:0,left:0};if(m)if(m.relative){var y=x(r,h?"y":"x");w.top=h?y+m.top:m.top,w.left=h?m.left:y+m.left}else w=m;else if(i(n)&&"#"!==n){var b=$(n);if(!b)return;w=O(b,r)}g&&(w.top+=g.top,w.left+=g.left),d&&(w.top=Math.max(0,w.top-A(d).height));var M=P(r),E=M.viewport,C=M.size;w.top=h?Math.max(0,Math.min(C.height-E.height,w.top)):x(r,"y"),w.left=p?Math.max(0,Math.min(C.width-E.width,w.left)):x(r,"x"),!1!==this.hook(c,"before",w,s)?(l.pos=w,this.start(c),this.bind(!1,!0)):l.opts=null}}},o.prototype.toTop=function(e,n){this.to(e,t({},n||{},{vertical:!0,horizontal:!1}))},o.prototype.toLeft=function(e,n){this.to(e,t({},n||{},{vertical:!1,horizontal:!0}))},o.prototype.toElement=function(t,n){var o=this.$el;e&&o&&this.to(O(t,o),n||{})},o.prototype.stop=function(t){void 0===t&&(t=!1);var e=this.$el,n=this.ctx,i=n.pos;e&&n.progress&&(o.caf(n.id),n.progress=!1,n.start=0,n.id=0,t&&i&&(b(e,i.left,"x"),b(e,i.top,"y")),this.complete())},o.prototype.update=function(e){if(this.$el){var n=t({},this.opts,e);this.stop(),this.unbind(!0,!0),this.opts=n,this.bind(!0,!1)}},o.prototype.destroy=function(){this.$el&&(this.stop(),this.unbind(!0,!0),this.$el=null)},o.prototype.onBefore=function(t,e){return!0},o.prototype.onStep=function(t){},o.prototype.onAfter=function(t,e){},o.prototype.onCancel=function(){},o.prototype.onComplete=function(t){},o.prototype.start=function(t){var e=this.ctx;e.opts=t,e.progress=!0,e.easing=r(t.easing)?t.easing:g[t.easing];var n=this.$el,i=e.pos,l={top:x(n,"y"),left:x(n,"x")};if(t.quickMode){var a=P(n).viewport,u=a.width,s=a.height;Math.abs(l.top-i.top)>s&&(l.top=l.top>i.top?i.top+s:i.top-s),Math.abs(l.left-i.left)>u&&(l.left=l.left>i.left?i.left+u:i.left-u)}e.startPos=l,e.id=o.raf(this.loop)},o.prototype.complete=function(){var t=this.$el,o=this.ctx,i=o.hash,r=o.cancel,l=o.opts,a=o.pos,u=o.$trigger;if(t&&l){if(null!=i&&i!==window.location.hash){var s=l.updateURL;e&&n&&!1!==s&&window.history["replace"===s?"replaceState":"pushState"](null,"",i)}this.unbind(!1,!0),o.opts=null,o.$trigger=null,r?this.hook(l,"cancel"):this.hook(l,"after",a,u),this.hook(l,"complete",r)}},o.prototype.hook=function(t,e){for(var n=[],o=2;o=0&&n[o]!==t;);return o>-1},O=function(t){return Math.max(t.scrollHeight,t.clientHeight,t.offsetHeight)},$=function(t){return Math.max(t.scrollWidth,t.clientWidth,t.offsetWidth)},M=function(t){return{width:$(t),height:O(t)}},E={y:"scrollTop",x:"scrollLeft"},I={y:"pageYOffset",x:"pageXOffset"},C=function(t,e){return y(t)?t[I[e]]:t[E[e]]},S=function(t,e,n){if(y(t)){var o="y"===n;t.scrollTo(o?t.pageXOffset:e,o?e:t.pageYOffset)}else t[E[n]]=e},k=function(t,e){var n=t.getBoundingClientRect();if(n.width||n.height){var o={top:0,left:0},i=void 0;if(y(e)||x(e))i=document.documentElement,o.top=window[I.y],o.left=window[I.x];else{var r=(i=e).getBoundingClientRect();o.top=-1*r.top+i[E.y],o.left=-1*r.left+i[E.x]}return{top:n.top+o.top-i.clientTop,left:n.left+o.left-i.clientLeft}}return n},A=e?"onwheel"in document?"wheel":"mousewheel":"wheel",L=function(t,e,n,i,r){n.split(" ").forEach(function(n){t[e](function(t){return"wheel"===t?A:t}(n),i,!!o&&{passive:r})})},P=function(t,e,n,o){return L(t,"addEventListener",e,n,o)},Q=function(t,e,n,o){return L(t,"removeEventListener",e,n,o)},z=/^(\+|-)=(\d+(?:\.\d+)?)$/,W=function(e,n){var o,r={top:0,left:0,relative:!1};if(a(e,"top")||a(e,"left"))r=t({},r,e);else if(u(e))if(e.length>1)r.top=e[0],r.left=e[1];else{if(1!==e.length)return null;r.top=n?e[0]:0,r.left=n?0:e[0]}else if(!u(o=e)&&o-parseFloat(o)+1>=0)n?r.top=e:r.left=e;else{if(!i(e))return null;var l=e.trim().match(z);if(!l)return null;var s=l[1],c=parseInt(l[2],10);"+"===s?(r.top=n?c:0,r.left=n?0:c):(r.top=n?-c:0,r.left=n?0:-c),r.relative=!0}return r},j={trigger:"[data-scroll]",header:"[data-scroll-header]",duration:1e3,easing:"easeOutQuint",offset:0,vertical:!0,horizontal:!1,cancellable:!0,updateURL:!1,preventDefault:!0,stopPropagation:!0,before:null,after:null,cancel:null,complete:null,step:null};return function(){function o(n,i){var r=this;this.$el=null,this.ctx={$trigger:null,opts:null,progress:!1,pos:null,startPos:null,easing:null,start:0,id:0,cancel:!1,hash:null},this.loop=function(t){var e=r,n=e.$el,i=e.ctx;if(i.start||(i.start=t),i.progress&&n){var u=i.opts,a=i.pos,l=i.start,s=i.startPos,c=i.easing,f=u.duration,p={top:"y",left:"x"},h=t-l,d=Math.min(1,Math.max(h/f,0));Object.keys(a).forEach(function(t){var e=a[t],o=s[t],i=e-o;if(0!==i){var r=c(d,f*d,0,1,f);S(n,Math.round(o+i*r),p[t])}}),h<=f?(r.hook(u,"step",d),i.id=o.raf(r.loop)):r.stop(!0)}else r.stop()},this.handleClick=function(e){for(var n=r.opts,o=e.target;o&&o!==document;o=o.parentNode)if(b(o,n.trigger)){var i=JSON.parse(o.getAttribute("data-scroll-options")||"{}"),u=o.getAttribute("data-scroll")||o.getAttribute("href"),a=t({},n,i),l=a.preventDefault,s=a.stopPropagation,c=a.vertical,f=a.horizontal;l&&e.preventDefault(),s&&e.stopPropagation(),r.ctx.$trigger=o,f&&c?r.to(u,a):c?r.toTop(u,a):f&&r.toLeft(u,a);break}},this.handleStop=function(t){var e=r.ctx,n=e.opts;n&&n.cancellable?(e.cancel=!0,r.stop()):t.preventDefault()},this.opts=t({},j,n||{});var u=null;e&&(u="string"==typeof i?w(i):null!=i?i:window),this.$el=u,u&&this.bind(!0,!1)}return o.create=function(t,e){return new o(t,e)},o.prototype.to=function(n,o){if(e){var r=this.$el,u=this.ctx,a=this.opts,l=u.$trigger,s=t({},a,o||{}),c=s.offset,f=s.vertical,p=s.horizontal,h=m(s.header)?s.header:w(s.header),d=i(n)&&/^#/.test(n)?n:null;if(u.opts=s,u.cancel=!1,u.hash=d,this.stop(),r){var v=W(c,f),g=W(n,f),b={top:0,left:0};if(g)if(g.relative){var E=C(r,f?"y":"x");b.top=f?E+g.top:g.top,b.left=f?g.left:E+g.left}else b=g;else if(i(n)&&"#"!==n){var I=w(n);if(!I)return;b=k(I,r)}v&&(b.top+=v.top,b.left+=v.left),h&&(b.top=Math.max(0,b.top-M(h).height));var S=function(t){var e=y(t)||x(t);return{viewport:{width:e?Math.min(window.innerWidth,document.documentElement.clientWidth):t.clientWidth,height:e?window.innerHeight:t.clientHeight},size:e?{width:Math.max($(document.body),$(document.documentElement)),height:Math.max(O(document.body),O(document.documentElement))}:M(t)}}(r),A=S.viewport,L=S.size;b.top=f?Math.max(0,Math.min(L.height-A.height,b.top)):C(r,"y"),b.left=p?Math.max(0,Math.min(L.width-A.width,b.left)):C(r,"x"),!1!==this.hook(s,"before",b,l)?(u.pos=b,this.start(s),this.bind(!1,!0)):u.opts=null}}},o.prototype.toTop=function(e,n){this.to(e,t({},n||{},{vertical:!0,horizontal:!1}))},o.prototype.toLeft=function(e,n){this.to(e,t({},n||{},{vertical:!1,horizontal:!0}))},o.prototype.toElement=function(t,n){var o=this.$el;e&&o&&this.to(k(t,o),n||{})},o.prototype.stop=function(t){void 0===t&&(t=!1);var e=this.$el,n=this.ctx,i=n.pos;e&&n.progress&&(o.caf(n.id),n.progress=!1,n.start=0,n.id=0,t&&i&&(S(e,i.left,"x"),S(e,i.top,"y")),this.complete())},o.prototype.update=function(e){if(this.$el){var n=t({},this.opts,e);this.stop(),this.unbind(!0,!0),this.opts=n,this.bind(!0,!1)}},o.prototype.destroy=function(){this.$el&&(this.stop(),this.unbind(!0,!0),this.$el=null)},o.prototype.onBefore=function(t,e){return!0},o.prototype.onStep=function(t){},o.prototype.onAfter=function(t,e){},o.prototype.onCancel=function(){},o.prototype.onComplete=function(t){},o.prototype.start=function(t){var e=this.ctx;e.opts=t,e.progress=!0,e.easing=r(t.easing)?t.easing:v[t.easing];var n=this.$el,i={top:C(n,"y"),left:C(n,"x")};e.startPos=i,e.id=o.raf(this.loop)},o.prototype.complete=function(){var t=this.$el,o=this.ctx,i=o.hash,r=o.cancel,u=o.opts,a=o.pos,l=o.$trigger;if(t&&u){if(null!=i&&i!==window.location.hash){var s=u.updateURL;e&&n&&!1!==s&&window.history["replace"===s?"replaceState":"pushState"](null,"",i)}this.unbind(!1,!0),o.opts=null,o.$trigger=null,r?this.hook(u,"cancel"):this.hook(u,"after",a,l),this.hook(u,"complete",r)}},o.prototype.hook=function(t,e){for(var n,o=[],i=2;i