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 \n

Content 01

page top
\n

Content 02

page top
\n

Content 03

page top
\n

Content 04

page top
\n

Content 05

page top
\n
\n"; +export declare const fixture = "\n
\n \n

Content 01

page top
\n

Content 02

page top
\n

Content 03

page top
\n

Content 04

page top
\n

Content 05

page top
\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