Content server: When a category contains only one item, go directly to the book list instead of forcing the user to click ont hat one item

This commit is contained in:
Kovid Goyal 2010-11-25 11:20:22 -07:00
parent a1efc0cf1b
commit 344b72e74b
3 changed files with 95 additions and 15 deletions

View File

@ -38,6 +38,7 @@ Monocle.Browser.on = {
iPad: navigator.userAgent.indexOf("iPad") != -1, iPad: navigator.userAgent.indexOf("iPad") != -1,
BlackBerry: navigator.userAgent.indexOf("BlackBerry") != -1, BlackBerry: navigator.userAgent.indexOf("BlackBerry") != -1,
Android: navigator.userAgent.indexOf('Android') != -1, Android: navigator.userAgent.indexOf('Android') != -1,
MacOSX: navigator.userAgent.indexOf('Mac OS X') != -1,
Kindle3: navigator.userAgent.match(/Kindle\/3/) Kindle3: navigator.userAgent.match(/Kindle\/3/)
} }
@ -162,12 +163,23 @@ Monocle.Browser.has.transform3d = Monocle.Browser.CSSProps.isSupported([
'OPerspective', 'OPerspective',
'msPerspective' 'msPerspective'
]) && Monocle.Browser.CSSProps.supportsMediaQueryProperty('transform-3d'); ]) && Monocle.Browser.CSSProps.supportsMediaQueryProperty('transform-3d');
Monocle.Browser.has.embedded = (top != self);
Monocle.Browser.has.iframeTouchBug = Monocle.Browser.iOSVersionBelow("4.2"); Monocle.Browser.has.iframeTouchBug = Monocle.Browser.iOSVersionBelow("4.2");
Monocle.Browser.has.selectThruBug = Monocle.Browser.iOSVersionBelow("4.2"); Monocle.Browser.has.selectThruBug = Monocle.Browser.iOSVersionBelow("4.2");
Monocle.Browser.has.mustScrollSheaf = Monocle.Browser.is.MobileSafari; Monocle.Browser.has.mustScrollSheaf = Monocle.Browser.is.MobileSafari;
Monocle.Browser.has.iframeDoubleWidthBug = Monocle.Browser.has.mustScrollSheaf; Monocle.Browser.has.iframeDoubleWidthBug = Monocle.Browser.has.mustScrollSheaf;
Monocle.Browser.has.floatColumnBug = Monocle.Browser.is.WebKit; Monocle.Browser.has.floatColumnBug = Monocle.Browser.is.WebKit;
Monocle.Browser.has.relativeIframeWidthBug = Monocle.Browser.on.Android;
Monocle.Browser.has.jumpFlickerBug =
Monocle.Browser.on.MacOSX && Monocle.Browser.is.WebKit;
if (typeof window.console == "undefined") { if (typeof window.console == "undefined") {
window.console = { window.console = {
@ -1091,11 +1103,29 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) {
cmpt.dom.setStyles(Monocle.Styles.component); cmpt.dom.setStyles(Monocle.Styles.component);
Monocle.Styles.applyRules(cmpt.contentDocument.body, Monocle.Styles.body); Monocle.Styles.applyRules(cmpt.contentDocument.body, Monocle.Styles.body);
} }
lockFrameWidths();
dom.find('overlay').dom.setStyles(Monocle.Styles.overlay); dom.find('overlay').dom.setStyles(Monocle.Styles.overlay);
dispatchEvent('monocle:styles'); dispatchEvent('monocle:styles');
} }
function lockingFrameWidths() {
if (!Monocle.Browser.has.relativeIframeWidthBug) { return; }
for (var i = 0, cmpt; cmpt = dom.find('component', i); ++i) {
cmpt.style.display = "none";
}
}
function lockFrameWidths() {
if (!Monocle.Browser.has.relativeIframeWidthBug) { return; }
for (var i = 0, cmpt; cmpt = dom.find('component', i); ++i) {
cmpt.style.width = cmpt.parentNode.offsetWidth+"px";
cmpt.style.display = "block";
}
}
function setBook(bk, place, callback) { function setBook(bk, place, callback) {
p.book = bk; p.book = bk;
var pageCount = 0; var pageCount = 0;
@ -1121,12 +1151,14 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) {
if (!p.initialized) { if (!p.initialized) {
console.warn('Attempt to resize book before initialization.'); console.warn('Attempt to resize book before initialization.');
} }
lockingFrameWidths();
if (!dispatchEvent("monocle:resizing", {}, true)) { if (!dispatchEvent("monocle:resizing", {}, true)) {
return; return;
} }
clearTimeout(p.resizeTimer); clearTimeout(p.resizeTimer);
p.resizeTimer = setTimeout( p.resizeTimer = setTimeout(
function () { function () {
lockFrameWidths();
p.flipper.moveTo({ page: pageNumber() }); p.flipper.moveTo({ page: pageNumber() });
dispatchEvent("monocle:resize"); dispatchEvent("monocle:resize");
}, },
@ -1765,12 +1797,7 @@ Monocle.Book = function (dataSource) {
function componentIdMatching(str) { function componentIdMatching(str) {
for (var i = 0; i < p.componentIds.length; ++i) { return p.componentIds.indexOf(str) >= 0 ? str : null;
if (str.indexOf(p.componentIds[i]) > -1) {
return p.componentIds[i];
}
}
return null;
} }
@ -2018,6 +2045,12 @@ Monocle.Component = function (book, id, index, chapters, source) {
function loadFrameFromURL(url, frame, callback) { function loadFrameFromURL(url, frame, callback) {
if (!url.match(/^\//)) {
var link = document.createElement('a');
link.setAttribute('href', url);
url = link.href;
delete(link);
}
frame.onload = function () { frame.onload = function () {
frame.onload = null; frame.onload = null;
Monocle.defer(callback); Monocle.defer(callback);
@ -2460,7 +2493,7 @@ Monocle.Flippers.Legacy = function (reader) {
function moveTo(locus, callback) { function moveTo(locus, callback) {
var fn = frameToLocus; var fn = frameToLocus;
if (typeof callback == "function") { if (typeof callback == "function") {
fn = function () { frameToLocus(); callback(); } fn = function (locus) { frameToLocus(locus); callback(locus); }
} }
p.reader.getBook().setOrLoadPageAt(page(), locus, fn); p.reader.getBook().setOrLoadPageAt(page(), locus, fn);
} }
@ -2794,7 +2827,9 @@ Monocle.Dimensions.Columns = function (pageDiv) {
function scrollerWidth() { function scrollerWidth() {
var bdy = p.page.m.activeFrame.contentDocument.body; var bdy = p.page.m.activeFrame.contentDocument.body;
if (Monocle.Browser.has.iframeDoubleWidthBug) { if (Monocle.Browser.has.iframeDoubleWidthBug) {
if (Monocle.Browser.iOSVersion < "4.1") { if (Monocle.Browser.on.Android) {
return bdy.scrollWidth * 1.5; // I actually have no idea why 1.5.
} else if (Monocle.Browser.iOSVersion < "4.1") {
var hbw = bdy.scrollWidth / 2; var hbw = bdy.scrollWidth / 2;
var sew = scrollerElement().scrollWidth; var sew = scrollerElement().scrollWidth;
return Math.max(sew, hbw); return Math.max(sew, hbw);
@ -2969,6 +3004,7 @@ Monocle.Flippers.Slider = function (reader) {
function setPage(pageDiv, locus, callback) { function setPage(pageDiv, locus, callback) {
ensureWaitControl();
p.reader.getBook().setOrLoadPageAt( p.reader.getBook().setOrLoadPageAt(
pageDiv, pageDiv,
locus, locus,
@ -3048,6 +3084,7 @@ Monocle.Flippers.Slider = function (reader) {
checkPoint(boxPointX); checkPoint(boxPointX);
p.turnData.releasing = true; p.turnData.releasing = true;
showWaitControl(lowerPage());
if (dir == k.FORWARDS) { if (dir == k.FORWARDS) {
if ( if (
@ -3088,14 +3125,18 @@ Monocle.Flippers.Slider = function (reader) {
function onGoingBackward(x) { function onGoingBackward(x) {
var lp = lowerPage(); var lp = lowerPage(), up = upperPage();
showWaitControl(up);
jumpOut(lp, // move lower page off-screen jumpOut(lp, // move lower page off-screen
function () { function () {
flipPages(); // flip lower to upper flipPages(); // flip lower to upper
setPage( // set upper page to previous setPage( // set upper page to previous
lp, lp,
getPlace(lowerPage()).getLocus({ direction: k.BACKWARDS }), getPlace(lowerPage()).getLocus({ direction: k.BACKWARDS }),
function () { lifted(x); } function () {
lifted(x);
hideWaitControl(up);
}
); );
} }
); );
@ -3103,8 +3144,10 @@ Monocle.Flippers.Slider = function (reader) {
function afterGoingForward() { function afterGoingForward() {
var up = upperPage(); var up = upperPage(), lp = lowerPage();
if (p.interactive) { if (p.interactive) {
showWaitControl(up);
showWaitControl(lp);
setPage( // set upper (off screen) to current setPage( // set upper (off screen) to current
up, up,
getPlace().getLocus({ direction: k.FORWARDS }), getPlace().getLocus({ direction: k.FORWARDS }),
@ -3113,6 +3156,7 @@ Monocle.Flippers.Slider = function (reader) {
} }
); );
} else { } else {
showWaitControl(lp);
flipPages(); flipPages();
jumpIn(up, function () { prepareNextPage(announceTurn); }); jumpIn(up, function () { prepareNextPage(announceTurn); });
} }
@ -3171,6 +3215,8 @@ Monocle.Flippers.Slider = function (reader) {
function announceTurn() { function announceTurn() {
hideWaitControl(upperPage());
hideWaitControl(lowerPage());
p.reader.dispatchEvent('monocle:turn'); p.reader.dispatchEvent('monocle:turn');
resetTurnData(); resetTurnData();
} }
@ -3319,12 +3365,14 @@ Monocle.Flippers.Slider = function (reader) {
function jumpIn(pageDiv, callback) { function jumpIn(pageDiv, callback) {
setX(pageDiv, 0, { duration: 1 }, callback); var dur = Monocle.Browser.has.jumpFlickerBug ? 1 : 0;
setX(pageDiv, 0, { duration: dur }, callback);
} }
function jumpOut(pageDiv, callback) { function jumpOut(pageDiv, callback) {
setX(pageDiv, 0 - pageDiv.offsetWidth, { duration: 1 }, callback); var dur = Monocle.Browser.has.jumpFlickerBug ? 1 : 0;
setX(pageDiv, 0 - pageDiv.offsetWidth, { duration: dur }, callback);
} }
@ -3357,6 +3405,28 @@ Monocle.Flippers.Slider = function (reader) {
} }
function ensureWaitControl() {
if (p.waitControl) { return; }
p.waitControl = {
createControlElements: function (holder) {
return holder.dom.make('div', 'flippers_slider_wait');
}
}
p.reader.addControl(p.waitControl, 'page');
}
function showWaitControl(page) {
var ctrl = p.reader.dom.find('flippers_slider_wait', page.m.pageIndex);
ctrl.style.opacity = 0.5;
}
function hideWaitControl(page) {
var ctrl = p.reader.dom.find('flippers_slider_wait', page.m.pageIndex);
ctrl.style.opacity = 0;
}
API.pageCount = p.pageCount; API.pageCount = p.pageCount;
API.addPage = addPage; API.addPage = addPage;
API.getPlace = getPlace; API.getPlace = getPlace;

View File

@ -794,7 +794,7 @@ class TagBrowserMixin(object): # {{{
cc_label = None cc_label = None
if category in db.field_metadata: if category in db.field_metadata:
cc_label = db.field_metadata[category]['label'] cc_label = db.field_metadata[category]['label']
result = self.db.get_custom_items_with_ids(label=cc_label) result = db.get_custom_items_with_ids(label=cc_label)
else: else:
result = [] result = []
compare = (lambda x,y:cmp(x.lower(), y.lower())) compare = (lambda x,y:cmp(x.lower(), y.lower()))

View File

@ -5,7 +5,7 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import operator, os, json import operator, os, json, re
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from urllib import quote, unquote from urllib import quote, unquote
@ -401,6 +401,16 @@ class BrowseServer(object):
script = 'true' script = 'true'
if len(items) == 1:
# Only one item in category, go directly to book list
prefix = '' if self.is_wsgi else self.opts.url_prefix
html = get_category_items(category, items,
self.search_restriction_name, datatype,
self.opts.url_prefix)
href = re.search(r'<a href="([^"]+)"', html)
if href is not None:
raise cherrypy.HTTPRedirect(prefix+href.group(1))
if len(items) <= self.opts.max_opds_ungrouped_items: if len(items) <= self.opts.max_opds_ungrouped_items:
script = 'false' script = 'false'
items = get_category_items(category, items, items = get_category_items(category, items,