From 7cd2fe0b546ef48a540d949fd1f21009cfaf9f37 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Wed, 18 Feb 2015 03:41:40 +0300 Subject: [PATCH] Full update --- README.md | 84 ++------- dist/skrollr.decks.js | 388 ++++++++++++++++---------------------- dist/skrollr.decks.min.js | 4 +- gulpfile.js | 4 + index.html | 301 +++++++++++++++++------------ package.json | 2 +- src/skrollr.decks.js | 386 ++++++++++++++++--------------------- 7 files changed, 533 insertions(+), 636 deletions(-) diff --git a/README.md b/README.md index 40f49aa..bbf1026 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,37 @@ -skrollr-decks -============= +#skrollr-decks [skrollr](https://github.com/Prinzhorn/skrollr) plugin for fullpage presentation decks -#Installation +##Installation -First of all: look at the example -http://trysound.github.io/skrollr-decks/ - -Download the `dist/skrollr.decks.min.js` file and include it right after the `skrollr.min.js` file. Then you need to add 'skrollr-decks-init' class to any element on your page and 'skrollr-deck' class on every sections. - -Skrollr-decks will set `min-height` of each segment to the height of window. It will also autoresize with the window resizing. - -If the height of segment is more than window height then the segement will scroll through before triggering the next segment. - -#Usage - -##Navigation - -skrollr-decks can either generate nagivation or use existing navigation. - -Just add this HTML to your page: - -```html - +``` +bower i skrollr-decks ``` -##Custom Decks - -If you wank create custom decks call this method - -###skrollr.decks.init(options) - -####options.segments - -Type: `String`; Default: `'.skrollr-deck'` - -classname of segments - -####options.nav - -Type: `String`; Default: `'.skrollr-decks-nav'` - -classname of navigation - -####options.gotoDuration - -Type: `Integer`; Default: `600` - -scrolling duration on nav link click - -####options.deckDuration +Add 'skrollr-decks-init' class to `` and 'skrollr-deck' class to every section. -Type: `Integer`; Default: `300` -auto scrolling duration to next or previous deck +##API -####options.deckDelay +###skrollr.decks.init(options) -Type: `Integer`; Default: `200` +- `options.decks` (.skrollr-deck) - decks classname +- `offset` (15) - offset in percents to deck since which will autoscroll +- `duration`(600) - scrolling duration +- `easing`(quaratic) - scrolling easing, [more](https://github.com/Prinzhorn/skrollr#easing) +- `delay`(500) - delay before scroll +- `autoscroll`(true) -delay for mouse scrolling +###skrollr.decks.refresh() -####options.autoScroll +Recalc height of all decks. Need to update when content added -Type: `Boolean`; Default: `true` +###skrollr.decks.animateTo(anchor, noAnimation) -enable auto scroll on next or previous deck detection +- `anchor` - `#id` of deck, `up` or `down` +- `noAnimation` - prevents animation -#License +##License [The MIT License (MIT)](LICENSE) diff --git a/dist/skrollr.decks.js b/dist/skrollr.decks.js index 847457f..495f581 100644 --- a/dist/skrollr.decks.js +++ b/dist/skrollr.decks.js @@ -1,5 +1,5 @@ /*! - * skrollr-decks 0.2.2 + * skrollr-decks 1.0.0 * Fullpage presentation decks with scrolling * https://github.com/TrySound/skrollr-decks * @@ -20,281 +20,223 @@ } (function (window, document, skrollr) { "use strict"; - var setTimeout = window.setTimeout, - clearTimeout = window.clearTimeout; + var defaults = { + decks: '.skrollr-deck', + offset: 15, + duration: 600, + easing: 'quadratic', + delay: 500, + autoscroll: true, + onRender: null + }; - /** - * Helpers - * - */ - function hasClass(el, name) { - return new RegExp(' ' + name + ' ').test(' ' + el.className + ' '); - } + var setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + isInitialized = false, + settings = {}, + segments = {}, + segmentsList = [], + nav = document.createElement('ul'); + - function addClass(el, name) { - if ( el && ! hasClass(el, name)) { - el.className += (el.className ? ' ' : '') + name; + // Stop animating on scroll keys + document.addEventListener('keydown', function (e) { + var inst = skrollr.get(), + keys = [38, 40, + 33, 34, + 36, 35]; + + if(keys.indexOf(e.keyCode) > -1) { + if(inst && inst.isAnimatingTo()) { + inst.stopAnimateTo(); + } } - } + }, false); + + // Auto resize + window.addEventListener('resize', resizeDecks); - function removeClass(el, name) { - if (el && hasClass(el, name)) { - el.className = el.className.replace(new RegExp('(\\s|^)'+name+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, ''); + // Auto initialize + document.addEventListener('DOMContentLoaded', function () { + var el = document.querySelector('.skrollr-decks-init'); + if(el && el.tagName === 'BODY') { + init(); } - } + }, false); - /** - * Main Class - * - */ - function Main(settings) { - var inst = skrollr.get(), - renderTimer, - delay = settings.deckDelay, - update = this.updateSegment.bind(this); + return { + init: init, + animateTo: animateTo, + refresh: resizeDecks + }; - this._settings = settings; - this.getSegments(settings.segments); - if(this._segments.length > 0) { - this.resizeSegments(); - this.getNav(settings.nav); - this.listenAnchors(); - inst.refresh(); - inst.on('render', function (e) { - clearTimeout(renderTimer); - renderTimer = setTimeout(function () { - update(e.direction === 'up'); - }, delay); - }); + // Initialize + function init (user) { + if(isInitialized) { + return false; } else { - this.invalid = true; + isInitialized = true; } - } - Main.prototype = { - setActive: function (deck, duration) { - var item = this._items[deck.getAttribute('data-skrollr-decks-index')], - scroller = skrollr.get(), - offset; + var key, inst, renderTimer; - offset = scroller.relativeToAbsolute(deck, 'top', 'top'); - scroller.animateTo(offset + 1, { - duration: duration - }); - - if(this._activeDeck !== 'deck') { - removeClass(this._activeItem, 'skrollr-decks-achor-active'); - removeClass(this._activeDeck, 'skrollr-deck-active'); - addClass(item, 'skrollr-decks-achor-active'); - addClass(deck, 'skrollr-deck-active'); - this._activeItem = item; - this._activeDeck = deck; - } - }, - - getSegments: function (selector) { - var segments, - result = [], - el, i, max; - - if(typeof selector === 'string') { - segments = document.querySelectorAll(selector); - } else if(selector.tagName) { - segments = [selector]; - } else if(selector.length) { - segments = selector; - } + user = typeof user === 'object' ? user : {}; + for(key in defaults) if(defaults.hasOwnProperty(key)) { + settings[key] = user[key] || defaults[key]; + } - for(i = 0, max = segments.length; i < max; i++) { - el = segments[i]; + inst = skrollr.init({ + forceHeight: false + }); - if(el.tagName) { - if(! el.id) { - el.id = 'skrollr-deck-' + i; - } - result.push(el); - } - } + segments = findDecks(settings.decks, segmentsList); + nav = createNav(segmentsList); - this._segments = result; - return result; - }, + resizeDecks(); - resizeSegments: function () { - var segments = this._segments, - wnd = window; + document.body.appendChild(nav); - function setHeight() { - var height = wnd.innerHeight + 2 + 'px', - i; + inst.refresh(nav.children); - for(i = segments.length; i--; ) { - segments[i].style.minHeight = height; - } - }; - - setHeight(); - window.addEventListener('resize', setHeight, false); - }, - - updateSegment: function (direction) { - var inst = skrollr.get(), - items, item, segment; - - items = this._nav.getElementsByClassName('skrollable-between'); - item = items[direction ? 0 : items.length - 1]; - - segment = this._segments[item.getAttribute('data-skrollr-decks-index')]; - if(items.length > 1 || window.innerHeight + 2 === segment.clientHeight) { - this.setActive(segment, this._settings.deckDuration); - } - }, + if(settings.autoscroll) { + window.addEventListener('resize', update, false); + inst.on('render', function (e) { + clearTimeout(renderTimer); + renderTimer = setTimeout(function () { + update(e); + }, settings.delay); + }); + } + } - getNav: function (selector) { - var nav, menu, - segments = this._segments; + // Goto + function animateTo(anchor, noAnim) { + var el = segments[anchor], + inst = skrollr.get(), + top, active, index; - if(typeof selector === 'string') { - nav = document.querySelector(selector); - } else if(selector.tagName) { - nav = selector; - } else if(selector.length && selector[0].tagName) { - nav = selector[0]; - } + if(inst) { + inst.stopAnimateTo(); - this._items = []; - if(nav) { - if(nav.tagName === 'UL') { - menu = nav; - this.appendLinks(menu); - } else { - menu = nav.getElementsByTagName('ul')[0]; - if(menu) { - this.appendLinks(menu); - } else { - menu = this.appendLinks(); - nav.appendChild(menu); - } + if( ! el) { + active = nav.getElementsByClassName('skrollable-between'); + if(active.length === 1) { + index = Number(active[0].getAttribute('data-skrollr-decks-index')); + el = segmentsList[anchor === 'up' ? index - 1 : anchor === 'down' ? index + 1 : -1]; } - } else { - menu = this.appendLinks(); - menu.className = 'skrollr-decks-nav'; - document.body.insertBefore(menu, document.body.firstChild); - } - this._nav = menu; - return menu; - }, - - appendLinks: function (menu) { - var segments = this._segments, - el, items, id, - i, max; - - if(menu) { - items = menu.getElementsByTagName('li'); - } else { - menu = document.createElement('ul'); - menu.style.display = 'none'; - items = []; + if(active.length === 2) { + active = active[anchor === 'up' ? 0 : anchor === 'down' ? 1 : -1]; + el = active ? segments[active.getAttribute('data-anchor-target')] : null; + } } - for(i = 0, max = segments.length; i < max; i++) { - id = '#' + segments[i].id; - el = items[i]; - if( ! el) { - el = document.createElement('li'); - menu.appendChild(el); + if(el) { + top = inst.relativeToAbsolute(el, 'top', 'top') + 1; + if(noAnim) { + inst.setScrollTop(top, true); + } else { + inst.animateTo(top, settings); } - segments[i].setAttribute('data-skrollr-decks-index', i); - el.setAttribute('data-skrollr-decks-index', i); - el.setAttribute('data-anchor-target', id); - el.innerHTML = '' + el.innerHTML + ''; - if( ! el.hasAttribute('data-top-bottom')) { - el.setAttribute('data-top-bottom', ''); - } - if( ! el.hasAttribute('data-bottom-top')) { - el.setAttribute('data-bottom-top', ''); - } - this._items.push(el); + return true; } + } - return menu; - }, + return false; + } - listenAnchors: function () { - var self = this; + // Update decks size + function resizeDecks() { + var wndHeight = window.innerHeight + 2, + deck, deckHeight, key; + for(key in segments) if(segments.hasOwnProperty(key)) { + deck = segments[key]; + deck.style.height = 'auto'; + deckHeight = deck.offsetHeight; + deck.style.height = (deckHeight < wndHeight ? wndHeight : deckHeight) + 'px'; + } + } - self._nav.addEventListener('click', function (event) { - var anchor = event.target, - item = anchor.parentNode, - index, - segment; - if(anchor.tagName === 'A' && item.hasAttribute('data-skrollr-decks-index')) { - index = item.getAttribute('data-skrollr-decks-index'); - segment = self._segments[index]; - self.setActive(segment, self._settings.gotoDuration); - } - event.preventDefault(); - }, false); - } - }; - var Decks = { - init: function (user) { - var defaults = { - segments: '.skrollr-deck', - nav: '.skrollr-decks-nav', - gotoDuration: 600, - deckDuration: 300, - deckDelay: 200, - autoScroll: true - }; + // Autoscroll + function update(e) { + var inst = skrollr.get(), + active = nav.getElementsByClassName('skrollable-between'), + el, before, after; - var key, - settings = {}; + if(active.length === 2) { + before = e.direction === 'up' ? 0 : 1; + after = e.direction === 'up' ? 1 : 0; - user = typeof user === 'object' ? user : {}; - for(key in defaults) if(defaults.hasOwnProperty(key)) { - settings[key] = user[key] || defaults[key]; + el = segments[active[before].getAttribute('data-anchor-target')]; + if( ! isVol(el)) { + el = segments[active[after].getAttribute('data-anchor-target')]; } + inst.animateTo(inst.relativeToAbsolute(el, 'top', 'top') + 1, settings); + } + } - var inst = skrollr.init({ - forceHeight: false - }); + function isVol(el) { + var inst = skrollr.get(), + top = inst.getScrollTop(), + height = window.innerHeight, + bottom = top + height, + elTop = inst.relativeToAbsolute(el, 'top', 'top'), + elBottom = inst.relativeToAbsolute(el, 'top', 'bottom'), + offset = height * settings.offset / 100; + + return elTop + offset < bottom && elBottom - offset > top; + } - if( ! this._decks) { - this._decks = new Main(settings); - if(this._decks.invalid) { - this._decks = undefined; - } + + // Layout + function findDecks(selector, list) { + var items = {}, + start = +new Date(), + el, i, id; + + if(typeof selector === 'string') { + selector = document.querySelectorAll(selector); + for(i = selector.length - 1; i > -1; i--) { + el = selector[i]; + list.unshift(el); + el.id = !! el.id ? el.id : 'skroll-deck-id-' + i; + items['#' + el.id] = el; } } - }; + return items; + } - // Auto-initialize - document.addEventListener('DOMContentLoaded', function () { - var init = this.querySelector('.skrollr-decks-init'); + function createNav(list) { + var frag = document.createElement('ul'), + item = document.createElement('li'), + i, max, el; - if(init) { - Decks.init(); - } - }, false); + frag.style.display = 'none'; + item.setAttribute('data-top-bottom', ''); + item.setAttribute('data-bottom-top', ''); + for(i = 0, max = list.length; i < max; i++) { + el = item.cloneNode(); + el.setAttribute('data-skrollr-decks-index', i); + el.setAttribute('data-anchor-target', '#' + list[i].id); + frag.appendChild(el); + } - return Decks; + return frag; + } })); diff --git a/dist/skrollr.decks.min.js b/dist/skrollr.decks.min.js index b4c9b6d..7dee05f 100644 --- a/dist/skrollr.decks.min.js +++ b/dist/skrollr.decks.min.js @@ -1,9 +1,9 @@ /*! - * skrollr-decks 0.2.2 + * skrollr-decks 1.0.0 * Fullpage presentation decks with scrolling * https://github.com/TrySound/skrollr-decks * * Released under the MIT license * Copyright (c) 2015, Bogdan Chadkin */ -!function(t){"use strict";window.skrollr?window.skrollr.decks=t(window,document,window.skrollr):console.error("`skrollr` not found")}(function(t,e,s){"use strict";function i(t,e){return new RegExp(" "+e+" ").test(" "+t.className+" ")}function n(t,e){t&&!i(t,e)&&(t.className+=(t.className?" ":"")+e)}function r(t,e){t&&i(t,e)&&(t.className=t.className.replace(new RegExp("(\\s|^)"+e+"(\\s|$)")," ").replace(/^\s+|\s+$/g,""))}function a(t){var e,i=s.get(),n=t.deckDelay,r=this.updateSegment.bind(this);this._settings=t,this.getSegments(t.segments),this._segments.length>0?(this.resizeSegments(),this.getNav(t.nav),this.listenAnchors(),i.refresh(),i.on("render",function(t){l(e),e=o(function(){r("up"===t.direction)},n)})):this.invalid=!0}var o=t.setTimeout,l=t.clearTimeout;a.prototype={setActive:function(t,e){var i,a=this._items[t.getAttribute("data-skrollr-decks-index")],o=s.get();i=o.relativeToAbsolute(t,"top","top"),o.animateTo(i+1,{duration:e}),"deck"!==this._activeDeck&&(r(this._activeItem,"skrollr-decks-achor-active"),r(this._activeDeck,"skrollr-deck-active"),n(a,"skrollr-decks-achor-active"),n(t,"skrollr-deck-active"),this._activeItem=a,this._activeDeck=t)},getSegments:function(t){var s,i,n,r,a=[];for("string"==typeof t?s=e.querySelectorAll(t):t.tagName?s=[t]:t.length&&(s=t),n=0,r=s.length;r>n;n++)i=s[n],i.tagName&&(i.id||(i.id="skrollr-deck-"+n),a.push(i));return this._segments=a,a},resizeSegments:function(){function e(){var t,e=i.innerHeight+2+"px";for(t=s.length;t--;)s[t].style.minHeight=e}var s=this._segments,i=t;e(),t.addEventListener("resize",e,!1)},updateSegment:function(e){{var i,n,r;s.get()}i=this._nav.getElementsByClassName("skrollable-between"),n=i[e?0:i.length-1],r=this._segments[n.getAttribute("data-skrollr-decks-index")],(i.length>1||t.innerHeight+2===r.clientHeight)&&this.setActive(r,this._settings.deckDuration)},getNav:function(t){{var s,i;this._segments}return"string"==typeof t?s=e.querySelector(t):t.tagName?s=t:t.length&&t[0].tagName&&(s=t[0]),this._items=[],s?"UL"===s.tagName?(i=s,this.appendLinks(i)):(i=s.getElementsByTagName("ul")[0],i?this.appendLinks(i):(i=this.appendLinks(),s.appendChild(i))):(i=this.appendLinks(),i.className="skrollr-decks-nav",e.body.insertBefore(i,e.body.firstChild)),this._nav=i,i},appendLinks:function(t){var s,i,n,r,a,o=this._segments;for(t?i=t.getElementsByTagName("li"):(t=e.createElement("ul"),t.style.display="none",i=[]),r=0,a=o.length;a>r;r++)n="#"+o[r].id,s=i[r],s||(s=e.createElement("li"),t.appendChild(s)),o[r].setAttribute("data-skrollr-decks-index",r),s.setAttribute("data-skrollr-decks-index",r),s.setAttribute("data-anchor-target",n),s.innerHTML=''+s.innerHTML+"",s.hasAttribute("data-top-bottom")||s.setAttribute("data-top-bottom",""),s.hasAttribute("data-bottom-top")||s.setAttribute("data-bottom-top",""),this._items.push(s);return t},listenAnchors:function(){var t=this;t._nav.addEventListener("click",function(e){var s,i,n=e.target,r=n.parentNode;"A"===n.tagName&&r.hasAttribute("data-skrollr-decks-index")&&(s=r.getAttribute("data-skrollr-decks-index"),i=t._segments[s],t.setActive(i,t._settings.gotoDuration)),e.preventDefault()},!1)}};var c={init:function(t){var e,i={segments:".skrollr-deck",nav:".skrollr-decks-nav",gotoDuration:600,deckDuration:300,deckDelay:200,autoScroll:!0},n={};t="object"==typeof t?t:{};for(e in i)i.hasOwnProperty(e)&&(n[e]=t[e]||i[e]);s.init({forceHeight:!1});this._decks||(this._decks=new a(n),this._decks.invalid&&(this._decks=void 0))}};return e.addEventListener("DOMContentLoaded",function(){var t=this.querySelector(".skrollr-decks-init");t&&c.init()},!1),c}); \ No newline at end of file +!function(t){"use strict";window.skrollr?window.skrollr.decks=t(window,document,window.skrollr):console.error("`skrollr` not found")}(function(t,e,o){"use strict";function n(n){if(g)return!1;g=!0;var r,l,m;n="object"==typeof n?n:{};for(r in u)u.hasOwnProperty(r)&&(p[r]=n[r]||u[r]);l=o.init({forceHeight:!1}),h=s(p.decks,b),k=d(b),i(),e.body.appendChild(k),l.refresh(k.children),p.autoscroll&&(t.addEventListener("resize",a,!1),l.on("render",function(t){f(m),m=c(function(){a(t)},p.delay)}))}function r(t,e){var n,r,i,a=h[t],l=o.get();return l&&(l.stopAnimateTo(),a||(r=k.getElementsByClassName("skrollable-between"),1===r.length&&(i=Number(r[0].getAttribute("data-skrollr-decks-index")),a=b["up"===t?i-1:"down"===t?i+1:-1]),2===r.length&&(r=r["up"===t?0:"down"===t?1:-1],a=r?h[r.getAttribute("data-anchor-target")]:null)),a)?(n=l.relativeToAbsolute(a,"top","top")+1,e?l.setScrollTop(n,!0):l.animateTo(n,p),!0):!1}function i(){var e,o,n,r=t.innerHeight+2;for(n in h)h.hasOwnProperty(n)&&(e=h[n],e.style.height="auto",o=e.offsetHeight,e.style.height=(r>o?r:o)+"px")}function a(t){var e,n,r,i=o.get(),a=k.getElementsByClassName("skrollable-between");2===a.length&&(n="up"===t.direction?0:1,r="up"===t.direction?1:0,e=h[a[n].getAttribute("data-anchor-target")],l(e)||(e=h[a[r].getAttribute("data-anchor-target")]),i.animateTo(i.relativeToAbsolute(e,"top","top")+1,p))}function l(e){var n=o.get(),r=n.getScrollTop(),i=t.innerHeight,a=r+i,l=n.relativeToAbsolute(e,"top","top"),s=n.relativeToAbsolute(e,"top","bottom"),d=i*p.offset/100;return a>l+d&&s-d>r}function s(t,o){{var n,r,i={};+new Date}if("string"==typeof t)for(t=e.querySelectorAll(t),r=t.length-1;r>-1;r--)n=t[r],o.unshift(n),n.id=n.id?n.id:"skroll-deck-id-"+r,i["#"+n.id]=n;return i}function d(t){var o,n,r,i=e.createElement("ul"),a=e.createElement("li");for(i.style.display="none",a.setAttribute("data-top-bottom",""),a.setAttribute("data-bottom-top",""),o=0,n=t.length;n>o;o++)r=a.cloneNode(),r.setAttribute("data-skrollr-decks-index",o),r.setAttribute("data-anchor-target","#"+t[o].id),i.appendChild(r);return i}var u={decks:".skrollr-deck",offset:15,duration:600,easing:"quadratic",delay:500,autoscroll:!0,onRender:null},c=t.setTimeout,f=t.clearTimeout,g=!1,p={},h={},b=[],k=e.createElement("ul");return e.addEventListener("keydown",function(t){var e=o.get(),n=[38,40,33,34,36,35];n.indexOf(t.keyCode)>-1&&e&&e.isAnimatingTo()&&e.stopAnimateTo()},!1),t.addEventListener("resize",i),e.addEventListener("DOMContentLoaded",function(){var t=e.querySelector(".skrollr-decks-init");t&&"BODY"===t.tagName&&n()},!1),{init:n,animateTo:r,refresh:i}}); \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index e7cbd6c..1ed60da 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -23,3 +23,7 @@ gulp.task('default', function () { })) .pipe(gulp.dest('dist')); }); + +gulp.task('dev', ['default'], function () { + gulp.watch('src/*.js', ['default']); +}) diff --git a/index.html b/index.html index cdce72b..36a30ae 100644 --- a/index.html +++ b/index.html @@ -10,64 +10,111 @@ @@ -75,75 +122,83 @@ - - - -
- -
- 1 -
- -
- 2 -
- -
- 3 -
- -
- 4 -
- -
- 5 -
- -
-

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi nobis fugit atque placeat, illo consequuntur ipsa corporis laborum commodi incidunt! Voluptas, vel, quibusdam.

-

Deleniti doloribus, voluptatibus praesentium recusandae, quos debitis. Voluptatum vel praesentium quo, pariatur odit nulla. Enim, ipsam, optio deserunt aperiam quo placeat ad repudiandae!

-

Rerum sed libero dolor neque explicabo amet culpa qui! Cupiditate accusamus necessitatibus quo, non, ratione facilis sint aliquam in iste optio quidem, eligendi.

-

Ex perferendis vitae iure nesciunt, tenetur laborum dolores, nulla, magni omnis libero cupiditate reprehenderit porro impedit quibusdam eveniet quos odio nihil laudantium repellendus.

-

Dolore ducimus est id alias unde aut ut magnam, quia voluptas dolorum sit rerum ea incidunt molestias, autem illo distinctio laboriosam commodi architecto?

-

Et adipisci vel molestias beatae odio vero tempore, suscipit consectetur fugiat similique consequuntur, officiis delectus enim reiciendis accusamus eum accusantium, possimus eos perferendis.

-

Odio minus enim, earum similique perspiciatis. Iusto eveniet, alias dignissimos expedita. Tempore rem, amet possimus. Nobis laudantium fugit est incidunt, libero atque aperiam.

-

Dolorum possimus magni optio distinctio facilis eum neque beatae debitis saepe voluptatibus laborum nam omnis excepturi adipisci perspiciatis, dicta amet odit impedit aspernatur!

-

Expedita labore et vero. Optio eius vitae illo ea aut doloribus cumque qui maiores consectetur, omnis, ut nulla cupiditate rerum. Sequi, quaerat, cupiditate.

-

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi nobis fugit atque placeat, illo consequuntur ipsa corporis laborum commodi incidunt! Voluptas, vel, quibusdam.

-

Deleniti doloribus, voluptatibus praesentium recusandae, quos debitis. Voluptatum vel praesentium quo, pariatur odit nulla. Enim, ipsam, optio deserunt aperiam quo placeat ad repudiandae!

-

Rerum sed libero dolor neque explicabo amet culpa qui! Cupiditate accusamus necessitatibus quo, non, ratione facilis sint aliquam in iste optio quidem, eligendi.

-

Ex perferendis vitae iure nesciunt, tenetur laborum dolores, nulla, magni omnis libero cupiditate reprehenderit porro impedit quibusdam eveniet quos odio nihil laudantium repellendus.

-

Dolore ducimus est id alias unde aut ut magnam, quia voluptas dolorum sit rerum ea incidunt molestias, autem illo distinctio laboriosam commodi architecto?

-

Et adipisci vel molestias beatae odio vero tempore, suscipit consectetur fugiat similique consequuntur, officiis delectus enim reiciendis accusamus eum accusantium, possimus eos perferendis.

-

Odio minus enim, earum similique perspiciatis. Iusto eveniet, alias dignissimos expedita. Tempore rem, amet possimus. Nobis laudantium fugit est incidunt, libero atque aperiam.

-

Dolorum possimus magni optio distinctio facilis eum neque beatae debitis saepe voluptatibus laborum nam omnis excepturi adipisci perspiciatis, dicta amet odit impedit aspernatur!

-

Expedita labore et vero. Optio eius vitae illo ea aut doloribus cumque qui maiores consectetur, omnis, ut nulla cupiditate rerum. Sequi, quaerat, cupiditate.

-
-
- +
+ + + + + + +
+ +
+ 1 +
+ +
+ 2 +
+ +
+ 3 +
+ +
+ 4 +
+ +
+ 5 +
+ +
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi nobis fugit atque placeat, illo consequuntur ipsa corporis laborum commodi incidunt! Voluptas, vel, quibusdam.

+

Deleniti doloribus, voluptatibus praesentium recusandae, quos debitis. Voluptatum vel praesentium quo, pariatur odit nulla. Enim, ipsam, optio deserunt aperiam quo placeat ad repudiandae!

+

Rerum sed libero dolor neque explicabo amet culpa qui! Cupiditate accusamus necessitatibus quo, non, ratione facilis sint aliquam in iste optio quidem, eligendi.

+

Ex perferendis vitae iure nesciunt, tenetur laborum dolores, nulla, magni omnis libero cupiditate reprehenderit porro impedit quibusdam eveniet quos odio nihil laudantium repellendus.

+

Dolore ducimus est id alias unde aut ut magnam, quia voluptas dolorum sit rerum ea incidunt molestias, autem illo distinctio laboriosam commodi architecto?

+

Et adipisci vel molestias beatae odio vero tempore, suscipit consectetur fugiat similique consequuntur, officiis delectus enim reiciendis accusamus eum accusantium, possimus eos perferendis.

+

Odio minus enim, earum similique perspiciatis. Iusto eveniet, alias dignissimos expedita. Tempore rem, amet possimus. Nobis laudantium fugit est incidunt, libero atque aperiam.

+

Dolorum possimus magni optio distinctio facilis eum neque beatae debitis saepe voluptatibus laborum nam omnis excepturi adipisci perspiciatis, dicta amet odit impedit aspernatur!

+

Expedita labore et vero. Optio eius vitae illo ea aut doloribus cumque qui maiores consectetur, omnis, ut nulla cupiditate rerum. Sequi, quaerat, cupiditate.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi nobis fugit atque placeat, illo consequuntur ipsa corporis laborum commodi incidunt! Voluptas, vel, quibusdam.

+

Deleniti doloribus, voluptatibus praesentium recusandae, quos debitis. Voluptatum vel praesentium quo, pariatur odit nulla. Enim, ipsam, optio deserunt aperiam quo placeat ad repudiandae!

+

Rerum sed libero dolor neque explicabo amet culpa qui! Cupiditate accusamus necessitatibus quo, non, ratione facilis sint aliquam in iste optio quidem, eligendi.

+

Ex perferendis vitae iure nesciunt, tenetur laborum dolores, nulla, magni omnis libero cupiditate reprehenderit porro impedit quibusdam eveniet quos odio nihil laudantium repellendus.

+

Dolore ducimus est id alias unde aut ut magnam, quia voluptas dolorum sit rerum ea incidunt molestias, autem illo distinctio laboriosam commodi architecto?

+

Et adipisci vel molestias beatae odio vero tempore, suscipit consectetur fugiat similique consequuntur, officiis delectus enim reiciendis accusamus eum accusantium, possimus eos perferendis.

+

Odio minus enim, earum similique perspiciatis. Iusto eveniet, alias dignissimos expedita. Tempore rem, amet possimus. Nobis laudantium fugit est incidunt, libero atque aperiam.

+

Dolorum possimus magni optio distinctio facilis eum neque beatae debitis saepe voluptatibus laborum nam omnis excepturi adipisci perspiciatis, dicta amet odit impedit aspernatur!

+

Expedita labore et vero. Optio eius vitae illo ea aut doloribus cumque qui maiores consectetur, omnis, ut nulla cupiditate rerum. Sequi, quaerat, cupiditate.

+
+
+ +
+ + diff --git a/package.json b/package.json index 8001509..25f7535 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "skrollr-decks", - "version": "0.2.2", + "version": "1.0.0", "description": "Fullpage presentation decks with scrolling", "main": "gulpfile.js", "scripts": { diff --git a/src/skrollr.decks.js b/src/skrollr.decks.js index f49e9a4..68acd10 100644 --- a/src/skrollr.decks.js +++ b/src/skrollr.decks.js @@ -11,281 +11,223 @@ } (function (window, document, skrollr) { "use strict"; - var setTimeout = window.setTimeout, - clearTimeout = window.clearTimeout; + var defaults = { + decks: '.skrollr-deck', + offset: 15, + duration: 600, + easing: 'quadratic', + delay: 500, + autoscroll: true, + onRender: null + }; - /** - * Helpers - * - */ - function hasClass(el, name) { - return new RegExp(' ' + name + ' ').test(' ' + el.className + ' '); - } + var setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + isInitialized = false, + settings = {}, + segments = {}, + segmentsList = [], + nav = document.createElement('ul'); + - function addClass(el, name) { - if ( el && ! hasClass(el, name)) { - el.className += (el.className ? ' ' : '') + name; + // Stop animating on scroll keys + document.addEventListener('keydown', function (e) { + var inst = skrollr.get(), + keys = [38, 40, + 33, 34, + 36, 35]; + + if(keys.indexOf(e.keyCode) > -1) { + if(inst && inst.isAnimatingTo()) { + inst.stopAnimateTo(); + } } - } + }, false); + + // Auto resize + window.addEventListener('resize', resizeDecks); - function removeClass(el, name) { - if (el && hasClass(el, name)) { - el.className = el.className.replace(new RegExp('(\\s|^)'+name+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, ''); + // Auto initialize + document.addEventListener('DOMContentLoaded', function () { + var el = document.querySelector('.skrollr-decks-init'); + if(el && el.tagName === 'BODY') { + init(); } - } + }, false); - /** - * Main Class - * - */ - function Main(settings) { - var inst = skrollr.get(), - renderTimer, - delay = settings.deckDelay, - update = this.updateSegment.bind(this); + return { + init: init, + animateTo: animateTo, + refresh: resizeDecks + }; - this._settings = settings; - this.getSegments(settings.segments); - if(this._segments.length > 0) { - this.resizeSegments(); - this.getNav(settings.nav); - this.listenAnchors(); - inst.refresh(); - inst.on('render', function (e) { - clearTimeout(renderTimer); - renderTimer = setTimeout(function () { - update(e.direction === 'up'); - }, delay); - }); + // Initialize + function init (user) { + if(isInitialized) { + return false; } else { - this.invalid = true; + isInitialized = true; } - } - Main.prototype = { - setActive: function (deck, duration) { - var item = this._items[deck.getAttribute('data-skrollr-decks-index')], - scroller = skrollr.get(), - offset; + var key, inst, renderTimer; - offset = scroller.relativeToAbsolute(deck, 'top', 'top'); - scroller.animateTo(offset + 1, { - duration: duration - }); - - if(this._activeDeck !== 'deck') { - removeClass(this._activeItem, 'skrollr-decks-achor-active'); - removeClass(this._activeDeck, 'skrollr-deck-active'); - addClass(item, 'skrollr-decks-achor-active'); - addClass(deck, 'skrollr-deck-active'); - this._activeItem = item; - this._activeDeck = deck; - } - }, - - getSegments: function (selector) { - var segments, - result = [], - el, i, max; - - if(typeof selector === 'string') { - segments = document.querySelectorAll(selector); - } else if(selector.tagName) { - segments = [selector]; - } else if(selector.length) { - segments = selector; - } + user = typeof user === 'object' ? user : {}; + for(key in defaults) if(defaults.hasOwnProperty(key)) { + settings[key] = user[key] || defaults[key]; + } - for(i = 0, max = segments.length; i < max; i++) { - el = segments[i]; + inst = skrollr.init({ + forceHeight: false + }); - if(el.tagName) { - if(! el.id) { - el.id = 'skrollr-deck-' + i; - } - result.push(el); - } - } + segments = findDecks(settings.decks, segmentsList); + nav = createNav(segmentsList); - this._segments = result; - return result; - }, + resizeDecks(); - resizeSegments: function () { - var segments = this._segments, - wnd = window; + document.body.appendChild(nav); - function setHeight() { - var height = wnd.innerHeight + 2 + 'px', - i; + inst.refresh(nav.children); - for(i = segments.length; i--; ) { - segments[i].style.minHeight = height; - } - }; - - setHeight(); - window.addEventListener('resize', setHeight, false); - }, - - updateSegment: function (direction) { - var inst = skrollr.get(), - items, item, segment; - - items = this._nav.getElementsByClassName('skrollable-between'); - item = items[direction ? 0 : items.length - 1]; - - segment = this._segments[item.getAttribute('data-skrollr-decks-index')]; - if(items.length > 1 || window.innerHeight + 2 === segment.clientHeight) { - this.setActive(segment, this._settings.deckDuration); - } - }, + if(settings.autoscroll) { + window.addEventListener('resize', update, false); + inst.on('render', function (e) { + clearTimeout(renderTimer); + renderTimer = setTimeout(function () { + update(e); + }, settings.delay); + }); + } + } - getNav: function (selector) { - var nav, menu, - segments = this._segments; + // Goto + function animateTo(anchor, noAnim) { + var el = segments[anchor], + inst = skrollr.get(), + top, active, index; - if(typeof selector === 'string') { - nav = document.querySelector(selector); - } else if(selector.tagName) { - nav = selector; - } else if(selector.length && selector[0].tagName) { - nav = selector[0]; - } + if(inst) { + inst.stopAnimateTo(); - this._items = []; - if(nav) { - if(nav.tagName === 'UL') { - menu = nav; - this.appendLinks(menu); - } else { - menu = nav.getElementsByTagName('ul')[0]; - if(menu) { - this.appendLinks(menu); - } else { - menu = this.appendLinks(); - nav.appendChild(menu); - } + if( ! el) { + active = nav.getElementsByClassName('skrollable-between'); + if(active.length === 1) { + index = Number(active[0].getAttribute('data-skrollr-decks-index')); + el = segmentsList[anchor === 'up' ? index - 1 : anchor === 'down' ? index + 1 : -1]; } - } else { - menu = this.appendLinks(); - menu.className = 'skrollr-decks-nav'; - document.body.insertBefore(menu, document.body.firstChild); - } - this._nav = menu; - return menu; - }, - - appendLinks: function (menu) { - var segments = this._segments, - el, items, id, - i, max; - - if(menu) { - items = menu.getElementsByTagName('li'); - } else { - menu = document.createElement('ul'); - menu.style.display = 'none'; - items = []; + if(active.length === 2) { + active = active[anchor === 'up' ? 0 : anchor === 'down' ? 1 : -1]; + el = active ? segments[active.getAttribute('data-anchor-target')] : null; + } } - for(i = 0, max = segments.length; i < max; i++) { - id = '#' + segments[i].id; - el = items[i]; - if( ! el) { - el = document.createElement('li'); - menu.appendChild(el); + if(el) { + top = inst.relativeToAbsolute(el, 'top', 'top') + 1; + if(noAnim) { + inst.setScrollTop(top, true); + } else { + inst.animateTo(top, settings); } - segments[i].setAttribute('data-skrollr-decks-index', i); - el.setAttribute('data-skrollr-decks-index', i); - el.setAttribute('data-anchor-target', id); - el.innerHTML = '' + el.innerHTML + ''; - if( ! el.hasAttribute('data-top-bottom')) { - el.setAttribute('data-top-bottom', ''); - } - if( ! el.hasAttribute('data-bottom-top')) { - el.setAttribute('data-bottom-top', ''); - } - this._items.push(el); + return true; } + } - return menu; - }, + return false; + } - listenAnchors: function () { - var self = this; + // Update decks size + function resizeDecks() { + var wndHeight = window.innerHeight + 2, + deck, deckHeight, key; + for(key in segments) if(segments.hasOwnProperty(key)) { + deck = segments[key]; + deck.style.height = 'auto'; + deckHeight = deck.offsetHeight; + deck.style.height = (deckHeight < wndHeight ? wndHeight : deckHeight) + 'px'; + } + } - self._nav.addEventListener('click', function (event) { - var anchor = event.target, - item = anchor.parentNode, - index, - segment; - if(anchor.tagName === 'A' && item.hasAttribute('data-skrollr-decks-index')) { - index = item.getAttribute('data-skrollr-decks-index'); - segment = self._segments[index]; - self.setActive(segment, self._settings.gotoDuration); - } - event.preventDefault(); - }, false); - } - }; - var Decks = { - init: function (user) { - var defaults = { - segments: '.skrollr-deck', - nav: '.skrollr-decks-nav', - gotoDuration: 600, - deckDuration: 300, - deckDelay: 200, - autoScroll: true - }; + // Autoscroll + function update(e) { + var inst = skrollr.get(), + active = nav.getElementsByClassName('skrollable-between'), + el, before, after; - var key, - settings = {}; + if(active.length === 2) { + before = e.direction === 'up' ? 0 : 1; + after = e.direction === 'up' ? 1 : 0; - user = typeof user === 'object' ? user : {}; - for(key in defaults) if(defaults.hasOwnProperty(key)) { - settings[key] = user[key] || defaults[key]; + el = segments[active[before].getAttribute('data-anchor-target')]; + if( ! isVol(el)) { + el = segments[active[after].getAttribute('data-anchor-target')]; } + inst.animateTo(inst.relativeToAbsolute(el, 'top', 'top') + 1, settings); + } + } - var inst = skrollr.init({ - forceHeight: false - }); + function isVol(el) { + var inst = skrollr.get(), + top = inst.getScrollTop(), + height = window.innerHeight, + bottom = top + height, + elTop = inst.relativeToAbsolute(el, 'top', 'top'), + elBottom = inst.relativeToAbsolute(el, 'top', 'bottom'), + offset = height * settings.offset / 100; + + return elTop + offset < bottom && elBottom - offset > top; + } - if( ! this._decks) { - this._decks = new Main(settings); - if(this._decks.invalid) { - this._decks = undefined; - } + + // Layout + function findDecks(selector, list) { + var items = {}, + start = +new Date(), + el, i, id; + + if(typeof selector === 'string') { + selector = document.querySelectorAll(selector); + for(i = selector.length - 1; i > -1; i--) { + el = selector[i]; + list.unshift(el); + el.id = !! el.id ? el.id : 'skroll-deck-id-' + i; + items['#' + el.id] = el; } } - }; + return items; + } - // Auto-initialize - document.addEventListener('DOMContentLoaded', function () { - var init = this.querySelector('.skrollr-decks-init'); + function createNav(list) { + var frag = document.createElement('ul'), + item = document.createElement('li'), + i, max, el; - if(init) { - Decks.init(); - } - }, false); + frag.style.display = 'none'; + item.setAttribute('data-top-bottom', ''); + item.setAttribute('data-bottom-top', ''); + for(i = 0, max = list.length; i < max; i++) { + el = item.cloneNode(); + el.setAttribute('data-skrollr-decks-index', i); + el.setAttribute('data-anchor-target', '#' + list[i].id); + frag.appendChild(el); + } - return Decks; + return frag; + } }));