@cocreate/resize 1.11.2 → 1.13.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/src/index.js CHANGED
@@ -2,455 +2,698 @@
2
2
  import observer from "@cocreate/observer";
3
3
  import "./index.css";
4
4
 
5
- const EVENTS = ['mousemove touchmove', 'mousedown touchstart', 'mouseup touchend'];
6
- const DIRECTIONS = ['left', 'right', 'top', 'bottom'];
5
+ const EVENTS = [
6
+ "mousemove touchmove",
7
+ "mousedown touchstart",
8
+ "mouseup touchend"
9
+ ];
10
+ const DIRECTIONS = ["left", "right", "top", "bottom"];
7
11
 
8
12
  const styleEl = document.createElement("style");
9
- styleEl.setAttribute('component', 'resize');
13
+ styleEl.setAttribute("component", "resize");
10
14
  document.head.appendChild(styleEl);
11
15
  const styleSheet = styleEl.sheet;
12
16
 
13
17
  const coCreateResize = {
14
- selector: '', //'.resize',
15
- resizers: [],
16
- resizeWidgets: [],
17
-
18
- init: function(handleObj) {
19
- for (var handleKey in handleObj)
20
- if (handleObj.hasOwnProperty(handleKey) && handleKey == 'selector')
21
- this.selector = handleObj[handleKey];
22
-
23
- this.resizers = document.querySelectorAll(this.selector);
24
- var _this = this;
25
- this.resizers.forEach(function(resize, idx) {
26
- let resizeWidget = new CoCreateResize(resize, handleObj);
27
- _this.resizeWidgets[idx] = resizeWidget;
28
- });
29
- },
30
-
31
- initElement: function(target) {
32
- let resizeWidget = new CoCreateResize(target, {
33
- dragLeft: "[resize='left']",
34
- dragRight: "[resize='right']",
35
- dragTop: "[resize='top']",
36
- dragBottom: "[resize='bottom']"
37
- });
38
- this.resizeWidgets[0] = resizeWidget;
39
- }
18
+ selector: "", //'.resize',
19
+ resizers: [],
20
+ resizeWidgets: [],
21
+
22
+ init: function (handleObj) {
23
+ for (var handleKey in handleObj)
24
+ if (handleObj.hasOwnProperty(handleKey) && handleKey == "selector")
25
+ this.selector = handleObj[handleKey];
26
+
27
+ this.resizers = document.querySelectorAll(this.selector);
28
+ var _this = this;
29
+ this.resizers.forEach(function (resize, idx) {
30
+ let resizeWidget = new CoCreateResize(resize, handleObj);
31
+ _this.resizeWidgets[idx] = resizeWidget;
32
+ });
33
+ },
34
+
35
+ initElement: function (target) {
36
+ let resizeWidget = new CoCreateResize(target, {
37
+ dragLeft: "[resize='left']",
38
+ dragRight: "[resize='right']",
39
+ dragTop: "[resize='top']",
40
+ dragBottom: "[resize='bottom']"
41
+ });
42
+ this.resizeWidgets[0] = resizeWidget;
43
+ }
40
44
  };
41
45
 
42
46
  function CoCreateResize(resizer, options) {
43
- this.resizeWidget = resizer;
44
- this.cornerSize = 10;
45
- this.init(options);
47
+ this.resizeWidget = resizer;
48
+ this.cornerSize = 10;
49
+ this.init(options);
46
50
  }
47
51
 
48
52
  CoCreateResize.prototype = {
49
- init: function(handleObj) {
50
- if (this.resizeWidget) {
51
- this.initDrags = [];
52
- this.checkCorners = [];
53
- this.doDrags = [];
54
- this.Drags = [];
55
-
56
- //this is for grid
57
- this.isGrid = this.detectGrid();
58
- this.gridWidth = 0;
59
- this.gridHeight = 0;
60
- this.limitSpan = 0;
61
- this.widthSpan = 0;
62
- this.heightSpan = 0;
63
- this.originClassAttribute = this.resizeWidget.getAttribute('class');
64
-
65
- DIRECTIONS.map(d => {
66
- this.Drags[d] = this.resizeWidget.querySelector(handleObj['drag' + d.charAt(0).toUpperCase() + d.slice(1)]);
67
- });
68
-
69
- this.bindListeners();
70
- this.initResize();
71
-
72
- //this is just for grid system
73
- this.getGridProperty();
74
- window.addEventListener('resize', this.checkGridColumns.bind(this));
75
- }
76
- },
77
-
78
- getGridProperty: function() {
79
- if (!this.resizeWidget.parentNode) return;
80
- let compStyles = window.getComputedStyle(this.resizeWidget.parentNode);
81
- let gridColumns = compStyles.gridTemplateColumns;
82
- let height = compStyles.gridAutoRows;
83
-
84
- if (gridColumns !== 'none') {
85
- let width = gridColumns.split(' ');
86
- this.limitSpan = width.length;
87
- this.gridColumnGap = Number.parseInt(compStyles.gridColumnGap);
88
- this.gridRowGap = Number.parseInt(compStyles.gridRowGap);
89
- this.gridWidth = Number.parseFloat(width[0]);
90
- this.gridHeight = Number.parseInt(height);
91
- }
92
- },
93
-
94
- checkGridColumns: function() {
95
- if (typeof this.resizeWidget !== 'undefined' && this.resizeWidget.parentNode)
96
- {
97
- let compStylesOfParent = window.getComputedStyle(this.resizeWidget.parentNode);
98
- let spans = 0;
99
- let gridColumns = compStylesOfParent.gridTemplateColumns.split(' ');
100
- let temp = gridColumns[0];
101
- gridColumns.map(v => {
102
- if (v == temp) spans ++;
103
- });
104
- this.limitSpan = spans;
105
- if (this.resizeWidget.style['grid-column-end'])
106
- {
107
- let curClassAttributes = this.resizeWidget.getAttribute('class').split(' ');
108
- let prevColumnState = curClassAttributes[curClassAttributes.length - 1].split('_');
109
- let prevSpan = Number.parseInt(prevColumnState[1]);
110
- let curColumnState = this.resizeWidget.style['grid-column-end'].split(' ');
111
- let curSpan = Number.parseInt(curColumnState[1]);
112
-
113
- let span = 0;
114
- if (this.limitSpan >= prevSpan) span = prevSpan;
115
- else if (prevSpan > this.limitSpan) span = this.limitSpan;
116
- else span = Math.min(curSpan, this.limitSpan);
117
-
118
- this.resizeWidget.style['grid-column-end'] = 'span ' + span;
119
- }
120
- }
121
- },
122
-
123
- initResize: function() {
124
- DIRECTIONS.map(d => {
125
- if (this.Drags[d])
126
- this.addListenerMulti(this.Drags[d], EVENTS[0], this.checkCorners[d]);
127
- });
128
- },
129
-
130
- checkDragImplementation: function(e, from, to, offset, fcur, scur) {
131
- if (e.touches)
132
- e = e.touches[0];
133
- let other;
134
- if (to == 'top')
135
- other = 'bottom'
136
- else if (to == 'bottom')
137
- other = 'top'
138
- else if (to == 'left')
139
- other = 'right'
140
- else if (to == 'right')
141
- other = 'left'
142
- this.removeListenerMulti(this.Drags[from], EVENTS[1], this.initDrags[from]);
143
- this.removeListenerMulti(this.Drags[from], EVENTS[1], this.initDrags[to]);
144
- this.removeListenerMulti(this.Drags[from], EVENTS[1], this.initDrags[other]);
145
- this.addListenerMulti(this.Drags[from], EVENTS[1], this.initDrags[from]);
146
-
147
- if (offset < this.cornerSize && this.Drags[to]) {
148
- this.Drags[from].style.cursor = fcur;
149
- this.addListenerMulti(this.Drags[from], EVENTS[1], this.initDrags[to]);
150
- }
151
- else {
152
- this.Drags[from].style.cursor = scur;
153
- }
154
- },
155
-
156
- initDrag: function(e, idx) {
157
- e.preventDefault();
158
-
159
- if (!this.resizeWidget.hasAttribute('resizing')){
160
- this.resizeWidget.setAttribute('resizing', '')
161
- }
162
-
163
- let selector = document.defaultView.getComputedStyle(this.resizeWidget);
164
- styleSheet.insertRule('iframe {pointer-events: none}', 0)
165
-
166
- if (idx == 'top' || idx == 'bottom') {
167
- this.startTop = parseInt(selector.top, 10);
168
- this.startHeight = parseInt(selector.height, 10);
169
-
170
- if (e.touches)
171
- this.startY = e.touches[0].clientY;
172
- else
173
- this.startY = e.clientY;
174
- }
175
- else {
176
- this.startLeft = parseInt(selector.left, 10);
177
- this.startWidth = parseInt(selector.width, 10);
178
-
179
- if (e.touches)
180
- this.startX = e.touches[0].clientX;
181
- else
182
- this.startX = e.clientX;
183
- }
184
-
185
- this.addListenerMulti(document.documentElement, EVENTS[0], this.doDrags[idx]);
186
- this.addListenerMulti(document.documentElement, EVENTS[2], this.stopDrag);
187
- },
188
-
189
- initTopDrag: function(e) {
190
- this.initDrag(e, 'top');
191
- },
192
- initBottomDrag: function(e) {
193
- this.initDrag(e, 'bottom');
194
- },
195
- initLeftDrag: function(e) {
196
- this.initDrag(e, 'left');
197
-
198
- },
199
- initRightDrag: function(e) {
200
- this.initDrag(e, 'right');
201
- },
202
-
203
- //this is just for grid system
204
- setRowEnd: function(height) {
205
- if (this.gridHeight) {
206
- this.heightSpan = Math.ceil((height - (this.heightSpan - 1) * this.gridRowGap) / this.gridHeight );
207
- this.resizeWidget.style['grid-row-end'] = 'span ' + this.heightSpan;
208
- this.collaborate({rowEnd: this.heightSpan})
209
- }
210
- },
211
-
212
- doTopDrag: function(e) {
213
- let top, height;
214
-
215
- if (e.touches)
216
- e = e.touches[0];
217
- top = this.startTop + e.clientY - this.startY;
218
- height = this.startHeight - e.clientY + this.startY;
219
-
220
- if (height < 10)
221
- return;
222
- if (!this.isGrid) {
223
- this.resizeWidget.style.top = top + 'px';
224
- this.collaborate({top, height})
225
- }
226
- this.resizeWidget.style.height = height + 'px';
227
- this.setRowEnd(height);
228
- },
229
-
230
-
231
- doBottomDrag: function(e) {
232
- let height;
233
-
234
- if (e.touches)
235
- e = e.touches[0];
236
-
237
- height = this.startHeight + e.clientY - this.startY;
238
-
239
- if (height < 10)
240
- return;
241
- if (!this.isGrid)
242
- this.collaborate({height})
243
-
244
- this.resizeWidget.style.height = height + 'px';
245
- this.setRowEnd(height);
246
- },
247
-
248
- //this is just for grid system
249
- setColumnEnd: function(width) {
250
- if (this.gridWidth) {
251
- let spans = Math.ceil((width - (this.widthSpan - 1) * this.gridColumnGap) / this.gridWidth);
252
- this.widthSpan = (spans > this.limitSpan) ? this.limitSpan : spans;
253
- this.resizeWidget.style['grid-column-end'] = 'span ' + this.widthSpan;
254
- this.collaborate({columnEnd: this.widthSpan})
255
- }
256
- },
257
-
258
- doLeftDrag: function(e) {
259
- let left, width;
260
- if (e.touches)
261
- e = e.touches[0];
262
- left = this.startLeft + e.clientX - this.startX;
263
- width = this.startWidth - e.clientX + this.startX;
264
-
265
- if (width < 10)
266
- return;
267
- if (!this.isGrid) {
268
- this.resizeWidget.style.left = left + 'px';
269
- this.collaborate({left, width})
270
- }
271
-
272
- this.resizeWidget.style.width = width + 'px';
273
- this.setColumnEnd(width);
274
- },
275
-
276
-
277
- doRightDrag: function(e) {
278
- let width;
279
- if (e.touches)
280
- e = e.touches[0];
281
- width = this.startWidth + e.clientX - this.startX;
282
- if (width < 10)
283
- return;
284
-
285
- if (!this.isGrid)
286
- this.collaborate({width})
287
-
288
- this.resizeWidget.style.width = width + 'px';
289
- this.setColumnEnd(width);
290
- },
291
-
292
- detectGrid: function() {
293
- let isGrid = false;
294
- if (this.resizeWidget.parentNode) {
295
- let compStyles = window.getComputedStyle(this.resizeWidget.parentNode);
296
- isGrid = (compStyles.display === 'grid');
297
- }
298
- this.isGrid = isGrid;
299
- return isGrid;
300
- },
301
-
302
- stopDrag: function(e) {
303
- styleSheet.deleteRule(0)
304
- if (this.resizeWidget.hasAttribute('resizing')){
305
- this.resizeWidget.removeAttribute('resizing', '')
306
- }
307
-
308
- //this is just for grid system
309
- if (this.detectGrid()) {
310
- this.resizeWidget.style.width = null;
311
- this.resizeWidget.style.height = null;
312
- this.resizeWidget.style.left = null;
313
- this.resizeWidget.style.top = null;
314
-
315
- if (this.widthSpan) this.resizeWidget.setAttribute('class', this.originClassAttribute + ' grid-column-end:span_' + this.widthSpan);
316
- if (this.heightSpan) this.resizeWidget.setAttribute('class', this.originClassAttribute + ' grid-row-end:span_' + this.heightSpan);
317
- }
318
-
319
- DIRECTIONS.map(d => { this.removeListenerMulti(document.documentElement, EVENTS[0], this.doDrags[d]) });
320
- this.removeListenerMulti(document.documentElement, EVENTS[2], this.stopDrag);
321
- },
322
- checkLeftCorners: function(e) {
323
- let offset = e.clientY - this.getDistance(this.Drags['left'], true) + document.documentElement.scrollTop;
324
- if (offset > 10) {
325
- offset = this.getDistance(this.Drags['left'], true) + this.Drags['left'].clientHeight - e.clientY - document.documentElement.scrollTop;
326
- this.checkDragImplementation(e, 'left', 'bottom', offset, 'ne-resize', 'e-resize');
327
- } else {
328
- this.checkDragImplementation(e, 'left', 'top', offset, 'se-resize', 'e-resize');
329
- }
330
- },
331
- checkTopCorners: function(e) {
332
- let offset = e.clientX - this.getDistance(this.Drags['top'], false) + document.documentElement.scrollTop;
333
- if (offset > 10) {
334
- offset = this.getDistance(this.Drags['top'], false) + this.Drags['top'].clientWidth - e.clientX - document.documentElement.scrollLeft;
335
- this.checkDragImplementation(e, 'top', 'right', offset, 'ne-resize', 's-resize');
336
- } else {
337
- this.checkDragImplementation(e, 'top', 'left', offset, 'se-resize', 's-resize');
338
- }
339
- },
340
- checkBottomCorners: function(e) {
341
- let offset = e.clientX - this.getDistance(this.Drags['bottom'], false) + document.documentElement.scrollTop;
342
- if (offset > 10) {
343
- offset = this.getDistance(this.Drags['bottom'], false) + this.Drags['bottom'].clientWidth - e.clientX - document.documentElement.scrollLeft;
344
- this.checkDragImplementation(e, 'bottom', 'right', offset, 'se-resize', 's-resize');
345
- } else {
346
- this.checkDragImplementation(e, 'bottom', 'left', offset, 'ne-resize', 's-resize');
347
- }
348
- },
349
- checkRightCorners: function(e) {
350
- let offset = e.clientY - this.getDistance(this.Drags['right'], true) + document.documentElement.scrollTop;
351
- if (offset > 10) {
352
- offset = this.getDistance(this.Drags['right'], true) + this.Drags['right'].clientHeight - e.clientY - document.documentElement.scrollTop;
353
- this.checkDragImplementation(e, 'right', 'bottom', offset, 'se-resize', 'e-resize');
354
- } else {
355
- this.checkDragImplementation(e, 'right', 'top', offset, 'ne-resize', 'e-resize');
356
- }
357
- },
358
-
359
- bindListeners: function() {
360
- this.doDrags['left'] = this.doLeftDrag.bind(this);
361
- this.doDrags['top'] = this.doTopDrag.bind(this);
362
- this.doDrags['right'] = this.doRightDrag.bind(this);
363
- this.doDrags['bottom'] = this.doBottomDrag.bind(this);
364
-
365
- this.stopDrag = this.stopDrag.bind(this);
366
-
367
- this.checkCorners['left'] = this.checkLeftCorners.bind(this);
368
- this.checkCorners['top'] = this.checkTopCorners.bind(this);
369
- this.checkCorners['bottom'] = this.checkBottomCorners.bind(this);
370
- this.checkCorners['right'] = this.checkRightCorners.bind(this);
371
-
372
- this.initDrags['top'] = this.initTopDrag.bind(this);
373
- this.initDrags['left'] = this.initLeftDrag.bind(this);
374
- this.initDrags['bottom'] = this.initBottomDrag.bind(this);
375
- this.initDrags['right'] = this.initRightDrag.bind(this);
376
- },
377
-
378
- getDistance: function(elem, flag) {
379
- var location = 0;
380
- if (!elem) return;
381
- if (elem.offsetParent) {
382
- do {
383
- location += (flag) ? elem.offsetTop : elem.offsetLeft;
384
- elem = elem.offsetParent;
385
- } while (elem);
386
- }
387
- return location >= 0 ? location : 0;
388
- },
389
-
390
- // Bind multiiple events to a listener
391
- addListenerMulti: function(element, eventNames, listener) {
392
- var events = eventNames.split(' ');
393
- for (var i = 0, iLen = events.length; i < iLen; i++) {
394
- element.addEventListener(events[i], listener, { passive: false });
395
- }
396
- },
397
-
398
- // Remove multiiple events from a listener
399
- removeListenerMulti: function(element, eventNames, listener) {
400
- var events = eventNames.split(' ');
401
- for (var i = 0, iLen = events.length; i < iLen; i++) {
402
- element.removeEventListener(events[i], listener, { passive: false });
403
- }
404
- },
405
-
406
- collaborate: function({left, top, width, height, rowEnd, columnEnd}) {
407
- if (window.CoCreate && window.CoCreate.text) {
408
- let domTextEditor = this.resizeWidget.closest('[contenteditable]');
409
- if (domTextEditor) {
410
- if (left)
411
- CoCreate.text.setStyle({
412
- domTextEditor, target: this.resizeWidget, property: 'left', value: left + 'px'
413
- })
414
- if (top)
415
- CoCreate.text.setStyle({
416
- domTextEditor, target: this.resizeWidget, property: 'top', value: top + 'px'
417
- })
418
- if (width)
419
- CoCreate.text.setStyle({
420
- domTextEditor, target: this.resizeWidget, property: 'width', value: width + 'px'
421
- })
422
- if (height)
423
- CoCreate.text.setStyle({
424
- domTextEditor, target: this.resizeWidget, property: 'height', value: height + 'px'
425
- })
426
- if (rowEnd)
427
- CoCreate.text.setStyle({
428
- domTextEditor, target: this.resizeWidget, property: 'grid-row-end', value: 'span ' + rowEnd
429
- })
430
- if (columnEnd)
431
- CoCreate.text.setStyle({
432
- domTextEditor, target: this.resizeWidget, property: 'grid-column-end', value: 'span ' + columnEnd
433
- })
434
- }
435
- }
436
- }
53
+ init: function (handleObj) {
54
+ if (this.resizeWidget) {
55
+ this.initDrags = [];
56
+ this.checkCorners = [];
57
+ this.doDrags = [];
58
+ this.Drags = [];
59
+
60
+ //this is for grid
61
+ this.isGrid = this.detectGrid();
62
+ this.gridWidth = 0;
63
+ this.gridHeight = 0;
64
+ this.limitSpan = 0;
65
+ this.widthSpan = 0;
66
+ this.heightSpan = 0;
67
+ this.originClassAttribute = this.resizeWidget.getAttribute("class");
68
+
69
+ DIRECTIONS.map((d) => {
70
+ this.Drags[d] = this.resizeWidget.querySelector(
71
+ handleObj["drag" + d.charAt(0).toUpperCase() + d.slice(1)]
72
+ );
73
+ });
74
+
75
+ this.bindListeners();
76
+ this.initResize();
77
+
78
+ //this is just for grid system
79
+ this.getGridProperty();
80
+ window.addEventListener("resize", this.checkGridColumns.bind(this));
81
+ }
82
+ },
83
+
84
+ getGridProperty: function () {
85
+ if (!this.resizeWidget.parentNode) return;
86
+ let compStyles = window.getComputedStyle(this.resizeWidget.parentNode);
87
+ let gridColumns = compStyles.gridTemplateColumns;
88
+ let height = compStyles.gridAutoRows;
89
+
90
+ if (gridColumns !== "none") {
91
+ let width = gridColumns.split(" ");
92
+ this.limitSpan = width.length;
93
+ this.gridColumnGap = Number.parseInt(compStyles.gridColumnGap);
94
+ this.gridRowGap = Number.parseInt(compStyles.gridRowGap);
95
+ this.gridWidth = Number.parseFloat(width[0]);
96
+ this.gridHeight = Number.parseInt(height);
97
+ }
98
+ },
99
+
100
+ checkGridColumns: function () {
101
+ if (
102
+ typeof this.resizeWidget !== "undefined" &&
103
+ this.resizeWidget.parentNode
104
+ ) {
105
+ let compStylesOfParent = window.getComputedStyle(
106
+ this.resizeWidget.parentNode
107
+ );
108
+ let spans = 0;
109
+ let gridColumns = compStylesOfParent.gridTemplateColumns.split(" ");
110
+ let temp = gridColumns[0];
111
+ gridColumns.map((v) => {
112
+ if (v == temp) spans++;
113
+ });
114
+ this.limitSpan = spans;
115
+ if (this.resizeWidget.style["grid-column-end"]) {
116
+ let curClassAttributes = this.resizeWidget
117
+ .getAttribute("class")
118
+ .split(" ");
119
+ let prevColumnState =
120
+ curClassAttributes[curClassAttributes.length - 1].split(
121
+ "_"
122
+ );
123
+ let prevSpan = Number.parseInt(prevColumnState[1]);
124
+ let curColumnState =
125
+ this.resizeWidget.style["grid-column-end"].split(" ");
126
+ let curSpan = Number.parseInt(curColumnState[1]);
127
+
128
+ let span = 0;
129
+ if (this.limitSpan >= prevSpan) span = prevSpan;
130
+ else if (prevSpan > this.limitSpan) span = this.limitSpan;
131
+ else span = Math.min(curSpan, this.limitSpan);
132
+
133
+ this.resizeWidget.style["grid-column-end"] = "span " + span;
134
+ }
135
+ }
136
+ },
137
+
138
+ initResize: function () {
139
+ DIRECTIONS.map((d) => {
140
+ if (this.Drags[d])
141
+ this.addListenerMulti(
142
+ this.Drags[d],
143
+ EVENTS[0],
144
+ this.checkCorners[d]
145
+ );
146
+ });
147
+ },
148
+
149
+ checkDragImplementation: function (e, from, to, offset, fcur, scur) {
150
+ if (e.touches) e = e.touches[0];
151
+ let other;
152
+ if (to == "top") other = "bottom";
153
+ else if (to == "bottom") other = "top";
154
+ else if (to == "left") other = "right";
155
+ else if (to == "right") other = "left";
156
+ this.removeListenerMulti(
157
+ this.Drags[from],
158
+ EVENTS[1],
159
+ this.initDrags[from]
160
+ );
161
+ this.removeListenerMulti(
162
+ this.Drags[from],
163
+ EVENTS[1],
164
+ this.initDrags[to]
165
+ );
166
+ this.removeListenerMulti(
167
+ this.Drags[from],
168
+ EVENTS[1],
169
+ this.initDrags[other]
170
+ );
171
+ this.addListenerMulti(
172
+ this.Drags[from],
173
+ EVENTS[1],
174
+ this.initDrags[from]
175
+ );
176
+
177
+ if (offset < this.cornerSize && this.Drags[to]) {
178
+ this.Drags[from].style.cursor = fcur;
179
+ this.addListenerMulti(
180
+ this.Drags[from],
181
+ EVENTS[1],
182
+ this.initDrags[to]
183
+ );
184
+ } else {
185
+ this.Drags[from].style.cursor = scur;
186
+ }
187
+ },
188
+
189
+ initDrag: function (e, idx) {
190
+ e.preventDefault();
191
+
192
+ if (!this.resizeWidget.hasAttribute("resizing")) {
193
+ this.resizeWidget.setAttribute("resizing", "");
194
+ }
195
+
196
+ let selector = document.defaultView.getComputedStyle(this.resizeWidget);
197
+ styleSheet.insertRule("iframe {pointer-events: none}", 0);
198
+
199
+ if (idx == "top" || idx == "bottom") {
200
+ this.startTop = parseInt(selector.top, 10);
201
+ this.startHeight = parseInt(selector.height, 10);
202
+
203
+ if (e.touches) this.startY = e.touches[0].clientY;
204
+ else this.startY = e.clientY;
205
+ } else {
206
+ this.startLeft = parseInt(selector.left, 10);
207
+ this.startRight = parseInt(selector.right, 10);
208
+ this.startWidth = parseInt(selector.width, 10);
209
+
210
+ if (e.touches) this.startX = e.touches[0].clientX;
211
+ else this.startX = e.clientX;
212
+ }
213
+
214
+ this.addListenerMulti(
215
+ document.documentElement,
216
+ EVENTS[0],
217
+ this.doDrags[idx]
218
+ );
219
+ this.addListenerMulti(
220
+ document.documentElement,
221
+ EVENTS[2],
222
+ this.stopDrag
223
+ );
224
+ },
225
+
226
+ initTopDrag: function (e) {
227
+ this.initDrag(e, "top");
228
+ },
229
+ initBottomDrag: function (e) {
230
+ this.initDrag(e, "bottom");
231
+ },
232
+ initLeftDrag: function (e) {
233
+ this.initDrag(e, "left");
234
+ },
235
+ initRightDrag: function (e) {
236
+ this.initDrag(e, "right");
237
+ },
238
+
239
+ //this is just for grid system
240
+ setRowEnd: function (height) {
241
+ if (this.gridHeight) {
242
+ this.heightSpan = Math.ceil(
243
+ (height - (this.heightSpan - 1) * this.gridRowGap) /
244
+ this.gridHeight
245
+ );
246
+ this.resizeWidget.style["grid-row-end"] = "span " + this.heightSpan;
247
+ this.collaborate({ rowEnd: this.heightSpan });
248
+ }
249
+ },
250
+
251
+ doTopDrag: function (e) {
252
+ let top, height;
253
+
254
+ if (e.touches) e = e.touches[0];
255
+ top = this.startTop + e.clientY - this.startY;
256
+ height = this.startHeight - e.clientY + this.startY;
257
+
258
+ if (height < 10) return;
259
+ if (!this.isGrid) {
260
+ this.resizeWidget.style.top = top + "px";
261
+ this.collaborate({ top, height });
262
+ }
263
+ this.resizeWidget.style.height = height + "px";
264
+ this.setRowEnd(height);
265
+ },
266
+
267
+ doBottomDrag: function (e) {
268
+ let height;
269
+
270
+ if (e.touches) e = e.touches[0];
271
+
272
+ height = this.startHeight + e.clientY - this.startY;
273
+
274
+ if (height < 10) return;
275
+ if (!this.isGrid) this.collaborate({ height });
276
+
277
+ this.resizeWidget.style.height = height + "px";
278
+ this.setRowEnd(height);
279
+ },
280
+
281
+ //this is just for grid system
282
+ setColumnEnd: function (width) {
283
+ if (this.gridWidth) {
284
+ let spans = Math.ceil(
285
+ (width - (this.widthSpan - 1) * this.gridColumnGap) /
286
+ this.gridWidth
287
+ );
288
+ this.widthSpan = spans > this.limitSpan ? this.limitSpan : spans;
289
+ this.resizeWidget.style["grid-column-end"] =
290
+ "span " + this.widthSpan;
291
+ this.collaborate({ columnEnd: this.widthSpan });
292
+ }
293
+ },
294
+
295
+ doLeftDrag: function (e) {
296
+ let left, right, width;
297
+ if (e.touches) e = e.touches[0];
298
+ left = this.startLeft + e.clientX - this.startX;
299
+ right = this.startRight;
300
+ width = this.startWidth - e.clientX + this.startX;
301
+
302
+ if (width < 10) return;
303
+ if (!this.isGrid) {
304
+ this.resizeWidget.style.left = "";
305
+ this.resizeWidget.style.right = right + "px";
306
+ this.collaborate({ left, width });
307
+ }
308
+
309
+ this.resizeWidget.style.width = width + "px";
310
+ this.setColumnEnd(width);
311
+ },
312
+
313
+ doRightDrag: function (e) {
314
+ let width;
315
+ if (e.touches) e = e.touches[0];
316
+ width = this.startWidth + e.clientX - this.startX;
317
+ if (width < 10) return;
318
+
319
+ if (!this.isGrid) this.collaborate({ width });
320
+
321
+ this.resizeWidget.style.width = width + "px";
322
+ this.setColumnEnd(width);
323
+ },
324
+
325
+ detectGrid: function () {
326
+ let isGrid = false;
327
+ if (this.resizeWidget.parentNode) {
328
+ let compStyles = window.getComputedStyle(
329
+ this.resizeWidget.parentNode
330
+ );
331
+ isGrid = compStyles.display === "grid";
332
+ }
333
+ this.isGrid = isGrid;
334
+ return isGrid;
335
+ },
336
+
337
+ stopDrag: function (e) {
338
+ styleSheet.deleteRule(0);
339
+ if (this.resizeWidget.hasAttribute("resizing")) {
340
+ this.resizeWidget.removeAttribute("resizing", "");
341
+ }
342
+
343
+ //this is just for grid system
344
+ if (this.detectGrid()) {
345
+ this.resizeWidget.style.width = null;
346
+ this.resizeWidget.style.height = null;
347
+ this.resizeWidget.style.left = null;
348
+ this.resizeWidget.style.top = null;
349
+
350
+ if (this.widthSpan)
351
+ this.resizeWidget.setAttribute(
352
+ "class",
353
+ this.originClassAttribute +
354
+ " grid-column-end:span_" +
355
+ this.widthSpan
356
+ );
357
+ if (this.heightSpan)
358
+ this.resizeWidget.setAttribute(
359
+ "class",
360
+ this.originClassAttribute +
361
+ " grid-row-end:span_" +
362
+ this.heightSpan
363
+ );
364
+ }
365
+
366
+ DIRECTIONS.map((d) => {
367
+ this.removeListenerMulti(
368
+ document.documentElement,
369
+ EVENTS[0],
370
+ this.doDrags[d]
371
+ );
372
+ });
373
+ this.removeListenerMulti(
374
+ document.documentElement,
375
+ EVENTS[2],
376
+ this.stopDrag
377
+ );
378
+ },
379
+ checkLeftCorners: function (e) {
380
+ let offset =
381
+ e.clientY -
382
+ this.getDistance(this.Drags["left"], true) +
383
+ document.documentElement.scrollTop;
384
+ if (offset > 10) {
385
+ offset =
386
+ this.getDistance(this.Drags["left"], true) +
387
+ this.Drags["left"].clientHeight -
388
+ e.clientY -
389
+ document.documentElement.scrollTop;
390
+ this.checkDragImplementation(
391
+ e,
392
+ "left",
393
+ "bottom",
394
+ offset,
395
+ "ne-resize",
396
+ "e-resize"
397
+ );
398
+ } else {
399
+ this.checkDragImplementation(
400
+ e,
401
+ "left",
402
+ "top",
403
+ offset,
404
+ "se-resize",
405
+ "e-resize"
406
+ );
407
+ }
408
+ },
409
+ checkTopCorners: function (e) {
410
+ let offset =
411
+ e.clientX -
412
+ this.getDistance(this.Drags["top"], false) +
413
+ document.documentElement.scrollTop;
414
+ if (offset > 10) {
415
+ offset =
416
+ this.getDistance(this.Drags["top"], false) +
417
+ this.Drags["top"].clientWidth -
418
+ e.clientX -
419
+ document.documentElement.scrollLeft;
420
+ this.checkDragImplementation(
421
+ e,
422
+ "top",
423
+ "right",
424
+ offset,
425
+ "ne-resize",
426
+ "s-resize"
427
+ );
428
+ } else {
429
+ this.checkDragImplementation(
430
+ e,
431
+ "top",
432
+ "left",
433
+ offset,
434
+ "se-resize",
435
+ "s-resize"
436
+ );
437
+ }
438
+ },
439
+ checkBottomCorners: function (e) {
440
+ let offset =
441
+ e.clientX -
442
+ this.getDistance(this.Drags["bottom"], false) +
443
+ document.documentElement.scrollTop;
444
+ if (offset > 10) {
445
+ offset =
446
+ this.getDistance(this.Drags["bottom"], false) +
447
+ this.Drags["bottom"].clientWidth -
448
+ e.clientX -
449
+ document.documentElement.scrollLeft;
450
+ this.checkDragImplementation(
451
+ e,
452
+ "bottom",
453
+ "right",
454
+ offset,
455
+ "se-resize",
456
+ "s-resize"
457
+ );
458
+ } else {
459
+ this.checkDragImplementation(
460
+ e,
461
+ "bottom",
462
+ "left",
463
+ offset,
464
+ "ne-resize",
465
+ "s-resize"
466
+ );
467
+ }
468
+ },
469
+ checkRightCorners: function (e) {
470
+ let offset =
471
+ e.clientY -
472
+ this.getDistance(this.Drags["right"], true) +
473
+ document.documentElement.scrollTop;
474
+ if (offset > 10) {
475
+ offset =
476
+ this.getDistance(this.Drags["right"], true) +
477
+ this.Drags["right"].clientHeight -
478
+ e.clientY -
479
+ document.documentElement.scrollTop;
480
+ this.checkDragImplementation(
481
+ e,
482
+ "right",
483
+ "bottom",
484
+ offset,
485
+ "se-resize",
486
+ "e-resize"
487
+ );
488
+ } else {
489
+ this.checkDragImplementation(
490
+ e,
491
+ "right",
492
+ "top",
493
+ offset,
494
+ "ne-resize",
495
+ "e-resize"
496
+ );
497
+ }
498
+ },
499
+
500
+ bindListeners: function () {
501
+ this.doDrags["left"] = this.doLeftDrag.bind(this);
502
+ this.doDrags["top"] = this.doTopDrag.bind(this);
503
+ this.doDrags["right"] = this.doRightDrag.bind(this);
504
+ this.doDrags["bottom"] = this.doBottomDrag.bind(this);
505
+
506
+ this.stopDrag = this.stopDrag.bind(this);
507
+
508
+ this.checkCorners["left"] = this.checkLeftCorners.bind(this);
509
+ this.checkCorners["top"] = this.checkTopCorners.bind(this);
510
+ this.checkCorners["bottom"] = this.checkBottomCorners.bind(this);
511
+ this.checkCorners["right"] = this.checkRightCorners.bind(this);
512
+
513
+ this.initDrags["top"] = this.initTopDrag.bind(this);
514
+ this.initDrags["left"] = this.initLeftDrag.bind(this);
515
+ this.initDrags["bottom"] = this.initBottomDrag.bind(this);
516
+ this.initDrags["right"] = this.initRightDrag.bind(this);
517
+ },
518
+
519
+ getDistance: function (elem, flag) {
520
+ var location = 0;
521
+ if (!elem) return;
522
+ if (elem.offsetParent) {
523
+ do {
524
+ location += flag ? elem.offsetTop : elem.offsetLeft;
525
+ elem = elem.offsetParent;
526
+ } while (elem);
527
+ }
528
+ return location >= 0 ? location : 0;
529
+ },
530
+
531
+ // Bind multiiple events to a listener
532
+ addListenerMulti: function (element, eventNames, listener) {
533
+ var events = eventNames.split(" ");
534
+ for (var i = 0, iLen = events.length; i < iLen; i++) {
535
+ element.addEventListener(events[i], listener, { passive: false });
536
+ }
537
+ },
538
+
539
+ // Remove multiiple events from a listener
540
+ removeListenerMulti: function (element, eventNames, listener) {
541
+ var events = eventNames.split(" ");
542
+ for (var i = 0, iLen = events.length; i < iLen; i++) {
543
+ element.removeEventListener(events[i], listener, {
544
+ passive: false
545
+ });
546
+ }
547
+ },
548
+
549
+ collaborate: function ({ left, top, width, height, rowEnd, columnEnd }) {
550
+ if (window.CoCreate && window.CoCreate.text) {
551
+ let domTextEditor = this.resizeWidget.closest("[contenteditable]");
552
+ if (domTextEditor) {
553
+ if (left)
554
+ CoCreate.text.setStyle({
555
+ domTextEditor,
556
+ target: this.resizeWidget,
557
+ property: "left",
558
+ value: left + "px"
559
+ });
560
+ if (top)
561
+ CoCreate.text.setStyle({
562
+ domTextEditor,
563
+ target: this.resizeWidget,
564
+ property: "top",
565
+ value: top + "px"
566
+ });
567
+ if (width)
568
+ CoCreate.text.setStyle({
569
+ domTextEditor,
570
+ target: this.resizeWidget,
571
+ property: "width",
572
+ value: width + "px"
573
+ });
574
+ if (height)
575
+ CoCreate.text.setStyle({
576
+ domTextEditor,
577
+ target: this.resizeWidget,
578
+ property: "height",
579
+ value: height + "px"
580
+ });
581
+ if (rowEnd)
582
+ CoCreate.text.setStyle({
583
+ domTextEditor,
584
+ target: this.resizeWidget,
585
+ property: "grid-row-end",
586
+ value: "span " + rowEnd
587
+ });
588
+ if (columnEnd)
589
+ CoCreate.text.setStyle({
590
+ domTextEditor,
591
+ target: this.resizeWidget,
592
+ property: "grid-column-end",
593
+ value: "span " + columnEnd
594
+ });
595
+ }
596
+ }
597
+ }
437
598
  };
438
599
 
600
+ // Function to auto-resize the element based on its content
601
+ function autoResizeElement(element) {
602
+ // Reset height to auto to calculate scrollHeight correctly
603
+ element.style.height = "auto";
604
+
605
+ let scrollHeight;
606
+ if (element.contentDocument) {
607
+ scrollHeight = element.contentDocument.body.scrollHeight;
608
+ } else {
609
+ // For other elements, get scrollHeight directly
610
+ scrollHeight = element.scrollHeight;
611
+ }
612
+
613
+ // Set the height of the element to the calculated scrollHeight
614
+ element.style.height = scrollHeight + "px";
615
+ }
616
+
617
+ // Observe the resize of the element
618
+ function observeElementResize(element) {
619
+ const resizeObserver = new ResizeObserver(() => {
620
+ autoResizeElement(element);
621
+ });
622
+
623
+ resizeObserver.observe(element);
624
+ }
625
+
626
+ // Listen for input events on the entire document
627
+ function initAutoHeight(element) {
628
+ if (
629
+ element &&
630
+ !(element instanceof HTMLCollection) &&
631
+ !(element instanceof NodeList) &&
632
+ !Array.isArray(element)
633
+ )
634
+ element = [element];
635
+ else if (!element) {
636
+ element = document.querySelectorAll('[height="auto"]');
637
+
638
+ // Add event listener for iframes on load
639
+ document.addEventListener(
640
+ "input",
641
+ function (event) {
642
+ // Check if the target element has height="auto"
643
+ if (event.target.getAttribute("height") === "auto") {
644
+ autoResizeElement(event.target);
645
+ }
646
+ },
647
+ false
648
+ );
649
+
650
+ if (element.contentDocument) {
651
+ // Create a MutationObserver for changes within the iframe's body
652
+ const observer = new MutationObserver(autoResizeElement);
653
+ observer.observe(iframeDocument.body, {
654
+ childList: true,
655
+ subtree: true
656
+ });
657
+
658
+ // Handle iframe document changes (e.g., if src or srcdoc is modified)
659
+ element.addEventListener("load", () => {
660
+ observer.disconnect(); // Disconnect the previous observer
661
+ observeIframeContent(); // Reinitialize the observer on new document
662
+ });
663
+ }
664
+ }
665
+
666
+ for (let i = 0; i < element.length; i++) {
667
+ autoResizeElement(element[i]);
668
+ observeElementResize(element[i]); // Observe resize changes
669
+ }
670
+ }
671
+
672
+ initAutoHeight();
673
+
439
674
  observer.init({
440
- name: 'CoCreateResize',
441
- observe: ['addedNodes'],
442
- selector: "[resizable]:not([resizable='false'])",
443
- callback: function(mutation) {
444
- coCreateResize.initElement(mutation.target);
675
+ name: "CoCreateResize",
676
+ observe: ["addedNodes"],
677
+ selector: "[resizable]:not([resizable='false'])",
678
+ callback: function (mutation) {
679
+ coCreateResize.initElement(mutation.target);
680
+ }
681
+ });
445
682
 
446
- }
683
+ observer.init({
684
+ name: "CoCreateResize",
685
+ observe: ["addedNodes"],
686
+ selector: "[height='auto']",
687
+ callback: function (mutation) {
688
+ initAutoHeight(mutation.target);
689
+ }
447
690
  });
448
691
 
449
692
  coCreateResize.init({
450
- selector: "[resizable]:not([resizable='false'])",
451
- dragLeft: "[resize='left']",
452
- dragRight: "[resize='right']",
453
- dragTop: "[resize='top']",
454
- dragBottom: "[resize='bottom']",
693
+ selector: "[resizable]:not([resizable='false'])",
694
+ dragLeft: "[resize='left']",
695
+ dragRight: "[resize='right']",
696
+ dragTop: "[resize='top']",
697
+ dragBottom: "[resize='bottom']"
455
698
  });
456
699
  export default coCreateResize;