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.
- 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,27 @@
|
|
1
|
+
//= require ./core/monocle
|
2
|
+
//= require ./compat/env
|
3
|
+
//= require ./compat/css
|
4
|
+
//= require ./compat/stubs
|
5
|
+
//= require ./compat/browser
|
6
|
+
//= require ./compat/gala
|
7
|
+
//= require ./core/bookdata
|
8
|
+
//= require ./core/factory
|
9
|
+
//= require ./core/events
|
10
|
+
//= require ./core/styles
|
11
|
+
//= require ./core/formatting
|
12
|
+
//= require ./core/reader
|
13
|
+
//= require ./core/book
|
14
|
+
//= require ./core/place
|
15
|
+
//= require ./core/component
|
16
|
+
//= require ./core/selection
|
17
|
+
//= require ./core/billboard
|
18
|
+
//= require ./controls/panel
|
19
|
+
//= require ./panels/twopane
|
20
|
+
//= require ./panels/imode
|
21
|
+
//= require ./panels/eink
|
22
|
+
//= require ./panels/marginal
|
23
|
+
//= require ./panels/magic
|
24
|
+
//= require ./dimensions/columns
|
25
|
+
//= require ./flippers/slider
|
26
|
+
//= require ./flippers/scroller
|
27
|
+
//= require ./flippers/instant
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree ./controls
|
@@ -0,0 +1,61 @@
|
|
1
|
+
Monocle.Panels.eInk = function (flipper, evtCallbacks) {
|
2
|
+
|
3
|
+
var API = { constructor: Monocle.Panels.eInk }
|
4
|
+
var k = API.constants = API.constructor;
|
5
|
+
var p = API.properties = {
|
6
|
+
flipper: flipper
|
7
|
+
}
|
8
|
+
|
9
|
+
|
10
|
+
function initialize() {
|
11
|
+
p.panel = new Monocle.Controls.Panel();
|
12
|
+
p.reader = p.flipper.properties.reader;
|
13
|
+
p.reader.addControl(p.panel);
|
14
|
+
|
15
|
+
p.panel.listenTo({ end: function (panel, x) {
|
16
|
+
if (x < p.panel.properties.div.offsetWidth / 2) {
|
17
|
+
p.panel.setDirection(flipper.constants.BACKWARDS);
|
18
|
+
} else {
|
19
|
+
p.panel.setDirection(flipper.constants.FORWARDS);
|
20
|
+
}
|
21
|
+
evtCallbacks.end(panel, x);
|
22
|
+
} });
|
23
|
+
|
24
|
+
var s = p.panel.properties.div.style;
|
25
|
+
p.reader.listen("monocle:componentchanging", function () {
|
26
|
+
s.opacity = 1;
|
27
|
+
Monocle.defer(function () { s.opacity = 0 }, 40);
|
28
|
+
});
|
29
|
+
s.width = "100%";
|
30
|
+
s.background = "#000";
|
31
|
+
s.opacity = 0;
|
32
|
+
|
33
|
+
if (k.LISTEN_FOR_KEYS) {
|
34
|
+
Monocle.Events.listen(window.top.document, 'keyup', handleKeyEvent);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
function handleKeyEvent(evt) {
|
40
|
+
var eventCharCode = evt.charCode || evt.keyCode;
|
41
|
+
var dir = null;
|
42
|
+
if (eventCharCode == k.KEYS["PAGEUP"]) {
|
43
|
+
dir = flipper.constants.BACKWARDS;
|
44
|
+
} else if (eventCharCode == k.KEYS["PAGEDOWN"]) {
|
45
|
+
dir = flipper.constants.FORWARDS;
|
46
|
+
}
|
47
|
+
if (dir) {
|
48
|
+
flipper.moveTo({ direction: dir });
|
49
|
+
evt.preventDefault();
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
initialize();
|
55
|
+
|
56
|
+
return API;
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
Monocle.Panels.eInk.LISTEN_FOR_KEYS = true;
|
61
|
+
Monocle.Panels.eInk.KEYS = { "PAGEUP": 33, "PAGEDOWN": 34 };
|
@@ -0,0 +1,180 @@
|
|
1
|
+
// A three-pane system of page interaction. The left 33% turns backwards, the
|
2
|
+
// right 33% turns forwards, and contact on the middle third causes the
|
3
|
+
// system to go into "interactive mode". In this mode, the page-flipping panels
|
4
|
+
// are only active in the margins, and all of the actual text content of the
|
5
|
+
// book is selectable. The user can exit "interactive mode" by hitting the little
|
6
|
+
// IMode icon in the lower right corner of the reader.
|
7
|
+
//
|
8
|
+
Monocle.Panels.IMode = function (flipper, evtCallbacks) {
|
9
|
+
|
10
|
+
var API = { constructor: Monocle.Panels.IMode }
|
11
|
+
var k = API.constants = API.constructor;
|
12
|
+
var p = API.properties = {}
|
13
|
+
|
14
|
+
|
15
|
+
function initialize() {
|
16
|
+
p.flipper = flipper;
|
17
|
+
p.reader = flipper.properties.reader;
|
18
|
+
p.panels = {
|
19
|
+
forwards: new Monocle.Controls.Panel(),
|
20
|
+
backwards: new Monocle.Controls.Panel()
|
21
|
+
}
|
22
|
+
p.divs = {}
|
23
|
+
|
24
|
+
for (var dir in p.panels) {
|
25
|
+
p.reader.addControl(p.panels[dir]);
|
26
|
+
p.divs[dir] = p.panels[dir].properties.div;
|
27
|
+
p.panels[dir].listenTo(evtCallbacks);
|
28
|
+
p.panels[dir].setDirection(flipper.constants[dir.toUpperCase()]);
|
29
|
+
p.divs[dir].style.width = "33%";
|
30
|
+
p.divs[dir].style[dir == "forwards" ? "right" : "left"] = 0;
|
31
|
+
}
|
32
|
+
|
33
|
+
p.panels.central = new Monocle.Controls.Panel();
|
34
|
+
p.reader.addControl(p.panels.central);
|
35
|
+
p.divs.central = p.panels.central.properties.div;
|
36
|
+
p.divs.central.dom.setStyles({ left: "33%", width: "34%" });
|
37
|
+
menuCallbacks({ end: modeOn });
|
38
|
+
|
39
|
+
for (dir in p.panels) {
|
40
|
+
p.divs[dir].dom.addClass('panels_imode_panel');
|
41
|
+
p.divs[dir].dom.addClass('panels_imode_'+dir+'Panel');
|
42
|
+
}
|
43
|
+
|
44
|
+
p.toggleIcon = {
|
45
|
+
createControlElements: function (cntr) {
|
46
|
+
var div = cntr.dom.make('div', 'panels_imode_toggleIcon');
|
47
|
+
Monocle.Events.listenForTap(div, modeOff);
|
48
|
+
return div;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
p.reader.addControl(p.toggleIcon, null, { hidden: true });
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
function menuCallbacks(callbacks) {
|
56
|
+
p.menuCallbacks = callbacks;
|
57
|
+
p.panels.central.listenTo(p.menuCallbacks);
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
function toggle() {
|
62
|
+
p.interactive ? modeOff() : modeOn();
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
function modeOn() {
|
67
|
+
if (p.interactive) {
|
68
|
+
return;
|
69
|
+
}
|
70
|
+
|
71
|
+
p.panels.central.contract();
|
72
|
+
|
73
|
+
var page = p.reader.visiblePages()[0];
|
74
|
+
var sheaf = page.m.sheafDiv;
|
75
|
+
var bw = sheaf.offsetLeft;
|
76
|
+
var fw = page.offsetWidth - (sheaf.offsetLeft + sheaf.offsetWidth);
|
77
|
+
bw = Math.floor(((bw - 2) / page.offsetWidth) * 10000 / 100 ) + "%";
|
78
|
+
fw = Math.floor(((fw - 2) / page.offsetWidth) * 10000 / 100 ) + "%";
|
79
|
+
|
80
|
+
startCameo(function () {
|
81
|
+
p.divs.forwards.style.width = fw;
|
82
|
+
p.divs.backwards.style.width = bw;
|
83
|
+
Monocle.Styles.affix(p.divs.central, 'transform', 'translateY(-100%)');
|
84
|
+
});
|
85
|
+
|
86
|
+
p.reader.showControl(p.toggleIcon);
|
87
|
+
|
88
|
+
p.interactive = true;
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
function modeOff() {
|
93
|
+
if (!p.interactive) {
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
|
97
|
+
p.panels.central.contract();
|
98
|
+
|
99
|
+
p.reader.selection.deselect();
|
100
|
+
|
101
|
+
startCameo(function () {
|
102
|
+
p.divs.forwards.style.width = "33%";
|
103
|
+
p.divs.backwards.style.width = "33%";
|
104
|
+
Monocle.Styles.affix(p.divs.central, 'transform', 'translateY(0)');
|
105
|
+
});
|
106
|
+
|
107
|
+
p.reader.hideControl(p.toggleIcon);
|
108
|
+
|
109
|
+
p.interactive = false;
|
110
|
+
}
|
111
|
+
|
112
|
+
|
113
|
+
function startCameo(fn) {
|
114
|
+
// Set transitions on the panels.
|
115
|
+
var trn = Monocle.Panels.IMode.CAMEO_DURATION+"ms ease-in";
|
116
|
+
Monocle.Styles.affix(p.divs.forwards, 'transition', "width "+trn);
|
117
|
+
Monocle.Styles.affix(p.divs.backwards, 'transition', "width "+trn);
|
118
|
+
Monocle.Styles.affix(p.divs.central, 'transition', "-webkit-transform "+trn);
|
119
|
+
|
120
|
+
// Temporarily disable listeners.
|
121
|
+
for (var pan in p.panels) {
|
122
|
+
p.panels[pan].deafen();
|
123
|
+
}
|
124
|
+
|
125
|
+
// Set the panels to opaque.
|
126
|
+
for (var div in p.divs) {
|
127
|
+
p.divs[div].style.opacity = 1;
|
128
|
+
}
|
129
|
+
|
130
|
+
if (typeof WebkitTransitionEvent != "undefined") {
|
131
|
+
p.cameoListener = Monocle.Events.listen(
|
132
|
+
p.divs.central,
|
133
|
+
'webkitTransitionEnd',
|
134
|
+
endCameo
|
135
|
+
);
|
136
|
+
} else {
|
137
|
+
setTimeout(endCameo, k.CAMEO_DURATION);
|
138
|
+
}
|
139
|
+
fn();
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
function endCameo() {
|
144
|
+
setTimeout(function () {
|
145
|
+
// Remove panel transitions.
|
146
|
+
var trn = "opacity linear " + Monocle.Panels.IMode.LINGER_DURATION + "ms";
|
147
|
+
Monocle.Styles.affix(p.divs.forwards, 'transition', trn);
|
148
|
+
Monocle.Styles.affix(p.divs.backwards, 'transition', trn);
|
149
|
+
Monocle.Styles.affix(p.divs.central, 'transition', trn);
|
150
|
+
|
151
|
+
// Set the panels to transparent.
|
152
|
+
for (var div in p.divs) {
|
153
|
+
p.divs[div].style.opacity = 0;
|
154
|
+
}
|
155
|
+
|
156
|
+
// Re-enable listeners.
|
157
|
+
p.panels.forwards.listenTo(evtCallbacks);
|
158
|
+
p.panels.backwards.listenTo(evtCallbacks);
|
159
|
+
p.panels.central.listenTo(p.menuCallbacks);
|
160
|
+
}, Monocle.Panels.IMode.LINGER_DURATION);
|
161
|
+
|
162
|
+
|
163
|
+
if (p.cameoListener) {
|
164
|
+
Monocle.Events.deafen(p.divs.central, 'webkitTransitionEnd', endCameo);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
|
169
|
+
API.toggle = toggle;
|
170
|
+
API.modeOn = modeOn;
|
171
|
+
API.modeOff = modeOff;
|
172
|
+
API.menuCallbacks = menuCallbacks;
|
173
|
+
|
174
|
+
initialize();
|
175
|
+
|
176
|
+
return API;
|
177
|
+
}
|
178
|
+
|
179
|
+
Monocle.Panels.IMode.CAMEO_DURATION = 250;
|
180
|
+
Monocle.Panels.IMode.LINGER_DURATION = 250;
|
@@ -0,0 +1,297 @@
|
|
1
|
+
Monocle.Panels.Magic = function (flipper, evtCallbacks) {
|
2
|
+
|
3
|
+
var API = { constructor: Monocle.Panels.Magic }
|
4
|
+
var k = API.constants = API.constructor;
|
5
|
+
var p = API.properties = {
|
6
|
+
flipper: flipper,
|
7
|
+
evtCallbacks: evtCallbacks,
|
8
|
+
parts: {},
|
9
|
+
action: {},
|
10
|
+
contacts: [],
|
11
|
+
startListeners: [],
|
12
|
+
disabled: false
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
function initialize() {
|
17
|
+
p.reader = flipper.properties.reader;
|
18
|
+
p.parts = {
|
19
|
+
reader: p.reader.dom.find('box'),
|
20
|
+
cmpts: []
|
21
|
+
}
|
22
|
+
for (var i = 0; i < p.flipper.pageCount; ++i) {
|
23
|
+
p.parts.cmpts.push(p.reader.dom.find('component', i));
|
24
|
+
}
|
25
|
+
initListeners();
|
26
|
+
|
27
|
+
p.reader.listen('monocle:componentmodify', initListeners);
|
28
|
+
p.reader.listen('monocle:magic:init', initListeners);
|
29
|
+
p.reader.listen('monocle:magic:halt', haltListeners);
|
30
|
+
p.reader.listen('monocle:modal:on', disable);
|
31
|
+
p.reader.listen('monocle:modal:off', enable);
|
32
|
+
Monocle.Events.listen(window, 'gala:contact:cancel', resetAction);
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
function initListeners(evt) {
|
37
|
+
//console.log('magic:init');
|
38
|
+
stopListening();
|
39
|
+
startListening();
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
function haltListeners(evt) {
|
44
|
+
//console.log('magic:halt');
|
45
|
+
stopListening();
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
function disable(evt) {
|
50
|
+
//console.log('modal:on - halting magic');
|
51
|
+
stopListening();
|
52
|
+
p.disabled = true;
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
function enable(evt) {
|
57
|
+
//console.log('modal:off - initing magic');
|
58
|
+
p.disabled = false;
|
59
|
+
startListening();
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
function startListening() {
|
64
|
+
if (p.disabled || p.startListeners.length) { return; }
|
65
|
+
|
66
|
+
p.startListeners.push([
|
67
|
+
p.parts.reader,
|
68
|
+
Monocle.Events.listenForContact(
|
69
|
+
p.parts.reader,
|
70
|
+
{ 'start': translatorFunction(p.parts.reader, readerContactStart) }
|
71
|
+
)
|
72
|
+
]);
|
73
|
+
|
74
|
+
for (var i = 0, ii = p.parts.cmpts.length; i < ii; ++i) {
|
75
|
+
p.startListeners.push([
|
76
|
+
p.parts.cmpts[i].contentDocument.defaultView,
|
77
|
+
Monocle.Events.listenForContact(
|
78
|
+
p.parts.cmpts[i].contentDocument.defaultView,
|
79
|
+
{ 'start': translatorFunction(p.parts.cmpts[i], cmptContactStart) }
|
80
|
+
)
|
81
|
+
]);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
function stopListening() {
|
87
|
+
if (p.disabled || !p.startListeners.length) { return; }
|
88
|
+
for (var j = 0, jj = p.startListeners.length; j < jj; ++j) {
|
89
|
+
Monocle.Events.deafenForContact(
|
90
|
+
p.startListeners[j][0],
|
91
|
+
p.startListeners[j][1]
|
92
|
+
);
|
93
|
+
}
|
94
|
+
p.startListeners = [];
|
95
|
+
}
|
96
|
+
|
97
|
+
|
98
|
+
function listenForMoveAndEnd(fnMove, fnEnd) {
|
99
|
+
listenOnElem(
|
100
|
+
document.defaultView,
|
101
|
+
translatorFunction(document.documentElement, fnMove),
|
102
|
+
translatorFunction(document.documentElement, fnEnd)
|
103
|
+
);
|
104
|
+
for (var i = 0, ii = p.parts.cmpts.length; i < ii; ++i) {
|
105
|
+
listenOnElem(
|
106
|
+
p.parts.cmpts[i].contentDocument.defaultView,
|
107
|
+
translatorFunction(p.parts.cmpts[i], fnMove),
|
108
|
+
translatorFunction(p.parts.cmpts[i], fnEnd)
|
109
|
+
);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
function listenOnElem(elem, fnMove, fnEnd) {
|
115
|
+
var contactListeners = Monocle.Events.listenForContact(
|
116
|
+
elem,
|
117
|
+
{
|
118
|
+
'move': fnMove,
|
119
|
+
'end': function (evt) { deafenContactListeners(); fnEnd(evt); }
|
120
|
+
}
|
121
|
+
);
|
122
|
+
p.contacts.push([elem, contactListeners]);
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
function deafenContactListeners() {
|
127
|
+
for (var i = 0, ii = p.contacts.length; i < ii; ++i) {
|
128
|
+
Monocle.Events.deafenForContact(p.contacts[i][0], p.contacts[i][1]);
|
129
|
+
}
|
130
|
+
p.contacts = [];
|
131
|
+
}
|
132
|
+
|
133
|
+
|
134
|
+
function readerContactStart(evt) {
|
135
|
+
listenForMoveAndEnd(readerContactMove, readerContactEnd);
|
136
|
+
p.action.startX = evt.m.readerX;
|
137
|
+
p.action.startY = evt.m.readerY;
|
138
|
+
p.action.screenX = evt.m.screenX;
|
139
|
+
p.action.screenY = evt.m.screenY;
|
140
|
+
p.action.dir = evt.m.readerX > halfway() ? k.FORWARDS : k.BACKWARDS;
|
141
|
+
p.action.handled = !dispatch('monocle:magic:contact:start', evt);
|
142
|
+
if (!p.action.handled) { invoke('start', evt); }
|
143
|
+
}
|
144
|
+
|
145
|
+
|
146
|
+
function readerContactMove(evt) {
|
147
|
+
if (p.action.handled) {
|
148
|
+
dispatch('monocle:magic:contact:move', evt);
|
149
|
+
} else {
|
150
|
+
invoke('move', evt);
|
151
|
+
}
|
152
|
+
// Can't prevent mousemove, so has no effect there. Preventing default
|
153
|
+
// for touchmove will override scrolling, while still allowing selection.
|
154
|
+
evt.preventDefault();
|
155
|
+
}
|
156
|
+
|
157
|
+
|
158
|
+
function readerContactEnd(evt) {
|
159
|
+
p.action.endX = evt.m.readerX;
|
160
|
+
p.action.endY = evt.m.readerY;
|
161
|
+
if (dispatch('monocle:magic:contact', evt)) { invoke('end', evt); }
|
162
|
+
p.action = {};
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
function cmptContactStart(evt) {
|
167
|
+
if (actionIsCancelled(evt)) { return resetAction(); }
|
168
|
+
p.action.startX = evt.m.readerX;
|
169
|
+
p.action.startY = evt.m.readerY;
|
170
|
+
p.action.screenX = evt.m.screenX;
|
171
|
+
p.action.screenY = evt.m.screenY;
|
172
|
+
listenForMoveAndEnd(cmptContactMove, cmptContactEnd);
|
173
|
+
}
|
174
|
+
|
175
|
+
|
176
|
+
function cmptContactMove(evt) {
|
177
|
+
if (actionIsEmpty()) { return; }
|
178
|
+
if (actionIsCancelled(evt)) { return resetAction(); }
|
179
|
+
|
180
|
+
// Can't prevent mousemove, so has no effect there. Preventing default
|
181
|
+
// for touchmove will override scrolling, while still allowing selection.
|
182
|
+
evt.preventDefault();
|
183
|
+
}
|
184
|
+
|
185
|
+
|
186
|
+
function cmptContactEnd(evt) {
|
187
|
+
if (actionIsEmpty()) { return; }
|
188
|
+
if (actionIsCancelled(evt)) { return resetAction(); }
|
189
|
+
p.action.endX = evt.m.readerX;
|
190
|
+
p.action.endY = evt.m.readerY;
|
191
|
+
if (Math.abs(p.action.endX - p.action.startX) < k.LEEWAY) {
|
192
|
+
p.action.dir = p.action.startX > halfway() ? k.FORWARDS : k.BACKWARDS;
|
193
|
+
} else {
|
194
|
+
p.action.dir = p.action.startX > p.action.endX ? k.FORWARDS : k.BACKWARDS;
|
195
|
+
}
|
196
|
+
|
197
|
+
if (dispatch('monocle:magic:contact', evt)) {
|
198
|
+
invoke('start', evt);
|
199
|
+
invoke('end', evt);
|
200
|
+
}
|
201
|
+
p.action = {};
|
202
|
+
}
|
203
|
+
|
204
|
+
|
205
|
+
// Adds two new properties to evt.m:
|
206
|
+
// - readerX
|
207
|
+
// - readerY
|
208
|
+
//
|
209
|
+
// Calculated as the offset of the click from the top left of reader element.
|
210
|
+
//
|
211
|
+
// Then calls the passed function.
|
212
|
+
//
|
213
|
+
function translatorFunction(registrant, callback) {
|
214
|
+
return function (evt) {
|
215
|
+
translatingReaderOffset(registrant, evt, callback);
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
|
220
|
+
function translatingReaderOffset(registrant, evt, callback) {
|
221
|
+
if (typeof p.action.screenX != 'undefined') {
|
222
|
+
evt.m.readerX = p.action.startX + (evt.m.screenX - p.action.screenX);
|
223
|
+
evt.m.readerY = p.action.startY + (evt.m.screenY - p.action.screenY);
|
224
|
+
} else {
|
225
|
+
var dr = document.documentElement.getBoundingClientRect();
|
226
|
+
var rr = p.parts.reader.getBoundingClientRect();
|
227
|
+
rr = { left: rr.left - dr.left, top: rr.top - dr.top }
|
228
|
+
|
229
|
+
if (evt.view == window) {
|
230
|
+
evt.m.readerX = Math.round(evt.m.pageX - rr.left);
|
231
|
+
evt.m.readerY = Math.round(evt.m.pageY - rr.top);
|
232
|
+
} else {
|
233
|
+
var er = registrant.getBoundingClientRect();
|
234
|
+
er = { left: er.left - dr.left, top: er.top - dr.top }
|
235
|
+
evt.m.readerX = Math.round((er.left - rr.left) + evt.m.clientX);
|
236
|
+
evt.m.readerY = Math.round((er.top - rr.top) + evt.m.clientY);
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
callback(evt);
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
function halfway() {
|
245
|
+
return p.parts.reader.offsetWidth / 2;
|
246
|
+
}
|
247
|
+
|
248
|
+
|
249
|
+
function resetAction() {
|
250
|
+
p.action = {};
|
251
|
+
deafenContactListeners();
|
252
|
+
}
|
253
|
+
|
254
|
+
|
255
|
+
function actionIsCancelled(evt) {
|
256
|
+
var win = evt.target.ownerDocument.defaultView;
|
257
|
+
return (evt.defaultPrevented || !win.getSelection().isCollapsed);
|
258
|
+
}
|
259
|
+
|
260
|
+
|
261
|
+
function actionIsEmpty() {
|
262
|
+
return typeof p.action.startX == 'undefined';
|
263
|
+
}
|
264
|
+
|
265
|
+
|
266
|
+
// Returns true if the event WAS NOT cancelled.
|
267
|
+
function dispatch(evtName, trigger) {
|
268
|
+
var rr = p.parts.reader.getBoundingClientRect();
|
269
|
+
var evtData = {
|
270
|
+
trigger: trigger,
|
271
|
+
start: { x: p.action.startX, y: p.action.startY },
|
272
|
+
end: { x: p.action.endX, y: p.action.endY },
|
273
|
+
max: { x: rr.right - rr.left, y: rr.bottom - rr.top }
|
274
|
+
}
|
275
|
+
return p.reader.dispatchEvent(evtName, evtData, true);
|
276
|
+
}
|
277
|
+
|
278
|
+
|
279
|
+
function invoke(evtType, evt) {
|
280
|
+
if (p.evtCallbacks[evtType]) {
|
281
|
+
p.evtCallbacks[evtType](p.action.dir, evt.m.readerX, evt.m.readerY, API);
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
|
286
|
+
API.enable = enable;
|
287
|
+
API.disable = disable;
|
288
|
+
|
289
|
+
initialize();
|
290
|
+
|
291
|
+
return API;
|
292
|
+
}
|
293
|
+
|
294
|
+
|
295
|
+
Monocle.Panels.Magic.LEEWAY = 3;
|
296
|
+
Monocle.Panels.Magic.FORWARDS = 1;
|
297
|
+
Monocle.Panels.Magic.BACKWARDS = -1;
|