Skip to content
Browse files

Persistent proportional font-sizing with Formatting#setFontScale.

Additionally, you can now pass a float multiplier into Reader
initialisation options with 'fontScale'.
  • Loading branch information...
1 parent 3a79afe commit 2402da9d185601dea22cdc4df607449fb0b8b180 @joseph committed Feb 10, 2012
Showing with 149 additions and 18 deletions.
  1. +92 −3 src/core/formatting.js
  2. +3 −0 src/core/reader.js
  3. +2 −4 src/core/selection.js
  4. +52 −11 test/formatting/index.html
View
95 src/core/formatting.js
@@ -14,6 +14,7 @@ Monocle.Formatting = function (reader, optStyles, optScale) {
function initialize() {
+ p.fontScale = optScale;
clampStylesheets(optStyles);
p.reader.listen('monocle:componentmodify', persistOnComponentChange);
}
@@ -36,6 +37,7 @@ Monocle.Formatting = function (reader, optStyles, optScale) {
function persistOnComponentChange(evt) {
var doc = evt.m['document'];
doc.documentElement.id = p.reader.properties.systemId;
+ adjustFontScaleForDoc(doc, p.fontScale);
for (var i = 0; i < p.stylesheets.length; ++i) {
if (p.stylesheets[i]) {
addPageStylesheet(doc, i);
@@ -59,9 +61,7 @@ Monocle.Formatting = function (reader, optStyles, optScale) {
var i = 0, cmpt = null;
while (cmpt = p.reader.dom.find('component', i++)) {
- if (cmpt.contentDocument) {
addPageStylesheet(cmpt.contentDocument, sheetIndex);
- }
}
return sheetIndex;
}, restorePlace);
@@ -122,7 +122,7 @@ Monocle.Formatting = function (reader, optStyles, optScale) {
function changingStylesheet(callback, restorePlace) {
restorePlace = (restorePlace === false) ? false : true;
if (restorePlace) {
- p.reader.dispatchEvent("monocle:stylesheetchanging", {});
+ dispatchChanging();
}
var result = callback();
if (restorePlace) {
@@ -135,6 +135,11 @@ Monocle.Formatting = function (reader, optStyles, optScale) {
}
+ function dispatchChanging() {
+ p.reader.dispatchEvent("monocle:stylesheetchanging", {});
+ }
+
+
function dispatchChange() {
p.reader.dispatchEvent("monocle:stylesheetchange", {});
}
@@ -175,9 +180,93 @@ Monocle.Formatting = function (reader, optStyles, optScale) {
}
+ /* FONT SCALING */
+
+ function setFontScale(scale, restorePlace) {
+ p.fontScale = scale;
+ if (restorePlace) {
+ dispatchChanging();
+ }
+ var i = 0, cmpt = null;
+ while (cmpt = p.reader.dom.find('component', i++)) {
+ adjustFontScaleForDoc(cmpt.contentDocument, scale);
+ }
+ if (restorePlace) {
+ p.reader.recalculateDimensions(true);
+ dispatchChange();
+ } else {
+ p.reader.recalculateDimensions(false);
+ }
+ }
+
+
+ function adjustFontScaleForDoc(doc, scale) {
+ var elems = doc.getElementsByTagName('*');
+ if (scale) {
+ scale = parseFloat(scale);
+ if (!doc.pfsSwept) {
+ sweepElements(doc, elems);
+ }
+
+ // Iterate over each element, applying scale to the original
+ // font-size. If a proportional font sizing is already applied to
+ // the element, update existing cssText, otherwise append new cssText.
+ //
+ for (var j = 0, jj = elems.length; j < jj; ++j) {
+ var newFs = fsProperty(elems[j].pfsOriginal, scale);
+ if (elems[j].pfsApplied) {
+ replaceFontSizeInStyle(elems[j], newFs);
+ } else {
+ elems[j].style.cssText += newFs;
+ }
+ elems[j].pfsApplied = scale;
+ }
+ } else if (doc.pfsSwept) {
+ // Iterate over each element, removing proportional font-sizing flag
+ // and property from cssText.
+ for (var j = 0, jj = elems.length; j < jj; ++j) {
+ if (elems[j].pfsApplied) {
+ var oprop = elems[j].pfsOriginalProp;
+ var opropDec = oprop ? 'font-size: '+oprop+' ! important;' : '';
+ replaceFontSizeInStyle(elems[j], opropDec);
+ elems[j].pfsApplied = null;
+ }
+ }
+
+ // Establish new baselines in case classes have changed.
+ sweepElements(doc, elems);
+ }
+ }
+
+
+ function sweepElements(doc, elems) {
+ // Iterate over each element, looking at its font size and storing
+ // the original value against the element.
+ for (var i = 0, ii = elems.length; i < ii; ++i) {
+ var currStyle = doc.defaultView.getComputedStyle(elems[i], null);
+ var fs = parseFloat(currStyle.getPropertyValue('font-size'));
+ elems[i].pfsOriginal = fs;
+ elems[i].pfsOriginalProp = elems[i].style.fontSize;
+ }
+ doc.pfsSwept = true;
+ }
+
+
+ function fsProperty(orig, scale) {
+ return 'font-size: '+(orig*scale)+'px ! important;';
+ }
+
+
+ function replaceFontSizeInStyle(elem, newProp) {
+ var lastFs = /font-size:[^;]/
+ elem.style.cssText = elem.style.cssText.replace(lastFs, newProp);
+ }
+
+
API.addPageStyles = addPageStyles;
API.updatePageStyles = updatePageStyles;
API.removePageStyles = removePageStyles;
+ API.setFontScale = setFontScale;
initialize();
View
3 src/core/reader.js
@@ -24,6 +24,9 @@
// stylesheet: A string of CSS rules to apply to the contents of each
// component loaded into the reader.
//
+// fontScale: a float to multiply against the default font-size of each
+// element in each component.
+//
// place: A book locus for the page to open to when the reader is
// initialized. (See comments at Book#pageNumberAt for more about
// the locus option).
View
6 src/core/selection.js
@@ -16,9 +16,8 @@ Monocle.Selection = function (reader) {
function pollSelection() {
var index = 0, frame = null;
- while (frame = reader.dom.find('component', index)) {
+ while (frame = reader.dom.find('component', index++)) {
pollSelectionOnWindow(frame.contentWindow, index);
- index += 1;
}
}
@@ -60,9 +59,8 @@ Monocle.Selection = function (reader) {
//
function deselect() {
var index = 0, frame = null;
- while (frame = reader.dom.find('component', index)) {
+ while (frame = reader.dom.find('component', index++)) {
deselectOnWindow(frame.contentWindow);
- index += 1;
}
}
View
63 test/formatting/index.html
@@ -25,16 +25,34 @@
<script type="text/javascript" src="../../dist/scripts/monocore.js"></script>
<script type="text/javascript">
- Monocle.DEBUG = true;
-
- // Initialize the reader element.
- Monocle.Events.listen(window, 'load', function () {
- window.reader = Monocle.Reader(
- 'reader',
- Monocle.bookDataFromIds(['part1', 'part2']),
- { stylesheet: "body { color: #090; }" }
- );
- });
+ (function () {
+ function init() {
+ var bd = Monocle.bookDataFromIds(['part1', 'part2']);
+ var opts = { stylesheet: 'body { color: #090; }' };
+ window.reader = Monocle.Reader('reader', bd, opts, readerLoaded);
+ }
+
+
+ function readerLoaded() {
+ var sSel = document.getElementById('sizeSelect');
+ sSel.addEventListener('change', function (evt) {
+ reader.formatting.setFontScale(parseFloat(sSel.value), true);
+ });
+
+ var cSel = document.getElementById('colorSelect');
+ cSel.addEventListener('change', function (evt) {
+ reader.formatting.updatePageStyles(
+ reader.formatting.properties.initialStyles,
+ 'body { color: '+cSel.value+'; }',
+ true
+ );
+ });
+ }
+
+
+ Monocle.DEBUG = true;
+ Monocle.Events.listen(window, 'load', init);
+ })();
</script>
</head>
@@ -48,8 +66,31 @@
turns the component's body text <span style="color: #090;">green</span>.
</p>
- <div id="reader"></div>
+ <p>
+ Font-scale:
+ <select id="sizeSelect">
+ <option value="">&mdash;</option>
+ <option value="0.1">10%</option>
+ <option value="0.5">50%</option>
+ <option value="0.8">80%</option>
+ <option value="1.0">100%</option>
+ <option value="1.1">110%</option>
+ <option value="1.3">130%</option>
+ <option value="1.6">160%</option>
+ <option value="2.0">200%</option>
+ <option value="2.5">250%</option>
+ <option value="4.0">400%</option>
+ <option value="8.0">800%</option>
+ </select>
+ Color:
+ <select id="colorSelect">
+ <option value="#090">Green</option>
+ <option value="#009">Blue</option>
+ </select>
+ </p>
+
+ <div id="reader"></div>
<div id="part1">
<p>

0 comments on commit 2402da9

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