/** * fullPage Pure Javascript v.0.0.8 (Alpha) - Not support given until Beta version. * https://github.com/alvarotrigo/fullPage.js * MIT licensed * * Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo */ (function (root, window, document, factory, undefined) { if (typeof define === "function" && define.amd) { // AMD. Register as an anonymous module. define(function () { root.fullpage = factory(window, document); return root.fullpage; }); } else if (typeof exports === "object") { // Node. Does not work with strict CommonJS. module.exports = factory(window, document); } else { // Browser globals. window.fullpage = factory(window, document); } })(this, window, document, function (window, document, undefined) { "use strict"; var fullpage; //CONSTANTS // keeping central set of classnames and selectors var WRAPPER = "fullpage-wrapper"; var WRAPPER_SEL = "." + WRAPPER; // util 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; // section var SECTION_DEFAULT_SEL = ".section"; var SECTION = "fp-section"; var SECTION_SEL = "." + SECTION; var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; // section nav var SECTION_NAV = "fp-nav"; var SECTION_NAV_SEL = "#" + SECTION_NAV; var SECTION_NAV_TOOLTIP = "fp-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"; // slide nav var SLIDES_NAV = "fp-slidesNav"; var SLIDES_NAV_SEL = "." + SLIDES_NAV; var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + " a"; 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 = SLIDES_ARROW + " " + 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 = SLIDES_ARROW + " " + SLIDES_NEXT; var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; //globals var options; var slideMoving = false; var isTouchDevice = navigator.userAgent.match( /(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/ ); var isTouch = "ontouchstart" in window || navigator.msMaxTouchPoints > 0 || navigator.maxTouchPoints; var windowsHeight = getWindowHeight(); var isResizing = false; var lastScrolledDestiny; var lastScrolledSlide; var canScroll = true; var scrollings = []; var nav; var activeAnimation; var originals; var container; //easeInOutCubic animation included in the plugin Math.easeInOutCubic = function (t, b, c, d) { if ((t /= d / 2) < 1) return (c / 2) * t * t * t + b; return (c / 2) * ((t -= 2) * t * t + 2) + b; }; function initialize(element, customOptions) { // Create some defaults, extending them with any options that were provided var defaults = { //navigation menu: false, anchors: [], navigation: false, navigationPosition: "right", navigationColor: "#000", navigationTooltips: [], showActiveTooltip: false, slidesNavigation: false, slidesNavPosition: "bottom", scrollBar: true, //scrolling css3: true, scrollingSpeed: 1000, autoScrolling: true, fitToSection: false, fitToSectionDelay: 0, easingcss3: "ease", loopHorizontal: true, touchSensitivity: 5, //Accessibility keyboardScrolling: true, recordHistory: true, //design controlArrows: true, //Custom selectors sectionSelector: SECTION_DEFAULT_SEL, slideSelector: SLIDE_DEFAULT_SEL, //events afterLoad: null, onLeave: null, afterRender: null, afterResize: null, afterReBuild: null, afterSlideLoad: null, onSlideLeave: null }; options = extend(defaults, customOptions); originals = clone(options); //deep copy container = $(element); init(afterDomReady); } function init(callback) { removeClass(container, DESTROYED); //in case it was destroyed before initilizing it again displayWarnings(); //if css3 is not supported, it will use jQuery animations if (options.css3) { options.css3 = support3d(); } if (container !== null) { css(container, { height: "100%", position: "relative" }); //adding a class to recognize the container internally in the code addClass(container, WRAPPER); addClass($("html"), ENABLED); } //trying to use fullpage without a selector? else { showError( "error", "Error! Fullpage.js needs to be initialized with a selector. For example: fullpage('#fullpage');" ); } setMouseWheelScrolling(true); addTouchHandler(); addResizeHandler(); addScrollHandler(); //adding internal class names to void problem with common ones var originalSections = $$(options.sectionSelector); for (i = 0; i < originalSections.length; ++i) { addClass(originalSections[i], SECTION); } var originalSlides = $$(options.slideSelector); for (i = 0; i < originalSlides.length; ++i) { addClass(originalSlides[i], SLIDE); } //creating the navigation dots if (options.navigation) { addVerticalNavigation(); } var sections = $$(SECTION_SEL); for (var i = 0; i < sections.length; i++) { var index = i; var section = sections[i]; var that = section; var slides = $$(SLIDE_SEL, section); var numSlides = slides.length; //if no active section is defined, the 1st one will be the default one if (!index && $(SECTION_ACTIVE_SEL) === null) { addClass(section, ACTIVE); } if (typeof options.anchors[index] !== "undefined") { section.setAttribute("data-anchor", options.anchors[index]); //activating the menu / nav element on load if (hasClass(section, ACTIVE)) { activateMenuAndNav(options.anchors[index], index); } } // if there's any slide if (numSlides > 0) { var sliderWidth = numSlides * 100; var slideWidth = 100 / numSlides; var slidesHTML = section.innerHTML; var newHTML = '
' + slidesHTML + "
"; section.innerHTML = newHTML; //getting again the NEW dom elements after innerHTML slides = $$(SLIDE_SEL, section); setCss($(SLIDES_CONTAINER_SEL, section), "width", sliderWidth + "%"); if (options.controlArrows && numSlides > 1) { createSlideArrows(section); } if (options.slidesNavigation) { addSlidesNavigation(section, numSlides); } for (var a = 0; a < slides.length; a++) { var currentSlide = slides[a]; setCss(currentSlide, "width", slideWidth + "%"); } var startingSlide = $(SLIDE_ACTIVE_SEL, section); //if the slide won#t be an starting point, the default will be the first one if (typeof startingSlide !== null) { addClass(slides[0], ACTIVE); } //is there a starting point for a non-starting section? else { silentLandscapeScroll(startingSlide); } } } callback(); } function afterDomReady() { //adding event for horizontal slides arrows navigation var slidesArrows = $$(SLIDES_ARROW_SEL); for (var i = 0; i < slidesArrows.length; i++) { addListenerMulti( slidesArrows[i], "click onclick touchstart", arrowsHandler ); } setAutoScrolling(options.autoScrolling, "internal"); //the starting point is a slide? var activeSection = $(SECTION_ACTIVE_SEL); var activeSlide = $(SLIDE_ACTIVE_SEL, activeSection); var activeSectionIndex = getNodeIndex($(SECTION_ACTIVE_SEL)); //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/slide by default. if ( activeSlide && (activeSectionIndex !== 0 || (activeSectionIndex === 0 && getNodeIndex(activeSlide) !== 0)) ) { silentLandscapeScroll(activeSlide); } //vertical centered of the navigation + first bullet active if (options.navigation) { setCss(nav, "margin-top", "-" + nav.offsetHeight / 2 + "px"); var activeLi = $$("li", nav)[getNodeIndex($(SECTION_ACTIVE_SEL))]; addClass($("a", activeLi), ACTIVE); } afterRenderActions(); //getting the anchor link in the URL and deleting the `#` var value = window.location.hash.replace("#", "").split("/"); var destiny = value[0]; if (destiny.length) { var section = $('[data-anchor="' + destiny + '"]'); if (!options.animateAnchor && section.length) { if (options.autoScrolling) { silentScroll(section.offsetTop); } else { silentScroll(0); setBodyClass(destiny); //scrolling the page to the section with no animation var scrollSettings = getScrollSettings(section.offsetTop); scrollTo(scrollSettings.element, scrollSettings.options, 0); } activateMenuAndNav(destiny, null); isFunction(options.afterLoad) && options.afterLoad.call(section, destiny, getNodeIndex(section) + 1); //updating the active class removeClass(activeSection, ACTIVE); addClass(section, ACTIVE); } } //setting the class for the body element setBodyClass(); //support for IE > 8 addHandler( document, scrollToAnchor, "DOMContentLoaded", "DOMContentLoaded", "DOMContentLoaded" ); } /* --------------- Javascript helpers ---------------*/ /** * Replacement of jQuery extend method. */ function extend(defaultOptions, options) { //creating the object if it doesnt exist if (typeof options !== "object") { options = {}; } for (var key in options) { if (defaultOptions.hasOwnProperty(key)) { defaultOptions[key] = options[key]; } } return defaultOptions; } function getById(element) { return document.getElementById(element); } function getByTag(element) { return document.getElementsByTagName(element)[0]; } function css(el, props) { var key; for (key in props) { if (props.hasOwnProperty(key)) { if (key !== null) { el.style[key] = props[key]; } } } return el; } function setCss(element, style, value) { element.style[style] = value; } function $(selector, context) { context = context || document; return context.querySelector(selector); } function $$(selector, context) { context = context || document; return context.querySelectorAll(selector); } function getNodeIndex(node) { var index = 0; while ((node = node.previousSibling)) { if (node.nodeType != 3 || !/^\s*$/.test(node.data)) { index++; } } return index; } function toggle(element, display) { if (typeof display !== "undefined") { if (display) { element.style.display = "block"; } else { element.style.display = "none"; } } else { if (element.style.display == "block") { element.style.display = "none"; } else { element.style.display = "block"; } } return element; } //http://jaketrent.com/post/addremove-classes-raw-javascript/ function hasClass(ele, cls) { return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)")); } function removeClass(element, className) { if (element && hasClass(element, className)) { var reg = new RegExp("(\\s|^)" + className + "(\\s|$)"); element.className = element.className.replace(reg, ""); } } function addClass(element, className) { if (element && !hasClass(element, className)) { element.className += " " + className; } } //http://stackoverflow.com/questions/22100853/dom-pure-javascript-solution-to-jquery-closest-implementation function closest(el, fn) { return el && (fn(el) ? el : closest(el.parentNode, fn)); } function getWindowWidth() { return "innerWidth" in window ? window.innerWidth : document.documentElement.offsetWidth; } function getWindowHeight() { return "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight; } function clone(obj) { if (null === obj || "object" !== typeof obj) { return obj; } var copy = obj.constructor(); for (var attr in obj) { if (obj.hasOwnProperty(attr)) { copy[attr] = obj[attr]; } } return copy; } function preventDefault(event) { event.preventDefault ? event.preventDefault() : (event.returnValue = false); } function isFunction(functionToCheck) { var getType = {}; return ( functionToCheck && getType.toString.call(functionToCheck) === "[object Function]" ); } function addListenerMulti(el, s, fn) { var evts = s.split(" "); for (var i = 0, iLen = evts.length; i < iLen; i++) { if (document.addEventListener) { el.addEventListener(evts[i], fn, false); } else { el.attachEvent(evts[i], fn, false); //IE 6/7/8 } } } /** * 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 currentTime = 0; var increment = 20; activeAnimation = true; var animateScroll = function () { if (activeAnimation) { //in order to stope it from other function whenever we want var val = to; currentTime += increment; val = Math.easeInOutCubic(currentTime, start, change, duration); setScrolling(element, val); if (currentTime < duration) { setTimeout(animateScroll, increment); } else if (typeof callback !== "undefined") { callback(); } } else if (currentTime < duration) { callback(); } }; animateScroll(); } //http://stackoverflow.com/questions/3464876/javascript-get-window-x-y-position-for-scroll function getScrollTop() { var doc = document.documentElement; return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); } //http://stackoverflow.com/questions/842336/is-there-a-way-to-select-sibling-nodes function getChildren(n, skipMe) { var r = []; for (; n; n = n.nextSibling) if (n.nodeType == 1 && n != skipMe) r.push(n); return r; } //Gets siblings function getAllSiblings(n) { return getChildren(n.parentNode.firstChild, n); } function next(element) { var nextSibling = element.nextSibling; while (nextSibling && nextSibling.nodeType != 1) { nextSibling = nextSibling.nextSibling; } return nextSibling; } function prev(element) { var prevSibling = element.previousSibling; while (prevSibling && prevSibling.nodeType != 1) { prevSibling = prevSibling.previousSibling; } return prevSibling; } /* --------------- END Javascript helpers ---------------*/ /** * 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 != window && hasClass(element, SLIDES_WRAPPER)) { position = element.scrollLeft; } else if (!options.autoScrolling || options.scrollBar) { position = getScrollTop(); } else { position = element.offsetTop; } //gets the top property of the wrapper return position; } function setScrolling(element, val) { if ( !options.autoScrolling || options.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"; } } function setAutoScrolling(value, type) { setVariableState("autoScrolling", value, type); var element = $(SECTION_ACTIVE_SEL); if (options.autoScrolling && !options.scrollBar) { css(document.body, { overflow: "hidden", height: "100%" }); css(getByTag("html"), { overflow: "hidden", height: "100%" }); setRecordHistory(options.recordHistory, "internal"); //for IE touch devices css(container, { "-ms-touch-action": "none", "touch-action": "none" }); if (element) { //moving the container up silentScroll(element.offsetTop); } } else { css(document.body, { overflow: "visible", height: "100%" }); css(getByTag("html"), { overflow: "visible", height: "100%" }); setRecordHistory(false, "internal"); //for IE touch devices css(container, { "-ms-touch-action": "", "touch-action": "" }); silentScroll(0); //scrolling the page to the section with no animation var scrollSettings = getScrollSettings(element.offsetTop); scrollSettings.element.scrollTo(0, scrollSettings.options); } } /** * Defines wheter to record the history for each hash change in the URL. */ function setRecordHistory(value, type) { setVariableState("recordHistory", value, type); } /** * Defines the scrolling speed */ function setScrollingSpeed(value, type) { setVariableState("scrollingSpeed", value, type); } /** * Sets fitToSection */ function setFitToSection(value, type) { setVariableState("fitToSection", value, type); } /** * Adds or removes the possiblity of scrolling through sections by using the mouse wheel or the trackpad. */ function setMouseWheelScrolling(value) { if (value) { addMouseWheelHandler(); } else { removeMouseWheelHandler(); } } /** * Adds or removes the possiblity of scrolling through sections by using the keyboard arrow keys */ function setKeyboardScrolling(value) { options.keyboardScrolling = value; } /** * Moves the page up one section. */ function moveSectionUp() { var section = prev($(SECTION_ACTIVE_SEL)); if (section) { scrollPage(section, null, true); } } /** * Moves the page down one section. */ function moveSectionDown() { var section = next($(SECTION_ACTIVE_SEL)); if (section) { scrollPage(section, null, false); } } /** * Moves the page to the given section and slide with no animation. * Anchors or index positions can be used as params. */ function silentMoveTo(sectionAnchor, slideAnchor) { setScrollingSpeed(0, "internal"); moveTo(sectionAnchor, slideAnchor); setScrollingSpeed(originals.scrollingSpeed, "internal"); } /** * Moves the page to the given section and slide. * Anchors or index positions can be used as params. */ function moveTo(sectionAnchor, slideAnchor) { var destiny = getSectionByAnchor(sectionAnchor); if (typeof slideAnchor !== "undefined") { scrollPageAndSlide(sectionAnchor, slideAnchor); } else if (destiny) { scrollPage(destiny); } } /** * Slides right the slider of the active section. */ function moveSlideRight() { moveSlide("next"); } /** * Slides left the slider of the active section. */ function moveSlideLeft() { moveSlide("prev"); } /** * When resizing is finished, we adjust the slides sizes and positions */ function reBuild(resizing) { if (hasClass(container, DESTROYED)) { return; } isResizing = true; windowsHeight = getWindowHeight(); var sections = $$(SECTION_SEL); for (var i = 0; i < sections.length; ++i) { var section = sections[i]; var slidesWrap = $(SLIDES_WRAPPER_SEL, section); var slides = $$(SLIDE_SEL, section); //adjusting the position fo the FULL WIDTH slides... if (slidesWrap && slides.length > 1) { landscapeScroll(slidesWrap, $(SLIDE_ACTIVE_SEL, slidesWrap)); } } var activeSection = $(SECTION_ACTIVE_SEL); //isn't it the first section? if (getNodeIndex(activeSection)) { //adjusting the position for the current section silentScroll(activeSection.offsetTop); } isResizing = false; isFunction(options.afterResize) && resizing && options.afterResize.call(container); isFunction(options.afterReBuild) && !resizing && options.afterReBuild.call(container); } /** * Creates the control arrows for the given section */ function createSlideArrows(section) { var prev = document.createElement("div"); prev.className = SLIDES_ARROW_PREV; var next = document.createElement("div"); next.className = SLIDES_ARROW_NEXT; var slides = $(SLIDES_WRAPPER_SEL, section); if (options.controlArrowColor != "#fff") { //setCss(next, 'border-color', 'transparent transparent transparent '+options.controlArrowColor); //setCss(prev, 'border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); } slides.parentNode.appendChild(prev); slides.parentNode.appendChild(next); if (!options.loopHorizontal) { $(SLIDES_ARROW_PREV_SEL, section).style.display = "none"; } } /** * Creates a vertical navigation bar. */ function addVerticalNavigation() { var div = document.createElement("div"); div.setAttribute("id", SECTION_NAV); var divUl = document.createElement("ul"); div.appendChild(divUl); document.body.appendChild(div); nav = $(SECTION_NAV_SEL); setCss(nav, "color", options.navigationColor); addClass(nav, options.navigationPosition); if (options.showActiveTooltip) { addClass(nav, SHOW_ACTIVE_TOOLTIP); } var li = ""; for (var i = 0; i < $$(SECTION_SEL).length; i++) { var link = ""; if (options.anchors.length) { link = options.anchors[i]; } li = li + '
  • '; // Only add tooltip if needed (defined by user) var tooltip = options.navigationTooltips[i]; if (typeof tooltip !== undefined && tooltip !== "") { li += '
    ' + tooltip + "
    "; } li += "
  • "; } var ul = $("ul", nav); ul.innerHTML = ul.innerHTML + li; //creating the event listener var links = $$(SLIDES_NAV_LINK_SEL); for (var l = 0; l < links.length; l++) { addListenerMulti(links[l], "click onclick touchstart", function (e) { e = window.event || e || e.originalEvent; preventDefault(e); var index = getNodeIndex(this.parentNode); scrollPage($$(SECTION_SEL)[index], null, false); }); } } /** * Actions and callbacks to fire afterRender */ function afterRenderActions() { var section = $(SECTION_ACTIVE_SEL); isFunction(options.afterLoad) && options.afterLoad.call( section, section.getAttribute("data-anchor"), getNodeIndex(section) + 1 ); isFunction(options.afterRender) && options.afterRender.call(container); } var scrollId; var scrollId2; var isScrolling = false; //when scrolling function scrollHandler() { var currentSection; if (!options.autoScrolling || options.scrollBar) { var currentScroll = getScrollTop(); var visibleSectionIndex = 0; var initial = Math.abs(currentScroll - $$(SECTION_SEL)[0].offsetTop); //taking the section which is showing more content in the viewport var sections = $$(SECTION_SEL); for (var i = 0; i < sections.length; ++i) { var section = sections[i]; var current = Math.abs(currentScroll - section.offsetTop); if (current < initial) { visibleSectionIndex = i; initial = current; } } //geting the last one, the current one on the screen currentSection = $$(SECTION_SEL)[visibleSectionIndex]; } if (!options.autoScrolling || options.scrollBar) { //executing it only once the first time we reach the section if (!hasClass(currentSection, ACTIVE)) { isScrolling = true; var leavingSection = $(SECTION_ACTIVE_SEL); var leavingSectionIndex = getNodeIndex(leavingSection) + 1; var yMovement = getYmovement(currentSection); var anchorLink = currentSection.getAttribute("data-anchor"); var sectionIndex = getNodeIndex(currentSection) + 1; var activeSlide = $(SLIDE_ACTIVE_SEL, currentSection); if (activeSlide) { var slideAnchorLink = activeSlide.getAttribute("data-anchor"); var slideIndex = getNodeIndex(activeSlide); } if (canScroll) { //removing siblings active class removeClass(leavingSection, ACTIVE); //adding the active class to the current active section addClass(currentSection, ACTIVE); isFunction(options.onLeave) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement ); isFunction(options.afterLoad) && options.afterLoad.call(currentSection, anchorLink, sectionIndex); activateMenuAndNav(anchorLink, 0); if (options.anchors.length) { //needed to enter in hashChange event when using the menu with anchor links lastScrolledDestiny = anchorLink; setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); } } //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet clearTimeout(scrollId); scrollId = setTimeout(function () { isScrolling = false; }, 100); } if (options.fitToSection) { //for the auto adjust of the viewport to fit a whole section clearTimeout(scrollId2); scrollId2 = setTimeout(function () { if ((canScroll && !options.autoScrolling) || options.scrollBar) { //allows to scroll to an active section and //if the section is already active, we prevent firing callbacks if ( getNodeIndex($(SECTION_ACTIVE_SEL)) == getNodeIndex(currentSection) ) { isResizing = true; } scrollPage(currentSection); isResizing = false; } }, options.fitToSectionDelay); } } } /** * Determines the way of scrolling up or down: * by 'automatically' scrolling a section or by using the default and normal scrolling. */ function scrolling(type) { if (type == "down") { moveSectionDown(); } else { moveSectionUp(); } } var touchStartY = 0; var touchStartX = 0; var touchEndY = 0; var touchEndX = 0; /* Detecting touch events * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. * This way, the touchstart and the touch moves shows an small difference between them which is the * used one to determine the direction. */ function touchMoveHandler(event) { var e = window.event || event || event.originalEvent; if (isReallyTouch(e)) { if (options.autoScrolling) { //preventing the easing on iOS devices preventDefault(event); } var activeSection = $(SECTION_ACTIVE_SEL); var slides = $$(SLIDES_WRAPPER_SEL, activeSection); if (canScroll && !slideMoving) { //if theres any # var touchEvents = getEventsPage(e); touchEndY = touchEvents.y; touchEndX = touchEvents.x; //if movement in the X axys is greater than in the Y and the currect section has slides... if ( slides && Math.abs(touchStartX - touchEndX) > Math.abs(touchStartY - touchEndY) ) { //is the movement greater than the minimum resistance to scroll? if ( Math.abs(touchStartX - touchEndX) > (getWindowWidth() / 100) * options.touchSensitivity ) { if (touchStartX > touchEndX) { moveSlideRight(); //next } else { moveSlideLeft(); //prev } } } //vertical scrolling (only when autoScrolling is enabled) else if (options.autoScrolling) { //is the movement greater than the minimum resistance to scroll? if ( Math.abs(touchStartY - touchEndY) > (getWindowHeight() / 100) * options.touchSensitivity ) { if (touchStartY > touchEndY) { scrolling("down"); } else if (touchEndY > touchStartY) { scrolling("up"); } } } } } } /** * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen * this way we make sure that is really a touch event what IE is detecting. */ function isReallyTouch(e) { //if is not IE || IE is detecting `touch` or `pen` return typeof e.pointerType === "undefined" || e.pointerType != "mouse"; } /** * Handler for the touch start event. */ function touchStartHandler(event) { var e = window.event || event || event.originalEvent; //stopping the auto scroll to adjust to a section if (options.fitToSection) { activeAnimation = false; } if (isReallyTouch(e)) { var touchEvents = getEventsPage(e); touchStartY = touchEvents.y; touchStartX = touchEvents.x; } } /** * 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); } /** * Detecting mousewheel scrolling * * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html * http://www.sitepoint.com/html5-javascript-mouse-wheel/ */ var prevTime = new Date().getTime(); function MouseWheelHandler(e) { var curTime = new Date().getTime(); if (options.autoScrolling) { // cross-browser wheel delta e = window.event || e || e.originalEvent; var value = e.wheelDelta || -e.deltaY || -e.detail; var delta = Math.max(-1, Math.min(1, value)); //Limiting the array to 150 (lets not waist memory!) if (scrollings.length > 149) { scrollings.shift(); } //keeping record of the previous scrollings scrollings.push(Math.abs(value)); //preventing to scroll the site on mouse wheel when scrollbar is present if (options.scrollBar) { preventDefault(e); } var timeDiff = curTime - prevTime; prevTime = curTime; //haven't they scrolled in a while? //(enough to be consider a different scrolling action to scroll another section) if (timeDiff > 200) { //emptying the array, we dont care about old scrollings for our averages scrollings = []; } if (canScroll) { //if theres any # var averageEnd = getAverage(scrollings, 10); var averageMiddle = getAverage(scrollings, 70); var isAccelerating = averageEnd >= averageMiddle; if (isAccelerating) { //scrolling down? if (delta < 0) { scrolling("down"); //scrolling up? } else { scrolling("up"); } } } return false; } if (options.fitToSection) { //stopping the auto scroll to adjust to a section activeAnimation = false; } } /** * Slides a slider to the given direction. */ function moveSlide(direction) { var activeSection = $(SECTION_ACTIVE_SEL); var slides = $(SLIDES_WRAPPER_SEL, activeSection); // more than one slide needed and nothing should be sliding if (!slides || slideMoving) { return; } var currentSlide = $(SLIDE_ACTIVE_SEL, slides); var destiny = null; if (direction === "prev") { destiny = prev(currentSlide); } else { destiny = next(currentSlide); } //isn't there a next slide in the secuence? if (!destiny) { //respect loopHorizontal settin if (!options.loopHorizontal) return; var siblings = getAllSiblings(currentSlide); if (direction === "prev") { destiny = siblings[siblings.length - 1]; //last } else { destiny = siblings[0]; //first } } slideMoving = true; landscapeScroll(slides, destiny); } /** * Maintains the active slides in the viewport * (Because he `scroll` animation might get lost with some actions) */ function keepSlidesPosition() { var activeSlides = $$(SLIDE_ACTIVE_SEL); for (var i = 0; i < activeSlides.length; i++) { silentLandscapeScroll(activeSlides[i], "internal"); } } /** * Scrolls the site to the given element and scrolls to the slide if a callback is given. */ function scrollPage(element, callback, isMovementUp) { if (element === null) { return; } //there's no element to scroll, leaving the function //local variables var v = { element: element, callback: callback, isMovementUp: isMovementUp, dtop: element.offsetTop, yMovement: getYmovement(element), anchorLink: element.getAttribute("data-anchor"), sectionIndex: getNodeIndex(element), activeSlide: $(SLIDE_ACTIVE_SEL, element), activeSection: $(SECTION_ACTIVE_SEL), leavingSection: getNodeIndex($(SECTION_ACTIVE_SEL)) + 1, //caching the value of isResizing at the momment the function is called //because it will be checked later inside a setTimeout and the value might change localIsResizing: isResizing }; //quiting when destination scroll is the same as the current one if ( (getNodeIndex(v.activeSection) == v.sectionIndex && !isResizing) || (options.scrollBar && getScrollTop() === v.dtop) ) { return; } if (v.activeSlide) { var slideAnchorLink = v.activeSlide.getAttribute("data-anchor"); var slideIndex = getNodeIndex(v.activeSlide); } var siblings = $$(SECTION_SEL); for (var s = 0; s < siblings.length; s++) { removeClass(siblings[s], ACTIVE); } addClass(element, ACTIVE); //preventing from activating the MouseWheelHandler event //more than once if the page is scrolling canScroll = false; setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); //callback (onLeave) if the site is not just resizing and readjusting the slides isFunction(options.onLeave) && !v.localIsResizing && options.onLeave.call( v.activeSection, v.leavingSection, v.sectionIndex + 1, v.yMovement ); performMovement(v); //flag to avoid callingn `scrollPage()` twice in case of using anchor links lastScrolledDestiny = v.anchorLink; activateMenuAndNav(v.anchorLink, v.sectionIndex); } /** * Performs the movement (by CSS3 or by jQuery) */ function performMovement(v) { // using CSS3 translate functionality if (options.css3 && options.autoScrolling && !options.scrollBar) { var translate3d = "translate3d(0px, -" + v.dtop + "px, 0px)"; transformContainer(translate3d, true); //even when the scrollingSpeed is 0 there's a little delay, which might cause the //scrollingSpeed to change in case of using silentMoveTo(); if (options.scrollingSpeed) { setTimeout(function () { afterSectionLoads(v); }, options.scrollingSpeed); } else { afterSectionLoads(v); } } // using jQuery animate else { var scrollSettings = getScrollSettings(v.dtop); scrollTo( scrollSettings.element, scrollSettings.options, options.scrollingSpeed, function () { afterSectionLoads(v); } ); } } /** * Gets the scrolling settings depending on the plugin autoScrolling option */ function getScrollSettings(top) { var scroll = {}; //top property animation if (options.autoScrolling && !options.scrollBar) { scroll.options = -top; scroll.element = $("." + WRAPPER); } //window real scrolling else { scroll.options = top; scroll.element = window; } return scroll; } /** * Actions to do once the section is loaded */ function afterSectionLoads(v) { //callback (afterLoad) if the site is not just resizing and readjusting the slides isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, v.sectionIndex + 1); canScroll = true; isFunction(v.callback) && v.callback.call(this); } /** * Scrolls to the anchor in the URL when loading the site */ function scrollToAnchor() { //getting the anchor link in the URL and deleting the `#` var value = window.location.hash.replace("#", "").split("/"); var section = value[0]; var slide = value[1]; if (section) { //if theres any # scrollPageAndSlide(section, slide); } } //detecting any change on the URL to scroll to the given anchor link //(a way to detect back history button as we play with the hashes on the URL) if (document.addEventListener) { window.addEventListener("hashchange", hashChangeHandler, false); //IE9, Chrome, Safari, Oper } else { window.attachEvent("onhashchange", hashChangeHandler); //IE 6/7/8 } function arrowsHandler(event) { var element = this; //IE 8 (using attach event...) //http://stackoverflow.com/a/4590231/1081396 if (element.self == window) { element = event.target || event.srcElement; } if (hasClass(element, SLIDES_PREV)) { moveSlideLeft(); } else { moveSlideRight(); } } function hashChangeHandler() { if (!isScrolling) { var value = window.location.hash.replace("#", "").split("/"); var section = value[0]; var slide = value[1]; if (section.length) { //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) var isFirstSlideMove = typeof lastScrolledDestiny === "undefined"; var isFirstScrollMove = typeof lastScrolledDestiny === "undefined" && typeof slide === "undefined" && !slideMoving; /*in order to call scrollpage() only once for each destination at a time It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` event is fired on every scroll too.*/ if ( (section && section !== lastScrolledDestiny && !isFirstSlideMove) || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slide) ) { scrollPageAndSlide(section, slide); } } } } /** * Sliding with arrow keys, both, vertical and horizontal */ var keydownId; document.onkeydown = function (e) { clearTimeout(keydownId); var activeElement = document.activeElement; var tagName = activeElement.tagName; if ( tagName !== "SELECT" && tagName !== "INPUT" && options.keyboardScrolling && options.autoScrolling ) { e = window.event || e || e.originalEvent; var charCode = e.charCode || e.keyCode; //preventing the scroll with arrow keys & spacebar & Page Up & Down keys var keyControls = [40, 38, 32, 33, 34]; for (var i = 0; i < keyControls.length; i++) { if (keyControls[i] == charCode) { preventDefault(e); } } var shiftPressed = e.shiftKey; keydownId = setTimeout(function () { onkeydown(shiftPressed, charCode); }, 150); } }; function onkeydown(shiftPressed, charCode) { switch (charCode) { //up case 38: case 33: moveSectionUp(); break; //down case 32: //spacebar if (shiftPressed) { moveSectionUp(); break; } case 40: case 34: moveSectionDown(); break; //Home case 36: moveTo(1); break; //End case 35: moveTo($$(SECTION_SEL).length); break; //left case 37: moveSlideLeft(); break; //right case 39: moveSlideRight(); break; default: return; // exit this handler for other keys } } /** * Scrolls the slider to the given slide destination for the given section */ var slidesNav = $(SLIDES_NAV_LINK_SEL); if (slidesNav !== null) { addListenerMulti( $(SLIDES_NAV_LINK_SEL), "click onclick touchstart", function (e) { preventDefault(e); //equivalent to: var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); var section = closest(this, function (el) { return hasClass(e1, SECTION); }); var slides = $(SLIDES_WRAPPER_SEL, section); var li = closest(this, function (el) { return el.tagName === "li"; }); var liIndex = getNodeIndex(li); var destiny = $$(SLIDE_SEL, slides)[liIndex]; landscapeScroll(slides, destiny); } ); } /** * Scrolling horizontally when clicking on the slider controls. */ // $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, function() { // if ($(this).hasClass(SLIDES_PREV)) { // moveSlideLeft(); // } else { // moveSlideRight(); // } // }); /** * Scrolls horizontal sliders. */ function landscapeScroll(slides, destiny) { var slideIndex = getNodeIndex(destiny); //equivalent to slides.closest(SECTION_SEL) var section = closest(slides, function (e1) { return hasClass(e1, SECTION); }); var sectionIndex = getNodeIndex(section); var anchorLink = section.getAttribute("data-anchor"); var slidesNav = $(SLIDES_NAV_SEL, section); var slideAnchor = getSlideAnchor(destiny); //caching the value of isResizing at the momment the function is called //because it will be checked later inside a setTimeout and the value might change var localIsResizing = isResizing; if (options.onSlideLeave) { var prevSlide = $(SLIDE_ACTIVE_SEL, section); var prevSlideIndex = getNodeIndex(prevSlide); var xMovement = getXmovement(prevSlideIndex, slideIndex); //if the site is not just resizing and readjusting the slides if (!localIsResizing && xMovement !== "none") { isFunction(options.onSlideLeave) && options.onSlideLeave.call( prevSlide, anchorLink, sectionIndex + 1, prevSlideIndex, xMovement ); } } var siblings = $$(SLIDE_SEL, section); for (var s = 0; s < siblings.length; s++) { removeClass(siblings[s], ACTIVE); } addClass(destiny, ACTIVE); if (!options.loopHorizontal && options.controlArrows) { //hidding it for the fist slide, showing for the rest toggle($(SLIDES_ARROW_PREV_SEL, section), slideIndex !== 0); //hidding it for the last slide, showing for the rest toggle($(SLIDES_ARROW_NEXT_SEL, section), !destiny.is(":last-child")); } //only changing the URL if the slides are in the current section (not for resize re-adjusting) if (hasClass(section, ACTIVE)) { setState(slideIndex, slideAnchor, anchorLink, sectionIndex); } var afterSlideLoads = function () { //if the site is not just resizing and readjusting the slides if (!localIsResizing) { isFunction(options.afterSlideLoad) && options.afterSlideLoad.call( destiny, anchorLink, sectionIndex + 1, slideAnchor, slideIndex ); } //letting them slide again slideMoving = false; }; if (options.css3) { var translate3d = "translate3d(-" + Math.round(destiny.offsetLeft) + "px, 0px, 0px)"; var slidesContainer = $(SLIDES_CONTAINER_SEL, slides); addAnimation(slidesContainer, options.scrollingSpeed > 0); setTransforms(slidesContainer, translate3d); setTimeout( function () { afterSlideLoads(); }, options.scrollingSpeed, options.easing ); } else { scrollTo( slides, Math.round(destiny.offsetLeft), options.scrollingSpeed, function () { afterSlideLoads(); } ); } if (options.slidesNavigation) { removeClass($(ACTIVE_SEL, slidesNav), ACTIVE); var activeNavLi = $$("li", slidesNav)[slideIndex]; var activeLink = $("a", activeNavLi); addClass(activeLink, ACTIVE); } } //when resizing the site, we adjust the heights of the sections var previousHeight = windowsHeight; var resizeId; function resizeHandler() { // rebuild immediately on touch devices if (isTouchDevice) { //if the keyboard is visible if (document.activeElement.getAttribute("type") !== "text") { var currentHeight = getWindowHeight(); //making sure the change in the viewport size is enough to force a rebuild. (20 % of the window to avoid problems when hidding scroll bars) if ( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight)) / 100 ) { reBuild(true); previousHeight = currentHeight; } } } else { //in order to call the functions only when the resize is finished //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing clearTimeout(resizeId); resizeId = setTimeout(function () { reBuild(true); }, 350); } } /** * Adds transition animations for the given element */ function addAnimation(element) { var transition = "all " + options.scrollingSpeed + "ms " + options.easingcss3; removeClass(element, NO_TRANSITION); css(element, { "-webkit-transition": transition, transition: transition }); return element; } /** * Remove transition animations for the given element */ function removeAnimation(element) { return addClass(element, NO_TRANSITION); } /** * Activating the website navigation dots according to the given slide name. */ function activateNavDots(name, sectionIndex) { if (options.navigation) { removeClass($(ACTIVE_SEL, nav), ACTIVE); if (name) { addClass($('a[href="#' + name + '"]', nav), ACTIVE); } else { var currentLi = $$("li", nav)[sectionIndex]; addClass($("a", currentLi), ACTIVE); } } } /** * Activating the website main menu elements according to the given slide name. */ function activateMenuElement(name) { if (options.menu) { var menu = $(options.menu); if (menu) { removeClass($(ACTIVE_SEL, menu), ACTIVE); addClass($('[data-menuanchor="' + name + '"]', menu), ACTIVE); } } } function activateMenuAndNav(anchor, index) { activateMenuElement(anchor); activateNavDots(anchor, index); } /** * Retuns `up` or `down` depending on the scrolling movement to reach its destination * from the current section. */ function getYmovement(destiny) { var fromIndex = getNodeIndex($(SECTION_ACTIVE_SEL)); var toIndex = getNodeIndex(destiny); if (fromIndex == toIndex) { return "none"; } if (fromIndex > toIndex) { return "up"; } return "down"; } /** * Retuns `right` or `left` depending on the scrolling movement to reach its destination * from the current slide. */ function getXmovement(fromIndex, toIndex) { if (fromIndex == toIndex) { return "none"; } if (fromIndex > toIndex) { return "left"; } return "right"; } /** * 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(container); } else { removeAnimation(container); } setTransforms(container, translate3d); //syncronously removing the class after the animation has been applied. setTimeout(function () { removeClass(container, NO_TRANSITION); }, 10); } /** * Gets a section by its anchor / index */ function getSectionByAnchor(sectionAnchor) { //section var section = $(SECTION_SEL + '[data-anchor="' + sectionAnchor + '"]'); if (!section) { section = $$(SECTION_SEL)[sectionAnchor - 1]; } return section; } /** * Gets a slide inside a given section by its anchor / index */ function getSlideByAnchor(slideAnchor, section) { var slides = $(SLIDES_WRAPPER_SEL, section); var slide = $(SLIDE_SEL + '[data-anchor="' + slideAnchor + '"]', slides); if (slides && !slide) { slide = $$(SLIDE_SEL, slides)[slideAnchor]; } return slide; } /** * Scrolls to the given section and slide */ function scrollPageAndSlide(destiny, slide) { var section = getSectionByAnchor(decodeURI(destiny)); if (typeof slide === "undefined") { slide = 0; } //we need to scroll to the section and then to the slide if (destiny !== lastScrolledDestiny && !hasClass(section, ACTIVE)) { scrollPage(section, function () { scrollSlider(section, slide); }); } //if we were already in the section else { scrollSlider(section, slide); } } /** * Scrolls the slider to the given slide destination for the given section */ function scrollSlider(section, slideAnchor) { if (typeof slideAnchor !== "undefined") { var slides = $(SLIDES_WRAPPER_SEL, section); var destiny = getSlideByAnchor(slideAnchor, section); if (destiny) { landscapeScroll(slides, destiny); } } } /** * Creates a landscape navigation bar with dots for horizontal sliders. */ function addSlidesNavigation(section, numSlides) { var div = document.createElement("div"); div.className = SLIDES_NAV; var divUl = document.createElement("ul"); div.appendChild(divUl); section.appendChild(div); var nav = $(SLIDES_NAV_SEL, section); var ul = $("ul", nav); //top or bottom addClass(nav, options.slidesNavPosition); var list = ""; for (var i = 0; i < numSlides; i++) { list = list + '
  • '; } ul.innerHTML = ul.innerHTML + list; //centering it setCss(nav, "margin-left", "-" + nav.offsetWidth / 2 + "px"); var firstLi = $$("li", nav)[0]; addClass($("a", firstLi), ACTIVE); } /** * Sets the state of the website depending on the active section/slide. * It changes the URL hash when needed and updates the body class. */ function setState(slideIndex, slideAnchor, anchorLink, sectionIndex) { var sectionHash = ""; if (options.anchors.length) { //isn't it the first slide? if (slideIndex) { if (typeof anchorLink !== "undefined") { sectionHash = anchorLink; } //slide without anchor link? We take the index instead. if (typeof slideAnchor === "undefined") { slideAnchor = slideIndex; } lastScrolledSlide = slideAnchor; setUrlHash(sectionHash + "/" + slideAnchor); //first slide won't have slide anchor, just the section one } else if (typeof slideIndex !== "undefined") { lastScrolledSlide = slideAnchor; setUrlHash(anchorLink); } //section without slides else { setUrlHash(anchorLink); } } setBodyClass(); } /** * Sets the URL hash. */ function setUrlHash(url) { if (options.recordHistory) { location.hash = url; } else { //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) if (isTouchDevice || isTouch) { history.replaceState(undefined, undefined, "#" + url); } else { var baseUrl = window.location.href.split("#")[0]; window.location.replace(baseUrl + "#" + url); } } } /** * Gets the anchor for the given slide. Its index will be used if there's none. */ function getSlideAnchor(slide) { var slideAnchor = slide.getAttribute("data-anchor"); var slideIndex = getNodeIndex(slide); //Slide without anchor link? We take the index instead. if (!slideAnchor) { slideAnchor = slideIndex; } return slideAnchor; } /** * Sets a class for the body of the page depending on the active section / slide */ function setBodyClass(text) { var section = $(SECTION_ACTIVE_SEL); var slide = $(SLIDE_ACTIVE_SEL, section); var sectionAnchor = section.getAttribute("data-anchor"); var sectionIndex = getNodeIndex(section); var text = String(sectionIndex); if (options.anchors.length) { text = sectionAnchor; } if (slide) { var slideAnchor = getSlideAnchor(slide); text = text + "-" + slideAnchor; } //changing slash for dash to make it a valid CSS style text = text.replace("/", "-").replace("#", ""); //removing previous anchor classes var classRe = new RegExp("\\b\\s?" + VIEWING_PREFIX + "-[^\\s]+\\b", "g"); document.body.className = document.body.className.replace(classRe, ""); //adding the current anchor addClass(document.body, VIEWING_PREFIX + "-" + text); } /** * Checks for translate3d support * @return boolean * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support */ function support3d() { var el = document.createElement("p"), has3d, transforms = { webkitTransform: "-webkit-transform", OTransform: "-o-transform", msTransform: "-ms-transform", MozTransform: "-moz-transform", transform: "transform" }; // Add it to the body to get the computed style. document.body.insertBefore(el, null); for (var t in transforms) { if (el.style[t] !== undefined) { el.style[t] = "translate3d(1px,1px,1px)"; has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); } } document.body.removeChild(el); return has3d !== undefined && has3d.length > 0 && has3d !== "none"; } /** * Removes the auto scrolling action fired by the mouse wheel and trackpad. * After this function is called, the mousewheel and trackpad movements won't scroll through sections. */ function removeMouseWheelHandler() { var wrapper = $(WRAPPER_SEL); if (document.addEventListener) { wrapper.removeEventListener("mousewheel", MouseWheelHandler, false); //IE9, Chrome, Safari, Oper wrapper.removeEventListener("wheel", MouseWheelHandler, false); //Firefox } else { wrapper.detachEvent("onmousewheel", MouseWheelHandler); //IE 6/7/8 } } /** * Adds the auto scrolling action for the mouse wheel and trackpad. * After this function is called, the mousewheel and trackpad movements will scroll through sections */ function addMouseWheelHandler() { addHandler( $(WRAPPER_SEL), MouseWheelHandler, "mousewheel", "onmousewheel", "wheel" ); } function addResizeHandler() { addHandler(window, resizeHandler, "resize", "onresize"); } function addScrollHandler() { addHandler(window, scrollHandler, "scroll", "onscroll", "onscroll"); } function addHandler(element, method, normal, oldIE, firefox) { if (element.addEventListener) { element.addEventListener(normal, method, false); //IE9, Chrome, Safari, Oper if (typeof firefox !== "undefined") { element.addEventListener(firefox, method, false); //Firefox } } else { element.attachEvent(oldIE, method); //IE 6/7/8 } } /** * Adds the possibility to auto scroll through sections on touch devices. */ function addTouchHandler() { if (isTouchDevice || isTouch) { var wrapper = $(WRAPPER_SEL); if (document.addEventListener) { //Microsoft pointers var MSPointer = getMSPointer(); wrapper.removeEventListener("touchstart", touchStartHandler); wrapper.removeEventListener(MSPointer.down, touchStartHandler); wrapper.removeEventListener("touchmove", touchMoveHandler); wrapper.removeEventListener(MSPointer.move, touchMoveHandler); addListenerMulti( wrapper, "touchstart " + MSPointer.down, touchStartHandler ); addListenerMulti( wrapper, "touchmove " + MSPointer.move, touchMoveHandler ); } } } /** * Removes the auto scrolling for touch devices. */ function removeTouchHandler() { if (isTouchDevice || isTouch) { var wrapper = $(WRAPPER_SEL); if (wrapper.addEventListener) { //Microsoft pointers var MSPointer = getMSPointer(); wrapper.removeEventListener("touchstart", touchStartHandler); wrapper.removeEventListener(MSPointer.down, touchStartHandler); wrapper.removeEventListener("touchmove", touchMoveHandler); wrapper.removeEventListener(MSPointer.move, touchMoveHandler); } } } /* * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11) * https://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx */ function getMSPointer() { var pointer; //IE >= 11 & rest of browsers if (window.PointerEvent) { pointer = { down: "pointerdown", move: "pointermove" }; } //IE < 11 else { pointer = { down: "MSPointerDown", move: "MSPointerMove" }; } return pointer; } /** * Gets the pageX and pageY properties depending on the browser. * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 */ function getEventsPage(e) { var events = []; events.y = typeof e.pageY !== "undefined" && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY; events.x = typeof e.pageX !== "undefined" && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX; //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 if (isTouch && isReallyTouch(e)) { events.y = e.touches[0].pageY; events.x = e.touches[0].pageX; } return events; } function silentLandscapeScroll(activeSlide, noCallbacks) { setScrollingSpeed(0, "internal"); if (typeof noCallbacks !== "undefined") { //preventing firing callbacks afterSlideLoad etc. isResizing = true; } //equivalent to: activeSlide.closest(SLIDES_WRAPPER_SEL) var slides = closest(activeSlide, function (el) { return hasClass(el, SLIDES_WRAPPER); }); landscapeScroll(slides, activeSlide); if (typeof noCallbacks !== "undefined") { isResizing = false; } setScrollingSpeed(originals.scrollingSpeed, "internal"); } function silentScroll(top) { if (options.scrollBar) { var scrollSettings = getScrollSettings(top); setScrolling(scrollSettings.element, scrollSettings.options, 0); } else if (options.css3) { var translate3d = "translate3d(0px, -" + top + "px, 0px)"; transformContainer(translate3d, false); } else { setCss(container, "top", -top + "px"); } } function setTransforms(element, translate3d) { css(element, { "-webkit-transform": translate3d, "-moz-transform": translate3d, "-ms-transform": translate3d, transform: translate3d }); } /* * 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) { options[variable] = value; if (type !== "internal") { originals[variable] = value; } } /** * Displays warnings */ function displayWarnings() { //anchors can not have the same value as any element ID or NAME for (var i = 0; i < options.anchors.length; i++) { var name = options.anchors[i]; var existId = getById("#" + name); if (existId || $$('[name="' + name + '"]').length) { showError( "error", "data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE)." ); } } } /** * Shows a message in the console of the given type. */ function showError(type, text) { console && console[type] && console[type]("fullPage: " + text); } //API fullpage = { initialize: initialize, moveSectionUp: moveSectionUp, moveSectionDown: moveSectionDown, moveTo: moveTo, silentMoveTo: silentMoveTo, moveSlideRight: moveSlideRight, moveSlideLeft: moveSlideLeft, setAutoScrolling: setAutoScrolling, setFitToSection: setFitToSection, setKeyboardScrolling: setKeyboardScrolling, setRecordHistory: setRecordHistory, setScrollingSpeed: setScrollingSpeed }; return fullpage; });