Permalink
Browse files

Poll components for selected text, send selection/deselection events.

Listen on Reader for 'monocle:selection' and 'monocle:deselection'. See
test/selection for example code.
  • Loading branch information...
joseph committed Feb 10, 2012
1 parent e852239 commit e09690b66c9f52a04495a843da4657f9c9e8d415
Showing with 90 additions and 2 deletions.
  1. +56 −1 src/core/selection.js
  2. +2 −0 test/events/index.html
  3. +32 −1 test/selection/index.html
View
@@ -2,10 +2,59 @@ Monocle.Selection = function (reader) {
var API = { constructor: Monocle.Selection };
var k = API.constants = API.constructor;
var p = API.properties = {
- reader: reader
+ reader: reader,
+ lastSelection: []
};
+ function initialize() {
+ if (k.SELECTION_POLLING_INTERVAL) {
+ setInterval(pollSelection, k.SELECTION_POLLING_INTERVAL);
+ }
+ }
+
+
+ function pollSelection() {
+ var index = 0, frame = null;
+ while (frame = reader.dom.find('component', index)) {
+ pollSelectionOnWindow(frame.contentWindow, index);
+ index += 1;
+ }
+ }
+
+
+ function pollSelectionOnWindow(win, index) {
+ var sel = win.getSelection();
+ var lm = p.lastSelection[index] || {};
+ var nm = p.lastSelection[index] = {
+ selected: anythingSelected(win),
+ range: sel.rangeCount ? sel.getRangeAt(0) : null,
+ string: sel.toString()
+ };
+ if (nm.selected) {
+ nm.rangeStartContainer = nm.range.startContainer;
+ nm.rangeEndContainer = nm.range.endContainer;
+ nm.rangeStartOffset = nm.range.startOffset;
+ nm.rangeEndOffset = nm.range.endOffset;
+ if (!sameRange(nm, lm)) {
+ p.reader.dispatchEvent('monocle:selection', nm);
+ }
+ } else if (lm.selected) {
+ p.reader.dispatchEvent('monocle:deselection', lm);
+ }
+ }
+
+
+ function sameRange(m1, m2) {
+ return (
+ m1.rangeStartContainer == m2.rangeStartContainer &&
+ m1.rangeEndContainer == m2.rangeEndContainer &&
+ m1.rangeStartOffset == m2.rangeStartOffset &&
+ m1.rangeEndOffset == m2.rangeEndOffset
+ );
+ }
+
+
// Given a window object, remove any user selections within. Trivial in
// most browsers, but involving major mojo on iOS.
//
@@ -86,5 +135,11 @@ Monocle.Selection = function (reader) {
API.deselect = deselect;
+
+ initialize();
+
return API;
}
+
+
+Monocle.Selection.SELECTION_POLLING_INTERVAL = 250;
View
@@ -91,6 +91,8 @@
listenFor('monocle:interactive:off');
listenFor('monocle:controlhide');
listenFor('monocle:controlshow');
+ listenFor('monocle:selection');
+ listenFor('monocle:deselection');
window.reader = Monocle.Reader('reader', bd, options);
}
View
@@ -14,19 +14,47 @@
border: 1px solid #000;
background-color: #CCC;
}
+ #statusSelect {
+ margin: 20px 0;
+ background: #FFC;
+ padding: 6px;
+ visibility: hidden;
+ width: 300px;
+ height: 5em;
+ overflow: auto;
+ }
</style>
<script type="text/javascript" src="../../dist/scripts/monocore.js"></script>
<script>
(function () {
Monocle.DEBUG = true;
+ function textSelected(evt) {
+ console.log("Selection: "+evt.m.string);
+ var st = document.getElementById('statusSelect');
+ var sel = evt.m.string;
+ st.innerHTML = sel;
+ st.style.visibility = 'visible';
+ }
+
+
+ function textDeselected(evt) {
+ console.log("Deselection.");
+ var st = document.getElementById('statusSelect');
+ st.style.visibility = 'hidden';
+ }
+
function init() {
window.reader = Monocle.Reader(
'reader',
Monocle.bookData({ components: ['pt1.html', 'pt2.html'] }),
- { panels: Monocle.Panels.Marginal }
+ { panels: Monocle.Panels.Marginal },
+ function (rdr) {
+ rdr.listen('monocle:selection', textSelected);
+ rdr.listen('monocle:deselection', textDeselected);
+ }
);
}
@@ -44,5 +72,8 @@ <h1>Selection events</h1>
</p>
<div id="reader"></div>
+
+ <div id="statusSelect"></div>
+
</body>
</html>

0 comments on commit e09690b

Please sign in to comment.