-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.js
More file actions
132 lines (114 loc) · 4.49 KB
/
background.js
File metadata and controls
132 lines (114 loc) · 4.49 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
chrome.runtime.onInstalled.addListener(() => {
// Creates a context menu-item
chrome.contextMenus.create({
id: "edit-node",
title: "Edit this node",
contexts: ["all"]
});
});
chrome.contextMenus.onClicked.addListener((info, tab) => {
// If user clicked the "Edit this node" menu-item
if (info.menuItemId === "edit-node") {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: enableEditMode
});
}
});
function enableEditMode() {
const EMPTY_NODE_SELECTOR = ':is(span,div,a):is(:empty)';
const NODE_WITH_TEXT_SELECTOR = ':not(:empty)';
function disableEditMode() {
const state = window.__editThisNodeState;
enableEmptyNodes();
state.node.removeAttribute('contentEditable');
state.node.removeEventListener('blur', disableEditMode);
state.node.removeEventListener('paste', handlePaste);
state.node = null;
state.originalContent = null;
state.lastRightClickX = -1;
state.lastRightClickY = -1;
document.removeEventListener('keydown', handleKeyDown);
}
function disableEmptyNodes() {
const state = window.__editThisNodeState;
const emptyNodes = state.node.querySelectorAll(EMPTY_NODE_SELECTOR);
emptyNodes.forEach(emptyNode => {
emptyNode.setAttribute('data-display', emptyNode.style.display)
emptyNode.style.display = 'none';
});
}
function enableEmptyNodes() {
const state = window.__editThisNodeState;
const emptyNodes = state.node.querySelectorAll(EMPTY_NODE_SELECTOR);
emptyNodes.forEach(emptyNode => {
if (emptyNode.hasAttribute('data-display')) {
emptyNode.style.display = emptyNode.style.display = emptyNode.getAttribute('data-display');
emptyNode.removeAttribute('data-display');
}
});
}
function isEditMode() {
return !!window?.__editThisNodeState?.node;
}
function handleKeyDown(event) {
const keyCode = event.keyCode;
switch (keyCode) {
case 13: // enter
event.preventDefault();
disableEditMode();
break;
case 27: // escape
const state = window.__editThisNodeState;
state.node.innerHTML = state.originalContent;
event.preventDefault();
disableEditMode();
break;
default:
// do nothing
}
}
function handlePaste(event) {
console.info(':::::::::: paste handler');
event.preventDefault();
let paste = (event.clipboardData || window.clipboardData).getData("text");
const selection = window.getSelection();
selection.deleteFromDocument();
selection.getRangeAt(0).insertNode(document.createTextNode(paste));
}
// When clicking out-side the element, removes the contenteditable.
const state = window.__editThisNodeState;
document.addEventListener("click", (event) => {
const editableNode = event.target.closest('[contentEditable]');
// If click occured inside the editable node. cancel operation
if (editableNode) {
event.preventDefault();
}
// If click occured outside the editable node, asume cancel operation
else if (isEditMode()) {
event.preventDefault();
disableEditMode();
}
}, { capture: true });
const hasLegalCordinates = state.lastRightClickX > 0 && state.lastRightClickY > 0;
if (!hasLegalCordinates) {
alert('Unable to get cordinates for the element');
}
const targetNode = hasLegalCordinates && document.elementFromPoint(state.lastRightClickX, state.lastRightClickY);
if (targetNode) {
const editableNode = targetNode.closest(NODE_WITH_TEXT_SELECTOR);
state.node = editableNode;
state.originalContent = state.node.innerHTML;
editableNode.setAttribute('contentEditable', true);
editableNode.focus();
const range = document.createRange();
range.selectNodeContents(editableNode);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
editableNode.addEventListener('paste', handlePaste);
editableNode.addEventListener("blur", disableEditMode);
disableEmptyNodes();
document.addEventListener('keydown', handleKeyDown);
}
}