-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathreferencing.js
More file actions
102 lines (79 loc) · 3.05 KB
/
Copy pathreferencing.js
File metadata and controls
102 lines (79 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Put any selected text into the URL's fragment identifier.
var Tracker = require('trackr');
var ReactiveVar = require('trackr-reactive-var');
var TextQuoteAnchor = require('dom-anchor-text-quote');
// Use polyfill for the 'selectionchange' event to support Firefox<45
require('selectionchange-polyfill').start();
var selectorInUrl = require('./oa-selector-in-url');
// Whether module is enabled.
var enabled = new ReactiveVar(false);
// Whether the URL is currently affected by a selection. Read-only.
var active = new ReactiveVar(false);
// Handler for window's selectionchanged event
function onSelectionChange(event) {
// Check if we are still enabled (the event listener will be disabled only when Tracker flushes)
if (enabled.get()) {
var selection = document.getSelection();
processSelection(selection);
}
}
// Turn selection into fragment identifier, update window's URL.
function processSelection(selection) {
if (selection!==null && !selection.isCollapsed) {
// Signal our activity (intended to disable dereferencing).
active.set(true);
Tracker.flush(); // Force update now to prevent race condition with hashchange event.
// Transform selection -> range -> selector -> fragment identifier.
var range = selection.getRangeAt(0);
var selector = TextQuoteAnchor.fromRange(document.body, range).toSelector();
var fragmentIdentifier = selectorInUrl.fragmentIdentifierFromSelector(selector);
if (active.get()) {
// If an existing selection is modified, prevent deluging browsing history.
window.location.replace('#'+fragmentIdentifier);
}
else {
window.location.assign('#'+fragmentIdentifier);
}
}
else { // Nothing is selected.
// Clear fragment identifier
//clearFragmentIdentifier();
// Signal that selection is inactive (intended to reenable referencing)
active.set(false);
}
}
function clearFragmentIdentifier() {
// Remove our influence from the URL (sets hash to empty string).
window.location.assign('');
}
// Add and remove event listeners whenever we are switched on or off
Tracker.autorun(function () {
if (enabled.get()) {
enable();
}
else {
if (!Tracker.currentComputation.firstRun) { // We naturally start disabled.
disable();
}
}
});
function enable() {
// Run every time the selection changes.
document.addEventListener("selectionchange", onSelectionChange);
// Trigger once artificially if the user could already have been selecting things.
if (['interactive', 'complete'].indexOf(document.readyState) > -1) {
window.setTimeout(onSelectionChange, 0);
}
}
function disable() {
// Stop listening to events.
window.removeEventListener("selectionchange", onSelectionChange);
// Clean up the URL.
clearFragmentIdentifier();
// If active, deactivate.
active.set(false);
}
module.exports = {
enabled: enabled,
active: active, // TODO turn into read-only version
};