@cocreate/cursors 1.10.15 → 1.11.0
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.
- package/CHANGELOG.md +36 -0
- package/package.json +8 -8
- package/src/index.css +5 -14
- package/src/index.js +131 -183
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
# [1.11.0](https://github.com/CoCreate-app/CoCreate-cursors/compare/v1.10.18...v1.11.0) (2021-12-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add style top to cursor ([1e6d26c](https://github.com/CoCreate-app/CoCreate-cursors/commit/1e6d26c31919700399b3473a938f49f3cc2978b0))
|
|
7
|
+
* update dependencies ([9895f14](https://github.com/CoCreate-app/CoCreate-cursors/commit/9895f14bf1de1c133f0477134ccb654fb31f79d0))
|
|
8
|
+
* update dependencies ([2307656](https://github.com/CoCreate-app/CoCreate-cursors/commit/2307656877e1936cb8b5d978414df898a1de0b27))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* multi cursor support between many elements in window.top ([3b2dab9](https://github.com/CoCreate-app/CoCreate-cursors/commit/3b2dab9e1a6886026b7976eed44180d89a70ad83))
|
|
14
|
+
|
|
15
|
+
## [1.10.18](https://github.com/CoCreate-app/CoCreate-cursors/compare/v1.10.17...v1.10.18) (2021-12-08)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* check contenteditable element then iframe ([29bd7b4](https://github.com/CoCreate-app/CoCreate-cursors/commit/29bd7b4e7460c478cec37916fe9bb7439d2b8805))
|
|
21
|
+
* use attribute for socket_id instead of id ([db901da](https://github.com/CoCreate-app/CoCreate-cursors/commit/db901daa270551cd6b1b6b95124d785ed81643c9))
|
|
22
|
+
|
|
23
|
+
## [1.10.17](https://github.com/CoCreate-app/CoCreate-cursors/compare/v1.10.16...v1.10.17) (2021-11-27)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Bug Fixes
|
|
27
|
+
|
|
28
|
+
* update dependencies ([4532eb5](https://github.com/CoCreate-app/CoCreate-cursors/commit/4532eb5470d6a8a76c22ed636ba83e9db43d2064))
|
|
29
|
+
|
|
30
|
+
## [1.10.16](https://github.com/CoCreate-app/CoCreate-cursors/compare/v1.10.15...v1.10.16) (2021-11-27)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Bug Fixes
|
|
34
|
+
|
|
35
|
+
* update dependencies ([000e805](https://github.com/CoCreate-app/CoCreate-cursors/commit/000e80564cfa029a60d0891da18a4076edb44ff2))
|
|
36
|
+
|
|
1
37
|
## [1.10.15](https://github.com/CoCreate-app/CoCreate-cursors/compare/v1.10.14...v1.10.15) (2021-11-27)
|
|
2
38
|
|
|
3
39
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/cursors",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Collaborative user cursor position for inputs, textarea's and contenteditable elements.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cursors",
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
"webpack-log": "^3.0.1"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@cocreate/crud-client": "^1.4.
|
|
66
|
-
"@cocreate/docs": "^1.2.
|
|
67
|
-
"@cocreate/message-client": "^1.1.
|
|
68
|
-
"@cocreate/observer": "^1.3.
|
|
69
|
-
"@cocreate/random-color": "^1.2.
|
|
70
|
-
"@cocreate/selection": "^1.
|
|
71
|
-
"@cocreate/uuid": "^1.1.
|
|
65
|
+
"@cocreate/crud-client": "^1.4.39",
|
|
66
|
+
"@cocreate/docs": "^1.2.61",
|
|
67
|
+
"@cocreate/message-client": "^1.1.57",
|
|
68
|
+
"@cocreate/observer": "^1.3.53",
|
|
69
|
+
"@cocreate/random-color": "^1.2.14",
|
|
70
|
+
"@cocreate/selection": "^1.3.0",
|
|
71
|
+
"@cocreate/uuid": "^1.1.50"
|
|
72
72
|
}
|
|
73
73
|
}
|
package/src/index.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
cursor {
|
|
2
2
|
position: absolute;
|
|
3
3
|
display: inline-block;
|
|
4
4
|
width: 2px;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
/*z-index:10;*/
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
cursor-flag {
|
|
10
10
|
position: absolute;
|
|
11
11
|
background-color: inherit;
|
|
12
12
|
top: 0px;
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
pointer-events: auto;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
cursor-flag:hover {
|
|
22
22
|
height: 14px;
|
|
23
23
|
width: unset;
|
|
24
24
|
padding: 1px 5px 0px 5px;
|
|
@@ -27,13 +27,8 @@
|
|
|
27
27
|
white-space: nowrap;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
opacity: 0.6;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.cursor-selection {
|
|
36
|
-
position: absolute;
|
|
30
|
+
selected-text {
|
|
31
|
+
opacity: 0.4;
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
.mirror {
|
|
@@ -49,7 +44,3 @@
|
|
|
49
44
|
background: rgba(0, 0, 0, 0.00);
|
|
50
45
|
width: 0px;
|
|
51
46
|
}
|
|
52
|
-
|
|
53
|
-
.users_selections {
|
|
54
|
-
opacity: 0.4;
|
|
55
|
-
}
|
package/src/index.js
CHANGED
|
@@ -10,7 +10,6 @@ const clientId = window.CoCreateSockets.clientId || uuid.generate(12);
|
|
|
10
10
|
const cursorBackground = randomColor();
|
|
11
11
|
|
|
12
12
|
let enviroment_prod = true;
|
|
13
|
-
let documents = new Map();
|
|
14
13
|
|
|
15
14
|
let selector = "[collection][document_id][name]:not([contentEditable='false'])";
|
|
16
15
|
|
|
@@ -34,120 +33,17 @@ function initElement(element) {
|
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
function initDocument(doc) {
|
|
37
|
-
|
|
36
|
+
let documents = window.top.cursorDocuments;
|
|
37
|
+
if (!documents){
|
|
38
|
+
documents = new Map();
|
|
39
|
+
window.top.cursorDocuments = documents;
|
|
40
|
+
}
|
|
41
|
+
if (!documents.has(doc)) {
|
|
38
42
|
initResizeObserver(doc.documentElement);
|
|
39
43
|
documents.set(doc);
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
var getCoordinates = function(element, position_start, position_end) {
|
|
44
|
-
var mirrorDiv;
|
|
45
|
-
let ID_MIRROR = element.getAttribute('mirror_id');
|
|
46
|
-
let document = element.ownerDocument;
|
|
47
|
-
mirrorDiv = document.getElementById(ID_MIRROR);
|
|
48
|
-
|
|
49
|
-
if (!mirrorDiv) {
|
|
50
|
-
mirrorDiv = document.createElement('div');
|
|
51
|
-
mirrorDiv.id = ID_MIRROR;
|
|
52
|
-
mirrorDiv.className = (enviroment_prod) ? 'mirror mirror_scroll mirror_color' : 'mirror mirror_scroll';
|
|
53
|
-
mirrorDiv.contentEditable = false;
|
|
54
|
-
mirrorDiv.element = element;
|
|
55
|
-
element.insertAdjacentElement('afterend', mirrorDiv);
|
|
56
|
-
_initEvents(element);
|
|
57
|
-
initDocument(document);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
let computed = getComputedStyle(element);
|
|
61
|
-
let rect = element.getBoundingClientRect();
|
|
62
|
-
let scrollBarWidth = 0;
|
|
63
|
-
if (element.clientWidth != 0)
|
|
64
|
-
scrollBarWidth = element.offsetWidth - element.clientWidth;
|
|
65
|
-
let style = mirrorDiv.style;
|
|
66
|
-
|
|
67
|
-
style.position = 'absolute';
|
|
68
|
-
style.top = element.offsetTop + 'px';
|
|
69
|
-
style.left = element.offsetLeft + 'px';
|
|
70
|
-
style.width = rect.width + 'px';
|
|
71
|
-
style.height = rect.height + 'px';
|
|
72
|
-
style.visibility = 'visible';
|
|
73
|
-
style.overflowX = computed['overflowX'];
|
|
74
|
-
style.overflowY = computed['overflowY'];
|
|
75
|
-
style.margin = '0px';
|
|
76
|
-
style.paddingRight = parseInt(computed['paddingRight']) + scrollBarWidth + 'px';
|
|
77
|
-
style.border = computed['border'];
|
|
78
|
-
style.borderColor = 'transparent';
|
|
79
|
-
|
|
80
|
-
if (element.nodeName !== 'INPUT') {
|
|
81
|
-
style.wordWrap = 'break-word';
|
|
82
|
-
style.whiteSpace = 'pre-wrap';
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
style.whiteSpace = 'pre';
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
let properties = ['boxSizing', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', 'paddingTop', 'paddingBottom', 'paddingLeft', 'fontStyle', 'fontVariant', 'fontWeight', 'fontStretch', 'fontSize', 'lineHeight', 'fontFamily', 'textAlign', 'textTransform', 'textIndent', 'textDecoration', 'letterSpacing', 'wordSpacing', 'textRendering', 'webkitWritingMode', 'textTransform', 'textIndent', 'overflowWrap'];
|
|
89
|
-
|
|
90
|
-
properties.forEach(function(prop) {
|
|
91
|
-
if (['left', 'top'].indexOf(prop.toLowerCase()) === -1)
|
|
92
|
-
style[prop] = computed[prop];
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
let cursor_container = mirrorDiv.querySelectorAll('.cursor-container');
|
|
97
|
-
let users_selections = mirrorDiv.querySelectorAll('.users_selections');
|
|
98
|
-
|
|
99
|
-
let value_element = (['TEXTAREA', 'INPUT'].indexOf(element.nodeName) == -1) ? element.innerHTML : element.value;
|
|
100
|
-
mirrorDiv.textContent = value_element.substring(0, position_start);
|
|
101
|
-
|
|
102
|
-
if (element.nodeName === 'INPUT')
|
|
103
|
-
mirrorDiv.textContent = mirrorDiv.textContent.replace(/\s/g, " ");
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
var span = document.createElement('span');
|
|
107
|
-
span.id = element.nodeName + 'span_selections';
|
|
108
|
-
let value_span = value_element.substring(position_start, position_end) || '';
|
|
109
|
-
span.textContent = value_span;
|
|
110
|
-
mirrorDiv.appendChild(span);
|
|
111
|
-
|
|
112
|
-
if (cursor_container) {
|
|
113
|
-
cursor_container.forEach(function(child_cursor, index, array) {
|
|
114
|
-
mirrorDiv.appendChild(child_cursor);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (users_selections) {
|
|
119
|
-
users_selections.forEach(function(child_selection, index, array) {
|
|
120
|
-
mirrorDiv.appendChild(child_selection);
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// create mirror text end
|
|
125
|
-
let value_end = value_element.substring(position_end) || '';
|
|
126
|
-
var span_end = document.createElement('span');
|
|
127
|
-
mirrorDiv.appendChild(span_end);
|
|
128
|
-
span_end.textContent = value_end;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
var coordinates = {
|
|
132
|
-
start: {
|
|
133
|
-
top: span.offsetTop,
|
|
134
|
-
left: span.offsetLeft
|
|
135
|
-
},
|
|
136
|
-
end: {
|
|
137
|
-
top: span_end.offsetTop,
|
|
138
|
-
left: span_end.offsetLeft
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
return coordinates;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
function getStyle(el, styleProp) {
|
|
146
|
-
if (window.getComputedStyle)
|
|
147
|
-
var y = document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
|
|
148
|
-
return y;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
47
|
function drawCursors(selection) {
|
|
152
48
|
const socket_id = selection['clientId'];
|
|
153
49
|
const collection = selection['collection'];
|
|
@@ -162,11 +58,20 @@ function drawCursors(selection) {
|
|
|
162
58
|
elements = document.querySelectorAll(selector);
|
|
163
59
|
}
|
|
164
60
|
for (let element of elements) {
|
|
61
|
+
if (element.activeElement) {
|
|
62
|
+
element.activeElement = '';
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
165
65
|
let realtime = element.getAttribute('realtime');
|
|
166
66
|
let cursors = element.getAttribute('cursors');
|
|
167
67
|
if (realtime == 'false' || cursors == 'false') continue;
|
|
168
|
-
if (element.
|
|
169
|
-
let domTextEditor = element
|
|
68
|
+
if (element.hasAttribute('contenteditable')) {
|
|
69
|
+
let domTextEditor = element;
|
|
70
|
+
if (element.tagName == 'IFRAME'){
|
|
71
|
+
let frameClientId = element.contentDocument.defaultView.CoCreateSockets.clientId;
|
|
72
|
+
if (frameClientId == selection.clientId) continue;
|
|
73
|
+
domTextEditor = element.contentDocument.documentElement;
|
|
74
|
+
}
|
|
170
75
|
let pos = getElementPosition(domTextEditor.htmlString, start, end);
|
|
171
76
|
element = domTextEditor.querySelector(pos.path);
|
|
172
77
|
let endPos = end - start;
|
|
@@ -176,85 +81,129 @@ function drawCursors(selection) {
|
|
|
176
81
|
end = pos.start;
|
|
177
82
|
start = pos.start;
|
|
178
83
|
}
|
|
179
|
-
if(!element)
|
|
84
|
+
if(!element) continue;
|
|
180
85
|
let document = element.ownerDocument;
|
|
86
|
+
let mirrorDiv;
|
|
181
87
|
let id_mirror = element.getAttribute('mirror_id');
|
|
182
|
-
if (!id_mirror)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
88
|
+
if (!id_mirror){
|
|
89
|
+
id_mirror = uuid.generate(8);
|
|
90
|
+
element.setAttribute('mirror_id', id_mirror);
|
|
91
|
+
|
|
92
|
+
mirrorDiv = document.createElement('cursor-container');
|
|
93
|
+
mirrorDiv.id = id_mirror;
|
|
94
|
+
mirrorDiv.className = (enviroment_prod) ? 'mirror mirror_scroll mirror_color' : 'mirror mirror_scroll';
|
|
95
|
+
mirrorDiv.contentEditable = false;
|
|
96
|
+
mirrorDiv.element = element;
|
|
97
|
+
element.insertAdjacentElement('afterend', mirrorDiv);
|
|
98
|
+
_initEvents(element);
|
|
99
|
+
initDocument(document);
|
|
100
|
+
}
|
|
101
|
+
else
|
|
102
|
+
mirrorDiv = document.getElementById(id_mirror);
|
|
103
|
+
|
|
104
|
+
let computed = getComputedStyle(element);
|
|
105
|
+
let rect = element.getBoundingClientRect();
|
|
106
|
+
let borderWidth = parseInt(computed['border-width']) * 2;
|
|
107
|
+
let scrollBarWidth = 0;
|
|
108
|
+
if (element.clientWidth != 0)
|
|
109
|
+
scrollBarWidth = element.offsetWidth - element.clientWidth - borderWidth;
|
|
110
|
+
let style = mirrorDiv.style;
|
|
111
|
+
|
|
112
|
+
style.position = 'absolute';
|
|
113
|
+
style.top = element.offsetTop + 'px';
|
|
114
|
+
style.left = element.offsetLeft + 'px';
|
|
115
|
+
style.width = rect.width + 'px';
|
|
116
|
+
style.height = rect.height + 'px';
|
|
117
|
+
style.visibility = 'visible';
|
|
118
|
+
style.overflowX = computed['overflowX'];
|
|
119
|
+
style.overflowY = computed['overflowY'];
|
|
120
|
+
style.margin = '0px';
|
|
121
|
+
style.paddingRight = parseInt(computed['paddingRight']) + scrollBarWidth + 'px';
|
|
122
|
+
style.border = computed['border'];
|
|
123
|
+
style.borderColor = 'transparent';
|
|
124
|
+
|
|
125
|
+
if (element.nodeName !== 'INPUT') {
|
|
126
|
+
style.wordWrap = 'break-word';
|
|
127
|
+
style.whiteSpace = 'pre-wrap';
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
style.whiteSpace = 'pre';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let properties = ['boxSizing', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', 'paddingTop', 'paddingBottom', 'paddingLeft', 'fontStyle', 'fontVariant', 'fontWeight', 'fontStretch', 'fontSize', 'lineHeight', 'fontFamily', 'textAlign', 'textTransform', 'textIndent', 'textDecoration', 'letterSpacing', 'wordSpacing', 'textRendering', 'webkitWritingMode', 'textTransform', 'textIndent', 'overflowWrap'];
|
|
134
|
+
|
|
135
|
+
properties.forEach(function(prop) {
|
|
136
|
+
if (['left', 'top'].indexOf(prop.toLowerCase()) === -1)
|
|
137
|
+
style[prop] = computed[prop];
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
let spanText = mirrorDiv.querySelector('span-text');
|
|
141
|
+
if (!spanText)
|
|
142
|
+
spanText = document.createElement('span-text');
|
|
143
|
+
spanText.style['display'] = 'block';
|
|
144
|
+
let value_element = (['TEXTAREA', 'INPUT'].indexOf(element.nodeName) == -1) ? element.innerHTML : element.value;
|
|
145
|
+
|
|
146
|
+
spanText.textContent = value_element;
|
|
147
|
+
if (element.nodeName === 'INPUT')
|
|
148
|
+
spanText.textContent = mirrorDiv.textContent.replace(/\s/g, " ");
|
|
149
|
+
mirrorDiv.appendChild(spanText);
|
|
150
|
+
let cursor, cursorFlag;
|
|
151
|
+
let details = {collection, document_id, name};
|
|
193
152
|
if (socket_id) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
153
|
+
let userSelections = document.querySelectorAll(`selection[socket_id="${socket_id}"]`);
|
|
154
|
+
if (userSelections) {
|
|
155
|
+
for (let userSelection of userSelections){
|
|
156
|
+
if (userSelection.details != details)
|
|
157
|
+
userSelection.remove();
|
|
198
158
|
}
|
|
199
|
-
});
|
|
200
|
-
cursor = elementMirror.querySelector('.cursor-container#socket_' + socket_id);
|
|
201
|
-
if (!cursor) {
|
|
202
|
-
let cursor_template = '<div class="cursor-container" \
|
|
203
|
-
id="socket_' + socket_id + '" \
|
|
204
|
-
style="background-color:' + selection.background + '"> \
|
|
205
|
-
<div class="cursor-flag" \
|
|
206
|
-
collection="users" \
|
|
207
|
-
document_id="' + selection.user_id + '" \
|
|
208
|
-
name="name">' + selection.userName + '</div>\
|
|
209
|
-
</div>';
|
|
210
|
-
elementMirror.innerHTML = cursor_template + elementMirror.innerHTML;
|
|
211
159
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
160
|
+
let selection_user = mirrorDiv.querySelector(`selection[socket_id="${socket_id}"]`);
|
|
161
|
+
if (!selection_user){
|
|
162
|
+
selection_user = document.createElement('selection');
|
|
163
|
+
selection_user.setAttribute('socket_id', socket_id);
|
|
164
|
+
selection_user.style["position"] = "absolute";
|
|
165
|
+
let style_mirror = getComputedStyle(mirrorDiv);
|
|
166
|
+
selection_user.style["top"] = style_mirror.paddingTop;
|
|
167
|
+
selection_user.style["left"] = style_mirror.paddingLeft;
|
|
168
|
+
selection_user.style["width"] = mirrorDiv.clientWidth - parseInt(computed['padding-left']) - parseInt(computed['padding-right']) - scrollBarWidth + 'px';
|
|
169
|
+
selection_user.details = {collection, document_id, name};
|
|
170
|
+
|
|
171
|
+
mirrorDiv.appendChild(selection_user);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let value_element = (['TEXTAREA', 'INPUT'].indexOf(element.nodeName) == -1) ? element.innerHTML : element.value;
|
|
175
|
+
selection_user.textContent = value_element.substring(0, start);
|
|
176
|
+
|
|
177
|
+
let value_end = value_element.substring(end) || '';
|
|
178
|
+
let span_end = document.createElement('span-end');
|
|
179
|
+
span_end.textContent = value_end;
|
|
180
|
+
|
|
181
|
+
cursor = document.createElement('cursor');
|
|
182
|
+
cursor.setAttribute('socket_id', socket_id);
|
|
220
183
|
cursor.dataset.start = start;
|
|
221
184
|
cursor.dataset.end = end;
|
|
222
|
-
cursor.setAttribute('socket_id', socket_id);
|
|
223
185
|
cursor.setAttribute('user-name', selection.userName);
|
|
224
186
|
cursor.setAttribute('user-background', selection.background);
|
|
225
187
|
cursor.setAttribute('user-color', selection.color);
|
|
226
|
-
cursor.style["height"] = cursor_height + "px";
|
|
227
188
|
cursor.style["background"] = selection.background;
|
|
189
|
+
cursor.details = {collection, document_id, name};
|
|
190
|
+
cursor.textContent = "1";
|
|
191
|
+
span_end.prepend(cursor);
|
|
192
|
+
|
|
193
|
+
let selectedText = document.createElement('selected-text');
|
|
194
|
+
selectedText.style["backgroundColor"] = selection.background;
|
|
195
|
+
selectedText.textContent = value_element.substring(start, end) || '';
|
|
196
|
+
span_end.prepend(selectedText);
|
|
197
|
+
|
|
198
|
+
cursorFlag = document.createElement('cursor-flag');
|
|
199
|
+
cursorFlag.setAttribute('collection', 'users');
|
|
200
|
+
cursorFlag.setAttribute('document_id', selection.user_id);
|
|
201
|
+
cursorFlag.setAttribute('name', 'name');
|
|
228
202
|
cursorFlag.style["background"] = selection.background;
|
|
229
203
|
cursorFlag.innerHTML = selection.userName;
|
|
230
|
-
cursor.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (selection_user) {
|
|
234
|
-
selection_user.remove();
|
|
235
|
-
}
|
|
236
|
-
if ((start != end)) {
|
|
237
|
-
var scrollwidth = element.offsetWidth - element.scrollWidth;
|
|
238
|
-
var padding_right = parseInt(getComputedStyle(element)["paddingRight"]);
|
|
239
|
-
|
|
240
|
-
selection_user = document.createElement('span');
|
|
241
|
-
selection_user.id = 'sel-' + socket_id;
|
|
242
|
-
selection_user.className = 'users_selections';
|
|
243
|
-
let style_mirror = getComputedStyle(elementMirror);
|
|
244
|
-
selection_user.style["position"] = "absolute";
|
|
245
|
-
selection_user.style["top"] = style_mirror.paddingTop;
|
|
246
|
-
selection_user.style["left"] = style_mirror.paddingLeft;
|
|
247
|
-
selection_user.style["padding-right"] = scrollwidth + padding_right + "px";
|
|
248
|
-
elementMirror.insertBefore(selection_user, elementMirror.firstChild);
|
|
249
|
-
let selection_span_by_user = document.createElement('span');
|
|
250
|
-
selection_span_by_user.id = 'selection-' + socket_id;
|
|
251
|
-
selection_span_by_user.style.backgroundColor = selection.background;
|
|
252
|
-
let value_element = (['TEXTAREA', 'INPUT'].indexOf(element.nodeName) == -1) ? element.innerHTML : element.value;
|
|
253
|
-
selection_user.textContent = value_element.substring(0, start);
|
|
254
|
-
let value_span_selection = value_element.substring(start, end) || '';
|
|
255
|
-
selection_span_by_user.textContent = value_span_selection;
|
|
256
|
-
selection_user.appendChild(selection_span_by_user);
|
|
257
|
-
}
|
|
204
|
+
cursor.appendChild(cursorFlag);
|
|
205
|
+
|
|
206
|
+
selection_user.appendChild(span_end);
|
|
258
207
|
}
|
|
259
208
|
scrollMirror(element);
|
|
260
209
|
}
|
|
@@ -273,9 +222,9 @@ function updateCursors(element) {
|
|
|
273
222
|
}
|
|
274
223
|
for (let mirrorDiv of mirrorDivs) {
|
|
275
224
|
element = mirrorDiv.element;
|
|
276
|
-
let
|
|
225
|
+
let cursors = mirrorDiv.querySelectorAll('cursor');
|
|
277
226
|
|
|
278
|
-
|
|
227
|
+
cursors.forEach(function(child_cursor, index, array) {
|
|
279
228
|
let clientId = child_cursor.getAttribute('socket_id');
|
|
280
229
|
let userName = child_cursor.getAttribute('user-name');
|
|
281
230
|
let background = child_cursor.getAttribute('user-background');
|
|
@@ -297,12 +246,12 @@ function updateCursors(element) {
|
|
|
297
246
|
}
|
|
298
247
|
|
|
299
248
|
function removeCursor(clientId) {
|
|
300
|
-
let elements = document.querySelectorAll(
|
|
249
|
+
let elements = document.querySelectorAll(`cursor[socket_id="${clientId}"]`);
|
|
301
250
|
elements.forEach(function(element, index, array) {
|
|
302
251
|
element.parentNode.removeChild(element);
|
|
303
252
|
});
|
|
304
253
|
|
|
305
|
-
let sel_elements = document.querySelectorAll(
|
|
254
|
+
let sel_elements = document.querySelectorAll(`selection[socket_id="${clientId}"]`);
|
|
306
255
|
sel_elements.forEach(function(sel_element, index, array) {
|
|
307
256
|
sel_element.parentNode.removeChild(sel_element);
|
|
308
257
|
});
|
|
@@ -361,7 +310,6 @@ function sendPosition(info) {
|
|
|
361
310
|
|
|
362
311
|
|
|
363
312
|
message.listen('cursor', function(selection) {
|
|
364
|
-
if (selection.clientId == clientId) return;
|
|
365
313
|
if (selection.start != null && selection.end != null)
|
|
366
314
|
drawCursors(selection);
|
|
367
315
|
else
|