-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
sticky-attribution.js
82 lines (81 loc) · 3.41 KB
/
sticky-attribution.js
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
/*!
* =======================================================
* STICKY ATTRIBUTION
* =======================================================
*
* Author: Taufik Nurrohman
* URL: https://github.com/taufik-nurrohman
* License: Public Domain
*
* -------------------------------------------------------
*
*/
(function(win, doc) {
var getSelection = 'getSelection',
removeAllRanges = 'removeAllRanges',
addRange = 'addRange',
parentNode = 'parentNode',
firstChild = 'firstChild',
appendChild = 'appendChild',
removeChild = 'removeChild',
test = 'test',
innerHTML = 'innerHTML';
// does not have support for the selection API, skip!
if (!win[getSelection]) return;
var selection, target, clone, container, c, range;
// listen to the “copy” event
doc.addEventListener("copy", function(e) {
// check whether the target is a `<pre>`, `<code>` or `<any class="no-attribution">` element
target = e.target;
// if the target is a text node, try to get the closest HTML element
while (target.nodeType === 3) {
target = target[parentNode];
}
// create a container
container = doc.createElement('div');
/*
container.style.width = container.style.height = '1px';
container.style.overflow = 'hidden';
container.style.position = 'absolute';
container.style.top = container.style.left = 0;
*/
if (
// make sure we have selection
(selection = win[getSelection]()) &&
// make sure we have selection range
(selection.rangeCount) &&
// get the first selection range
(selection = selection.getRangeAt(0)) &&
// clone the current selection range, then get the HTML contents of the selection
(clone = selection.cloneRange(), selection = selection.cloneContents())
) {
// append HTML contents of the selection to the container
while (c = selection[firstChild]) {
container[appendChild](c);
}
// insert the attribution to the end of the contents
// only if the target element is not a `<pre>`, `<code>` and `<any class="no-attribution">`
if (!/^(pre|code)$/i[test](target.nodeName || "") && !/(^|\s)no-attribution(\s|$)/i[test](target.className || "")) {
var href = win.location.href;
container[innerHTML] += '<br><br>© ' + doc.title + '<br>Source: <a href="' + href + '">' + href + '</a>';
}
// create a new range
range = doc.createRange();
// append the container to the `<body>` section
doc.body[appendChild](container);
// move selection range to the container
range.selectNodeContents(container);
selection = win[getSelection]();
selection[removeAllRanges]();
selection[addRange](range);
// there should be a short time there, we have copied the new selection…
setTimeout(function() {
// now remove the container…
container[parentNode][removeChild](container);
// then restore the previous selection!
selection[removeAllRanges]();
selection[addRange](clone);
});
}
}, false);
})(window, document);