monocle-rails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.DS_Store +0 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/monocle/rails.rb +8 -0
- data/lib/monocle/rails/version.rb +5 -0
- data/monocle-rails.gemspec +23 -0
- data/vendor/.DS_Store +0 -0
- data/vendor/assets/.DS_Store +0 -0
- data/vendor/assets/javascripts/.DS_Store +0 -0
- data/vendor/assets/javascripts/compat/browser.js +120 -0
- data/vendor/assets/javascripts/compat/css.js +145 -0
- data/vendor/assets/javascripts/compat/env.js +463 -0
- data/vendor/assets/javascripts/compat/gala.js +469 -0
- data/vendor/assets/javascripts/compat/stubs.js +50 -0
- data/vendor/assets/javascripts/controls/contents.js +59 -0
- data/vendor/assets/javascripts/controls/magnifier.js +51 -0
- data/vendor/assets/javascripts/controls/panel.js +136 -0
- data/vendor/assets/javascripts/controls/placesaver.js +100 -0
- data/vendor/assets/javascripts/controls/scrubber.js +140 -0
- data/vendor/assets/javascripts/controls/spinner.js +99 -0
- data/vendor/assets/javascripts/controls/stencil.js +410 -0
- data/vendor/assets/javascripts/core/billboard.js +120 -0
- data/vendor/assets/javascripts/core/book.js +467 -0
- data/vendor/assets/javascripts/core/bookdata.js +59 -0
- data/vendor/assets/javascripts/core/component.js +413 -0
- data/vendor/assets/javascripts/core/events.js +56 -0
- data/vendor/assets/javascripts/core/factory.js +194 -0
- data/vendor/assets/javascripts/core/formatting.js +317 -0
- data/vendor/assets/javascripts/core/monocle.js +16 -0
- data/vendor/assets/javascripts/core/place.js +210 -0
- data/vendor/assets/javascripts/core/reader.js +683 -0
- data/vendor/assets/javascripts/core/selection.js +158 -0
- data/vendor/assets/javascripts/core/styles.js +155 -0
- data/vendor/assets/javascripts/dimensions/columns.js +218 -0
- data/vendor/assets/javascripts/flippers/instant.js +78 -0
- data/vendor/assets/javascripts/flippers/scroller.js +128 -0
- data/vendor/assets/javascripts/flippers/slider.js +469 -0
- data/vendor/assets/javascripts/monocore.js +27 -0
- data/vendor/assets/javascripts/monoctrl.js +1 -0
- data/vendor/assets/javascripts/panels/eink.js +61 -0
- data/vendor/assets/javascripts/panels/imode.js +180 -0
- data/vendor/assets/javascripts/panels/magic.js +297 -0
- data/vendor/assets/javascripts/panels/marginal.js +50 -0
- data/vendor/assets/javascripts/panels/twopane.js +34 -0
- data/vendor/assets/stylesheets/monocore.css +194 -0
- data/vendor/assets/stylesheets/monoctrl.css +168 -0
- metadata +129 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
Monocle.Selection = function (reader) {
|
2
|
+
var API = { constructor: Monocle.Selection };
|
3
|
+
var k = API.constants = API.constructor;
|
4
|
+
var p = API.properties = {
|
5
|
+
reader: reader,
|
6
|
+
lastSelection: []
|
7
|
+
};
|
8
|
+
|
9
|
+
|
10
|
+
function initialize() {
|
11
|
+
if (k.SELECTION_POLLING_INTERVAL) {
|
12
|
+
setInterval(pollSelection, k.SELECTION_POLLING_INTERVAL);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
|
17
|
+
function pollSelection() {
|
18
|
+
var index = 0, frame = null;
|
19
|
+
while (frame = reader.dom.find('component', index++)) {
|
20
|
+
if (frame.contentWindow) {
|
21
|
+
pollSelectionOnWindow(frame.contentWindow, index);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
|
27
|
+
function pollSelectionOnWindow(win, index) {
|
28
|
+
var sel = win.getSelection();
|
29
|
+
if (!sel) { return; }
|
30
|
+
var lm = p.lastSelection[index] || {};
|
31
|
+
var nm = p.lastSelection[index] = {
|
32
|
+
selected: anythingSelected(win),
|
33
|
+
range: sel.rangeCount ? sel.getRangeAt(0) : null,
|
34
|
+
string: sel.toString()
|
35
|
+
};
|
36
|
+
if (nm.selected) {
|
37
|
+
nm.rangeStartContainer = nm.range.startContainer;
|
38
|
+
nm.rangeEndContainer = nm.range.endContainer;
|
39
|
+
nm.rangeStartOffset = nm.range.startOffset;
|
40
|
+
nm.rangeEndOffset = nm.range.endOffset;
|
41
|
+
if (!sameRange(nm, lm)) {
|
42
|
+
p.reader.dispatchEvent('monocle:selection', nm);
|
43
|
+
}
|
44
|
+
} else if (lm.selected) {
|
45
|
+
p.reader.dispatchEvent('monocle:deselection', lm);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
function sameRange(m1, m2) {
|
51
|
+
return (
|
52
|
+
m1.rangeStartContainer == m2.rangeStartContainer &&
|
53
|
+
m1.rangeEndContainer == m2.rangeEndContainer &&
|
54
|
+
m1.rangeStartOffset == m2.rangeStartOffset &&
|
55
|
+
m1.rangeEndOffset == m2.rangeEndOffset
|
56
|
+
);
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
// Given a window object, remove any user selections within. Trivial in
|
61
|
+
// most browsers, but involving major mojo on iOS.
|
62
|
+
//
|
63
|
+
function deselect() {
|
64
|
+
var index = 0, frame = null;
|
65
|
+
while (frame = reader.dom.find('component', index++)) {
|
66
|
+
deselectOnWindow(frame.contentWindow);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
function deselectOnWindow(win) {
|
72
|
+
win = win || window;
|
73
|
+
if (!anythingSelected(win)) { return; }
|
74
|
+
|
75
|
+
if (Monocle.Browser.iOSVersion && !Monocle.Browser.iOSVersionBelow(5)) {
|
76
|
+
preservingScale(function () {
|
77
|
+
preservingScrollPosition(function () {
|
78
|
+
var inp = document.createElement('input');
|
79
|
+
inp.style.cssText = [
|
80
|
+
'position: absolute',
|
81
|
+
'top: 0',
|
82
|
+
'left: 0',
|
83
|
+
'width: 0',
|
84
|
+
'height: 0'
|
85
|
+
].join(';');
|
86
|
+
document.body.appendChild(inp);
|
87
|
+
inp.focus();
|
88
|
+
document.body.removeChild(inp);
|
89
|
+
})
|
90
|
+
});
|
91
|
+
}
|
92
|
+
|
93
|
+
var sel = win.getSelection();
|
94
|
+
sel.removeAllRanges();
|
95
|
+
win.document.body.scrollLeft = 0;
|
96
|
+
win.document.body.scrollTop = 0;
|
97
|
+
}
|
98
|
+
|
99
|
+
|
100
|
+
function preservingScrollPosition(fn) {
|
101
|
+
var sx = window.scrollX, sy = window.scrollY;
|
102
|
+
fn();
|
103
|
+
window.scrollTo(sx, sy);
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
function preservingScale(fn) {
|
108
|
+
var head = document.querySelector('head');
|
109
|
+
var ovp = head.querySelector('meta[name=viewport]');
|
110
|
+
var createViewportMeta = function (content) {
|
111
|
+
var elem = document.createElement('meta');
|
112
|
+
elem.setAttribute('name', 'viewport');
|
113
|
+
elem.setAttribute('content', content);
|
114
|
+
head.appendChild(elem);
|
115
|
+
return elem;
|
116
|
+
}
|
117
|
+
|
118
|
+
var nvp;
|
119
|
+
if (ovp) {
|
120
|
+
var ovpcontent = ovp.getAttribute('content');
|
121
|
+
var re = /user-scalable\s*=\s*([^,$\s])*/;
|
122
|
+
var result = ovpcontent.match(re);
|
123
|
+
if (result && ['no', '0'].indexOf(result[1]) >= 0) {
|
124
|
+
fn();
|
125
|
+
} else {
|
126
|
+
var nvpcontent = ovpcontent.replace(re, '');
|
127
|
+
nvpcontent += nvpcontent ? ', ' : '';
|
128
|
+
nvpcontent += 'user-scalable=no';
|
129
|
+
head.removeChild(ovp);
|
130
|
+
nvp = createViewportMeta(nvpcontent);
|
131
|
+
fn();
|
132
|
+
head.removeChild(nvp);
|
133
|
+
head.appendChild(ovp);
|
134
|
+
}
|
135
|
+
} else {
|
136
|
+
nvp = createViewportMeta('user-scalable=no');
|
137
|
+
fn();
|
138
|
+
nvp.setAttribute('content', 'user-scalable=yes');
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
function anythingSelected(win) {
|
144
|
+
var sel = win.getSelection();
|
145
|
+
return sel && !sel.isCollapsed;
|
146
|
+
}
|
147
|
+
|
148
|
+
|
149
|
+
API.deselect = deselect;
|
150
|
+
|
151
|
+
|
152
|
+
initialize();
|
153
|
+
|
154
|
+
return API;
|
155
|
+
}
|
156
|
+
|
157
|
+
|
158
|
+
Monocle.Selection.SELECTION_POLLING_INTERVAL = 250;
|
@@ -0,0 +1,155 @@
|
|
1
|
+
Monocle.Styles = {
|
2
|
+
|
3
|
+
// Takes a hash and returns a string.
|
4
|
+
rulesToString: function (rules) {
|
5
|
+
if (typeof rules != 'string') {
|
6
|
+
var parts = [];
|
7
|
+
for (var declaration in rules) {
|
8
|
+
parts.push(declaration+": "+rules[declaration]+";")
|
9
|
+
}
|
10
|
+
rules = parts.join(" ");
|
11
|
+
}
|
12
|
+
return rules;
|
13
|
+
},
|
14
|
+
|
15
|
+
|
16
|
+
// Takes a hash or string of CSS property assignments and applies them
|
17
|
+
// to the element.
|
18
|
+
//
|
19
|
+
applyRules: function (elem, rules) {
|
20
|
+
rules = Monocle.Styles.rulesToString(rules);
|
21
|
+
elem.style.cssText += ';'+rules;
|
22
|
+
return elem.style.cssText;
|
23
|
+
},
|
24
|
+
|
25
|
+
|
26
|
+
// Generates cross-browser properties for a given property.
|
27
|
+
// ie, affix(<elem>, 'transition', 'linear 100ms') would apply that value
|
28
|
+
// to webkitTransition for WebKit browsers, and to MozTransition for Gecko.
|
29
|
+
//
|
30
|
+
affix: function (elem, property, value) {
|
31
|
+
var target = elem.style ? elem.style : elem;
|
32
|
+
var props = Monocle.Browser.css.toDOMProps(property);
|
33
|
+
while (props.length) { target[props.shift()] = value; }
|
34
|
+
},
|
35
|
+
|
36
|
+
|
37
|
+
setX: function (elem, x) {
|
38
|
+
var s = elem.style;
|
39
|
+
if (typeof x == "number") { x += "px"; }
|
40
|
+
var val = Monocle.Browser.env.supportsTransform3d ?
|
41
|
+
'translate3d('+x+', 0, 0)' :
|
42
|
+
'translateX('+x+')';
|
43
|
+
val = (x == '0px') ? 'none' : val;
|
44
|
+
s.webkitTransform = s.MozTransform = s.OTransform = s.transform = val;
|
45
|
+
return x;
|
46
|
+
},
|
47
|
+
|
48
|
+
|
49
|
+
setY: function (elem, y) {
|
50
|
+
var s = elem.style;
|
51
|
+
if (typeof y == "number") { y += "px"; }
|
52
|
+
var val = Monocle.Browser.env.supportsTransform3d ?
|
53
|
+
'translate3d(0, '+y+', 0)' :
|
54
|
+
'translateY('+y+')';
|
55
|
+
val = (y == '0px') ? 'none' : val;
|
56
|
+
s.webkitTransform = s.MozTransform = s.OTransform = s.transform = val;
|
57
|
+
return y;
|
58
|
+
},
|
59
|
+
|
60
|
+
|
61
|
+
getX: function (elem) {
|
62
|
+
var currStyle = document.defaultView.getComputedStyle(elem, null);
|
63
|
+
var re = /matrix\([^,]+,[^,]+,[^,]+,[^,]+,\s*([^,]+),[^\)]+\)/;
|
64
|
+
var props = Monocle.Browser.css.toDOMProps('transform');
|
65
|
+
var matrix = null;
|
66
|
+
while (props.length && !matrix) {
|
67
|
+
matrix = currStyle[props.shift()];
|
68
|
+
}
|
69
|
+
return parseInt(matrix.match(re)[1], 10);
|
70
|
+
},
|
71
|
+
|
72
|
+
|
73
|
+
transitionFor: function (elem, prop, duration, timing, delay) {
|
74
|
+
var tProps = Monocle.Browser.css.toDOMProps('transition');
|
75
|
+
var pProps = Monocle.Browser.css.toCSSProps(prop);
|
76
|
+
timing = timing || "linear";
|
77
|
+
delay = (delay || 0)+"ms";
|
78
|
+
for (var i = 0, ii = tProps.length; i < ii; ++i) {
|
79
|
+
var t = "none";
|
80
|
+
if (duration) {
|
81
|
+
t = [pProps[i], duration+"ms", timing, delay].join(" ");
|
82
|
+
}
|
83
|
+
elem.style[tProps[i]] = t;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
// These rule definitions are more or less compulsory for Monocle to behave
|
91
|
+
// as expected. Which is why they appear here and not in the stylesheet.
|
92
|
+
// Adjust them if you know what you're doing.
|
93
|
+
//
|
94
|
+
Monocle.Styles.container = {
|
95
|
+
"position": "absolute",
|
96
|
+
"overflow": "hidden",
|
97
|
+
"top": "0",
|
98
|
+
"left": "0",
|
99
|
+
"bottom": "0",
|
100
|
+
"right": "0"
|
101
|
+
}
|
102
|
+
|
103
|
+
Monocle.Styles.page = {
|
104
|
+
"position": "absolute",
|
105
|
+
"z-index": "1",
|
106
|
+
"-webkit-user-select": "none",
|
107
|
+
"-moz-user-select": "none",
|
108
|
+
"-ms-user-select": "none",
|
109
|
+
"user-select": "none",
|
110
|
+
"-webkit-transform": "translate3d(0,0,0)",
|
111
|
+
"visibility": "visible"
|
112
|
+
|
113
|
+
/*
|
114
|
+
"background": "white",
|
115
|
+
"top": "0",
|
116
|
+
"left": "0",
|
117
|
+
"bottom": "0",
|
118
|
+
"right": "0"
|
119
|
+
*/
|
120
|
+
}
|
121
|
+
|
122
|
+
Monocle.Styles.sheaf = {
|
123
|
+
"position": "absolute",
|
124
|
+
"overflow": "hidden"
|
125
|
+
|
126
|
+
/*
|
127
|
+
"top": "0",
|
128
|
+
"left": "0",
|
129
|
+
"bottom": "0",
|
130
|
+
"right": "0"
|
131
|
+
*/
|
132
|
+
}
|
133
|
+
|
134
|
+
Monocle.Styles.component = {
|
135
|
+
"width": "100%",
|
136
|
+
"height": "100%",
|
137
|
+
"border": "none",
|
138
|
+
"-webkit-user-select": "none",
|
139
|
+
"-moz-user-select": "none",
|
140
|
+
"-ms-user-select": "none",
|
141
|
+
"user-select": "none"
|
142
|
+
}
|
143
|
+
|
144
|
+
Monocle.Styles.control = {
|
145
|
+
"z-index": "100",
|
146
|
+
"cursor": "pointer"
|
147
|
+
}
|
148
|
+
|
149
|
+
Monocle.Styles.overlay = {
|
150
|
+
"position": "absolute",
|
151
|
+
"display": "none",
|
152
|
+
"width": "100%",
|
153
|
+
"height": "100%",
|
154
|
+
"z-index": "1000"
|
155
|
+
}
|
@@ -0,0 +1,218 @@
|
|
1
|
+
Monocle.Dimensions.Columns = function (pageDiv) {
|
2
|
+
|
3
|
+
var API = { constructor: Monocle.Dimensions.Columns }
|
4
|
+
var k = API.constants = API.constructor;
|
5
|
+
var p = API.properties = {
|
6
|
+
page: pageDiv,
|
7
|
+
reader: pageDiv.m.reader,
|
8
|
+
length: 0,
|
9
|
+
width: 0
|
10
|
+
}
|
11
|
+
|
12
|
+
// Logically, forceColumn browsers can't have a gap, because that would
|
13
|
+
// make the minWidth > 200%. But how much greater? Not worth the effort.
|
14
|
+
k.GAP = Monocle.Browser.env.forceColumns ? 0 : 20;
|
15
|
+
|
16
|
+
function update(callback) {
|
17
|
+
setColumnWidth();
|
18
|
+
Monocle.defer(function () {
|
19
|
+
p.length = columnCount();
|
20
|
+
if (Monocle.DEBUG) {
|
21
|
+
console.log(
|
22
|
+
'page['+p.page.m.pageIndex+'] -> '+p.length+
|
23
|
+
' ('+p.page.m.activeFrame.m.component.properties.id+')'
|
24
|
+
);
|
25
|
+
}
|
26
|
+
callback(p.length);
|
27
|
+
});
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
function setColumnWidth() {
|
32
|
+
var pdims = pageDimensions();
|
33
|
+
var ce = columnedElement();
|
34
|
+
|
35
|
+
p.width = pdims.width;
|
36
|
+
|
37
|
+
var rules = Monocle.Styles.rulesToString(k.STYLE["columned"]);
|
38
|
+
rules += Monocle.Browser.css.toCSSDeclaration('column-width', pdims.col+'px');
|
39
|
+
rules += Monocle.Browser.css.toCSSDeclaration('column-gap', k.GAP+'px');
|
40
|
+
rules += Monocle.Browser.css.toCSSDeclaration('column-fill', 'auto');
|
41
|
+
rules += Monocle.Browser.css.toCSSDeclaration('transform', 'none');
|
42
|
+
|
43
|
+
if (Monocle.Browser.env.forceColumns && ce.scrollHeight > pdims.height) {
|
44
|
+
rules += Monocle.Styles.rulesToString(k.STYLE['column-force']);
|
45
|
+
if (Monocle.DEBUG) {
|
46
|
+
console.warn("Force columns ("+ce.scrollHeight+" > "+pdims.height+")");
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
if (ce.style.cssText != rules) {
|
51
|
+
// Update offset because we're translating to zero.
|
52
|
+
p.page.m.offset = 0;
|
53
|
+
|
54
|
+
// IE10 hack.
|
55
|
+
if (Monocle.Browser.env.documentElementHasScrollbars) {
|
56
|
+
ce.ownerDocument.documentElement.style.overflow = 'hidden';
|
57
|
+
}
|
58
|
+
|
59
|
+
// Apply body style changes.
|
60
|
+
ce.style.cssText = rules;
|
61
|
+
|
62
|
+
if (Monocle.Browser.env.scrollToApplyStyle) {
|
63
|
+
ce.scrollLeft = 0;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
// Returns the element to which columns CSS should be applied.
|
70
|
+
//
|
71
|
+
function columnedElement() {
|
72
|
+
return p.page.m.activeFrame.contentDocument.body;
|
73
|
+
}
|
74
|
+
|
75
|
+
|
76
|
+
// Returns the width of the offsettable area of the columned element. By
|
77
|
+
// definition, the number of pages is always this divided by the
|
78
|
+
// width of a single page (eg, the client area of the columned element).
|
79
|
+
//
|
80
|
+
function columnedWidth() {
|
81
|
+
var bd = columnedElement();
|
82
|
+
var de = p.page.m.activeFrame.contentDocument.documentElement;
|
83
|
+
|
84
|
+
var w = Math.max(bd.scrollWidth, de.scrollWidth);
|
85
|
+
|
86
|
+
// Add one because the final column doesn't have right gutter.
|
87
|
+
// w += k.GAP;
|
88
|
+
|
89
|
+
if (!Monocle.Browser.env.widthsIgnoreTranslate && p.page.m.offset) {
|
90
|
+
w += p.page.m.offset;
|
91
|
+
}
|
92
|
+
return w;
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
function pageDimensions() {
|
97
|
+
var elem = p.page.m.sheafDiv;
|
98
|
+
var w = elem.clientWidth;
|
99
|
+
if (elem.getBoundingClientRect) { w = elem.getBoundingClientRect().width; }
|
100
|
+
if (Monocle.Browser.env.roundPageDimensions) { w = Math.round(w); }
|
101
|
+
return { col: w, width: w + k.GAP, height: elem.clientHeight }
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
function columnCount() {
|
106
|
+
return Math.ceil(columnedWidth() / pageDimensions().width)
|
107
|
+
}
|
108
|
+
|
109
|
+
|
110
|
+
function locusToOffset(locus) {
|
111
|
+
return pageDimensions().width * (locus.page - 1);
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
// Moves the columned element to the offset implied by the locus.
|
116
|
+
//
|
117
|
+
// The 'transition' argument is optional, allowing the translation to be
|
118
|
+
// animated. If not given, no change is made to the columned element's
|
119
|
+
// transition property.
|
120
|
+
//
|
121
|
+
function translateToLocus(locus, transition) {
|
122
|
+
var offset = locusToOffset(locus);
|
123
|
+
p.page.m.offset = offset;
|
124
|
+
translateToOffset(offset, transition);
|
125
|
+
return offset;
|
126
|
+
}
|
127
|
+
|
128
|
+
|
129
|
+
function translateToOffset(offset, transition) {
|
130
|
+
var ce = columnedElement();
|
131
|
+
if (transition) {
|
132
|
+
Monocle.Styles.affix(ce, "transition", transition);
|
133
|
+
}
|
134
|
+
// NB: can't use setX as it causes a flicker on iOS.
|
135
|
+
Monocle.Styles.affix(ce, "transform", "translateX(-"+offset+"px)");
|
136
|
+
}
|
137
|
+
|
138
|
+
|
139
|
+
function percentageThroughOfNode(target) {
|
140
|
+
if (!target) { return 0; }
|
141
|
+
var doc = p.page.m.activeFrame.contentDocument;
|
142
|
+
var offset = 0;
|
143
|
+
if (Monocle.Browser.env.findNodesByScrolling) {
|
144
|
+
// First, remove translation...
|
145
|
+
translateToOffset(0);
|
146
|
+
|
147
|
+
// Store scroll offsets for all windows.
|
148
|
+
var win, s;
|
149
|
+
win = s = p.page.m.activeFrame.contentWindow;
|
150
|
+
var scrollers = [
|
151
|
+
[win, win.scrollX, win.scrollY],
|
152
|
+
[window, window.scrollX, window.scrollY]
|
153
|
+
];
|
154
|
+
//while (s != s.parent) { scrollers.push([s, s.scrollX]); s = s.parent; }
|
155
|
+
|
156
|
+
var scroller, x;
|
157
|
+
if (Monocle.Browser.env.sheafIsScroller) {
|
158
|
+
scroller = p.page.m.sheafDiv;
|
159
|
+
x = scroller.scrollLeft;
|
160
|
+
target.scrollIntoView();
|
161
|
+
offset = scroller.scrollLeft;
|
162
|
+
} else {
|
163
|
+
scroller = win;
|
164
|
+
x = scroller.scrollX;
|
165
|
+
target.scrollIntoView();
|
166
|
+
offset = scroller.scrollX;
|
167
|
+
}
|
168
|
+
|
169
|
+
// Restore scroll offsets for all windows.
|
170
|
+
while (s = scrollers.shift()) {
|
171
|
+
s[0].scrollTo(s[1], s[2]);
|
172
|
+
}
|
173
|
+
|
174
|
+
// ... finally, replace translation.
|
175
|
+
translateToOffset(p.page.m.offset);
|
176
|
+
} else {
|
177
|
+
offset = target.getBoundingClientRect().left;
|
178
|
+
offset -= doc.body.getBoundingClientRect().left;
|
179
|
+
}
|
180
|
+
|
181
|
+
// We know at least 1px will be visible, and offset should not be 0.
|
182
|
+
offset += 1;
|
183
|
+
|
184
|
+
// Percent is the offset divided by the total width of the component.
|
185
|
+
var percent = offset / (p.length * p.width);
|
186
|
+
|
187
|
+
// Page number would be offset divided by the width of a single page.
|
188
|
+
// var pageNum = Math.ceil(offset / pageDimensions().width);
|
189
|
+
|
190
|
+
return percent;
|
191
|
+
}
|
192
|
+
|
193
|
+
|
194
|
+
API.update = update;
|
195
|
+
API.percentageThroughOfNode = percentageThroughOfNode;
|
196
|
+
|
197
|
+
API.locusToOffset = locusToOffset;
|
198
|
+
API.translateToLocus = translateToLocus;
|
199
|
+
|
200
|
+
return API;
|
201
|
+
}
|
202
|
+
|
203
|
+
|
204
|
+
Monocle.Dimensions.Columns.STYLE = {
|
205
|
+
// Most of these are already applied to body, but they're repeated here
|
206
|
+
// in case columnedElement() is ever anything other than body.
|
207
|
+
"columned": {
|
208
|
+
"margin": "0",
|
209
|
+
"padding": "0",
|
210
|
+
"height": "100%",
|
211
|
+
"width": "100%",
|
212
|
+
"position": "absolute"
|
213
|
+
},
|
214
|
+
"column-force": {
|
215
|
+
"min-width": "200%",
|
216
|
+
"overflow": "hidden"
|
217
|
+
}
|
218
|
+
}
|