From c4edbb3ee97e1da6eeea14c73dfa4a1672a8516d Mon Sep 17 00:00:00 2001 From: miripiruni Date: Fri, 18 Jan 2013 21:01:10 +0400 Subject: [PATCH 1/3] 1.Added methods: shower.isSlideMode() & shower.toggleMode(); 2. All with hash and body.classList are incapsulated into shower.enterSlideMode() and shower.enterListMode() (no more copypaste code in eventListener). --- shower.js | 143 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 73 insertions(+), 70 deletions(-) diff --git a/shower.js b/shower.js index f96f217..a3d3f01 100755 --- a/shower.js +++ b/shower.js @@ -135,27 +135,32 @@ window.shower = (function(window, document, undefined) { e.preventDefault(); window.open(e.target.getAttribute('href')); - return; + return false; } - var slideId = shower._getContainingSlideId(e.target); + var slideId = shower._getContainingSlideId(e.target), + i = slideList.length - 1, + slideNumber; - if ('' !== slideId && shower.isListMode()) { - e.preventDefault(); + if (slideId === '') { + return false; + } - // NOTE: we should update hash to get things work properly - url.hash = '#' + slideId; - if (isHistoryApiSupported) { - history.replaceState(null, null, url.pathname + '?full#' + slideId); + for (; i >= 0; --i) { + if (slideId === slideList[i].id) { + slideNumber = i; + break; } - shower.enterSlideMode(); - - shower.updateProgress(shower.getCurrentSlideNumber()); - shower.updateCurrentAndPassedSlides(shower.getCurrentSlideNumber()); - shower.runSlideshowIfPresented(shower.getCurrentSlideNumber()); } - return; + shower.go(slideNumber); + + if (shower.isListMode()) { + e.preventDefault(); + shower.enterSlideMode(); + } + + return true; }; /** @@ -246,9 +251,17 @@ window.shower = (function(window, document, undefined) { * @returns {Number|Boolean} */ shower.enterSlideMode = function(callback) { - // check if it's already in slide mode... - if (body.classList.contains('full')) { - return false; + var currentSlideNumber = shower.getCurrentSlideNumber(); + + if (currentSlideNumber === -1) { + currentSlideNumber = 0; + } + + shower.go(currentSlideNumber); + shower.showPresenterNotes(currentSlideNumber); + + if (shower.isListMode() && isHistoryApiSupported) { + history.pushState(null, null, url.pathname + '?full' + shower.getSlideHash(currentSlideNumber)); } body.classList.remove('list'); @@ -258,7 +271,9 @@ window.shower = (function(window, document, undefined) { console.clear(); } - shower.showPresenterNotes(shower.getCurrentSlideNumber()); + shower.updateProgress(currentSlideNumber); + shower.updateCurrentAndPassedSlides(currentSlideNumber); + shower.runSlideshowIfPresented(currentSlideNumber); if (typeof(callback) === "function") { callback(); @@ -273,14 +288,17 @@ window.shower = (function(window, document, undefined) { * @returns {Number} */ shower.enterListMode = function(callback) { - // check if it's already in list mode... - if (body.classList.contains('list')) { - return false; - } + var currentSlideNumber = shower.getCurrentSlideNumber(); body.classList.remove('full'); body.classList.add('list'); + if (shower.isSlideMode() && isHistoryApiSupported) { + history.pushState(null, null, url.pathname + shower.getSlideHash(currentSlideNumber)); + } + + shower.scrollToSlide(currentSlideNumber); + if (typeof(callback) === "function") { callback(); } @@ -288,7 +306,23 @@ window.shower = (function(window, document, undefined) { return shower._applyTransform('none'); }; - // @TODO: add method shower.toggleMode() + /** + * Toggle Mode: Slide and List + * @param {Function} callback + */ + shower.toggleMode = function(callback) { + if (shower.isListMode()) { + shower.enterSlideMode(); + } else { + shower.enterListMode(); + } + + if (typeof(callback) === "function") { + callback(); + } + + return true; + }; /** * Get current slide number. Starts from zero. Warning: when in url you have @@ -324,7 +358,7 @@ window.shower = (function(window, document, undefined) { throw new Error('Gimme slide number as Number, baby!'); } - if ( ! shower.isListMode()) { + if (shower.isSlideMode()) { throw new Error('You can\'t scroll to because you in slide mode. Please, switch to list mode.'); } @@ -345,13 +379,21 @@ window.shower = (function(window, document, undefined) { }; /** - * Chech if it's list mode. + * Check if it's List mode. * @returns {Boolean} */ shower.isListMode = function() { return isHistoryApiSupported ? ! /^full.*/.test(url.search.substr(1)) : body.classList.contains('list'); }; + /** + * Check if it's Slide mode. + * @returns {Boolean} + */ + shower.isSlideMode = function() { + return isHistoryApiSupported ? /^full.*/.test(url.search.substr(1)) : body.classList.contains('full'); + }; + /** * Update progress bar. * @param {Number} slideNumber slide number (sic!) @@ -459,7 +501,7 @@ window.shower = (function(window, document, undefined) { url.hash = shower.getSlideHash(slideNumber); - if ( ! shower.isListMode()) { + if (shower.isSlideMode()) { shower.updateProgress(slideNumber); shower.updateCurrentAndPassedSlides(slideNumber); shower.showPresenterNotes(slideNumber); @@ -534,32 +576,21 @@ window.shower = (function(window, document, undefined) { // Event handlers window.addEventListener('DOMContentLoaded', function() { - if ( ! shower.isListMode()) { - // "?full" is present without slide hash, so we should display first slide - if (-1 === shower.getCurrentSlideNumber()) { - if (isHistoryApiSupported) { - history.replaceState(null, null, url.pathname + '?full' + shower.getSlideHash(0)); - } - } - + if (shower.isSlideMode()) { shower.enterSlideMode(); - shower.updateProgress(shower.getCurrentSlideNumber()); - shower.updateCurrentAndPassedSlides(shower.getCurrentSlideNumber()); - shower.runSlideshowIfPresented(shower.getCurrentSlideNumber()); } }, false); window.addEventListener('popstate', function(e) { if (shower.isListMode()) { shower.enterListMode(); - shower.scrollToSlide(shower.getCurrentSlideNumber()); } else { shower.enterSlideMode(); } }, false); window.addEventListener('resize', function(e) { - if ( ! shower.isListMode()) { + if (shower.isSlideMode()) { shower._applyTransform(shower._getTransform()); } }, false); @@ -579,48 +610,23 @@ window.shower = (function(window, document, undefined) { var slideNumber = e.shiftKey ? currentSlideNumber : 0; shower.go(slideNumber); - - if (isHistoryApiSupported) { - history.pushState(null, null, url.pathname + '?full' + shower.getSlideHash(slideNumber)); - } shower.enterSlideMode(); - - shower.updateProgress(slideNumber); - shower.updateCurrentAndPassedSlides(slideNumber); - shower.runSlideshowIfPresented(slideNumber); } else { - if (isHistoryApiSupported) { - history.pushState(null, null, url.pathname + shower.getSlideHash(currentSlideNumber)); - } shower.enterListMode(); - shower.scrollToSlide(currentSlideNumber); } break; case 13: // Enter if (shower.isListMode() && -1 !== currentSlideNumber) { e.preventDefault(); - - if (isHistoryApiSupported) { - history.pushState(null, null, url.pathname + '?full' + shower.getSlideHash(currentSlideNumber)); - } shower.enterSlideMode(); - - shower.updateProgress(currentSlideNumber); - shower.updateCurrentAndPassedSlides(currentSlideNumber); - shower.runSlideshowIfPresented(currentSlideNumber); } break; case 27: // Esc - if ( ! shower.isListMode()) { + if (shower.isSlideMode()) { e.preventDefault(); - - if (isHistoryApiSupported) { - history.pushState(null, null, url.pathname + shower.getSlideHash(currentSlideNumber)); - } shower.enterListMode(); - shower.scrollToSlide(currentSlideNumber); } break; @@ -640,7 +646,7 @@ window.shower = (function(window, document, undefined) { case 74: // j e.preventDefault(); - if ( ! shower.isListMode()) { + if (shower.isSlideMode()) { // Inner navigation is "completed" if current slide have // no inner navigation or inner navigation is fully shown innerNavigationCompleted = !slideList[currentSlideNumber].hasInnerNavigation || @@ -657,7 +663,7 @@ window.shower = (function(window, document, undefined) { currentSlideNumber++; shower.go(currentSlideNumber); // We must run slideshow only in full mode - if ( ! shower.isListMode()) { + if (shower.isSlideMode()) { shower.runSlideshowIfPresented(currentSlideNumber); } } @@ -665,20 +671,17 @@ window.shower = (function(window, document, undefined) { case 36: // Home e.preventDefault(); - shower.first(); break; case 35: // End e.preventDefault(); - shower.last(); break; case 9: // Tab = +1; Shift + Tab = -1 case 32: // Space = +1; Shift + Space = -1 e.preventDefault(); - shower[e.shiftKey ? 'previous' : 'next'](); break; From ce373040064192aa8c1d9ecbe0cc89c8e3eb7532 Mon Sep 17 00:00:00 2001 From: miripiruni Date: Sun, 20 Jan 2013 00:47:54 +0400 Subject: [PATCH 2/3] Fixed problems with touch devices; Small refactoring. --- shower.js | 85 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/shower.js b/shower.js index a3d3f01..9d6270c 100755 --- a/shower.js +++ b/shower.js @@ -104,12 +104,12 @@ window.shower = (function(window, document, undefined) { }; /** - * Get containing slide id. + * Get slide id from HTML element. * @private * @param {domElem} el * @returns {String} */ - shower._getContainingSlideId = function(el) { + shower._getSlideIdByEl = function(el) { while ('BODY' !== el.nodeName && 'HTML' !== el.nodeName) { if (el.classList.contains('slide')) { return el.id; @@ -122,28 +122,33 @@ window.shower = (function(window, document, undefined) { }; /** - * Dispatch single slide mode. - * @TODO: Renaming needed? Or just some handlers rewriting? + * For touch devices: check if click on links... + * + * @TODO: add support for textareas/inputs/... + * * @private * @param {domElem} e - * @returns {Undefined} + * @returns {Boolean} */ - shower._dispatchSingleSlideMode = function(e) { - // Process links - // @TODO: presentation links support + shower._checkInteractiveElement = function(e) { if ('A' === e.target.nodeName) { - e.preventDefault(); - - window.open(e.target.getAttribute('href')); + return true; + } else { return false; } + }; - var slideId = shower._getContainingSlideId(e.target), - i = slideList.length - 1, + /** + * Get slide number by slideId + * @param {Number} slideId (HTML id or position in slideList) + * @returns {Number} + */ + shower.getSlideNumber = function(slideId) { + var i = slideList.length - 1, slideNumber; if (slideId === '') { - return false; + slideNumber = 0; } for (; i >= 0; --i) { @@ -153,16 +158,10 @@ window.shower = (function(window, document, undefined) { } } - shower.go(slideNumber); - - if (shower.isListMode()) { - e.preventDefault(); - shower.enterSlideMode(); - } - - return true; + return slideNumber; }; + /** * Show next slide. If slide is last returns false, otherwise return slide * number which been shown. @@ -690,25 +689,37 @@ window.shower = (function(window, document, undefined) { } }, false); - document.addEventListener('click', shower._dispatchSingleSlideMode, false); - document.addEventListener('touchend', shower._dispatchSingleSlideMode, false); - - document.addEventListener('touchstart', function(e) { - if ( ! shower.isListMode()) { - var currentSlideNumber = shower.getCurrentSlideNumber(), - x = e.touches[0].pageX; - if (x > window.innerWidth / 2) { - currentSlideNumber++; - } else { - currentSlideNumber--; - } - - shower.go(currentSlideNumber); + document.addEventListener('click', function(e) { + if (shower.isListMode() && shower._getSlideIdByEl(e.target)) { + e.preventDefault(); + shower.go(shower.getSlideNumber(shower._getSlideIdByEl(e.target))); + shower.enterSlideMode(); } }, false); + document.addEventListener('touchstart', function(e) { + if (shower._getSlideIdByEl(e.target)) { + if (shower.isSlideMode() && ! shower._checkInteractiveElement(e)) { + var x = e.touches[0].pageX; + + if (x > window.innerWidth / 2) { + shower.next(); + } else { + shower.previous(); + } + } + + if (shower.isListMode()) { + shower.go(shower.getSlideNumber(shower._getSlideIdByEl(e.target))); + shower.enterSlideMode(); + } + } + + + }, false); + document.addEventListener('touchmove', function(e) { - if ( ! shower.isListMode()) { + if (shower.isSlideMode()) { e.preventDefault(); } }, false); From f36d547070c3655975405a19a88bd3abb27d6ae7 Mon Sep 17 00:00:00 2001 From: miripiruni Date: Sun, 20 Jan 2013 01:13:21 +0400 Subject: [PATCH 3/3] JSDoc; JS code style --- shower.js | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/shower.js b/shower.js index 9d6270c..7589533 100755 --- a/shower.js +++ b/shower.js @@ -1,7 +1,8 @@ -// Shower HTML presentation engine: github.com/shower/shower -// Copyright © 2010–2013 Vadim Makeev, pepelsbey.net -// Licensed under MIT license: github.com/shower/shower/wiki/MIT-License - +/** + * Shower HTML presentation engine: github.com/shower/shower + * @copyright 2010–2013 Vadim Makeev, pepelsbey.net + * @license MIT license: github.com/shower/shower/wiki/MIT-License + */ window.shower = (function(window, document, undefined) { var shower = {}, url = window.location, @@ -25,7 +26,7 @@ window.shower = (function(window, document, undefined) { }; for (i = 0; i < l; i++) { - // Slide ID's are optional. In case of missing ID we set it to the + // Slide IDs are optional. In case of missing ID we set it to the // slide number if ( ! slides[i].id) { slides[i].id = i + 1; @@ -148,9 +149,11 @@ window.shower = (function(window, document, undefined) { slideNumber; if (slideId === '') { - slideNumber = 0; + slideNumber = 0; } + // As fast as you can ;-) + // http://jsperf.com/for-vs-foreach/46 for (; i >= 0; --i) { if (slideId === slideList[i].id) { slideNumber = i; @@ -184,7 +187,7 @@ window.shower = (function(window, document, undefined) { // slides starts from 0 ret = currentSlideNumber + 2; - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } } else { @@ -209,7 +212,7 @@ window.shower = (function(window, document, undefined) { ret = currentSlideNumber; shower.go(currentSlideNumber - 1); - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } } else { @@ -225,7 +228,7 @@ window.shower = (function(window, document, undefined) { * @returns {Number} */ shower.first = function(callback) { - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } @@ -238,7 +241,7 @@ window.shower = (function(window, document, undefined) { * @returns {Number} */ shower.last = function(callback) { - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } return shower.go(slideList.length - 1); @@ -274,7 +277,7 @@ window.shower = (function(window, document, undefined) { shower.updateCurrentAndPassedSlides(currentSlideNumber); shower.runSlideshowIfPresented(currentSlideNumber); - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } @@ -298,7 +301,7 @@ window.shower = (function(window, document, undefined) { shower.scrollToSlide(currentSlideNumber); - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } @@ -316,7 +319,7 @@ window.shower = (function(window, document, undefined) { shower.enterListMode(); } - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } @@ -455,15 +458,17 @@ window.shower = (function(window, document, undefined) { if (window.console) { slideNumber = shower._normalizeSlideNumber(slideNumber); - var slideId = slideList[slideNumber].id; - var nextSlideId = slideList[slideNumber + 1] ? slideList[slideNumber + 1].id : null; + var slideId = slideList[slideNumber].id, + nextSlideId = slideList[slideNumber + 1] ? slideList[slideNumber + 1].id : null, + notes = document.getElementById(slideId).querySelector('footer'); - var notes = document.getElementById(slideId).querySelector('footer'); if (notes) { console.info(notes.innerHTML.replace(/\n\s+/g,'\n')); } + if (nextSlideId) { var next = document.getElementById(nextSlideId).querySelector('h2'); + if (next) { next = next.innerHTML.replace(/^\s+|<[^>]+>/g,''); console.info('NEXT: ' + next); @@ -505,7 +510,7 @@ window.shower = (function(window, document, undefined) { shower.updateCurrentAndPassedSlides(slideNumber); shower.showPresenterNotes(slideNumber); - if (typeof(callback) === "function") { + if (typeof(callback) === 'function') { callback(); } }