Shreygupta (Talk | contribs) |
Shreygupta (Talk | contribs) |
||
Line 235: | Line 235: | ||
</div> | </div> | ||
<script> | <script> | ||
− | + | $(document).ready(function() { | |
− | jQuery('#fullpage').fullpage(); | + | $('#fullpage').fullpage(); |
+ | }); | ||
+ | </script> | ||
+ | <script> | ||
+ | /*! | ||
+ | * fullPage 2.9.5 | ||
+ | * https://github.com/alvarotrigo/fullPage.js | ||
+ | * @license MIT licensed | ||
+ | * | ||
+ | * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo | ||
+ | */ | ||
+ | (function(global, factory) { | ||
+ | 'use strict'; | ||
+ | if (typeof define === 'function' && define.amd) { | ||
+ | define(['jquery'], function($) { | ||
+ | return factory($, global, global.document, global.Math); | ||
+ | }); | ||
+ | } else if (typeof exports === "object" && exports) { | ||
+ | module.exports = factory(require('jquery'), global, global.document, global.Math); | ||
+ | } else { | ||
+ | factory(jQuery, global, global.document, global.Math); | ||
+ | } | ||
+ | })(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { | ||
+ | 'use strict'; | ||
+ | |||
+ | // keeping central set of classnames and selectors | ||
+ | var WRAPPER = 'fullpage-wrapper'; | ||
+ | var WRAPPER_SEL = '.' + WRAPPER; | ||
+ | |||
+ | // slimscroll | ||
+ | var SCROLLABLE = 'fp-scrollable'; | ||
+ | var SCROLLABLE_SEL = '.' + SCROLLABLE; | ||
+ | |||
+ | // 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; | ||
+ | var COMPLETELY = 'fp-completely'; | ||
+ | var COMPLETELY_SEL = '.' + COMPLETELY; | ||
+ | |||
+ | // section | ||
+ | var SECTION_DEFAULT_SEL = '.section'; | ||
+ | var SECTION = 'fp-section'; | ||
+ | var SECTION_SEL = '.' + SECTION; | ||
+ | var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; | ||
+ | var SECTION_FIRST_SEL = SECTION_SEL + ':first'; | ||
+ | var SECTION_LAST_SEL = SECTION_SEL + ':last'; | ||
+ | var TABLE_CELL = 'fp-tableCell'; | ||
+ | var TABLE_CELL_SEL = '.' + TABLE_CELL; | ||
+ | var AUTO_HEIGHT = 'fp-auto-height'; | ||
+ | var AUTO_HEIGHT_SEL = '.fp-auto-height'; | ||
+ | var NORMAL_SCROLL = 'fp-normal-scroll'; | ||
+ | var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; | ||
+ | |||
+ | // section nav | ||
+ | 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'; | ||
+ | |||
+ | // 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; | ||
+ | |||
+ | var $window = $(window); | ||
+ | var $document = $(document); | ||
+ | |||
+ | $.fn.fullpage = function(options) { | ||
+ | //only once my friend! | ||
+ | if($('html').hasClass(ENABLED)){ displayWarnings(); return; } | ||
+ | |||
+ | // common jQuery objects | ||
+ | var $htmlBody = $('html, body'); | ||
+ | var $body = $('body'); | ||
+ | |||
+ | var FP = $.fn.fullpage; | ||
+ | |||
+ | // Creating some defaults, extending them with any options that were provided | ||
+ | options = $.extend({ | ||
+ | //navigation | ||
+ | menu: false, | ||
+ | anchors:[], | ||
+ | lockAnchors: false, | ||
+ | navigation: false, | ||
+ | navigationPosition: 'right', | ||
+ | navigationTooltips: [], | ||
+ | showActiveTooltip: false, | ||
+ | slidesNavigation: false, | ||
+ | slidesNavPosition: 'bottom', | ||
+ | scrollBar: false, | ||
+ | hybrid: false, | ||
+ | |||
+ | //scrolling | ||
+ | css3: true, | ||
+ | scrollingSpeed: 700, | ||
+ | autoScrolling: true, | ||
+ | fitToSection: true, | ||
+ | fitToSectionDelay: 1000, | ||
+ | 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: false, | ||
+ | scrollOverflowReset: false, | ||
+ | scrollOverflowHandler: $.fn.fp_scrolloverflow ? $.fn.fp_scrolloverflow.iscrollHandler : null, | ||
+ | scrollOverflowOptions: null, | ||
+ | touchSensitivity: 5, | ||
+ | normalScrollElementTouchThreshold: 5, | ||
+ | bigSectionsDestination: null, | ||
+ | |||
+ | //Accessibility | ||
+ | keyboardScrolling: true, | ||
+ | animateAnchor: true, | ||
+ | recordHistory: true, | ||
+ | |||
+ | //design | ||
+ | controlArrows: true, | ||
+ | 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' | ||
+ | }, | ||
+ | |||
+ | //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, | ||
+ | afterResponsive: null, | ||
+ | |||
+ | lazyLoading: true | ||
+ | }, options); | ||
+ | |||
+ | //flag to avoid very fast sliding for landscape sliders | ||
+ | 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 container = $(this); | ||
+ | var windowsHeight = $window.height(); | ||
+ | var isResizing = false; | ||
+ | var isWindowFocused = true; | ||
+ | var lastScrolledDestiny; | ||
+ | var lastScrolledSlide; | ||
+ | var canScroll = true; | ||
+ | var scrollings = []; | ||
+ | var controlPressed; | ||
+ | var startingSection; | ||
+ | var isScrollAllowed = {}; | ||
+ | isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; | ||
+ | isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); | ||
+ | var MSPointer = getMSPointer(); | ||
+ | var events = { | ||
+ | touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, | ||
+ | touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down | ||
+ | }; | ||
+ | var scrollBarHandler; | ||
+ | |||
+ | //timeouts | ||
+ | var resizeId; | ||
+ | var afterSectionLoadsId; | ||
+ | var afterSlideLoadsId; | ||
+ | var scrollId; | ||
+ | var scrollId2; | ||
+ | var keydownId; | ||
+ | var originals = $.extend(true, {}, options); //deep copy | ||
+ | |||
+ | displayWarnings(); | ||
+ | |||
+ | //easeInOutCubic animation included in the plugin | ||
+ | $.extend($.easing,{ easeInOutCubic: function (x, 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;}}); | ||
+ | |||
+ | /** | ||
+ | * Sets the autoScroll option. | ||
+ | * It changes the scroll bar visibility and the history of the site as a result. | ||
+ | */ | ||
+ | function setAutoScrolling(value, type){ | ||
+ | //removing the transformation | ||
+ | if(!value){ | ||
+ | silentScroll(0); | ||
+ | } | ||
+ | |||
+ | setVariableState('autoScrolling', value, type); | ||
+ | |||
+ | var element = $(SECTION_ACTIVE_SEL); | ||
+ | |||
+ | if(options.autoScrolling && !options.scrollBar){ | ||
+ | $htmlBody.css({ | ||
+ | 'overflow' : 'hidden', | ||
+ | 'height' : '100%' | ||
+ | }); | ||
+ | |||
+ | setRecordHistory(originals.recordHistory, 'internal'); | ||
+ | |||
+ | //for IE touch devices | ||
+ | container.css({ | ||
+ | '-ms-touch-action': 'none', | ||
+ | 'touch-action': 'none' | ||
+ | }); | ||
+ | |||
+ | if(element.length){ | ||
+ | //moving the container up | ||
+ | silentScroll(element.position().top); | ||
+ | } | ||
+ | |||
+ | }else{ | ||
+ | $htmlBody.css({ | ||
+ | 'overflow' : 'visible', | ||
+ | 'height' : 'initial' | ||
+ | }); | ||
+ | |||
+ | setRecordHistory(false, 'internal'); | ||
+ | |||
+ | //for IE touch devices | ||
+ | container.css({ | ||
+ | '-ms-touch-action': '', | ||
+ | 'touch-action': '' | ||
+ | }); | ||
+ | |||
+ | //scrolling the page to the section with no animation | ||
+ | if (element.length) { | ||
+ | $htmlBody.scrollTop(element.position().top); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * 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); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Sets lockAnchors | ||
+ | */ | ||
+ | function setLockAnchors(value){ | ||
+ | options.lockAnchors = value; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds or remove the possibility of scrolling through sections by using the mouse wheel or the trackpad. | ||
+ | */ | ||
+ | function setMouseWheelScrolling(value){ | ||
+ | if(value){ | ||
+ | addMouseWheelHandler(); | ||
+ | addMiddleWheelHandler(); | ||
+ | }else{ | ||
+ | removeMouseWheelHandler(); | ||
+ | removeMiddleWheelHandler(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. | ||
+ | * Optionally a second parameter can be used to specify the direction for which the action will be applied. | ||
+ | * | ||
+ | * @param directions string containing the direction or directions separated by comma. | ||
+ | */ | ||
+ | function setAllowScrolling(value, directions){ | ||
+ | if(typeof directions !== 'undefined'){ | ||
+ | directions = directions.replace(/ /g,'').split(','); | ||
+ | |||
+ | $.each(directions, function (index, direction){ | ||
+ | setIsScrollAllowed(value, direction, 'm'); | ||
+ | }); | ||
+ | } | ||
+ | else{ | ||
+ | setIsScrollAllowed(value, 'all', 'm'); | ||
+ | |||
+ | if(value){ | ||
+ | setMouseWheelScrolling(true); | ||
+ | addTouchHandler(); | ||
+ | }else{ | ||
+ | setMouseWheelScrolling(false); | ||
+ | removeTouchHandler(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys | ||
+ | */ | ||
+ | function setKeyboardScrolling(value, directions){ | ||
+ | if(typeof directions !== 'undefined'){ | ||
+ | directions = directions.replace(/ /g,'').split(','); | ||
+ | |||
+ | $.each(directions, function (index, direction){ | ||
+ | setIsScrollAllowed(value, direction, 'k'); | ||
+ | }); | ||
+ | }else{ | ||
+ | setIsScrollAllowed(value, 'all', 'k'); | ||
+ | options.keyboardScrolling = value; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Moves the page up one section. | ||
+ | */ | ||
+ | function moveSectionUp(){ | ||
+ | var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); | ||
+ | |||
+ | //looping to the bottom if there's no more sections above | ||
+ | if (!prev.length && (options.loopTop || options.continuousVertical)) { | ||
+ | prev = $(SECTION_SEL).last(); | ||
+ | } | ||
+ | |||
+ | if (prev.length) { | ||
+ | scrollPage(prev, null, true); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Moves the page down one section. | ||
+ | */ | ||
+ | function moveSectionDown(){ | ||
+ | var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); | ||
+ | |||
+ | //looping to the top if there's no more sections below | ||
+ | if(!next.length && | ||
+ | (options.loopBottom || options.continuousVertical)){ | ||
+ | next = $(SECTION_SEL).first(); | ||
+ | } | ||
+ | |||
+ | if(next.length){ | ||
+ | scrollPage(next, 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.length > 0){ | ||
+ | scrollPage(destiny); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Slides right the slider of the active section. | ||
+ | * Optional `section` param. | ||
+ | */ | ||
+ | function moveSlideRight(section){ | ||
+ | moveSlide('right', section); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Slides left the slider of the active section. | ||
+ | * Optional `section` param. | ||
+ | */ | ||
+ | function moveSlideLeft(section){ | ||
+ | moveSlide('left', section); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * When resizing is finished, we adjust the slides sizes and positions | ||
+ | */ | ||
+ | function reBuild(resizing){ | ||
+ | if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed | ||
+ | |||
+ | isResizing = true; | ||
+ | |||
+ | windowsHeight = $window.height(); //updating global var | ||
+ | |||
+ | $(SECTION_SEL).each(function(){ | ||
+ | var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); | ||
+ | var slides = $(this).find(SLIDE_SEL); | ||
+ | |||
+ | //adjusting the height of the table-cell for IE and Firefox | ||
+ | if(options.verticalCentered){ | ||
+ | $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); | ||
+ | } | ||
+ | |||
+ | $(this).css('height', windowsHeight + 'px'); | ||
+ | |||
+ | //adjusting the position fo the FULL WIDTH slides... | ||
+ | if (slides.length > 1) { | ||
+ | landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | if(options.scrollOverflow){ | ||
+ | scrollBarHandler.createScrollBarForAll(); | ||
+ | } | ||
+ | |||
+ | var activeSection = $(SECTION_ACTIVE_SEL); | ||
+ | var sectionIndex = activeSection.index(SECTION_SEL); | ||
+ | |||
+ | //isn't it the first section? | ||
+ | if(sectionIndex){ | ||
+ | //adjusting the position for the current section | ||
+ | silentMoveTo(sectionIndex + 1); | ||
+ | } | ||
+ | |||
+ | isResizing = false; | ||
+ | $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); | ||
+ | $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` | ||
+ | * are smaller than the set limit values. | ||
+ | */ | ||
+ | function setResponsive(active){ | ||
+ | var isResponsive = $body.hasClass(RESPONSIVE); | ||
+ | |||
+ | if(active){ | ||
+ | if(!isResponsive){ | ||
+ | setAutoScrolling(false, 'internal'); | ||
+ | setFitToSection(false, 'internal'); | ||
+ | $(SECTION_NAV_SEL).hide(); | ||
+ | $body.addClass(RESPONSIVE); | ||
+ | $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); | ||
+ | } | ||
+ | } | ||
+ | else if(isResponsive){ | ||
+ | setAutoScrolling(originals.autoScrolling, 'internal'); | ||
+ | setFitToSection(originals.autoScrolling, 'internal'); | ||
+ | $(SECTION_NAV_SEL).show(); | ||
+ | $body.removeClass(RESPONSIVE); | ||
+ | $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if($(this).length){ | ||
+ | //public functions | ||
+ | FP.version = '2.9.5'; | ||
+ | FP.setAutoScrolling = setAutoScrolling; | ||
+ | FP.setRecordHistory = setRecordHistory; | ||
+ | FP.setScrollingSpeed = setScrollingSpeed; | ||
+ | FP.setFitToSection = setFitToSection; | ||
+ | FP.setLockAnchors = setLockAnchors; | ||
+ | FP.setMouseWheelScrolling = setMouseWheelScrolling; | ||
+ | FP.setAllowScrolling = setAllowScrolling; | ||
+ | FP.setKeyboardScrolling = setKeyboardScrolling; | ||
+ | FP.moveSectionUp = moveSectionUp; | ||
+ | FP.moveSectionDown = moveSectionDown; | ||
+ | FP.silentMoveTo = silentMoveTo; | ||
+ | FP.moveTo = moveTo; | ||
+ | FP.moveSlideRight = moveSlideRight; | ||
+ | FP.moveSlideLeft = moveSlideLeft; | ||
+ | FP.fitToSection = fitToSection; | ||
+ | FP.reBuild = reBuild; | ||
+ | FP.setResponsive = setResponsive; | ||
+ | FP.destroy = destroy; | ||
+ | |||
+ | //functions we want to share across files but which are not | ||
+ | //mean to be used on their own by developers | ||
+ | FP.shared ={ | ||
+ | afterRenderActions: afterRenderActions | ||
+ | }; | ||
+ | |||
+ | init(); | ||
+ | |||
+ | bindEvents(); | ||
+ | } | ||
+ | |||
+ | function init(){ | ||
+ | //if css3 is not supported, it will use jQuery animations | ||
+ | if(options.css3){ | ||
+ | options.css3 = support3d(); | ||
+ | } | ||
+ | |||
+ | options.scrollBar = options.scrollBar || options.hybrid; | ||
+ | |||
+ | setOptionsFromDOM(); | ||
+ | prepareDom(); | ||
+ | setAllowScrolling(true); | ||
+ | setAutoScrolling(options.autoScrolling, 'internal'); | ||
+ | responsive(); | ||
+ | |||
+ | //setting the class for the body element | ||
+ | setBodyClass(); | ||
+ | |||
+ | if(document.readyState === 'complete'){ | ||
+ | scrollToAnchor(); | ||
+ | } | ||
+ | $window.on('load', scrollToAnchor); | ||
+ | } | ||
+ | |||
+ | function bindEvents(){ | ||
+ | $window | ||
+ | //when scrolling... | ||
+ | .on('scroll', scrollHandler) | ||
+ | |||
+ | //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) | ||
+ | .on('hashchange', hashChangeHandler) | ||
+ | |||
+ | //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. | ||
+ | .blur(blurHandler) | ||
+ | |||
+ | //when resizing the site, we adjust the heights of the sections, slimScroll... | ||
+ | .resize(resizeHandler); | ||
+ | |||
+ | $document | ||
+ | //Sliding with arrow keys, both, vertical and horizontal | ||
+ | .keydown(keydownHandler) | ||
+ | |||
+ | //to prevent scrolling while zooming | ||
+ | .keyup(keyUpHandler) | ||
+ | |||
+ | //Scrolls to the section when clicking the navigation bullet | ||
+ | .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) | ||
+ | |||
+ | //Scrolls the slider to the given slide destination for the given section | ||
+ | .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) | ||
+ | |||
+ | .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); | ||
+ | |||
+ | //Scrolling horizontally when clicking on the slider controls. | ||
+ | $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); | ||
+ | |||
+ | /** | ||
+ | * Applying normalScroll elements. | ||
+ | * Ignoring the scrolls over the specified selectors. | ||
+ | */ | ||
+ | if(options.normalScrollElements){ | ||
+ | $document.on('mouseenter touchstart', options.normalScrollElements, function () { | ||
+ | setAllowScrolling(false); | ||
+ | }); | ||
+ | |||
+ | $document.on('mouseleave touchend', options.normalScrollElements, function(){ | ||
+ | setAllowScrolling(true); | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Setting options from DOM elements if they are not provided. | ||
+ | */ | ||
+ | function setOptionsFromDOM(){ | ||
+ | var sections = container.find(options.sectionSelector); | ||
+ | |||
+ | //no anchors option? Checking for them in the DOM attributes | ||
+ | if(!options.anchors.length){ | ||
+ | options.anchors = sections.filter('[data-anchor]').map(function(){ | ||
+ | return $(this).data('anchor').toString(); | ||
+ | }).get(); | ||
+ | } | ||
+ | |||
+ | //no tooltips option? Checking for them in the DOM attributes | ||
+ | if(!options.navigationTooltips.length){ | ||
+ | options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ | ||
+ | return $(this).data('tooltip').toString(); | ||
+ | }).get(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Works over the DOM structure to set it up for the current fullpage options. | ||
+ | */ | ||
+ | function prepareDom(){ | ||
+ | container.css({ | ||
+ | 'height': '100%', | ||
+ | 'position': 'relative' | ||
+ | }); | ||
+ | |||
+ | //adding a class to recognize the container internally in the code | ||
+ | container.addClass(WRAPPER); | ||
+ | $('html').addClass(ENABLED); | ||
+ | |||
+ | //due to https://github.com/alvarotrigo/fullPage.js/issues/1502 | ||
+ | windowsHeight = $window.height(); | ||
+ | |||
+ | container.removeClass(DESTROYED); //in case it was destroyed before initializing it again | ||
+ | |||
+ | addInternalSelectors(); | ||
+ | |||
+ | //styling the sections / slides / menu | ||
+ | $(SECTION_SEL).each(function(index){ | ||
+ | var section = $(this); | ||
+ | var slides = section.find(SLIDE_SEL); | ||
+ | var numSlides = slides.length; | ||
+ | |||
+ | styleSection(section, index); | ||
+ | styleMenu(section, index); | ||
+ | |||
+ | // if there's any slide | ||
+ | if (numSlides > 0) { | ||
+ | styleSlides(section, slides, numSlides); | ||
+ | }else{ | ||
+ | if(options.verticalCentered){ | ||
+ | addTableClass(section); | ||
+ | } | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | //fixed elements need to be moved out of the plugin container due to problems with CSS3. | ||
+ | if(options.fixedElements && options.css3){ | ||
+ | $(options.fixedElements).appendTo($body); | ||
+ | } | ||
+ | |||
+ | //vertical centered of the navigation + active bullet | ||
+ | if(options.navigation){ | ||
+ | addVerticalNavigation(); | ||
+ | } | ||
+ | |||
+ | enableYoutubeAPI(); | ||
+ | |||
+ | if(options.scrollOverflow){ | ||
+ | scrollBarHandler = options.scrollOverflowHandler.init(options); | ||
+ | }else{ | ||
+ | afterRenderActions(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Styles the horizontal slides for a section. | ||
+ | */ | ||
+ | function styleSlides(section, slides, numSlides){ | ||
+ | var sliderWidth = numSlides * 100; | ||
+ | var slideWidth = 100 / numSlides; | ||
+ | |||
+ | slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); | ||
+ | slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); | ||
+ | |||
+ | section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); | ||
+ | |||
+ | if(numSlides > 1){ | ||
+ | if(options.controlArrows){ | ||
+ | createSlideArrows(section); | ||
+ | } | ||
+ | |||
+ | if(options.slidesNavigation){ | ||
+ | addSlidesNavigation(section, numSlides); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | slides.each(function(index) { | ||
+ | $(this).css('width', slideWidth + '%'); | ||
+ | |||
+ | if(options.verticalCentered){ | ||
+ | addTableClass($(this)); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | var startingSlide = section.find(SLIDE_ACTIVE_SEL); | ||
+ | |||
+ | //if the slide won't be an starting point, the default will be the first one | ||
+ | //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( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ | ||
+ | silentLandscapeScroll(startingSlide, 'internal'); | ||
+ | }else{ | ||
+ | slides.eq(0).addClass(ACTIVE); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Styling vertical sections | ||
+ | */ | ||
+ | function styleSection(section, index){ | ||
+ | //if no active section is defined, the 1st one will be the default one | ||
+ | if(!index && $(SECTION_ACTIVE_SEL).length === 0) { | ||
+ | section.addClass(ACTIVE); | ||
+ | } | ||
+ | startingSection = $(SECTION_ACTIVE_SEL); | ||
+ | |||
+ | section.css('height', windowsHeight + 'px'); | ||
+ | |||
+ | if(options.paddingTop){ | ||
+ | section.css('padding-top', options.paddingTop); | ||
+ | } | ||
+ | |||
+ | if(options.paddingBottom){ | ||
+ | section.css('padding-bottom', options.paddingBottom); | ||
+ | } | ||
+ | |||
+ | if (typeof options.sectionsColor[index] !== 'undefined') { | ||
+ | section.css('background-color', options.sectionsColor[index]); | ||
+ | } | ||
+ | |||
+ | if (typeof options.anchors[index] !== 'undefined') { | ||
+ | section.attr('data-anchor', options.anchors[index]); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Sets the data-anchor attributes to the menu elements and activates the current one. | ||
+ | */ | ||
+ | function styleMenu(section, index){ | ||
+ | if (typeof options.anchors[index] !== 'undefined') { | ||
+ | //activating the menu / nav element on load | ||
+ | if(section.hasClass(ACTIVE)){ | ||
+ | activateMenuAndNav(options.anchors[index], index); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) | ||
+ | if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ | ||
+ | $(options.menu).appendTo($body); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds internal classes to be able to provide customizable selectors | ||
+ | * keeping the link with the style sheet. | ||
+ | */ | ||
+ | function addInternalSelectors(){ | ||
+ | container.find(options.sectionSelector).addClass(SECTION); | ||
+ | container.find(options.slideSelector).addClass(SLIDE); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Creates the control arrows for the given section | ||
+ | */ | ||
+ | function createSlideArrows(section){ | ||
+ | section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); | ||
+ | |||
+ | if(options.controlArrowColor!='#fff'){ | ||
+ | section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); | ||
+ | section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); | ||
+ | } | ||
+ | |||
+ | if(!options.loopHorizontal){ | ||
+ | section.find(SLIDES_ARROW_PREV_SEL).hide(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Creates a vertical navigation bar. | ||
+ | */ | ||
+ | function addVerticalNavigation(){ | ||
+ | $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); | ||
+ | var nav = $(SECTION_NAV_SEL); | ||
+ | |||
+ | nav.addClass(function() { | ||
+ | return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; | ||
+ | }); | ||
+ | |||
+ | for (var i = 0; i < $(SECTION_SEL).length; i++) { | ||
+ | var link = ''; | ||
+ | if (options.anchors.length) { | ||
+ | link = options.anchors[i]; | ||
+ | } | ||
+ | |||
+ | var li = '<li><a href="#' + link + '"><span></span></a>'; | ||
+ | |||
+ | // Only add tooltip if needed (defined by user) | ||
+ | var tooltip = options.navigationTooltips[i]; | ||
+ | |||
+ | if (typeof tooltip !== 'undefined' && tooltip !== '') { | ||
+ | li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; | ||
+ | } | ||
+ | |||
+ | li += '</li>'; | ||
+ | |||
+ | nav.find('ul').append(li); | ||
+ | } | ||
+ | |||
+ | //centering it vertically | ||
+ | $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); | ||
+ | |||
+ | //activating the current active section | ||
+ | $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | * Enables the Youtube videos API so we can control their flow if necessary. | ||
+ | */ | ||
+ | function enableYoutubeAPI(){ | ||
+ | container.find('iframe[src*="youtube.com/embed/"]').each(function(){ | ||
+ | addURLParam($(this), 'enablejsapi=1'); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds a new parameter and its value to the `src` of a given element | ||
+ | */ | ||
+ | function addURLParam(element, newParam){ | ||
+ | var originalSrc = element.attr('src'); | ||
+ | element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | * Returns the prefix sign to use for a new parameter in an existen URL. | ||
+ | * | ||
+ | * @return {String} ? | & | ||
+ | */ | ||
+ | function getUrlParamSign(url){ | ||
+ | return ( !/\?/.test( url ) ) ? '?' : '&'; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Actions and callbacks to fire afterRender | ||
+ | */ | ||
+ | function afterRenderActions(){ | ||
+ | var section = $(SECTION_ACTIVE_SEL); | ||
+ | |||
+ | section.addClass(COMPLETELY); | ||
+ | |||
+ | lazyLoad(section); | ||
+ | playMedia(section); | ||
+ | |||
+ | if(options.scrollOverflow){ | ||
+ | options.scrollOverflowHandler.afterLoad(); | ||
+ | } | ||
+ | |||
+ | if(isDestinyTheStartingSection()){ | ||
+ | $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); | ||
+ | } | ||
+ | |||
+ | $.isFunction( options.afterRender ) && options.afterRender.call(container); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) | ||
+ | */ | ||
+ | function isDestinyTheStartingSection(){ | ||
+ | var destinationSection = getSectionByAnchor(getAnchorsURL().section); | ||
+ | |||
+ | return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); | ||
+ | } | ||
+ | |||
+ | |||
+ | var isScrolling = false; | ||
+ | var lastScroll = 0; | ||
+ | |||
+ | //when scrolling... | ||
+ | function scrollHandler(){ | ||
+ | var currentSection; | ||
+ | |||
+ | if(!options.autoScrolling || options.scrollBar){ | ||
+ | var currentScroll = $window.scrollTop(); | ||
+ | var scrollDirection = getScrollDirection(currentScroll); | ||
+ | var visibleSectionIndex = 0; | ||
+ | var screen_mid = currentScroll + ($window.height() / 2.0); | ||
+ | var isAtBottom = $body.height() - $window.height() === currentScroll; | ||
+ | var sections = document.querySelectorAll(SECTION_SEL); | ||
+ | |||
+ | //when using `auto-height` for a small last section it won't be centered in the viewport | ||
+ | if(isAtBottom){ | ||
+ | visibleSectionIndex = sections.length - 1; | ||
+ | } | ||
+ | //is at top? when using `auto-height` for a small first section it won't be centered in the viewport | ||
+ | else if(!currentScroll){ | ||
+ | visibleSectionIndex = 0; | ||
+ | } | ||
+ | |||
+ | //taking the section which is showing more content in the viewport | ||
+ | else{ | ||
+ | for (var i = 0; i < sections.length; ++i) { | ||
+ | var section = sections[i]; | ||
+ | |||
+ | // Pick the the last section which passes the middle line of the screen. | ||
+ | if (section.offsetTop <= screen_mid) | ||
+ | { | ||
+ | visibleSectionIndex = i; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if(isCompletelyInViewPort(scrollDirection)){ | ||
+ | if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ | ||
+ | $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //geting the last one, the current one on the screen | ||
+ | currentSection = $(sections).eq(visibleSectionIndex); | ||
+ | |||
+ | //setting the visible section as active when manually scrolling | ||
+ | //executing only once the first time we reach the section | ||
+ | if(!currentSection.hasClass(ACTIVE)){ | ||
+ | isScrolling = true; | ||
+ | var leavingSection = $(SECTION_ACTIVE_SEL); | ||
+ | var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; | ||
+ | var yMovement = getYmovement(currentSection); | ||
+ | var anchorLink = currentSection.data('anchor'); | ||
+ | var sectionIndex = currentSection.index(SECTION_SEL) + 1; | ||
+ | var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); | ||
+ | var slideIndex; | ||
+ | var slideAnchorLink; | ||
+ | |||
+ | if(activeSlide.length){ | ||
+ | slideAnchorLink = activeSlide.data('anchor'); | ||
+ | slideIndex = activeSlide.index(); | ||
+ | } | ||
+ | |||
+ | if(canScroll){ | ||
+ | currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); | ||
+ | |||
+ | $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); | ||
+ | $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); | ||
+ | |||
+ | stopMedia(leavingSection); | ||
+ | lazyLoad(currentSection); | ||
+ | playMedia(currentSection); | ||
+ | |||
+ | activateMenuAndNav(anchorLink, sectionIndex - 1); | ||
+ | |||
+ | 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(){ | ||
+ | //checking it again in case it changed during the delay | ||
+ | if(options.fitToSection && | ||
+ | |||
+ | //is the destination element bigger than the viewport? | ||
+ | $(SECTION_ACTIVE_SEL).outerHeight() <= windowsHeight | ||
+ | ){ | ||
+ | fitToSection(); | ||
+ | } | ||
+ | }, options.fitToSectionDelay); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Fits the site to the nearest active section | ||
+ | */ | ||
+ | function fitToSection(){ | ||
+ | //checking fitToSection again in case it was set to false before the timeout delay | ||
+ | if(canScroll){ | ||
+ | //allows to scroll to an active section and | ||
+ | //if the section is already active, we prevent firing callbacks | ||
+ | isResizing = true; | ||
+ | |||
+ | scrollPage($(SECTION_ACTIVE_SEL)); | ||
+ | isResizing = false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Determines whether the active section has seen in its whole or not. | ||
+ | */ | ||
+ | function isCompletelyInViewPort(movement){ | ||
+ | var top = $(SECTION_ACTIVE_SEL).position().top; | ||
+ | var bottom = top + $window.height(); | ||
+ | |||
+ | if(movement == 'up'){ | ||
+ | return bottom >= ($window.scrollTop() + $window.height()); | ||
+ | } | ||
+ | return top <= $window.scrollTop(); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Gets the directon of the the scrolling fired by the scroll event. | ||
+ | */ | ||
+ | function getScrollDirection(currentScroll){ | ||
+ | var direction = currentScroll > lastScroll ? 'down' : 'up'; | ||
+ | |||
+ | lastScroll = currentScroll; | ||
+ | |||
+ | //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination | ||
+ | previousDestTop = currentScroll; | ||
+ | |||
+ | return direction; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * 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 (!isScrollAllowed.m[type]){ | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; | ||
+ | |||
+ | if(options.scrollOverflow){ | ||
+ | var scrollable = options.scrollOverflowHandler.scrollable($(SECTION_ACTIVE_SEL)); | ||
+ | var check = (type === 'down') ? 'bottom' : 'top'; | ||
+ | |||
+ | if(scrollable.length > 0 ){ | ||
+ | //is the scrollbar at the start/end of the scroll? | ||
+ | if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ | ||
+ | scrollSection(); | ||
+ | }else{ | ||
+ | return true; | ||
+ | } | ||
+ | }else{ | ||
+ | // moved up/down | ||
+ | scrollSection(); | ||
+ | } | ||
+ | }else{ | ||
+ | // moved up/down | ||
+ | scrollSection(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | * Preventing bouncing in iOS #2285 | ||
+ | */ | ||
+ | function preventBouncing(event){ | ||
+ | var e = event.originalEvent; | ||
+ | if(options.autoScrolling && isReallyTouch(e)){ | ||
+ | //preventing the easing on iOS devices | ||
+ | event.preventDefault(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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 = event.originalEvent; | ||
+ | var activeSection = $(e.target).closest(SECTION_SEL); | ||
+ | |||
+ | // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain | ||
+ | if (isReallyTouch(e) ) { | ||
+ | |||
+ | if(options.autoScrolling){ | ||
+ | //preventing the easing on iOS devices | ||
+ | event.preventDefault(); | ||
+ | } | ||
+ | |||
+ | 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 (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { | ||
+ | |||
+ | //is the movement greater than the minimum resistance to scroll? | ||
+ | if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { | ||
+ | if (touchStartX > touchEndX) { | ||
+ | if(isScrollAllowed.m.right){ | ||
+ | moveSlideRight(activeSection); //next | ||
+ | } | ||
+ | } else { | ||
+ | if(isScrollAllowed.m.left){ | ||
+ | moveSlideLeft(activeSection); //prev | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //vertical scrolling (only when autoScrolling is enabled) | ||
+ | else if(options.autoScrolling && canScroll){ | ||
+ | |||
+ | //is the movement greater than the minimum resistance to scroll? | ||
+ | if (Math.abs(touchStartY - touchEndY) > ($window.height() / 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 = event.originalEvent; | ||
+ | |||
+ | //stopping the auto scroll to adjust to a section | ||
+ | if(options.fitToSection){ | ||
+ | $htmlBody.stop(); | ||
+ | } | ||
+ | |||
+ | 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(); | ||
+ | var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); | ||
+ | |||
+ | //autoscrolling and not zooming? | ||
+ | if(options.autoScrolling && !controlPressed && !isNormalScroll){ | ||
+ | // cross-browser wheel delta | ||
+ | e = e || window.event; | ||
+ | var value = e.wheelDelta || -e.deltaY || -e.detail; | ||
+ | var delta = Math.max(-1, Math.min(1, value)); | ||
+ | |||
+ | var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; | ||
+ | var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); | ||
+ | |||
+ | //Limiting the array to 150 (lets not waste 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){ | ||
+ | e.preventDefault ? e.preventDefault() : e.returnValue = false; | ||
+ | } | ||
+ | |||
+ | //time difference between the last scroll and the current one | ||
+ | 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){ | ||
+ | var averageEnd = getAverage(scrollings, 10); | ||
+ | var averageMiddle = getAverage(scrollings, 70); | ||
+ | var isAccelerating = averageEnd >= averageMiddle; | ||
+ | |||
+ | //to avoid double swipes... | ||
+ | if(isAccelerating && isScrollingVertically){ | ||
+ | //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 | ||
+ | $htmlBody.stop(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Slides a slider to the given direction. | ||
+ | * Optional `section` param. | ||
+ | */ | ||
+ | function moveSlide(direction, section){ | ||
+ | var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; | ||
+ | var slides = activeSection.find(SLIDES_WRAPPER_SEL); | ||
+ | var numSlides = slides.find(SLIDE_SEL).length; | ||
+ | |||
+ | // more than one slide needed and nothing should be sliding | ||
+ | if (!slides.length || slideMoving || numSlides < 2) { | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | var currentSlide = slides.find(SLIDE_ACTIVE_SEL); | ||
+ | var destiny = null; | ||
+ | |||
+ | if(direction === 'left'){ | ||
+ | destiny = currentSlide.prev(SLIDE_SEL); | ||
+ | }else{ | ||
+ | destiny = currentSlide.next(SLIDE_SEL); | ||
+ | } | ||
+ | |||
+ | //isn't there a next slide in the secuence? | ||
+ | if(!destiny.length){ | ||
+ | //respect loopHorizontal settin | ||
+ | if (!options.loopHorizontal) return; | ||
+ | |||
+ | if(direction === 'left'){ | ||
+ | destiny = currentSlide.siblings(':last'); | ||
+ | }else{ | ||
+ | destiny = currentSlide.siblings(':first'); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | slideMoving = true; | ||
+ | |||
+ | landscapeScroll(slides, destiny, direction); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Maintains the active slides in the viewport | ||
+ | * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) | ||
+ | */ | ||
+ | function keepSlidesPosition(){ | ||
+ | $(SLIDE_ACTIVE_SEL).each(function(){ | ||
+ | silentLandscapeScroll($(this), 'internal'); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | var previousDestTop = 0; | ||
+ | /** | ||
+ | * Returns the destination Y position based on the scrolling direction and | ||
+ | * the height of the section. | ||
+ | */ | ||
+ | function getDestinationPosition(element){ | ||
+ | var elemPosition = element.position(); | ||
+ | |||
+ | //top of the desination will be at the top of the viewport | ||
+ | var position = elemPosition.top; | ||
+ | var isScrollingDown = elemPosition.top > previousDestTop; | ||
+ | var sectionBottom = position - windowsHeight + element.outerHeight(); | ||
+ | var bigSectionsDestination = options.bigSectionsDestination; | ||
+ | |||
+ | //is the destination element bigger than the viewport? | ||
+ | if(element.outerHeight() > windowsHeight){ | ||
+ | //scrolling up? | ||
+ | if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ | ||
+ | position = sectionBottom; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section | ||
+ | else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ | ||
+ | //The bottom of the destination will be at the bottom of the viewport | ||
+ | position = sectionBottom; | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | Keeping record of the last scrolled position to determine the scrolling direction. | ||
+ | No conventional methods can be used as the scroll bar might not be present | ||
+ | AND the section might not be active if it is auto-height and didnt reach the middle | ||
+ | of the viewport. | ||
+ | */ | ||
+ | previousDestTop = position; | ||
+ | return position; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Scrolls the site to the given element and scrolls to the slide if a callback is given. | ||
+ | */ | ||
+ | function scrollPage(element, callback, isMovementUp){ | ||
+ | if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function | ||
+ | |||
+ | var dtop = getDestinationPosition(element); | ||
+ | var slideAnchorLink; | ||
+ | var slideIndex; | ||
+ | |||
+ | //local variables | ||
+ | var v = { | ||
+ | element: element, | ||
+ | callback: callback, | ||
+ | isMovementUp: isMovementUp, | ||
+ | dtop: dtop, | ||
+ | yMovement: getYmovement(element), | ||
+ | anchorLink: element.data('anchor'), | ||
+ | sectionIndex: element.index(SECTION_SEL), | ||
+ | activeSlide: element.find(SLIDE_ACTIVE_SEL), | ||
+ | activeSection: $(SECTION_ACTIVE_SEL), | ||
+ | leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_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((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } | ||
+ | |||
+ | if(v.activeSlide.length){ | ||
+ | slideAnchorLink = v.activeSlide.data('anchor'); | ||
+ | slideIndex = v.activeSlide.index(); | ||
+ | } | ||
+ | |||
+ | //callback (onLeave) if the site is not just resizing and readjusting the slides | ||
+ | if($.isFunction(options.onLeave) && !v.localIsResizing){ | ||
+ | if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // If continuousVertical && we need to wrap around | ||
+ | if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && | ||
+ | ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or | ||
+ | (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down | ||
+ | |||
+ | v = createInfiniteSections(v); | ||
+ | } | ||
+ | |||
+ | //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) | ||
+ | if(!v.localIsResizing){ | ||
+ | stopMedia(v.activeSection); | ||
+ | } | ||
+ | |||
+ | if(options.scrollOverflow){ | ||
+ | options.scrollOverflowHandler.beforeLeave(); | ||
+ | } | ||
+ | |||
+ | element.addClass(ACTIVE).siblings().removeClass(ACTIVE); | ||
+ | lazyLoad(element); | ||
+ | |||
+ | if(options.scrollOverflow){ | ||
+ | options.scrollOverflowHandler.onLeave(); | ||
+ | } | ||
+ | |||
+ | //preventing from activating the MouseWheelHandler event | ||
+ | //more than once if the page is scrolling | ||
+ | canScroll = false; | ||
+ | |||
+ | setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); | ||
+ | |||
+ | performMovement(v); | ||
+ | |||
+ | //flag to avoid callingn `scrollPage()` twice in case of using anchor links | ||
+ | lastScrolledDestiny = v.anchorLink; | ||
+ | |||
+ | //avoid firing it twice (as it does also on scroll) | ||
+ | activateMenuAndNav(v.anchorLink, v.sectionIndex); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Performs the vertical movement (by CSS3 or by jQuery) | ||
+ | */ | ||
+ | function performMovement(v){ | ||
+ | // using CSS3 translate functionality | ||
+ | if (options.css3 && options.autoScrolling && !options.scrollBar) { | ||
+ | |||
+ | // 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 translate3d = 'translate3d(0px, -' + Math.round(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){ | ||
+ | clearTimeout(afterSectionLoadsId); | ||
+ | afterSectionLoadsId = setTimeout(function () { | ||
+ | afterSectionLoads(v); | ||
+ | }, options.scrollingSpeed); | ||
+ | }else{ | ||
+ | afterSectionLoads(v); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // using jQuery animate | ||
+ | else{ | ||
+ | var scrollSettings = getScrollSettings(v); | ||
+ | |||
+ | $(scrollSettings.element).animate( | ||
+ | scrollSettings.options, | ||
+ | options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` | ||
+ | if(options.scrollBar){ | ||
+ | |||
+ | /* Hack! | ||
+ | The timeout prevents setting the most dominant section in the viewport as "active" when the user | ||
+ | scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. | ||
+ | When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. | ||
+ | */ | ||
+ | setTimeout(function(){ | ||
+ | afterSectionLoads(v); | ||
+ | },30); | ||
+ | }else{ | ||
+ | afterSectionLoads(v); | ||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Gets the scrolling settings depending on the plugin autoScrolling option | ||
+ | */ | ||
+ | function getScrollSettings(v){ | ||
+ | var scroll = {}; | ||
+ | |||
+ | if(options.autoScrolling && !options.scrollBar){ | ||
+ | scroll.options = { 'top': -v.dtop}; | ||
+ | scroll.element = WRAPPER_SEL; | ||
+ | }else{ | ||
+ | scroll.options = { 'scrollTop': v.dtop}; | ||
+ | scroll.element = 'html, body'; | ||
+ | } | ||
+ | |||
+ | return scroll; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds sections before or after the current one to create the infinite effect. | ||
+ | */ | ||
+ | function createInfiniteSections(v){ | ||
+ | // Scrolling down | ||
+ | if (!v.isMovementUp) { | ||
+ | // Move all previous sections to after the active section | ||
+ | $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); | ||
+ | } | ||
+ | else { // Scrolling up | ||
+ | // Move all next sections to before the active section | ||
+ | $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); | ||
+ | } | ||
+ | |||
+ | // Maintain the displayed position (now that we changed the element order) | ||
+ | silentScroll($(SECTION_ACTIVE_SEL).position().top); | ||
+ | |||
+ | // Maintain the active slides visible in the viewport | ||
+ | keepSlidesPosition(); | ||
+ | |||
+ | // save for later the elements that still need to be reordered | ||
+ | v.wrapAroundElements = v.activeSection; | ||
+ | |||
+ | // Recalculate animation variables | ||
+ | v.dtop = v.element.position().top; | ||
+ | v.yMovement = getYmovement(v.element); | ||
+ | |||
+ | //sections will temporally have another position in the DOM | ||
+ | //updating this values in case we need them | ||
+ | v.leavingSection = v.activeSection.index(SECTION_SEL) + 1; | ||
+ | v.sectionIndex = v.element.index(SECTION_SEL); | ||
+ | |||
+ | return v; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Fix section order after continuousVertical changes have been animated | ||
+ | */ | ||
+ | function continuousVerticalFixSectionOrder (v) { | ||
+ | // If continuousVertical is in effect (and autoScrolling would also be in effect then), | ||
+ | // finish moving the elements around so the direct navigation will function more simply | ||
+ | if (!v.wrapAroundElements || !v.wrapAroundElements.length) { | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (v.isMovementUp) { | ||
+ | $(SECTION_FIRST_SEL).before(v.wrapAroundElements); | ||
+ | } | ||
+ | else { | ||
+ | $(SECTION_LAST_SEL).after(v.wrapAroundElements); | ||
+ | } | ||
+ | |||
+ | silentScroll($(SECTION_ACTIVE_SEL).position().top); | ||
+ | |||
+ | // Maintain the active slides visible in the viewport | ||
+ | keepSlidesPosition(); | ||
+ | } | ||
+ | |||
+ | |||
+ | /** | ||
+ | * Actions to do once the section is loaded. | ||
+ | */ | ||
+ | function afterSectionLoads (v){ | ||
+ | continuousVerticalFixSectionOrder(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)); | ||
+ | |||
+ | if(options.scrollOverflow){ | ||
+ | options.scrollOverflowHandler.afterLoad(); | ||
+ | } | ||
+ | |||
+ | if(!v.localIsResizing){ | ||
+ | playMedia(v.element); | ||
+ | } | ||
+ | |||
+ | v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); | ||
+ | |||
+ | canScroll = true; | ||
+ | |||
+ | $.isFunction(v.callback) && v.callback.call(this); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * 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 | ||
+ | .attr(attribute, element.data(attribute)) | ||
+ | .removeAttr('data-' + attribute); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Lazy loads image, video and audio elements. | ||
+ | */ | ||
+ | function lazyLoad(destiny){ | ||
+ | if (!options.lazyLoading){ | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | var panel = getSlideOrSection(destiny); | ||
+ | var element; | ||
+ | |||
+ | panel.find('img[data-src], img[data-srcset], source[data-src], video[data-src], audio[data-src], iframe[data-src]').each(function(){ | ||
+ | element = $(this); | ||
+ | |||
+ | $.each(['src', 'srcset'], function(index, type){ | ||
+ | var attribute = element.attr('data-' + type); | ||
+ | if(typeof attribute !== 'undefined' && attribute){ | ||
+ | setSrc(element, type); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | if(element.is('source')){ | ||
+ | var typeToPlay = element.closest('video').length ? 'video' : 'audio'; | ||
+ | element.closest(typeToPlay).get(0).load(); | ||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Plays video and audio elements. | ||
+ | */ | ||
+ | function playMedia(destiny){ | ||
+ | var panel = getSlideOrSection(destiny); | ||
+ | |||
+ | //playing HTML5 media elements | ||
+ | panel.find('video, audio').each(function(){ | ||
+ | var element = $(this).get(0); | ||
+ | |||
+ | if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { | ||
+ | element.play(); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | //youtube videos | ||
+ | panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ | ||
+ | var element = $(this).get(0); | ||
+ | |||
+ | if ( element.hasAttribute('data-autoplay') ){ | ||
+ | playYoutube(element); | ||
+ | } | ||
+ | |||
+ | //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. | ||
+ | element.onload = function() { | ||
+ | if ( element.hasAttribute('data-autoplay') ){ | ||
+ | playYoutube(element); | ||
+ | } | ||
+ | }; | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Plays a youtube video | ||
+ | */ | ||
+ | function playYoutube(element){ | ||
+ | element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Stops video and audio elements. | ||
+ | */ | ||
+ | function stopMedia(destiny){ | ||
+ | var panel = getSlideOrSection(destiny); | ||
+ | |||
+ | //stopping HTML5 media elements | ||
+ | panel.find('video, audio').each(function(){ | ||
+ | var element = $(this).get(0); | ||
+ | |||
+ | if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { | ||
+ | element.pause(); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | //youtube videos | ||
+ | panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ | ||
+ | var element = $(this).get(0); | ||
+ | |||
+ | if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ | ||
+ | $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); | ||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Gets the active slide (or section) for the given section | ||
+ | */ | ||
+ | function getSlideOrSection(destiny){ | ||
+ | var slide = destiny.find(SLIDE_ACTIVE_SEL); | ||
+ | if( slide.length ) { | ||
+ | destiny = $(slide); | ||
+ | } | ||
+ | |||
+ | return destiny; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Scrolls to the anchor in the URL when loading the site | ||
+ | */ | ||
+ | function scrollToAnchor(){ | ||
+ | var anchors = getAnchorsURL(); | ||
+ | var sectionAnchor = anchors.section; | ||
+ | var slideAnchor = anchors.slide; | ||
+ | |||
+ | if(sectionAnchor){ //if theres any # | ||
+ | if(options.animateAnchor){ | ||
+ | scrollPageAndSlide(sectionAnchor, slideAnchor); | ||
+ | }else{ | ||
+ | silentMoveTo(sectionAnchor, slideAnchor); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * 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) | ||
+ | */ | ||
+ | function hashChangeHandler(){ | ||
+ | if(!isScrolling && !options.lockAnchors){ | ||
+ | var anchors = getAnchorsURL(); | ||
+ | var sectionAnchor = anchors.section; | ||
+ | var slideAnchor = anchors.slide; | ||
+ | |||
+ | //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 slideAnchor === 'undefined' && !slideMoving); | ||
+ | |||
+ | if(sectionAnchor.length){ | ||
+ | /*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 ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { | ||
+ | scrollPageAndSlide(sectionAnchor, slideAnchor); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //gets the URL anchors (section and slide) | ||
+ | function getAnchorsURL(){ | ||
+ | //getting the anchor link in the URL and deleting the `#` | ||
+ | var hash = window.location.hash; | ||
+ | var anchorsParts = hash.replace('#', '').split('/'); | ||
+ | |||
+ | //using / for visual reasons and not as a section/slide separator #2803 | ||
+ | var isFunkyAnchor = hash.indexOf('#/') > -1; | ||
+ | |||
+ | return { | ||
+ | section: isFunkyAnchor ? '/' + anchorsParts[1] : decodeURIComponent(anchorsParts[0]), | ||
+ | slide: isFunkyAnchor ? decodeURIComponent(anchorsParts[2]) : decodeURIComponent(anchorsParts[1]) | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //Sliding with arrow keys, both, vertical and horizontal | ||
+ | function keydownHandler(e) { | ||
+ | |||
+ | clearTimeout(keydownId); | ||
+ | |||
+ | var activeElement = $(':focus'); | ||
+ | |||
+ | if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && | ||
+ | activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && | ||
+ | options.keyboardScrolling && options.autoScrolling){ | ||
+ | var keyCode = e.which; | ||
+ | |||
+ | //preventing the scroll with arrow keys & spacebar & Page Up & Down keys | ||
+ | var keyControls = [40, 38, 32, 33, 34]; | ||
+ | if($.inArray(keyCode, keyControls) > -1){ | ||
+ | e.preventDefault(); | ||
+ | } | ||
+ | |||
+ | controlPressed = e.ctrlKey; | ||
+ | |||
+ | keydownId = setTimeout(function(){ | ||
+ | onkeydown(e); | ||
+ | },150); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function tooltipTextHandler(){ | ||
+ | $(this).prev().trigger('click'); | ||
+ | } | ||
+ | |||
+ | //to prevent scrolling while zooming | ||
+ | function keyUpHandler(e){ | ||
+ | if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox | ||
+ | controlPressed = e.ctrlKey; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //binding the mousemove when the mouse's middle button is released | ||
+ | function mouseDownHandler(e){ | ||
+ | //middle button | ||
+ | if (e.which == 2){ | ||
+ | oldPageY = e.pageY; | ||
+ | container.on('mousemove', mouseMoveHandler); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //unbinding the mousemove when the mouse's middle button is released | ||
+ | function mouseUpHandler(e){ | ||
+ | //middle button | ||
+ | if (e.which == 2){ | ||
+ | container.off('mousemove'); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //Scrolling horizontally when clicking on the slider controls. | ||
+ | function slideArrowHandler(){ | ||
+ | var section = $(this).closest(SECTION_SEL); | ||
+ | |||
+ | if ($(this).hasClass(SLIDES_PREV)) { | ||
+ | if(isScrollAllowed.m.left){ | ||
+ | moveSlideLeft(section); | ||
+ | } | ||
+ | } else { | ||
+ | if(isScrollAllowed.m.right){ | ||
+ | moveSlideRight(section); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. | ||
+ | function blurHandler(){ | ||
+ | isWindowFocused = false; | ||
+ | controlPressed = false; | ||
+ | } | ||
+ | |||
+ | //Scrolls to the section when clicking the navigation bullet | ||
+ | function sectionBulletHandler(e){ | ||
+ | e.preventDefault(); | ||
+ | var index = $(this).parent().index(); | ||
+ | scrollPage($(SECTION_SEL).eq(index)); | ||
+ | } | ||
+ | |||
+ | //Scrolls the slider to the given slide destination for the given section | ||
+ | function slideBulletHandler(e){ | ||
+ | e.preventDefault(); | ||
+ | var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); | ||
+ | var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); | ||
+ | |||
+ | landscapeScroll(slides, destiny); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Keydown event | ||
+ | */ | ||
+ | function onkeydown(e){ | ||
+ | var shiftPressed = e.shiftKey; | ||
+ | |||
+ | //do nothing if we can not scroll or we are not using horizotnal key arrows. | ||
+ | if(!canScroll && [37,39].indexOf(e.which) < 0){ | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | switch (e.which) { | ||
+ | //up | ||
+ | case 38: | ||
+ | case 33: | ||
+ | if(isScrollAllowed.k.up){ | ||
+ | moveSectionUp(); | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | //down | ||
+ | case 32: //spacebar | ||
+ | if(shiftPressed && isScrollAllowed.k.up){ | ||
+ | moveSectionUp(); | ||
+ | break; | ||
+ | } | ||
+ | /* falls through */ | ||
+ | case 40: | ||
+ | case 34: | ||
+ | if(isScrollAllowed.k.down){ | ||
+ | moveSectionDown(); | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | //Home | ||
+ | case 36: | ||
+ | if(isScrollAllowed.k.up){ | ||
+ | moveTo(1); | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | //End | ||
+ | case 35: | ||
+ | if(isScrollAllowed.k.down){ | ||
+ | moveTo( $(SECTION_SEL).length ); | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | //left | ||
+ | case 37: | ||
+ | if(isScrollAllowed.k.left){ | ||
+ | moveSlideLeft(); | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | //right | ||
+ | case 39: | ||
+ | if(isScrollAllowed.k.right){ | ||
+ | moveSlideRight(); | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | default: | ||
+ | return; // exit this handler for other keys | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Detecting the direction of the mouse movement. | ||
+ | * Used only for the middle button of the mouse. | ||
+ | */ | ||
+ | var oldPageY = 0; | ||
+ | function mouseMoveHandler(e){ | ||
+ | if(canScroll){ | ||
+ | // moving up | ||
+ | if (e.pageY < oldPageY && isScrollAllowed.m.up){ | ||
+ | moveSectionUp(); | ||
+ | } | ||
+ | |||
+ | // moving down | ||
+ | else if(e.pageY > oldPageY && isScrollAllowed.m.down){ | ||
+ | moveSectionDown(); | ||
+ | } | ||
+ | } | ||
+ | oldPageY = e.pageY; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Scrolls horizontal sliders. | ||
+ | */ | ||
+ | function landscapeScroll(slides, destiny, direction){ | ||
+ | var section = slides.closest(SECTION_SEL); | ||
+ | var v = { | ||
+ | slides: slides, | ||
+ | destiny: destiny, | ||
+ | direction: direction, | ||
+ | destinyPos: destiny.position(), | ||
+ | slideIndex: destiny.index(), | ||
+ | section: section, | ||
+ | sectionIndex: section.index(SECTION_SEL), | ||
+ | anchorLink: section.data('anchor'), | ||
+ | slidesNav: section.find(SLIDES_NAV_SEL), | ||
+ | slideAnchor: getAnchor(destiny), | ||
+ | prevSlide: section.find(SLIDE_ACTIVE_SEL), | ||
+ | prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), | ||
+ | |||
+ | //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 | ||
+ | }; | ||
+ | v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); | ||
+ | |||
+ | //important!! Only do it when not resizing | ||
+ | if(!v.localIsResizing){ | ||
+ | //preventing from scrolling to the next/prev section when using scrollHorizontally | ||
+ | canScroll = false; | ||
+ | } | ||
+ | |||
+ | if(options.onSlideLeave){ | ||
+ | |||
+ | //if the site is not just resizing and readjusting the slides | ||
+ | if(!v.localIsResizing && v.xMovement!=='none'){ | ||
+ | if($.isFunction( options.onSlideLeave )){ | ||
+ | if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.direction, v.slideIndex ) === false){ | ||
+ | slideMoving = false; | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); | ||
+ | |||
+ | if(!v.localIsResizing){ | ||
+ | stopMedia(v.prevSlide); | ||
+ | lazyLoad(destiny); | ||
+ | } | ||
+ | |||
+ | if(!options.loopHorizontal && options.controlArrows){ | ||
+ | //hidding it for the fist slide, showing for the rest | ||
+ | section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); | ||
+ | |||
+ | //hidding it for the last slide, showing for the rest | ||
+ | section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); | ||
+ | } | ||
+ | |||
+ | //only changing the URL if the slides are in the current section (not for resize re-adjusting) | ||
+ | if(section.hasClass(ACTIVE) && !v.localIsResizing){ | ||
+ | setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); | ||
+ | } | ||
+ | |||
+ | performHorizontalMove(slides, v, true); | ||
+ | } | ||
+ | |||
+ | |||
+ | function afterSlideLoads(v){ | ||
+ | activeSlidesNavigation(v.slidesNav, v.slideIndex); | ||
+ | |||
+ | //if the site is not just resizing and readjusting the slides | ||
+ | if(!v.localIsResizing){ | ||
+ | $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); | ||
+ | |||
+ | //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally | ||
+ | //and to prevent double scroll right after a windows resize | ||
+ | canScroll = true; | ||
+ | |||
+ | playMedia(v.destiny); | ||
+ | } | ||
+ | |||
+ | //letting them slide again | ||
+ | slideMoving = false; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Performs the horizontal movement. (CSS3 or jQuery) | ||
+ | * | ||
+ | * @param fireCallback {Bool} - determines whether or not to fire the callback | ||
+ | */ | ||
+ | function performHorizontalMove(slides, v, fireCallback){ | ||
+ | var destinyPos = v.destinyPos; | ||
+ | |||
+ | if(options.css3){ | ||
+ | var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; | ||
+ | |||
+ | addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d)); | ||
+ | |||
+ | afterSlideLoadsId = setTimeout(function(){ | ||
+ | fireCallback && afterSlideLoads(v); | ||
+ | }, options.scrollingSpeed, options.easing); | ||
+ | }else{ | ||
+ | slides.animate({ | ||
+ | scrollLeft : Math.round(destinyPos.left) | ||
+ | }, options.scrollingSpeed, options.easing, function() { | ||
+ | |||
+ | fireCallback && afterSlideLoads(v); | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Sets the state for the horizontal bullet navigations. | ||
+ | */ | ||
+ | function activeSlidesNavigation(slidesNav, slideIndex){ | ||
+ | slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); | ||
+ | slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); | ||
+ | } | ||
+ | |||
+ | var previousHeight = windowsHeight; | ||
+ | |||
+ | //when resizing the site, we adjust the heights of the sections, slimScroll... | ||
+ | function resizeHandler(){ | ||
+ | //checking if it needs to get responsive | ||
+ | responsive(); | ||
+ | |||
+ | // rebuild immediately on touch devices | ||
+ | if (isTouchDevice) { | ||
+ | var activeElement = $(document.activeElement); | ||
+ | |||
+ | //if the keyboard is NOT visible | ||
+ | if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { | ||
+ | var currentHeight = $window.height(); | ||
+ | |||
+ | //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); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Checks if the site needs to get responsive and disables autoScrolling if so. | ||
+ | * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. | ||
+ | */ | ||
+ | function responsive(){ | ||
+ | var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity | ||
+ | var heightLimit = options.responsiveHeight; | ||
+ | |||
+ | //only calculating what we need. Remember its called on the resize event. | ||
+ | var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; | ||
+ | var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; | ||
+ | |||
+ | if(widthLimit && heightLimit){ | ||
+ | setResponsive(isBreakingPointWidth || isBreakingPointHeight); | ||
+ | } | ||
+ | else if(widthLimit){ | ||
+ | setResponsive(isBreakingPointWidth); | ||
+ | } | ||
+ | else if(heightLimit){ | ||
+ | setResponsive(isBreakingPointHeight); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds transition animations for the given element | ||
+ | */ | ||
+ | function addAnimation(element){ | ||
+ | var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; | ||
+ | |||
+ | element.removeClass(NO_TRANSITION); | ||
+ | return element.css({ | ||
+ | '-webkit-transition': transition, | ||
+ | 'transition': transition | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Remove transition animations for the given element | ||
+ | */ | ||
+ | function removeAnimation(element){ | ||
+ | return element.addClass(NO_TRANSITION); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Activating the vertical navigation bullets according to the given slide name. | ||
+ | */ | ||
+ | function activateNavDots(name, sectionIndex){ | ||
+ | if(options.navigation){ | ||
+ | $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); | ||
+ | if(name){ | ||
+ | $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); | ||
+ | }else{ | ||
+ | $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Activating the website main menu elements according to the given slide name. | ||
+ | */ | ||
+ | function activateMenuElement(name){ | ||
+ | if(options.menu){ | ||
+ | $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); | ||
+ | $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Sets to active the current menu and vertical nav items. | ||
+ | */ | ||
+ | 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 = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); | ||
+ | var toIndex = destiny.index(SECTION_SEL); | ||
+ | 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'; | ||
+ | } | ||
+ | |||
+ | function addTableClass(element){ | ||
+ | //In case we are styling for the 2nd time as in with reponsiveSlides | ||
+ | if(!element.hasClass(TABLE)){ | ||
+ | element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function getTableHeight(element){ | ||
+ | var sectionHeight = windowsHeight; | ||
+ | |||
+ | if(options.paddingTop || options.paddingBottom){ | ||
+ | var section = element; | ||
+ | if(!section.hasClass(SECTION)){ | ||
+ | section = element.closest(SECTION_SEL); | ||
+ | } | ||
+ | |||
+ | var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); | ||
+ | sectionHeight = (windowsHeight - paddings); | ||
+ | } | ||
+ | |||
+ | return sectionHeight; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * 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); | ||
+ | } | ||
+ | |||
+ | container.css(getTransforms(translate3d)); | ||
+ | |||
+ | //syncronously removing the class after the animation has been applied. | ||
+ | setTimeout(function(){ | ||
+ | container.removeClass(NO_TRANSITION); | ||
+ | },10); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Gets a section by its anchor / index | ||
+ | */ | ||
+ | function getSectionByAnchor(sectionAnchor){ | ||
+ | if(!sectionAnchor) return []; | ||
+ | |||
+ | var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); | ||
+ | if(!section.length){ | ||
+ | section = $(SECTION_SEL).eq( sectionAnchor -1); | ||
+ | } | ||
+ | |||
+ | return section; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Gets a slide inside a given section by its anchor / index | ||
+ | */ | ||
+ | function getSlideByAnchor(slideAnchor, section){ | ||
+ | var slides = section.find(SLIDES_WRAPPER_SEL); | ||
+ | var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); | ||
+ | |||
+ | if(!slide.length){ | ||
+ | slide = slides.find(SLIDE_SEL).eq(slideAnchor); | ||
+ | } | ||
+ | |||
+ | return slide; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Scrolls to the given section and slide anchors | ||
+ | */ | ||
+ | function scrollPageAndSlide(destiny, slide){ | ||
+ | var section = getSectionByAnchor(destiny); | ||
+ | |||
+ | //do nothing if there's no section with the given anchor name | ||
+ | if(!section.length) return; | ||
+ | |||
+ | //default slide | ||
+ | if (typeof slide === 'undefined') { | ||
+ | slide = 0; | ||
+ | } | ||
+ | |||
+ | //we need to scroll to the section and then to the slide | ||
+ | if (destiny !== lastScrolledDestiny && !section.hasClass(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 = section.find(SLIDES_WRAPPER_SEL); | ||
+ | var destiny = getSlideByAnchor(slideAnchor, section); | ||
+ | |||
+ | if(destiny.length){ | ||
+ | landscapeScroll(slides, destiny); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Creates a landscape navigation bar with dots for horizontal sliders. | ||
+ | */ | ||
+ | function addSlidesNavigation(section, numSlides){ | ||
+ | section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); | ||
+ | var nav = section.find(SLIDES_NAV_SEL); | ||
+ | |||
+ | //top or bottom | ||
+ | nav.addClass(options.slidesNavPosition); | ||
+ | |||
+ | for(var i=0; i< numSlides; i++){ | ||
+ | nav.find('ul').append('<li><a href="#"><span></span></a></li>'); | ||
+ | } | ||
+ | |||
+ | //centering it | ||
+ | nav.css('margin-left', '-' + (nav.width()/2) + 'px'); | ||
+ | |||
+ | nav.find('li').first().find('a').addClass(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 && !options.lockAnchors){ | ||
+ | |||
+ | //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){ | ||
+ | window.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 / section. Its index will be used if there's none. | ||
+ | */ | ||
+ | function getAnchor(element){ | ||
+ | var anchor = element.data('anchor'); | ||
+ | var index = element.index(); | ||
+ | |||
+ | //Slide without anchor link? We take the index instead. | ||
+ | if(typeof anchor === 'undefined'){ | ||
+ | anchor = index; | ||
+ | } | ||
+ | |||
+ | return anchor; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Sets a class for the body of the page depending on the active section / slide | ||
+ | */ | ||
+ | function setBodyClass(){ | ||
+ | var section = $(SECTION_ACTIVE_SEL); | ||
+ | var slide = section.find(SLIDE_ACTIVE_SEL); | ||
+ | |||
+ | var sectionAnchor = getAnchor(section); | ||
+ | var slideAnchor = getAnchor(slide); | ||
+ | |||
+ | var text = String(sectionAnchor); | ||
+ | |||
+ | if(slide.length){ | ||
+ | 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"); | ||
+ | $body[0].className = $body[0].className.replace(classRe, ''); | ||
+ | |||
+ | //adding the current anchor | ||
+ | $body.addClass(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(){ | ||
+ | if (document.addEventListener) { | ||
+ | document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper | ||
+ | document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox | ||
+ | document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox | ||
+ | } else { | ||
+ | document.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 | ||
+ | * https://developer.mozilla.org/en-US/docs/Web/Events/wheel | ||
+ | */ | ||
+ | function addMouseWheelHandler(){ | ||
+ | var prefix = ''; | ||
+ | var _addEventListener; | ||
+ | |||
+ | if (window.addEventListener){ | ||
+ | _addEventListener = "addEventListener"; | ||
+ | }else{ | ||
+ | _addEventListener = "attachEvent"; | ||
+ | prefix = 'on'; | ||
+ | } | ||
+ | |||
+ | // detect available wheel event | ||
+ | var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" | ||
+ | document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" | ||
+ | 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox | ||
+ | |||
+ | |||
+ | if(support == 'DOMMouseScroll'){ | ||
+ | document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false); | ||
+ | } | ||
+ | |||
+ | //handle MozMousePixelScroll in older Firefox | ||
+ | else{ | ||
+ | document[ _addEventListener ](prefix + support, MouseWheelHandler, false); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Binding the mousemove when the mouse's middle button is pressed | ||
+ | */ | ||
+ | function addMiddleWheelHandler(){ | ||
+ | container | ||
+ | .on('mousedown', mouseDownHandler) | ||
+ | .on('mouseup', mouseUpHandler); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Unbinding the mousemove when the mouse's middle button is released | ||
+ | */ | ||
+ | function removeMiddleWheelHandler(){ | ||
+ | container | ||
+ | .off('mousedown', mouseDownHandler) | ||
+ | .off('mouseup', mouseUpHandler); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Adds the possibility to auto scroll through sections on touch devices. | ||
+ | */ | ||
+ | function addTouchHandler(){ | ||
+ | if(isTouchDevice || isTouch){ | ||
+ | if(options.autoScrolling){ | ||
+ | $body.off(events.touchmove).on(events.touchmove, preventBouncing); | ||
+ | } | ||
+ | |||
+ | $(WRAPPER_SEL) | ||
+ | .off(events.touchstart).on(events.touchstart, touchStartHandler) | ||
+ | .off(events.touchmove).on(events.touchmove, touchMoveHandler); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Removes the auto scrolling for touch devices. | ||
+ | */ | ||
+ | function removeTouchHandler(){ | ||
+ | if(isTouchDevice || isTouch){ | ||
+ | if(options.autoScrolling){ | ||
+ | $body.off(events.touchmove); | ||
+ | } | ||
+ | |||
+ | $(WRAPPER_SEL) | ||
+ | .off(events.touchstart) | ||
+ | .off(events.touchmove); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11) | ||
+ | * http://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) && options.scrollBar){ | ||
+ | events.y = e.touches[0].pageY; | ||
+ | events.x = e.touches[0].pageX; | ||
+ | } | ||
+ | |||
+ | return events; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Slides silently (with no animation) the active slider to the given slide. | ||
+ | * @param noCallback {bool} true or defined -> no callbacks | ||
+ | */ | ||
+ | function silentLandscapeScroll(activeSlide, noCallbacks){ | ||
+ | setScrollingSpeed (0, 'internal'); | ||
+ | |||
+ | if(typeof noCallbacks !== 'undefined'){ | ||
+ | //preventing firing callbacks afterSlideLoad etc. | ||
+ | isResizing = true; | ||
+ | } | ||
+ | |||
+ | landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); | ||
+ | |||
+ | if(typeof noCallbacks !== 'undefined'){ | ||
+ | isResizing = false; | ||
+ | } | ||
+ | |||
+ | setScrollingSpeed(originals.scrollingSpeed, 'internal'); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * 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 (options.css3 && options.autoScrolling && !options.scrollBar){ | ||
+ | var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; | ||
+ | transformContainer(translate3d, false); | ||
+ | } | ||
+ | else if(options.autoScrolling && !options.scrollBar){ | ||
+ | container.css('top', -roundedTop); | ||
+ | } | ||
+ | else{ | ||
+ | $htmlBody.scrollTop(roundedTop); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Returns the cross-browser transform string. | ||
+ | */ | ||
+ | function getTransforms(translate3d){ | ||
+ | return { | ||
+ | '-webkit-transform': translate3d, | ||
+ | '-moz-transform': translate3d, | ||
+ | '-ms-transform':translate3d, | ||
+ | 'transform': translate3d | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) | ||
+ | * @type m (mouse) or k (keyboard) | ||
+ | */ | ||
+ | function setIsScrollAllowed(value, direction, type){ | ||
+ | //up, down, left, right | ||
+ | if(direction !== 'all'){ | ||
+ | isScrollAllowed[type][direction] = value; | ||
+ | } | ||
+ | |||
+ | //all directions? | ||
+ | else{ | ||
+ | $.each(Object.keys(isScrollAllowed[type]), function(index, key){ | ||
+ | isScrollAllowed[type][key] = value; | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | * Destroys fullpage.js plugin events and optinally its html markup and styles | ||
+ | */ | ||
+ | function destroy(all){ | ||
+ | setAutoScrolling(false, 'internal'); | ||
+ | setAllowScrolling(false); | ||
+ | setKeyboardScrolling(false); | ||
+ | container.addClass(DESTROYED); | ||
+ | |||
+ | clearTimeout(afterSlideLoadsId); | ||
+ | clearTimeout(afterSectionLoadsId); | ||
+ | clearTimeout(resizeId); | ||
+ | clearTimeout(scrollId); | ||
+ | clearTimeout(scrollId2); | ||
+ | |||
+ | $window | ||
+ | .off('scroll', scrollHandler) | ||
+ | .off('hashchange', hashChangeHandler) | ||
+ | .off('resize', resizeHandler); | ||
+ | |||
+ | $document | ||
+ | .off('click touchstart', SECTION_NAV_SEL + ' a') | ||
+ | .off('mouseenter', SECTION_NAV_SEL + ' li') | ||
+ | .off('mouseleave', SECTION_NAV_SEL + ' li') | ||
+ | .off('click touchstart', SLIDES_NAV_LINK_SEL) | ||
+ | .off('mouseover', options.normalScrollElements) | ||
+ | .off('mouseout', options.normalScrollElements); | ||
+ | |||
+ | $(SECTION_SEL) | ||
+ | .off('click touchstart', SLIDES_ARROW_SEL); | ||
+ | |||
+ | clearTimeout(afterSlideLoadsId); | ||
+ | clearTimeout(afterSectionLoadsId); | ||
+ | |||
+ | //lets make a mess! | ||
+ | if(all){ | ||
+ | destroyStructure(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | * Removes inline styles added by fullpage.js | ||
+ | */ | ||
+ | function destroyStructure(){ | ||
+ | //reseting the `top` or `translate` properties to 0 | ||
+ | silentScroll(0); | ||
+ | |||
+ | //loading all the lazy load content | ||
+ | container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ | ||
+ | setSrc($(this), 'src'); | ||
+ | }); | ||
+ | |||
+ | container.find('img[data-srcset]').each(function(){ | ||
+ | setSrc($(this), 'srcset'); | ||
+ | }); | ||
+ | |||
+ | $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); | ||
+ | |||
+ | //removing inline styles | ||
+ | $(SECTION_SEL).css( { | ||
+ | 'height': '', | ||
+ | 'background-color' : '', | ||
+ | 'padding': '' | ||
+ | }); | ||
+ | |||
+ | $(SLIDE_SEL).css( { | ||
+ | 'width': '' | ||
+ | }); | ||
+ | |||
+ | container.css({ | ||
+ | 'height': '', | ||
+ | 'position': '', | ||
+ | '-ms-touch-action': '', | ||
+ | 'touch-action': '' | ||
+ | }); | ||
+ | |||
+ | $htmlBody.css({ | ||
+ | 'overflow': '', | ||
+ | 'height': '' | ||
+ | }); | ||
+ | |||
+ | // remove .fp-enabled class | ||
+ | $('html').removeClass(ENABLED); | ||
+ | |||
+ | // remove .fp-responsive class | ||
+ | $body.removeClass(RESPONSIVE); | ||
+ | |||
+ | // remove all of the .fp-viewing- classes | ||
+ | $.each($body.get(0).className.split(/\s+/), function (index, className) { | ||
+ | if (className.indexOf(VIEWING_PREFIX) === 0) { | ||
+ | $body.removeClass(className); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | //removing added classes | ||
+ | $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ | ||
+ | if(options.scrollOverflowHandler){ | ||
+ | options.scrollOverflowHandler.remove($(this)); | ||
+ | } | ||
+ | $(this).removeClass(TABLE + ' ' + ACTIVE); | ||
+ | }); | ||
+ | |||
+ | removeAnimation(container); | ||
+ | |||
+ | //Unwrapping content | ||
+ | container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ | ||
+ | //unwrap not being use in case there's no child element inside and its just text | ||
+ | $(this).replaceWith(this.childNodes); | ||
+ | }); | ||
+ | |||
+ | //removing the applied transition from the fullpage wrapper | ||
+ | container.css({ | ||
+ | '-webkit-transition': 'none', | ||
+ | 'transition': 'none' | ||
+ | }); | ||
+ | |||
+ | //scrolling the page to the top with no animation | ||
+ | $htmlBody.scrollTop(0); | ||
+ | |||
+ | //removing selectors | ||
+ | var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; | ||
+ | $.each(usedSelectors, function(index, value){ | ||
+ | $('.' + value).removeClass(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){ | ||
+ | options[variable] = value; | ||
+ | if(type !== 'internal'){ | ||
+ | originals[variable] = value; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Displays warnings | ||
+ | */ | ||
+ | function displayWarnings(){ | ||
+ | var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; | ||
+ | if($('html').hasClass(ENABLED)){ | ||
+ | showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Disable mutually exclusive settings | ||
+ | if (options.continuousVertical && | ||
+ | (options.loopTop || options.loopBottom)) { | ||
+ | options.continuousVertical = false; | ||
+ | showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); | ||
+ | } | ||
+ | |||
+ | if(options.scrollBar && options.scrollOverflow){ | ||
+ | showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); | ||
+ | } | ||
+ | |||
+ | if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ | ||
+ | options.continuousVertical = false; | ||
+ | showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); | ||
+ | } | ||
+ | |||
+ | if(options.scrollOverflow && !options.scrollOverflowHandler){ | ||
+ | options.scrollOverflow = false; | ||
+ | showError('error', 'The option `scrollOverflow:true` requires the file `scrolloverflow.min.js`. Please include it before fullPage.js.'); | ||
+ | } | ||
+ | |||
+ | //using extensions? Wrong file! | ||
+ | $.each(extensions, function(index, extension){ | ||
+ | //is the option set to true? | ||
+ | if(options[extension]){ | ||
+ | showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); | ||
+ | } | ||
+ | }); | ||
+ | //anchors can not have the same value as any element ID or NAME | ||
+ | $.each(options.anchors, function(index, name){ | ||
+ | |||
+ | //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) | ||
+ | var nameAttr = $document.find('[name]').filter(function() { | ||
+ | return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); | ||
+ | }); | ||
+ | |||
+ | var idAttr = $document.find('[id]').filter(function() { | ||
+ | return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); | ||
+ | }); | ||
+ | |||
+ | if(idAttr.length || nameAttr.length ){ | ||
+ | showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); | ||
+ | idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); | ||
+ | nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); | ||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Shows a message in the console of the given type. | ||
+ | */ | ||
+ | function showError(type, text){ | ||
+ | console && console[type] && console[type]('fullPage: ' + text); | ||
+ | } | ||
+ | |||
+ | }; //end of $.fn.fullpage | ||
}); | }); | ||
</script> | </script> |
Revision as of 18:15, 28 October 2017
Some section
Some section
Some section
Some section