UNPKG

fullpage.js

Version:

Create beautiful fullscreen snap scrolling websites

1,701 lines (1,438 loc) 197 kB
/*! * fullPage 4.0.37 * https://github.com/alvarotrigo/fullPage.js * * @license GPLv3 for open source use only * or Fullpage Commercial License for commercial use * http://alvarotrigo.com/fullPage/pricing/ * * Copyright (C) 2018 http://alvarotrigo.com/fullPage - A project by Alvaro Trigo */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.fullpage = factory()); })(this, (function () { 'use strict'; // https://tc39.github.io/ecma262/#sec-array.prototype.find if (!Array.prototype.find) { Object.defineProperty(Array.prototype, 'find', { value: function value(predicate) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. var thisArg = arguments[1]; // 5. Let k be 0. var k = 0; // 6. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). // d. If testResult is true, return kValue. var kValue = o[k]; if (predicate.call(thisArg, kValue, k, o)) { return kValue; } // e. Increase k by 1. k++; } // 7. Return undefined. return undefined; } }); } // Production steps of ECMA-262, Edition 6, 22.1.2.1 if (!Array.from) { Array.from = function () { var toStr = Object.prototype.toString; var isCallable = function isCallable(fn) { return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; }; var toInteger = function toInteger(value) { var number = Number(value); if (isNaN(number)) { return 0; } if (number === 0 || !isFinite(number)) { return number; } return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); }; var maxSafeInteger = Math.pow(2, 53) - 1; var toLength = function toLength(value) { var len = toInteger(value); return Math.min(Math.max(len, 0), maxSafeInteger); }; // The length property of the from method is 1. return function from(arrayLike /*, mapFn, thisArg */ ) { // 1. Let C be the this value. var C = this; // 2. Let items be ToObject(arrayLike). var items = Object(arrayLike); // 3. ReturnIfAbrupt(items). if (arrayLike == null) { throw new TypeError('Array.from requires an array-like object - not null or undefined'); } // 4. If mapfn is undefined, then let mapping be false. var mapFn = arguments.length > 1 ? arguments[1] : void undefined; var T; if (typeof mapFn !== 'undefined') { // 5. else // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. if (!isCallable(mapFn)) { throw new TypeError('Array.from: when provided, the second argument must be a function'); } // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. if (arguments.length > 2) { T = arguments[2]; } } // 10. Let lenValue be Get(items, "length"). // 11. Let len be ToLength(lenValue). var len = toLength(items.length); // 13. If IsConstructor(C) is true, then // 13. a. Let A be the result of calling the [[Construct]] internal method // of C with an argument list containing the single item len. // 14. a. Else, Let A be ArrayCreate(len). var A = isCallable(C) ? Object(new C(len)) : new Array(len); // 16. Let k be 0. var k = 0; // 17. Repeat, while k < len… (also steps a - h) var kValue; while (k < len) { kValue = items[k]; if (mapFn) { A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); } else { A[k] = kValue; } k += 1; } // 18. Let putStatus be Put(A, "length", len, true). A.length = len; // 20. Return A. return A; }; }(); } var win = window; var doc = document; var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/) || navigator.userAgent.includes("Mac") && "ontouchend" in document; // iPad on iOS 13 detection var isMacDevice = /(Mac|iPhone|iPod|iPad)/i.test(win.navigator.userAgent); // @ts-ignore var isTouch = 'ontouchstart' in win || navigator.msMaxTouchPoints > 0 || navigator.maxTouchPoints; var isIE11 = !!window.MSInputMethodContext && !!document.documentMode; // taken from https://github.com/udacity/ud891/blob/gh-pages/lesson2-focus/07-modals-and-keyboard-traps/solution/modal.js var focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], summary:not([disabled]), [contenteditable]'; // cache common elements var FP = { test: {}, shared: {} }; var extensions = ['parallax', 'scrollOverflowReset', 'dragAndMove', 'offsetSections', 'fadingEffect', 'responsiveSlides', 'continuousHorizontal', 'interlockedSlides', 'scrollHorizontally', 'resetSliders', 'cards', 'dropEffect', 'waterEffect']; var isInsideIframe = function () { var inIframe = window.self !== window.top; return function () { return inIframe; }; }(); /** * forEach polyfill for IE * https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Browser_Compatibility */ if (win.NodeList && !NodeList.prototype.forEach) { NodeList.prototype.forEach = function (callback, thisArg) { thisArg = thisArg || window; for (var i = 0; i < this.length; i++) { callback.call(thisArg, this[i], i, this); } }; } if (typeof Object.assign != 'function') { // Must be writable: true, enumerable: false, configurable: true Object.defineProperty(Object, 'assign', { value: function assign(target, varArgs) { if (target == null) { // TypeError if undefined or null throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource != null) { // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); } // https://stackoverflow.com/questions/51719553/padstart-not-working-in-ie11 // https://github.com/behnammodi/polyfill/blob/master/string.polyfill.js // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart if (!String.prototype.padStart) { String.prototype.padStart = function padStart(targetLength, padString) { targetLength = targetLength >> 0; //truncate if number or convert non-number to 0; padString = String(typeof padString !== 'undefined' ? padString : ' '); if (this.length > targetLength) { return String(this); } else { targetLength = targetLength - this.length; if (targetLength > padString.length) { padString += Array.apply(null, Array(targetLength)).map(function () { return padString; }).join(""); } return padString.slice(0, targetLength) + String(this); } }; } //utils /** * Shows a message in the console of the given type. */ function showError(type, text) { win.console && win.console[type] && win.console[type]('fullPage: ' + text); } function isVisible(el) { var style = win.getComputedStyle(el); return style.display !== 'none'; } function getVisible(elements) { return Array.from(elements).filter(function (e) { return isVisible(e); }); } /** * Equivalent of jQuery function $(). */ function $(selector, context) { context = arguments.length > 1 ? context : document; return context ? context.querySelectorAll(selector) : null; } /** * Extends a given Object properties and its childs. */ function deepExtend(out) { out = out || {}; for (var i = 1, len = arguments.length; i < len; ++i) { var obj = arguments[i]; if (!obj) { continue; } for (var key in obj) { if (!obj.hasOwnProperty(key) || key == '__proto__' || key == 'constructor') { continue; } // based on https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ if (Object.prototype.toString.call(obj[key]) === '[object Object]') { out[key] = deepExtend(out[key], obj[key]); continue; } out[key] = obj[key]; } } return out; } /** * Checks if the passed element contains the passed class. */ function hasClass(el, className) { if (el == null) { return false; } return el.classList.contains(className); } /** * Gets the window height. Crossbrowser. */ function getWindowHeight() { return 'innerHeight' in win ? win.innerHeight : doc.documentElement.offsetHeight; } /** * Gets the window width. */ function getWindowWidth() { return win.innerWidth; } /** * Set's the CSS properties for the passed item/s. * @param {NodeList|HTMLElement|Object} items * @param {Object} props css properties and values. */ function css(items, props) { items = getList(items); var key; for (key in props) { if (props.hasOwnProperty(key)) { if (key !== null) { for (var i = 0; i < items.length; i++) { var item = items[i]; item.style[key] = props[key]; } } } } return items; } /** * Gets the previous element to the passed element. */ function prev(item) { return item.previousElementSibling; } /** * Gets the next element to the passed element. */ function next(item) { return item.nextElementSibling; } /** * Gets the last element from the passed list of elements. */ function last(item) { return item[item.length - 1]; } /** * Gets index from the passed element. * @param {String} selector is optional. */ function index(item, selector) { item = isArrayOrList(item) ? item[0] : item; var children = selector != null ? $(selector, item.parentNode) : item.parentNode.childNodes; var num = 0; for (var i = 0; i < children.length; i++) { if (children[i] == item) return num; if (children[i].nodeType == 1) num++; } return -1; } /** * Gets an iterable element for the passed element/s */ function getList(item) { return !isArrayOrList(item) ? [item] : item; } /** * Adds the display=none property for the passed element/s */ function hide(el) { el = getList(el); for (var i = 0; i < el.length; i++) { el[i].style.display = 'none'; } return el; } /** * Adds the display=block property for the passed element/s */ function show(el) { el = getList(el); for (var i = 0; i < el.length; i++) { el[i].style.display = 'block'; } return el; } /** * Checks if the passed element is an iterable element or not */ function isArrayOrList(el) { return Object.prototype.toString.call(el) === '[object Array]' || Object.prototype.toString.call(el) === '[object NodeList]'; } /** * Adds the passed class to the passed element/s */ function addClass(el, className) { el = getList(el); for (var i = 0; i < el.length; i++) { var item = el[i]; item.classList.add(className); } return el; } /** * Removes the passed class to the passed element/s * @param {String} `className` can be multiple classnames separated by whitespace */ function removeClass(el, className) { el = getList(el); var classNames = className.split(' '); for (var a = 0; a < classNames.length; a++) { className = classNames[a]; for (var i = 0; i < el.length; i++) { var item = el[i]; item.classList.remove(className); } } return el; } /** * Appends the given element ot the given parent. */ function appendTo(el, parent) { parent.appendChild(el); } /** Usage: var wrapper = document.createElement('div'); wrapper.className = 'fp-slides'; wrap($('.slide'), wrapper); https://jsfiddle.net/qwzc7oy3/15/ (vanilla) https://jsfiddle.net/oya6ndka/1/ (jquery equivalent) */ function wrap(toWrap, wrapper, isWrapAll) { var newParent; wrapper = wrapper || doc.createElement('div'); for (var i = 0; i < toWrap.length; i++) { var item = toWrap[i]; if (isWrapAll && !i || !isWrapAll) { newParent = wrapper.cloneNode(true); item.parentNode.insertBefore(newParent, item); } newParent.appendChild(item); } return toWrap; } /** Usage: var wrapper = document.createElement('div'); wrapper.className = 'fp-slides'; wrap($('.slide'), wrapper); https://jsfiddle.net/qwzc7oy3/27/ (vanilla) https://jsfiddle.net/oya6ndka/4/ (jquery equivalent) */ function wrapAll(toWrap, wrapper) { wrap(toWrap, wrapper, true); } /** * Usage: * wrapInner(document.querySelector('#pepe'), '<div class="test">afdas</div>'); * wrapInner(document.querySelector('#pepe'), element); * * https://jsfiddle.net/zexxz0tw/6/ * * https://stackoverflow.com/a/21817590/1081396 */ function wrapInner(parent, wrapper) { parent.appendChild(wrapper); while (parent.firstChild !== wrapper) { wrapper.appendChild(parent.firstChild); } } /** * Usage: * unwrap(document.querySelector('#pepe')); * unwrap(element); * * https://jsfiddle.net/szjt0hxq/1/ * */ function unwrap(wrapper) { var wrapperContent = doc.createDocumentFragment(); while (wrapper.firstChild) { wrapperContent.appendChild(wrapper.firstChild); } wrapper.parentNode.replaceChild(wrapperContent, wrapper); } /** * http://stackoverflow.com/questions/22100853/dom-pure-javascript-solution-to-jquery-closest-implementation * Returns the element or `false` if there's none */ function closest(el, selector) { if (el && el.nodeType === 1) { if (matches(el, selector)) { return el; } return closest(el.parentNode, selector); } return null; } /** * Places one element (rel) after another one or group of them (reference). * @param {HTMLElement} reference * @param {HTMLElement|NodeList|String|Array} el * https://jsfiddle.net/9s97hhzv/1/ */ function after(reference, el) { insertBefore(reference, reference.nextSibling, el); } /** * Places one element (rel) before another one or group of them (reference). * @param {HTMLElement} reference * @param {HTMLElement|NodeList|String|Array} el * https://jsfiddle.net/9s97hhzv/1/ */ function before(reference, el) { insertBefore(reference, reference, el); } /** * Based in https://stackoverflow.com/a/19316024/1081396 * and https://stackoverflow.com/a/4793630/1081396 */ function insertBefore(reference, beforeElement, el) { if (!isArrayOrList(el)) { if (typeof el == 'string') { el = createElementFromHTML(el); } el = [el]; } for (var i = 0; i < el.length; i++) { reference.parentNode.insertBefore(el[i], beforeElement); } } //http://stackoverflow.com/questions/3464876/javascript-get-window-x-y-position-for-scroll function getScrollTop() { var docElement = doc.documentElement; return (win.pageYOffset || docElement.scrollTop) - (docElement.clientTop || 0); } /** * Gets the siblings of the passed element */ function siblings(el) { return Array.prototype.filter.call(el.parentNode.children, function (child) { return child !== el; }); } function preventDefault(event) { event.preventDefault(); } function getAttr(el, attr) { return el.getAttribute(attr); } function docAddEvent(event, callback, options) { doc.addEventListener(event, callback, options === 'undefined' ? null : options); } function windowAddEvent(event, callback, options) { win.addEventListener(event, callback, options === 'undefined' ? null : options); } function docRemoveEvent(event, callback, options) { doc.removeEventListener(event, callback, options === 'undefined' ? null : options); } function windowRemoveEvent(event, callback, options) { win.removeEventListener(event, callback, options === 'undefined' ? null : options); } /** * Determines whether the passed item is of function type. */ function isFunction(item) { if (typeof item === 'function') { return true; } var type = Object.prototype.toString.call(item); return type === '[object Function]' || type === '[object GeneratorFunction]'; } /** * Trigger custom events */ function trigger(el, eventName, data) { var event; data = typeof data === 'undefined' ? {} : data; // Native if (typeof win.CustomEvent === "function") { event = new CustomEvent(eventName, { detail: data }); } else { event = doc.createEvent('CustomEvent'); event.initCustomEvent(eventName, true, true, data); } el.dispatchEvent(event); } /** * Polyfill of .matches() */ function matches(el, selector) { return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); } /** * Toggles the visibility of the passed element el. */ function toggle(el, value) { if (typeof value === "boolean") { for (var i = 0; i < el.length; i++) { el[i].style.display = value ? 'block' : 'none'; } } //we don't use it in other way, so no else :) return el; } /** * Creates a HTMLElement from the passed HTML string. * https://stackoverflow.com/a/494348/1081396 */ function createElementFromHTML(htmlString) { var div = doc.createElement('div'); div.innerHTML = htmlString.trim(); // Change this to div.childNodes to support multiple top-level nodes return div.firstChild; } /** * Removes the passed item/s from the DOM. */ function remove(items) { items = getList(items); for (var i = 0; i < items.length; i++) { var item = items[i]; if (item && item.parentElement) { item.parentNode.removeChild(item); } } } //https://jsfiddle.net/w1rktecz/ function untilAll(item, selector, fn) { var sibling = item[fn]; var siblings = []; while (sibling) { if (matches(sibling, selector) || selector == null) { siblings.push(sibling); } sibling = sibling[fn]; } return siblings; } /** * Gets all next elements matching the passed selector. */ function nextAll(item, selector) { return untilAll(item, selector, 'nextElementSibling'); } /** * Gets all previous elements matching the passed selector. */ function prevAll(item, selector) { return untilAll(item, selector, 'previousElementSibling'); } /** * Converts an object to an array. */ function toArray(objectData) { return Object.keys(objectData).map(function (key) { return objectData[key]; }); } function getLast(items) { return items[items.length - 1]; } /** * Gets the average of the last `number` elements of the given array. */ function getAverage(elements, number) { var sum = 0; //taking `number` elements from the end to make the average, if there are not enought, 1 var lastElements = elements.slice(Math.max(elements.length - number, 1)); for (var i = 0; i < lastElements.length; i++) { sum = sum + lastElements[i]; } return Math.ceil(sum / number); } /** * Sets the value for the given attribute from the `data-` attribute with the same suffix * ie: data-srcset ==> srcset | data-src ==> src */ function setSrc(element, attribute) { element.setAttribute(attribute, getAttr(element, 'data-' + attribute)); element.removeAttribute('data-' + attribute); } function getParentsUntil(item, topParentSelector) { var parents = [item]; do { item = item.parentNode; parents.push(item); } while (!matches(item, topParentSelector)); return parents; } function isInsideInput() { var activeElement = doc.activeElement; return matches(activeElement, 'textarea') || matches(activeElement, 'input') || matches(activeElement, 'select') || getAttr(activeElement, 'contentEditable') == "true" || getAttr(activeElement, 'contentEditable') == ''; } //utils are public, so we can use it wherever we want // @ts-ignore window["fp_utils"] = { "$": $, "deepExtend": deepExtend, "hasClass": hasClass, "getWindowHeight": getWindowHeight, "css": css, "prev": prev, "next": next, "last": last, "index": index, "getList": getList, "hide": hide, "show": show, "isArrayOrList": isArrayOrList, "addClass": addClass, "removeClass": removeClass, "appendTo": appendTo, "wrap": wrap, "wrapAll": wrapAll, "unwrap": unwrap, "closest": closest, "after": after, "before": before, "insertBefore": insertBefore, "getScrollTop": getScrollTop, "siblings": siblings, "preventDefault": preventDefault, "isFunction": isFunction, "trigger": trigger, "matches": matches, "toggle": toggle, "createElementFromHTML": createElementFromHTML, "remove": remove, // "filter": filter, "untilAll": untilAll, "nextAll": nextAll, "prevAll": prevAll, "showError": showError }; var utils = /*#__PURE__*/Object.freeze({ __proto__: null, showError: showError, isVisible: isVisible, getVisible: getVisible, $: $, deepExtend: deepExtend, hasClass: hasClass, getWindowHeight: getWindowHeight, getWindowWidth: getWindowWidth, css: css, prev: prev, next: next, last: last, index: index, getList: getList, hide: hide, show: show, isArrayOrList: isArrayOrList, addClass: addClass, removeClass: removeClass, appendTo: appendTo, wrap: wrap, wrapAll: wrapAll, wrapInner: wrapInner, unwrap: unwrap, closest: closest, after: after, before: before, insertBefore: insertBefore, getScrollTop: getScrollTop, siblings: siblings, preventDefault: preventDefault, getAttr: getAttr, docAddEvent: docAddEvent, windowAddEvent: windowAddEvent, docRemoveEvent: docRemoveEvent, windowRemoveEvent: windowRemoveEvent, isFunction: isFunction, trigger: trigger, matches: matches, toggle: toggle, createElementFromHTML: createElementFromHTML, remove: remove, untilAll: untilAll, nextAll: nextAll, prevAll: prevAll, toArray: toArray, getLast: getLast, getAverage: getAverage, setSrc: setSrc, getParentsUntil: getParentsUntil, isInsideInput: isInsideInput }); function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; }; } else { _typeof = function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } var EventEmitter = { events: {}, on: function on(event, listener) { var _this = this; if (_typeof(this.events[event]) !== 'object') { this.events[event] = []; } this.events[event].push(listener); return function () { return _this.removeListener(event, listener); }; }, removeListener: function removeListener(event, listener) { if (_typeof(this.events[event]) === 'object') { var idx = this.events[event].indexOf(listener); if (idx > -1) { this.events[event].splice(idx, 1); } } }, emit: function emit(event) { var _this2 = this; for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (_typeof(this.events[event]) === 'object') { this.events[event].forEach(function (listener) { return listener.apply(_this2, args); }); } }, once: function once(event, listener) { var _this3 = this; var remove = this.on(event, function () { remove(); for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } listener.apply(_this3, args); }); } }; var defaultState = { numSections: 0, numSlides: 0, slides: [], sections: [], activeSection: null, scrollTrigger: null, isBeyondFullpage: false, aboutToScrollToFullPage: false, slideMoving: false, isResizing: false, isScrolling: false, lastScrolledDestiny: undefined, lastScrolledSlide: undefined, activeAnimation: false, canScroll: true, touchDirection: 'none', wheelDirection: 'none', isGrabbing: false, isUsingWheel: false, isWindowFocused: true, previousDestTop: 0, windowsHeight: getWindowHeight(), isDoingContinousVertical: false, timeouts: {}, scrollY: 0, scrollX: 0, isFullpageInitDone: false }; var state = Object.assign({}, defaultState); // @ts-ignore win.state = state; function setState(props) { Object.assign(state, props); } function getState() { return state; } function getActivePanel() { return state.activeSection && state.activeSection.activeSlide ? state.activeSection.activeSlide : state.activeSection; } function resetState() { setState(defaultState); } var events = { onAfterRenderNoAnchor: 'onAfterRenderNoAnchor', onClickOrTouch: 'onClickOrTouch', moveSlideLeft: 'moveSlideLeft', moveSlideRight: 'moveSlideRight', onInitialise: 'onInitialise', beforeInit: 'beforeInit', bindEvents: 'bindEvents', onDestroy: 'onDestroy', onDestroyAll: 'onDestroyAll', contentChanged: 'contentChanged', onScrollOverflowScrolled: 'onScrollOverflowScrolled', onScrollPageAndSlide: 'onScrollPageAndSlide', onKeyDown: 'onKeyDown', onMenuClick: 'onMenuClick', scrollPage: 'scrollPage', landscapeScroll: 'landscapeScroll', scrollBeyondFullpage: 'scrollBeyondFullpage', onPerformMovement: 'onPerformMovement', onSlideLeave: 'onSlideLeave', onLeave: 'onLeave', afterSectionLoads: 'afterSectionLoads', afterSlideLoads: 'afterSlideLoads' }; EventEmitter.on(events.bindEvents, bindEvents$c); function bindEvents$c() { //Scrolls to the section when clicking the navigation bullet //simulating the jQuery .on('click') event using delegation ['click', 'touchstart'].forEach(function (eventName) { docAddEvent(eventName, delegatedEvents); }); windowAddEvent('focus', focusHandler); internalEvents(); } function internalEvents() { EventEmitter.on(events.onDestroy, onDestroy$9); } function delegatedEvents(e) { EventEmitter.emit(events.onClickOrTouch, { e: e, target: e.target }); } function onDestroy$9() { ['click', 'touchstart'].forEach(function (eventName) { docRemoveEvent(eventName, delegatedEvents); }); } // changing isWindowFocused to true on focus event function focusHandler() { setState({ isWindowFocused: true }); } // keeping central set of classnames and selectors var WRAPPER = 'fullpage-wrapper'; var WRAPPER_SEL = '.' + WRAPPER; // slimscroll var SCROLLABLE = 'fp-scrollable'; var RESPONSIVE = 'fp-responsive'; var NO_TRANSITION = 'fp-notransition'; var DESTROYED = 'fp-destroyed'; var ENABLED = 'fp-enabled'; var VIEWING_PREFIX = 'fp-viewing'; var ACTIVE = 'active'; var ACTIVE_SEL = '.' + ACTIVE; var COMPLETELY = 'fp-completely'; var COMPLETELY_SEL = '.' + COMPLETELY; var LOADED = 'fp-loaded'; var SECTION_DEFAULT_SEL = '.section'; var SECTION = 'fp-section'; var SECTION_SEL = '.' + SECTION; var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; var TABLE_CELL = 'fp-tableCell'; var TABLE_CELL_SEL = '.' + TABLE_CELL; var AUTO_HEIGHT = 'fp-auto-height'; var AUTO_HEIGHT_SEL = '.' + AUTO_HEIGHT; var AUTO_HEIGHT_RESPONSIVE = 'fp-auto-height-responsive'; var AUTO_HEIGHT_RESPONSIVE_SEL = '.' + AUTO_HEIGHT_RESPONSIVE; var NORMAL_SCROLL = 'fp-normal-scroll'; var SECTION_NAV = 'fp-nav'; var SECTION_NAV_SEL = '#' + SECTION_NAV; var SECTION_NAV_TOOLTIP = 'fp-tooltip'; var SECTION_NAV_TOOLTIP_SEL = '.' + SECTION_NAV_TOOLTIP; var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; // slide var SLIDE_DEFAULT_SEL = '.slide'; var SLIDE = 'fp-slide'; var SLIDE_SEL = '.' + SLIDE; var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; var SLIDES_WRAPPER = 'fp-slides'; var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; var SLIDES_CONTAINER = 'fp-slidesContainer'; var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; var TABLE = 'fp-table'; var OVERFLOW = 'fp-overflow'; var OVERFLOW_SEL = '.' + OVERFLOW; var IS_OVERFLOW = 'fp-is-overflow'; // slide nav var SLIDES_NAV = 'fp-slidesNav'; var SLIDES_NAV_SEL = '.' + SLIDES_NAV; var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; var SLIDES_STYLED_ARROW = 'fp-arrow'; var SLIDES_ARROW = 'fp-controlArrow'; var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; var SLIDES_PREV = 'fp-prev'; var SLIDES_PREV_SEL = '.' + SLIDES_PREV; var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; var SLIDES_NEXT = 'fp-next'; var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; // Watermark var WATERMARK = 'fp-watermark'; var WATERMARK_SEL = '.' + WATERMARK; var defaultOptions = { //navigation menu: false, anchors: [], lockAnchors: false, navigation: false, navigationPosition: 'right', navigationTooltips: [], showActiveTooltip: false, slidesNavigation: false, slidesNavPosition: 'bottom', scrollBar: false, hybrid: false, licenseKey: '', credits: { "enabled": true, "label": 'Made with fullPage.js', "position": 'right' }, //scrolling css3: true, scrollingSpeed: 700, autoScrolling: true, fitToSection: true, fitToSectionDelay: 600, easing: 'easeInOutCubic', easingcss3: 'ease', loopBottom: false, loopTop: false, loopHorizontal: true, continuousVertical: false, continuousHorizontal: false, scrollHorizontally: false, interlockedSlides: false, dragAndMove: false, offsetSections: false, resetSliders: false, fadingEffect: false, normalScrollElements: null, scrollOverflow: true, scrollOverflowReset: false, skipIntermediateItems: false, touchSensitivity: 5, touchWrapper: null, bigSectionsDestination: null, adjustOnNavChange: true, //Accessibility keyboardScrolling: true, animateAnchor: true, recordHistory: true, allowCorrectDirection: false, //design scrollOverflowMacStyle: true, controlArrows: true, controlArrowsHTML: ['<div class="' + SLIDES_STYLED_ARROW + '"></div>', '<div class="' + SLIDES_STYLED_ARROW + '"></div>'], controlArrowColor: '#fff', verticalCentered: true, sectionsColor: [], paddingTop: 0, paddingBottom: 0, fixedElements: null, responsive: 0, //backwards compabitility with responsiveWiddth responsiveWidth: 0, responsiveHeight: 0, responsiveSlides: false, parallax: false, parallaxOptions: { type: 'reveal', percentage: 62, property: 'translate' }, cards: false, cardsOptions: { perspective: 100, fadeContent: true, fadeBackground: true }, //Custom selectors sectionSelector: SECTION_DEFAULT_SEL, slideSelector: SLIDE_DEFAULT_SEL, //events afterLoad: null, beforeLeave: null, onLeave: null, afterRender: null, afterResize: null, afterReBuild: null, afterSlideLoad: null, onSlideLeave: null, afterResponsive: null, onScrollOverflow: null, lazyLoading: true, lazyLoadThreshold: 0, observer: true, scrollBeyondFullpage: true }; var container = null; var g_initialAnchorsInDom = false; var originals = deepExtend({}, defaultOptions); //deep copy var g_options = null; function getInitialAnchorsInDom() { return g_initialAnchorsInDom; } function setContainer(value) { container = value; } function getContainer(value) { return container; } function getOptions() { return g_options || defaultOptions; } function setOptions(options) { g_options = deepExtend({}, defaultOptions, options); originals = Object.assign({}, g_options); } function getOriginals() { return originals; } function setOption(name, value) { defaultOptions[name] = value; } /* * Sets the state for a variable with multiple states (original, and temporal) * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. * This function is used to keep track of both states, the original and the temporal one. * If type is not 'internal', then we assume the user is globally changing the variable. */ function setVariableState(variable, value, type) { g_options[variable] = value; if (type !== 'internal') { originals[variable] = value; } } /** * Setting options from DOM elements if they are not provided. */ function setOptionsFromDOM() { //no anchors option? Checking for them in the DOM attributes if (!getOptions().anchors.length) { var anchorsAttribute = '[data-anchor]'; var anchors = $(getOptions().sectionSelector.split(',').join(anchorsAttribute + ',') + anchorsAttribute, container); if (anchors.length && anchors.length === $(getOptions().sectionSelector, container).length) { g_initialAnchorsInDom = true; anchors.forEach(function (item) { getOptions().anchors.push(getAttr(item, 'data-anchor').toString()); }); } } //no tooltips option? Checking for them in the DOM attributes if (!getOptions().navigationTooltips.length) { var tooltipsAttribute = '[data-tooltip]'; var tooltips = $(getOptions().sectionSelector.split(',').join(tooltipsAttribute + ',') + tooltipsAttribute, container); if (tooltips.length) { tooltips.forEach(function (item) { getOptions().navigationTooltips.push(getAttr(item, 'data-tooltip').toString()); }); } } } var plainItem = function plainItem(panel) { this.anchor = panel.anchor; this.item = panel.item; this.index = panel.index(); this.isLast = this.index === panel.item.parentElement.querySelectorAll(panel.selector).length - 1; this.isFirst = !this.index; this.isActive = panel.isActive; }; /** * Item. Slide or Section objects share the same properties. */ var Item = function Item(el, selector) { this.parent = this.parent || null; this.selector = selector; this.anchor = getAttr(el, 'data-anchor') || getOptions().anchors[index(el, getOptions().sectionSelector)]; this.item = el; this.isVisible = isVisible(el); this.isActive = hasClass(el, ACTIVE); this.hasScroll = hasClass(el, OVERFLOW) || $(OVERFLOW_SEL, el)[0] != null; this.isSection = selector === getOptions().sectionSelector; this.container = closest(el, SLIDES_CONTAINER_SEL) || closest(el, WRAPPER_SEL); this.index = function () { return this.siblings().indexOf(this); }; }; Item.prototype.siblings = function () { if (this.isSection) { if (this.isVisible) { return state.sections; } else { return state.sectionsIncludingHidden; } } return this.parent ? this.parent.slides : 0; }; Item.prototype.prev = function () { var siblings = this.siblings(); var currentIndex = this.isSection ? siblings.indexOf(this) : this.parent.slides.indexOf(this); var prevIndex = currentIndex - 1; if (prevIndex >= 0) { return siblings[prevIndex]; } return null; }; Item.prototype.next = function () { var siblings = this.siblings(); var currentIndex = this.isSection ? siblings.indexOf(this) : this.parent.slides.indexOf(this); var nextIndex = currentIndex + 1; if (nextIndex < siblings.length) { return siblings[nextIndex]; } return null; }; Item.prototype["prevPanel"] = function () { return this.prev() || (this.parent ? this.parent.prev() : null); }; Item.prototype["nextPanel"] = function () { return this.next() || (this.parent ? this.parent.next() : null); }; Item.prototype.getSiblings = function () { if (this.isSection) { return state.sections; } return state.panels; }; function getNodes(panels) { return panels.map(function (panel) { return panel.item; }); } function getPanelByElement(panels, el) { return panels.find(function (panel) { return panel.item === el; }); } var Section = function Section(el) { plainItem.call(this, el); }; var Slide = function Slide(el) { plainItem.call(this, el); }; /** * Gets the active slide (or section) for the given section */ function getSlideOrSection(destiny) { var slide = $(SLIDE_ACTIVE_SEL, destiny); if (slide.length) { destiny = slide[0]; } return destiny; } function getSlideOrSectionPanel(panel) { if (!panel) { return null; } return panel.activeSlide ? panel.activeSlide : panel; } function isFullPageAbove() { return getContainer().getBoundingClientRect().bottom >= 0; } /** * Gets the scrolling settings depending on the plugin autoScrolling option */ function getScrollSettings(top) { var options = getOptions(); var position; var element; //top property animation if (options.autoScrolling && !options.scrollBar) { position = -top; element = $(WRAPPER_SEL)[0]; } //window real scrolling else { position = top; element = window; } return { options: position, element: element }; } /** * Scrolls the page / slider the given number of pixels. * It will do it one or another way dependiong on the library's config. */ function setScrolling(element, val) { if (!getOptions().autoScrolling || getOptions().scrollBar || element.self != window && hasClass(element, SLIDES_WRAPPER)) { //scrolling horizontally through the slides? if (element.self != window && hasClass(element, SLIDES_WRAPPER)) { element.scrollLeft = val; } //vertical scroll else { element.scrollTo(0, val); } } else { element.style.top = val + 'px'; } } /** * Adds transition animations for the given element */ function addAnimation(element) { var transition = 'transform ' + getOptions().scrollingSpeed + 'ms ' + getOptions().easingcss3; removeClass(element, NO_TRANSITION); return css(element, { '-webkit-transition': transition, 'transition': transition }); } /** * Retuns `up` or `down` depending on the scrolling movement to reach its destination * from the current section. */ function getYmovement(activeSection, destiny) { var fromIndex = activeSection.index(); var toIndex = index(destiny, SECTION_SEL); if (fromIndex == toIndex) { return 'none'; } if (fromIndex > toIndex) { return 'up'; } return 'down'; } /** * Remove transition animations for the given element */ function removeAnimation(element) { return addClass(element, NO_TRANSITION); } /** * Returns the cross-browser transform string. */ function getTransforms(translate3d) { return { '-webkit-transform': translate3d, '-moz-transform': translate3d, '-ms-transform': translate3d, 'transform': translate3d }; } var silentScrollId; /** * Adds a css3 transform property to the container class with or without animation depending on the animated param. */ function transformContainer(translate3d, animated) { if (animated) { addAnimation(getContainer()); } else { removeAnimation(getContainer()); } clearTimeout(silentScrollId); css(getContainer(), getTransforms(translate3d)); FP.test.translate3d = translate3d; //syncronously removing the class after the animation has been applied. silentScrollId = setTimeout(function () { removeClass(getContainer(), NO_TRANSITION); }, 10); } /** * Scrolls silently (with no animation) the page to the given Y position. */ function silentScroll(top) { // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 // that's why we round it to 0. var roundedTop = Math.round(top); if (getOptions().css3 && getOptions().autoScrolling && !getOptions().scrollBar) { var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; transformContainer(translate3d, false); } else if (getOptions().autoScrolling && !getOptions().scrollBar) { css(getContainer(), { 'top': -roundedTop + 'px' }); FP.test.top = -roundedTop + 'px'; } else { var scrollSettings = getScrollSettings(roundedTop); setScrolling(scrollSettings.element, scrollSettings.options); } } FP.setScrollingSpeed = setScrollingSpeed; /** * Defines the scrolling speed */ function setScrollingSpeed(value, type) { setVariableState('scrollingSpeed', value, type); } var $body = null; var $html = null; var $htmlBody = null; // caching common elements function setCache() { $body = $('body')[0]; $html = $('html')[0]; $htmlBody = $('html, body'); } //@ts-check var _g_animateScroll; /** * Simulates the animated scrollTop of jQuery. Used when css3:false or scrollBar:true or autoScrolling:false * http://stackoverflow.com/a/16136789/1081396 */ function scrollTo(element, to, duration, callback) { var start = getScrolledPosition(element); var change = to - start; var isCallbackFired = false; var startTime; var wasAnimationActive = state.activeAnimation; setState({ activeAnimation: true }); // Cancelling any possible previous animations (io: clicking on nav dots very fast) if (_g_animateScroll) { window.cancelAnimationFrame(_g_animateScroll); } _g_animateScroll = function g_animateScroll(timestamp) { if (!startTime) { startTime = timestamp; } var currentTime = Math.floor(timestamp - startTime); if (state.activeAnimation) { //in order to stope it from other function whenever we want var val = to; if (duration) { // @ts-ignore val = win.fp_easings[getOptions().easing](currentTime, start, change, duration); } if (currentTime <= duration) { setScrolling(element, val); } if (currentTime < duration) { window.requestAnimationFrame(_g_animateScroll); } else if (typeof callback !== 'undefined' && !isCallbackFired) { setScrolling(element, to); callback(); setState({ activeAnimation: false }); isCallbackFired = true; } } else if (!isCallbackFired && !wasAnimationActive) { callback(); setState({ activeAnimation: false }); isCallbackFired = true; } }; window.requestAnimationFrame(_g_animateScroll); } /** * Getting the position of the element to scroll when using jQuery animations */ function getScrolledPosition(element) { var position; //is not the window element and is a slide? if (element.self != win && hasClass(element, SLIDES_WRAPPER)) { position = element.scrollLeft; } else if (!getOptions().autoScrolling || getOptions().scrollBar) { position = getScrollTop(); } else { position = element.offsetTop; } //gets the top property of the wrapper return position; } /** * Makes sure to only create a Panel object if the element exist */ function nullOrSection(el) { if (el && !el.item) { return new Section(new SectionPanel(el)); } return el ? new Section(el) : null; } function nullOrSlide(el) { return el ? new Slide(el) : null; } /** * Dispatch events & callbacks */ function fireCallback(eventName, v) { var eventData = getEventData(eventName, v); trigger(getContainer(), eventName, eventData); if (getOptions()[eventName].apply(eventData[Object.keys(eventData)[0]], toArray(eventData)) === false) { return false; } return true; } /** * Gets the event's data for the given event on the right format. */ function getEventData(eventName, v) { //using functions to run only the necessary bits within the object var paramsPerEvent = { afterRender: function afterRender() { return { section: nullOrSection(getState().activeSection), slide: nullOrSlide(getState().activeSection.activeSlide) }; }, onLeave: function onLeave() { return { origin: nullOrSection(v.items.origin), destination: nullOrSection(v.items.destination), directio