mirror of
https://github.com/flynx/PortableMag.git
synced 2025-10-28 18:50:08 +00:00
migrated to iScroll5 and a partial rewrite...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
48b30ccb5a
commit
fc8b17910e
@ -19,7 +19,7 @@
|
|||||||
</author>
|
</author>
|
||||||
|
|
||||||
|
|
||||||
<!--preference name="orientation" value="landscape" /-->
|
<preference name="orientation" value="landscape" />
|
||||||
<preference name="fullscreen" value="true" />
|
<preference name="fullscreen" value="true" />
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -62,7 +62,7 @@
|
|||||||
.top-toolbar, .bottom-toolbar {
|
.top-toolbar, .bottom-toolbar {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: silver;
|
color: silver;
|
||||||
box-shadow: 5px 5px 50px 5px #444 inset;
|
/*box-shadow: 5px 5px 50px 5px #444 inset;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-toolbar .title,
|
.top-toolbar .title,
|
||||||
@ -154,8 +154,8 @@
|
|||||||
.light-viewer .bottom-toolbar {
|
.light-viewer .bottom-toolbar {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: silver;
|
color: silver;
|
||||||
background: white;
|
/*background: white;
|
||||||
box-shadow: 5px 5px 50px 20px #eee;
|
box-shadow: 5px 5px 50px 20px #eee;*/
|
||||||
}
|
}
|
||||||
.light-viewer .top-toolbar a,
|
.light-viewer .top-toolbar a,
|
||||||
.light-viewer .bottom-toolbar a {
|
.light-viewer .bottom-toolbar a {
|
||||||
@ -240,8 +240,8 @@
|
|||||||
.dark-viewer .bottom-toolbar {
|
.dark-viewer .bottom-toolbar {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: gray;
|
color: gray;
|
||||||
background: black;
|
/*background: black;
|
||||||
box-shadow: none;
|
box-shadow: none;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-viewer .top-toolbar a,
|
.dark-viewer .top-toolbar a,
|
||||||
|
|||||||
@ -299,7 +299,8 @@ body {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
background: #555;
|
/*background: #555;*/
|
||||||
|
background: transparent;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
@ -319,12 +320,6 @@ body {
|
|||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.page-view-mode .top-toolbar,
|
|
||||||
.page-view-mode .bottom-toolbar,
|
|
||||||
.full-page-view-mode .top-toolbar,
|
|
||||||
.full-page-view-mode .bottom-toolbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* title */
|
/* title */
|
||||||
.top-toolbar .title,
|
.top-toolbar .title,
|
||||||
@ -560,6 +555,7 @@ body {
|
|||||||
|
|
||||||
.page-view-mode .top-toolbar,
|
.page-view-mode .top-toolbar,
|
||||||
.page-view-mode .bottom-toolbar {
|
.page-view-mode .bottom-toolbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-view-mode .page .content {
|
.page-view-mode .page .content {
|
||||||
|
|||||||
1565
ext-lib/iscroll-infinite.js
Executable file
1565
ext-lib/iscroll-infinite.js
Executable file
File diff suppressed because it is too large
Load Diff
594
ext-lib/iscroll-lite.js
Executable file
594
ext-lib/iscroll-lite.js
Executable file
@ -0,0 +1,594 @@
|
|||||||
|
/*!
|
||||||
|
* iScroll Lite base on iScroll v4.1.6 ~ Copyright (c) 2011 Matteo Spinelli, http://cubiq.org
|
||||||
|
* Released under MIT license, http://cubiq.org/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
var m = Math,
|
||||||
|
mround = function (r) { return r >> 0; },
|
||||||
|
vendor = (/webkit/i).test(navigator.appVersion) ? 'webkit' :
|
||||||
|
(/firefox/i).test(navigator.userAgent) ? 'Moz' :
|
||||||
|
'opera' in window ? 'O' : '',
|
||||||
|
|
||||||
|
// Browser capabilities
|
||||||
|
isAndroid = (/android/gi).test(navigator.appVersion),
|
||||||
|
isIDevice = (/iphone|ipad/gi).test(navigator.appVersion),
|
||||||
|
isPlaybook = (/playbook/gi).test(navigator.appVersion),
|
||||||
|
isTouchPad = (/hp-tablet/gi).test(navigator.appVersion),
|
||||||
|
|
||||||
|
has3d = 'WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix(),
|
||||||
|
hasTouch = 'ontouchstart' in window && !isTouchPad,
|
||||||
|
hasTransform = vendor + 'Transform' in document.documentElement.style,
|
||||||
|
hasTransitionEnd = isIDevice || isPlaybook,
|
||||||
|
|
||||||
|
nextFrame = (function() {
|
||||||
|
return window.requestAnimationFrame
|
||||||
|
|| window.webkitRequestAnimationFrame
|
||||||
|
|| window.mozRequestAnimationFrame
|
||||||
|
|| window.oRequestAnimationFrame
|
||||||
|
|| window.msRequestAnimationFrame
|
||||||
|
|| function(callback) { return setTimeout(callback, 17); }
|
||||||
|
})(),
|
||||||
|
cancelFrame = (function () {
|
||||||
|
return window.cancelRequestAnimationFrame
|
||||||
|
|| window.webkitCancelAnimationFrame
|
||||||
|
|| window.webkitCancelRequestAnimationFrame
|
||||||
|
|| window.mozCancelRequestAnimationFrame
|
||||||
|
|| window.oCancelRequestAnimationFrame
|
||||||
|
|| window.msCancelRequestAnimationFrame
|
||||||
|
|| clearTimeout
|
||||||
|
})(),
|
||||||
|
|
||||||
|
// Events
|
||||||
|
RESIZE_EV = 'onorientationchange' in window ? 'orientationchange' : 'resize',
|
||||||
|
START_EV = hasTouch ? 'touchstart' : 'mousedown',
|
||||||
|
MOVE_EV = hasTouch ? 'touchmove' : 'mousemove',
|
||||||
|
END_EV = hasTouch ? 'touchend' : 'mouseup',
|
||||||
|
CANCEL_EV = hasTouch ? 'touchcancel' : 'mouseup',
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
trnOpen = 'translate' + (has3d ? '3d(' : '('),
|
||||||
|
trnClose = has3d ? ',0)' : ')',
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
iScroll = function (el, options) {
|
||||||
|
var that = this,
|
||||||
|
doc = document,
|
||||||
|
i;
|
||||||
|
|
||||||
|
that.wrapper = typeof el == 'object' ? el : doc.getElementById(el);
|
||||||
|
that.wrapper.style.overflow = 'hidden';
|
||||||
|
that.scroller = that.wrapper.children[0];
|
||||||
|
|
||||||
|
// Default options
|
||||||
|
that.options = {
|
||||||
|
hScroll: true,
|
||||||
|
vScroll: true,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
bounce: true,
|
||||||
|
bounceLock: false,
|
||||||
|
momentum: true,
|
||||||
|
lockDirection: true,
|
||||||
|
useTransform: true,
|
||||||
|
useTransition: false,
|
||||||
|
|
||||||
|
// Events
|
||||||
|
onRefresh: null,
|
||||||
|
onBeforeScrollStart: function (e) { e.preventDefault(); },
|
||||||
|
onScrollStart: null,
|
||||||
|
onBeforeScrollMove: null,
|
||||||
|
onScrollMove: null,
|
||||||
|
onBeforeScrollEnd: null,
|
||||||
|
onScrollEnd: null,
|
||||||
|
onTouchEnd: null,
|
||||||
|
onDestroy: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// User defined options
|
||||||
|
for (i in options) that.options[i] = options[i];
|
||||||
|
|
||||||
|
// Set starting position
|
||||||
|
that.x = that.options.x;
|
||||||
|
that.y = that.options.y;
|
||||||
|
|
||||||
|
// Normalize options
|
||||||
|
that.options.useTransform = hasTransform ? that.options.useTransform : false;
|
||||||
|
that.options.hScrollbar = that.options.hScroll && that.options.hScrollbar;
|
||||||
|
that.options.vScrollbar = that.options.vScroll && that.options.vScrollbar;
|
||||||
|
that.options.useTransition = hasTransitionEnd && that.options.useTransition;
|
||||||
|
|
||||||
|
// Set some default styles
|
||||||
|
that.scroller.style[vendor + 'TransitionProperty'] = that.options.useTransform ? '-' + vendor.toLowerCase() + '-transform' : 'top left';
|
||||||
|
that.scroller.style[vendor + 'TransitionDuration'] = '0';
|
||||||
|
that.scroller.style[vendor + 'TransformOrigin'] = '0 0';
|
||||||
|
if (that.options.useTransition) that.scroller.style[vendor + 'TransitionTimingFunction'] = 'cubic-bezier(0.33,0.66,0.66,1)';
|
||||||
|
|
||||||
|
if (that.options.useTransform) that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose;
|
||||||
|
else that.scroller.style.cssText += ';position:absolute;top:' + that.y + 'px;left:' + that.x + 'px';
|
||||||
|
|
||||||
|
that.refresh();
|
||||||
|
|
||||||
|
that._bind(RESIZE_EV, window);
|
||||||
|
that._bind(START_EV);
|
||||||
|
if (!hasTouch) that._bind('mouseout', that.wrapper);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
iScroll.prototype = {
|
||||||
|
enabled: true,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
steps: [],
|
||||||
|
scale: 1,
|
||||||
|
|
||||||
|
handleEvent: function (e) {
|
||||||
|
var that = this;
|
||||||
|
switch(e.type) {
|
||||||
|
case START_EV:
|
||||||
|
if (!hasTouch && e.button !== 0) return;
|
||||||
|
that._start(e);
|
||||||
|
break;
|
||||||
|
case MOVE_EV: that._move(e); break;
|
||||||
|
case END_EV:
|
||||||
|
case CANCEL_EV: that._end(e); break;
|
||||||
|
case RESIZE_EV: that._resize(); break;
|
||||||
|
case 'mouseout': that._mouseout(e); break;
|
||||||
|
case 'webkitTransitionEnd': that._transitionEnd(e); break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_resize: function () {
|
||||||
|
this.refresh();
|
||||||
|
},
|
||||||
|
|
||||||
|
_pos: function (x, y) {
|
||||||
|
x = this.hScroll ? x : 0;
|
||||||
|
y = this.vScroll ? y : 0;
|
||||||
|
|
||||||
|
if (this.options.useTransform) {
|
||||||
|
this.scroller.style[vendor + 'Transform'] = trnOpen + x + 'px,' + y + 'px' + trnClose + ' scale(' + this.scale + ')';
|
||||||
|
} else {
|
||||||
|
x = mround(x);
|
||||||
|
y = mround(y);
|
||||||
|
this.scroller.style.left = x + 'px';
|
||||||
|
this.scroller.style.top = y + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
},
|
||||||
|
|
||||||
|
_start: function (e) {
|
||||||
|
var that = this,
|
||||||
|
point = hasTouch ? e.touches[0] : e,
|
||||||
|
matrix, x, y;
|
||||||
|
|
||||||
|
if (!that.enabled) return;
|
||||||
|
|
||||||
|
if (that.options.onBeforeScrollStart) that.options.onBeforeScrollStart.call(that, e);
|
||||||
|
|
||||||
|
if (that.options.useTransition) that._transitionTime(0);
|
||||||
|
|
||||||
|
that.moved = false;
|
||||||
|
that.animating = false;
|
||||||
|
that.zoomed = false;
|
||||||
|
that.distX = 0;
|
||||||
|
that.distY = 0;
|
||||||
|
that.absDistX = 0;
|
||||||
|
that.absDistY = 0;
|
||||||
|
that.dirX = 0;
|
||||||
|
that.dirY = 0;
|
||||||
|
|
||||||
|
if (that.options.momentum) {
|
||||||
|
if (that.options.useTransform) {
|
||||||
|
// Very lame general purpose alternative to CSSMatrix
|
||||||
|
matrix = getComputedStyle(that.scroller, null)[vendor + 'Transform'].replace(/[^0-9-.,]/g, '').split(',');
|
||||||
|
x = matrix[4] * 1;
|
||||||
|
y = matrix[5] * 1;
|
||||||
|
} else {
|
||||||
|
x = getComputedStyle(that.scroller, null).left.replace(/[^0-9-]/g, '') * 1;
|
||||||
|
y = getComputedStyle(that.scroller, null).top.replace(/[^0-9-]/g, '') * 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x != that.x || y != that.y) {
|
||||||
|
if (that.options.useTransition) that._unbind('webkitTransitionEnd');
|
||||||
|
else cancelFrame(that.aniTime);
|
||||||
|
that.steps = [];
|
||||||
|
that._pos(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
that.startX = that.x;
|
||||||
|
that.startY = that.y;
|
||||||
|
that.pointX = point.pageX;
|
||||||
|
that.pointY = point.pageY;
|
||||||
|
|
||||||
|
that.startTime = e.timeStamp || Date.now();
|
||||||
|
|
||||||
|
if (that.options.onScrollStart) that.options.onScrollStart.call(that, e);
|
||||||
|
|
||||||
|
that._bind(MOVE_EV);
|
||||||
|
that._bind(END_EV);
|
||||||
|
that._bind(CANCEL_EV);
|
||||||
|
},
|
||||||
|
|
||||||
|
_move: function (e) {
|
||||||
|
var that = this,
|
||||||
|
point = hasTouch ? e.touches[0] : e,
|
||||||
|
deltaX = point.pageX - that.pointX,
|
||||||
|
deltaY = point.pageY - that.pointY,
|
||||||
|
newX = that.x + deltaX,
|
||||||
|
newY = that.y + deltaY,
|
||||||
|
timestamp = e.timeStamp || Date.now();
|
||||||
|
|
||||||
|
if (that.options.onBeforeScrollMove) that.options.onBeforeScrollMove.call(that, e);
|
||||||
|
|
||||||
|
that.pointX = point.pageX;
|
||||||
|
that.pointY = point.pageY;
|
||||||
|
|
||||||
|
// Slow down if outside of the boundaries
|
||||||
|
if (newX > 0 || newX < that.maxScrollX) {
|
||||||
|
newX = that.options.bounce ? that.x + (deltaX / 2) : newX >= 0 || that.maxScrollX >= 0 ? 0 : that.maxScrollX;
|
||||||
|
}
|
||||||
|
if (newY > 0 || newY < that.maxScrollY) {
|
||||||
|
newY = that.options.bounce ? that.y + (deltaY / 2) : newY >= 0 || that.maxScrollY >= 0 ? 0 : that.maxScrollY;
|
||||||
|
}
|
||||||
|
|
||||||
|
that.distX += deltaX;
|
||||||
|
that.distY += deltaY;
|
||||||
|
that.absDistX = m.abs(that.distX);
|
||||||
|
that.absDistY = m.abs(that.distY);
|
||||||
|
|
||||||
|
if (that.absDistX < 6 && that.absDistY < 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock direction
|
||||||
|
if (that.options.lockDirection) {
|
||||||
|
if (that.absDistX > that.absDistY + 5) {
|
||||||
|
newY = that.y;
|
||||||
|
deltaY = 0;
|
||||||
|
} else if (that.absDistY > that.absDistX + 5) {
|
||||||
|
newX = that.x;
|
||||||
|
deltaX = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
that.moved = true;
|
||||||
|
that._pos(newX, newY);
|
||||||
|
that.dirX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
|
||||||
|
that.dirY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
|
||||||
|
|
||||||
|
if (timestamp - that.startTime > 300) {
|
||||||
|
that.startTime = timestamp;
|
||||||
|
that.startX = that.x;
|
||||||
|
that.startY = that.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (that.options.onScrollMove) that.options.onScrollMove.call(that, e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_end: function (e) {
|
||||||
|
if (hasTouch && e.touches.length != 0) return;
|
||||||
|
|
||||||
|
var that = this,
|
||||||
|
point = hasTouch ? e.changedTouches[0] : e,
|
||||||
|
target, ev,
|
||||||
|
momentumX = { dist:0, time:0 },
|
||||||
|
momentumY = { dist:0, time:0 },
|
||||||
|
duration = (e.timeStamp || Date.now()) - that.startTime,
|
||||||
|
newPosX = that.x,
|
||||||
|
newPosY = that.y,
|
||||||
|
newDuration;
|
||||||
|
|
||||||
|
that._unbind(MOVE_EV);
|
||||||
|
that._unbind(END_EV);
|
||||||
|
that._unbind(CANCEL_EV);
|
||||||
|
|
||||||
|
if (that.options.onBeforeScrollEnd) that.options.onBeforeScrollEnd.call(that, e);
|
||||||
|
|
||||||
|
if (!that.moved) {
|
||||||
|
if (hasTouch) {
|
||||||
|
// Find the last touched element
|
||||||
|
target = point.target;
|
||||||
|
while (target.nodeType != 1) target = target.parentNode;
|
||||||
|
|
||||||
|
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
|
||||||
|
ev = document.createEvent('MouseEvents');
|
||||||
|
ev.initMouseEvent('click', true, true, e.view, 1,
|
||||||
|
point.screenX, point.screenY, point.clientX, point.clientY,
|
||||||
|
e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
|
||||||
|
0, null);
|
||||||
|
ev._fake = true;
|
||||||
|
target.dispatchEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
that._resetPos(200);
|
||||||
|
|
||||||
|
if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duration < 300 && that.options.momentum) {
|
||||||
|
momentumX = newPosX ? that._momentum(newPosX - that.startX, duration, -that.x, that.scrollerW - that.wrapperW + that.x, that.options.bounce ? that.wrapperW : 0) : momentumX;
|
||||||
|
momentumY = newPosY ? that._momentum(newPosY - that.startY, duration, -that.y, (that.maxScrollY < 0 ? that.scrollerH - that.wrapperH + that.y : 0), that.options.bounce ? that.wrapperH : 0) : momentumY;
|
||||||
|
|
||||||
|
newPosX = that.x + momentumX.dist;
|
||||||
|
newPosY = that.y + momentumY.dist;
|
||||||
|
|
||||||
|
if ((that.x > 0 && newPosX > 0) || (that.x < that.maxScrollX && newPosX < that.maxScrollX)) momentumX = { dist:0, time:0 };
|
||||||
|
if ((that.y > 0 && newPosY > 0) || (that.y < that.maxScrollY && newPosY < that.maxScrollY)) momentumY = { dist:0, time:0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (momentumX.dist || momentumY.dist) {
|
||||||
|
newDuration = m.max(m.max(momentumX.time, momentumY.time), 10);
|
||||||
|
|
||||||
|
that.scrollTo(mround(newPosX), mround(newPosY), newDuration);
|
||||||
|
|
||||||
|
if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
that._resetPos(200);
|
||||||
|
if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_resetPos: function (time) {
|
||||||
|
var that = this,
|
||||||
|
resetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,
|
||||||
|
resetY = that.y >= 0 || that.maxScrollY > 0 ? 0 : that.y < that.maxScrollY ? that.maxScrollY : that.y;
|
||||||
|
|
||||||
|
if (resetX == that.x && resetY == that.y) {
|
||||||
|
if (that.moved) {
|
||||||
|
if (that.options.onScrollEnd) that.options.onScrollEnd.call(that); // Execute custom code on scroll end
|
||||||
|
that.moved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
that.scrollTo(resetX, resetY, time || 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
_mouseout: function (e) {
|
||||||
|
var t = e.relatedTarget;
|
||||||
|
|
||||||
|
if (!t) {
|
||||||
|
this._end(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (t = t.parentNode) if (t == this.wrapper) return;
|
||||||
|
|
||||||
|
this._end(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_transitionEnd: function (e) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
if (e.target != that.scroller) return;
|
||||||
|
|
||||||
|
that._unbind('webkitTransitionEnd');
|
||||||
|
|
||||||
|
that._startAni();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Utilities
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_startAni: function () {
|
||||||
|
var that = this,
|
||||||
|
startX = that.x, startY = that.y,
|
||||||
|
startTime = Date.now(),
|
||||||
|
step, easeOut,
|
||||||
|
animate;
|
||||||
|
|
||||||
|
if (that.animating) return;
|
||||||
|
|
||||||
|
if (!that.steps.length) {
|
||||||
|
that._resetPos(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
step = that.steps.shift();
|
||||||
|
|
||||||
|
if (step.x == startX && step.y == startY) step.time = 0;
|
||||||
|
|
||||||
|
that.animating = true;
|
||||||
|
that.moved = true;
|
||||||
|
|
||||||
|
if (that.options.useTransition) {
|
||||||
|
that._transitionTime(step.time);
|
||||||
|
that._pos(step.x, step.y);
|
||||||
|
that.animating = false;
|
||||||
|
if (step.time) that._bind('webkitTransitionEnd');
|
||||||
|
else that._resetPos(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
animate = function () {
|
||||||
|
var now = Date.now(),
|
||||||
|
newX, newY;
|
||||||
|
|
||||||
|
if (now >= startTime + step.time) {
|
||||||
|
that._pos(step.x, step.y);
|
||||||
|
that.animating = false;
|
||||||
|
if (that.options.onAnimationEnd) that.options.onAnimationEnd.call(that); // Execute custom code on animation end
|
||||||
|
that._startAni();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
now = (now - startTime) / step.time - 1;
|
||||||
|
easeOut = m.sqrt(1 - now * now);
|
||||||
|
newX = (step.x - startX) * easeOut + startX;
|
||||||
|
newY = (step.y - startY) * easeOut + startY;
|
||||||
|
that._pos(newX, newY);
|
||||||
|
if (that.animating) that.aniTime = nextFrame(animate);
|
||||||
|
};
|
||||||
|
|
||||||
|
animate();
|
||||||
|
},
|
||||||
|
|
||||||
|
_transitionTime: function (time) {
|
||||||
|
this.scroller.style[vendor + 'TransitionDuration'] = time + 'ms';
|
||||||
|
},
|
||||||
|
|
||||||
|
_momentum: function (dist, time, maxDistUpper, maxDistLower, size) {
|
||||||
|
var deceleration = 0.0006,
|
||||||
|
speed = m.abs(dist) / time,
|
||||||
|
newDist = (speed * speed) / (2 * deceleration),
|
||||||
|
newTime = 0, outsideDist = 0;
|
||||||
|
|
||||||
|
// Proportinally reduce speed if we are outside of the boundaries
|
||||||
|
if (dist > 0 && newDist > maxDistUpper) {
|
||||||
|
outsideDist = size / (6 / (newDist / speed * deceleration));
|
||||||
|
maxDistUpper = maxDistUpper + outsideDist;
|
||||||
|
speed = speed * maxDistUpper / newDist;
|
||||||
|
newDist = maxDistUpper;
|
||||||
|
} else if (dist < 0 && newDist > maxDistLower) {
|
||||||
|
outsideDist = size / (6 / (newDist / speed * deceleration));
|
||||||
|
maxDistLower = maxDistLower + outsideDist;
|
||||||
|
speed = speed * maxDistLower / newDist;
|
||||||
|
newDist = maxDistLower;
|
||||||
|
}
|
||||||
|
|
||||||
|
newDist = newDist * (dist < 0 ? -1 : 1);
|
||||||
|
newTime = speed / deceleration;
|
||||||
|
|
||||||
|
return { dist: newDist, time: mround(newTime) };
|
||||||
|
},
|
||||||
|
|
||||||
|
_offset: function (el) {
|
||||||
|
var left = -el.offsetLeft,
|
||||||
|
top = -el.offsetTop;
|
||||||
|
|
||||||
|
while (el = el.offsetParent) {
|
||||||
|
left -= el.offsetLeft;
|
||||||
|
top -= el.offsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { left: left, top: top };
|
||||||
|
},
|
||||||
|
|
||||||
|
_bind: function (type, el, bubble) {
|
||||||
|
(el || this.scroller).addEventListener(type, this, !!bubble);
|
||||||
|
},
|
||||||
|
|
||||||
|
_unbind: function (type, el, bubble) {
|
||||||
|
(el || this.scroller).removeEventListener(type, this, !!bubble);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Public methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
destroy: function () {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
that.scroller.style[vendor + 'Transform'] = '';
|
||||||
|
|
||||||
|
// Remove the event listeners
|
||||||
|
that._unbind(RESIZE_EV, window);
|
||||||
|
that._unbind(START_EV);
|
||||||
|
that._unbind(MOVE_EV);
|
||||||
|
that._unbind(END_EV);
|
||||||
|
that._unbind(CANCEL_EV);
|
||||||
|
that._unbind('mouseout', that.wrapper);
|
||||||
|
if (that.options.useTransition) that._unbind('webkitTransitionEnd');
|
||||||
|
|
||||||
|
if (that.options.onDestroy) that.options.onDestroy.call(that);
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh: function () {
|
||||||
|
var that = this,
|
||||||
|
offset;
|
||||||
|
|
||||||
|
that.wrapperW = that.wrapper.clientWidth;
|
||||||
|
that.wrapperH = that.wrapper.clientHeight;
|
||||||
|
|
||||||
|
that.scrollerW = that.scroller.offsetWidth;
|
||||||
|
that.scrollerH = that.scroller.offsetHeight;
|
||||||
|
that.maxScrollX = that.wrapperW - that.scrollerW;
|
||||||
|
that.maxScrollY = that.wrapperH - that.scrollerH;
|
||||||
|
that.dirX = 0;
|
||||||
|
that.dirY = 0;
|
||||||
|
|
||||||
|
that.hScroll = that.options.hScroll && that.maxScrollX < 0;
|
||||||
|
that.vScroll = that.options.vScroll && (!that.options.bounceLock && !that.hScroll || that.scrollerH > that.wrapperH);
|
||||||
|
|
||||||
|
offset = that._offset(that.wrapper);
|
||||||
|
that.wrapperOffsetLeft = -offset.left;
|
||||||
|
that.wrapperOffsetTop = -offset.top;
|
||||||
|
|
||||||
|
|
||||||
|
that.scroller.style[vendor + 'TransitionDuration'] = '0';
|
||||||
|
|
||||||
|
that._resetPos(200);
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollTo: function (x, y, time, relative) {
|
||||||
|
var that = this,
|
||||||
|
step = x,
|
||||||
|
i, l;
|
||||||
|
|
||||||
|
that.stop();
|
||||||
|
|
||||||
|
if (!step.length) step = [{ x: x, y: y, time: time, relative: relative }];
|
||||||
|
|
||||||
|
for (i=0, l=step.length; i<l; i++) {
|
||||||
|
if (step[i].relative) { step[i].x = that.x - step[i].x; step[i].y = that.y - step[i].y; }
|
||||||
|
that.steps.push({ x: step[i].x, y: step[i].y, time: step[i].time || 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
that._startAni();
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollToElement: function (el, time) {
|
||||||
|
var that = this, pos;
|
||||||
|
el = el.nodeType ? el : that.scroller.querySelector(el);
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
pos = that._offset(el);
|
||||||
|
pos.left += that.wrapperOffsetLeft;
|
||||||
|
pos.top += that.wrapperOffsetTop;
|
||||||
|
|
||||||
|
pos.left = pos.left > 0 ? 0 : pos.left < that.maxScrollX ? that.maxScrollX : pos.left;
|
||||||
|
pos.top = pos.top > 0 ? 0 : pos.top < that.maxScrollY ? that.maxScrollY : pos.top;
|
||||||
|
time = time === undefined ? m.max(m.abs(pos.left)*2, m.abs(pos.top)*2) : time;
|
||||||
|
|
||||||
|
that.scrollTo(pos.left, pos.top, time);
|
||||||
|
},
|
||||||
|
|
||||||
|
disable: function () {
|
||||||
|
this.stop();
|
||||||
|
this._resetPos(0);
|
||||||
|
this.enabled = false;
|
||||||
|
|
||||||
|
// If disabled after touchstart we make sure that there are no left over events
|
||||||
|
this._unbind(MOVE_EV);
|
||||||
|
this._unbind(END_EV);
|
||||||
|
this._unbind(CANCEL_EV);
|
||||||
|
},
|
||||||
|
|
||||||
|
enable: function () {
|
||||||
|
this.enabled = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function () {
|
||||||
|
cancelFrame(this.aniTime);
|
||||||
|
this.steps = [];
|
||||||
|
this.moved = false;
|
||||||
|
this.animating = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof exports !== 'undefined') exports.iScroll = iScroll;
|
||||||
|
else window.iScroll = iScroll;
|
||||||
|
|
||||||
|
})();
|
||||||
2015
ext-lib/iscroll-probe.js
Executable file
2015
ext-lib/iscroll-probe.js
Executable file
File diff suppressed because it is too large
Load Diff
2172
ext-lib/iscroll-zoom.js
Executable file
2172
ext-lib/iscroll-zoom.js
Executable file
File diff suppressed because it is too large
Load Diff
2828
ext-lib/iscroll.js
2828
ext-lib/iscroll.js
File diff suppressed because it is too large
Load Diff
274
index.html
274
index.html
@ -34,6 +34,7 @@
|
|||||||
.magazine {
|
.magazine {
|
||||||
left: 150px;
|
left: 150px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
|
background-color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
@ -89,6 +90,9 @@
|
|||||||
<script src="ext-lib/jszip-inflate.js"></script>
|
<script src="ext-lib/jszip-inflate.js"></script>
|
||||||
<!--script src="ext-lib\jszip-deflate.js"></script-->
|
<!--script src="ext-lib\jszip-deflate.js"></script-->
|
||||||
|
|
||||||
|
<script src="ext-lib/iscroll.js"></script>
|
||||||
|
<script src="ext-lib/iscroll-zoom.js"></script>
|
||||||
|
|
||||||
<script src="lib/jli.js"></script>
|
<script src="lib/jli.js"></script>
|
||||||
<script src="lib/scroller.js"></script>
|
<script src="lib/scroller.js"></script>
|
||||||
<script src="lib/keyboard.js"></script>
|
<script src="lib/keyboard.js"></script>
|
||||||
@ -242,8 +246,90 @@ function handleFileSelect(evt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX these stubs override the magazine API and use iScroll...
|
||||||
|
|
||||||
$(document).ready(function(){
|
// XXX need to account for page align...
|
||||||
|
// XXX this works only for big pages...
|
||||||
|
function getVisiblePage(){
|
||||||
|
var offset = $('.magazine').offset().left
|
||||||
|
var width = $('.viewer').width()
|
||||||
|
var pages = $('.page')
|
||||||
|
// filter the closest page to the viewer...
|
||||||
|
.filter(function(){
|
||||||
|
var page = $(this)
|
||||||
|
var p = page.position().left + offset
|
||||||
|
return p >= 0 && p < width/2
|
||||||
|
|| p < 0 && p + page.width() >= width/2
|
||||||
|
})
|
||||||
|
// select the best candidate...
|
||||||
|
// XXX
|
||||||
|
return pages
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************ iScroll5 Actions ***/
|
||||||
|
|
||||||
|
// XXX next/prev page work but only when BOTH:
|
||||||
|
// - MagazineScroller.zoom is set to 1
|
||||||
|
// - current page is focused
|
||||||
|
|
||||||
|
// XXX zoom != 1 messes up both iScroll5 navigation AND PortableMag navigation...
|
||||||
|
|
||||||
|
// XXX we do not need the snap feature, flick event is enough to do next/prev page...
|
||||||
|
|
||||||
|
// XXX make centered page account for page align...
|
||||||
|
|
||||||
|
|
||||||
|
function enableFreeScroll(){
|
||||||
|
MagazineScroller.options.scrollY = true
|
||||||
|
MagazineScroller.options.freeScroll = true
|
||||||
|
MagazineScroller.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableFreeScroll(){
|
||||||
|
MagazineScroller.options.scrollY = false
|
||||||
|
MagazineScroller.options.freeScroll = false
|
||||||
|
MagazineScroller.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Actions...
|
||||||
|
|
||||||
|
// XXX this needs correct reference point calc...
|
||||||
|
function zoomTo(n, scale, time){
|
||||||
|
// calculate page projection center...
|
||||||
|
var page = setCurrent(n)
|
||||||
|
|
||||||
|
var sc = getMagazineScale()
|
||||||
|
var st = scale
|
||||||
|
|
||||||
|
var d = st / sc
|
||||||
|
|
||||||
|
var W = $('.viewer').width()
|
||||||
|
var w = page.width()*sc
|
||||||
|
var o = page.offset().left
|
||||||
|
|
||||||
|
var C = W/2
|
||||||
|
var c = o + w/2
|
||||||
|
|
||||||
|
// left border -> 0
|
||||||
|
// centered -> C = c -> independent of d
|
||||||
|
// right border -> W
|
||||||
|
|
||||||
|
console.log('>>>', c, C, d, (c-C)*d)
|
||||||
|
|
||||||
|
// XXX this works iff d == 2
|
||||||
|
|
||||||
|
MagazineScroller.zoom(scale, C + (c-C)*d, null, time)
|
||||||
|
|
||||||
|
//return page
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
|
||||||
// this is to fix some sort of bug baking things align in a wrong
|
// this is to fix some sort of bug baking things align in a wrong
|
||||||
// way at startup...
|
// way at startup...
|
||||||
@ -259,18 +345,166 @@ $(document).ready(function(){
|
|||||||
$(document)
|
$(document)
|
||||||
.keydown(makeKeyboardHandler(KEYBOARD_CONFIG))
|
.keydown(makeKeyboardHandler(KEYBOARD_CONFIG))
|
||||||
|
|
||||||
window.MagazineScroller = makeScrollHandler($('.viewer'), {
|
window.MagazineScroller = new IScroll('.viewer', {
|
||||||
hScroll: true,
|
tap: true,
|
||||||
vScroll: false,
|
|
||||||
// XXX still a bit flacky...
|
scrollX: true,
|
||||||
preCallback: function(){stopAnimation($('.magazine'))},
|
scrollY: false,
|
||||||
// XXX...
|
|
||||||
//scrollCallback: function(){ updateNavigator() },
|
scrollbars: true,
|
||||||
//enableMultiClicks: true,
|
fadeScrollbars: true,
|
||||||
transitionEasing: 'cubic-bezier(0.33,0.66,0.66,1)',
|
interactiveScrollbars: true,
|
||||||
}).start()
|
shrinkScrollbars: 'clip',
|
||||||
|
|
||||||
|
//bounce: false,
|
||||||
|
|
||||||
|
zoom: true,
|
||||||
|
// XXX calc these dynamically depending on viewer size/resolution...
|
||||||
|
zoomMin: 0.2,
|
||||||
|
zoomMax: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
window.MULTI_FINGER_RELEASE_TIMEOUT = 50
|
||||||
|
|
||||||
$('.viewer')
|
$('.viewer')
|
||||||
|
.on('tap', function(){
|
||||||
|
// XXX for some reason this does not focus the page clicked
|
||||||
|
// if it's not the current and we are in page view...
|
||||||
|
focusPage(event.target, togglePageView('?') == 'on' ? 'auto' : 'center')
|
||||||
|
|
||||||
|
handleCaption(event.target)
|
||||||
|
})
|
||||||
|
.on('touchstart', function(){
|
||||||
|
// This is here to recover from touching a finger after
|
||||||
|
// lifting it before the timeout...
|
||||||
|
if(event.touches.length > 2){
|
||||||
|
delete window._THIRD_FINGER_LIFTED
|
||||||
|
}
|
||||||
|
if(event.touches.length > 1){
|
||||||
|
delete window._SECOND_FINGER_LIFTED
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('mouseup touchend', function(){
|
||||||
|
var now = Date.now()
|
||||||
|
|
||||||
|
// handle the touchend only if ALL fingers are lifted...
|
||||||
|
if(event.touches != null){
|
||||||
|
// count touches within a timeout to handle multytouch swipes...
|
||||||
|
if(event.touches.length == 2){
|
||||||
|
window._THIRD_FINGER_LIFTED = now
|
||||||
|
} else if(event.touches.length == 1){
|
||||||
|
window._SECOND_FINGER_LIFTED = now
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we are still touching skip any action...
|
||||||
|
if(event.touches.length > 0){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// three finger action...
|
||||||
|
if(window._THIRD_FINGER_LIFTED != null
|
||||||
|
&& now - _THIRD_FINGER_LIFTED <= MULTI_FINGER_RELEASE_TIMEOUT){
|
||||||
|
// first/last pages...
|
||||||
|
if(MagazineScroller.directionX > 0){
|
||||||
|
setTimeout(last, 0)
|
||||||
|
} else if(MagazineScroller.directionX < 0){
|
||||||
|
setTimeout(first, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// two finger action...
|
||||||
|
} else if(window._SECOND_FINGER_LIFTED != null
|
||||||
|
&& now - _SECOND_FINGER_LIFTED <= MULTI_FINGER_RELEASE_TIMEOUT){
|
||||||
|
// next/prev cover...
|
||||||
|
if(MagazineScroller.directionX > 0){
|
||||||
|
setTimeout(nextCover, 0)
|
||||||
|
} else if(MagazineScroller.directionX < 0){
|
||||||
|
setTimeout(prevCover, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// single finger action...
|
||||||
|
} else {
|
||||||
|
if(togglePageView('?') == 'on'){
|
||||||
|
// next/prev page...
|
||||||
|
if(MagazineScroller.directionX > 0){
|
||||||
|
setTimeout(nextPage, 0)
|
||||||
|
} else if(MagazineScroller.directionX < 0){
|
||||||
|
setTimeout(prevPage, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setCurrent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
// XXX do we really need this???
|
||||||
|
window.MagazineScroller
|
||||||
|
.on('flick', function(){
|
||||||
|
if(togglePageView('?') == 'on'){
|
||||||
|
if(this.directionX > 0){
|
||||||
|
setTimeout(nextPage, 0)
|
||||||
|
} else if(this.directionX < 0){
|
||||||
|
setTimeout(prevPage, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
|
window.MagazineScroller
|
||||||
|
.on('scrollCancel', function(){
|
||||||
|
if(togglePageView('?') == 'on'){
|
||||||
|
focusPage(setCurrent(centeredPage()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// XXX is this needed???
|
||||||
|
window.MagazineScroller
|
||||||
|
.on('scrollEnd', function(){
|
||||||
|
// focus page that we end up on...
|
||||||
|
if(!togglePageView('?') == 'on'){
|
||||||
|
setCurrent()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// zooming...
|
||||||
|
// XXX needs testing on device...
|
||||||
|
window.MagazineScroller
|
||||||
|
.on('zoomStart', function(){
|
||||||
|
window._START_SCALE = getMagazineScale()
|
||||||
|
})
|
||||||
|
window.MagazineScroller
|
||||||
|
.on('zoomEnd', function(){
|
||||||
|
var s = getMagazineScale()
|
||||||
|
|
||||||
|
// XXX add issue support...
|
||||||
|
//var state = togglePageView('?')
|
||||||
|
|
||||||
|
// zoom in...
|
||||||
|
if(window._START_SCALE > s){
|
||||||
|
togglePageView('off')
|
||||||
|
|
||||||
|
// zoom out...
|
||||||
|
} else {
|
||||||
|
togglePageView('on')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$('.magazine')
|
||||||
|
.css({
|
||||||
|
'-webkit-transform-origin': '0px 50%',
|
||||||
|
'left': 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.viewer')
|
||||||
|
.on('mouseup tapup', function(){
|
||||||
|
//MagazineScroller.scrollToElement(getVisiblePage()[0], 300, true, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
.on('scrollCancelled', function(){ setCurrentPage() })
|
.on('scrollCancelled', function(){ setCurrentPage() })
|
||||||
.on('shortClick', handleCaption)
|
.on('shortClick', handleCaption)
|
||||||
.on('shortClick', handleClick)
|
.on('shortClick', handleClick)
|
||||||
@ -279,6 +513,7 @@ $(document).ready(function(){
|
|||||||
.on('swipeRight', handleSwipeRight)
|
.on('swipeRight', handleSwipeRight)
|
||||||
.on('swipeUp swipeDown', function(){ togglePageView('off') })
|
.on('swipeUp swipeDown', function(){ togglePageView('off') })
|
||||||
.on('screenReleased', handleScrollRelease)
|
.on('screenReleased', handleScrollRelease)
|
||||||
|
*/
|
||||||
|
|
||||||
.on('pageChanged', updatePageNumberIndicator)
|
.on('pageChanged', updatePageNumberIndicator)
|
||||||
.on('magazineDataLoaded', loadMagazineChrome)
|
.on('magazineDataLoaded', loadMagazineChrome)
|
||||||
@ -299,26 +534,28 @@ $(document).ready(function(){
|
|||||||
|
|
||||||
togglePageView('on')
|
togglePageView('on')
|
||||||
// XXX this still depends on touchSwipe...
|
// XXX this still depends on touchSwipe...
|
||||||
setupNavigator()
|
//setupNavigator()
|
||||||
loadMagazineChrome()
|
//loadMagazineChrome()
|
||||||
setCurrentPage(0)
|
//setCurrentPage(0)
|
||||||
|
|
||||||
toggleThemes('none')
|
//toggleThemes('none')
|
||||||
|
|
||||||
|
|
||||||
setupEditor()
|
//setupEditor()
|
||||||
|
|
||||||
$('.dpi').text(getDPI())
|
$('.dpi').text(getDPI())
|
||||||
|
|
||||||
|
|
||||||
// hide the splash...
|
// hide the splash...
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
//setCurrentPage(0)
|
|
||||||
|
focusPage(0, null, 0)
|
||||||
|
|
||||||
$('.splash').fadeOut()
|
$('.splash').fadeOut()
|
||||||
}, 350)
|
}, 350)
|
||||||
// remove the spinner...
|
// remove the spinner...
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
$('#spinner').spin(false)
|
$('#spinner').spin(false)
|
||||||
|
MagazineScroller.refresh()
|
||||||
}, 500)
|
}, 500)
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -944,7 +1181,6 @@ $(document).ready(function(){
|
|||||||
</div>
|
</div>
|
||||||
<!-- Magazine Viewer (end) ------------------------------------------>
|
<!-- Magazine Viewer (end) ------------------------------------------>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Magazine Chrome (end) -->
|
<!-- Magazine Chrome (end) -->
|
||||||
|
|
||||||
|
|||||||
@ -138,17 +138,23 @@ var KEYBOARD_CONFIG = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Home: firstPage,
|
//Home: firstPage,
|
||||||
End: lastPage,
|
//End: lastPage,
|
||||||
|
Home: function(){ first() },
|
||||||
|
End: function(){ last() },
|
||||||
Left: {
|
Left: {
|
||||||
default: function(){ prevPage() },
|
//default: function(){ prevPage() },
|
||||||
shift: prevBookmark,
|
default: function(){ prev() },
|
||||||
ctrl: prevArticle,
|
//shift: prevBookmark,
|
||||||
|
//ctrl: prevArticle,
|
||||||
|
ctrl: function(){ prevCover() },
|
||||||
},
|
},
|
||||||
Right: {
|
Right: {
|
||||||
default: function(){ nextPage() },
|
//default: function(){ nextPage() },
|
||||||
shift: nextBookmark,
|
default: function(){ next() },
|
||||||
ctrl: nextArticle,
|
//shift: nextBookmark,
|
||||||
|
//ctrl: nextArticle,
|
||||||
|
ctrl: function(){ nextCover() },
|
||||||
},
|
},
|
||||||
Space: {
|
Space: {
|
||||||
default: 'Right',
|
default: 'Right',
|
||||||
|
|||||||
405
layout.js
405
layout.js
@ -4,8 +4,6 @@
|
|||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
var SNAP_TO_PAGES_IN_RIBBON = false
|
|
||||||
|
|
||||||
var DEFAULT_TRANSITION_DURATION = 200
|
var DEFAULT_TRANSITION_DURATION = 200
|
||||||
|
|
||||||
var INNERTIA_SCALE = 0.25
|
var INNERTIA_SCALE = 0.25
|
||||||
@ -23,61 +21,6 @@ var toggleThemes = createCSSClassToggler('.chrome', [
|
|||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
// NOTE: this should not change anything unless the screen size changes...
|
|
||||||
function fitScreenSizedPages(){
|
|
||||||
var s = getPageTargetScale(1)
|
|
||||||
var W = $('.viewer').width()
|
|
||||||
$(SCREEN_SIZED_PAGES).width(W / s)
|
|
||||||
}
|
|
||||||
|
|
||||||
var togglePageFitMode = createCSSClassToggler(
|
|
||||||
'.chrome',
|
|
||||||
'page-fit-to-viewer',
|
|
||||||
function(action){
|
|
||||||
if(action == 'on'){
|
|
||||||
var n = getPageNumber()
|
|
||||||
var scale = getMagazineScale()
|
|
||||||
$(RESIZABLE_PAGES)
|
|
||||||
.width($('.viewer').width() / scale)
|
|
||||||
} else {
|
|
||||||
var n = getPageNumber()
|
|
||||||
$(RESIZABLE_PAGES).width('')
|
|
||||||
}
|
|
||||||
fitScreenSizedPages()
|
|
||||||
setCurrentPage(n)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
var togglePageView = createCSSClassToggler(
|
|
||||||
'.chrome',
|
|
||||||
'full-page-view-mode',
|
|
||||||
function(action){
|
|
||||||
var view = $('.viewer')
|
|
||||||
var page = $('.page')
|
|
||||||
|
|
||||||
// XXX
|
|
||||||
setTransitionDuration($('.magazine'), 0)
|
|
||||||
var n = getPageNumber()
|
|
||||||
|
|
||||||
if(action == 'on'){
|
|
||||||
var scale = getPageTargetScale(1).value
|
|
||||||
setMagazineScale(scale)
|
|
||||||
//unanimated($('.magazine, .viewer'), togglePageFitMode)('on')
|
|
||||||
togglePageFitMode('on')
|
|
||||||
$('.viewer').trigger('fullScreenMode')
|
|
||||||
} else {
|
|
||||||
//unanimated($('.magazine, .viewer'), togglePageFitMode)('off')
|
|
||||||
togglePageFitMode('off')
|
|
||||||
var scale = getPageTargetScale(PAGES_IN_RIBBON).value
|
|
||||||
setMagazineScale(scale)
|
|
||||||
$('.viewer').trigger('ribbonMode')
|
|
||||||
}
|
|
||||||
// NOTE: can't disable transitions on this one because ScrollTo
|
|
||||||
// uses jQuery animation...
|
|
||||||
setCurrentPage(n)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// XXX this is neither final nor usable...
|
// XXX this is neither final nor usable...
|
||||||
function prepareInlineCaptions(){
|
function prepareInlineCaptions(){
|
||||||
$('.page img[title]').each(function(){
|
$('.page img[title]').each(function(){
|
||||||
@ -90,30 +33,12 @@ function prepareInlineCaptions(){
|
|||||||
|
|
||||||
/************************************************** event handlers ***/
|
/************************************************** event handlers ***/
|
||||||
|
|
||||||
// Click
|
|
||||||
// - in full page do the default click, if clicked on other page, select
|
|
||||||
// - in ribbon, open clicked page in full mode
|
|
||||||
function handleClick(evt, data){
|
|
||||||
var target = getPageNumber(data.orig_event.target)
|
|
||||||
if(target != -1){
|
|
||||||
var mag = $('.magazine')
|
|
||||||
|
|
||||||
if(togglePageView('?') == 'on'){
|
|
||||||
setTransitionDuration(mag, DEFAULT_TRANSITION_DURATION)
|
|
||||||
} else {
|
|
||||||
togglePageView('on')
|
|
||||||
}
|
|
||||||
setCurrentPage(target)
|
|
||||||
|
|
||||||
//setTransitionEasing(mag, 'ease')
|
|
||||||
setTransitionEasing(mag, 'cubic-bezier(0.33,0.66,0.66,1)')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Click on caption...
|
// Click on caption...
|
||||||
// XXX add inline caption support...
|
// XXX add inline caption support...
|
||||||
function handleCaption(evt, data){
|
function handleCaption(elem){
|
||||||
elem = $(data.orig_event.target)
|
//elem = $(data.orig_event.target)
|
||||||
|
elem = elem == null ? $('.current.page').find('.caption') : $(elem)
|
||||||
|
|
||||||
if(elem.is('.image-fit-height, .image-fit, .image-with-caption')
|
if(elem.is('.image-fit-height, .image-fit, .image-with-caption')
|
||||||
|| elem.parents('.image-fit-height, .image-fit, .image-with-caption').length > 0){
|
|| elem.parents('.image-fit-height, .image-fit, .image-with-caption').length > 0){
|
||||||
|
|
||||||
@ -136,328 +61,6 @@ function handleCaption(evt, data){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Long Click
|
|
||||||
// - in full page, go to ribbon
|
|
||||||
// - in ribbon, center clicked page
|
|
||||||
function handleLongClick(evt, data){
|
|
||||||
var target = getPageNumber(data.orig_event.target)
|
|
||||||
if(target != -1){
|
|
||||||
var mag = $('.magazine')
|
|
||||||
|
|
||||||
if(togglePageView('?') == 'on'){
|
|
||||||
togglePageView('off')
|
|
||||||
} else {
|
|
||||||
setTransitionDuration(mag, DEFAULT_TRANSITION_DURATION)
|
|
||||||
}
|
|
||||||
setCurrentPage(target)
|
|
||||||
|
|
||||||
//setTransitionEasing(mag, 'ease')
|
|
||||||
setTransitionEasing(mag, 'cubic-bezier(0.33,0.66,0.66,1)')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Swipe Left/Right
|
|
||||||
// - in full page, next/prev page select
|
|
||||||
// - in ribbon, kinetic scroll
|
|
||||||
// - with two fingers, select next/prev article
|
|
||||||
function makeSwipeHandler(actionA, actionB){
|
|
||||||
return function(evt, data){
|
|
||||||
// ribbon mode...
|
|
||||||
if(togglePageView('?') == 'off'){
|
|
||||||
|
|
||||||
// article navigation...
|
|
||||||
if(data.touches >= 2){
|
|
||||||
actionB($('.current.page'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// this makes things snap...
|
|
||||||
if(SNAP_TO_PAGES_IN_RIBBON){
|
|
||||||
setCurrentPage()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return handleScrollRelease(evt, data)
|
|
||||||
}
|
|
||||||
// full page view...
|
|
||||||
var mag = $('.magazine')
|
|
||||||
//setTransitionEasing(mag, 'ease-out')
|
|
||||||
setTransitionEasing(mag, 'cubic-bezier(0.33,0.66,0.66,1)')
|
|
||||||
|
|
||||||
if(data.touches >= 2){
|
|
||||||
actionB($('.current.page'))
|
|
||||||
} else {
|
|
||||||
actionA($('.current.page'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var handleSwipeLeft = makeSwipeHandler(prevPage, prevArticle)
|
|
||||||
var handleSwipeRight = makeSwipeHandler(nextPage, nextArticle)
|
|
||||||
|
|
||||||
|
|
||||||
// XXX
|
|
||||||
GLOBAL_SCROLL_CALLBACK = null
|
|
||||||
|
|
||||||
// Scroll Release
|
|
||||||
// - check bounds and if out center first/last page
|
|
||||||
// - filter out "throw" speeds below threshold
|
|
||||||
// - do inertial scroll (within check bounds)
|
|
||||||
// - snap to pages
|
|
||||||
//
|
|
||||||
// NOTE: this will also handle swipeUp/swopeDown as we do not
|
|
||||||
// explicitly bind them...
|
|
||||||
// NOTE: at this point this ONLY handles horizontal scroll...
|
|
||||||
//
|
|
||||||
// XXX restore all the changed values...
|
|
||||||
// XXX this may kill the ipad...
|
|
||||||
function handleScrollRelease(evt, data){
|
|
||||||
console.log(callback)
|
|
||||||
var callback = GLOBAL_SCROLL_CALLBACK
|
|
||||||
var speed = data.speed.x
|
|
||||||
var pages = $('.page')
|
|
||||||
var mag = $('.magazine')
|
|
||||||
// innertial scroll...
|
|
||||||
// XXX make this generic...
|
|
||||||
//var t = DEFAULT_TRANSITION_DURATION * (1+Math.abs(speed))
|
|
||||||
var t = DEFAULT_TRANSITION_DURATION
|
|
||||||
// XXX this is only horizontal at this point...
|
|
||||||
var at = getElementShift(mag).left
|
|
||||||
var d = MAX_DISTANCE_TO_SCROLL != null ? MAX_DISTANCE_TO_SCROLL : Infinity
|
|
||||||
var s = sign(speed) >= 0 ? 1 : -1
|
|
||||||
var to = (at + (Math.min(Math.abs(t*speed*INNERTIA_SCALE), d) * s))
|
|
||||||
var first = getMagazineOffset(pages.first(), null, 'center')
|
|
||||||
var last = getMagazineOffset(pages.last(), null, 'center')
|
|
||||||
|
|
||||||
var easing = 'cubic-bezier(0.33,0.66,0.66,1)'
|
|
||||||
|
|
||||||
// filter out really small speeds...
|
|
||||||
if(Math.abs(speed) > 0.5){
|
|
||||||
// check bounds...
|
|
||||||
// NOTE: need to cut the distance and time if we are going the
|
|
||||||
// hit the bounds...
|
|
||||||
if(to > first){
|
|
||||||
// trim the time proportionally...
|
|
||||||
var _t = t
|
|
||||||
t = Math.abs(t * ((at-first)/(at-to)))
|
|
||||||
to = first
|
|
||||||
//easing = 'linear'
|
|
||||||
} else if(to < last){
|
|
||||||
// trim the time proportionally...
|
|
||||||
var _t = t
|
|
||||||
t = Math.abs(t * ((at-last)/(at-to)))
|
|
||||||
to = last
|
|
||||||
//easing = 'linear'
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//easing = 'ease-out'
|
|
||||||
}
|
|
||||||
|
|
||||||
animateElementTo(mag, to, t, easing, speed, callback)
|
|
||||||
|
|
||||||
// check scroll bounds...
|
|
||||||
// do not let the user scroll out of view...
|
|
||||||
} else {
|
|
||||||
if(at > first){
|
|
||||||
//animateElementTo(mag, first, DEFAULT_TRANSITION_DURATION, 'ease-in')
|
|
||||||
animateElementTo(mag, first,
|
|
||||||
DEFAULT_TRANSITION_DURATION,
|
|
||||||
easing,
|
|
||||||
null,
|
|
||||||
callback)
|
|
||||||
|
|
||||||
} else if(at < last){
|
|
||||||
//animateElementTo(mag, last, DEFAULT_TRANSITION_DURATION, 'ease-in')
|
|
||||||
animateElementTo(mag, last,
|
|
||||||
DEFAULT_TRANSITION_DURATION,
|
|
||||||
easing,
|
|
||||||
null,
|
|
||||||
callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************* helpers ***/
|
|
||||||
|
|
||||||
function getPageInMagazineOffset(page, scale){
|
|
||||||
if(page == null){
|
|
||||||
page = $('.current.page')
|
|
||||||
} else if(typeof(page) == typeof(7)){
|
|
||||||
page = $($('.page')[page])
|
|
||||||
}
|
|
||||||
|
|
||||||
return page.position().left / (scale == null ? getMagazineScale() : scale)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX there is something here that depends on scale that is either not
|
|
||||||
// compensated, or is over compensated...
|
|
||||||
function getMagazineOffset(page, scale, align){
|
|
||||||
if(page == null){
|
|
||||||
page = $('.current.page')
|
|
||||||
// if no current page get the first...
|
|
||||||
if(page.length == 0){
|
|
||||||
page = $('.page').first()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(scale == null){
|
|
||||||
scale = getMagazineScale()
|
|
||||||
}
|
|
||||||
if(align == null){
|
|
||||||
align = getPageAlign(page)
|
|
||||||
}
|
|
||||||
var mag = $('.magazine')
|
|
||||||
|
|
||||||
// calculate the align offset...
|
|
||||||
if(align == 'left'){
|
|
||||||
var offset = 0
|
|
||||||
|
|
||||||
} else if(align == 'right'){
|
|
||||||
var offset = $('.viewer').width() - page.width()*scale
|
|
||||||
|
|
||||||
// center (default)
|
|
||||||
} else {
|
|
||||||
var offset = $('.viewer').width()/2 - (page.width()/2)*scale
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: this without scaling also represents the inner width of
|
|
||||||
// the viewer...
|
|
||||||
var w = mag.outerWidth(true)
|
|
||||||
// XXX this depends on scale...
|
|
||||||
//var pos = getPageInMagazineOffset(page, scale)
|
|
||||||
var pos = page.position().left//*scale
|
|
||||||
|
|
||||||
var l = 0
|
|
||||||
|
|
||||||
return -((w - w*scale)/2 + pos) + offset
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getPageNumber(page){
|
|
||||||
// a page/element is given explicitly...
|
|
||||||
if(page != null){
|
|
||||||
page = $(page)
|
|
||||||
if(!page.hasClass('page')){
|
|
||||||
page = page.parents('.page')
|
|
||||||
}
|
|
||||||
return $('.page').index(page)
|
|
||||||
}
|
|
||||||
|
|
||||||
// current page index...
|
|
||||||
if(togglePageView('?') == 'on'){
|
|
||||||
return $('.page').index($('.current.page'))
|
|
||||||
|
|
||||||
// get the closest page to view center...
|
|
||||||
// NOTE: this ignores page aligns and only gets the page who's center
|
|
||||||
// is closer to view's center
|
|
||||||
} else {
|
|
||||||
var scale = getMagazineScale()
|
|
||||||
var o = -$($('.magazine')[0]).offset().left - $('.viewer').offset().left
|
|
||||||
var W = $('.viewer').width()
|
|
||||||
var cur = -1
|
|
||||||
var res = $('.page').map(function(i, e){
|
|
||||||
e = $(e)
|
|
||||||
var l = e.position().left
|
|
||||||
var w = e.width()*scale
|
|
||||||
return Math.abs((l+(w/2)) - (o+(W/2)))
|
|
||||||
}).toArray()
|
|
||||||
cur = res.indexOf(Math.min.apply(Math, res))
|
|
||||||
return cur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getMagazineScale(){
|
|
||||||
return getElementScale($('.magazine'))
|
|
||||||
}
|
|
||||||
function setMagazineScale(scale){
|
|
||||||
var mag = $('.magazine')
|
|
||||||
var cur = $('.current.page')
|
|
||||||
if(cur.length == 0){
|
|
||||||
cur = $('.page').first()
|
|
||||||
}
|
|
||||||
|
|
||||||
// center-align ribbon view pages...
|
|
||||||
var align = togglePageView('?') == 'off' ? 'center' : null
|
|
||||||
var left = getMagazineOffset(cur, scale, align)
|
|
||||||
|
|
||||||
setElementTransform(mag, left, scale)
|
|
||||||
|
|
||||||
return mag
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************* actions ***/
|
|
||||||
|
|
||||||
function setCurrentPage(n, use_transitions){
|
|
||||||
if(n == null){
|
|
||||||
n = getPageNumber()
|
|
||||||
}
|
|
||||||
if(typeof(n) != typeof(3)){
|
|
||||||
n = getPageNumber(n)
|
|
||||||
}
|
|
||||||
var l = $('.page').length
|
|
||||||
// normalize the number...
|
|
||||||
n = n < 0 ? l - n : n
|
|
||||||
n = n < -l ? 0 : n
|
|
||||||
n = n >= l ? l - 1 : n
|
|
||||||
use_transitions = use_transitions != null ?
|
|
||||||
use_transitions
|
|
||||||
: USE_TRANSITIONS_FOR_ANIMATION
|
|
||||||
|
|
||||||
$('.current.page').removeClass('current')
|
|
||||||
$($('.page')[n]).addClass('current')
|
|
||||||
|
|
||||||
var cur = $('.current.page')
|
|
||||||
|
|
||||||
// center-align pages in ribbon view...
|
|
||||||
var align = togglePageView('?') == 'off' ? 'center' : null
|
|
||||||
var left = getMagazineOffset(cur, null, align)
|
|
||||||
|
|
||||||
if(use_transitions){
|
|
||||||
setElementTransform($('.magazine'), left)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
animateElementTo($('.magazine'), left)
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.viewer').trigger('pageChanged', n)
|
|
||||||
|
|
||||||
$(':focus').blur()
|
|
||||||
return cur
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function nextPage(page){
|
|
||||||
// XXX is this the right place for this?
|
|
||||||
setTransitionDuration($('.magazine'), DEFAULT_TRANSITION_DURATION)
|
|
||||||
setCurrentPage(getPageNumber(page)+1)
|
|
||||||
}
|
|
||||||
function prevPage(page){
|
|
||||||
// XXX is this the right place for this?
|
|
||||||
setTransitionDuration($('.magazine'), DEFAULT_TRANSITION_DURATION)
|
|
||||||
var n = getPageNumber(page)-1
|
|
||||||
n = n < 0 ? 0 : n
|
|
||||||
setCurrentPage(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function firstPage(){
|
|
||||||
// XXX is this the right place for this?
|
|
||||||
setTransitionDuration($('.magazine'), DEFAULT_TRANSITION_DURATION)
|
|
||||||
setCurrentPage(0)
|
|
||||||
}
|
|
||||||
function lastPage(){
|
|
||||||
// XXX is this the right place for this?
|
|
||||||
setTransitionDuration($('.magazine'), DEFAULT_TRANSITION_DURATION)
|
|
||||||
setCurrentPage(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* vim:set ts=4 sw=4 : */
|
* vim:set ts=4 sw=4 : */
|
||||||
|
|||||||
814
magazine.js
814
magazine.js
@ -55,6 +55,12 @@ var FULL_HISTORY_ENABLED = false
|
|||||||
// if true, use CSS3 transforms to scroll, of false, use left.
|
// if true, use CSS3 transforms to scroll, of false, use left.
|
||||||
var USE_TRANSFORM = true
|
var USE_TRANSFORM = true
|
||||||
|
|
||||||
|
var SCROLL_TIME = 400
|
||||||
|
|
||||||
|
var BOUNCE_LENGTH = 10
|
||||||
|
var BOUNCE_TIME_DIVIDER = 5
|
||||||
|
|
||||||
|
|
||||||
// list of css classes of pages that will not allow page fitting.
|
// list of css classes of pages that will not allow page fitting.
|
||||||
var NO_RESIZE_CLASSES = [
|
var NO_RESIZE_CLASSES = [
|
||||||
'no-resize',
|
'no-resize',
|
||||||
@ -119,20 +125,23 @@ var _PAGE_VIEW
|
|||||||
// - single page mode (.page-view-mode)
|
// - single page mode (.page-view-mode)
|
||||||
// - thumbnail/ribbon mode
|
// - thumbnail/ribbon mode
|
||||||
var togglePageView = createCSSClassToggler(
|
var togglePageView = createCSSClassToggler(
|
||||||
'.viewer',
|
'.chrome',
|
||||||
'page-view-mode',
|
'page-view-mode',
|
||||||
// post-change callback...
|
// post-change callback...
|
||||||
function(action){
|
function(action){
|
||||||
if(action == 'on'){
|
if(action == 'on'){
|
||||||
fitNPages(1, !FIT_PAGE_TO_VIEW)
|
fitNPages(1, !FIT_PAGE_TO_VIEW)
|
||||||
|
MagazineScroller.options.momentum = false
|
||||||
_PAGE_VIEW = true
|
_PAGE_VIEW = true
|
||||||
} else {
|
} else {
|
||||||
fitNPages(PAGES_IN_RIBBON)
|
fitNPages(PAGES_IN_RIBBON)
|
||||||
|
MagazineScroller.options.momentum = true
|
||||||
_PAGE_VIEW = false
|
_PAGE_VIEW = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// this will simply update the current view...
|
// this will simply update the current view...
|
||||||
function updateView(){
|
function updateView(){
|
||||||
return togglePageView(togglePageView('?'))
|
return togglePageView(togglePageView('?'))
|
||||||
@ -142,6 +151,68 @@ function updateView(){
|
|||||||
|
|
||||||
/********************************************************* helpers ***/
|
/********************************************************* helpers ***/
|
||||||
|
|
||||||
|
function centeredPageNumber(){
|
||||||
|
var scale = getMagazineScale()
|
||||||
|
var o = -$($('.magazine')[0]).offset().left - $('.viewer').offset().left
|
||||||
|
var W = $('.viewer').width()
|
||||||
|
var cur = -1
|
||||||
|
var res = $('.page').map(function(i, e){
|
||||||
|
e = $(e)
|
||||||
|
var l = e.position().left
|
||||||
|
var w = e.width()*scale
|
||||||
|
return Math.abs((l+(w/2)) - (o+(W/2)))
|
||||||
|
}).toArray()
|
||||||
|
cur = res.indexOf(Math.min.apply(Math, res))
|
||||||
|
return cur
|
||||||
|
}
|
||||||
|
function centeredPage(){
|
||||||
|
return $('.page').eq(centeredPageNumber())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function visiblePages(partial){
|
||||||
|
var W = $('.viewer').width()
|
||||||
|
var scale = getMagazineScale()
|
||||||
|
|
||||||
|
return $('.page').filter(function(_, page){
|
||||||
|
page = $(page)
|
||||||
|
|
||||||
|
// XXX this calculates the offset from the document rather than the magazine...
|
||||||
|
var o = page.offset().left
|
||||||
|
|
||||||
|
// page out of view (right)...
|
||||||
|
if(o >= W){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var w = page.width() * scale
|
||||||
|
|
||||||
|
if(o < 0){
|
||||||
|
// partial left...
|
||||||
|
if(partial && o + w > 0){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// page out of view (left)...
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// partial right...
|
||||||
|
if(partial && W - o < w){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// page compleately in view...
|
||||||
|
if(W - o >= w){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: we should not get here but just in case...
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function isPageResizable(page){
|
function isPageResizable(page){
|
||||||
if(page == null){
|
if(page == null){
|
||||||
page = $('.current.page')
|
page = $('.current.page')
|
||||||
@ -223,35 +294,64 @@ function getMagazineTitle(){
|
|||||||
|
|
||||||
|
|
||||||
function getMagazineScale(){
|
function getMagazineScale(){
|
||||||
return getElementScale($('.scaler'))
|
return getElementScale($('.magazine'))
|
||||||
}
|
}
|
||||||
function setPageScale(scale){
|
function setMagazineScale(scale){
|
||||||
return setElementTransform($('.scaler'), null, scale)
|
var mag = $('.magazine')
|
||||||
|
var cur = $('.current.page')
|
||||||
|
if(cur.length == 0){
|
||||||
|
cur = $('.page').first()
|
||||||
|
}
|
||||||
|
|
||||||
|
// center-align ribbon view pages...
|
||||||
|
var align = togglePageView('?') == 'off' ? 'center' : null
|
||||||
|
var left = getMagazineOffset(cur, scale, align)
|
||||||
|
|
||||||
|
//setElementTransform(mag, left, scale)
|
||||||
|
MagazineScroller.zoom(scale)
|
||||||
|
|
||||||
|
return mag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: if page is not given get the current page number...
|
// NOTE: if page is not given get the current page number...
|
||||||
function getPageNumber(page){
|
function getPageNumber(page){
|
||||||
if(page == null){
|
// a page/element is given explicitly...
|
||||||
page = $('.current.page')
|
if(page != null){
|
||||||
} else {
|
|
||||||
page = $(page)
|
page = $(page)
|
||||||
|
if(!page.hasClass('page')){
|
||||||
|
page = page.parents('.page')
|
||||||
|
}
|
||||||
|
return $('.page').index(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
// current page index...
|
||||||
|
if(togglePageView('?') == 'on'){
|
||||||
|
return $('.page').index($('.current.page'))
|
||||||
|
|
||||||
|
// get the closest page to view center...
|
||||||
|
// NOTE: this ignores page aligns and only gets the page who's center
|
||||||
|
// is closer to view's center
|
||||||
|
} else {
|
||||||
|
return centeredPageNumber()
|
||||||
}
|
}
|
||||||
return $('.page').index(page)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE: negative values will yield results from the tail...
|
// NOTE: negative values will yield results from the tail...
|
||||||
function getPageAt(n){
|
function getPageAt(n){
|
||||||
var page = $('.page')
|
var page = $('.page')
|
||||||
if(n < 0){
|
if(n < 0){
|
||||||
n = page.length + n
|
n = page.length + n
|
||||||
}
|
}
|
||||||
return $(page[n])
|
return $(page).eq(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
function shiftMagazineTo(offset){
|
function shiftMagazineTo(offset){
|
||||||
setElementTransform($('.magazine'), offset)
|
MagazineScroller.scrollTo(offset, 0, 200)
|
||||||
|
//setElementTransform($('.magazine'), offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX this is almost the same as getElementScale...
|
// XXX this is almost the same as getElementScale...
|
||||||
@ -386,373 +486,374 @@ function viewResizeHandler(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// swipe state handler
|
|
||||||
// this handles single and double finger swipes and dragging
|
|
||||||
// while draggign this triggers magazineDragging event on the viewer...
|
|
||||||
// NOTE: this will trigger 'magazineDragging' event on the viewer on
|
|
||||||
// each call while dragging...
|
|
||||||
// XXX for some reason with finger count of 3 and greater, touchSwipe
|
|
||||||
// dies on android...
|
|
||||||
function makeSwipeHandler(){
|
|
||||||
var pages
|
|
||||||
var cur
|
|
||||||
var n
|
|
||||||
var scale
|
|
||||||
var mag
|
|
||||||
var pos
|
|
||||||
var viewer = $('.viewer')
|
|
||||||
|
|
||||||
return function(evt, phase, direction, distance, duration, fingers){
|
|
||||||
|
|
||||||
if(phase == 'start'){
|
|
||||||
// NOTE: this is used with the "unanimated" trick, we will make
|
|
||||||
// dragging real-time...
|
|
||||||
togglePageDragging('on')
|
|
||||||
|
|
||||||
// setup the data for the drag...
|
|
||||||
pages = $('.page')
|
|
||||||
cur = $('.current.page')
|
|
||||||
n = pages.index(cur)
|
|
||||||
scale = getMagazineScale()
|
|
||||||
mag = $('.magazine')
|
|
||||||
pos = $('.navigator .bar .indicator')
|
|
||||||
|
|
||||||
// XXX make this drag pages that are larger than view before dragging outside...
|
|
||||||
} else if(phase=='move'
|
|
||||||
// see if wee need to drag the page and allways drag the ribbon...
|
|
||||||
&& (DRAG_FULL_PAGE || !_PAGE_VIEW)
|
|
||||||
&& (direction=='left' || direction=='right')){
|
|
||||||
if(direction == 'left'){
|
|
||||||
shiftMagazineTo(-cur.position().left/scale - distance/scale)
|
|
||||||
} else if(direction == 'right') {
|
|
||||||
shiftMagazineTo(-cur.position().left/scale + distance/scale)
|
|
||||||
}
|
|
||||||
viewer.trigger('magazineDragging')
|
|
||||||
|
|
||||||
} else if(phase == 'cancel'){
|
|
||||||
togglePageDragging('off')
|
|
||||||
setCurrentPage()
|
|
||||||
|
|
||||||
} else if(phase =='end' ){
|
|
||||||
togglePageDragging('off')
|
|
||||||
// see which page is closer to the middle of the screen and set it...
|
|
||||||
// do this based on how much we dragged...
|
|
||||||
var p = Math.ceil((distance/scale)/cur.width())
|
|
||||||
|
|
||||||
// prev page...
|
|
||||||
if(direction == 'right'){
|
|
||||||
// 2 fingers moves to closest article...
|
|
||||||
if(fingers == 2){
|
|
||||||
prevArticle()
|
|
||||||
// 3+ fingers moves to bookmark...
|
|
||||||
} else if(fingers >= 3){
|
|
||||||
prevBookmark()
|
|
||||||
} else {
|
|
||||||
setCurrentPage(Math.max(n-p, 0))
|
|
||||||
}
|
|
||||||
// next page...
|
|
||||||
} else if(direction == 'left'){
|
|
||||||
if(fingers == 2){
|
|
||||||
nextArticle()
|
|
||||||
} else if(fingers >= 3){
|
|
||||||
nextBookmark()
|
|
||||||
} else {
|
|
||||||
setCurrentPage(Math.min(n+p, pages.length-1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************** layout ***/
|
/********************************************************** layout ***/
|
||||||
|
|
||||||
|
// mode can be:
|
||||||
|
// - viewer
|
||||||
|
// - content
|
||||||
|
//
|
||||||
|
// XXX should this calculate offset????
|
||||||
|
function fitPagesTo(mode, cur, time, scale){
|
||||||
|
mode = mode == null ? 'content' : mode
|
||||||
|
cur = cur == null ? centeredPageNumber() : cur
|
||||||
|
time = time == null ? 0 : time
|
||||||
|
scale = scale == null ? getMagazineScale() : scale
|
||||||
|
|
||||||
|
// fit to content...
|
||||||
|
if(mode == 'content'){
|
||||||
|
var target_width = 'auto'
|
||||||
|
var target_height = 'auto'
|
||||||
|
|
||||||
|
// fit to viewer...
|
||||||
|
} else if(mode == 'viewer'){
|
||||||
|
var viewer = $('.viewer')
|
||||||
|
var W = viewer.width()
|
||||||
|
var H = viewer.height()
|
||||||
|
// XXX is this a good way to sample content size???
|
||||||
|
var content = $('.content')
|
||||||
|
var w = content.width()
|
||||||
|
var h = content.height()
|
||||||
|
|
||||||
|
// need to calc width only...
|
||||||
|
if(W/H > w/h){
|
||||||
|
s = H/h
|
||||||
|
w = W/s
|
||||||
|
h = h
|
||||||
|
|
||||||
|
// need to calc height only...
|
||||||
|
} else if(W/H > w/h){
|
||||||
|
s = W/w
|
||||||
|
h = H/s
|
||||||
|
w = w
|
||||||
|
|
||||||
|
// set both width and height to defaults (content and page ratios match)...
|
||||||
|
} else {
|
||||||
|
s = W/h
|
||||||
|
h = h
|
||||||
|
w = w
|
||||||
|
}
|
||||||
|
var target_width = w
|
||||||
|
var target_height = h
|
||||||
|
|
||||||
|
// bad mode...
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var pages = $('.page')
|
||||||
|
var offset = 0
|
||||||
|
|
||||||
|
$(RESIZABLE_PAGES)
|
||||||
|
.each(function(_, e){
|
||||||
|
var E = $(e)
|
||||||
|
var w = target_width == 'auto' ? E.find('.content').width() : target_width
|
||||||
|
var h = target_height == 'auto' ? E.find('.content').height() : target_height
|
||||||
|
|
||||||
|
// offset...
|
||||||
|
if(pages.index(e) < cur){
|
||||||
|
offset += (E.width() - w)
|
||||||
|
}
|
||||||
|
// offset half the current page...
|
||||||
|
if(pages.index(e) == cur){
|
||||||
|
// XXX to be more accurate we can use distance from page
|
||||||
|
// center rather than 1/2...
|
||||||
|
offset += ((E.width() - w)/2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(time <= 0){
|
||||||
|
e.style.width = w
|
||||||
|
e.style.height = h
|
||||||
|
} else {
|
||||||
|
E.animate({
|
||||||
|
width: w,
|
||||||
|
height: h,
|
||||||
|
}, time, 'linear')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//$(NON_RESIZABLE_PAGES).width('auto')
|
||||||
|
$(NON_RESIZABLE_PAGES)
|
||||||
|
.each(function(_, e){
|
||||||
|
e.style.width = 'auto'
|
||||||
|
})
|
||||||
|
|
||||||
|
MagazineScroller.scrollBy(offset*scale, 0, time)
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
MagazineScroller.refresh()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: if n is not given then it defaults to 1
|
// NOTE: if n is not given then it defaults to 1
|
||||||
// NOTE: if n > 1 and fit_to_content is not given it defaults to true
|
// NOTE: if n > 1 and fit_to_content is not given it defaults to true
|
||||||
// NOTE: if n is 1 then fit_to_content bool argument controls wether:
|
// NOTE: if n is 1 then fit_to_content bool argument controls wether:
|
||||||
// - the page will be stretched to viewer (false)
|
// - the page will be stretched to viewer (false)
|
||||||
// - or to content (true)
|
// - or to content (true)
|
||||||
|
// XXX need to align/focus the corrent page...
|
||||||
|
// case:
|
||||||
|
// when current page is pushed off center by a resized page...
|
||||||
function fitNPages(n, fit_to_content){
|
function fitNPages(n, fit_to_content){
|
||||||
if(n == null){
|
n = n == null ? 1 : n
|
||||||
n = 1
|
|
||||||
}
|
|
||||||
if(n > 1 && fit_to_content == null){
|
|
||||||
fit_to_content = true
|
|
||||||
}
|
|
||||||
var view = $('.viewer')
|
|
||||||
if(USE_REAL_PAGE_SIZES){
|
|
||||||
var page = $(RESIZABLE_PAGES)
|
|
||||||
} else {
|
|
||||||
var page = $('.page')
|
|
||||||
}
|
|
||||||
var content = $('.content')
|
|
||||||
var cur = $('.current.page')
|
|
||||||
|
|
||||||
var W = view.width()
|
|
||||||
var H = view.height()
|
|
||||||
var cW = content.width()
|
|
||||||
var cH = content.height()
|
|
||||||
|
|
||||||
// to compensate for transitions, no data sampling should be beyound
|
|
||||||
// this point, as we will start changing things next...
|
|
||||||
|
|
||||||
var scale = getPageTargetScale(n, fit_to_content)
|
var scale = getPageTargetScale(n, fit_to_content)
|
||||||
// cache some data...
|
if(n == 1){
|
||||||
var target_width = scale.width
|
fitPagesTo('viewer')
|
||||||
var target_height = scale.height
|
|
||||||
var rW = scale.result_width
|
|
||||||
|
|
||||||
// NOTE: we need to calculate the offset as the actual widths during
|
|
||||||
// the animation are not correct... so just looking at .position()
|
|
||||||
// will be counterproductive...
|
|
||||||
if(!USE_REAL_PAGE_SIZES && fit_to_content){
|
|
||||||
var offset = rW * getPageNumber()-1
|
|
||||||
} else {
|
} else {
|
||||||
// calculate the target offset...
|
fitPagesTo('content')
|
||||||
if(USE_REAL_PAGE_SIZES){
|
|
||||||
var rpages = $(RESIZABLE_PAGES+', .current.page')
|
|
||||||
} else {
|
|
||||||
var rpages = page
|
|
||||||
}
|
|
||||||
var i = rpages.index(cur)
|
|
||||||
var offset = rW * i-1
|
|
||||||
// now do the no-resize elements...
|
|
||||||
if(USE_REAL_PAGE_SIZES){
|
|
||||||
var nrpages = $(NON_RESIZABLE_PAGES+', .current.page')
|
|
||||||
i = nrpages.index(cur)
|
|
||||||
nrpages.splice(i)
|
|
||||||
nrpages.each(function(_, e){
|
|
||||||
offset += $(e).children('.content').width()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
MagazineScroller.zoom(scale)
|
||||||
// align the magazine...
|
MagazineScroller.refresh()
|
||||||
if(USE_REAL_PAGE_SIZES){
|
|
||||||
if(!isPageResizable(cur)){
|
|
||||||
var align = getPageAlign(cur)
|
|
||||||
|
|
||||||
// center align if explicitly required or if we are in a ribbon...
|
|
||||||
if(n > 1 || align == 'center'){
|
|
||||||
rW = cur.children('.content').width()
|
|
||||||
|
|
||||||
// align left...
|
|
||||||
} else if(align == 'left'){
|
|
||||||
rW = $('.viewer').width()/scale
|
|
||||||
|
|
||||||
// align right...
|
|
||||||
} else if(align == 'right'){
|
|
||||||
var v = $('.viewer')
|
|
||||||
rW = (v.width()/scale/2 - (v.width()/scale-cur.width()))*2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now do the actual modification...
|
|
||||||
|
|
||||||
// do the scaling...
|
|
||||||
setElementScale($('.scaler'), scale)
|
|
||||||
|
|
||||||
// XXX for some reason setting size "auto" will first shrink the whole
|
|
||||||
// page to 0 and then instantly set it to the correct size...
|
|
||||||
//page
|
|
||||||
// .width(target_width)
|
|
||||||
// .height(target_height)
|
|
||||||
//if(USE_REAL_PAGE_SIZES){
|
|
||||||
// $(NON_RESIZABLE_PAGES).width('auto')
|
|
||||||
//}
|
|
||||||
|
|
||||||
// NOTE: we only need the .scaler animated, the rest just plays havoc with
|
|
||||||
// the transition...
|
|
||||||
// XXX this still jumps to offset on left/right aligned pages but 1) on
|
|
||||||
// fast transitions it is not noticable and 2) it is way better than
|
|
||||||
// the effect that was before...
|
|
||||||
unanimated($('.page, .content, .magazine'), function(){
|
|
||||||
// NOTE: this is not done directly as to avoid artifacts asociated with
|
|
||||||
// setting 'auto' to all the elements, which makes them first slowly
|
|
||||||
// shrink down to 0 and then appear correctly sized in an instant.
|
|
||||||
page.each(function(_, e){
|
|
||||||
if(target_width == 'auto'){
|
|
||||||
e.style.width = $(e).find('.content').width()
|
|
||||||
e.style.height = $(e).find('.content').height()
|
|
||||||
} else {
|
|
||||||
e.style.width = target_width
|
|
||||||
e.style.height = target_height
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if(USE_REAL_PAGE_SIZES){
|
|
||||||
//$(NON_RESIZABLE_PAGES).width('auto')
|
|
||||||
$(NON_RESIZABLE_PAGES).each(function(_, e){
|
|
||||||
e.style.width = 'auto'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// fix position...
|
|
||||||
setCurrentPage(null, offset, rW)
|
|
||||||
}, 200)()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************* actions ***/
|
/********************************************************* actions ***/
|
||||||
|
|
||||||
// NOTE: "width" is used ONLY to center the page.
|
// Set the .current class...
|
||||||
// NOTE: if n is not given it will be set to current page number
|
//
|
||||||
// NOTE: if width is not given it will be set to current page width.
|
// page can be:
|
||||||
// NOTE: n can be:
|
// - null - centered page in view
|
||||||
// - page number
|
// - number - page number/index
|
||||||
// - page element
|
// - page - a page element
|
||||||
// NOTE: this will fire a 'pageChanged(n)' event on the viewer each time
|
// - elem - resolves to a containing page element
|
||||||
// it is called...
|
function setCurrent(page){
|
||||||
// NOTE: this now supports negative indexes to count pages from the end...
|
var pages = $('.page')
|
||||||
function setCurrentPage(n, offset, width){
|
page = page == null ? pages.eq(centeredPageNumber())
|
||||||
var page = $('.page')
|
: typeof(page) == typeof(123) ? pages.eq(Math.max(0, Math.min(page, pages.length-1)))
|
||||||
// setup n and cur...
|
: !$(page).eq(0).hasClass('page') ? $(page).eq(0).parents('.page').eq(0)
|
||||||
// no n is given, do the defaultdance
|
: $(page).eq(0)
|
||||||
if(n == null){
|
|
||||||
var cur = $('.current.page')
|
|
||||||
// no current page...
|
|
||||||
// try to land on the magazine cover...
|
|
||||||
if(cur.length == 0){
|
|
||||||
cur = $('.magazine > .cover')
|
|
||||||
}
|
|
||||||
// try the first cover...
|
|
||||||
if(cur.length == 0){
|
|
||||||
cur = $('.cover.page')
|
|
||||||
}
|
|
||||||
// try first page...
|
|
||||||
if(cur.length == 0){
|
|
||||||
cur = page.first()
|
|
||||||
}
|
|
||||||
// no pages to work with...
|
|
||||||
if(cur.length == 0){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n = page.index(cur)
|
|
||||||
|
|
||||||
// n is a number...
|
if(page.hasClass('current')){
|
||||||
} else if(typeof(n) == typeof(1)) {
|
return page
|
||||||
// normalize n...
|
|
||||||
if(n >= page.length){
|
|
||||||
n = page.length-1
|
|
||||||
} else if(-n > page.length){
|
|
||||||
n = 0
|
|
||||||
}
|
|
||||||
var cur = getPageAt(n)
|
|
||||||
|
|
||||||
// n is an element, likely...
|
|
||||||
} else {
|
|
||||||
var cur = $(n)
|
|
||||||
n = $('.page').index(cur)
|
|
||||||
//n = page.index(cur)
|
|
||||||
}
|
|
||||||
|
|
||||||
// default width...
|
|
||||||
if(width == null){
|
|
||||||
width = cur.width()
|
|
||||||
if(USE_REAL_PAGE_SIZES && togglePageView('?') == 'on'){
|
|
||||||
var align = getPageAlign(cur)
|
|
||||||
var scale = getMagazineScale()
|
|
||||||
if(align == 'center'){
|
|
||||||
width = cur.width()
|
|
||||||
|
|
||||||
} else if(align == 'left'){
|
|
||||||
width = $('.viewer').width()/scale
|
|
||||||
|
|
||||||
} else if(align == 'right'){
|
|
||||||
var v = $('.viewer')
|
|
||||||
width = (v.width()/scale/2 - (v.width()/scale-cur.width()))*2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the class...
|
||||||
$('.current.page').removeClass('current')
|
$('.current.page').removeClass('current')
|
||||||
cur.addClass('current')
|
return page.addClass('current')
|
||||||
|
|
||||||
// NOTE: this will be wrong during a transition, that's why we
|
|
||||||
// can pass the pre-calculated offset as an argument...
|
|
||||||
shiftMagazineTo(-(offset == null ?
|
|
||||||
cur.position()['left']/getMagazineScale()
|
|
||||||
: offset))
|
|
||||||
|
|
||||||
// center the pages correctly...
|
|
||||||
// NOTE: this is the main reason we need width, and we can get it
|
|
||||||
// pre-calculated because of ongoing transitions make it
|
|
||||||
// pointless to read it...
|
|
||||||
$('.magazine').css({
|
|
||||||
'margin-left': -width/2
|
|
||||||
})
|
|
||||||
|
|
||||||
$('.viewer').trigger('pageChanged', n)
|
|
||||||
|
|
||||||
return cur
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function goToMagazineCover(){
|
// Focus a page...
|
||||||
return setCurrentPage(0)
|
//
|
||||||
|
// NOTE: n is a setCurrent(..) compatible value...
|
||||||
|
// NOTE: if n is out of bounds (n < 0 | n >= length) this will focus the
|
||||||
|
// first/last page and bounce...
|
||||||
|
function focusPage(n, align, time){
|
||||||
|
// XXX the default needs to depend on the scale...
|
||||||
|
align = align == null ? 'auto' : align
|
||||||
|
time = time == null ? SCROLL_TIME : time
|
||||||
|
|
||||||
|
var page = setCurrent(n)
|
||||||
|
var pages = $('.page')
|
||||||
|
|
||||||
|
align = align == 'auto' ? getPageAlign(page) : align
|
||||||
|
|
||||||
|
// magazine offset...
|
||||||
|
var m = page.position().left
|
||||||
|
// base value for 'left' align...
|
||||||
|
var o = 0
|
||||||
|
|
||||||
|
var w = page.width() * getMagazineScale()
|
||||||
|
var W = $('.viewer').width()
|
||||||
|
|
||||||
|
if(align != 'left'){
|
||||||
|
|
||||||
|
// right...
|
||||||
|
if(align == 'right'){
|
||||||
|
o = W - w
|
||||||
|
|
||||||
|
// center / default...
|
||||||
|
} else {
|
||||||
|
o = W/2 - w/2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compensate for first/last page align to screen (optional???)...
|
||||||
|
var offset = page.offset().left
|
||||||
|
var f = pages.first().offset().left
|
||||||
|
if(f + o - offset >= 0){
|
||||||
|
o = 0
|
||||||
|
m = 0
|
||||||
|
}
|
||||||
|
var last = $('.page').last()
|
||||||
|
var l = last.offset().left
|
||||||
|
if(l + o - offset <= W - w){
|
||||||
|
o = 0
|
||||||
|
m = last.position().left + last.width()*getMagazineScale() - W
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the bounce...
|
||||||
|
if(time > 0){
|
||||||
|
var i = pages.index(page)
|
||||||
|
var l = pages.length
|
||||||
|
if(n < 0){
|
||||||
|
o += BOUNCE_LENGTH*getMagazineScale()
|
||||||
|
time /= BOUNCE_TIME_DIVIDER
|
||||||
|
}
|
||||||
|
if(n >= l){
|
||||||
|
o -= BOUNCE_LENGTH*getMagazineScale()
|
||||||
|
time /= BOUNCE_TIME_DIVIDER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this does not care about the zoom...
|
||||||
|
MagazineScroller.scrollTo(-m + o, 0, time)
|
||||||
|
|
||||||
|
return page
|
||||||
}
|
}
|
||||||
function goToMagazineEnd(){
|
|
||||||
return setCurrentPage(-1)
|
|
||||||
|
// Focus first/last page...
|
||||||
|
//
|
||||||
|
// NOTE: if we are already at the first/last page, do a bounce...
|
||||||
|
function first(align){
|
||||||
|
// visually show that we are at the start...
|
||||||
|
if($('.magazine').offset().left >= 0){
|
||||||
|
return focusPage(-1, align)
|
||||||
|
}
|
||||||
|
return focusPage(0, align)
|
||||||
}
|
}
|
||||||
function goToArticleCover(){
|
function last(align){
|
||||||
// try and get the actual first cover...
|
var mag = $('.magazine')
|
||||||
var cover = $('.current.page')
|
var l = mag.offset().left
|
||||||
.parents('.article')
|
var end = mag.offset().left + mag.width()*getMagazineScale()
|
||||||
.find('.cover.page')
|
var i = $('.page').length-1
|
||||||
.first()
|
|
||||||
if(cover.length == 0){
|
if(end <= $('.viewer').width()+1){
|
||||||
// no cover, get the first page...
|
return focusPage(i+1, align)
|
||||||
return setCurrentPage(
|
}
|
||||||
$('.current.page')
|
return focusPage(i, align)
|
||||||
.parents('.article')
|
}
|
||||||
.find('.page')
|
|
||||||
.first())
|
|
||||||
|
// Focus a page of class cls adjacent to current in direction...
|
||||||
|
//
|
||||||
|
// direction can be:
|
||||||
|
// - 'next' - next page
|
||||||
|
// - 'prev' - previous page
|
||||||
|
//
|
||||||
|
// If cls is not given, then all pages (.page) are considered.
|
||||||
|
//
|
||||||
|
// NOTE: if we are already at the first/last page and direction is
|
||||||
|
// prev/next resp. then do a bounce...
|
||||||
|
function step(direction, cls, align){
|
||||||
|
cls = cls == null ? '' : cls
|
||||||
|
|
||||||
|
var page = visiblePages(true).filter('.current').eq(0)
|
||||||
|
var pages = $('.page')
|
||||||
|
|
||||||
|
if(page.length == 0){
|
||||||
|
page = setCurrent()
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = pages.index(page)
|
||||||
|
var l = pages.length
|
||||||
|
|
||||||
|
// if we are at the first/last page do the bounce dance...
|
||||||
|
// bounce first...
|
||||||
|
if(i == 0 && direction == 'prev'){
|
||||||
|
return focusPage(-1, align)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bounce last...
|
||||||
|
if(i == l-1 && direction == 'next'){
|
||||||
|
return focusPage(l, align)
|
||||||
|
}
|
||||||
|
|
||||||
|
var to = page[direction+'All']('.page'+cls)
|
||||||
|
|
||||||
|
// if we have no pages on the same level, to a deeper search...
|
||||||
|
if(to.length == 0){
|
||||||
|
if(direction == 'next'){
|
||||||
|
to = pages.slice(i+1).filter('.page'+cls).first()
|
||||||
|
} else {
|
||||||
|
to = pages.slice(0, i).filter('.page'+cls).last()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// still no candidates, then we can't do a thing...
|
||||||
|
if(to.length == 0){
|
||||||
|
to = page
|
||||||
|
}
|
||||||
|
|
||||||
|
return focusPage(to.eq(0), align)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Focus next/prev page shorthands...
|
||||||
|
//
|
||||||
|
function nextPage(cls, align){ return step('next', cls, align) }
|
||||||
|
function prevPage(cls, align){ return step('prev', cls, align) }
|
||||||
|
|
||||||
|
|
||||||
|
// Focus next/prev cover page shorthands...
|
||||||
|
//
|
||||||
|
function nextCover(cls, align){
|
||||||
|
cls = cls == null ? '' : cls
|
||||||
|
return step('next', '.cover'+cls, align)
|
||||||
|
}
|
||||||
|
function prevCover(cls, align){
|
||||||
|
cls = cls == null ? '' : cls
|
||||||
|
return step('prev', '.cover'+cls, align)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Move the view a screen width (.viewer) left/right...
|
||||||
|
//
|
||||||
|
// NOTE: if we are at magazine start/end and try to move left/right resp.
|
||||||
|
// this will do a bounce...
|
||||||
|
function nextScreen(time){
|
||||||
|
time = time == null ? SCROLL_TIME : time
|
||||||
|
var W = $('.viewer').width()
|
||||||
|
var mag = $('.magazine')
|
||||||
|
var o = mag.position().left
|
||||||
|
var w = mag.width()*getMagazineScale()
|
||||||
|
|
||||||
|
// we reached the end...
|
||||||
|
if(w + o < 2*W){
|
||||||
|
// NOTE: we use focusPage(..) to handle stuff like bounces...
|
||||||
|
return focusPage($('.page').length)
|
||||||
|
}
|
||||||
|
|
||||||
|
MagazineScroller.scrollTo(o-W, 0, time)
|
||||||
|
return setCurrent()
|
||||||
|
}
|
||||||
|
function prevScreen(time){
|
||||||
|
time = time == null ? SCROLL_TIME : time
|
||||||
|
var W = $('.viewer').width()
|
||||||
|
var o = $('.magazine').position().left
|
||||||
|
|
||||||
|
// we reached the start...
|
||||||
|
if(-o < W){
|
||||||
|
// NOTE: we use focusPage(..) to handle stuff like bounces...
|
||||||
|
return focusPage(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
MagazineScroller.scrollTo(o+W, 0, time)
|
||||||
|
return setCurrent()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mode-aware next/prev high-level actions...
|
||||||
|
//
|
||||||
|
// Supported modes:
|
||||||
|
// - page view - focus next/prev page
|
||||||
|
// - magazine view - view next/prev screen
|
||||||
|
//
|
||||||
|
function next(){
|
||||||
|
if(togglePageView('?') == 'on'){
|
||||||
|
return nextPage()
|
||||||
} else {
|
} else {
|
||||||
return setCurrentPage(cover)
|
return nextScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function prev(){
|
||||||
|
if(togglePageView('?') == 'on'){
|
||||||
function nextPage(){
|
return prevPage()
|
||||||
var pages = $('.page')
|
} else {
|
||||||
var cur = $('.current.page')
|
return prevScreen()
|
||||||
return setCurrentPage(Math.min(pages.index(cur)+1, pages.length-1))
|
|
||||||
}
|
|
||||||
function prevPage(){
|
|
||||||
var pages = $('.page')
|
|
||||||
var cur = $('.current.page')
|
|
||||||
return setCurrentPage(Math.max(pages.index(cur)-1, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function nextArticle(){
|
|
||||||
var cur = $('.current.page').parents('.article')
|
|
||||||
// we are at the magazine cover...
|
|
||||||
if(cur.length == 0){
|
|
||||||
return setCurrentPage(
|
|
||||||
$('.magazine .article .page:first-child').first())
|
|
||||||
}
|
}
|
||||||
// just find the next one...
|
|
||||||
var articles = $('.magazine .article')
|
|
||||||
return setCurrentPage(
|
|
||||||
$(articles[Math.min(articles.index(cur)+1, articles.length-1)])
|
|
||||||
.find('.page')
|
|
||||||
.first())
|
|
||||||
}
|
|
||||||
function prevArticle(){
|
|
||||||
var cur = $('.current.page').parents('.article')
|
|
||||||
// we are at the magazine cover...
|
|
||||||
if(cur.length == 0){
|
|
||||||
//return $('.current.page')
|
|
||||||
return setCurrentPage()
|
|
||||||
}
|
|
||||||
// just find the prev one...
|
|
||||||
var articles = $('.magazine .article')
|
|
||||||
return setCurrentPage(
|
|
||||||
$(articles[Math.max(articles.index(cur)-1, 0)])
|
|
||||||
.find('.page')
|
|
||||||
.first())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -809,6 +910,7 @@ function clearBookmarks(){
|
|||||||
// NOTE: this will trigger the folowing events on the viewer:
|
// NOTE: this will trigger the folowing events on the viewer:
|
||||||
// - bookmarkAdded(n)
|
// - bookmarkAdded(n)
|
||||||
// - bookmarkRemoved(n)
|
// - bookmarkRemoved(n)
|
||||||
|
// XXX rewrite...
|
||||||
function toggleBookmark(n){
|
function toggleBookmark(n){
|
||||||
if(n == null){
|
if(n == null){
|
||||||
n = getPageNumber()
|
n = getPageNumber()
|
||||||
@ -841,21 +943,13 @@ function toggleBookmark(n){
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextBookmark(){
|
function nextBookmark(cls, align){
|
||||||
var pages = $('.page')
|
cls = cls == null ? '' : cls
|
||||||
pages = $(pages.splice(getPageNumber()+1))
|
return step('next', '.bookmark'+cls, align)
|
||||||
page = pages.children('.bookmark').first().parents('.page')
|
|
||||||
if(page.length != 0){
|
|
||||||
return setCurrentPage(page)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
function prevBookmark(){
|
function prevBookmark(cls, align){
|
||||||
var pages = $('.page')
|
cls = cls == null ? '' : cls
|
||||||
pages.splice(getPageNumber())
|
return step('prev', '.bookmark'+cls, align)
|
||||||
page = pages.children('.bookmark').last().parents('.page')
|
|
||||||
if(page.length != 0){
|
|
||||||
return setCurrentPage(page)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user