UNPKG

slimscroll

Version:

slimscroll is a small commonjs module with no library dependencies (sans jquery) that transforms any div into a scrollable area with a nice scrollbar - similar to the one Facebook and Google started using in their products recently. slimScroll doesn't occ

1,604 lines (1,380 loc) 111 kB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 'use strict'; // console.log("example test wepps!!s"); var linotype = require('../../../index'); window.onload =function(){ window.Linotype = new linotype({ verticalCentered: false }); window.Linotype.init(); }; },{"../../../index":2}],2:[function(require,module,exports){ /* * linotype * http://github.amexpub.com/modules/linotype * * Copyright (c) 2013 AmexPub. All rights reserved. */ module.exports = require('./lib/linotype'); },{"./lib/linotype":4}],3:[function(require,module,exports){ /* * linotype * https://github.com/typesettin/linotype * @author yaw joseph etse * Copyright (c) 2014 Typesettin. All rights reserved. */ 'use strict'; var classie = require('classie'); // extend = require('util-extend'), // events = require('events'), // util = require('util'); /** * A module that adds simple dom utility functionality. * @author yaw joseph etse * @constructor */ var domhelper = { /** * toggles class across nodelist/elementcollection * @param {object} elementCollection - html dom element * @param {object} element - html dom element * @param {string} name of class! * @public */ removeAllClassAndToggle: function(element,elementCollection,toggleClass){ //updating the active class for(var h =0; h <elementCollection.length; h++){ classie.removeClass(elementCollection[h],toggleClass); } classie.addClass(element,toggleClass); }, /** * removes element from dom * @param {object} elementCollection - html dom element * @public */ removeElement: function(element){ //updating the active class element.parentNode.removeChild(element); }, /** * converts idnex of node in nodelist * @param {object} nodelist - html dom element * @param {object} element - html dom element * @return {number} index of element in nodelist * @method */ nodeIndexOfNodeList: function(nodelist,element){ return domhelper.nodelistToArray(nodelist,true).indexOf(element.outerHTML); }, /** * converts nodelists to arrays * @param {node} nl - html dom element * @return { array} array of html nodes * @method */ nodelistToArray: function(nl,useStrings){ var arr = []; for (var i = 0, ref = arr.length = nl.length; i < ref; i++) { arr[i] = (useStrings) ? nl[i].outerHTML : nl[i]; } return arr; }, /** * Returns cloaset DOM element. * @param {node} element - html dom element * @return {node} - closet node element * @method */ closetElement: function(element){ if(typeof element.length === 'number'){ return undefined; } var matches = domhelper.nodelistToArray(document.querySelectorAll(element.nodeName+'.'+element.className.trim().split(" ").join("."))), cleanMatches = []; // console.log("matches",matches.length,matches); for (var x =0; x < matches.length; x++){ // console.log('x',x,'element',element,'matches[x]',matches[x],'isEqualNode',matches[x].isEqualNode(element),'compareDocumentPosition',element.compareDocumentPosition(matches[x])); if(element.compareDocumentPosition(matches[x])<4 && !matches[x].isEqualNode(element)){ cleanMatches.push(matches[x]); } } function compareNumbers(a, b) { return a.compareDocumentPosition( b ) - b.compareDocumentPosition( a ); } // console.log("matches cleaned",cleanMatches.length,cleanMatches); // console.log("matches sorted",cleanMatches.sort(compareNumbers)); return cleanMatches[0]; }, /** * Hides DOM elements. * @method * @param {node} element - html dom element */ elementHideCss: function(element){ element.style.display="none"; }, /** * Shows DOM elements. * @method * @param {node} element - html dom element */ elementShowCss: function(element){ element.setAttribute('style',element.getAttribute('style').replace("display: none;")); }, /** * Wraps inner elements * @method * @param {node} element - html dom element * @param {node} innerElement - element to wrap html dom element */ elementContentWrapInner: function(element,innerElement){ var wrapper = element, w = innerElement, len = element.childElementCount, wrapper_clone = wrapper.cloneNode(true); wrapper.innerHTML=''; wrapper.appendChild(w); var newFirstChild = wrapper.firstChild; newFirstChild.innerHTML=wrapper_clone.innerHTML; }, /** * Wraps element with wrapper * @method * @param {node} element - html dom element * @param {node} wrapperElement - element to wrap html dom element */ elementWrap: function(element,wrapperElement){ var elementParent =element.parentNode, element_clone = element.cloneNode(true); elementParent.replaceChild(wrapperElement,element); wrapperElement.appendChild(element); }, /** * get scroll position of element * @method * @param {node} element - html dom element * @return {number} position of scroll */ getScrollTop: function(element){ // console.log(typeof element); if(element === window && typeof window.pageYOffset!== 'undefined'){ //most browsers except IE before #9 return window.pageYOffset; } else if(typeof element ==="object"){ return element.scrollTop; } else { var B= document.body; //IE 'quirks' var D= document.documentElement; //IE with doctype D= (D.clientHeight)? D: B; return D.scrollTop; } }, /** * get scroll position of element * @method * @param {node} element - html dom element * @return {object} position element */ getPosition: function(element) { var xPosition = 0; var yPosition = 0; while(element) { xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft); yPosition += (element.offsetTop - element.scrollTop + element.clientTop); element = element.offsetParent; } return { x: xPosition, y: yPosition, left: xPosition, top: yPosition }; }, /** * get element selector * @method * @param {node} element - html dom element * @return {string} query selector string */ getElementSelector: function(element){ var tagSelector = (element.tagName) ? element.tagName:'', idSelector = (element.id) ? '#'+element.id+'':'', classSelector=''; if(element.classList){ for(var x=0; x < element.classList.length; x++){ classSelector+='.'+element.classList[x]+""; } } return tagSelector+idSelector+classSelector; }, /** * get parent element * @method * @param {node} element - html dom element * @param {string} selector - selector * @param {string} selectorType - selector type (id or class) */ getParentElement: function(element,selector,selectorType){ if(element.tagName==='BODY' || element.tagName==='HTML' || selector==='body' || selector==='html' || selector===undefined){ // console.log('body selected'); return undefined; } else if( (selectorType==='id' && element.parentNode.id === selector) || element.parentNode.className.match(new RegExp(selector,'g'))){ // console.log("parent node"); return element.parentNode; //new RegExp(pattern,modifiers) } else { // console.log("look up higher"); return domhelper.getParentElement(element.parentNode,selector,selectorType); } }, getPreviousElements: function(element,returnArray){ if(element.previousElementSibling){ returnArray.push(element.previousElementSibling); return domhelper.getPreviousElements(element.previousElementSibling,returnArray); } else{ return returnArray; } }, getNextElements: function(element,returnArray){ if(element.nextElementSibling){ returnArray.push(element.nextElementSibling); return domhelper.getNextElements(element.nextElementSibling,returnArray); } else{ return returnArray; } }, insertAllBefore: function(element,elementsToInsert){ var parentElement = element.parentNode; // console.log("parentElement",parentElement,"element",element,"elementsToInsert",elementsToInsert); if(elementsToInsert.length){ for(var x =0; x<elementsToInsert.length; x++){ // console.log(x,"elementsToInsert[x]",elementsToInsert[x]) parentElement.insertBefore(elementsToInsert[x],element); } } else{ parentElement.insertBefore(elementsToInsert,element); } }, insertAllAfter: function(element,elementsToInsert){ var parentElement = element.parentNode; var nextSibling = element.nextSibling; // console.log("parentElement",parentElement,"element",element,"elementsToInsert",elementsToInsert); if(elementsToInsert.length){ for(var x =0; x<elementsToInsert.length; x++){ // console.log(x,"elementsToInsert[x]",elementsToInsert[x]) // elementsToInsert[x].style.background="green"; parentElement.insertBefore(elementsToInsert[x],nextSibling); } } else{ parentElement.insertBefore(elementsToInsert,nextSibling); } }, unwrapElement: function(element){ var parentNodeElem = element.parentNode; if(parentNodeElem.nodeName !== "BODY"){ var parentParentNodeElem = parentNodeElem.parentNode; parentParentNodeElem.innerHTML=''; parentParentNodeElem.appendChild(element); } }, onWindowLoaded: function(callback){ var readyStateCheckInterval = setInterval(function() { if (document.readyState === "complete") { callback(); clearInterval(readyStateCheckInterval); } }, 10); } }; module.exports = domhelper; // If there is a window object, that at least has a document property, // define linotype if ( typeof window === "object" && typeof window.document === "object" ) { window.domhelper = domhelper; } },{"classie":11}],4:[function(require,module,exports){ /** * @title linotype * @{@link https://github.com/typesettin/linotype} * @author Yaw Joseph Etse * @copyright Copyright (c) 2014 Typesettin. All rights reserved. * @license MIT */ 'use strict'; var classie = require('classie'), extend = require('util-extend'), events = require('events'), domhelper = require('./domhelper'), Slimscroll = require('./slimscroll'), util = require('util'); /** * A module that represents a linotype object, a linotyper is a page composition tool. * @{@link https://github.com/typesettin/linotype} * @author Yaw Joseph Etse * @copyright Copyright (c) 2014 Typesettin. All rights reserved. * @license MIT * @module linotype * @requires module:classie * @requires module:util-extent * @requires module:util * @requires module:events * @todo need to finish the .closet implementation for @linotype.getTableHeight method * @todo need @linotype~checkParentForNormalScrollElement to fix parent.isEqualNode to loop through selector of normalscrollelements called from @linotype~touchMoveHandler * @todo fix resizeme text sizing * @throws {ConfigurationError} If conflicting scrolling options are set */ var linotype = function(config_options){ /** module default configuration */ var options, linotypeElement, defaults = { 'verticalCentered' : true, 'resize' : true, 'slidesColor' : [], 'anchors':[], 'scrollingSpeed': 700, 'easing': 'easeInQuart', 'menu': false, 'navigation': false, 'navigationPosition': 'right', 'navigationColor': '#000', 'navigationTooltips': [], 'slidesNavigation': false, 'slidesNavPosition': 'bottom', 'controlArrowColor': '#fff', 'loopBottom': false, 'loopTop': false, 'loopHorizontal': true, 'autoScrolling': true, 'scrollOverflow': false, 'css3': true, 'paddingTop': 0, 'paddingBottom': 0, 'fixedElements': null, 'normalScrollElements': null, 'keyboardScrolling': true, 'touchSensitivity': 5, 'continuousVertical': false, 'animateAnchor': true, 'idSelector' : 'fullpage', 'normalScrollElementTouchThreshold': 5, //events 'afterLoad': null, 'onLeave': null, 'afterRender': null, 'afterResize': null, 'afterSlideLoad': null, 'onSlideLeave': null }, ConfigurationError = function(message){ this.name = "ConfigurationError"; this.message = message || "Linotype Configuration Error"; }, scrollDelay = (typeof config_options === "object" && typeof config_options.scrollDelay === "number") ? config_options.scrollDelay : 600, container, slideMoving = false, isTablet = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|Windows Phone)/), windowsHeight, isMoving = false, isResizing = false, resizeTimeout = false, lastScrolledDestiny, lastScrolledSlide, scrollId, isScrolling = false, touchStartY = 0, touchStartX = 0, touchEndY = 0, touchEndX = 0; //extend default options options = extend( defaults,config_options ); /** * @exception {ConfigurationError} If conflicting scrolling options are set */ ConfigurationError.prototype = new Error(); ConfigurationError.prototype.constructor = ConfigurationError; if (options.continuousVertical && (options.loopTop || options.loopBottom)) { options.continuousVertical = false; throw new ConfigurationError("Option loopTop/loopBottom is mutually exclusive with continuousVertical; continuousVertical disabled"); } /** @throws Disable mutually exclusive settings */ if (scrollDelay < 400) { options.continuousVertical = false; throw new RangeError("BE CAREFUL! Not recommened to change it under 400 for a good behavior in laptops and Apple devices (laptops, mouses...)"); } /** The current module configuration */ this.config = function(){ return options; }; /** The current scroll delay setting */ this.scrollDelay = function(){ return scrollDelay; }; /** * set the scrolling behaviour * @param {number} value */ this.setAutoScrolling = function(value){ options.autoScrolling = value; //el = document.getElementById( options.idSelector ), //sections = el.getElementsByClassName( options.sectionClass ); var element = document.getElementsByClassName('section active')[0], docElemHTML = document.getElementsByTagName("html")[0], docElemBody = document.getElementsByTagName("body")[0], elementPosition = getPosition(element); if(options.autoScrolling){ docElemHTML.style.overflow = 'hidden'; docElemHTML.style.height = '100%'; docElemBody.style.overflow = 'hidden'; docElemBody.style.height = '100%'; if(element.length){ //moving the container up silentScroll(elementPosition.top); } } else{ docElemHTML.style.overflow = 'auto'; docElemHTML.style.height = 'auto'; docElemBody.style.overflow = 'auto'; docElemBody.style.height = 'auto'; silentScroll(0); //scrolling the page to the section with no animation docElemHTML.scrollTop = elementPosition.top; docElemBody.scrollTop = elementPosition.top; } }; /** * Defines the scrolling speed * @param {number} value - set the scrolling speed */ this.setScrollingSpeed = function(value){ options.scrollingSpeed = value; }; /** * Adds or remove the possiblity of scrolling through sections by using the keyboard arrow keys * @param {number} value */ this.setKeyboardScrolling = function (value){ options.keyboardScrolling = value; }; /** * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. * @param {number} value */ this.setMouseWheelScrolling = function (value){ console.log('setMouseWheelScrolling',value); if(value){ addMouseWheelHandler(); }else{ removeMouseWheelHandler(); } }; /** * Adds or remove the possiblity of scrolling through sections by using the mouse wheel/trackpad or touch gestures. * @param {number} value */ this.setAllowScrolling = function (value){ if(value){ this.setMouseWheelScrolling(true); addTouchHandler(); } else{ this.setMouseWheelScrolling(false); removeTouchHandler(); } }; /** * Moves to previous section */ this.moveSectionUp = function(){ // console.log("moveSectionUp"); var prev = document.querySelector('.section.active').previousElementSibling; // console.log("prev",prev); if(prev && classie.hasClass(prev,'section')){ //looping to the bottom if there's no more sections above if (!prev && (options.loopTop || options.continuousVertical)) { prev = document.getElementsByClassName('section')[document.getElementsByClassName('section').length - 1]; } if (prev) { scrollPage(prev, null, true); } } }; /** * Moves to next section */ this.moveSectionDown = function (){ var next = document.querySelector('.section.active').nextElementSibling; if(next && classie.hasClass(next,'section')){ //looping to the top if there's no more sections below if(!next && (options.loopBottom || options.continuousVertical)){ next = document.getElementsByClassName('section')[0];//$('.section').first(); } if(next){ scrollPage(next, null, false); } } }; /** * Moves to specific section * @param {number} section - number of section * @param {number} slide - numder of slide */ this.moveTo = function (section, slide){ var destiny = ''; if(isNaN(section)){ destiny = document.querySelector('[data-anchor="'+section+'"]'); }else{ destiny = document.getElementsByClassName('section')[ (section -1) ]; } if (typeof slide !== 'undefined'){ scrollPageAndSlide(section, slide); }else if(destiny){ scrollPage(destiny); } }; /** * moves slide right */ this.moveSlideRight = function(){ moveSlide('next'); }; /** * moves slide left */ this.moveSlideLeft = function(){ moveSlide('prev'); }; /** * intialize a new linotype */ this.init = function(){ var docElemBody = document.getElementsByTagName('body')[0]; windowsHeight = document.documentElement.clientHeight; linotypeElement = document.getElementById(options.idSelector); container = linotypeElement; //activate touch events this.setAllowScrolling(true); if(options.css3){ options.css3 = support3d(); } if(linotypeElement){ container.style.height='100%'; container.style.position='relative'; container.style['-ms-touch-action']='none'; } else{ var oldBodyHTML = document.getElementsByTagName('body')[0].innerHTML; document.getElementsByTagName('body')[0].innerHTML='<div id="superContainer">'+oldBodyHTML+'</div>'; container = document.getElementById('superContainer'); } //creating the navigation dots if (options.navigation) { var navHTML = document.createElement('div'); navHTML.innerHTML = "<ul></ul>"; navHTML.setAttribute("id", "fullPage-nav"); docElemBody.appendChild(navHTML); var nav = document.getElementById("fullPage-nav"); nav.style.color = options.navigationColor; classie.addClass(nav,options.navigationPosition); } var sections = container.getElementsByClassName('section'); for(var index = 0; index < sections.length; index++){ var that = sections[index]; var $this = sections[index]; var slides = ($this !== 'undefined') ? $this.getElementsByClassName('slide') : 0; var numSlides = slides.length; //if no active section is defined, the 1st one will be the default one if(!index && document.getElementsByClassName('section active').length === 0) { classie.addClass($this,'active'); } if($this.style !== undefined){ $this.style.height = windowsHeight + 'px'; if(options.paddingTop || options.paddingBottom){ $this.style.padding = options.paddingTop + ' 0 ' + options.paddingBottom + ' 0'; } if (typeof options.slidesColor[index] !== 'undefined') { $this.style['background-color'] = options.slidesColor[index]; } } if (typeof options.anchors[index] !== 'undefined' && typeof $this === 'object' ) { $this.setAttribute('data-anchor', options.anchors[index]); } if (options.navigation) { var link = (options.anchors.length)? options.anchors[index]:'', tooltip = (typeof options.navigationTooltips[index] !== 'undefined')? options.navigationTooltips[index] : '', navToSetHTML = document.getElementById("fullPage-nav"), navUL = navToSetHTML.getElementsByTagName('ul')[0], newLIToAdd = document.createElement('li'); newLIToAdd.innerHTML='<a href="#' + link + '"><span></span></a></li>'; if(tooltip){ newLIToAdd.setAttribute('data-tooltip',tooltip); } navUL.appendChild(newLIToAdd); } // if there's any slide if (numSlides > 0) { var sliderWidth = numSlides * 100; var slideWidth = 100 / numSlides; var slidesContainerEl = document.createElement("div"); var slidesContainerForControlsEl = document.createElement("div"); slidesContainerEl.setAttribute('class','slidesContainer'); slidesContainerForControlsEl.setAttribute('class','slides'); elementContentWrapInner($this,slidesContainerEl); elementContentWrapInner($this,slidesContainerForControlsEl); $this.getElementsByClassName('slidesContainer')[0].style.width = sliderWidth + '%'; $this.innerHTML += '<div class="controlArrow prev"></div><div class="controlArrow next"></div>'; if(options.controlArrowColor!=='#fff'){ $this.getElementsByClassName('controlArrow next')[0].style['border-color'] = 'transparent transparent transparent '+options.controlArrowColor; $this.getElementsByClassName('controlArrow prev')[0].style['border-color'] = 'transparent transparent transparent '+options.controlArrowColor; } if(!options.loopHorizontal){ elementHideCss($this.getElementsByClassName('controlArrow prev')[0]); } if(options.slidesNavigation){ addSlidesNavigation($this, numSlides); } for(var i = 0; i< numSlides;i++){ //if the slide won#t be an starting point, the default will be the first one if(!i && $this.getElementsByClassName('slide active').length ===0){ classie.addClass($this.getElementsByClassName('slide')[0],'active'); } $this.getElementsByClassName('slide')[i].style.width=slideWidth + '%'; if(options.verticalCentered){ addTableClass($this.getElementsByClassName('slide')[i]); } } } else{ if(options.verticalCentered){ addTableClass($this); } } } this.setup(); }.bind(this); /** * finalizing the module for events */ this.setup = function(){ this.setAutoScrolling(options.autoScrolling); var nav = document.getElementById("fullPage-nav"); //the starting point is a slide? var activeSlide = document.getElementsByClassName('section active')[0].getElementsByClassName(' slide active')[0]; // console.log("activeSlide",activeSlide); if( typeof activeSlide !== 'undefined' && activeSlide.length && ( nodelistToArray(document.getElementsByClassName('section'),true).indexOf(activeSlide.outerHTML)/* $('.section.active').index('.section')*/ !== 0 || ( nodelistToArray(document.getElementsByClassName('section'),true).indexOf(activeSlide.outerHTML) /* $('.section.active').index('.section')*/ === 0 )/*&& activeSlide.index() !== 0 */) ){ var prevScrollingSpeepd = options.scrollingSpeed; this.setScrollingSpeed(0); landscapeScroll(document.getElementsByClassName('section active').getElementsByClassName('slides') , activeSlide); this.setScrollingSpeed(prevScrollingSpeepd); } // //fixed elements need to be moved out of the plugin container due to problems with CSS3. if(options.fixedElements && options.css3){ document.getElementsByTagName('body')[0].appendChild(document.querySelector(options.fixedElements)); } //vertical centered of the navigation + first bullet active if(options.navigation){ nav.style['margin-top'] = '-' + (nav.offsetHeight/2) + 'px'; var activeSection = nodelistToArray(document.getElementsByClassName('section'),true).indexOf(document.getElementsByClassName('section active')[0].outerHTML); var navigationATag = nav.getElementsByTagName('li')[activeSection].getElementsByTagName('a')[0]; classie.addClass(navigationATag,'active'); } //moving the menu outside the main container (avoid problems with fixed positions when using CSS3 tranforms) if(options.menu && options.css3){ document.getElementsByTagName('body')[0].appendChild(document.querySelector(options.menu)); } if(options.scrollOverflow){ //after DOM and images are loaded // if (document.readyState === "complete") { init(); } onWindowLoaded(function(){ var sections = document.getElementsByClassName('section'); for(var x=0; x < sections.length; x++){ var slides = sections[x].getElementsByClassName('slide'); var $this = sections[x]; if(slides.length){ for(var y=0; y< slides.length; y++){ // console.log(x,y,' slides'); createSlimScrolling(slides[y]); } } else{ // console.log(x,'no slides'); createSlimScrolling($this); } } if(typeof options.afterRender === "function"){ options.afterRender(); } }); } else{ if(typeof options.afterRender === "function"){ options.afterRender(); } } //getting the anchor link in the URL and deleting the `#` var value = window.location.hash.replace('#', '').split('/'); var destiny = value[0]; if(destiny.length){ var section = document.querySelector('[data-anchor="'+destiny+'"]'); if(!options.animateAnchor && section.length){ silentScroll( getPosition(section).top); if(typeof options.afterLoad === "function"){ options.afterLoad( destiny, (nodelistToArray(document.getElementsByClassName('section'),true).indexOf(section.outerHTML) + 1)); } //updating the active class var sectionColllection = document.getElementsByClassName('section'); for(var h =0; h <sectionColllection.length; h++){ classie.removeClass(sectionColllection[h],'active'); } classie.addClass(section,'active'); } } onWindowLoaded(function() { scrollToAnchor(); }); this.setupEventHandlers(); }.bind(this); /** * The current scroll delay setting */ this.setupEventHandlers = function(){ window.addEventListener("hashchange", windowOnHashChangeEvent, false); window.addEventListener("scroll",windowScrollEvent, false); window.addEventListener("onorientationchange",browserOnOrientationChange, false); window.addEventListener("resize",windowResizeEvent, false); document.addEventListener("keydown",keydownEvent,false); var sections = document.querySelectorAll('.section'); for(var t =0; t<sections.length;t++){ sections[t].addEventListener("click",sectionClickEvent,false); } var navlinks = document.querySelectorAll('#fullPage-nav a'); for(var x =0; x<navlinks.length;x++){ navlinks[x].addEventListener("click",navigationClickEvent,false); } if(options.slidesNavigation){ document.querySelector('.fullPage-slidesNav').addEventListener('click',slideNavClickEvent,false); } }; /** * Adds the possibility to auto scroll through sections on touch devices. */ function addTouchHandler(){ document.removeEventListener('touchstart'); document.removeEventListener('MSPointerDown'); document.addEventListener('touchstart',touchStartHandler,false); document.addEventListener('MSPointerDown',touchStartHandler,false); document.removeEventListener('touchmove'); document.removeEventListener('MSPointerMove'); document.addEventListener('touchmove',touchMoveHandler,false); document.addEventListener('MSPointerMove',touchMoveHandler,false); } /** * Removes the auto scrolling for touch devices. */ function removeTouchHandler(){ document.removeEventListener('touchmove MSPointerMove'); } var elementHideCss = domhelper.elementHideCss; var elementShowCss = domhelper.elementShowCss; var elementContentWrapInner = domhelper.elementContentWrapInner; var unwrapElement = domhelper.unwrapElement; var onWindowLoaded = domhelper.onWindowLoaded; var nodelistToArray = domhelper.nodelistToArray; var closetElement = domhelper.closetElement; var getParentElement = domhelper.getParentElement; var insertAllBefore = domhelper.insertAllBefore; var insertAllAfter = domhelper.insertAllAfter; var getNextElements = domhelper.getNextElements; var getPreviousElements = domhelper.getPreviousElements; var nodeIndexOfNodeList = domhelper.nodeIndexOfNodeList; var getScrollTop = domhelper.getScrollTop; var removeAllClassAndToggle = domhelper.removeAllClassAndToggle; var getElementSelector = domhelper.getElementSelector; var getPosition = domhelper.getPosition; function touchStartHandler(e){ var touchEvents = getEventsPage(e); touchStartY = touchEvents.y; touchStartX = touchEvents.x; } /** * 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 = []; if (window.navigator.msPointerEnabled){ events.y = e.pageY; events.x = e.pageX; }else{ events.y = e.touches[0].pageY; events.x = e.touches[0].pageX; } return events; } /* 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. */ var touchMoveHandler = function(e){ // var e = event; if(options.autoScrolling){ //preventing the easing on iOS devices e.preventDefault(); } // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain if (!checkParentForNormalScrollElement(e.target)) { var touchMoved = false; var activeSection = document.querySelector('.section.active'); var scrollable; if (!isMoving && !slideMoving) { //if theres any # var touchEvents = getEventsPage(e); touchEndY = touchEvents.y; touchEndX = touchEvents.x; //if movement in the X axys is greater than in the Y and the currect section has slides... if (activeSection.getElementsByClassName('slide').length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { //is the movement greater than the minimum resistance to scroll? if (Math.abs(touchStartX - touchEndX) > (window.innerWidth / 100 * options.touchSensitivity)) { if (touchStartX > touchEndX) { this.moveSlideRight(); //next } else { this.moveSlideLeft(); //prev } } } //vertical scrolling (only when autoScrolling is enabled) else if(options.autoScrolling){ //if there are landscape slides, we check if the scrolling bar is in the current one or not if(activeSection.getElementsByClassName('slide').length){ scrollable= activeSection.querySelector('.slide.active').querySelector('.scrollable'); }else{ scrollable = activeSection.querySelector('.scrollable'); } //is the movement greater than the minimum resistance to scroll? if (Math.abs(touchStartY - touchEndY) > (window.innerHeight / 100 * options.touchSensitivity)) { if (touchStartY > touchEndY) { if(scrollable && scrollable.length > 0 ){ //is the scrollbar at the end of the scroll? if(isScrolled('bottom', scrollable)){ this.moveSectionDown(); }else{ return true; } }else{ // moved down this.moveSectionDown(); } } else if (touchEndY > touchStartY) { if(scrollable && scrollable.length > 0){ //is the scrollbar at the start of the scroll? if(isScrolled('top', scrollable)){ this.moveSectionUp(); } else{ return true; } }else{ // moved up this.moveSectionUp(); } } } } } } }.bind(this); /** * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements * Currently works well for iOS - Android might need some testing * @param {Element} el target element / jquery selector (in subsequent nodes) * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold * @return {boolean} true if there is a match to options.normalScrollElements * @todo need to fix parent.isEqualNode to loop through selector of normalscrollelements called from @linotype~touchMoveHandler */ function checkParentForNormalScrollElement (el, hop) { hop = hop || 0; var parent = el.parentNode; if (hop < options.normalScrollElementTouchThreshold && parent.isEqualNode(document.querySelector(options.normalScrollElements)) ) { return true; } else if (hop === options.normalScrollElementTouchThreshold) { return false; } else { return checkParentForNormalScrollElement(parent, ++hop); } } /** * Retuns `up` or `down` depending on the scrolling movement to reach its destination * from the current section. */ function getYmovement(destiny){ var fromIndex = nodeIndexOfNodeList(document.getElementsByClassName('section'),document.getElementsByClassName('section active')[0]); //$('.section.active').index('.section'); var toIndex = nodeIndexOfNodeList(document.getElementsByClassName('section'),destiny);//destiny.index('.section'); 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'; } /** * Sliding with arrow keys, both, vertical and horizontal */ var keydownEvent = function(e){ console.log("keydownEvent",isMoving); if (options.keyboardScrolling && !isMoving) { switch (e.which) { //up case 38: case 33: this.moveSectionUp(); break; //down case 40: case 34: this.moveSectionDown(); break; //left case 37: this.moveSlideLeft(); break; //right case 39: this.moveSlideRight(); break; default: return; // exit this handler for other keys } } }.bind(this); /** * Removes the auto scrolling action fired by the mouse wheel and tackpad. * 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 } else { document.detachEvent("onmousewheel", MouseWheelHandler); //IE 6/7/8 } } /** * Adds the auto scrolling action for the mouse wheel and tackpad. * After this function is called, the mousewheel and trackpad movements will scroll through sections */ function addMouseWheelHandler(){ if (document.addEventListener) { document.addEventListener("mousewheel", MouseWheelHandler, false); //IE9, Chrome, Safari, Oper document.addEventListener("wheel", MouseWheelHandler, false); //Firefox } else { document.attachEvent("onmousewheel", MouseWheelHandler); //IE 6/7/8 } } /** * Detecting mousewheel scrolling * * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html * http://www.sitepoint.com/html5-javascript-mouse-wheel/ */ var MouseWheelHandler = function (e){ /* jshint debug:true */ // debugger; if(options.autoScrolling){ // cross-browser wheel delta e = window.event || e; var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.deltaY || -e.detail))); var scrollable; var activeSection = document.querySelector('.section.active'); if (!isMoving) { //if theres any # //if there are landscape slides, we check if the scrolling bar is in the current one or not if(activeSection.querySelectorAll('.slides').length){ console.log("has slides"); scrollable= activeSection.querySelector('.slide.active').querySelector('.scrollable'); }else{ console.log("on section"); scrollable = activeSection.querySelector('.scrollable'); // console.log("scrollable.length",(typeof scrollable.length)); } //scrolling down? if (delta < 0) { if(scrollable){ //is the scrollbar at the end of the scroll? if(isScrolled('bottom', scrollable)){ this.moveSectionDown(); }else{ return true; //normal scroll } }else{ this.moveSectionDown(); } } //scrolling up? else { if(scrollable){ //is the scrollbar at the start of the scroll? if(isScrolled('top', scrollable)){ this.moveSectionUp(); }else{ return true; //normal scroll } }else{ this.moveSectionUp(); } } } return false; } }.bind(this); /** handle updating window hash location */ function windowOnHashChangeEvent(e){ if(!isScrolling){ var value = window.location.hash.replace('#', '').split('/'); var section = value[0]; var slide = value[1]; //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slide === 'undefined'); /*in order to call scrollpage() only once for each destination at a time It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` event is fired on every scroll too.*/ if ((section && section !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide !== slide )) { scrollPageAndSlide(section, slide); } } } //window scroll event function windowScrollEvent(e){ // console.log("window scroll"); var allSections = document.getElementsByClassName('section'); if(!options.autoScrolling){ var currentScroll = getScrollTop(window); var scrolledSections = []; nodelistToArray(document.querySelectorAll('.section')).map(function(mapIndex,index,arr){ var $this = mapIndex; if ($this.offsetTop< (currentScroll + 100)){ if($this){scrolledSections.push($this);} } }); //geting the last one, the current one on the screen var currentSectionIndex = scrolledSections.length-1; var currentSection = scrolledSections[currentSectionIndex]; // console.log("currentSection",currentSection); //executing only once the first time we reach the section if(!classie.hasClass(currentSection,'active')){ var leavingSection =nodeIndexOfNodeList(document.getElementsByClassName('section'),document.querySelector('.section.active')) +1; isScrolling = true; var yMovement = getYmovement(currentSection); removeAllClassAndToggle(currentSection,allSections,'active'); var anchorLink = currentSection.getAttribute('data-anchor'); if(typeof options.onLeave ==='function'){ options.onLeave.call(leavingSection, (currentSectionIndex + 1), yMovement); } activateMenuElement(anchorLink); activateNavDots(anchorLink, 0); if(options.anchors.length && !isMoving){ //needed to enter in hashChange event when using the menu with anchor links lastScrolledDestiny = anchorLink; location.hash = anchorLink; } //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet clearTimeout(scrollId); scrollId = setTimeout(function(){ isScrolling = false; }, 100); } } } //navigation action function navigationClickEvent(e){ e.preventDefault(); var atarget = e.target.parentNode.parentNode; var allNavTargets = e.target.parentNode.parentNode.parentNode.children; var index = nodeIndexOfNodeList(allNavTargets,atarget); scrollPage(document.getElementsByClassName('section')[index]); } //slidenav click event function slideNavClickEvent(e){ e.preventDefault(); var etarget = e.target; if(etarget.tagName==='SPAN'){ var slides = document.querySelector('.section.active').querySelectorAll('.slide'), destiny; var slideLI = etarget.parentNode.parentNode; var allSlidesLI = etarget.parentNode.parentNode.parentNode.children; classie.addClass(slideLI,'clickedTarget'); destiny = slides[nodeIndexOfNodeList(allSlidesLI,slideLI)]; classie.removeClass(slideLI,'clickedTarget'); landscapeScroll(slides,destiny); } } //click events var sectionClickEvent = function(e){ var eventTarget = e.target; if(classie.hasClass(eventTarget,'controlArrow')){ if(classie.hasClass(eventTarget,'prev')){ this.moveSlideLeft(); } else{ this.moveSlideRight(); } } else if(classie.hasClass(eventTarget,'toSlide')){ e.preventDefault(); console.log("toSlide"); // var slides = $(this).closest('.section').find('.slides'); // var currentSlide = slides.find('.slide.active'); // var destiny = null; // destiny = slides.find('.slide').eq( ($(this).data('index') -1) ); // if(destiny.length > 0){ // landscapeScroll(slides, destiny); // } } }.bind(this); //window resize event function windowResizeEvent(e){ clearTimeout(resizeTimeout); resizeTimeout = setTimeout(doneResizing, 500); } //mobile orientation change function browserOnOrientationChange(e){ console.log("browserOnOrientationChange"); doneResizing(); } /** * When resizing is finished, we adjust the slides sizes and positions */ function doneResizing() { isResizing = true; var windowsWidth = window.innerWidth; windowsHeight = window.innerHeight; //text and images resizing if (options.resize) { resizeMe(windowsHeight, windowsWidth); } var allSections = document.getElementsByClassName('section'); for(var x = 0; x <allSections.length; x++){ var $this = allSections[x], scrollHeight = getScrollHeight($this), slides = $this.querySelectorAll('.slide'); //adjusting the height of the table-cell for IE and Firefox if(options.verticalCentered){ $this.querySelector('.tableCell').style.height = getTableHeight($this) + 'px'; } $this.style.height = windowsHeight + 'px'; //resizing the scrolling divs if(options.scrollOverflow){ if(slides.length){ for(var y=0; y< slides.length; y++){ // console.log(x,y,' slides'); createSlimScrolling(slides[y]); } }else{ createSlimScrolling($this); } } //adjusting the position fo the FULL WIDTH slides... if (slides.length) { landscapeScroll(slides, $this.querySelector('.slide.active')); } } //adjusting the position for the current section var activeSection = document.querySelector('.section.active'); var destinyPos = getPosition(activeSection); //isn't it the first section? if(nodeIndexOfNodeList(allSections,activeSection)){ scrollPage(activeSection); } isResizing = false; if(typeof options.afterResize ==='function') {options.afterResize.call();} } /** * Resizing of the font size depending on the window size as well as some of the images on the site. */ function resizeMe(displayHeight, displayWidth) { //Standard height, for which the body font size is correct var preferredHeight = 825; var windowSize = displayHeight; /* Problem to be solved if (displayHeight < 825) { var percentage = (windowSize * 100) / preferredHeight; var newFontSize = percentage.toFixed(2); $("img").each(function() { var newWidth = ((80 * percentage) / 100).toFixed(2); $(this).css("width", newWidth + '%'); }); } else { $("img").each(function() { $(this).css("width", ''); }); }*/ if (displayHeight < 825 || displayWidth < 900) { // console.log("displayHeight",displayHeight); // console.log("displayWidth",displayWidth); if (displayWidth < 900) { windowSize = displayWidth; preferredHeight = 900; } var percentage = (windowSize * 100) / preferredHeight; var newFontSize = percentage.toFixed(2); // console.log("percentage",percentage); // console.log("newFontSize",newFontSize); document.getElementsByTagName("body")[0].style["font-size"] = newFontSize + '%'; } else { // console.log("displayHeight",displayHeight); // console.log("displayWidth",displayWidth); document.getElementsByTagName("body")[0].style["font-size"] = '100%'; } } function scrollToAnchor(){ //getting the anchor link in the URL and deleting the `#` var value = window.location.hash.replace('#', '').split('/'); var section = value[0]; var slide = value[1]; if(section){ //if theres any # scrollPageAndSlide(section, slide); } } /** * Scrolls to the given section and slide */ function scrollPageAndSlide(destiny, slide){ // console.log("scrollPageAndSlide"); var section; if (typeof slide === 'undefined') { slide = 0; } if(isNaN(destiny)){ section = document.querySelector('[data-anchor="'+destiny+'"]'); } else{ section = document.getElementsByClassName('section')[(destiny -1)]; } if(section){ //we need to scroll to the section and then to the slide if (destiny !== lastScrolledDestiny && !classie.hasClass(section,'active')){ scrollPage(section, function(){ scrollSlider(section, slide); }); } //if we were already in the section else{ scrollSlider(section, slide); } } } /** * Scrolls the slider to the given slide destination for the given section */ function scrollSlider(section, slide){ if(typeof slide !== 'undefined' && slide !== 0){ var slides = section.querySelectorAll('.slide'); var destiny = section.querySelector('.slides').querySelector('[data-anchor="'+slide+'"]'); if(!destiny){ destiny = section.querySelectorAll('.slide')[slide]; } if(destiny){ landscapeScroll(slides, destiny); } } } function moveSlide(direction){ var activeSection = document.querySelector('.section.active'); var slides = activeSection.getElementsByClassName('slide'); // more than one slide needed and nothing should be sliding if (!slides.length || slideMoving) { return; } var currentSlide = activeSection.querySelector('.slide.active'); var destiny = null; if(direction === 'prev'){ destiny = currentSlide.previousElementSibling; }else{ destiny = currentSlide.nextElementSibling; } //isn't there a next slide in the secuence? if(!destiny){ //respect loopHorizontal settin if (!options.loopHorizontal) {return;} if(direction === 'prev'){ destiny = currentSlide.parentNode.lastElementChild;// currentSlide.siblings(':last'); }else{ destiny = currentSlide.parentNode.firstElementChild;//currentSlide.siblings(':first'); } } slideMoving = true; landscapeScroll(slides, destiny); } function scrollPage(element, callback, isMovementUp){ var scrollOptions = {}, scrolledElement, dest = getPosition(element); if(typeof dest === "undefined"){ return; } //there's no element to scroll, leaving the function /** @todo TODO: why does dest.bottom === jquery.position().top */ var dtop = dest.top, yMovement = getYmovement(element), anchorLink = element.getAttribute('data-anchor'), sectionIndex = nodelistToArray(document.getElementsByClassName('section'),true).indexOf(element.outerHTML), ///element.index('.section'); activeSlide = element.querySelector('.slide.active'), activeSection = document.querySelector('.section.active'), leavingSection = nodelistToArray(document.getElementsByClassName('section'),true).indexOf(activeSection.outerHTML) +1,//activeSection.index('.section') + 1; slideAnchorLink = null, slideIndex = null, localIsResizing = isResizing;//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 if(activeSlide !== null){ slideAnchorLink = activeSlide.getAttribute('data-anchor'); slideIndex = nodelistToArray(element.getElementsByClassName('slide'),true).indexOf(activeSlide.outerHTML);//activeSlide.index(); } // console.log("slideIndex",slideIndex); // If continuousVertical && we need to wrap around if (options.autoScrolling && options.continuousVertical && typeof (isMovementUp) !== "undefined" && ((!isMovementUp && yMovement === 'up') || // Intending to scroll down but about to go up or (isMovementUp && yMovement === 'down'))) { // intending to scroll up but about to go down // Scrolling down if (!isMovementUp) { // Move all previous sections to after the active section var muarray =[]; insertAllAfter(activeSection,getPreviousElements(activeSection,muarray).reverse()); // $(".section.active").after(activeSection.prevAll(".section").get().reverse()); } else { // Scrolling up // Move all next sections to before the active section var mdarray =[]; insertAllBefore(activeSection,getNextElements(activeSection,mdarray)); // $(".section.active").before(activeSection.nextAll(".section")); } // Maintain the displayed position (now that we changed the element order) silentScroll(getPosition(activeSection).top); // save for later the elements that still need to be reordered var wrapAroundElements = activeSection; // Recalculate animation variables dest = getPosition(element); dtop = dest.top; yMovement = getYmovement(element); } var elementCol = document.getElementsByClassName('section'); removeAllClassAndToggle(element,elementCol,'active'); //preventing from activating the MouseWheelHandler event //more than once if the page is scrolling isMoving = true; if