diff --git a/Gruntfile.js b/Gruntfile.js index d7ee290..32f3a1c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -11,19 +11,28 @@ module.exports = function(grunt) { dest: 'shower.min.js' } }, - dalek: { - test: { - src: [ - 'tests/shortcuts.js', - 'tests/inner-nav.js' - ] + connect: { + ribbon: { + options: { + port: 7497 + } } + }, + dalek: { + options: { + browser: ['chrome'] + }, + src: [ + 'tests/*.js' + ] } }); grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-dalek'); grunt.registerTask('default', ['uglify']); + grunt.registerTask('test', ['connect', 'dalek']); }; \ No newline at end of file diff --git a/package.json b/package.json index b15d0f4..70098ca 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,11 @@ "private": true, "devDependencies": { "dalekjs": "0.0.8", + "dalek-browser-chrome": "0.0.9", "grunt": "~0.4.2", - "grunt-contrib-uglify": "~0.3.0", + "grunt-contrib-uglify": "~0.3.2", "grunt-dalek": "~0.2.0", - "grunt-contrib-watch": "~0.5.3" + "grunt-contrib-watch": "~0.5.3", + "grunt-contrib-connect": "~0.6.0" } } diff --git a/shower.js b/shower.js index ee55b8d..b99af88 100755 --- a/shower.js +++ b/shower.js @@ -493,7 +493,7 @@ window.shower = window.shower || (function(window, document, undefined) { shower.first = function(callback) { var slide = shower.slideList[shower.getCurrentSlideNumber()]; - slide.timing && slide.stopTimer(); + slide && slide.timing && slide.stopTimer(); shower.go(0); if (typeof(callback) === 'function') { @@ -508,7 +508,7 @@ window.shower = window.shower || (function(window, document, undefined) { shower.last = function(callback) { var slide = shower.slideList[shower.getCurrentSlideNumber()]; - slide.timing && slide.stopTimer(); + slide && slide.timing && slide.stopTimer(); shower.go(shower.slideList.length - 1); if (typeof(callback) === 'function') { @@ -599,13 +599,18 @@ window.shower = window.shower || (function(window, document, undefined) { /** * Get current slide number. Starts from zero. Warning: when you have * slide number 1 in URL this method will return 0. - * If something is wrong return 0 to get the first slide. + * If there is no slide number in url, return -1. + * If there is a slide number in url, but the slide does not exist, return 0. * @returns {Number} */ shower.getCurrentSlideNumber = function() { var i = shower.slideList.length - 1, currentSlideId = url.hash.substr(1); + if (currentSlideId === '') { + return -1; + } + // As fast as you can ;-) // http://jsperf.com/for-vs-foreach/46 for (; i >= 0; --i) { @@ -634,6 +639,11 @@ window.shower = window.shower || (function(window, document, undefined) { throw new Error('You can\'t scroll to because you in slide mode. Please, switch to list mode.'); } + // @TODO: WTF? + if (-1 === slideNumber) { + return ret; + } + if (shower.slideList[slideNumber]) { currentSlide = document.getElementById(shower.slideList[slideNumber].id); window.scrollTo(0, currentSlide.offsetTop); @@ -804,13 +814,27 @@ window.shower = window.shower || (function(window, document, undefined) { // Event handlers window.addEventListener('DOMContentLoaded', function() { - if (body.classList.contains('full') || shower.isSlideMode()) { - shower.go(shower.getCurrentSlideNumber()); + var currentSlideNumber = shower.getCurrentSlideNumber(), + isSlideMode = body.classList.contains('full') || shower.isSlideMode(); + + if (currentSlideNumber === -1 && isSlideMode) { + shower.go(0); + } else if (currentSlideNumber === 0 || isSlideMode) { + shower.go(currentSlideNumber); + } + + if (isSlideMode) { shower.enterSlideMode(); } }, false); window.addEventListener('popstate', function() { + var currentSlideNumber = shower.getCurrentSlideNumber(); + + if (currentSlideNumber !== -1) { + shower.go(currentSlideNumber); + } + if (shower.isListMode()) { shower.enterListMode(); } else { @@ -826,7 +850,7 @@ window.shower = window.shower || (function(window, document, undefined) { document.addEventListener('keydown', function(e) { var currentSlideNumber = shower.getCurrentSlideNumber(), - slide = shower.slideList[currentSlideNumber], + slide = shower.slideList[ currentSlideNumber !== -1 ? currentSlideNumber : 0 ], slideNumber; switch (e.which) { @@ -860,7 +884,7 @@ window.shower = window.shower || (function(window, document, undefined) { break; case 13: // Enter - if (shower.isListMode() && currentSlideNumber) { + if (shower.isListMode() && -1 !== currentSlideNumber) { e.preventDefault(); shower.enterSlideMode(); diff --git a/shower.min.js b/shower.min.js index df14e71..fecafef 100644 --- a/shower.min.js +++ b/shower.min.js @@ -1,6 +1,6 @@ /** * Shower HTML presentation engine: github.com/shower/shower - * @copyright 2010–2013 Vadim Makeev, pepelsbey.net + * @copyright 2010–2014 Vadim Makeev, pepelsbey.net * @license MIT license: github.com/shower/shower/wiki/MIT-License */ -window.shower=window.shower||function(a,b,c){function d(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b])}var e,f={},g=a.location,h=b.body,i=[],j=[],k=!(!a.history||!a.history.pushState);return d.prototype={getSlideNumber:function(){return this.number},isLast:function(){return f.slideList.length===this.number+1},isFinished:function(){return this.innerComplete>=this.innerLength},process:function(a){return this.timing?(this.initTimer(a),this):(this.next(a),this)},initTimer:function(a){var b=this;return b.timing?(b.stopTimer(),e=b.isFinished()?setInterval(function(){b.stopTimer(),a.next()},b.timing*(b.innerLength||1)):setInterval(function(){b.isFinished()?(b.stopTimer(),a.next()):b.next(a)},b.timing),this):!1},stopTimer:function(){return e&&(clearInterval(e),e=!1),this},prev:function(a){var c,d=this;return!d.hasInnerNavigation||d.isFinished()||0===d.innerComplete?(a.prev(),!1):(c=b.getElementById(d.id).querySelectorAll(".next.active"),!c||c.length<1?!1:(d.innerComplete>0?(d.innerComplete--,c[c.length-1].classList.remove("active")):a.prev(),this))},next:function(a){var c,d=this;return!d.hasInnerNavigation||d.isFinished()?(a.next(),!1):(d.isFinished()||(c=b.getElementById(d.id).querySelectorAll(".next:not(.active)"),c[0].classList.add("active"),d.innerComplete++),this)}},f._getData=function(a,b){return a.dataset?a.dataset[b]:a.getAttribute("data-"+b)},f.slideList=[],f.init=function(a,c){var e;a=a||".slide",c=c||"div.progress div",i=b.querySelectorAll(a),j=b.querySelector(c);for(var g=0;ga&&(a=0),a>=f.slideList.length&&(a=f.slideList.length-1),a},f._getSlideIdByEl=function(a){for(;"BODY"!==a.nodeName&&"HTML"!==a.nodeName;){if(a.classList.contains("slide"))return a.id;a=a.parentNode}return""},f._checkInteractiveElement=function(a){return"A"===a.target.nodeName},f.getSlideNumber=function(a){var b,c=f.slideList.length-1;for(""===a&&(b=0);c>=0;--c)if(a===f.slideList[c].id){b=c;break}return b},f.go=function(a,b){var c;if(!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");return f.slideList[a]?(g.hash=f.getSlideHash(a),f.updateProgress(a),f.updateActiveAndVisitedSlides(a),f.isSlideMode()&&(f.showPresenterNotes(a),c=f.slideList[a],c.timing&&c.initTimer(f)),"function"==typeof b&&b(),a):!1},f.next=function(a){var b=f.getCurrentSlideNumber(),c=f.slideList[b+1];return c?(f.go(b+1),"function"==typeof a&&a(),this):!1},f._turnNextSlide=function(a){var b=f.getCurrentSlideNumber(),c=f.slideList[b];f.isSlideMode()?(c.stopTimer(),c.next(f)):f.go(b+1),"function"==typeof a&&a()},f.prev=f.previous=function(a){var b=f.getCurrentSlideNumber();return 1>b?!1:(f.go(b-1),"function"==typeof a&&a(),!0)},f._turnPreviousSlide=function(a){var b=f.getCurrentSlideNumber(),c=f.slideList[b];return c.stopTimer(),f.isSlideMode()?c.prev(f):f.go(b-1),"function"==typeof a&&a(),!0},f.first=function(a){var b=f.slideList[f.getCurrentSlideNumber()];b.timing&&b.stopTimer(),f.go(0),"function"==typeof a&&a()},f.last=function(a){var b=f.slideList[f.getCurrentSlideNumber()];b.timing&&b.stopTimer(),f.go(f.slideList.length-1),"function"==typeof a&&a()},f.enterSlideMode=function(a){var b=f.getCurrentSlideNumber();return h.classList.remove("list"),h.classList.add("full"),f.isListMode()&&k&&history.pushState(null,null,g.pathname+"?full"+f.getSlideHash(b)),f._applyTransform(f._getTransform()),"function"==typeof a&&a(),!0},f.enterListMode=function(a){var b;return h.classList.remove("full"),h.classList.add("list"),f.clearPresenterNotes(),f.isListMode()?!1:(b=f.getCurrentSlideNumber(),f.slideList[b].stopTimer(),f.isSlideMode()&&k&&history.pushState(null,null,g.pathname+f.getSlideHash(b)),f.scrollToSlide(b),f._applyTransform("none"),"function"==typeof a&&a(),!0)},f.toggleMode=function(a){return f.isListMode()?f.enterSlideMode():f.enterListMode(),"function"==typeof a&&a(),!0},f.getCurrentSlideNumber=function(){for(var a=f.slideList.length-1,b=g.hash.substr(1);a>=0;--a)if(b===f.slideList[a].id)return a;return 0},f.scrollToSlide=function(c){var d,e=!1;if(!f._isNumber(c))throw new Error("Gimme slide number as Number, baby!");if(f.isSlideMode())throw new Error("You can't scroll to because you in slide mode. Please, switch to list mode.");if(!f.slideList[c])throw new Error("There is no slide with number "+c);return d=b.getElementById(f.slideList[c].id),a.scrollTo(0,d.offsetTop),e=!0,e},f.isListMode=function(){return k?!/^full.*/.test(g.search.substr(1)):h.classList.contains("list")},f.isSlideMode=function(){return k?/^full.*/.test(g.search.substr(1)):h.classList.contains("full")},f.updateProgress=function(a){if(null===j)return!1;if(!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");return j.style.width=(100/(f.slideList.length-1)*f._normalizeSlideNumber(a)).toFixed(2)+"%",!0},f.updateActiveAndVisitedSlides=function(a){var c,d,e=f.slideList.length;if(a=f._normalizeSlideNumber(a),!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");for(c=0;e>c;++c)d=b.getElementById(f.slideList[c].id),a>c?(d.classList.remove("active"),d.classList.add("visited")):c>a?(d.classList.remove("visited"),d.classList.remove("active")):(d.classList.remove("visited"),d.classList.add("active"));return!0},f.clearPresenterNotes=function(){f.isSlideMode()&&a.console&&a.console.clear&&console.clear()},f.showPresenterNotes=function(c){if(f.clearPresenterNotes(),a.console){c=f._normalizeSlideNumber(c);var d=f.slideList[c].id,e=f.slideList[c+1]?f.slideList[c+1].id:null,g=b.getElementById(d).querySelector("footer");if(g&&g.innerHTML&&console.info(g.innerHTML.replace(/\n\s+/g,"\n")),e){var h=b.getElementById(e).querySelector("h2");h&&(h=h.innerHTML.replace(/^\s+|<[^>]+>/g,""),console.info("NEXT: "+h))}}},f.getSlideHash=function(a){if(!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");return a=f._normalizeSlideNumber(a),"#"+f.slideList[a].id},f.wheel=function(a){var d,e=b.querySelector("body"),g="locked"===e.getAttribute("data-scroll");g||f.isListMode()||(e.setAttribute("data-scroll","locked"),d=a.deltaY===c?a.wheelDeltaY<0:a.deltaY>0,d?f._turnNextSlide():f._turnPreviousSlide(),setTimeout(function(){e.setAttribute("data-scroll","unlocked")},200))},a.addEventListener("DOMContentLoaded",function(){(h.classList.contains("full")||f.isSlideMode())&&(f.go(f.getCurrentSlideNumber()),f.enterSlideMode())},!1),a.addEventListener("popstate",function(){f.isListMode()?f.enterListMode():f.enterSlideMode()},!1),a.addEventListener("resize",function(){f.isSlideMode()&&f._applyTransform(f._getTransform())},!1),b.addEventListener("keydown",function(a){var b,c=f.getCurrentSlideNumber(),d=f.slideList[c];switch(a.which){case 80:f.isListMode()&&a.altKey&&a.metaKey&&(a.preventDefault(),b=d.number,f.go(b),f.enterSlideMode(),f.showPresenterNotes(b),d.timing&&d.initTimer(f));break;case 116:a.preventDefault(),f.isListMode()?(b=a.shiftKey?d.number:0,f.go(b),f.enterSlideMode(),f.showPresenterNotes(b),d.timing&&d.initTimer(f)):f.enterListMode();break;case 13:f.isListMode()&&c&&(a.preventDefault(),f.enterSlideMode(),f.showPresenterNotes(c),d.timing&&d.initTimer(f));break;case 27:f.isSlideMode()&&(a.preventDefault(),f.enterListMode());break;case 33:case 38:case 37:case 72:case 75:if(a.altKey||a.ctrlKey||a.metaKey)return;a.preventDefault(),f._turnPreviousSlide();break;case 34:case 40:case 39:case 76:case 74:if(a.altKey||a.ctrlKey||a.metaKey)return;a.preventDefault(),f._turnNextSlide();break;case 36:a.preventDefault(),f.first();break;case 35:a.preventDefault(),f.last();break;case 9:case 32:a.preventDefault(),f[a.shiftKey?"_turnPreviousSlide":"_turnNextSlide"]()}},!1),f.init(),b.addEventListener("click",function(a){var b,c,d=f._getSlideIdByEl(a.target);d&&f.isListMode()&&(b=f.getSlideNumber(d),f.go(b),f.enterSlideMode(),f.showPresenterNotes(b),c=f.slideList[b],c.timing&&c.initTimer(f))},!1),b.addEventListener("touchstart",function(b){var c,d,e,g=f._getSlideIdByEl(b.target);g&&(f.isSlideMode()&&!f._checkInteractiveElement(b)&&(e=b.touches[0].pageX,e>a.innerWidth/2?f._turnNextSlide():f._turnPreviousSlide()),f.isListMode()&&(c=f.getSlideNumber(g),f.go(c),f.enterSlideMode(),f.showPresenterNotes(c),d=f.slideList[c],d.timing&&d.initTimer(f)))},!1),b.addEventListener("touchmove",function(a){f.isSlideMode()&&a.preventDefault()},!1),b.addEventListener("wheel",f.wheel,!1),b.addEventListener("mousewheel",f.wheel,!1),f}(this,this.document); \ No newline at end of file +window.shower=window.shower||function(a,b,c){function d(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b])}var e,f={},g=a.location,h=b.body,i=[],j=[],k=!(!a.history||!a.history.pushState);return d.prototype={getSlideNumber:function(){return this.number},isLast:function(){return f.slideList.length===this.number+1},isFinished:function(){return this.innerComplete>=this.innerLength},process:function(a){return this.timing?(this.initTimer(a),this):(this.next(a),this)},initTimer:function(a){var b=this;return b.timing?(b.stopTimer(),e=b.isFinished()?setInterval(function(){b.stopTimer(),a.next()},b.timing*(b.innerLength||1)):setInterval(function(){b.isFinished()?(b.stopTimer(),a.next()):b.next(a)},b.timing),this):!1},stopTimer:function(){return e&&(clearInterval(e),e=!1),this},prev:function(a){var c,d=this;return!d.hasInnerNavigation||d.isFinished()||0===d.innerComplete?(a.prev(),!1):(c=b.getElementById(d.id).querySelectorAll(".next.active"),!c||c.length<1?!1:(d.innerComplete>0?(d.innerComplete--,c[c.length-1].classList.remove("active")):a.prev(),this))},next:function(a){var c,d=this;return!d.hasInnerNavigation||d.isFinished()?(a.next(),!1):(d.isFinished()||(c=b.getElementById(d.id).querySelectorAll(".next:not(.active)"),c[0].classList.add("active"),d.innerComplete++),this)}},f._getData=function(a,b){return a.dataset?a.dataset[b]:a.getAttribute("data-"+b)},f.slideList=[],f.init=function(a,c){var e;a=a||".slide",c=c||"div.progress div",i=b.querySelectorAll(a),j=b.querySelector(c);for(var g=0;ga&&(a=0),a>=f.slideList.length&&(a=f.slideList.length-1),a},f._getSlideIdByEl=function(a){for(;"BODY"!==a.nodeName&&"HTML"!==a.nodeName;){if(a.classList.contains("slide"))return a.id;a=a.parentNode}return""},f._checkInteractiveElement=function(a){return"A"===a.target.nodeName},f.getSlideNumber=function(a){var b,c=f.slideList.length-1;for(""===a&&(b=0);c>=0;--c)if(a===f.slideList[c].id){b=c;break}return b},f.go=function(a,b){var c;if(!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");return f.slideList[a]?(g.hash=f.getSlideHash(a),f.updateProgress(a),f.updateActiveAndVisitedSlides(a),f.isSlideMode()&&(f.showPresenterNotes(a),c=f.slideList[a],c.timing&&c.initTimer(f)),"function"==typeof b&&b(),a):!1},f.next=function(a){var b=f.getCurrentSlideNumber(),c=f.slideList[b+1];return c?(f.go(b+1),"function"==typeof a&&a(),this):!1},f._turnNextSlide=function(a){var b=f.getCurrentSlideNumber(),c=f.slideList[b];f.isSlideMode()?(c.stopTimer(),c.next(f)):f.go(b+1),"function"==typeof a&&a()},f.prev=f.previous=function(a){var b=f.getCurrentSlideNumber();return 1>b?!1:(f.go(b-1),"function"==typeof a&&a(),!0)},f._turnPreviousSlide=function(a){var b=f.getCurrentSlideNumber(),c=f.slideList[b];return c.stopTimer(),f.isSlideMode()?c.prev(f):f.go(b-1),"function"==typeof a&&a(),!0},f.first=function(a){var b=f.slideList[f.getCurrentSlideNumber()];b&&b.timing&&b.stopTimer(),f.go(0),"function"==typeof a&&a()},f.last=function(a){var b=f.slideList[f.getCurrentSlideNumber()];b&&b.timing&&b.stopTimer(),f.go(f.slideList.length-1),"function"==typeof a&&a()},f.enterSlideMode=function(a){var b=f.getCurrentSlideNumber();return h.classList.remove("list"),h.classList.add("full"),f.isListMode()&&k&&history.pushState(null,null,g.pathname+"?full"+f.getSlideHash(b)),f._applyTransform(f._getTransform()),"function"==typeof a&&a(),!0},f.enterListMode=function(a){var b;return h.classList.remove("full"),h.classList.add("list"),f.clearPresenterNotes(),f.isListMode()?!1:(b=f.getCurrentSlideNumber(),f.slideList[b].stopTimer(),f.isSlideMode()&&k&&history.pushState(null,null,g.pathname+f.getSlideHash(b)),f.scrollToSlide(b),f._applyTransform("none"),"function"==typeof a&&a(),!0)},f.toggleMode=function(a){return f.isListMode()?f.enterSlideMode():f.enterListMode(),"function"==typeof a&&a(),!0},f.getCurrentSlideNumber=function(){var a=f.slideList.length-1,b=g.hash.substr(1);if(""===b)return-1;for(;a>=0;--a)if(b===f.slideList[a].id)return a;return 0},f.scrollToSlide=function(c){var d,e=!1;if(!f._isNumber(c))throw new Error("Gimme slide number as Number, baby!");if(f.isSlideMode())throw new Error("You can't scroll to because you in slide mode. Please, switch to list mode.");if(-1===c)return e;if(!f.slideList[c])throw new Error("There is no slide with number "+c);return d=b.getElementById(f.slideList[c].id),a.scrollTo(0,d.offsetTop),e=!0,e},f.isListMode=function(){return k?!/^full.*/.test(g.search.substr(1)):h.classList.contains("list")},f.isSlideMode=function(){return k?/^full.*/.test(g.search.substr(1)):h.classList.contains("full")},f.updateProgress=function(a){if(null===j)return!1;if(!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");return j.style.width=(100/(f.slideList.length-1)*f._normalizeSlideNumber(a)).toFixed(2)+"%",!0},f.updateActiveAndVisitedSlides=function(a){var c,d,e=f.slideList.length;if(a=f._normalizeSlideNumber(a),!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");for(c=0;e>c;++c)d=b.getElementById(f.slideList[c].id),a>c?(d.classList.remove("active"),d.classList.add("visited")):c>a?(d.classList.remove("visited"),d.classList.remove("active")):(d.classList.remove("visited"),d.classList.add("active"));return!0},f.clearPresenterNotes=function(){f.isSlideMode()&&a.console&&a.console.clear&&console.clear()},f.showPresenterNotes=function(c){if(f.clearPresenterNotes(),a.console){c=f._normalizeSlideNumber(c);var d=f.slideList[c].id,e=f.slideList[c+1]?f.slideList[c+1].id:null,g=b.getElementById(d).querySelector("footer");if(g&&g.innerHTML&&console.info(g.innerHTML.replace(/\n\s+/g,"\n")),e){var h=b.getElementById(e).querySelector("h2");h&&(h=h.innerHTML.replace(/^\s+|<[^>]+>/g,""),console.info("NEXT: "+h))}}},f.getSlideHash=function(a){if(!f._isNumber(a))throw new Error("Gimme slide number as Number, baby!");return a=f._normalizeSlideNumber(a),"#"+f.slideList[a].id},f.wheel=function(a){var d,e=b.querySelector("body"),g="locked"===e.getAttribute("data-scroll");g||f.isListMode()||(e.setAttribute("data-scroll","locked"),d=a.deltaY===c?a.wheelDeltaY<0:a.deltaY>0,d?f._turnNextSlide():f._turnPreviousSlide(),setTimeout(function(){e.setAttribute("data-scroll","unlocked")},200))},a.addEventListener("DOMContentLoaded",function(){var a=f.getCurrentSlideNumber(),b=h.classList.contains("full")||f.isSlideMode();-1===a&&b?f.go(0):(0===a||b)&&f.go(a),b&&f.enterSlideMode()},!1),a.addEventListener("popstate",function(){var a=f.getCurrentSlideNumber();-1!==a&&f.go(a),f.isListMode()?f.enterListMode():f.enterSlideMode()},!1),a.addEventListener("resize",function(){f.isSlideMode()&&f._applyTransform(f._getTransform())},!1),b.addEventListener("keydown",function(a){var b,c=f.getCurrentSlideNumber(),d=f.slideList[-1!==c?c:0];switch(a.which){case 80:f.isListMode()&&a.altKey&&a.metaKey&&(a.preventDefault(),b=d.number,f.go(b),f.enterSlideMode(),f.showPresenterNotes(b),d.timing&&d.initTimer(f));break;case 116:a.preventDefault(),f.isListMode()?(b=a.shiftKey?d.number:0,f.go(b),f.enterSlideMode(),f.showPresenterNotes(b),d.timing&&d.initTimer(f)):f.enterListMode();break;case 13:f.isListMode()&&-1!==c&&(a.preventDefault(),f.enterSlideMode(),f.showPresenterNotes(c),d.timing&&d.initTimer(f));break;case 27:f.isSlideMode()&&(a.preventDefault(),f.enterListMode());break;case 33:case 38:case 37:case 72:case 75:if(a.altKey||a.ctrlKey||a.metaKey)return;a.preventDefault(),f._turnPreviousSlide();break;case 34:case 40:case 39:case 76:case 74:if(a.altKey||a.ctrlKey||a.metaKey)return;a.preventDefault(),f._turnNextSlide();break;case 36:a.preventDefault(),f.first();break;case 35:a.preventDefault(),f.last();break;case 9:case 32:a.preventDefault(),f[a.shiftKey?"_turnPreviousSlide":"_turnNextSlide"]()}},!1),f.init(),b.addEventListener("click",function(a){var b,c,d=f._getSlideIdByEl(a.target);d&&f.isListMode()&&(b=f.getSlideNumber(d),f.go(b),f.enterSlideMode(),f.showPresenterNotes(b),c=f.slideList[b],c.timing&&c.initTimer(f))},!1),b.addEventListener("touchstart",function(b){var c,d,e,g=f._getSlideIdByEl(b.target);g&&(f.isSlideMode()&&!f._checkInteractiveElement(b)&&(e=b.touches[0].pageX,e>a.innerWidth/2?f._turnNextSlide():f._turnPreviousSlide()),f.isListMode()&&(c=f.getSlideNumber(g),f.go(c),f.enterSlideMode(),f.showPresenterNotes(c),d=f.slideList[c],d.timing&&d.initTimer(f)))},!1),b.addEventListener("touchmove",function(a){f.isSlideMode()&&a.preventDefault()},!1),b.addEventListener("wheel",f.wheel,!1),b.addEventListener("mousewheel",f.wheel,!1),f}(this,this.document); \ No newline at end of file diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..19d615a --- /dev/null +++ b/tests/index.html @@ -0,0 +1,34 @@ + + + + Test page for Shower + + + + + + +
+

1

+
+
+

2

+
+
+

3

+
+
+

4

+
+
+

5

+ + + +
+
+

6

+
+ + + \ No newline at end of file diff --git a/tests/inner-nav.js b/tests/inner-nav.js deleted file mode 100644 index 5b077d4..0000000 --- a/tests/inner-nav.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - // Right - 'Right Arrow key is switching .next to .active': function (test) { - test - .open('themes/ribbon/index.html?full#20') - .sendKeys('body', '\uE014') // Right - .assert.attr('[id="20"] li:nth-child(2)', 'class', 'next active', 'First .next is .active') - .done(); - } -}; \ No newline at end of file diff --git a/tests/navigation.js b/tests/navigation.js new file mode 100644 index 0000000..31eb387 --- /dev/null +++ b/tests/navigation.js @@ -0,0 +1,48 @@ +module.exports = { + 'Right Arrow key is switching first Next item to Active': function (test) { + test + .open('http://localhost:7497/tests/?full#5') + .sendKeys('body', '\uE014') // Right + .assert.attr('[id="5"] .next:first-of-type', 'class').to.contain('active', 'First Next item is Active') + .done(); + }, + 'Left Arrow key is switching Active items back to Next': function (test) { + test + .open('http://localhost:7497/tests/?full#5') + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE012') // Left + .sendKeys('body', '\uE012') // Left + .assert.numberOfElements('[id="5"] .next.active', 0, 'There are no Active items') + .done(); + }, + 'Right Arrow key is switching to next slide once all Next items becomes Active': function (test) { + test + .open('http://localhost:7497/tests/?full#5') + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE014') // Right + .assert.attr('[id="6"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + 'Left Arrow key is switching to previous slide when all Next items becomes Active': function (test) { + test + .open('http://localhost:7497/tests/?full#5') + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE014') // Right + .sendKeys('body', '\uE012') // Left + // Not sure why it’s failing. It works fine manually + .assert.attr('[id="4"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + 'Reload reset navigation': function (test) { + test + .open('http://localhost:7497/tests/?full#5') + .sendKeys('body', '\uE014') // Right + .reload() + .assert.numberOfElements('[id="5"] .next.active', 0, 'There are no Active items') + .done(); + } +}; \ No newline at end of file diff --git a/tests/shortcuts.js b/tests/shortcuts.js index d614533..dac0c16 100644 --- a/tests/shortcuts.js +++ b/tests/shortcuts.js @@ -1,75 +1,250 @@ module.exports = { - 'Body class is switching from `list` to `full` on F5': function (test) { - test - .open('themes/ribbon/index.html') - .sendKeys('body', '\uE035') // F5 - .assert.attr('body', 'class', 'full', 'Mode is full') - .done(); - }, + // -------------------------------- // F5 - 'Body class is switching from `full` to `list` on F5': function (test) { + // -------------------------------- + 'F5 is switching from List to Full': function (test) { test - .open('themes/ribbon/index.html?full') + .open('http://localhost:7497/tests/') .sendKeys('body', '\uE035') // F5 - .assert.attr('body', 'class', 'list', 'Mode is list') + .assert.attr('body', 'class', 'full', 'Mode is Full') .done(); }, - // Cmd Alt P — how to test multiple keys? - // 'Body class is switching from `list` to `full` on Cmd Alt P': function (test) { - // test - // .open('themes/ribbon/index.html') - // .sendKeys('body', '\uE03D\uE00A\u0050') // Cmd Alt P - // .assert.attr('body', 'class', 'full') - // .done(); - // }, + 'F5 is switching from Full to List': function (test) { + test + .open('http://localhost:7497/tests/?full') + .sendKeys('body', '\uE035') // F5 + .assert.attr('body', 'class', 'list', 'Mode is List') + .done(); + }, + // -------------------------------- + // Cmd Alt P + // -------------------------------- + 'Cmd Alt P keys are switching from List to Full': function (test) { + test + .open('http://localhost:7497/tests/') + .sendKeys('body', '\uE03D\uE00A\u0070') // Cmd Alt P + .assert.attr('body', 'class', 'full', 'Mode is Full') + .done(); + }, + 'Cmd Alt P keys are not switching from Full to List': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\uE03D\uE00A\u0070') // Cmd Alt P + .assert.attr('body', 'class', 'full', 'Mode is Full') + .done(); + }, + // -------------------------------- // Esc - 'Body class is switching from `full` to `list` on Esc': function (test) { + // -------------------------------- + 'Esc is switching from Full to List': function (test) { test - .open('themes/ribbon/index.html?full') + .open('http://localhost:7497/tests/?full#1') .sendKeys('body', '\uE00C') // Esc - .assert.attr('body', 'class', 'list', 'Mode is list') + .assert.attr('body', 'class').to.contain('list', 'Mode is List') .done(); }, - // End - 'End key select the last slide': function (test) { + // -------------------------------- + // Left + // -------------------------------- + 'Left Arrow key is switching to the previous slide': function (test) { test - .open('themes/ribbon/index.html') - .sendKeys('body', '\uE010') // End - .assert.attr('.slide:last-of-type', 'class', 'slide active', 'Last slide is active') + .open('http://localhost:7497/tests/?full#2') + .sendKeys('body', '\uE012') // Left + .assert.attr('[id="1"]', 'class').to.contain('active', 'Previous slide is Active') .done(); }, + // -------------------------------- + // Right + // -------------------------------- + 'Right Arrow key is switching to the next slide': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\uE014') // Right + .assert.attr('[id="2"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + // -------------------------------- + // Up + // -------------------------------- + 'Up Arrow key is switching to the previous slide': function (test) { + test + .open('http://localhost:7497/tests/?full#2') + .sendKeys('body', '\uE013') // Up + .assert.attr('[id="1"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + // -------------------------------- + // Down + // -------------------------------- + 'Down Arrow key is switching to the next slide': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\uE015') // Down + .assert.attr('[id="2"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + // -------------------------------- + // H + // -------------------------------- + 'H key is switching to the previous slide': function (test) { + test + .open('http://localhost:7497/tests/?full#2') + .sendKeys('body', '\u0068') // H + .assert.attr('[id="1"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + // -------------------------------- + // K + // -------------------------------- + 'K key is switching to the previous slide': function (test) { + test + .open('http://localhost:7497/tests/?full#2') + .sendKeys('body', '\u006B') // K + .assert.attr('[id="1"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + // -------------------------------- + // J + // -------------------------------- + 'J key is switching to the next slide': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\u006A') // J + .assert.attr('[id="2"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + // -------------------------------- + // L + // -------------------------------- + 'L key is switching to the next slide': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\u006C') // L + .assert.attr('[id="2"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + // -------------------------------- + // Space + // -------------------------------- + 'Space key is switching to the next slide': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\uE00D') // Space + .assert.attr('[id="2"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + 'Shift Space keys are switching to the previous slide': function (test) { + test + .open('http://localhost:7497/tests/?full#2') + .sendKeys('body', '\uE008\uE00D') // Shift Space + .assert.attr('[id="1"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + // -------------------------------- + // Tab + // -------------------------------- + 'Tab key is switching to the next slide': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\uE004') // Tab + // Not sure why it’s failing. It works fine manually + .assert.attr('[id="2"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + 'Shift Tab keys are switching to the previous slide': function (test) { + test + .open('http://localhost:7497/tests/?full#2') + .sendKeys('body', '\uE008\uE004') // Shift Tab + // Not sure why it’s failing. It works fine manually + .assert.attr('[id="1"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + // -------------------------------- + // PageUp + // -------------------------------- + 'PageUp key is switching to the previous slide': function (test) { + test + .open('http://localhost:7497/tests/?full#2') + .sendKeys('body', '\uE00E') // PageUp + .assert.attr('[id="1"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + // -------------------------------- + // PageDown + // -------------------------------- + 'PageDown key is switching to the next slide': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\uE00F') // PageDown + .assert.attr('[id="2"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + // -------------------------------- // Home - 'Home key select the first slide': function (test) { + // -------------------------------- + 'Home key select the first slide in List mode': function (test) { test - .open('themes/ribbon/index.html#20') + .open('http://localhost:7497/tests/') .sendKeys('body', '\uE011') // Home - .assert.attr('.slide:first-of-type', 'class', 'slide active', 'First slide is active') + // Failing unlike next one with current slide + .assert.attr('[id="1"]', 'class').to.contain('active', 'First slide is active') .done(); }, + 'Home key select the first slide in List mode (with current)': function (test) { + test + .open('http://localhost:7497/tests/#5') + .sendKeys('body', '\uE011') // Home + .assert.attr('[id="1"]', 'class').to.contain('active', 'First slide is active') + .done(); + }, + 'Home key select the first slide in Full mode': function (test) { + test + .open('http://localhost:7497/tests/?full#5') + .sendKeys('body', '\uE011') // Home + .assert.attr('[id="1"]', 'class').to.contain('active', 'First slide is active') + .done(); + }, + // -------------------------------- + // End + // -------------------------------- + 'End key select the last slide in List mode': function (test) { + test + .open('http://localhost:7497/tests/') + .sendKeys('body', '\uE010') // End + // Failing unlike next one with current slide + .assert.attr('[id="6"]', 'class').to.contain('active', 'Last slide is active') + .done(); + }, + 'End key select the last slide in List mode (with current)': function (test) { + test + .open('http://localhost:7497/tests/#1') + .sendKeys('body', '\uE010') // End + .assert.attr('[id="6"]', 'class').to.contain('active', 'Last slide is active') + .done(); + }, + 'End key select the last slide in Full mode': function (test) { + test + .open('http://localhost:7497/tests/?full#1') + .sendKeys('body', '\uE010') // End + .assert.attr('[id="6"]', 'class').to.contain('active', 'Last slide is active') + .done(); + }, + // -------------------------------- // Enter + // -------------------------------- 'Enter is opening current slide': function (test) { test - .open('themes/ribbon/index.html#1') + .open('http://localhost:7497/tests/#1') .sendKeys('body', '\uE007') // Enter .assert.attr('body', 'class', 'full', 'Full mode') - .assert.attr('[id="1"]', 'class', 'slide active', 'Slide #1 is active') + .assert.attr('[id="1"]', 'class').to.contain('active', 'First slide is active') .done(); }, - // Enter 'Enter is not opening any slide if there’s no current': function (test) { test - .open('themes/ribbon/index.html') + .open('http://localhost:7497/tests/') .sendKeys('body', '\uE007') // Enter - .assert.attr('body', 'class', 'list', 'Mode is list') + .assert.attr('body', 'class', 'list', 'Mode is List') .done(); } - // uE004 Tab - // uE008 Shift - // uE00D Space - // uE00E PageUp - // uE00F PageDown - // uE012 Left - // uE013 Up - // uE014 Right - // uE015 Down }; \ No newline at end of file diff --git a/tests/timer.js b/tests/timer.js new file mode 100644 index 0000000..a6412ab --- /dev/null +++ b/tests/timer.js @@ -0,0 +1,31 @@ +module.exports = { + 'Timer is switching to the next slide when finished': function (test) { + test + .open('http://localhost:7497/tests/?full#3') + .wait(5000) + .assert.attr('[id="4"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + 'Timer becomes Active and switching to the next slide when finished': function (test) { + test + .open('http://localhost:7497/tests/?full#4') + .sendKeys('body', '\uE012') // Left + .wait(5000) + .assert.attr('[id="4"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + }, + 'Left Arrow key is skipping timer while it’s not finished': function (test) { + test + .open('http://localhost:7497/tests/?full#3') + .sendKeys('body', '\uE012') // Left + .assert.attr('[id="2"]', 'class').to.contain('active', 'Previous slide is Active') + .done(); + }, + 'Right Arrow key is skipping timer while it’s not finished': function (test) { + test + .open('http://localhost:7497/tests/?full#3') + .sendKeys('body', '\uE014') // Right + .assert.attr('[id="4"]', 'class').to.contain('active', 'Next slide is Active') + .done(); + } +}; \ No newline at end of file