Skip to content
Browse files

Merge pull request #66 from joseph/transitions

Smoother transitions and animation in more browsers. Fixes #2.
  • Loading branch information...
2 parents 0ecfbe9 + b62ab96 commit d905119499ab40f7245f0bd6a58bf92b6f8eb751 @joseph joseph committed
Showing with 241 additions and 268 deletions.
  1. +22 −6 src/compat/env.js
  2. +11 −13 src/core/component.js
  3. +21 −0 src/core/events.js
  4. +6 −12 src/core/reader.js
  5. +15 −0 src/core/styles.js
  6. +26 −8 src/dimensions/columns.js
  7. +26 −20 src/flippers/scroller.js
  8. +95 −191 src/flippers/slider.js
  9. +15 −5 styles/monocore.css
  10. +4 −13 test/flippers/index.html
View
28 src/compat/env.js
@@ -214,6 +214,11 @@ Monocle.Env = function () {
// TEST FOR OPTIONAL CAPABILITIES
+ // Does it do CSS transitions?
+ ["supportsTransition", function () {
+ result(css.supportsPropertyWithAnyPrefix('transition'))
+ }],
+
// Can we find nodes in a document with an XPath?
//
["supportsXPath", testForFunction("document.evaluate")],
@@ -275,10 +280,14 @@ Monocle.Env = function () {
// Webkit-based browsers put floated elements in the wrong spot when
// columns are used -- they appear way down where they would be if there
// were no columns. Presumably the float positions are calculated before
- // the columns. A bug has been lodged.
+ // the columns. A bug has been lodged, and it's fixed in recent WebKits.
//
- // FIXME: Detection not yet implemented.
- ["floatsIgnoreColumns", testNotYetImplemented(false)],
+ ["floatsIgnoreColumns", function () {
+ if (!Monocle.Browser.is.WebKit) { return result(false); }
+ match = navigator.userAgent.match(/AppleWebKit\/([\d\.]+)/);
+ if (!match) { return result(false); }
+ return result(match[1] < "534.30");
+ }],
// The latest engines all agree that if a body is translated leftwards,
// its scrollWidth is shortened. But some older WebKits (notably iOS4)
@@ -311,8 +320,6 @@ Monocle.Env = function () {
// In iOS, the frame is clipped by overflow:hidden, so this doesn't seem to
// be a problem.
//
- // TODO: Is there a way to detect this?
- //
["relativeIframeExpands", function () {
result(navigator.userAgent.indexOf("Android 2") >= 0);
}],
@@ -333,7 +340,6 @@ Monocle.Env = function () {
// min-width is set, it's more difficult to recognise 1 page components,
// so we generally don't want to force it unless we have to.
//
- // FIXME: This is not detecting correctly for iOS3.
["forceColumns", function () {
loadTestFrame(function (fr) {
var bd = fr.contentDocument.body;
@@ -387,6 +393,16 @@ Monocle.Env = function () {
loadTestFrame(function (fr) {
result(fr.parentNode.scrollWidth > testFrameSize);
});
+ }],
+
+ // For some reason, iOS MobileSafari sometimes loses track of a page after
+ // slideOut -- it thinks it has an x-translation of 0, rather than -768 or
+ // whatever. So the page gets "stuck" there, until it is given a non-zero
+ // x-translation. The workaround is to set a non-zero duration on the jumpIn,
+ // which seems to force WebKit to recalculate the x of the page. Weird, yeah.
+ //
+ ["stickySlideOut", function () {
+ result(Monocle.Browser.is.MobileSafari);
}]
];
View
24 src/core/component.js
@@ -38,24 +38,22 @@ Monocle.Component = function (book, id, index, chapters, source) {
// Makes this component the active component for the pageDiv. There are
// several strategies for this (see loadFrame).
//
- // Some strategies are time-consuming (and usually asynchronous), some are
- // not. When the component has been loaded into the pageDiv's frame, the
- // callback will be invoked with the pageDiv and this component as arguments.
+ // When the component has been loaded into the pageDiv's frame, the callback
+ // will be invoked with the pageDiv and this component as arguments.
//
function applyTo(pageDiv, callback) {
var evtData = { 'page': pageDiv, 'source': p.source };
pageDiv.m.reader.dispatchEvent('monocle:componentchanging', evtData);
- return loadFrame(
- pageDiv,
- function () {
- setupFrame(
- pageDiv,
- pageDiv.m.activeFrame,
- function () { callback(pageDiv, API) }
- );
- }
- );
+ var onLoaded = function () {
+ setupFrame(
+ pageDiv,
+ pageDiv.m.activeFrame,
+ function () { callback(pageDiv, API) }
+ );
+ }
+
+ Monocle.defer(function () { loadFrame(pageDiv, onLoaded); });
}
View
21 src/core/events.js
@@ -277,6 +277,27 @@ Monocle.Events.listenForTap = function (elem, fn, activeClass) {
Monocle.Events.deafenForTap = Monocle.Events.deafenForContact;
+// Listen for the next transition-end event on the given element, call
+// the function, then deafen.
+//
+// Returns a function that can be used to cancel the listen early.
+//
+Monocle.Events.afterTransition = function (elem, fn) {
+ var evtName = "transitionend";
+ if (Monocle.Browser.is.WebKit) {
+ evtName = 'webkitTransitionEnd';
+ } else if (Monocle.Browser.is.Opera) {
+ evtName = 'oTransitionEnd';
+ }
+ var l = null, cancel = null;
+ l = function () { fn(); cancel(); }
+ cancel = function () { Monocle.Events.deafen(elem, evtName, l); }
+ Monocle.Events.listen(elem, evtName, l);
+ return cancel;
+}
+
+
+
// BROWSERHACK: iOS touch events on iframes are busted. The TouchMonitor,
// transposes touch events on underlying iframes onto the elements that
// sit above them. It's a massive hack.
View
18 src/core/reader.js
@@ -191,7 +191,7 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) {
function clampStylesheets(customStylesheet) {
var defCSS = k.DEFAULT_STYLE_RULES;
if (Monocle.Browser.env.floatsIgnoreColumns) {
- defCSS += "html#RS\\:monocle * { float: none !important; }";
+ defCSS.push("html#RS\\:monocle * { float: none !important; }");
}
p.defaultStyles = addPageStyles(defCSS, false);
if (customStylesheet) {
@@ -306,7 +306,7 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) {
recalculateDimensions(true);
dispatchEvent("monocle:resize");
},
- k.durations.RESIZE_DELAY
+ k.RESIZE_DELAY
);
}
@@ -746,13 +746,7 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) {
return API;
}
-Monocle.Reader.durations = {
- RESIZE_DELAY: 100
-}
-Monocle.Reader.abortMessage = {
- CLASSNAME: "monocleAbortMessage",
- TEXT: "Your browser does not support this technology."
-}
+Monocle.Reader.RESIZE_DELAY = 100;
Monocle.Reader.DEFAULT_SYSTEM_ID = 'RS:monocle'
Monocle.Reader.DEFAULT_CLASS_PREFIX = 'monelem_'
Monocle.Reader.DEFAULT_STYLE_RULES = [
@@ -763,9 +757,9 @@ Monocle.Reader.DEFAULT_STYLE_RULES = [
"overflow: visible !important;" +
"}",
"html#RS\\:monocle body {" +
- "margin: 0;"+
- "border: none;"+
- "padding: 0;"+
+ "margin: 0 !important;"+
+ "border: none !important;"+
+ "padding: 0 !important;"+
"-webkit-text-size-adjust: none;" +
"}",
"html#RS\\:monocle body * {" +
View
15 src/core/styles.js
@@ -57,6 +57,21 @@ Monocle.Styles = {
}
s.MozTransform = s.OTransform = s.transform = "translateY("+y+")";
return y;
+ },
+
+
+ transitionFor: function (elem, prop, duration, timing, delay) {
+ var tProps = Monocle.Browser.css.toDOMProps('transition');
+ var pProps = Monocle.Browser.css.toCSSProps(prop);
+ timing = timing || "linear";
+ delay = (delay || 0)+"ms";
+ for (var i = 0, ii = tProps.length; i < ii; ++i) {
+ var t = "none";
+ if (duration) {
+ t = [pProps[i], duration+"ms", timing, delay].join(" ");
+ }
+ elem.style[tProps[i]] = t;
+ }
}
}
View
34 src/dimensions/columns.js
@@ -9,6 +9,9 @@ Monocle.Dimensions.Columns = function (pageDiv) {
width: 0
}
+ // Logically, forceColumn browsers can't have a gap, because that would
+ // make the minWidth > 200%. But how much greater? Not worth the effort.
+ k.GAP = Monocle.Browser.env.forceColumns ? 0 : 20;
function update(callback) {
setColumnWidth();
@@ -32,9 +35,9 @@ Monocle.Dimensions.Columns = function (pageDiv) {
p.width = pdims.width;
var rules = Monocle.Styles.rulesToString(k.STYLE["columned"]);
- rules += Monocle.Browser.css.toCSSDeclaration('column-width', p.width+'px');
- rules += Monocle.Browser.css.toCSSDeclaration('column-gap', 0);
- rules += Monocle.Browser.css.toCSSDeclaration('transform', "translateX(0)");
+ rules += Monocle.Browser.css.toCSSDeclaration('column-width', pdims.col+'px');
+ rules += Monocle.Browser.css.toCSSDeclaration('column-gap', k.GAP+'px');
+ rules += Monocle.Browser.css.toCSSDeclaration('transform', 'translateX(0)');
if (Monocle.Browser.env.forceColumns && ce.scrollHeight > pdims.height) {
rules += Monocle.Styles.rulesToString(k.STYLE['column-force']);
@@ -74,6 +77,9 @@ Monocle.Dimensions.Columns = function (pageDiv) {
var w = Math.max(bd.scrollWidth, de.scrollWidth);
+ // Add one because the final column doesn't have right gutter.
+ w += k.GAP;
+
if (!Monocle.Browser.env.widthsIgnoreTranslate && p.page.m.offset) {
w += p.page.m.offset;
}
@@ -83,7 +89,11 @@ Monocle.Dimensions.Columns = function (pageDiv) {
function pageDimensions() {
var elem = p.page.m.sheafDiv;
- return { width: elem.clientWidth, height: elem.clientHeight }
+ return {
+ col: elem.clientWidth,
+ width: elem.clientWidth + k.GAP,
+ height: elem.clientHeight
+ }
}
@@ -97,16 +107,25 @@ Monocle.Dimensions.Columns = function (pageDiv) {
}
- function translateToLocus(locus) {
+ // Moves the columned element to the offset implied by the locus.
+ //
+ // The 'transition' argument is optional, allowing the translation to be
+ // animated. If not given, no change is made to the columned element's
+ // transition property.
+ //
+ function translateToLocus(locus, transition) {
var offset = locusToOffset(locus);
p.page.m.offset = offset;
- translateToOffset(offset);
+ translateToOffset(offset, transition);
return offset;
}
- function translateToOffset(offset) {
+ function translateToOffset(offset, transition) {
var ce = columnedElement();
+ if (transition) {
+ Monocle.Styles.affix(ce, "transition", transition);
+ }
Monocle.Styles.affix(ce, "transform", "translateX(-"+offset+"px)");
}
@@ -188,5 +207,4 @@ Monocle.Dimensions.Columns.STYLE = {
}
}
-
Monocle.pieceLoaded("dimensions/columns");
View
46 src/flippers/scroller.js
@@ -4,7 +4,7 @@ Monocle.Flippers.Scroller = function (reader, setPageFn) {
var k = API.constants = API.constructor;
var p = API.properties = {
pageCount: 1,
- duration: 200
+ duration: 300
}
@@ -58,23 +58,24 @@ Monocle.Flippers.Scroller = function (reader, setPageFn) {
function frameToLocus(locus) {
+ if (locus.boundarystart || locus.boundaryend) { return; }
p.turning = true;
-
- var x = page().m.dimensions.locusToOffset(locus);
- var bdy = page().m.activeFrame.contentDocument.body;
- if (false && typeof WebKitTransitionEvent != "undefined") {
- bdy.style.webkitTransition = "-webkit-transform " +
- p.duration + "ms ease-out 0ms";
- bdy.style.webkitTransform = "translateX(-"+x+"px)";
- Monocle.Events.listen(
- bdy,
- 'webkitTransitionEnd',
- function () {
- p.turning = false;
- p.reader.dispatchEvent('monocle:turn');
- }
- );
+ var dims = page().m.dimensions;
+ var fr = page().m.activeFrame;
+ var bdy = fr.contentDocument.body;
+ var anim = true;
+ if (p.activeComponent != fr.m.component) {
+ // No animation.
+ p.activeComponent = fr.m.component;
+ dims.translateToLocus(locus, "none");
+ Monocle.defer(turned);
+ } else if (Monocle.Browser.env.supportsTransition) {
+ // Native animation.
+ dims.translateToLocus(locus, p.duration+"ms ease-in 0ms");
+ Monocle.Events.afterTransition(bdy, turned);
} else {
+ // Old-school JS animation.
+ var x = dims.locusToOffset(locus);
var finalX = 0 - x;
var stamp = (new Date()).getTime();
var frameRate = 40;
@@ -86,21 +87,26 @@ Monocle.Flippers.Scroller = function (reader, setPageFn) {
(new Date()).getTime() - stamp > p.duration ||
Math.abs(currX - finalX) <= Math.abs((currX + step) - finalX)
) {
- clearTimeout(bdy.animInterval)
Monocle.Styles.setX(bdy, finalX);
- p.turning = false;
- p.reader.dispatchEvent('monocle:turn');
+ turned();
} else {
Monocle.Styles.setX(bdy, destX);
currX = destX;
+ setTimeout(stepFn, frameRate);
}
p.currX = destX;
}
- bdy.animInterval = setInterval(stepFn, frameRate);
+ stepFn();
}
}
+ function turned() {
+ p.turning = false;
+ p.reader.dispatchEvent('monocle:turn');
+ }
+
+
// THIS IS THE CORE API THAT ALL FLIPPERS MUST PROVIDE.
API.pageCount = p.pageCount;
API.addPage = addPage;
View
286 src/flippers/slider.js
@@ -14,6 +14,7 @@ Monocle.Flippers.Slider = function (reader) {
function initialize() {
p.reader = reader;
+ p.reader.listen("monocle:componentchanging", showWaitControl);
}
@@ -22,7 +23,7 @@ Monocle.Flippers.Slider = function (reader) {
// BROWSERHACK: Firefox 4 is prone to beachballing on the first page turn
// unless a zeroed translateX has been applied to the page div.
- Monocle.Styles.setX(pageDiv, "0px");
+ Monocle.Styles.setX(pageDiv, 0);
}
@@ -105,13 +106,12 @@ Monocle.Flippers.Slider = function (reader) {
function setPage(pageDiv, locus, callback) {
- ensureWaitControl();
p.reader.getBook().setOrLoadPageAt(
pageDiv,
locus,
function (locus) {
pageDiv.m.dimensions.translateToLocus(locus);
- if (callback) { callback(); }
+ Monocle.defer(callback);
}
);
}
@@ -144,8 +144,10 @@ Monocle.Flippers.Slider = function (reader) {
}
p.turnData.lifting = true;
+ var place = getPlace();
+
if (dir == k.FORWARDS) {
- if (getPlace().onLastPageOfBook()) {
+ if (place.onLastPageOfBook()) {
p.reader.dispatchEvent(
'monocle:boundaryend',
{
@@ -158,7 +160,7 @@ Monocle.Flippers.Slider = function (reader) {
}
onGoingForward(boxPointX);
} else if (dir == k.BACKWARDS) {
- if (getPlace().onFirstPageOfBook()) {
+ if (place.onFirstPageOfBook()) {
p.reader.dispatchEvent(
'monocle:boundarystart',
{
@@ -199,7 +201,6 @@ Monocle.Flippers.Slider = function (reader) {
checkPoint(boxPointX);
p.turnData.releasing = true;
- showWaitControl(lowerPage());
if (dir == k.FORWARDS) {
if (
@@ -245,19 +246,18 @@ Monocle.Flippers.Slider = function (reader) {
function onGoingBackward(x) {
var lp = lowerPage(), up = upperPage();
- showWaitControl(up);
- setPage( // set lower to "the page before upper"
+
+ // set lower to "the page before upper"
+ setPage(
lp,
getPlace(up).getLocus({ direction: k.BACKWARDS }),
function () {
- jumpOut( // move lower off the screen
- lp,
- function () {
- flipPages(); // flip lower to upper
- lifted(x);
- hideWaitControl(up);
- }
- );
+ // flip lower to upper, ready to slide in from left
+ flipPages();
+ // move lower off the screen to the left
+ jumpOut(lp, function () {
+ lifted(x);
+ });
}
);
}
@@ -266,19 +266,16 @@ Monocle.Flippers.Slider = function (reader) {
function afterGoingForward() {
var up = upperPage(), lp = lowerPage();
if (p.interactive) {
- showWaitControl(up);
- showWaitControl(lp);
- setPage( // set upper (off screen) to current
+ // set upper (off screen) to current
+ setPage(
up,
getPlace().getLocus({ direction: k.FORWARDS }),
function () {
- // move upper back onto screen
- // then set lower to next and reset turn
+ // move upper back onto screen, then set lower to next and reset turn
jumpIn(up, function () { prepareNextPage(announceTurn); });
}
);
} else {
- showWaitControl(lp);
flipPages();
jumpIn(up, function () { prepareNextPage(announceTurn); });
}
@@ -287,12 +284,14 @@ Monocle.Flippers.Slider = function (reader) {
function afterGoingBackward() {
if (p.interactive) {
- setPage( // set lower page to current
+ // set lower page to current
+ setPage(
lowerPage(),
getPlace().getLocus(),
function () {
- flipPages(); // flip lower to upper
- // set lower to next and reset turn:
+ // flip lower to upper
+ flipPages();
+ // set lower to next and reset turn
prepareNextPage(announceTurn);
}
);
@@ -309,10 +308,7 @@ Monocle.Flippers.Slider = function (reader) {
function afterCancellingBackward() {
flipPages(); // flip upper to lower
- jumpIn( // move lower back onto screen
- lowerPage(),
- function () { prepareNextPage(resetTurnData); }
- );
+ jumpIn(lowerPage(), function () { prepareNextPage(resetTurnData); });
}
@@ -344,196 +340,95 @@ Monocle.Flippers.Slider = function (reader) {
function resetTurnData() {
- hideWaitControl(upperPage());
- hideWaitControl(lowerPage());
+ hideWaitControl();
p.turnData = {};
}
function setX(elem, x, options, callback) {
- var duration;
+ var duration, transition;
if (!options.duration) {
duration = 0;
} else {
- duration = parseInt(options['duration']);
+ duration = parseInt(options.duration);
}
- if (typeof(x) == "number") { x = x + "px"; }
+ if (Monocle.Browser.env.supportsTransition) {
+ Monocle.Styles.transitionFor(
+ elem,
+ 'transform',
+ duration,
+ options.timing,
+ options.delay
+ );
- // BROWSERHACK: WEBKIT (transitions & transition events)
- if (typeof WebKitTransitionEvent != "undefined") {
- if (duration) {
- // Accelerate durations if we have a backlog of work...
- transition = '-webkit-transform';
- transition += ' ' + duration + "ms";
- transition += ' ' + (options['timing'] || 'linear');
- transition += ' ' + (options['delay'] || 0) + 'ms';
- } else {
- transition = 'none';
- }
- elem.style.webkitTransition = transition;
if (Monocle.Browser.env.supportsTransform3d) {
- elem.style.webkitTransform = "translate3d("+x+",0,0)";
+ Monocle.Styles.affix(elem, 'transform', 'translate3d('+x+'px,0,0)');
} else {
- elem.style.webkitTransform = "translateX("+x+")";
+ Monocle.Styles.affix(elem, 'transform', 'translateX('+x+'px)');
}
- // BROWSERHACK: NON-WEBKIT (no transitions)
- } else if (duration > 0) {
- // Exit any existing transition loop.
- clearTimeout(elem.setXTransitionInterval)
-
- var stamp = (new Date()).getTime();
- var frameRate = 40;
- var finalX = parseInt(x);
- var currX = getX(elem);
- var step = (finalX - currX) * (frameRate / duration);
- var stepFn = function () {
- var destX = currX + step;
- if (
- (new Date()).getTime() - stamp > duration ||
- Math.abs(currX - finalX) <= Math.abs((currX + step) - finalX)
- ) {
- clearTimeout(elem.setXTransitionInterval);
- Monocle.Styles.setX(elem, finalX);
- if (elem.setXTCB) {
- elem.setXTCB();
- }
+ if (typeof callback == "function") {
+ if (duration) {
+ Monocle.Events.afterTransition(elem, callback);
} else {
- Monocle.Styles.setX(elem, destX);
- currX = destX;
+ Monocle.defer(callback);
}
}
-
- elem.setXTransitionInterval = setInterval(stepFn, frameRate);
- } else {
- Monocle.Styles.setX(elem, x);
- }
-
- if (elem.setXTCB) {
- Monocle.Events.deafen(elem, 'webkitTransitionEnd', elem.setXTCB);
- elem.setXTCB = null;
- }
-
- elem.setXTCB = function () {
- if (callback) { callback(); }
- }
-
- var sX = getX(elem);
- if (!duration || sX == parseInt(x)) {
- elem.setXTCB();
- } else {
- Monocle.Events.listen(elem, 'webkitTransitionEnd', elem.setXTCB);
- }
- }
-
-
- // This is a replacement setX with better cross-browser support.
- // Two problems keep it from going in:
- //
- // * It removes the simulated transition support required for Moz less than 4.
- // * getX is still not cross-browser, so it sometimes fails to detect when
- // a transition has already occurred. Resulting in freezes.
- /*
- function setX(elem, x, options, callback) {
- var duration, transition;
-
- // NB: if the browser lacks transition support, moves immediately to x.
- if (!Monocle.Browser.env.supportsTransitions) {
- duration = 0;
- } else if (!options.duration) {
- duration = 0;
} else {
- duration = parseInt(options['duration']);
- }
-
- if (typeof(x) == "number") { x = x + "px"; }
-
- if (duration) {
- transition = duration + "ms";
- transition += ' ' + (options['timing'] || 'linear');
- transition += ' ' + (options['delay'] || 0) + 'ms';
- } else {
- transition = "none";
- }
-
- if (elem.setXTCB) {
- Monocle.Events.deafen(elem, 'webkitTransitionEnd', elem.setXTCB);
- Monocle.Events.deafen(elem, 'transitionend', elem.setXTCB);
- elem.setXTCB = null;
- }
-
- elem.setXTCB = function () {
- if (callback) { callback(); }
- }
-
- // Set the styles
- elem.dom.setBetaStyle('transition', transition);
- if (Monocle.Browser.env.supportsTransform3d) {
- elem.dom.setBetaStyle('transform', 'translate3d('+x+',0,0)');
- } else {
- elem.dom.setBetaStyle('transform', 'translateX('+x+')');
- }
-
- if (!duration) {
- elem.setXTCB();
- } else {
- Monocle.Events.listen(elem, 'webkitTransitionEnd', elem.setXTCB);
- Monocle.Events.listen(elem, 'transitionend', elem.setXTCB);
- }
- }
- */
-
-
- function getX(elem) {
- if (typeof WebKitCSSMatrix == "object") {
- var matrix = window.getComputedStyle(elem).webkitTransform;
- matrix = new WebKitCSSMatrix(matrix);
- return matrix.m41;
- } else {
- var prop = elem.style.MozTransform;
- if (!prop || prop == "") { return 0; }
- return parseFloat((/translateX\((\-?.*)px\)/).exec(prop)[1]) || 0;
+ // Old-school JS animation.
+ elem.currX = elem.currX || 0;
+ var completeTransition = function () {
+ elem.currX = x;
+ Monocle.Styles.setX(elem, x);
+ if (typeof callback == "function") { callback(); }
+ }
+ if (!duration) {
+ completeTransition();
+ } else {
+ var stamp = (new Date()).getTime();
+ var frameRate = 40;
+ var step = (x - elem.currX) * (frameRate / duration);
+ var stepFn = function () {
+ var destX = elem.currX + step;
+ var timeElapsed = ((new Date()).getTime() - stamp) >= duration;
+ var pastDest = (destX > x && elem.currX < x) ||
+ (destX < x && elem.currX > x);
+ if (timeElapsed || pastDest) {
+ completeTransition();
+ } else {
+ Monocle.Styles.setX(elem, destX);
+ elem.currX = destX;
+ setTimeout(stepFn, frameRate);
+ }
+ }
+ stepFn();
+ }
}
}
function jumpIn(pageDiv, callback) {
- Monocle.defer(function () {
- setX(pageDiv, 0, { duration: 0 }, callback);
- });
+ opts = { duration: (Monocle.Browser.env.stickySlideOut ? 1 : 0) }
+ setX(pageDiv, 0, opts, callback);
}
function jumpOut(pageDiv, callback) {
- Monocle.defer(function () {
- setX(pageDiv, 0 - pageDiv.offsetWidth, { duration: 0 }, callback);
- });
+ setX(pageDiv, 0 - pageDiv.offsetWidth, { duration: 0 }, callback);
}
// NB: Slides are always done by the visible upper page.
function slideIn(callback) {
- var slideOpts = {
- duration: k.durations.SLIDE,
- timing: 'ease-in'
- };
- Monocle.defer(function () {
- setX(upperPage(), 0, slideOpts, callback);
- });
+ setX(upperPage(), 0, slideOpts(), callback);
}
function slideOut(callback) {
- var slideOpts = {
- duration: k.durations.SLIDE,
- timing: 'ease-in'
- };
- Monocle.defer(function () {
- setX(upperPage(), 0 - upperPage().offsetWidth, slideOpts, callback);
- });
+ setX(upperPage(), 0 - upperPage().offsetWidth, slideOpts(), callback);
}
@@ -541,12 +436,21 @@ Monocle.Flippers.Slider = function (reader) {
setX(
upperPage(),
Math.min(0, cursorX - upperPage().offsetWidth),
- { duration: duration || k.durations.FOLLOW_CURSOR },
+ { duration: duration || k.FOLLOW_DURATION },
callback
);
}
+ function slideOpts() {
+ var opts = { timing: 'ease-in', duration: 320 }
+ var now = (new Date()).getTime();
+ if (p.lastSlide && now - p.lastSlide < 1500) { opts.duration *= 0.5; }
+ p.lastSlide = now;
+ return opts;
+ }
+
+
function ensureWaitControl() {
if (p.waitControl) { return; }
p.waitControl = {
@@ -558,17 +462,20 @@ Monocle.Flippers.Slider = function (reader) {
}
- function showWaitControl(page) {
- var ctrl = p.reader.dom.find('flippers_slider_wait', page.m.pageIndex);
- ctrl.style.visibility = "visible";
+ function showWaitControl() {
+ ensureWaitControl();
+ p.reader.dom.find('flippers_slider_wait', 0).style.opacity = 1;
+ p.reader.dom.find('flippers_slider_wait', 1).style.opacity = 1;
}
- function hideWaitControl(page) {
- var ctrl = p.reader.dom.find('flippers_slider_wait', page.m.pageIndex);
- ctrl.style.visibility = "hidden";
+ function hideWaitControl() {
+ ensureWaitControl();
+ p.reader.dom.find('flippers_slider_wait', 0).style.opacity = 0;
+ p.reader.dom.find('flippers_slider_wait', 1).style.opacity = 0;
}
+
// THIS IS THE CORE API THAT ALL FLIPPERS MUST PROVIDE.
API.pageCount = p.pageCount;
API.addPage = addPage;
@@ -590,9 +497,6 @@ Monocle.Flippers.Slider = function (reader) {
Monocle.Flippers.Slider.DEFAULT_PANELS_CLASS = Monocle.Panels.TwoPane;
Monocle.Flippers.Slider.FORWARDS = 1;
Monocle.Flippers.Slider.BACKWARDS = -1;
-Monocle.Flippers.Slider.durations = {
- SLIDE: 220,
- FOLLOW_CURSOR: 100
-}
+Monocle.Flippers.Slider.FOLLOW_DURATION = 100;
Monocle.pieceLoaded('flippers/slider');
View
20 styles/monocore.css
@@ -91,11 +91,21 @@ div.monelem_controls_panel_expanded {
div.monelem_flippers_slider_wait {
position: absolute;
- right: 2px;
- top: 2px;
- width: 20px;
- height: 20px;
+ right: 0px;
+ top: 0px;
+ width: 92px;
+ height: 112px;
background-repeat: no-repeat;
+ -webkit-background-size: 100%;
+ -moz-background-size: 100%;
+ background-size: 100%;
+}
+
+@media screen and (max-width: 640px) {
+ div.monelem_flippers_slider_wait {
+ width: 61px;
+ height: 75px;
+ }
}
@@ -111,5 +121,5 @@ div.monelem_panels_imode_toggleIcon {
}
div.monelem_flippers_slider_wait {
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABj0lEQVR42rXUu0uCURjHcaEyiCiJBmkQHEJHQboNITiE1OiSCA0NEkRIUhQtJhQkFpFLS9CFkiK6DZG5iLk0BA1B0FgRNNcf8PZ94LzyYl7K7MCHc57nnPfHOQ6aNE2rq7oHlhyhUMiBCaxhHQvwodFwxo4k8tiE7VugNNVmGhuYQQBzqveKcXjxARlORJCSQGNYL04QhqXMzV24wgP6ii5yXQikaMEbhqQuEzaPDJ7VnECT2luRWgKlaMAhwrJZIfATYZlVnYYfKezBogfacWuqMtRvtwOfqv24wzLM0tMDZxEz%2FXLIjfAOt9TGwDj80qgh9AVjah3AkSzOEawxMIs8DpCDS5pLfwi8wCCG0a4%2FeRTJGsJsuESzBAk90IpTOPXDiURCy2QyI3DE43FN5mg0KvO0ITCGRWMYCptT2NcPy4d6ICbBTE1fne%2FBDazlAluxjS10VHmqB%2FfwSl0ysOgZjwiizdA3w41VnMEj%2FUqBxtB%2B7OIJWRwjp9YRdMq5HwcW3aobA%2Bgqc%2Bz%2F%2F7G%2FAORsH%2Flqgs9VAAAAAElFTkSuQmCC);
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAABwCAMAAACkX%2BcnAAAB0VBMVEUAAACDg4OEhISFhYWGhoaHh4eIiIiJiIiJiYmKioqLi4uMjIyNjY2Ojo6Pj4%2BQkJCRkZGSkpKTk5OUlJSVlZWWlpaXl5eYmJiZmZmampqbm5ucnJycnJ2dnZ2dnZ6dnZ%2Benp6enp%2Bfn5%2Bfn6CgoKCgoKGhoKChoaGioqKjo6OkpKSlpaWmpaWmpqaoqKiqqqqrq6usrKytra2urq6wsLCxsbGzs7O0tLS0tLW1tbW1tba1tbe2tri4uLi4uLm4uLq6ury7u7y8vLy8vL28vL%2B9vb2%2Bvr6%2Bvr%2B%2Fv7%2B%2Fv8HAwMDAwMLAwMPBwcPCwsPExMTExMXFxcXGxsbHx8fIyMjJycrOztDOztHPz9DPz9HR0dTS0tTT09TT09XU1NbU1NfV1dfW1tjW1tnX19fX19rY2Nra2tva2tzd3eDe3t7f39%2Fh4eHi4uLl5enn5%2Bnp6ezp6e3q6u3q6u7r6%2B7r6%2B%2Fs7O%2Fs7PDt7fDt7fHu7vHu7vLv7%2B%2Fv7%2FLv7%2FPw8PDw8PPw8PTx8fTx8fXy8vXy8vbz8%2Fbz8%2Ff09Pf09Pj19fj19fn29vn39%2Fn39%2Fr4%2BPr4%2BPv5%2Bfv6%2Bvv6%2Bvz7%2B%2Fz7%2B%2F38%2FP39%2Ff39%2Ff7%2B%2Fv7%2B%2Fv%2F%2F%2F%2F%2BHSJEZAAAAAXRSTlMAQObYZgAAA5dJREFUaN61lk1uE0EQhd%2BrsQlREAgkFkQKLJByteQU3IIdd2OBYIFASFmAFLurWPT0uOfXme6aWUXy6PNL9XPXR3z6DSI93wQ0GkHjzweapM%2B%2Btn8SMAERPzKQQKN7IDRhD2APgkbumucvXp24T3s%2BH47H7%2F9U1AxmpvaDzV5IUMBfD0CbQXYPly93K%2BEiwneqphpMVc3e7p492zciQhGKNN2bX%2F42shJOEQFIQgAKgfgdpvFz7d58%2FPO4Fn5PiggBAUkAYhoUMJipwU5vhsfjWjhESMTsBChQVVMDYICadfjD4VAAFyGYZVcN7Vzar4iP6frkd5RuLjG7WlCFwdSy4ICtPlBAKJLNhYBq6HKf8IHrx4J7IQX5maqFLHeC3yrWwyEiFACSzlTVVFNuzQZTAG%2BrLoQwVT1kubvGF4wlVj2vi2isuvWrbiXJIUISYKwL5qpuWgbvXQHxSCeqbiXwvOrpClC1QdXViuAQUnpXgE1U%2FSb%2BUwVVF7JfdTWN2G4uFyiaeZz6oOpB1drzTF0sSw6ySdc5Y%2FZe1SPeCpPfS6p6yq4arK16V5eyAwWEp6oTEKpqewXEygBW9iMabzsAZjqoOkuTL227tjJvSg8UaG%2FGhW33obSK8d4dVj1eAV3VrXQsuBtXvd12XdWteCxg2nbobbuU2xQsHst42zHe6lllypOnbcdUeZ62HUzNoOXJz4vdpZXDz4rde5TDz4rdsQ6%2BLHZNxVjOip3VJD8ndjVtOSt2rEp%2BRuxCHXxZ7G6tCr4sdhUX1xPETmvhC2KndWNZFjtUjmVR7KRyLItiF2qTL4ndtdXCF8Tuqhq%2BIHaonfmi2Ek1fEHsQjV8YdtVt2VR7DzgM2J36QCfFbsbB%2Fi82MEBPit2HvBZsfMYy6zYuSSfq7oLfE7sLpzgk2J37QKfETt1gc%2BJnQ98Rux84NNiJ07wSbELTvBpsXOCT4rdRz%2F4WOzMCz4pdl7wKbGDG3xC7NzGMiV2jvCx2PnNfELsbvzgY7FrHOFjsXOEj7YdHeFjsfOF96sePOFjsXOED8XutSt8sO2uXOFDsfOFD6ruCx9U3Rc%2BEDt3eC52zvC%2B2DnD%2B2LnDe9V3RveEzt3eC527vBc7NzhudhtAe%2BuAH94VnV%2FeCZ2G8BzscMmUxdgi5lnYrcF%2FCR2wCZHSvftP9x2m8DTttsEnsRuK7hs8%2FPPxG4beCt2G8HbbbcNPG67reAUEfwHRePBMkvuZ4wAAAAASUVORK5CYII%3D);
}
View
17 test/flippers/index.html
@@ -88,11 +88,6 @@
}
}
- var fn = function (rdr) {
- rdr.listen('monocle:boundarystart', function () { console.log('start!') });
- rdr.listen('monocle:boundaryend', function () { console.log('end!') });
- }
-
// Initialize the reader element.
Monocle.Events.listen(
window,
@@ -101,26 +96,22 @@
window.reader1 = Monocle.Reader(
'instant',
bookData,
- { flipper: Monocle.Flippers.Instant },
- fn
+ { flipper: Monocle.Flippers.Instant }
);
window.reader2 = Monocle.Reader(
'scroller',
bookData,
- { flipper: Monocle.Flippers.Scroller },
- fn
+ { flipper: Monocle.Flippers.Scroller }
);
window.reader3 = Monocle.Reader(
'slider',
bookData,
- { flipper: Monocle.Flippers.Slider },
- fn
+ { flipper: Monocle.Flippers.Slider }
);
window.reader4 = Monocle.Reader(
'legacy',
bookData,
- { flipper: Monocle.Flippers.Legacy },
- fn
+ { flipper: Monocle.Flippers.Legacy }
);
}
);

0 comments on commit d905119

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