Skip to content
Browse files

Clean up, api consolidation and e-reader demo

  • Loading branch information...
1 parent d9ecebd commit b9204cc1c3c237a67fc47e21b7eea5cf835b3233 @cubiq committed Oct 21, 2011
View
2 README.md
@@ -1,4 +1,4 @@
-SwipeView v0.3 - 2011-10-15
+SwipeView v0.9 - 2011-10-21
===========================
Virtually infinite loop-able horizontal carousel for mobile webkit (in 4kb).
View
3,341 demo/ereader/alice.txt
3,341 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
140 demo/ereader/index.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+ <meta name="apple-mobile-web-app-capable" content="yes">
+ <meta name="apple-mobile-web-app-status-bar-style" content="black">
+ <title>SwipeView</title>
+ <link href="style.css" rel="stylesheet" type="text/css">
+ <script type="text/javascript" src="../../src/swipeview.js"></script>
+
+<script type="text/javascript">
+document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
+
+window.addEventListener('load', function () {
+ var ereader,
+ el,
+ i,
+ pageIndex,
+ pages = [],
+ req = new XMLHttpRequest();
+
+ ereader = new SwipeView('#wrapper', { hastyPageFlip:true });
+
+ // Ajax request
+ req.open('GET', 'alice.txt', true);
+ req.onreadystatechange = function () {
+ if (req.readyState != 4) return;
+
+ paginate(req.status != 200 && req.status != 304 ? false : req.responseText);
+
+ req = null;
+ }
+ req.send(null);
+
+ function paginate(book) {
+ var that = this,
+ container,
+ helper,
+ words = [],
+ segment,
+ wordCount = 100,
+ avgWordCount = 0,
+ pbCurrent = 0,
+ size;
+
+ if (!book) return;
+
+ book = book.replace(/\n\n/g, ' <br><br>').replace(/\n/g, ' ');
+ pbTotal = book.length;
+
+ container = document.createElement('div');
+ container.style.visibility = 'hidden';
+ container.innerHTML = '<div id="ereader-helper"></div>';
+ ereader.slider.appendChild(container);
+ helper = document.getElementById('ereader-helper');
+ helper.innerHTML = '';
+
+ while (book) {
+ words = book.split(' ', wordCount);
+ segment = words.join(' ');
+ helper.innerHTML = segment;
+
+ if (helper.offsetHeight > ereader.wrapperHeight) {
+ if (size == -1) {
+ words.pop();
+ segment = words.join(' ');
+
+ pages.push(segment);
+ book = book.substr(segment.length);
+ avgWordCount = Math.round((wordCount + avgWordCount)/2);
+ wordCount = avgWordCount;
+ size = 0;
+ } else {
+ size = 1;
+ wordCount--;
+ }
+ } else {
+ if (size == 1) {
+ pages.push(segment);
+ book = book.substr(segment.length);
+ avgWordCount = Math.round((wordCount + avgWordCount)/2);
+ wordCount = avgWordCount;
+ size = 0;
+ } else {
+ if (segment == book) {
+ pages.push(segment);
+ book = '';
+ }
+
+ size = -1;
+ wordCount++;
+ }
+ }
+ }
+
+ book = null;
+ words = null;
+ segment = null;
+ helper.innerHTML = '';
+ ereader.slider.removeChild(container);
+
+ ereader.upagePageCount(pages.length);
+
+ // Load initial data
+ for (i=0; i<3; i++) {
+ pageIndex = i==0 ? pages.length-1 : i-1;
+ el = document.createElement('div');
+ el.innerHTML = pages[pageIndex];
+ ereader.masterPages[i].appendChild(el)
+ }
+
+ document.getElementById('loading').style.display = 'none';
+ }
+
+ ereader.onFlip(function () {
+ var el,
+ upcoming,
+ i;
+
+ for (i=0; i<3; i++) {
+ upcoming = ereader.masterPages[i].dataset.upcomingPageIndex;
+
+ if (upcoming != ereader.masterPages[i].dataset.pageIndex) {
+ el = ereader.masterPages[i].querySelector('div');
+ el.innerHTML = pages[upcoming];
+ }
+ }
+ });
+}, false);
+</script>
+</head>
+
+<body>
+ <div id="loading">
+ <p>Paginating. Please wait...</p>
+ </div>
+ <div id="wrapper"></div>
+</body>
+</html>
View
56 demo/ereader/style.css
@@ -0,0 +1,56 @@
+html, body { height:100%; }
+body {
+ padding:0;
+ margin:0;
+ background:#DBD9CB;
+ -webkit-user-select:none;
+ -webkit-text-size-adjust:none;
+ color:#eee;
+ font-family:georgia,serif;
+ font-size:18px;
+ color:#2F271B;
+}
+
+#wrapper {
+ width:320px;
+ height:100%;
+ max-height:460px;
+}
+
+#wrapper > div > div {
+ overflow:hidden;
+}
+
+#wrapper > div > div > div {
+ padding:20px;
+ -webkit-transition-duration:.4s;
+ -webkit-transition-property:opacity;
+}
+
+#wrapper > div > .swipeview-loading div {
+ -webkit-transition-duration:0;
+ opacity:0;
+}
+
+#loading {
+ -webkit-box-sizing:border-box;
+ position:absolute;
+ z-index:100;
+ width:200px;
+ top:50%;
+ left:50%;
+ margin-left:-100px;
+ margin-top:-25px;
+ text-align:center;
+ font-size:14px;
+ background:#F4F2DE;
+ border:1px solid #BEBCA9;
+ -webkit-border-radius:10px;
+ -webkit-box-shadow:0 0 4px rgba(0,0,0,0.2);
+}
+
+#loading p {
+ padding:0;
+ margin:0;
+ height:50px; line-height:50px;
+}
View
0 demo/images/pic01.jpg → demo/gallery/images/pic01.jpg
File renamed without changes
View
0 demo/images/pic02.jpg → demo/gallery/images/pic02.jpg
File renamed without changes
View
0 demo/images/pic03.jpg → demo/gallery/images/pic03.jpg
File renamed without changes
View
0 demo/images/pic04.jpg → demo/gallery/images/pic04.jpg
File renamed without changes
View
0 demo/images/pic05.jpg → demo/gallery/images/pic05.jpg
File renamed without changes
View
0 demo/images/pic06.jpg → demo/gallery/images/pic06.jpg
File renamed without changes
View
110 demo/gallery/index.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+ <meta name="apple-mobile-web-app-capable" content="yes">
+ <meta name="apple-mobile-web-app-status-bar-style" content="black">
+ <title>SwipeView</title>
+ <link href="style.css" rel="stylesheet" type="text/css">
+ <script type="text/javascript" src="../../src/swipeview.js"></script>
+</head>
+
+<body>
+ <div id="wrapper"></div>
+
+<script type="text/javascript">
+document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
+
+var gallery,
+ el,
+ i,
+ page,
+ slides = [
+ {
+ img: 'images/pic01.jpg',
+ width: 300,
+ height: 213,
+ desc: 'Piazza del Duomo, Florence, Italy'
+ },
+ {
+ img: 'images/pic02.jpg',
+ width: 300,
+ height: 164,
+ desc: 'Tuscan Landscape'
+ },
+ {
+ img: 'images/pic03.jpg',
+ width: 300,
+ height: 213,
+ desc: 'Colosseo, Rome, Italy'
+ },
+ {
+ img: 'images/pic04.jpg',
+ width: 147,
+ height: 220,
+ desc: 'Somewhere near Chinatown, San Francisco'
+ },
+ {
+ img: 'images/pic05.jpg',
+ width: 300,
+ height: 213,
+ desc: 'Medieval guard tower, Asciano, Siena, Italy'
+ },
+ {
+ img: 'images/pic06.jpg',
+ width: 165,
+ height: 220,
+ desc: 'Leaning tower, Pisa, Italy'
+ }
+ ];
+
+gallery = new SwipeView('#wrapper', { numberOfPages: slides.length });
+
+// Load initial data
+for (i=0; i<3; i++) {
+ page = i==0 ? slides.length-1 : i-1;
+ el = document.createElement('img');
+ el.src = slides[page].img;
+ el.width = slides[page].width;
+ el.height = slides[page].height;
+ gallery.masterPages[i].appendChild(el);
+
+ el = document.createElement('span');
+ el.innerHTML = slides[page].desc;
+ gallery.masterPages[i].appendChild(el)
+}
+
+gallery.onFlip(function () {
+ var el,
+ upcoming,
+ i;
+
+ for (i=0; i<3; i++) {
+ upcoming = gallery.masterPages[i].dataset.upcomingPageIndex;
+
+ if (upcoming != gallery.masterPages[i].dataset.pageIndex) {
+ el = gallery.masterPages[i].querySelector('img');
+ el.src = slides[upcoming].img;
+ el.width = slides[upcoming].width;
+ el.height = slides[upcoming].height;
+
+ el = gallery.masterPages[i].querySelector('span');
+ el.innerHTML = slides[upcoming].desc;
+ }
+ }
+});
+
+gallery.onMoveOut(function () {
+ gallery.masterPages[gallery.currentMasterPage].className = gallery.masterPages[gallery.currentMasterPage].className.replace(/(^|\s)swipeview-active(\s|$)/, '');
+});
+
+gallery.onMoveIn(function () {
+ var className = gallery.masterPages[gallery.currentMasterPage].className;
+ /(^|\s)swipeview-active(\s|$)/.test(className) || (gallery.masterPages[gallery.currentMasterPage].className = !className ? 'swipeview-active' : className + ' swipeview-active');
+});
+
+
+</script>
+</body>
+</html>
View
43 demo/style.css → demo/gallery/style.css
@@ -16,16 +16,16 @@ body {
height:100%;
}
-#wrapper > div > div {
+#swipeview-slider > div {
+ position:relative;
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-box-pack:center;
-webkit-box-align:center;
overflow:hidden;
}
-#wrapper img {
- position:relative;
+#swipeview-slider img {
display:block;
border:5px solid #eee;
-webkit-box-shadow:0 2px 6px #000;
@@ -35,22 +35,27 @@ body {
opacity:1;
}
-#wrapper span {
- position:relative;
+#swipeview-slider span {
+ position:absolute;
+ bottom:0;
+ left:0;
+ width:100%;
+ padding:20px 0;
display:block;
- background:#000 -webkit-gradient(linear, 0 0, 0 100%, from(#333), to(#000));
- border:2px solid #777;
- padding:0 20px;
- margin-top:10px;
- height:20px;
- line-height:20px;
- -webkit-border-radius:11px;
- -webkit-background-clip:padding-box;
- -webkit-box-shadow:0 2px 6px #000;
- -webkit-transition-duration:.4s;
- -webkit-transition-property:opacity;
- opacity:1;
- text-shadow:0 -1px 0 #000;
+ background:rgba(0,0,0,0.75);
+ font-size:20px;
+ text-align:center;
+ text-shadow:0 1px 0 #000;
+ border-top:1px solid rgba(255,255,255,0.2);
+ -webkit-border-top-left-radius:10px;
+ -webkit-border-top-right-radius:10px;
+ -webkit-transition-duration:.3s;
+ -webkit-transition-property:-webkit-transform;
+ -webkit-transform:translate3d(0,100%,0);
+}
+
+#swipeview-slider .swipeview-active span {
+ -webkit-transform:translate3d(0,0,0);
}
#wrapper > div > .swipeview-loading {
@@ -68,5 +73,5 @@ body {
#wrapper > div > .swipeview-loading span {
-webkit-transition-duration:0;
- opacity:0;
+ -webkit-transform:translate3d(0,100%,0);
}
View
84 demo/index.html
@@ -1,84 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
- <meta name="apple-mobile-web-app-capable" content="yes">
- <meta name="apple-mobile-web-app-status-bar-style" content="black">
- <title>SwipeView</title>
- <link href="style.css" rel="stylesheet" type="text/css">
- <script type="text/javascript" src="../src/swipeview.js"></script>
-</head>
-
-<body>
- <div id="wrapper"></div>
-
-<script type="text/javascript">
- document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
-
- var sv = new SwipeView('#wrapper', {
- pages: [
- {
- img: {
- src: 'images/pic01.jpg',
- width: 300,
- height: 213
- },
- span: {
- innerText: 'Piazza del Duomo, Florence, Italy'
- }
- },
- {
- img: {
- src: 'images/pic02.jpg',
- width: 300,
- height: 164
- },
- span: {
- innerText: 'Tuscan Landscape'
- }
- },
- {
- img: {
- src: 'images/pic03.jpg',
- width: 300,
- height: 213
- },
- span: {
- innerText: 'Colosseo, Rome, Italy'
- }
- },
- {
- img: {
- src: 'images/pic04.jpg',
- width: 147,
- height: 220
- },
- span: {
- innerText: 'Somewhere near Chinatown, San Francisco'
- }
- },
- {
- img: {
- src: 'images/pic05.jpg',
- width: 300,
- height: 213
- },
- span: {
- innerText: 'Medieval guard tower, Asciano, Siena, Italy'
- }
- },
- {
- img: {
- src: 'images/pic06.jpg',
- width: 165,
- height: 220
- },
- span: {
- innerText: 'Leaning tower, Pisa, Italy'
- }
- }]
- });
-</script>
-</body>
-</html>
View
140 src/swipeview.js
@@ -1,5 +1,5 @@
/*!
- * SwipeView v0.3 ~ Copyright (c) 2011 Matteo Spinelli, http://cubiq.org
+ * SwipeView v0.9 ~ Copyright (c) 2011 Matteo Spinelli, http://cubiq.org
* Released under MIT license, http://cubiq.org/license
*/
var SwipeView = (function(){
@@ -10,18 +10,17 @@ var SwipeView = (function(){
endEvent = hasTouch ? 'touchend' : 'mouseup',
cancelEvent = hasTouch ? 'touchcancel' : 'mouseup',
-// isImage = function (value) { return /.(jpg|jpeg|png|gif|svg|pdf)(\?.*)?$/.test(value); },
-
SwipeView = function (el, options) {
- var i, l, j,
- element,
- page,
- count = 0;
+ var i,
+ div,
+ className;
- this.wrapper = document.querySelector(el);
+ this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
this.options = {
- pages: [],
- snapThreshold: null
+ text: null,
+ numberOfPages: 3,
+ snapThreshold: null,
+ hastyPageFlip: false
}
// User defined options
@@ -33,40 +32,27 @@ var SwipeView = (function(){
this.masterPages = [];
div = document.createElement('div');
+ div.id = 'swipeview-slider';
div.style.cssText = 'position:relative;top:0;height:100%;width:100%;-webkit-transition-duration:0;-webkit-transform:translate3d(0,0,0);-webkit-transition-timining-function:ease-out';
this.wrapper.appendChild(div);
this.slider = div;
this.refreshSize();
- for (i=0, l=this.options.pages.length; i<l; i++) {
- for (j in this.options.pages[i]) {
- this.options.pages[i][j].className = this.options.pages[i][j].className ? this.options.pages[i][j].className + ' swipeviewElement' + count : 'swipeviewElement' + count;
- count++;
- }
- count = 0;
- }
-
- for (i=0; i<3; i++) {
+ for (i=-1; i<2; i++) {
div = document.createElement('div');
- div.style.cssText = '-webkit-transform:translateZ(0);position:absolute;top:0;height:100%;width:100%;left:' + (i-1)*100 + '%';
+ div.id = 'swipeview-masterpage-' + (i+1);
+ div.style.cssText = '-webkit-transform:translateZ(0);position:absolute;top:0;height:100%;width:100%;left:' + i*100 + '%';
if (!div.dataset) div.dataset = {};
div.dataset.pageIndex = i;
- div.dataset.upcomingPageIndex = div.dataset.pageIndex;
-
- page = i==0 ? this.options.pages.length-1 : i-1;
- for (l in this.options.pages[page]) {
- element = document.createElement(l);
- for (j in this.options.pages[page][l]) {
- element[j] = this.options.pages[page][l][j];
- }
-
- div.appendChild(element);
- }
+ div.dataset.upcomingPageIndex = i;
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);
@@ -83,7 +69,22 @@ var SwipeView = (function(){
currentMasterPage: 1,
x: 0,
page: 0,
- image: 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 });
+ },
destroy: function () {
// Remove the event listeners
@@ -114,7 +115,7 @@ var SwipeView = (function(){
this.__resize();
break;
case 'webkitTransitionEnd':
- if (e.target == this.slider) this.__flip();
+ if (e.target == this.slider && !this.options.hastyPageFlip) this.__flip();
break;
}
},
@@ -131,6 +132,10 @@ var SwipeView = (function(){
: this.options.snapThreshold;
},
+ upagePageCount: function (n) {
+ this.options.numberOfPages = n;
+ },
+
__pos: function (x) {
this.x = x;
this.slider.style.webkitTransform = 'translate3d(' + x + 'px,0,0)';
@@ -151,6 +156,7 @@ var SwipeView = (function(){
this.initiated = true;
this.moved = false;
+ this.thresholdExceeded = false;
this.startX = point.pageX;
this.startY = point.pageY;
this.pointX = point.pageX;
@@ -169,12 +175,21 @@ var SwipeView = (function(){
var point = hasTouch ? e.touches[0] : e,
deltaX = point.pageX - this.pointX,
- newX = this.x + deltaX;
+ newX = this.x + deltaX,
+ dist = Math.abs(point.pageX - this.startX);
this.moved = true;
this.pointX = point.pageX;
this.directionX = deltaX > 0 ? 1 : deltaX < 0 ? -1 : 0;
+ 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);
}*/
@@ -188,7 +203,8 @@ var SwipeView = (function(){
var point = hasTouch ? e.changedTouches[0] : e,
pageFlip,
pageFlipIndex,
- newX;
+ newX,
+ className;
this.initiated = false;
@@ -201,6 +217,8 @@ var SwipeView = (function(){
return;
}
+ 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);
@@ -222,42 +240,38 @@ var SwipeView = (function(){
pageFlipIndex = this.page + 1;
}
- this.masterPages[pageFlip].className = 'swipeview-loading';
- pageFlipIndex = pageFlipIndex - Math.floor(pageFlipIndex / this.options.pages.length) * this.options.pages.length;
- this.masterPages[pageFlip].dataset.upcomingPageIndex = pageFlipIndex; // Index to be loaded when the user stops swiping
+ // 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
this.slider.style.webkitTransitionDuration = '500ms';
newX = -this.page * this.pageWidth;
- 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.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 () {
- var el,
- newIndex,
- i, l,
- j, k,
- count;
-
- for (i=0, l=this.masterPages.length; i<l; i++) {
- this.masterPages[i].className = '';
- newIndex = this.masterPages[i].dataset.upcomingPageIndex;
-
- if (newIndex != this.masterPages[i].dataset.pageIndex) {
- this.masterPages[i].dataset.pageIndex = newIndex;
- count = 0;
-
- for (j in this.options.pages[newIndex]) { // Parse all page elements
- el = this.masterPages[i].querySelector('.swipeviewElement' + count);
-
- for (k in this.options.pages[newIndex][j]) { // Parse all element attributes
- el[k] = this.options.pages[newIndex][j][k];
- }
- count++
- }
- }
+ this.__event('flip');
+
+ for (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;
}
},

0 comments on commit b9204cc

Please sign in to comment.
Something went wrong with that request. Please try again.