diff --git a/.DS_Store b/.DS_Store index 69cce95..cf0263d 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/samples/03 - slidingView/03 - swipeview/.DS_Store b/samples/03 - slidingView/03 - swipeview/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/samples/03 - slidingView/03 - swipeview/.DS_Store differ diff --git a/samples/03 - slidingView/03 - swipeview/index.html b/samples/03 - slidingView/03 - swipeview/index.html new file mode 100644 index 0000000..4c4ff7b --- /dev/null +++ b/samples/03 - slidingView/03 - swipeview/index.html @@ -0,0 +1,206 @@ + + + + Sliding View Sample + + + + + + + + + + + + + + + + + + +
+ +
+

Three Laws of Robotics

+
+ +

The Three Laws of Robotics (often shortened to The Three Laws or Three Laws) are a set of rules devised by the science fiction author Isaac Asimov and later added to. The rules are introduced in his 1942 short story "Runaround", although they were foreshadowed in a few earlier stories.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ + +
+
+ + + \ No newline at end of file diff --git a/samples/03 - slidingView/03 - swipeview/style.css b/samples/03 - slidingView/03 - swipeview/style.css new file mode 100755 index 0000000..830a1b2 --- /dev/null +++ b/samples/03 - slidingView/03 - swipeview/style.css @@ -0,0 +1,90 @@ +html, body { height:100%; } +body { + padding:0; + margin:0; + background:#fff; + -webkit-user-select:none; + -webkit-text-size-adjust:none; + color:#333; + font-family:helvetica; + font-size:12px; + text-align:center; +} + +h1 { + font-size:2em; + padding:20px 0; + margin:0; +} + +#wrapper { + width:100%; + min-width:320px; + height:150px; + background:#ddd; + border-top:1px solid #aaa; + border-bottom:1px solid #aaa; +} + +#nav { + position:absolute; + z-index:100; + top:8px; + width:200px; + height:20px; + left:50%; + background:rgba(0,0,0,0.75); + padding:0; + margin:0 0 0 -100px; + -webkit-border-radius:10px; +} + +#nav li { + display:block; + float:left; + width:14px; + height:14px; line-height:14px; + -webkit-border-radius:7px; + background:rgba(255,255,255,0.1); + overflow:hidden; + padding:0; + margin:3px 11px 0 0; + text-align:center; +} + +#nav li#prev { + margin-left:5px; + background:transparent; +} + +#nav li#next { + margin-right:0; + background:transparent; +} + +#nav li.selected { + background:rgba(255,255,255,0.4); +} + +#swipeview-slider > div { + position:relative; + display:-webkit-box; + -webkit-box-orient:vertical; + -webkit-box-pack:center; + -webkit-box-align:center; + overflow:hidden; +} + +#swipeview-slider span { + -webkit-box-sizing:border-box; + display:block; + text-align:center; + font-size:1.4em; + padding:0 20px; +} + +p { + padding:20px; + margin:0; + font-size:1.4em; +} diff --git a/samples/03 - slidingView/03 - swipeview/swipeview.js b/samples/03 - slidingView/03 - swipeview/swipeview.js new file mode 100755 index 0000000..15f304e --- /dev/null +++ b/samples/03 - slidingView/03 - swipeview/swipeview.js @@ -0,0 +1,474 @@ +/*! + * SwipeView v1.0 ~ Copyright (c) 2012 Matteo Spinelli, http://cubiq.org + * Released under MIT license, http://cubiq.org/license + */ +var SwipeView = (function (window, document) { + var dummyStyle = document.createElement('div').style, + vendor = (function () { + var vendors = 't,webkitT,MozT,msT,OT'.split(','), + t, + i = 0, + l = vendors.length; + + for ( ; i < l; i++ ) { + t = vendors[i] + 'ransform'; + if ( t in dummyStyle ) { + return vendors[i].substr(0, vendors[i].length - 1); + } + } + + return false; + })(), + cssVendor = vendor ? '-' + vendor.toLowerCase() + '-' : '', + + // Style properties + transform = prefixStyle('transform'), + transitionDuration = prefixStyle('transitionDuration'), + + // Browser capabilities + has3d = prefixStyle('perspective') in dummyStyle, + hasTouch = 'ontouchstart' in window, + hasTransform = !!vendor, + hasTransitionEnd = prefixStyle('transition') in dummyStyle, + + // Helpers + translateZ = has3d ? ' translateZ(0)' : '', + + // Events + resizeEvent = 'onorientationchange' in window ? 'orientationchange' : 'resize', + startEvent = hasTouch ? 'touchstart' : 'mousedown', + moveEvent = hasTouch ? 'touchmove' : 'mousemove', + endEvent = hasTouch ? 'touchend' : 'mouseup', + cancelEvent = hasTouch ? 'touchcancel' : 'mouseup', + transitionEndEvent = (function () { + if ( vendor === false ) return false; + + var transitionEnd = { + '' : 'transitionend', + 'webkit' : 'webkitTransitionEnd', + 'Moz' : 'transitionend', + 'O' : 'oTransitionEnd', + 'ms' : 'MSTransitionEnd' + }; + + return transitionEnd[vendor]; + })(), + + SwipeView = function (el, options) { + var i, + div, + className, + pageIndex; + + this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; + this.options = { + text: null, + numberOfPages: 3, + snapThreshold: null, + hastyPageFlip: false, + loop: true + }; + + // User defined options + for (i in options) this.options[i] = options[i]; + + this.wrapper.style.overflow = 'hidden'; + this.wrapper.style.position = 'relative'; + + this.masterPages = []; + + div = document.createElement('div'); + div.id = 'swipeview-slider'; + div.style.cssText = 'position:relative;top:0;height:100%;width:100%;' + cssVendor + 'transition-duration:0;' + cssVendor + 'transform:translateZ(0);' + cssVendor + 'transition-timing-function:ease-out'; + this.wrapper.appendChild(div); + this.slider = div; + + this.refreshSize(); + + for (i=-1; i<2; i++) { + div = document.createElement('div'); + div.id = 'swipeview-masterpage-' + (i+1); + div.style.cssText = cssVendor + 'transform:translateZ(0);position:absolute;top:0;height:100%;width:100%;left:' + i*100 + '%'; + if (!div.dataset) div.dataset = {}; + pageIndex = i == -1 ? this.options.numberOfPages - 1 : i; + div.dataset.pageIndex = pageIndex; + div.dataset.upcomingPageIndex = pageIndex; + + if (!this.options.loop && i == -1) div.style.visibility = 'hidden'; + + this.slider.appendChild(div); + this.masterPages.push(div); + } + + className = this.masterPages[1].className; + this.masterPages[1].className = !className ? 'swipeview-active' : className + ' swipeview-active'; + + window.addEventListener(resizeEvent, this, false); + this.wrapper.addEventListener(startEvent, this, false); + this.wrapper.addEventListener(moveEvent, this, false); + this.wrapper.addEventListener(endEvent, this, false); + this.slider.addEventListener(transitionEndEvent, this, false); + // in Opera >= 12 the transitionend event is lowercase so we register both events + if ( vendor == 'O' ) this.slider.addEventListener(transitionEndEvent.toLowerCase(), this, false); + +/* if (!hasTouch) { + this.wrapper.addEventListener('mouseout', this, false); + }*/ + }; + + SwipeView.prototype = { + currentMasterPage: 1, + x: 0, + page: 0, + pageIndex: 0, + customEvents: [], + + onFlip: function (fn) { + this.wrapper.addEventListener('swipeview-flip', fn, false); + this.customEvents.push(['flip', fn]); + }, + + onMoveOut: function (fn) { + this.wrapper.addEventListener('swipeview-moveout', fn, false); + this.customEvents.push(['moveout', fn]); + }, + + onMoveIn: function (fn) { + this.wrapper.addEventListener('swipeview-movein', fn, false); + this.customEvents.push(['movein', fn]); + }, + + onTouchStart: function (fn) { + this.wrapper.addEventListener('swipeview-touchstart', fn, false); + this.customEvents.push(['touchstart', fn]); + }, + + destroy: function () { + while ( this.customEvents.length ) { + this.wrapper.removeEventListener('swipeview-' + this.customEvents[0][0], this.customEvents[0][1], false); + this.customEvents.shift(); + } + + // Remove the event listeners + window.removeEventListener(resizeEvent, this, false); + this.wrapper.removeEventListener(startEvent, this, false); + this.wrapper.removeEventListener(moveEvent, this, false); + this.wrapper.removeEventListener(endEvent, this, false); + this.slider.removeEventListener(transitionEndEvent, this, false); + +/* if (!hasTouch) { + this.wrapper.removeEventListener('mouseout', this, false); + }*/ + }, + + refreshSize: function () { + this.wrapperWidth = this.wrapper.clientWidth; + this.wrapperHeight = this.wrapper.clientHeight; + this.pageWidth = this.wrapperWidth; + this.maxX = -this.options.numberOfPages * this.pageWidth + this.wrapperWidth; + this.snapThreshold = this.options.snapThreshold === null ? + Math.round(this.pageWidth * 0.15) : + /%/.test(this.options.snapThreshold) ? + Math.round(this.pageWidth * this.options.snapThreshold.replace('%', '') / 100) : + this.options.snapThreshold; + }, + + updatePageCount: function (n) { + this.options.numberOfPages = n; + this.maxX = -this.options.numberOfPages * this.pageWidth + this.wrapperWidth; + }, + + goToPage: function (p) { + var i; + + this.masterPages[this.currentMasterPage].className = this.masterPages[this.currentMasterPage].className.replace(/(^|\s)swipeview-active(\s|$)/, ''); + for (i=0; i<3; i++) { + className = this.masterPages[i].className; + /(^|\s)swipeview-loading(\s|$)/.test(className) || (this.masterPages[i].className = !className ? 'swipeview-loading' : className + ' swipeview-loading'); + } + + p = p < 0 ? 0 : p > this.options.numberOfPages-1 ? this.options.numberOfPages-1 : p; + this.page = p; + this.pageIndex = p; + this.slider.style[transitionDuration] = '0s'; + this.__pos(-p * this.pageWidth); + + this.currentMasterPage = (this.page + 1) - Math.floor((this.page + 1) / 3) * 3; + + this.masterPages[this.currentMasterPage].className = this.masterPages[this.currentMasterPage].className + ' swipeview-active'; + + if (this.currentMasterPage === 0) { + this.masterPages[2].style.left = this.page * 100 - 100 + '%'; + this.masterPages[0].style.left = this.page * 100 + '%'; + this.masterPages[1].style.left = this.page * 100 + 100 + '%'; + + this.masterPages[2].dataset.upcomingPageIndex = this.page === 0 ? this.options.numberOfPages-1 : this.page - 1; + this.masterPages[0].dataset.upcomingPageIndex = this.page; + this.masterPages[1].dataset.upcomingPageIndex = this.page == this.options.numberOfPages-1 ? 0 : this.page + 1; + } else if (this.currentMasterPage == 1) { + this.masterPages[0].style.left = this.page * 100 - 100 + '%'; + this.masterPages[1].style.left = this.page * 100 + '%'; + this.masterPages[2].style.left = this.page * 100 + 100 + '%'; + + this.masterPages[0].dataset.upcomingPageIndex = this.page === 0 ? this.options.numberOfPages-1 : this.page - 1; + this.masterPages[1].dataset.upcomingPageIndex = this.page; + this.masterPages[2].dataset.upcomingPageIndex = this.page == this.options.numberOfPages-1 ? 0 : this.page + 1; + } else { + this.masterPages[1].style.left = this.page * 100 - 100 + '%'; + this.masterPages[2].style.left = this.page * 100 + '%'; + this.masterPages[0].style.left = this.page * 100 + 100 + '%'; + + this.masterPages[1].dataset.upcomingPageIndex = this.page === 0 ? this.options.numberOfPages-1 : this.page - 1; + this.masterPages[2].dataset.upcomingPageIndex = this.page; + this.masterPages[0].dataset.upcomingPageIndex = this.page == this.options.numberOfPages-1 ? 0 : this.page + 1; + } + + this.__flip(); + }, + + next: function () { + if (!this.options.loop && this.x == this.maxX) return; + + this.directionX = -1; + this.x -= 1; + this.__checkPosition(); + }, + + prev: function () { + if (!this.options.loop && this.x === 0) return; + + this.directionX = 1; + this.x += 1; + this.__checkPosition(); + }, + + handleEvent: function (e) { + switch (e.type) { + case startEvent: + this.__start(e); + e.preventDefault(); + e.stopPropagation(); + return false; + break; + case moveEvent: + this.__move(e); + break; + case cancelEvent: + case endEvent: + this.__end(e); + break; + case resizeEvent: + this.__resize(); + break; + case transitionEndEvent: + case 'otransitionend': + if (e.target == this.slider && !this.options.hastyPageFlip) this.__flip(); + break; + } + }, + + + /** + * + * Pseudo private methods + * + */ + __pos: function (x) { + this.x = x; + this.slider.style[transform] = 'translate(' + x + 'px,0)' + translateZ; + }, + + __resize: function () { + this.refreshSize(); + this.slider.style[transitionDuration] = '0s'; + this.__pos(-this.page * this.pageWidth); + }, + + __start: function (e) { + //e.preventDefault(); + + if (this.initiated) return; + + var point = hasTouch ? e.touches[0] : e; + + this.initiated = true; + this.moved = false; + this.thresholdExceeded = false; + this.startX = point.pageX; + this.startY = point.pageY; + this.pointX = point.pageX; + this.pointY = point.pageY; + this.stepsX = 0; + this.stepsY = 0; + this.directionX = 0; + this.directionLocked = false; + +/* var matrix = getComputedStyle(this.slider, null).webkitTransform.replace(/[^0-9-.,]/g, '').split(','); + this.x = matrix[4] * 1;*/ + + this.slider.style[transitionDuration] = '0s'; + + this.__event('touchstart'); + }, + + __move: function (e) { + if (!this.initiated) return; + + var point = hasTouch ? e.touches[0] : e, + deltaX = point.pageX - this.pointX, + deltaY = point.pageY - this.pointY, + newX = this.x + deltaX, + dist = Math.abs(point.pageX - this.startX); + + this.moved = true; + this.pointX = point.pageX; + this.pointY = point.pageY; + this.directionX = deltaX > 0 ? 1 : deltaX < 0 ? -1 : 0; + this.stepsX += Math.abs(deltaX); + this.stepsY += Math.abs(deltaY); + + // We take a 10px buffer to figure out the direction of the swipe + if (this.stepsX < 10 && this.stepsY < 10) { +// e.preventDefault(); + return; + } + + // We are scrolling vertically, so skip SwipeView and give the control back to the browser + if (!this.directionLocked && this.stepsY > this.stepsX) { + this.initiated = false; + return; + } + + e.preventDefault(); + + this.directionLocked = true; + + if (!this.options.loop && (newX > 0 || newX < this.maxX)) { + newX = this.x + (deltaX / 2); + } + + if (!this.thresholdExceeded && dist >= this.snapThreshold) { + this.thresholdExceeded = true; + this.__event('moveout'); + } else if (this.thresholdExceeded && dist < this.snapThreshold) { + this.thresholdExceeded = false; + this.__event('movein'); + } + +/* if (newX > 0 || newX < this.maxX) { + newX = this.x + (deltaX / 2); + }*/ + + this.__pos(newX); + }, + + __end: function (e) { + if (!this.initiated) return; + + var point = hasTouch ? e.changedTouches[0] : e, + dist = Math.abs(point.pageX - this.startX); + + this.initiated = false; + + if (!this.moved) return; + + if (!this.options.loop && (this.x > 0 || this.x < this.maxX)) { + dist = 0; + this.__event('movein'); + } + + // Check if we exceeded the snap threshold + if (dist < this.snapThreshold) { + this.slider.style[transitionDuration] = Math.floor(300 * dist / this.snapThreshold) + 'ms'; + this.__pos(-this.page * this.pageWidth); + return; + } + + this.__checkPosition(); + }, + + __checkPosition: function () { + var pageFlip, + pageFlipIndex, + className; + + this.masterPages[this.currentMasterPage].className = this.masterPages[this.currentMasterPage].className.replace(/(^|\s)swipeview-active(\s|$)/, ''); + + // Flip the page + if (this.directionX > 0) { + this.page = -Math.ceil(this.x / this.pageWidth); + this.currentMasterPage = (this.page + 1) - Math.floor((this.page + 1) / 3) * 3; + this.pageIndex = this.pageIndex === 0 ? this.options.numberOfPages - 1 : this.pageIndex - 1; + + pageFlip = this.currentMasterPage - 1; + pageFlip = pageFlip < 0 ? 2 : pageFlip; + this.masterPages[pageFlip].style.left = this.page * 100 - 100 + '%'; + + pageFlipIndex = this.page - 1; + } else { + this.page = -Math.floor(this.x / this.pageWidth); + this.currentMasterPage = (this.page + 1) - Math.floor((this.page + 1) / 3) * 3; + this.pageIndex = this.pageIndex == this.options.numberOfPages - 1 ? 0 : this.pageIndex + 1; + + pageFlip = this.currentMasterPage + 1; + pageFlip = pageFlip > 2 ? 0 : pageFlip; + this.masterPages[pageFlip].style.left = this.page * 100 + 100 + '%'; + + pageFlipIndex = this.page + 1; + } + + // Add active class to current page + className = this.masterPages[this.currentMasterPage].className; + /(^|\s)swipeview-active(\s|$)/.test(className) || (this.masterPages[this.currentMasterPage].className = !className ? 'swipeview-active' : className + ' swipeview-active'); + + // Add loading class to flipped page + className = this.masterPages[pageFlip].className; + /(^|\s)swipeview-loading(\s|$)/.test(className) || (this.masterPages[pageFlip].className = !className ? 'swipeview-loading' : className + ' swipeview-loading'); + + pageFlipIndex = pageFlipIndex - Math.floor(pageFlipIndex / this.options.numberOfPages) * this.options.numberOfPages; + this.masterPages[pageFlip].dataset.upcomingPageIndex = pageFlipIndex; // Index to be loaded in the newly flipped page + + newX = -this.page * this.pageWidth; + + this.slider.style[transitionDuration] = Math.floor(500 * Math.abs(this.x - newX) / this.pageWidth) + 'ms'; + + // Hide the next page if we decided to disable looping + if (!this.options.loop) { + this.masterPages[pageFlip].style.visibility = newX === 0 || newX == this.maxX ? 'hidden' : ''; + } + + if (this.x == newX) { + this.__flip(); // If we swiped all the way long to the next page (extremely rare but still) + } else { + this.__pos(newX); + if (this.options.hastyPageFlip) this.__flip(); + } + }, + + __flip: function () { + this.__event('flip'); + + for (var i=0; i<3; i++) { + this.masterPages[i].className = this.masterPages[i].className.replace(/(^|\s)swipeview-loading(\s|$)/, ''); // Remove the loading class + this.masterPages[i].dataset.pageIndex = this.masterPages[i].dataset.upcomingPageIndex; + } + }, + + __event: function (type) { + var ev = document.createEvent("Event"); + + ev.initEvent('swipeview-' + type, true, true); + + this.wrapper.dispatchEvent(ev); + } + }; + + function prefixStyle (style) { + if ( vendor === '' ) return style; + + style = style.charAt(0).toUpperCase() + style.substr(1); + return vendor + style; + } + + return SwipeView; +})(window, document); \ No newline at end of file