Skip to content

Commit

Permalink
Merge remote branch 'upstream/componentry' into componentry
Browse files Browse the repository at this point in the history
  • Loading branch information
aronwoost committed Apr 26, 2011
2 parents 3ea986d + ae73c74 commit 835e526
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 106 deletions.
5 changes: 3 additions & 2 deletions src/book.js
Expand Up @@ -183,10 +183,11 @@ Monocle.Book = function (dataSource) {
function setPageAt(pageDiv, locus) {
locus = pageNumberAt(pageDiv, locus);
if (locus && !locus.load) {
var evtData = { locus: locus, page: pageDiv }
if (locus.boundarystart) {
pageDiv.m.reader.dispatchEvent('monocle:boundarystart', { locus: locus });
pageDiv.m.reader.dispatchEvent('monocle:boundarystart', evtData);
} else if (locus.boundaryend) {
pageDiv.m.reader.dispatchEvent('monocle:boundaryend', { locus: locus });
pageDiv.m.reader.dispatchEvent('monocle:boundaryend', evtData);
} else {
var component = p.components[p.componentIds.indexOf(locus.componentId)];
pageDiv.m.place = pageDiv.m.place || new Monocle.Place();
Expand Down
19 changes: 19 additions & 0 deletions src/compat.js
Expand Up @@ -216,6 +216,25 @@ Monocle.Browser.has.jumpFlickerBug =
Monocle.Browser.on.MacOSX && Monocle.Browser.is.WebKit;


// Chrome versions 10 and 11 (beta) have a bug whereby the content of a
// block with columns is not painted at all when the block is scrolled. The
// effect is that every page after the first page in a component is blank.
//
// More information:
//
// test/bugs/column-overflow-paint-bug
//
// https://bugs.webkit.org/show_bug.cgi?id=52987
//
// https://github.com/joseph/monocle/issues#issue/25
//
// Thanks to madfarmer on Github for identifying a workaround.
//
Monocle.Browser.has.columnOverflowPaintBug = Monocle.Browser.is.WebKit &&
!Monocle.Browser.is.MobileSafari &&
navigator.userAgent.indexOf("AppleWebKit/534") > 0;


// A little console stub if not initialized in a console-equipped browser.
if (typeof window.console == "undefined") {
window.console = {
Expand Down
72 changes: 40 additions & 32 deletions src/controls/spinner.js
Expand Up @@ -8,7 +8,9 @@ Monocle.Controls.Spinner = function (reader) {
var p = API.properties = {
reader: reader,
divs: [],
spinCount: 0
spinCount: 0,
repeaters: {},
showForPages: []
}


Expand All @@ -19,53 +21,58 @@ Monocle.Controls.Spinner = function (reader) {
}


// Registers spin/spun event handlers for: loading,componentchanging,resizing.
function listenForUsualDelays() {
p.reader.listen('monocle:componentloading', spin);
p.reader.listen('monocle:componentloaded', spun);
p.reader.listen('monocle:componentchanging', spin);
p.reader.listen('monocle:componentchange', spun);
p.reader.listen('monocle:resizing', resizeSpin);
p.reader.listen('monocle:resize', resizeSpun);
//p.reader.listen('monocle:stylesheetchanging', spin);
//p.reader.listen('monocle:stylesheetchange', spun);
function registerSpinEvt(startEvtType, stopEvtType) {
var label = startEvtType;
p.reader.listen(startEvtType, function (evt) { spin(label, evt) });
p.reader.listen(stopEvtType, function (evt) { spun(label, evt) });
}


function resizeSpin(evt) {
if (p.resizing) {
return;
}
spin(evt);
p.resizing = true;
}


function resizeSpun(evt) {
spun(evt);
p.resizing = false;
// Registers spin/spun event handlers for certain time-consuming events.
//
function listenForUsualDelays() {
registerSpinEvt('monocle:componentloading', 'monocle:componentloaded');
registerSpinEvt('monocle:componentchanging', 'monocle:componentchange');
registerSpinEvt('monocle:resizing', 'monocle:resize');
registerSpinEvt('monocle:jumping', 'monocle:jump');
//registerSpinEvt('monocle:stylesheetchanging', 'monocle:stylesheetchange');
}


function spin(evt) {
//console.log('Spinning on ' + (evt ? evt.type : 'unknown'));
p.spinCount += 1;
// Displays the spinner. Both arguments are optional.
//
function spin(label, evt) {
label = label || k.GENERIC_LABEL;
//console.log('Spinning on ' + (evt ? evt.type : label));
p.repeaters[label] = true;
p.reader.showControl(API);

// If the delay is on a page other than the page we've been assigned to,
// don't show the animation.
// don't show the animation. p.global ensures that if an event affects
// all pages, the animation is always shown, even if other events in this
// spin cycle are page-specific.
var page = evt && evt.m.page ? evt.m.page : null;
if (!page) { p.global = true; }
for (var i = 0; i < p.divs.length; ++i) {
var owner = p.divs[i].parentNode.parentNode;
p.divs[i].style.display = (!page || page == owner) ? 'block' : 'none';
if (page == owner) { p.showForPages.push(page); }
var show = p.global || p.showForPages.indexOf(page) >= 0;
p.divs[i].style.display = show ? 'block' : 'none';
}
}


function spun(evt) {
//console.log('Spun on ' + (evt ? evt.type : 'unknown'));
p.spinCount -= 1;
if (p.spinCount > 0) { return; }
// Stops displaying the spinner. Both arguments are optional.
//
function spun(label, evt) {
label = label || k.GENERIC_LABEL;
//console.log('Spun on ' + (evt ? evt.type : label));
p.repeaters[label] = false;
for (var l in p.repeaters) {
if (p.repeaters[l]) { return; }
}
p.global = false;
p.showForPages = [];
p.reader.hideControl(API);
}

Expand All @@ -78,4 +85,5 @@ Monocle.Controls.Spinner = function (reader) {
return API;
}

Monocle.Controls.Spinner.GENERIC_LABEL = "generic";
Monocle.pieceLoaded('controls/spinner');
100 changes: 80 additions & 20 deletions src/controls/stencil.js
Expand Up @@ -19,8 +19,10 @@ Monocle.Controls.Stencil = function (reader) {
p.reader.listen('monocle:stylesheetchange', update);
p.reader.listen('monocle:resize', update);
p.reader.listen('monocle:componentchange', function (evt) {
if (evt.m.page == p.reader.visiblePages()[0]) { Monocle.defer(update); }
Monocle.defer(update);
});
p.reader.listen('monocle:interactive:on', disable);
p.reader.listen('monocle:interactive:off', enable);
p.baseURL = getBaseURL();
return p.container;
}
Expand All @@ -45,18 +47,20 @@ Monocle.Controls.Stencil = function (reader) {
function draw() {
var pageDiv = p.reader.visiblePages()[0];
var cmptId = pageComponentId(pageDiv);
if (cmptId != p.activeComponent) {
calculateRectangles(pageDiv);
if (!p.components[cmptId]) {
return;
}

// Position the container.
alignToComponent(pageDiv);

// Layout the cutouts.
var placed = 0;
var rects = p.components[cmptId];
if (rects && rects.length) {
placed = layoutRectangles(pageDiv, rects);
if (!p.disabled) {
var rects = p.components[cmptId];
if (rects && rects.length) {
placed = layoutRectangles(pageDiv, rects);
}
}

// Hide remaining rects.
Expand All @@ -75,6 +79,10 @@ Monocle.Controls.Stencil = function (reader) {
p.activeComponent = cmptId;
var doc = pageDiv.m.activeFrame.contentDocument;
var offset = getOffset(pageDiv);
// BROWSERHACK: Gecko doesn't subtract translations from GBCR values.
if (Monocle.Browser.is.Gecko) {
offset.l = 0;
}
var calcRects = false;
if (!p.components[cmptId]) {
p.components[cmptId] = []
Expand All @@ -85,14 +93,13 @@ Monocle.Controls.Stencil = function (reader) {
for (var i = 0; i < iElems.length; ++i) {
if (iElems[i].href) {
var href = deconstructHref(iElems[i].href);
if (!iElems[i].processed) {
fixLink(iElems[i], href);
}
fixLink(iElems[i], href, clickHandler);

if (calcRects && iElems[i].getClientRects) {
var r = iElems[i].getClientRects();
for (var j = 0; j < r.length; j++) {
p.components[cmptId].push({
link: iElems[i],
href: href,
left: Math.ceil(r[j].left + offset.l),
top: Math.ceil(r[j].top),
Expand All @@ -111,11 +118,10 @@ Monocle.Controls.Stencil = function (reader) {
// Find the offset position in pixels from the left of the current page.
//
function getOffset(pageDiv) {
var place = p.reader.getPlace();
var pages = place.pageNumber() - 1;
var result = { w: pageDiv.m.dimensions.properties.measurements.width }
result.l = result.w * pages;
return result;
return {
l: pageDiv.m.offset || 0,
w: pageDiv.m.dimensions.properties.measurements.width
};
}


Expand All @@ -142,7 +148,8 @@ Monocle.Controls.Stencil = function (reader) {
width: visRects[i].width+"px",
height: visRects[i].height+"px"
});
fixLink(link, visRects[i].href);
link.relatedLink = visRects[i].link;
fixLink(link, visRects[i].href, cutoutClick);
}

return i;
Expand All @@ -153,12 +160,21 @@ Monocle.Controls.Stencil = function (reader) {
// clicks and go to the corresponding component (or open the external URL
// in a new window).
//
function fixLink(link, hrefObject) {
// NB: if the original link already has a click handler on it (eg, if the
// content is scripted), that click handler can:
//
// * stopPropagation if it is defined first
// * run Monocle.Events.deafen(link, 'click', link.stencilClickHandler)
//
// in order to prevent the default stencil click behaviour when in
// interactive mode.
//
function fixLink(link, hrefObject, handler) {
link.setAttribute('target', '_blank');
link.deconstructedHref = hrefObject;
if (link.processed) { return; }
Monocle.Events.listen(link, 'click', cutoutClick);
link.processed = true;
if (link.stencilClickHandler) { return; }
link.stencilClickHandler = handler;
Monocle.Events.listen(link, 'click', link.stencilClickHandler);
}


Expand Down Expand Up @@ -257,6 +273,39 @@ Monocle.Controls.Stencil = function (reader) {
// or moves to an internal component.
//
function cutoutClick(evt) {
var link = evt.currentTarget;
olink = link.relatedLink;
Monocle.Events.listen(olink, 'click', clickHandler);
var mimicEvt = document.createEvent('MouseEvents');
mimicEvt.initMouseEvent(
'click',
true,
true,
document.defaultView,
evt.detail,
evt.screenX,
evt.screenY,
evt.screenX,
evt.screenY,
evt.ctrlKey,
evt.altKey,
evt.shiftKey,
evt.metaKey,
evt.which,
null
);
try {
olink.dispatchEvent(mimicEvt);
} finally {
Monocle.Events.deafen(olink, 'click', clickHandler);
}
}


function clickHandler(evt) {
if (evt.defaultPrevented) { // NB: unfortunately not supported in Gecko.
return;
}
var link = evt.currentTarget;
var href = link.deconstructedHref;
if (!href) {
Expand All @@ -267,12 +316,23 @@ Monocle.Controls.Stencil = function (reader) {
return;
}
var cmptId = href.componentId + href.hash;
//console.log("Skipping to: "+cmptId);
p.reader.skipToChapter(cmptId);
evt.preventDefault();
}


function disable() {
p.disabled = true;
draw();
}


function enable() {
p.disabled = false;
draw();
}


API.createControlElements = createControlElements;
API.draw = draw;
API.update = update;
Expand Down
34 changes: 26 additions & 8 deletions src/dimensions/columns.js
Expand Up @@ -111,21 +111,31 @@ Monocle.Dimensions.Columns = function (pageDiv) {
function componentChanged(evt) {
if (evt.m['page'] != p.page) { return; }
var doc = evt.m['document'];
Monocle.Styles.applyRules(doc.body, k.BODY_STYLES);
if (Monocle.Browser.has.columnOverflowPaintBug) {
var div = doc.createElement('div');
Monocle.Styles.applyRules(div, k.BODY_STYLES);
div.style.cssText += "overflow: scroll !important;";
while (doc.body.childNodes.length) {
div.appendChild(doc.body.firstChild);
}
doc.body.appendChild(div);
} else {
Monocle.Styles.applyRules(doc.body, k.BODY_STYLES);

// BROWSERHACK: WEBKIT bug - iframe needs scrollbars explicitly disabled.
if (Monocle.Browser.is.WebKit) {
doc.documentElement.style.overflow = 'hidden';
// BROWSERHACK: WEBKIT bug - iframe needs scrollbars explicitly disabled.
if (Monocle.Browser.is.WebKit) {
doc.documentElement.style.overflow = 'hidden';
}
}

p.dirty = true;
}


function setColumnWidth() {
var cw = p.page.m.sheafDiv.clientWidth;
var doc = p.page.m.activeFrame.contentDocument;
if (currBodyStyleValue('column-width') != cw+"px") {
Monocle.Styles.affix(doc.body, 'column-width', cw+"px");
Monocle.Styles.affix(columnedElement(), 'column-width', cw+"px");
p.dirty = true;
}
}
Expand All @@ -152,11 +162,18 @@ Monocle.Dimensions.Columns = function (pageDiv) {
if (Monocle.Browser.has.mustScrollSheaf) {
return p.page.m.sheafDiv;
} else {
return p.page.m.activeFrame.contentDocument.body;
return columnedElement();
}
}


// Returns the element to which columns CSS should be applied.
function columnedElement() {
var elem = p.page.m.activeFrame.contentDocument.body;
return Monocle.Browser.has.columnOverflowPaintBug ? elem.firstChild : elem;
}


// Returns the width of the offsettable area of the scroller element. By
// definition, the number of pages is always this number divided by the
// width of a single page (eg, the client area of the scroller element).
Expand Down Expand Up @@ -229,7 +246,8 @@ Monocle.Dimensions.Columns = function (pageDiv) {

function translateToLocus(locus) {
var offset = locusToOffset(locus);
if (k.SETX) {
p.page.m.offset = 0 - offset;
if (k.SETX && !Monocle.Browser.has.columnOverflowPaintBug) {
var bdy = p.page.m.activeFrame.contentDocument.body;
Monocle.Styles.affix(bdy, "transform", "translateX("+offset+"px)");
} else {
Expand Down

0 comments on commit 835e526

Please sign in to comment.