monocle-rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/.DS_Store +0 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/lib/monocle/rails.rb +8 -0
  8. data/lib/monocle/rails/version.rb +5 -0
  9. data/monocle-rails.gemspec +23 -0
  10. data/vendor/.DS_Store +0 -0
  11. data/vendor/assets/.DS_Store +0 -0
  12. data/vendor/assets/javascripts/.DS_Store +0 -0
  13. data/vendor/assets/javascripts/compat/browser.js +120 -0
  14. data/vendor/assets/javascripts/compat/css.js +145 -0
  15. data/vendor/assets/javascripts/compat/env.js +463 -0
  16. data/vendor/assets/javascripts/compat/gala.js +469 -0
  17. data/vendor/assets/javascripts/compat/stubs.js +50 -0
  18. data/vendor/assets/javascripts/controls/contents.js +59 -0
  19. data/vendor/assets/javascripts/controls/magnifier.js +51 -0
  20. data/vendor/assets/javascripts/controls/panel.js +136 -0
  21. data/vendor/assets/javascripts/controls/placesaver.js +100 -0
  22. data/vendor/assets/javascripts/controls/scrubber.js +140 -0
  23. data/vendor/assets/javascripts/controls/spinner.js +99 -0
  24. data/vendor/assets/javascripts/controls/stencil.js +410 -0
  25. data/vendor/assets/javascripts/core/billboard.js +120 -0
  26. data/vendor/assets/javascripts/core/book.js +467 -0
  27. data/vendor/assets/javascripts/core/bookdata.js +59 -0
  28. data/vendor/assets/javascripts/core/component.js +413 -0
  29. data/vendor/assets/javascripts/core/events.js +56 -0
  30. data/vendor/assets/javascripts/core/factory.js +194 -0
  31. data/vendor/assets/javascripts/core/formatting.js +317 -0
  32. data/vendor/assets/javascripts/core/monocle.js +16 -0
  33. data/vendor/assets/javascripts/core/place.js +210 -0
  34. data/vendor/assets/javascripts/core/reader.js +683 -0
  35. data/vendor/assets/javascripts/core/selection.js +158 -0
  36. data/vendor/assets/javascripts/core/styles.js +155 -0
  37. data/vendor/assets/javascripts/dimensions/columns.js +218 -0
  38. data/vendor/assets/javascripts/flippers/instant.js +78 -0
  39. data/vendor/assets/javascripts/flippers/scroller.js +128 -0
  40. data/vendor/assets/javascripts/flippers/slider.js +469 -0
  41. data/vendor/assets/javascripts/monocore.js +27 -0
  42. data/vendor/assets/javascripts/monoctrl.js +1 -0
  43. data/vendor/assets/javascripts/panels/eink.js +61 -0
  44. data/vendor/assets/javascripts/panels/imode.js +180 -0
  45. data/vendor/assets/javascripts/panels/magic.js +297 -0
  46. data/vendor/assets/javascripts/panels/marginal.js +50 -0
  47. data/vendor/assets/javascripts/panels/twopane.js +34 -0
  48. data/vendor/assets/stylesheets/monocore.css +194 -0
  49. data/vendor/assets/stylesheets/monoctrl.css +168 -0
  50. metadata +129 -0
@@ -0,0 +1,56 @@
1
+ Monocle.Events = {};
2
+
3
+
4
+ Monocle.Events.wrapper = function (fn) {
5
+ return function (evt) { evt.m = new Gala.Cursor(evt); fn(evt); }
6
+ }
7
+
8
+
9
+ Monocle.Events.listen = Gala.listen;
10
+
11
+
12
+ Monocle.Events.deafen = Gala.deafen;
13
+
14
+
15
+ Monocle.Events.dispatch = Gala.dispatch;
16
+
17
+
18
+ Monocle.Events.listenForTap = function (elem, fn, tapClass) {
19
+ return Gala.onTap(elem, Monocle.Events.wrapper(fn), tapClass);
20
+ }
21
+
22
+
23
+ Monocle.Events.deafenForTap = Gala.deafenGroup;
24
+
25
+
26
+ Monocle.Events.listenForContact = function (elem, fns, options) {
27
+ options = options || { useCapture: false };
28
+ var wrappers = {};
29
+ for (var evtType in fns) {
30
+ wrappers[evtType] = Monocle.Events.wrapper(fns[evtType]);
31
+ }
32
+ return Gala.onContact(elem, wrappers, options.useCapture);
33
+ }
34
+
35
+
36
+ Monocle.Events.deafenForContact = Gala.deafenGroup;
37
+
38
+
39
+ // Listen for the next transition-end event on the given element, call
40
+ // the function, then deafen.
41
+ //
42
+ // Returns a function that can be used to cancel the listen early.
43
+ //
44
+ Monocle.Events.afterTransition = function (elem, fn) {
45
+ var evtName = "transitionend";
46
+ if (Monocle.Browser.is.WebKit) {
47
+ evtName = 'webkitTransitionEnd';
48
+ } else if (Monocle.Browser.is.Opera) {
49
+ evtName = 'oTransitionEnd';
50
+ }
51
+ var l = null, cancel = null;
52
+ l = function () { fn(); cancel(); }
53
+ cancel = function () { Monocle.Events.deafen(elem, evtName, l); }
54
+ Monocle.Events.listen(elem, evtName, l);
55
+ return cancel;
56
+ }
@@ -0,0 +1,194 @@
1
+ Monocle.Factory = function (element, label, index, reader) {
2
+
3
+ var API = { constructor: Monocle.Factory };
4
+ var k = API.constants = API.constructor;
5
+ var p = API.properties = {
6
+ element: element,
7
+ label: label,
8
+ index: index,
9
+ reader: reader,
10
+ prefix: reader.properties.classPrefix || ''
11
+ }
12
+
13
+
14
+ // If index is null, uses the first available slot. If index is not null and
15
+ // the slot is not free, throws an error.
16
+ //
17
+ function initialize() {
18
+ if (!p.label) { return; }
19
+ // Append the element to the reader's graph of DOM elements.
20
+ var node = p.reader.properties.graph;
21
+ node[p.label] = node[p.label] || [];
22
+ if (typeof p.index == 'undefined' && node[p.label][p.index]) {
23
+ throw('Element already exists in graph: '+p.label+'['+p.index+']');
24
+ } else {
25
+ p.index = p.index || node[p.label].length;
26
+ }
27
+ node[p.label][p.index] = p.element;
28
+
29
+ // Add the label as a class name.
30
+ addClass(p.label);
31
+ }
32
+
33
+
34
+ // Finds an element that has been created in the context of the current
35
+ // reader, with the given label. If oIndex is not provided, returns first.
36
+ // If oIndex is provided (eg, n), returns the nth element with the label.
37
+ //
38
+ function find(oLabel, oIndex) {
39
+ if (!p.reader.properties.graph[oLabel]) {
40
+ return null;
41
+ }
42
+ return p.reader.properties.graph[oLabel][oIndex || 0];
43
+ }
44
+
45
+
46
+ // Takes an elements and assimilates it into the reader -- essentially
47
+ // giving it a "dom" object of it's own. It will then be accessible via find.
48
+ //
49
+ // Note that (as per comments for initialize), if oIndex is provided and
50
+ // there is no free slot in the array for this label at that index, an
51
+ // error will be thrown.
52
+ //
53
+ function claim(oElement, oLabel, oIndex) {
54
+ return oElement.dom = new Monocle.Factory(
55
+ oElement,
56
+ oLabel,
57
+ oIndex,
58
+ p.reader
59
+ );
60
+ }
61
+
62
+
63
+ // Create an element with the given label.
64
+ //
65
+ // The last argument (whether third or fourth) is the options hash. Your
66
+ // options are:
67
+ //
68
+ // class - the classname for the element. Must only be one name.
69
+ // html - the innerHTML for the element.
70
+ // text - the innerText for the element (an alternative to html, simpler).
71
+ //
72
+ // Returns the created element.
73
+ //
74
+ function make(tagName, oLabel, indexOrOptions, orOptions) {
75
+ var oIndex, options;
76
+ if (arguments.length == 1) {
77
+ oLabel = null,
78
+ oIndex = 0;
79
+ options = {};
80
+ } else if (arguments.length == 2) {
81
+ oIndex = 0;
82
+ options = {};
83
+ } else if (arguments.length == 4) {
84
+ oIndex = arguments[2];
85
+ options = arguments[3];
86
+ } else if (arguments.length == 3) {
87
+ var lastArg = arguments[arguments.length - 1];
88
+ if (typeof lastArg == "number") {
89
+ oIndex = lastArg;
90
+ options = {};
91
+ } else {
92
+ oIndex = 0;
93
+ options = lastArg;
94
+ }
95
+ }
96
+
97
+ var oElement = document.createElement(tagName);
98
+ claim(oElement, oLabel, oIndex);
99
+ if (options['class']) {
100
+ oElement.className += " "+p.prefix+options['class'];
101
+ }
102
+ if (options['html']) {
103
+ oElement.innerHTML = options['html'];
104
+ }
105
+ if (options['text']) {
106
+ oElement.appendChild(document.createTextNode(options['text']));
107
+ }
108
+
109
+ return oElement;
110
+ }
111
+
112
+
113
+ // Creates an element by passing all the given arguments to make. Then
114
+ // appends the element as a child of the current element.
115
+ //
116
+ function append(tagName, oLabel, indexOrOptions, orOptions) {
117
+ var oElement = make.apply(this, arguments);
118
+ p.element.appendChild(oElement);
119
+ return oElement;
120
+ }
121
+
122
+
123
+ // Returns an array of [label, index, reader] for the given element.
124
+ // A simple way to introspect the arguments required for #find, for eg.
125
+ //
126
+ function address() {
127
+ return [p.label, p.index, p.reader];
128
+ }
129
+
130
+
131
+ // Apply a set of style rules (hash or string) to the current element.
132
+ // See Monocle.Styles.applyRules for more info.
133
+ //
134
+ function setStyles(rules) {
135
+ return Monocle.Styles.applyRules(p.element, rules);
136
+ }
137
+
138
+
139
+ function setBetaStyle(property, value) {
140
+ return Monocle.Styles.affix(p.element, property, value);
141
+ }
142
+
143
+
144
+ // ClassName manipulation functions - with thanks to prototype.js!
145
+
146
+ // Returns true if one of the current element's classnames matches name --
147
+ // classPrefix aware (so don't concate the prefix onto it).
148
+ //
149
+ function hasClass(name) {
150
+ name = p.prefix + name;
151
+ var klass = p.element.className;
152
+ if (!klass) { return false; }
153
+ if (klass == name) { return true; }
154
+ return new RegExp("(^|\\s)"+name+"(\\s|$)").test(klass);
155
+ }
156
+
157
+
158
+ // Adds name to the classnames of the current element (prepending the
159
+ // reader's classPrefix first).
160
+ //
161
+ function addClass(name) {
162
+ if (hasClass(name)) { return; }
163
+ var gap = p.element.className ? ' ' : '';
164
+ return p.element.className += gap+p.prefix+name;
165
+ }
166
+
167
+
168
+ // Removes (classPrefix+)name from the classnames of the current element.
169
+ //
170
+ function removeClass(name) {
171
+ var reName = new RegExp("(^|\\s+)"+p.prefix+name+"(\\s+|$)");
172
+ var reTrim = /^\s+|\s+$/g;
173
+ var klass = p.element.className;
174
+ p.element.className = klass.replace(reName, ' ').replace(reTrim, '');
175
+ return p.element.className;
176
+ }
177
+
178
+
179
+ API.find = find;
180
+ API.claim = claim;
181
+ API.make = make;
182
+ API.append = append;
183
+ API.address = address;
184
+
185
+ API.setStyles = setStyles;
186
+ API.setBetaStyle = setBetaStyle;
187
+ API.hasClass = hasClass;
188
+ API.addClass = addClass;
189
+ API.removeClass = removeClass;
190
+
191
+ initialize();
192
+
193
+ return API;
194
+ }
@@ -0,0 +1,317 @@
1
+ Monocle.Formatting = function (reader, optStyles, optScale) {
2
+ var API = { constructor: Monocle.Formatting };
3
+ var k = API.constants = API.constructor;
4
+ var p = API.properties = {
5
+ reader: reader,
6
+
7
+ // An array of style rules that are automatically applied to every page.
8
+ stylesheets: [],
9
+
10
+ // A multiplier on the default font-size of each element in every
11
+ // component. If null, the multiplier is not applied (or it is removed).
12
+ fontScale: null
13
+ }
14
+
15
+
16
+ function initialize() {
17
+ p.fontScale = optScale;
18
+ clampStylesheets(optStyles);
19
+ p.reader.listen('monocle:componentmodify', persistOnComponentChange);
20
+ }
21
+
22
+
23
+ // Clamp page frames to a set of styles that reduce Monocle breakage.
24
+ //
25
+ function clampStylesheets(implStyles) {
26
+ var defCSS = k.DEFAULT_STYLE_RULES;
27
+ if (Monocle.Browser.env.floatsIgnoreColumns) {
28
+ defCSS.push("html#RS\\:monocle * { float: none !important; }");
29
+ }
30
+ p.defaultStyles = addPageStyles(defCSS, false);
31
+ if (implStyles) {
32
+ p.initialStyles = addPageStyles(implStyles, false);
33
+ }
34
+ }
35
+
36
+
37
+ function persistOnComponentChange(evt) {
38
+ var doc = evt.m['document'];
39
+ doc.documentElement.id = p.reader.properties.systemId;
40
+ adjustFontScaleForDoc(doc, p.fontScale);
41
+ for (var i = 0; i < p.stylesheets.length; ++i) {
42
+ if (p.stylesheets[i]) {
43
+ addPageStylesheet(doc, i);
44
+ }
45
+ }
46
+ }
47
+
48
+
49
+ /* PAGE STYLESHEETS */
50
+
51
+ // API for adding a new stylesheet to all components. styleRules should be
52
+ // a string of CSS rules.
53
+ //
54
+ // Returns a sheet index value that can be used with updatePageStyles
55
+ // and removePageStyles.
56
+ //
57
+ function addPageStyles(styleRules) {
58
+ return changingStylesheet(function () {
59
+ p.stylesheets.push(styleRules);
60
+ var sheetIndex = p.stylesheets.length - 1;
61
+
62
+ var i = 0, cmpt = null;
63
+ while (cmpt = p.reader.dom.find('component', i++)) {
64
+ addPageStylesheet(cmpt.contentDocument, sheetIndex);
65
+ }
66
+ return sheetIndex;
67
+ });
68
+ }
69
+
70
+
71
+ // API for updating the styleRules in an existing page stylesheet across
72
+ // all components. Takes a sheet index value obtained via addPageStyles.
73
+ //
74
+ function updatePageStyles(sheetIndex, styleRules) {
75
+ return changingStylesheet(function () {
76
+ p.stylesheets[sheetIndex] = styleRules;
77
+ if (typeof styleRules.join == "function") {
78
+ styleRules = styleRules.join("\n");
79
+ }
80
+
81
+ var i = 0, cmpt = null;
82
+ while (cmpt = p.reader.dom.find('component', i++)) {
83
+ var doc = cmpt.contentDocument;
84
+ var styleTag = doc.getElementById('monStylesheet'+sheetIndex);
85
+ if (!styleTag) {
86
+ console.warn('No such stylesheet: ' + sheetIndex);
87
+ return;
88
+ }
89
+ if (styleTag.styleSheet) {
90
+ styleTag.styleSheet.cssText = styleRules;
91
+ } else {
92
+ styleTag.replaceChild(
93
+ doc.createTextNode(styleRules),
94
+ styleTag.firstChild
95
+ );
96
+ }
97
+ }
98
+ });
99
+ }
100
+
101
+
102
+ // API for removing a page stylesheet from all components. Takes a sheet
103
+ // index value obtained via addPageStyles.
104
+ //
105
+ function removePageStyles(sheetIndex) {
106
+ return changingStylesheet(function () {
107
+ p.stylesheets[sheetIndex] = null;
108
+ var i = 0, cmpt = null;
109
+ while (cmpt = p.reader.dom.find('component', i++)) {
110
+ var doc = cmpt.contentDocument;
111
+ var styleTag = doc.getElementById('monStylesheet'+sheetIndex);
112
+ styleTag.parentNode.removeChild(styleTag);
113
+ }
114
+ });
115
+ }
116
+
117
+
118
+ // Wraps all API-based stylesheet changes (add, update, remove) in a
119
+ // brace of custom events (stylesheetchanging/stylesheetchange), and
120
+ // recalculates component dimensions if specified (default to true).
121
+ //
122
+ function changingStylesheet(callback) {
123
+ dispatchChanging();
124
+ var result = callback();
125
+ p.reader.recalculateDimensions(true, dispatchChange);
126
+ return result;
127
+ }
128
+
129
+
130
+ function dispatchChanging() {
131
+ p.reader.dispatchEvent("monocle:stylesheetchanging", {});
132
+ }
133
+
134
+
135
+ function dispatchChange() {
136
+ p.reader.dispatchEvent("monocle:stylesheetchange", {});
137
+ }
138
+
139
+
140
+ // Private method for adding a stylesheet to a component. Used by
141
+ // addPageStyles.
142
+ //
143
+ function addPageStylesheet(doc, sheetIndex) {
144
+ var styleRules = p.stylesheets[sheetIndex];
145
+
146
+ if (!styleRules) {
147
+ return;
148
+ }
149
+
150
+ if (!doc || !doc.documentElement) {
151
+ return;
152
+ }
153
+
154
+ var head = doc.getElementsByTagName('head')[0];
155
+ if (!head) {
156
+ head = doc.createElement('head');
157
+ doc.documentElement.appendChild(head);
158
+ }
159
+
160
+ if (typeof styleRules.join == "function") {
161
+ styleRules = styleRules.join("\n");
162
+ }
163
+
164
+ var styleTag = doc.createElement('style');
165
+ styleTag.type = 'text/css';
166
+ styleTag.id = "monStylesheet"+sheetIndex;
167
+ if (styleTag.styleSheet) {
168
+ styleTag.styleSheet.cssText = styleRules;
169
+ } else {
170
+ styleTag.appendChild(doc.createTextNode(styleRules));
171
+ }
172
+
173
+ head.appendChild(styleTag);
174
+
175
+ return styleTag;
176
+ }
177
+
178
+
179
+ /* FONT SCALING */
180
+
181
+ function setFontScale(scale) {
182
+ p.fontScale = scale;
183
+ dispatchChanging();
184
+ var i = 0, cmpt = null;
185
+ while (cmpt = p.reader.dom.find('component', i++)) {
186
+ adjustFontScaleForDoc(cmpt.contentDocument, scale);
187
+ }
188
+ p.reader.recalculateDimensions(true, dispatchChange);
189
+ }
190
+
191
+
192
+ function adjustFontScaleForDoc(doc, scale) {
193
+ if (scale) {
194
+ if (!doc.body.pfsSwept) {
195
+ sweepElements(doc);
196
+ }
197
+ var evtData = { document: doc, scale: parseFloat(scale) };
198
+ p.reader.dispatchEvent('monocle:fontscaling', evtData);
199
+ scale = evtData.scale;
200
+
201
+ // Iterate over each element, applying scale to the original
202
+ // font-size. If a proportional font sizing is already applied to
203
+ // the element, update existing cssText, otherwise append new cssText.
204
+ walkTree(doc.body, function (elem) {
205
+ if (typeof elem.pfsOriginal == 'undefined') { return; }
206
+ var newFs = fsProperty(Math.round(elem.pfsOriginal*scale));
207
+ if (elem.pfsApplied) {
208
+ replaceFontSizeInStyle(elem, newFs);
209
+ } else {
210
+ elem.style.cssText += newFs;
211
+ }
212
+ elem.pfsApplied = scale;
213
+ });
214
+
215
+ p.reader.dispatchEvent('monocle:fontscale', evtData);
216
+ } else if (doc.body.pfsApplied) {
217
+ var evtData = { document: doc, scale: null };
218
+ p.reader.dispatchEvent('monocle:fontscaling', evtData);
219
+
220
+ // Iterate over each element, removing proportional font-sizing flag
221
+ // and property from cssText.
222
+ walkTree(doc.body, function (elem) {
223
+ if (typeof elem.pfsOriginal == 'undefined') { return; }
224
+ if (elem.pfsApplied) {
225
+ var oprop = elem.pfsOriginalProp;
226
+ var opropDec = oprop ? 'font-size: '+oprop+' ! important;' : '';
227
+ replaceFontSizeInStyle(elem, opropDec);
228
+ elem.pfsApplied = null;
229
+ }
230
+ });
231
+
232
+ // Establish new baselines in case classes have changed.
233
+ sweepElements(doc);
234
+
235
+ p.reader.dispatchEvent('monocle:fontscale', evtData);
236
+ }
237
+ }
238
+
239
+
240
+ function sweepElements(doc) {
241
+ // Iterate over each element, looking at its font size and storing
242
+ // the original value against the element.
243
+ walkTree(doc.body, function (elem) {
244
+ if (elem.getCTM) { return; } // Ignore SVG elements
245
+ var currStyle = doc.defaultView.getComputedStyle(elem, null);
246
+ var fs = parseFloat(currStyle.getPropertyValue('font-size'));
247
+ elem.pfsOriginal = fs;
248
+ elem.pfsOriginalProp = elem.style.fontSize;
249
+ });
250
+ doc.body.pfsSwept = true;
251
+ }
252
+
253
+
254
+ function walkTree(node, fn) {
255
+ if (node.nodeType != 1) { return; }
256
+ fn(node);
257
+ node = node.firstChild;
258
+ while (node) {
259
+ walkTree(node, fn);
260
+ node = node.nextSibling;
261
+ }
262
+ }
263
+
264
+
265
+ function fsProperty(fsInPixels) {
266
+ return 'font-size: '+fsInPixels+'px ! important;';
267
+ }
268
+
269
+
270
+ function replaceFontSizeInStyle(elem, newProp) {
271
+ var lastFs = /font-size:[^;]/
272
+ elem.style.cssText = elem.style.cssText.replace(lastFs, newProp);
273
+ }
274
+
275
+
276
+ API.addPageStyles = addPageStyles;
277
+ API.updatePageStyles = updatePageStyles;
278
+ API.removePageStyles = removePageStyles;
279
+ API.setFontScale = setFontScale;
280
+
281
+ initialize();
282
+
283
+ return API;
284
+ }
285
+
286
+
287
+
288
+ Monocle.Formatting.DEFAULT_STYLE_RULES = [
289
+ "html#RS\\:monocle * {" +
290
+ "-webkit-font-smoothing: subpixel-antialiased;" +
291
+ "text-rendering: auto !important;" +
292
+ "word-wrap: break-word !important;" +
293
+ "overflow: visible !important;" +
294
+ "}",
295
+ "html#RS\\:monocle body {" +
296
+ "margin: 0 !important;"+
297
+ "border: none !important;" +
298
+ "padding: 0 !important;" +
299
+ "width: 100% !important;" +
300
+ "position: absolute !important;" +
301
+ "-webkit-text-size-adjust: none;" +
302
+ "-ms-touch-action: none;" +
303
+ "-ms-content-zooming: none;" +
304
+ "-ms-content-zoom-chaining: chained;" +
305
+ "-ms-content-zoom-limit-min: 100%;" +
306
+ "-ms-content-zoom-limit-max: 100%;" +
307
+ "-ms-touch-select: none;" +
308
+ "}",
309
+ "html#RS\\:monocle body * {" +
310
+ "max-width: 100% !important;" +
311
+ "}",
312
+ "html#RS\\:monocle img, html#RS\\:monocle video, html#RS\\:monocle object, html#RS\\:monocle svg {" +
313
+ "max-height: 95% !important;" +
314
+ "height: auto !important;" +
315
+ "}",
316
+ "a:not([href]) { color: inherit; }"
317
+ ]