@innovastudio/contentbuilder 1.4.145 → 1.4.147
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.
|
@@ -10355,6 +10355,14 @@ class HtmlUtil {
|
|
|
10355
10355
|
this.builder.opts.onRender();
|
|
10356
10356
|
}
|
|
10357
10357
|
if (mode === 'full') {
|
|
10358
|
+
// freeform
|
|
10359
|
+
if (this.builder.docContainer) {
|
|
10360
|
+
this.builder.loadHTML(html);
|
|
10361
|
+
util.clearControls();
|
|
10362
|
+
this.builder.hideModal(modal);
|
|
10363
|
+
return;
|
|
10364
|
+
}
|
|
10365
|
+
|
|
10358
10366
|
// area.innerHTML = html;
|
|
10359
10367
|
area.innerHTML = '';
|
|
10360
10368
|
// Use createContextualFragment() to make embedded script executable
|
|
@@ -10879,10 +10887,12 @@ class HtmlUtil {
|
|
|
10879
10887
|
dom$k.removeElements(tmp.querySelectorAll('.row-add-initial'));
|
|
10880
10888
|
|
|
10881
10889
|
//Extra cleaning
|
|
10882
|
-
|
|
10883
|
-
|
|
10884
|
-
|
|
10885
|
-
|
|
10890
|
+
if (this.builder.cleanAOS) {
|
|
10891
|
+
elms = tmp.querySelectorAll('.aos-init');
|
|
10892
|
+
dom$k.removeClasses(elms, 'aos-init');
|
|
10893
|
+
elms = tmp.querySelectorAll('.aos-animate');
|
|
10894
|
+
dom$k.removeClasses(elms, 'aos-animate');
|
|
10895
|
+
}
|
|
10886
10896
|
elms = tmp.querySelectorAll('.skrollable');
|
|
10887
10897
|
dom$k.removeClasses(elms, 'skrollable');
|
|
10888
10898
|
elms = tmp.querySelectorAll('.skrollable-after');
|
|
@@ -11202,6 +11212,23 @@ class HtmlUtil {
|
|
|
11202
11212
|
elms = tmp.querySelectorAll('[data-html-25]');
|
|
11203
11213
|
dom$k.removeAttributes(elms, 'data-html-25');
|
|
11204
11214
|
}
|
|
11215
|
+
|
|
11216
|
+
// freeform
|
|
11217
|
+
elms = tmp.querySelectorAll('.is-block .handle, .is-block .rotate-handle');
|
|
11218
|
+
dom$k.removeElements(elms);
|
|
11219
|
+
elms = tmp.querySelectorAll('.is-block');
|
|
11220
|
+
Array.prototype.forEach.call(elms, elm => {
|
|
11221
|
+
dom$k.removeClass(elm, 'active');
|
|
11222
|
+
dom$k.removeClass(elm, 'multi');
|
|
11223
|
+
dom$k.removeClass(elm, 'editable');
|
|
11224
|
+
dom$k.removeClass(elm, 'fluid');
|
|
11225
|
+
dom$k.removeClass(elm, 'cloned');
|
|
11226
|
+
elm.removeAttribute('data-fluid-val');
|
|
11227
|
+
elm.removeAttribute('data-fluid');
|
|
11228
|
+
});
|
|
11229
|
+
tmp.querySelectorAll('.is-block.clone').forEach(elm => elm.parentNode.removeChild(elm));
|
|
11230
|
+
// tmp.querySelectorAll('.is-block.cloned').forEach(elm=>elm.classList.remove('cloned'));
|
|
11231
|
+
|
|
11205
11232
|
html = tmp.innerHTML.trim();
|
|
11206
11233
|
html = html.replace(/<font/g, '<span').replace(/<\/font/g, '</span');
|
|
11207
11234
|
}
|
|
@@ -14528,7 +14555,7 @@ Insipred by: https://www.kirupa.com/html5/drag.htm
|
|
|
14528
14555
|
*/
|
|
14529
14556
|
|
|
14530
14557
|
let initialX, initialY, currentX, currentY, xOffset, yOffset, dragActive, activeDraggableBox;
|
|
14531
|
-
class Draggable$
|
|
14558
|
+
class Draggable$2 {
|
|
14532
14559
|
constructor(opts = {}) {
|
|
14533
14560
|
this.opts = opts;
|
|
14534
14561
|
const elms = document.querySelectorAll(this.opts.selector);
|
|
@@ -14692,7 +14719,7 @@ const renderGridEditor = builder => {
|
|
|
14692
14719
|
//<button title="${util.out('Element Tool')}" class="cell-elmtool"><svg class="is-icon-flex" style="width:12px;height:12px;"><use xlink:href="#ion-ios-gear"></use></svg></button>
|
|
14693
14720
|
|
|
14694
14721
|
dom.appendHtml(builderStuff, html);
|
|
14695
|
-
new Draggable$
|
|
14722
|
+
new Draggable$2({
|
|
14696
14723
|
selector: '.is-draggable'
|
|
14697
14724
|
});
|
|
14698
14725
|
const grideditor = document.querySelector('.grideditor');
|
|
@@ -28673,7 +28700,7 @@ function dragControlCondition(moveable, e) {
|
|
|
28673
28700
|
return false;
|
|
28674
28701
|
}
|
|
28675
28702
|
|
|
28676
|
-
var Rotatable = {
|
|
28703
|
+
var Rotatable$1 = {
|
|
28677
28704
|
name: "rotatable",
|
|
28678
28705
|
canPinch: true,
|
|
28679
28706
|
props: {
|
|
@@ -28812,7 +28839,7 @@ var Rotatable = {
|
|
|
28812
28839
|
datas.startValue = rotatation * Math.PI / 180;
|
|
28813
28840
|
}
|
|
28814
28841
|
}, fillTransformStartEvent(e)), {
|
|
28815
|
-
dragStart: Draggable.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
28842
|
+
dragStart: Draggable$1.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
28816
28843
|
}));
|
|
28817
28844
|
var result = triggerEvent(moveable, "onRotateStart", params);
|
|
28818
28845
|
datas.isRotate = result !== false;
|
|
@@ -32513,7 +32540,7 @@ var Snappable = {
|
|
|
32513
32540
|
* @description Draggable refers to the ability to drag and move targets.
|
|
32514
32541
|
*/
|
|
32515
32542
|
|
|
32516
|
-
var Draggable = {
|
|
32543
|
+
var Draggable$1 = {
|
|
32517
32544
|
name: "draggable",
|
|
32518
32545
|
props: {
|
|
32519
32546
|
draggable: Boolean,
|
|
@@ -33401,7 +33428,7 @@ function fillTransformEvent(moveable, nextTransform, delta, isPinch, e) {
|
|
|
33401
33428
|
fillOriginalTransform(e, nextTransform);
|
|
33402
33429
|
return {
|
|
33403
33430
|
transform: nextTransform,
|
|
33404
|
-
drag: Draggable.drag(moveable, setCustomDrag(e, moveable.state, delta, isPinch, false))
|
|
33431
|
+
drag: Draggable$1.drag(moveable, setCustomDrag(e, moveable.state, delta, isPinch, false))
|
|
33405
33432
|
};
|
|
33406
33433
|
}
|
|
33407
33434
|
|
|
@@ -35298,7 +35325,7 @@ var Pinchable = makeAble("pinchable", {
|
|
|
35298
35325
|
* @description Resizable indicates whether the target's width and height can be increased or decreased.
|
|
35299
35326
|
*/
|
|
35300
35327
|
|
|
35301
|
-
var Resizable = {
|
|
35328
|
+
var Resizable$1 = {
|
|
35302
35329
|
name: "resizable",
|
|
35303
35330
|
ableGroup: "size",
|
|
35304
35331
|
canPinch: true,
|
|
@@ -35443,7 +35470,7 @@ var Resizable = {
|
|
|
35443
35470
|
setOrigin: function (origin) {
|
|
35444
35471
|
datas.transformOrigin = origin;
|
|
35445
35472
|
},
|
|
35446
|
-
dragStart: Draggable.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
35473
|
+
dragStart: Draggable$1.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
35447
35474
|
});
|
|
35448
35475
|
var result = triggerEvent(moveable, "onResizeStart", params);
|
|
35449
35476
|
|
|
@@ -35628,7 +35655,7 @@ var Resizable = {
|
|
|
35628
35655
|
dist: [distWidth, distHeight],
|
|
35629
35656
|
delta: delta,
|
|
35630
35657
|
isPinch: !!isPinch,
|
|
35631
|
-
drag: Draggable.drag(moveable, setCustomDrag(e, moveable.state, inverseDelta, !!isPinch, false))
|
|
35658
|
+
drag: Draggable$1.drag(moveable, setCustomDrag(e, moveable.state, inverseDelta, !!isPinch, false))
|
|
35632
35659
|
});
|
|
35633
35660
|
triggerEvent(moveable, "onResize", params);
|
|
35634
35661
|
return params;
|
|
@@ -36220,7 +36247,7 @@ var Scalable = {
|
|
|
36220
36247
|
setRatio: setRatio,
|
|
36221
36248
|
setFixedDirection: setFixedDirection
|
|
36222
36249
|
}, fillTransformStartEvent(e)), {
|
|
36223
|
-
dragStart: Draggable.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
36250
|
+
dragStart: Draggable$1.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
36224
36251
|
}));
|
|
36225
36252
|
var result = triggerEvent(moveable, "onScaleStart", params);
|
|
36226
36253
|
|
|
@@ -39363,7 +39390,7 @@ var OriginDraggable = {
|
|
|
39363
39390
|
var datas = e.datas;
|
|
39364
39391
|
setDragStart(moveable, e);
|
|
39365
39392
|
var params = fillParams(moveable, e, {
|
|
39366
|
-
dragStart: Draggable.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
39393
|
+
dragStart: Draggable$1.dragStart(moveable, new CustomGesto().dragStart([0, 0], e))
|
|
39367
39394
|
});
|
|
39368
39395
|
var result = triggerEvent(moveable, "onDragOriginStart", params);
|
|
39369
39396
|
datas.startOrigin = moveable.state.transformOrigin;
|
|
@@ -39426,7 +39453,7 @@ var OriginDraggable = {
|
|
|
39426
39453
|
dist: dist,
|
|
39427
39454
|
delta: delta,
|
|
39428
39455
|
transformOrigin: transformOrigin,
|
|
39429
|
-
drag: Draggable.drag(moveable, setCustomDrag(e, moveable.state, dragDelta, !!isPinch, false))
|
|
39456
|
+
drag: Draggable$1.drag(moveable, setCustomDrag(e, moveable.state, dragDelta, !!isPinch, false))
|
|
39430
39457
|
});
|
|
39431
39458
|
triggerEvent(moveable, "onDragOrigin", params);
|
|
39432
39459
|
return params;
|
|
@@ -41838,13 +41865,13 @@ var edgeDraggable = makeAble("edgeDraggable", {
|
|
|
41838
41865
|
return hasClass(target, prefix("direction")) && hasClass(target, prefix("line"));
|
|
41839
41866
|
},
|
|
41840
41867
|
dragControlStart: function (moveable, e) {
|
|
41841
|
-
return Draggable.dragStart(moveable, getDraggableEvent(e));
|
|
41868
|
+
return Draggable$1.dragStart(moveable, getDraggableEvent(e));
|
|
41842
41869
|
},
|
|
41843
41870
|
dragControl: function (moveable, e) {
|
|
41844
|
-
return Draggable.drag(moveable, getDraggableEvent(e));
|
|
41871
|
+
return Draggable$1.drag(moveable, getDraggableEvent(e));
|
|
41845
41872
|
},
|
|
41846
41873
|
dragControlEnd: function (moveable, e) {
|
|
41847
|
-
return Draggable.dragEnd(moveable, getDraggableEvent(e));
|
|
41874
|
+
return Draggable$1.dragEnd(moveable, getDraggableEvent(e));
|
|
41848
41875
|
},
|
|
41849
41876
|
dragGroupControlCondition: function (moveable, e) {
|
|
41850
41877
|
if (!moveable.props.edgeDraggable || !e.inputEvent) {
|
|
@@ -41855,16 +41882,16 @@ var edgeDraggable = makeAble("edgeDraggable", {
|
|
|
41855
41882
|
return hasClass(target, prefix("direction")) && hasClass(target, prefix("line"));
|
|
41856
41883
|
},
|
|
41857
41884
|
dragGroupControlStart: function (moveable, e) {
|
|
41858
|
-
return Draggable.dragGroupStart(moveable, getDraggableEvent(e));
|
|
41885
|
+
return Draggable$1.dragGroupStart(moveable, getDraggableEvent(e));
|
|
41859
41886
|
},
|
|
41860
41887
|
dragGroupControl: function (moveable, e) {
|
|
41861
|
-
return Draggable.dragGroup(moveable, getDraggableEvent(e));
|
|
41888
|
+
return Draggable$1.dragGroup(moveable, getDraggableEvent(e));
|
|
41862
41889
|
},
|
|
41863
41890
|
dragGroupControlEnd: function (moveable, e) {
|
|
41864
|
-
return Draggable.dragGroupEnd(moveable, getDraggableEvent(e));
|
|
41891
|
+
return Draggable$1.dragGroupEnd(moveable, getDraggableEvent(e));
|
|
41865
41892
|
},
|
|
41866
41893
|
unset: function (moveable) {
|
|
41867
|
-
return Draggable.unset(moveable);
|
|
41894
|
+
return Draggable$1.unset(moveable);
|
|
41868
41895
|
}
|
|
41869
41896
|
});
|
|
41870
41897
|
/**
|
|
@@ -41888,7 +41915,7 @@ var IndividualGroupable = {
|
|
|
41888
41915
|
},
|
|
41889
41916
|
events: {}
|
|
41890
41917
|
};
|
|
41891
|
-
var MOVEABLE_ABLES = [BeforeRenderable, Default, Snappable, Pinchable, Draggable, edgeDraggable, Rotatable, Resizable, Scalable, Warpable, Scrollable, Padding, Origin, OriginDraggable, Clippable, Roundable, Groupable, IndividualGroupable, Clickable, DragArea, Renderable];
|
|
41918
|
+
var MOVEABLE_ABLES = [BeforeRenderable, Default, Snappable, Pinchable, Draggable$1, edgeDraggable, Rotatable$1, Resizable$1, Scalable, Warpable, Scrollable, Padding, Origin, OriginDraggable, Clippable, Roundable, Groupable, IndividualGroupable, Clickable, DragArea, Renderable];
|
|
41892
41919
|
var MOVEABLE_EVENTS_PROPS_MAP = /*#__PURE__*/MOVEABLE_ABLES.reduce(function (current, able) {
|
|
41893
41920
|
return __assign$2(__assign$2({}, current), "events" in able ? able.events : {});
|
|
41894
41921
|
}, {});
|
|
@@ -52085,7 +52112,7 @@ class ColorPicker {
|
|
|
52085
52112
|
});
|
|
52086
52113
|
};
|
|
52087
52114
|
setupTabKeys(pickcolor);
|
|
52088
|
-
new Draggable$
|
|
52115
|
+
new Draggable$2({
|
|
52089
52116
|
selector: '#' + this.id + ' .is-draggable'
|
|
52090
52117
|
});
|
|
52091
52118
|
let tmp = document.createElement('div');
|
|
@@ -52950,7 +52977,7 @@ class GradientPicker {
|
|
|
52950
52977
|
});
|
|
52951
52978
|
};
|
|
52952
52979
|
setupTabKeys(pickGradient);
|
|
52953
|
-
new Draggable$
|
|
52980
|
+
new Draggable$2({
|
|
52954
52981
|
selector: '#' + this.id + ' .is-draggable'
|
|
52955
52982
|
});
|
|
52956
52983
|
const colorPicker = new ColorPicker({
|
|
@@ -75401,7 +75428,2106 @@ class Similarity {
|
|
|
75401
75428
|
}
|
|
75402
75429
|
}
|
|
75403
75430
|
|
|
75404
|
-
|
|
75431
|
+
class Common {
|
|
75432
|
+
constructor(options) {
|
|
75433
|
+
this.selector = options && options.selector || '.is-block';
|
|
75434
|
+
this.doc = options && options.doc || document;
|
|
75435
|
+
this.win = options && options.win || window;
|
|
75436
|
+
this.onDuplicate = options && options.onDuplicate || null;
|
|
75437
|
+
}
|
|
75438
|
+
transform2d(block, x1, y1, x2, y2, x3, y3, x4, y4) {
|
|
75439
|
+
this.matrix3d = new Matrix3D();
|
|
75440
|
+
return this.matrix3d.transform2d(block, x1, y1, x2, y2, x3, y3, x4, y4);
|
|
75441
|
+
}
|
|
75442
|
+
applyPercentage(block) {
|
|
75443
|
+
const rect = this.getRect(block);
|
|
75444
|
+
const container = block.parentNode;
|
|
75445
|
+
let isChildBlock = false;
|
|
75446
|
+
if (block.parentNode.matches(this.selector)) {
|
|
75447
|
+
// child block
|
|
75448
|
+
isChildBlock = true;
|
|
75449
|
+
}
|
|
75450
|
+
|
|
75451
|
+
// const containerRect = container.getBoundingClientRect(); // if container has top/left
|
|
75452
|
+
const containerRect = this.getRect(container); // if container has top/left
|
|
75453
|
+
const left = (rect.left - containerRect.left) / container.offsetWidth * 100;
|
|
75454
|
+
const top = (rect.top - containerRect.top) / container.offsetHeight * 100;
|
|
75455
|
+
let isBlockFixed = block.classList.contains('block-steady');
|
|
75456
|
+
if (isBlockFixed) {
|
|
75457
|
+
let dividerTop = (container.offsetHeight - block.offsetHeight) / (rect.top - containerRect.top);
|
|
75458
|
+
if (isNaN(dividerTop)) {
|
|
75459
|
+
// there is possibility of 0/0
|
|
75460
|
+
dividerTop = 1;
|
|
75461
|
+
}
|
|
75462
|
+
block.style.top = `calc((100% - ${block.offsetHeight}px)/${dividerTop})`;
|
|
75463
|
+
if (isChildBlock) {
|
|
75464
|
+
block.style.top = top + '%';
|
|
75465
|
+
}
|
|
75466
|
+
let dividerLeft = (container.offsetWidth - block.offsetWidth) / (rect.left - containerRect.left);
|
|
75467
|
+
if (isNaN(dividerLeft)) {
|
|
75468
|
+
// there is possibility of 0/0
|
|
75469
|
+
dividerLeft = 1;
|
|
75470
|
+
}
|
|
75471
|
+
// if(rect.left-containerRect.left===0) { // dividerLeft = Infinity
|
|
75472
|
+
// dividerLeft=1;
|
|
75473
|
+
// }
|
|
75474
|
+
block.style.left = `calc((100% - ${block.offsetWidth}px)/${dividerLeft})`;
|
|
75475
|
+
if (isChildBlock) {
|
|
75476
|
+
block.style.left = left + '%';
|
|
75477
|
+
}
|
|
75478
|
+
} else {
|
|
75479
|
+
const width = block.offsetWidth / container.offsetWidth * 100;
|
|
75480
|
+
const height = block.offsetHeight / container.offsetHeight * 100;
|
|
75481
|
+
block.style.width = width + '%';
|
|
75482
|
+
block.style.height = height + '%';
|
|
75483
|
+
block.style.top = top + '%';
|
|
75484
|
+
block.style.left = left + '%';
|
|
75485
|
+
}
|
|
75486
|
+
}
|
|
75487
|
+
applyPixels(block) {
|
|
75488
|
+
const rect = this.getRect(block);
|
|
75489
|
+
const containerRect = this.getRect(block.parentNode); // if container has top/left
|
|
75490
|
+
block.style.left = rect.left - containerRect.left + 'px';
|
|
75491
|
+
block.style.top = rect.top - containerRect.top + 'px';
|
|
75492
|
+
block.style.width = block.offsetWidth + 'px';
|
|
75493
|
+
}
|
|
75494
|
+
updateHeight(block) {
|
|
75495
|
+
if (!block.parentNode) return;
|
|
75496
|
+
let clonedDiv = block.cloneNode(true);
|
|
75497
|
+
clonedDiv.style.position = 'absolute';
|
|
75498
|
+
clonedDiv.style.top = '-9999px';
|
|
75499
|
+
clonedDiv.style.left = '-9999px';
|
|
75500
|
+
block.parentNode.appendChild(clonedDiv);
|
|
75501
|
+
clonedDiv.style.height = '';
|
|
75502
|
+
setTimeout(() => {
|
|
75503
|
+
let clonedDivHeight = clonedDiv.offsetHeight;
|
|
75504
|
+
if (block.offsetHeight <= clonedDivHeight) {
|
|
75505
|
+
block.style.height = clonedDivHeight + 'px';
|
|
75506
|
+
setTimeout(() => {
|
|
75507
|
+
block.parentNode.removeChild(clonedDiv);
|
|
75508
|
+
}, 10);
|
|
75509
|
+
} else {
|
|
75510
|
+
block.parentNode.removeChild(clonedDiv);
|
|
75511
|
+
}
|
|
75512
|
+
}, 10);
|
|
75513
|
+
}
|
|
75514
|
+
duplicate() {
|
|
75515
|
+
const block = this.doc.querySelector(this.selector + '.active');
|
|
75516
|
+
if (!block) return;
|
|
75517
|
+
if (this.onDuplicate) this.onDuplicate(block);
|
|
75518
|
+
}
|
|
75519
|
+
getRect(element) {
|
|
75520
|
+
let group = element.parentNode.closest(this.selector);
|
|
75521
|
+
if (element.closest(this.selector) && group) {
|
|
75522
|
+
let transform = group.style.transform;
|
|
75523
|
+
if (transform.includes('rotate')) {
|
|
75524
|
+
// Create a temporary element with the same dimensions and position
|
|
75525
|
+
const tempGroup = this.doc.createElement('div');
|
|
75526
|
+
tempGroup.style.position = 'absolute';
|
|
75527
|
+
tempGroup.style.width = group.offsetWidth + 'px';
|
|
75528
|
+
tempGroup.style.height = group.offsetHeight + 'px';
|
|
75529
|
+
tempGroup.style.left = group.style.left;
|
|
75530
|
+
tempGroup.style.top = group.style.top;
|
|
75531
|
+
// tempGroup.style.border ='red 1px solid';
|
|
75532
|
+
group.parentNode.appendChild(tempGroup);
|
|
75533
|
+
// const wrapperRect = tempGroup.getBoundingClientRect(); // Get the unrotated position
|
|
75534
|
+
|
|
75535
|
+
// Create a temporary element with the same dimensions and position
|
|
75536
|
+
const tempElement = this.doc.createElement('div');
|
|
75537
|
+
tempElement.style.position = 'absolute';
|
|
75538
|
+
tempElement.style.width = element.offsetWidth + 'px';
|
|
75539
|
+
tempElement.style.height = element.offsetHeight + 'px';
|
|
75540
|
+
tempElement.style.left = element.style.left;
|
|
75541
|
+
tempElement.style.top = element.style.top;
|
|
75542
|
+
// tempElement.style.border ='green 1px solid';
|
|
75543
|
+
tempGroup.appendChild(tempElement);
|
|
75544
|
+
const tempRect = tempElement.getBoundingClientRect(); // Get the unrotated position
|
|
75545
|
+
|
|
75546
|
+
// let top = tempRect.top - wrapperRect.top;
|
|
75547
|
+
// let left = tempRect.left - wrapperRect.left;
|
|
75548
|
+
|
|
75549
|
+
setTimeout(() => {
|
|
75550
|
+
tempElement.parentNode.removeChild(tempElement);
|
|
75551
|
+
tempGroup.parentNode.removeChild(tempGroup);
|
|
75552
|
+
}, 0);
|
|
75553
|
+
return tempRect;
|
|
75554
|
+
}
|
|
75555
|
+
}
|
|
75556
|
+
const rect = element.getBoundingClientRect();
|
|
75557
|
+
const transform = this.win.getComputedStyle(element).getPropertyValue('transform');
|
|
75558
|
+
if (transform !== 'none') {
|
|
75559
|
+
// Create a temporary element with the same dimensions and position
|
|
75560
|
+
const tempElement = this.doc.createElement('div');
|
|
75561
|
+
tempElement.style.position = 'absolute';
|
|
75562
|
+
tempElement.style.width = element.offsetWidth + 'px';
|
|
75563
|
+
tempElement.style.height = element.offsetHeight + 'px';
|
|
75564
|
+
tempElement.style.left = element.style.left;
|
|
75565
|
+
tempElement.style.top = element.style.top;
|
|
75566
|
+
// tempElement.style.border ='green 1px solid';
|
|
75567
|
+
element.parentNode.appendChild(tempElement);
|
|
75568
|
+
|
|
75569
|
+
// Get the unrotated position of the temporary element
|
|
75570
|
+
const tempRect = tempElement.getBoundingClientRect();
|
|
75571
|
+
setTimeout(() => {
|
|
75572
|
+
tempElement.parentNode.removeChild(tempElement);
|
|
75573
|
+
}, 1);
|
|
75574
|
+
return tempRect;
|
|
75575
|
+
} else {
|
|
75576
|
+
return rect;
|
|
75577
|
+
}
|
|
75578
|
+
}
|
|
75579
|
+
getTranslateValues(transformString) {
|
|
75580
|
+
// Regular expression to match the translate values in the transform string
|
|
75581
|
+
const regex = /translate\((-?\d+\.?\d*)px, (-?\d+\.?\d*)px\)/;
|
|
75582
|
+
|
|
75583
|
+
// Use the regular expression to extract x and y values
|
|
75584
|
+
const match = transformString.match(regex);
|
|
75585
|
+
|
|
75586
|
+
// If there's a match, return an object with x and y values
|
|
75587
|
+
if (match) {
|
|
75588
|
+
const [, x, y] = match.map(parseFloat);
|
|
75589
|
+
return {
|
|
75590
|
+
x,
|
|
75591
|
+
y
|
|
75592
|
+
};
|
|
75593
|
+
}
|
|
75594
|
+
|
|
75595
|
+
// If no match, return null or handle it as needed
|
|
75596
|
+
return null;
|
|
75597
|
+
}
|
|
75598
|
+
group(className = 'is-block', groupClassName = 'is-group') {
|
|
75599
|
+
let top = Infinity;
|
|
75600
|
+
let left = Infinity;
|
|
75601
|
+
let bottom = -Infinity;
|
|
75602
|
+
let right = -Infinity;
|
|
75603
|
+
|
|
75604
|
+
// Check group
|
|
75605
|
+
let blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active'));
|
|
75606
|
+
if (blocks.length <= 1) return;
|
|
75607
|
+
|
|
75608
|
+
// Check if there is selected block that is part of other group
|
|
75609
|
+
let ok = true;
|
|
75610
|
+
blocks.forEach(block => {
|
|
75611
|
+
if (block.parentNode.matches(this.selector)) {
|
|
75612
|
+
// TODO: detach block
|
|
75613
|
+
alert('One or more blocks belong to another group.');
|
|
75614
|
+
ok = false;
|
|
75615
|
+
}
|
|
75616
|
+
});
|
|
75617
|
+
if (!ok) return;
|
|
75618
|
+
blocks.forEach(block => {
|
|
75619
|
+
let elms = block.querySelectorAll(this.selector);
|
|
75620
|
+
if (elms.length > 0) {
|
|
75621
|
+
elms.forEach(elm => elm.classList.add('active'));
|
|
75622
|
+
this.unGroup(block);
|
|
75623
|
+
}
|
|
75624
|
+
});
|
|
75625
|
+
blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active'));
|
|
75626
|
+
blocks.forEach(block => {
|
|
75627
|
+
if (!block.parentNode.matches(this.selector)) {
|
|
75628
|
+
const rect = this.getRect(block);
|
|
75629
|
+
let blockTop = rect.top;
|
|
75630
|
+
let blockLeft = rect.left;
|
|
75631
|
+
let blockWidth = block.offsetWidth;
|
|
75632
|
+
let blockHeight = block.offsetHeight;
|
|
75633
|
+
top = Math.min(top, blockTop);
|
|
75634
|
+
left = Math.min(left, blockLeft);
|
|
75635
|
+
bottom = Math.max(bottom, blockTop + blockHeight);
|
|
75636
|
+
right = Math.max(right, blockLeft + blockWidth);
|
|
75637
|
+
}
|
|
75638
|
+
});
|
|
75639
|
+
const group = this.doc.createElement('div');
|
|
75640
|
+
group.classList.add(className);
|
|
75641
|
+
group.classList.add(groupClassName);
|
|
75642
|
+
group.classList.add('block-steady');
|
|
75643
|
+
group.style.top = top + 'px';
|
|
75644
|
+
group.style.left = left + 'px';
|
|
75645
|
+
group.style.width = right + 1 - left + 'px';
|
|
75646
|
+
group.style.height = bottom + 1 - top + 'px';
|
|
75647
|
+
const container = blocks[0].parentNode;
|
|
75648
|
+
container.appendChild(group);
|
|
75649
|
+
blocks.forEach(block => {
|
|
75650
|
+
if (!block.parentNode.matches(this.selector)) {
|
|
75651
|
+
this.applyPixels(block);
|
|
75652
|
+
let blockTop = parseFloat(block.style.top) || 0;
|
|
75653
|
+
let blockLeft = parseFloat(block.style.left) || 0;
|
|
75654
|
+
|
|
75655
|
+
// Adjust position relative to the group div
|
|
75656
|
+
block.style.top = blockTop - top + 'px';
|
|
75657
|
+
block.style.left = blockLeft - left + 'px';
|
|
75658
|
+
group.appendChild(block);
|
|
75659
|
+
this.applyPercentage(block);
|
|
75660
|
+
}
|
|
75661
|
+
});
|
|
75662
|
+
this.applyPercentage(group);
|
|
75663
|
+
blocks.forEach(block => {
|
|
75664
|
+
block.classList.remove('active');
|
|
75665
|
+
});
|
|
75666
|
+
group.classList.add('active');
|
|
75667
|
+
blocks = group.querySelectorAll(this.selector);
|
|
75668
|
+
blocks.forEach(target => {
|
|
75669
|
+
// Remove all breakpoints
|
|
75670
|
+
let attributesToRemove = [];
|
|
75671
|
+
const attributes = target.attributes;
|
|
75672
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
75673
|
+
const attributeName = attributes[i].name;
|
|
75674
|
+
if (attributeName.includes('data--y-') || attributeName.includes('data--x-') || attributeName.includes('data--w-') || attributeName.includes('data--h-')) {
|
|
75675
|
+
attributesToRemove.push(attributeName);
|
|
75676
|
+
}
|
|
75677
|
+
}
|
|
75678
|
+
attributesToRemove.forEach(attr => {
|
|
75679
|
+
target.removeAttribute(attr);
|
|
75680
|
+
});
|
|
75681
|
+
|
|
75682
|
+
// Make/save current inline style as default
|
|
75683
|
+
target.removeAttribute('data-breakpoint');
|
|
75684
|
+
target.setAttribute('data--y', target.style.top);
|
|
75685
|
+
target.setAttribute('data--x', target.style.left);
|
|
75686
|
+
target.setAttribute('data--w', target.style.width);
|
|
75687
|
+
target.setAttribute('data--h', target.style.height);
|
|
75688
|
+
});
|
|
75689
|
+
return group;
|
|
75690
|
+
}
|
|
75691
|
+
unGroup(element) {
|
|
75692
|
+
let group;
|
|
75693
|
+
if (element) group = element;else {
|
|
75694
|
+
let blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active'));
|
|
75695
|
+
blocks.forEach(block => {
|
|
75696
|
+
if (block.querySelector(this.selector)) {
|
|
75697
|
+
// this block is a group
|
|
75698
|
+
this.unGroup(block);
|
|
75699
|
+
}
|
|
75700
|
+
});
|
|
75701
|
+
return;
|
|
75702
|
+
}
|
|
75703
|
+
if (!group) return;
|
|
75704
|
+
if (!group.querySelector(this.selector)) return;
|
|
75705
|
+
this.applyPixels(group);
|
|
75706
|
+
const rect = this.getRect(group);
|
|
75707
|
+
const top = rect.top;
|
|
75708
|
+
const left = rect.left;
|
|
75709
|
+
const container = group.parentNode;
|
|
75710
|
+
group.querySelectorAll(this.selector).forEach(block => {
|
|
75711
|
+
this.applyPixels(block);
|
|
75712
|
+
let blockTop = parseFloat(block.style.top) || 0;
|
|
75713
|
+
let blockLeft = parseFloat(block.style.left) || 0;
|
|
75714
|
+
|
|
75715
|
+
// Adjust position relative to the group div
|
|
75716
|
+
block.style.top = blockTop + top + 'px';
|
|
75717
|
+
block.style.left = blockLeft + left + 'px';
|
|
75718
|
+
container.appendChild(block);
|
|
75719
|
+
|
|
75720
|
+
// Remove all breakpoints
|
|
75721
|
+
let attributesToRemove = [];
|
|
75722
|
+
const attributes = block.attributes;
|
|
75723
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
75724
|
+
const attributeName = attributes[i].name;
|
|
75725
|
+
if (attributeName.includes('data--y-') || attributeName.includes('data--x-') || attributeName.includes('data--w-') || attributeName.includes('data--h-')) {
|
|
75726
|
+
attributesToRemove.push(attributeName);
|
|
75727
|
+
}
|
|
75728
|
+
}
|
|
75729
|
+
attributesToRemove.forEach(attr => {
|
|
75730
|
+
block.removeAttribute(attr);
|
|
75731
|
+
});
|
|
75732
|
+
// Make/save current inline style as default
|
|
75733
|
+
block.removeAttribute('data-breakpoint');
|
|
75734
|
+
block.setAttribute('data--y', block.style.top);
|
|
75735
|
+
block.setAttribute('data--x', block.style.left);
|
|
75736
|
+
block.setAttribute('data--w', block.style.width);
|
|
75737
|
+
block.setAttribute('data--h', block.style.height);
|
|
75738
|
+
this.applyPercentage(block);
|
|
75739
|
+
});
|
|
75740
|
+
group.parentElement.removeChild(group);
|
|
75741
|
+
}
|
|
75742
|
+
addBreakpoint() {
|
|
75743
|
+
const viewportWidth = this.win.innerWidth;
|
|
75744
|
+
this.doc.body.setAttribute('data-breakpoint', viewportWidth);
|
|
75745
|
+
}
|
|
75746
|
+
|
|
75747
|
+
/*
|
|
75748
|
+
clearBreakpoint(target) {
|
|
75749
|
+
let breakpoint = target.getAttribute('data-breakpoint');
|
|
75750
|
+
if(!breakpoint) return;
|
|
75751
|
+
if(target.hasAttribute('data--y-'+breakpoint)) {
|
|
75752
|
+
target.removeAttribute('data--y-'+breakpoint);
|
|
75753
|
+
let top = target.getAttribute('data--y');
|
|
75754
|
+
if(top) target.style.top = top;
|
|
75755
|
+
}
|
|
75756
|
+
if(target.hasAttribute('data--x-'+breakpoint)) {
|
|
75757
|
+
target.removeAttribute('data--x-'+breakpoint);
|
|
75758
|
+
let left = target.getAttribute('data--x');
|
|
75759
|
+
if(left) target.style.left = left;
|
|
75760
|
+
}
|
|
75761
|
+
if(target.hasAttribute('data--w-'+breakpoint)) {
|
|
75762
|
+
target.removeAttribute('data--w-'+breakpoint);
|
|
75763
|
+
let width = target.getAttribute('data--w');
|
|
75764
|
+
if(width) target.style.width = width;
|
|
75765
|
+
}
|
|
75766
|
+
if(target.hasAttribute('data--h-'+breakpoint)) {
|
|
75767
|
+
target.removeAttribute('data--h-'+breakpoint);
|
|
75768
|
+
let height = target.getAttribute('data--h');
|
|
75769
|
+
if(height) target.style.height = height;
|
|
75770
|
+
}
|
|
75771
|
+
target.removeAttribute('data-breakpoint');
|
|
75772
|
+
// reset
|
|
75773
|
+
let top = target.getAttribute('data--y');
|
|
75774
|
+
if(top)target.style.top = top;
|
|
75775
|
+
let left = target.getAttribute('data--x');
|
|
75776
|
+
if(left) target.style.left = left;
|
|
75777
|
+
let width = target.getAttribute('data--w');
|
|
75778
|
+
if(width) target.style.width = width;
|
|
75779
|
+
let height = target.getAttribute('data--h');
|
|
75780
|
+
if(height) target.style.height = height;
|
|
75781
|
+
}
|
|
75782
|
+
*/
|
|
75783
|
+
|
|
75784
|
+
clearBreakpoint(target) {
|
|
75785
|
+
let attributesToRemove = [];
|
|
75786
|
+
const attributes = target.attributes;
|
|
75787
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
75788
|
+
const attributeName = attributes[i].name;
|
|
75789
|
+
if (attributeName.includes('data--y-') || attributeName.includes('data--x-') || attributeName.includes('data--w-') || attributeName.includes('data--h-') || attributeName.includes('data--transform-') || attributeName.includes('data--matrix-')) {
|
|
75790
|
+
attributesToRemove.push(attributeName);
|
|
75791
|
+
}
|
|
75792
|
+
}
|
|
75793
|
+
attributesToRemove.forEach(attr => {
|
|
75794
|
+
target.removeAttribute(attr);
|
|
75795
|
+
});
|
|
75796
|
+
target.removeAttribute('data-breakpoint');
|
|
75797
|
+
|
|
75798
|
+
// reset
|
|
75799
|
+
let top = target.getAttribute('data--y');
|
|
75800
|
+
if (top) target.style.top = top;
|
|
75801
|
+
let left = target.getAttribute('data--x');
|
|
75802
|
+
if (left) target.style.left = left;
|
|
75803
|
+
let width = target.getAttribute('data--w');
|
|
75804
|
+
if (width) target.style.width = width;
|
|
75805
|
+
let height = target.getAttribute('data--h');
|
|
75806
|
+
if (height) target.style.height = height;
|
|
75807
|
+
}
|
|
75808
|
+
clearAllBreakpoints(container) {
|
|
75809
|
+
// REVIEW (Currently not used)
|
|
75810
|
+
const elements = container.querySelectorAll(this.selector);
|
|
75811
|
+
elements.forEach(target => {
|
|
75812
|
+
let attributesToRemove = [];
|
|
75813
|
+
const attributes = target.attributes;
|
|
75814
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
75815
|
+
const attributeName = attributes[i].name;
|
|
75816
|
+
if (attributeName.includes('data--y-') || attributeName.includes('data--x-') || attributeName.includes('data--w-') || attributeName.includes('data--h-') || attributeName.includes('data--transform-') || attributeName.includes('data--matrix-')) {
|
|
75817
|
+
attributesToRemove.push(attributeName);
|
|
75818
|
+
}
|
|
75819
|
+
}
|
|
75820
|
+
attributesToRemove.forEach(attr => {
|
|
75821
|
+
target.removeAttribute(attr);
|
|
75822
|
+
});
|
|
75823
|
+
});
|
|
75824
|
+
elements.forEach(target => {
|
|
75825
|
+
let y = target.getAttribute('data--y');
|
|
75826
|
+
let x = target.getAttribute('data--x');
|
|
75827
|
+
let w = target.getAttribute('data--w');
|
|
75828
|
+
let h = target.getAttribute('data--h');
|
|
75829
|
+
if (y) target.style.top = y;
|
|
75830
|
+
if (x) target.style.left = x;
|
|
75831
|
+
if (w) target.style.width = w;
|
|
75832
|
+
if (h) target.style.height = h;
|
|
75833
|
+
});
|
|
75834
|
+
}
|
|
75835
|
+
getBreakpoints(target) {
|
|
75836
|
+
let breakpoints = [];
|
|
75837
|
+
const attributes = target.attributes;
|
|
75838
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
75839
|
+
const attributeName = attributes[i].name;
|
|
75840
|
+
if (attributeName.includes('data--y-') || attributeName.includes('data--x-') || attributeName.includes('data--w-') || attributeName.includes('data--h-')) {
|
|
75841
|
+
let val = attributeName.replace('data--y-', '');
|
|
75842
|
+
val = val.replace('data--x-', '');
|
|
75843
|
+
val = val.replace('data--w-', '');
|
|
75844
|
+
val = val.replace('data--h-', '');
|
|
75845
|
+
if (!breakpoints.includes(val)) breakpoints.push(val);
|
|
75846
|
+
}
|
|
75847
|
+
}
|
|
75848
|
+
return breakpoints;
|
|
75849
|
+
}
|
|
75850
|
+
getSelectedBlock() {
|
|
75851
|
+
const blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active') && !elm.classList.contains('cloned'));
|
|
75852
|
+
if (blocks.length === 1) {
|
|
75853
|
+
const block = blocks[0];
|
|
75854
|
+
return block;
|
|
75855
|
+
}
|
|
75856
|
+
return false;
|
|
75857
|
+
}
|
|
75858
|
+
checkOverlap(target) {
|
|
75859
|
+
const targetRect = target.getBoundingClientRect();
|
|
75860
|
+
const blocks = Array.from(target.parentNode.querySelectorAll(this.selector)).filter(elm => !elm.classList.contains('cloned'));
|
|
75861
|
+
let overlappedBlocks = [];
|
|
75862
|
+
for (const block of blocks) {
|
|
75863
|
+
if (block !== target) {
|
|
75864
|
+
const blockRect = block.getBoundingClientRect();
|
|
75865
|
+
if (targetRect.top < blockRect.bottom && targetRect.bottom > blockRect.top && targetRect.left < blockRect.right && targetRect.right > blockRect.left) {
|
|
75866
|
+
overlappedBlocks.push(block);
|
|
75867
|
+
}
|
|
75868
|
+
}
|
|
75869
|
+
}
|
|
75870
|
+
return overlappedBlocks;
|
|
75871
|
+
}
|
|
75872
|
+
}
|
|
75873
|
+
class Matrix3D {
|
|
75874
|
+
adj(m) {
|
|
75875
|
+
return [m[4] * m[8] - m[5] * m[7], m[2] * m[7] - m[1] * m[8], m[1] * m[5] - m[2] * m[4], m[5] * m[6] - m[3] * m[8], m[0] * m[8] - m[2] * m[6], m[2] * m[3] - m[0] * m[5], m[3] * m[7] - m[4] * m[6], m[1] * m[6] - m[0] * m[7], m[0] * m[4] - m[1] * m[3]];
|
|
75876
|
+
}
|
|
75877
|
+
multmm(a, b) {
|
|
75878
|
+
const c = Array(9);
|
|
75879
|
+
for (var i = 0; i != 3; ++i) {
|
|
75880
|
+
for (var j = 0; j != 3; ++j) {
|
|
75881
|
+
var cij = 0;
|
|
75882
|
+
for (var k = 0; k != 3; ++k) {
|
|
75883
|
+
cij += a[3 * i + k] * b[3 * k + j];
|
|
75884
|
+
}
|
|
75885
|
+
c[3 * i + j] = cij;
|
|
75886
|
+
}
|
|
75887
|
+
}
|
|
75888
|
+
return c;
|
|
75889
|
+
}
|
|
75890
|
+
multmv(m, v) {
|
|
75891
|
+
return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]];
|
|
75892
|
+
}
|
|
75893
|
+
pdbg(m, v) {
|
|
75894
|
+
const r = this.multmv(m, v);
|
|
75895
|
+
return r + ' (' + r[0] / r[2] + ', ' + r[1] / r[2] + ')';
|
|
75896
|
+
}
|
|
75897
|
+
basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4) {
|
|
75898
|
+
const m = [x1, x2, x3, y1, y2, y3, 1, 1, 1];
|
|
75899
|
+
const v = this.multmv(this.adj(m), [x4, y4, 1]);
|
|
75900
|
+
return this.multmm(m, [v[0], 0, 0, 0, v[1], 0, 0, 0, v[2]]);
|
|
75901
|
+
}
|
|
75902
|
+
general2DProjection(x1s, y1s, x1d, y1d, x2s, y2s, x2d, y2d, x3s, y3s, x3d, y3d, x4s, y4s, x4d, y4d) {
|
|
75903
|
+
const s = this.basisToPoints(x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s);
|
|
75904
|
+
const d = this.basisToPoints(x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d);
|
|
75905
|
+
return this.multmm(d, this.adj(s));
|
|
75906
|
+
}
|
|
75907
|
+
project(m, x, y) {
|
|
75908
|
+
const v = this.multmv(m, [x, y, 1]);
|
|
75909
|
+
return [v[0] / v[2], v[1] / v[2]];
|
|
75910
|
+
}
|
|
75911
|
+
transform2d(element, x1, y1, x2, y2, x3, y3, x4, y4) {
|
|
75912
|
+
const w = element.offsetWidth,
|
|
75913
|
+
h = element.offsetHeight;
|
|
75914
|
+
let t = this.general2DProjection(0, 0, x1, y1, w, 0, x2, y2, 0, h, x3, y3, w, h, x4, y4);
|
|
75915
|
+
for (let i = 0; i != 9; ++i) t[i] = t[i] / t[8];
|
|
75916
|
+
t = [t[0], t[3], 0, t[6], t[1], t[4], 0, t[7], 0, 0, 1, 0, t[2], t[5], 0, t[8]];
|
|
75917
|
+
t = 'matrix3d(' + t.join(', ') + ')';
|
|
75918
|
+
return t;
|
|
75919
|
+
}
|
|
75920
|
+
}
|
|
75921
|
+
class Ruler {
|
|
75922
|
+
constructor(options) {
|
|
75923
|
+
this.selector = options && options.selector || '.is-block';
|
|
75924
|
+
this.doc = options && options.doc || document;
|
|
75925
|
+
this.win = options && options.win || window;
|
|
75926
|
+
const rulerHTML = `
|
|
75927
|
+
<div class="ruler horizontal-ruler" id="horizontal-ruler-top"></div>
|
|
75928
|
+
<div class="ruler horizontal-ruler" id="horizontal-ruler-bottom"></div>
|
|
75929
|
+
<div class="ruler horizontal-ruler" id="horizontal-ruler-middle"></div>
|
|
75930
|
+
<div class="ruler vertical-ruler" id="vertical-ruler-left"></div>
|
|
75931
|
+
<div class="ruler vertical-ruler" id="vertical-ruler-right"></div>
|
|
75932
|
+
<div class="ruler vertical-ruler" id="vertical-ruler-center"></div>
|
|
75933
|
+
`;
|
|
75934
|
+
if (!this.doc.getElementById('horizontal-ruler-top')) this.doc.body.insertAdjacentHTML('beforeend', rulerHTML);
|
|
75935
|
+
this.horizontalRulerTop = this.doc.getElementById('horizontal-ruler-top');
|
|
75936
|
+
this.horizontalRulerBottom = this.doc.getElementById('horizontal-ruler-bottom');
|
|
75937
|
+
this.horizontalRulerMiddle = this.doc.getElementById('horizontal-ruler-middle');
|
|
75938
|
+
this.verticalRulerLeft = this.doc.getElementById('vertical-ruler-left');
|
|
75939
|
+
this.verticalRulerRight = this.doc.getElementById('vertical-ruler-right');
|
|
75940
|
+
this.verticalRulerCenter = this.doc.getElementById('vertical-ruler-center');
|
|
75941
|
+
this.setup();
|
|
75942
|
+
}
|
|
75943
|
+
setup() {
|
|
75944
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
75945
|
+
}
|
|
75946
|
+
refresh() {
|
|
75947
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
75948
|
+
}
|
|
75949
|
+
destroy() {
|
|
75950
|
+
[this.horizontalRulerTop, this.horizontalRulerBottom, this.verticalRulerLeft, this.verticalRulerRight].forEach(elm => {
|
|
75951
|
+
if (elm.parentNode) elm.parentNode.removeChild(elm);
|
|
75952
|
+
});
|
|
75953
|
+
}
|
|
75954
|
+
hideRulers() {
|
|
75955
|
+
this.horizontalRulerTop.style.top = '-1000px';
|
|
75956
|
+
this.horizontalRulerBottom.style.top = '-1000px';
|
|
75957
|
+
this.horizontalRulerMiddle.style.top = '-1000px';
|
|
75958
|
+
this.verticalRulerLeft.style.left = '-1000px';
|
|
75959
|
+
this.verticalRulerRight.style.left = '-1000px';
|
|
75960
|
+
this.verticalRulerCenter.style.left = '-1000px';
|
|
75961
|
+
this.rulerTop = null;
|
|
75962
|
+
this.rulerLeft = null;
|
|
75963
|
+
this.rulerRight = null;
|
|
75964
|
+
}
|
|
75965
|
+
updateRulers(block) {
|
|
75966
|
+
// if(block.querySelector(this.selector)) return; // group (because updateRules also calls parent group if child block is dragged)
|
|
75967
|
+
|
|
75968
|
+
let transform = block.style.transform;
|
|
75969
|
+
if (transform.includes('rotate') || transform.includes('matrix3d')) return;
|
|
75970
|
+
let parentTransform = block.parentNode.style.transform;
|
|
75971
|
+
if (parentTransform.includes('rotate')) return;
|
|
75972
|
+
this.hideRulers();
|
|
75973
|
+
const rect = block.getBoundingClientRect();
|
|
75974
|
+
const top = rect.top;
|
|
75975
|
+
const bottom = top + block.offsetHeight;
|
|
75976
|
+
const left = rect.left;
|
|
75977
|
+
const right = left + block.offsetWidth;
|
|
75978
|
+
const center = left + block.offsetWidth / 2;
|
|
75979
|
+
const middle = top + block.offsetHeight / 2;
|
|
75980
|
+
this.rulerTop = null;
|
|
75981
|
+
this.rulerLeft = null;
|
|
75982
|
+
this.rulerRight = null;
|
|
75983
|
+
let containerTop = 0;
|
|
75984
|
+
const container = block.parentNode;
|
|
75985
|
+
if (container) {
|
|
75986
|
+
this.elements = container.querySelectorAll(this.selector);
|
|
75987
|
+
containerTop = this.win.scrollY;
|
|
75988
|
+
}
|
|
75989
|
+
this.elements.forEach(element => {
|
|
75990
|
+
if (!this.doc.body.contains(element)) return; // in case element removed (eg. unGroup, block deleted)
|
|
75991
|
+
|
|
75992
|
+
if (block.contains(element)) return; // In case of group moving
|
|
75993
|
+
|
|
75994
|
+
let transform = element.style.transform;
|
|
75995
|
+
let parentTransform = element.parentNode.style.transform;
|
|
75996
|
+
if (!transform.includes('rotate') && !parentTransform.includes('rotate') && !transform.includes('matrix3d') && !parentTransform.includes('matrix3d') && element !== block && !element.classList.contains('cloned')) {
|
|
75997
|
+
const rect = element.getBoundingClientRect();
|
|
75998
|
+
const otherTop = rect.top;
|
|
75999
|
+
const otherBottom = rect.top + element.offsetHeight;
|
|
76000
|
+
const otherLeft = rect.left;
|
|
76001
|
+
const otherRight = rect.left + element.offsetWidth;
|
|
76002
|
+
const otherMiddle = rect.top + element.offsetHeight / 2;
|
|
76003
|
+
const otherCenter = rect.left + element.offsetWidth / 2;
|
|
76004
|
+
if (otherMiddle - 4 <= middle && middle <= otherMiddle + 4) {
|
|
76005
|
+
this.horizontalRulerMiddle.style.top = containerTop + otherTop + (element.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
|
|
76006
|
+
let val = otherTop + (element.offsetHeight - block.offsetHeight) / 2;
|
|
76007
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76008
|
+
}
|
|
76009
|
+
if (otherCenter - 4 <= center && center <= otherCenter + 4) {
|
|
76010
|
+
this.verticalRulerCenter.style.left = otherLeft + (element.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
|
|
76011
|
+
this.verticalRulerCenter.style.top = containerTop + 'px'; // adj
|
|
76012
|
+
|
|
76013
|
+
let val = otherLeft + (element.offsetWidth - block.offsetWidth) / 2;
|
|
76014
|
+
if (this.rulerLeft === null) this.rulerLeft = val;
|
|
76015
|
+
}
|
|
76016
|
+
|
|
76017
|
+
// block top
|
|
76018
|
+
if (otherTop - 4 <= top && top <= otherTop + 4) {
|
|
76019
|
+
this.horizontalRulerTop.style.top = containerTop + otherTop + 'px';
|
|
76020
|
+
let val = otherTop;
|
|
76021
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76022
|
+
}
|
|
76023
|
+
if (otherBottom - 4 <= top && top <= otherBottom + 4) {
|
|
76024
|
+
this.horizontalRulerTop.style.top = containerTop + otherBottom + 'px';
|
|
76025
|
+
let val = otherBottom;
|
|
76026
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76027
|
+
}
|
|
76028
|
+
|
|
76029
|
+
// block bottom
|
|
76030
|
+
if (otherTop - 4 <= bottom && bottom <= otherTop + 4) {
|
|
76031
|
+
this.horizontalRulerBottom.style.top = containerTop + otherTop + 'px';
|
|
76032
|
+
let val = otherTop - block.offsetHeight;
|
|
76033
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76034
|
+
}
|
|
76035
|
+
if (otherBottom - 4 <= bottom && bottom <= otherBottom + 4) {
|
|
76036
|
+
this.horizontalRulerBottom.style.top = containerTop + otherBottom + 'px';
|
|
76037
|
+
let val = otherBottom - block.offsetHeight;
|
|
76038
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76039
|
+
}
|
|
76040
|
+
|
|
76041
|
+
// block left
|
|
76042
|
+
if (otherLeft - 4 <= left && left <= otherLeft + 4) {
|
|
76043
|
+
this.verticalRulerLeft.style.left = otherLeft + 'px';
|
|
76044
|
+
this.verticalRulerLeft.style.top = containerTop + 'px'; // adj
|
|
76045
|
+
|
|
76046
|
+
let val = otherLeft;
|
|
76047
|
+
if (this.rulerLeft === null) this.rulerLeft = val;
|
|
76048
|
+
}
|
|
76049
|
+
if (otherRight - 4 <= left && left <= otherRight + 4) {
|
|
76050
|
+
this.verticalRulerLeft.style.left = otherRight + 'px';
|
|
76051
|
+
this.verticalRulerLeft.style.top = containerTop + 'px'; // adj
|
|
76052
|
+
|
|
76053
|
+
let val = otherRight;
|
|
76054
|
+
if (this.rulerLeft === null) this.rulerLeft = val;
|
|
76055
|
+
}
|
|
76056
|
+
|
|
76057
|
+
// block right
|
|
76058
|
+
if (otherLeft - 4 <= right && right <= otherLeft + 4) {
|
|
76059
|
+
this.verticalRulerRight.style.left = otherLeft + 'px';
|
|
76060
|
+
this.verticalRulerRight.style.top = containerTop + 'px'; // adj
|
|
76061
|
+
|
|
76062
|
+
let val = otherLeft;
|
|
76063
|
+
if (this.rulerRight === null) this.rulerRight = val;
|
|
76064
|
+
}
|
|
76065
|
+
if (otherRight - 4 <= right && right <= otherRight + 4) {
|
|
76066
|
+
this.verticalRulerRight.style.left = otherRight + 'px';
|
|
76067
|
+
this.verticalRulerRight.style.top = containerTop + 'px'; // adj
|
|
76068
|
+
|
|
76069
|
+
let val = otherRight;
|
|
76070
|
+
if (this.rulerRight === null) this.rulerRight = val;
|
|
76071
|
+
}
|
|
76072
|
+
}
|
|
76073
|
+
});
|
|
76074
|
+
|
|
76075
|
+
// Edges
|
|
76076
|
+
const conRect = block.parentNode.getBoundingClientRect();
|
|
76077
|
+
const conTop = conRect.top;
|
|
76078
|
+
const conBottom = conRect.top + block.parentNode.offsetHeight;
|
|
76079
|
+
const conLeft = conRect.left;
|
|
76080
|
+
const conRight = conRect.left + block.parentNode.offsetWidth;
|
|
76081
|
+
const conCenter = conRect.left + block.parentNode.offsetWidth / 2;
|
|
76082
|
+
const conMiddle = conRect.top + block.parentNode.offsetHeight / 2;
|
|
76083
|
+
if (conMiddle - 4 <= middle && middle <= conMiddle + 4) {
|
|
76084
|
+
this.horizontalRulerMiddle.style.top = containerTop + conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
|
|
76085
|
+
let val = conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2;
|
|
76086
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76087
|
+
}
|
|
76088
|
+
if (conCenter - 4 <= center && center <= conCenter + 4) {
|
|
76089
|
+
this.verticalRulerCenter.style.left = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
|
|
76090
|
+
this.verticalRulerCenter.style.top = containerTop + 'px';
|
|
76091
|
+
let val = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2;
|
|
76092
|
+
if (this.rulerLeft === null) this.rulerLeft = val;
|
|
76093
|
+
}
|
|
76094
|
+
|
|
76095
|
+
// block top
|
|
76096
|
+
if (conTop - 4 <= top && top <= conTop + 4) {
|
|
76097
|
+
this.horizontalRulerTop.style.top = containerTop + conTop + 'px';
|
|
76098
|
+
let val = conTop;
|
|
76099
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76100
|
+
}
|
|
76101
|
+
// block bottom
|
|
76102
|
+
if (conBottom - 4 <= bottom && bottom <= conBottom + 4) {
|
|
76103
|
+
this.horizontalRulerBottom.style.top = containerTop + conBottom - 3 + 'px'; // -3 is an adjustment to make the line visible
|
|
76104
|
+
|
|
76105
|
+
let val = conBottom - block.offsetHeight;
|
|
76106
|
+
if (this.rulerTop === null) this.rulerTop = val;
|
|
76107
|
+
}
|
|
76108
|
+
// block left
|
|
76109
|
+
if (conLeft - 4 <= left && left <= conLeft + 4) {
|
|
76110
|
+
this.verticalRulerLeft.style.left = conLeft + 2 + 'px'; // +3 is an adjustment
|
|
76111
|
+
this.verticalRulerLeft.style.top = containerTop + 'px';
|
|
76112
|
+
let val = conLeft;
|
|
76113
|
+
if (this.rulerLeft === null) this.rulerLeft = val;
|
|
76114
|
+
}
|
|
76115
|
+
// block right
|
|
76116
|
+
if (conRight - 4 <= right && right <= conRight + 4) {
|
|
76117
|
+
this.verticalRulerRight.style.left = conRight - 2 + 'px'; // -2 is an adjustment
|
|
76118
|
+
this.verticalRulerRight.style.top = containerTop + 'px';
|
|
76119
|
+
let val = conRight;
|
|
76120
|
+
if (this.rulerRight === null) this.rulerRight = val;
|
|
76121
|
+
}
|
|
76122
|
+
}
|
|
76123
|
+
}
|
|
76124
|
+
class Rotatable {
|
|
76125
|
+
constructor(options) {
|
|
76126
|
+
this.selector = options && options.selector || '.is-block';
|
|
76127
|
+
this.doc = options && options.doc || document;
|
|
76128
|
+
this.win = options && options.win || window;
|
|
76129
|
+
this.onBeforeChange = options && options.onBeforeChange || null;
|
|
76130
|
+
this.onChange = options && options.onChange || null;
|
|
76131
|
+
this.disableOnMobile = options && options.disableOnMobile || 0;
|
|
76132
|
+
this.centerX = 0;
|
|
76133
|
+
this.centerY = 0;
|
|
76134
|
+
this.initialRotation = 0;
|
|
76135
|
+
this.handleRotateStart = this.handleRotateStart.bind(this);
|
|
76136
|
+
this.handleDblClick = this.handleDblClick.bind(this);
|
|
76137
|
+
this.handleRotateMove = this.handleRotateMove.bind(this);
|
|
76138
|
+
this.handleRotateEnd = this.handleRotateEnd.bind(this);
|
|
76139
|
+
this.setup();
|
|
76140
|
+
this.common = new Common({
|
|
76141
|
+
selector: this.selector
|
|
76142
|
+
});
|
|
76143
|
+
}
|
|
76144
|
+
setup() {
|
|
76145
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76146
|
+
this.elements.forEach(element => {
|
|
76147
|
+
element.querySelectorAll('.rotate-handle').forEach(elm => elm.parentNode.removeChild(elm));
|
|
76148
|
+
const handleHTML = '<div class="rotate-handle" contentEditable="false"><div></div></div>';
|
|
76149
|
+
element.insertAdjacentHTML('afterbegin', handleHTML);
|
|
76150
|
+
const handles = Array.from(element.querySelectorAll('.rotate-handle')).filter(handle => handle.parentElement === element);
|
|
76151
|
+
handles.forEach(handle => {
|
|
76152
|
+
handle.addEventListener('mousedown', this.handleRotateStart);
|
|
76153
|
+
handle.addEventListener('touchstart', this.handleRotateStart, {
|
|
76154
|
+
passive: false
|
|
76155
|
+
});
|
|
76156
|
+
handle.addEventListener('dblclick', this.handleDblClick);
|
|
76157
|
+
});
|
|
76158
|
+
});
|
|
76159
|
+
}
|
|
76160
|
+
refresh() {
|
|
76161
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76162
|
+
this.elements.forEach(element => {
|
|
76163
|
+
let handles = Array.from(element.querySelectorAll('.rotate-handle')).filter(handle => handle.parentElement === element); // only one handle
|
|
76164
|
+
handles.forEach(handle => {
|
|
76165
|
+
handle.removeEventListener('mousedown', this.handleRotateStart);
|
|
76166
|
+
handle.removeEventListener('touchstart', this.handleRotateStart);
|
|
76167
|
+
handle.removeEventListener('dblclick', this.handleDblClick);
|
|
76168
|
+
handle.parentNode.removeChild(handle);
|
|
76169
|
+
});
|
|
76170
|
+
const handleHTML = '<div class="rotate-handle" contentEditable="false"><div></div></div>';
|
|
76171
|
+
element.insertAdjacentHTML('afterbegin', handleHTML);
|
|
76172
|
+
handles = Array.from(element.querySelectorAll('.rotate-handle')).filter(handle => handle.parentElement === element); // only one handle
|
|
76173
|
+
handles.forEach(handle => {
|
|
76174
|
+
handle.addEventListener('mousedown', this.handleRotateStart);
|
|
76175
|
+
handle.addEventListener('touchstart', this.handleRotateStart, {
|
|
76176
|
+
passive: false
|
|
76177
|
+
});
|
|
76178
|
+
handle.addEventListener('dblclick', this.handleDblClick);
|
|
76179
|
+
});
|
|
76180
|
+
});
|
|
76181
|
+
}
|
|
76182
|
+
destroy(block) {
|
|
76183
|
+
if (block) {
|
|
76184
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76185
|
+
this.elements.forEach(element => {
|
|
76186
|
+
if (element === block) {
|
|
76187
|
+
const handles = Array.from(element.querySelectorAll('.rotate-handle')).filter(handle => handle.parentElement === element);
|
|
76188
|
+
handles.forEach(handle => {
|
|
76189
|
+
handle.removeEventListener('mousedown', this.handleRotateStart);
|
|
76190
|
+
handle.removeEventListener('touchstart', this.handleRotateStart);
|
|
76191
|
+
handle.removeEventListener('dblclick', this.handleDblClick);
|
|
76192
|
+
handle.parentNode.removeChild(handle);
|
|
76193
|
+
});
|
|
76194
|
+
}
|
|
76195
|
+
});
|
|
76196
|
+
} else {
|
|
76197
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76198
|
+
this.elements.forEach(element => {
|
|
76199
|
+
const handles = Array.from(element.querySelectorAll('.rotate-handle')).filter(handle => handle.parentElement === element);
|
|
76200
|
+
handles.forEach(handle => {
|
|
76201
|
+
handle.removeEventListener('mousedown', this.handleRotateStart);
|
|
76202
|
+
handle.removeEventListener('touchstart', this.handleRotateStart);
|
|
76203
|
+
handle.removeEventListener('dblclick', this.handleDblClick);
|
|
76204
|
+
handle.parentNode.removeChild(handle);
|
|
76205
|
+
});
|
|
76206
|
+
});
|
|
76207
|
+
}
|
|
76208
|
+
}
|
|
76209
|
+
handleDblClick(event) {
|
|
76210
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
76211
|
+
event.preventDefault();
|
|
76212
|
+
event.stopImmediatePropagation();
|
|
76213
|
+
const block = event.target.parentNode;
|
|
76214
|
+
const transform = block.style.transform;
|
|
76215
|
+
if (transform.includes('rotate')) block.style.transform = '';
|
|
76216
|
+
this.clonedTarget = this.doc.querySelector(this.selector + '.cloned');
|
|
76217
|
+
if (this.clonedTarget) this.clonedTarget.style.transform = '';
|
|
76218
|
+
if (this.onChange) this.onChange();
|
|
76219
|
+
}
|
|
76220
|
+
handleRotateStart(event) {
|
|
76221
|
+
const viewportWidth = this.win.innerWidth;
|
|
76222
|
+
if (viewportWidth <= this.disableOnMobile) return;
|
|
76223
|
+
if (event.type === 'touchstart' && event.touches.length !== 1) {
|
|
76224
|
+
return; // Do nothing if more than one touch point is detected
|
|
76225
|
+
}
|
|
76226
|
+
|
|
76227
|
+
if (event.type === 'mousedown' && event.button !== 0) {
|
|
76228
|
+
return; // Do nothing if the right mouse button is clicked
|
|
76229
|
+
}
|
|
76230
|
+
|
|
76231
|
+
event.preventDefault();
|
|
76232
|
+
this.target = event.target.parentNode; // block
|
|
76233
|
+
|
|
76234
|
+
this.clonedTarget = this.doc.querySelector(this.selector + '.cloned');
|
|
76235
|
+
this.dragStartTimeout = setTimeout(() => {
|
|
76236
|
+
// Set a timeout before starting the drag (to differentiate from click)
|
|
76237
|
+
|
|
76238
|
+
if (event.type === 'mousedown') {
|
|
76239
|
+
this.startRotation(event.clientX, event.clientY);
|
|
76240
|
+
} else if (event.type === 'touchstart') {
|
|
76241
|
+
const touch = event.touches[0];
|
|
76242
|
+
this.startRotation(touch.clientX, touch.clientY);
|
|
76243
|
+
}
|
|
76244
|
+
this.doc.addEventListener('mousemove', this.handleRotateMove);
|
|
76245
|
+
this.doc.addEventListener('touchmove', this.handleRotateMove);
|
|
76246
|
+
}, 120);
|
|
76247
|
+
this.doc.addEventListener('mouseup', this.handleRotateEnd);
|
|
76248
|
+
this.doc.addEventListener('touchend', this.handleRotateEnd);
|
|
76249
|
+
}
|
|
76250
|
+
handleRotateMove() {
|
|
76251
|
+
let clientX, clientY;
|
|
76252
|
+
if (event.type === 'mousemove') {
|
|
76253
|
+
clientX = event.clientX;
|
|
76254
|
+
clientY = event.clientY;
|
|
76255
|
+
} else if (event.type === 'touchmove') {
|
|
76256
|
+
const touch = event.touches[0];
|
|
76257
|
+
clientX = touch.clientX;
|
|
76258
|
+
clientY = touch.clientY;
|
|
76259
|
+
}
|
|
76260
|
+
this.updateRotation(clientX, clientY);
|
|
76261
|
+
}
|
|
76262
|
+
handleRotateEnd() {
|
|
76263
|
+
clearTimeout(this.dragStartTimeout);
|
|
76264
|
+
this.doc.removeEventListener('mousemove', this.handleRotateMove);
|
|
76265
|
+
this.doc.removeEventListener('touchmove', this.handleRotateMove);
|
|
76266
|
+
this.doc.removeEventListener('mouseup', this.handleRotateEnd);
|
|
76267
|
+
this.doc.removeEventListener('touchend', this.handleRotateEnd);
|
|
76268
|
+
if (this.onChange) this.onChange();
|
|
76269
|
+
}
|
|
76270
|
+
getCurrentRotation(transform) {
|
|
76271
|
+
const match = transform.match(/rotate\(([-+]?\d*\.?\d*)deg\)/);
|
|
76272
|
+
return match ? parseFloat(match[1]) : 0;
|
|
76273
|
+
}
|
|
76274
|
+
startRotation() {
|
|
76275
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
76276
|
+
const target = this.target;
|
|
76277
|
+
const rect = target.getBoundingClientRect();
|
|
76278
|
+
this.centerX = rect.left + rect.width / 2;
|
|
76279
|
+
this.centerY = rect.top + rect.height / 2;
|
|
76280
|
+
|
|
76281
|
+
// Store the initial rotation
|
|
76282
|
+
if (target.parentNode.matches(this.selector)) {
|
|
76283
|
+
const currentTransform = target.style.transform;
|
|
76284
|
+
let currentRotation = this.getCurrentRotation(currentTransform);
|
|
76285
|
+
this.initialRotation = currentRotation;
|
|
76286
|
+
const parentTransform = target.parentNode.style.transform;
|
|
76287
|
+
let parentRotation = this.getCurrentRotation(parentTransform);
|
|
76288
|
+
if (parentRotation) {
|
|
76289
|
+
this.initialRotation = parentRotation;
|
|
76290
|
+
}
|
|
76291
|
+
} else {
|
|
76292
|
+
this.initialRotation = 0; // If no child blocks
|
|
76293
|
+
}
|
|
76294
|
+
}
|
|
76295
|
+
|
|
76296
|
+
updateRotation(x, y) {
|
|
76297
|
+
const target = this.target;
|
|
76298
|
+
const angle = Math.atan2(y - this.centerY, x - this.centerX);
|
|
76299
|
+
const degrees = angle * (180 / Math.PI);
|
|
76300
|
+
const initialRotation = this.initialRotation || 0;
|
|
76301
|
+
target.style.transform = `rotate(${degrees - initialRotation}deg)`;
|
|
76302
|
+
if (this.clonedTarget) this.clonedTarget.style.transform = `rotate(${degrees - initialRotation}deg)`;
|
|
76303
|
+
}
|
|
76304
|
+
}
|
|
76305
|
+
class Resizable {
|
|
76306
|
+
constructor(options) {
|
|
76307
|
+
this.selector = options && options.selector || '.is-block';
|
|
76308
|
+
this.doc = options && options.doc || document;
|
|
76309
|
+
this.win = options && options.win || window;
|
|
76310
|
+
this.onBeforeChange = options && options.onBeforeChange || null;
|
|
76311
|
+
this.onChange = options && options.onChange || null;
|
|
76312
|
+
this.disableOnMobile = options && options.disableOnMobile || 0;
|
|
76313
|
+
this.isResizing = false;
|
|
76314
|
+
this.resizeHandle = null;
|
|
76315
|
+
this.startX = 0;
|
|
76316
|
+
this.startY = 0;
|
|
76317
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76318
|
+
this.startResizing = this.startResizing.bind(this);
|
|
76319
|
+
this.handleResizeMove = this.handleResizeMove.bind(this);
|
|
76320
|
+
this.handleResizeEnd = this.handleResizeEnd.bind(this);
|
|
76321
|
+
this.setup();
|
|
76322
|
+
this.ruler = new Ruler({
|
|
76323
|
+
selector: this.selector,
|
|
76324
|
+
doc: this.doc,
|
|
76325
|
+
win: this.win
|
|
76326
|
+
});
|
|
76327
|
+
this.common = new Common({
|
|
76328
|
+
selector: this.selector,
|
|
76329
|
+
doc: this.doc,
|
|
76330
|
+
win: this.win
|
|
76331
|
+
});
|
|
76332
|
+
}
|
|
76333
|
+
setup() {
|
|
76334
|
+
this.elements.forEach(element => {
|
|
76335
|
+
element.querySelectorAll('.handle').forEach(elm => elm.parentNode.removeChild(elm));
|
|
76336
|
+
const handleHTML = `
|
|
76337
|
+
<div class="handle top-left"></div>
|
|
76338
|
+
<div class="handle top-right"></div>
|
|
76339
|
+
<div class="handle bottom-left"></div>
|
|
76340
|
+
<div class="handle bottom-right"></div>
|
|
76341
|
+
|
|
76342
|
+
<div class="handle top"></div>
|
|
76343
|
+
<div class="handle bottom"></div>
|
|
76344
|
+
<div class="handle left"></div>
|
|
76345
|
+
<div class="handle right"></div>`;
|
|
76346
|
+
element.insertAdjacentHTML('afterbegin', handleHTML);
|
|
76347
|
+
const handles = Array.from(element.querySelectorAll('.handle')).filter(handle => handle.parentElement === element);
|
|
76348
|
+
handles.forEach(handle => {
|
|
76349
|
+
handle.addEventListener('mousedown', this.startResizing);
|
|
76350
|
+
handle.addEventListener('touchstart', this.startResizing, {
|
|
76351
|
+
passive: false
|
|
76352
|
+
});
|
|
76353
|
+
});
|
|
76354
|
+
});
|
|
76355
|
+
}
|
|
76356
|
+
refresh() {
|
|
76357
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76358
|
+
this.elements.forEach(element => {
|
|
76359
|
+
let handles = Array.from(element.querySelectorAll('.handle')).filter(handle => handle.parentElement === element);
|
|
76360
|
+
handles.forEach(handle => {
|
|
76361
|
+
handle.removeEventListener('mousedown', this.startResizing);
|
|
76362
|
+
handle.removeEventListener('touchstart', this.startResizing);
|
|
76363
|
+
handle.parentNode.removeChild(handle);
|
|
76364
|
+
});
|
|
76365
|
+
const handleHTML = `
|
|
76366
|
+
<div class="handle top-left"></div>
|
|
76367
|
+
<div class="handle top-right"></div>
|
|
76368
|
+
<div class="handle bottom-left"></div>
|
|
76369
|
+
<div class="handle bottom-right"></div>
|
|
76370
|
+
|
|
76371
|
+
<div class="handle top"></div>
|
|
76372
|
+
<div class="handle bottom"></div>
|
|
76373
|
+
<div class="handle left"></div>
|
|
76374
|
+
<div class="handle right"></div>`;
|
|
76375
|
+
element.insertAdjacentHTML('afterbegin', handleHTML);
|
|
76376
|
+
handles = Array.from(element.querySelectorAll('.handle')).filter(handle => handle.parentElement === element);
|
|
76377
|
+
handles.forEach(handle => {
|
|
76378
|
+
handle.addEventListener('mousedown', this.startResizing);
|
|
76379
|
+
handle.addEventListener('touchstart', this.startResizing, {
|
|
76380
|
+
passive: false
|
|
76381
|
+
});
|
|
76382
|
+
});
|
|
76383
|
+
});
|
|
76384
|
+
this.ruler.refresh();
|
|
76385
|
+
}
|
|
76386
|
+
destroy(block) {
|
|
76387
|
+
if (block) {
|
|
76388
|
+
const handles = Array.from(block.querySelectorAll('.handle')).filter(handle => handle.parentElement === block);
|
|
76389
|
+
handles.forEach(handle => {
|
|
76390
|
+
handle.removeEventListener('mousedown', this.startResizing);
|
|
76391
|
+
handle.removeEventListener('touchstart', this.startResizing);
|
|
76392
|
+
handle.parentNode.removeChild(handle);
|
|
76393
|
+
});
|
|
76394
|
+
} else {
|
|
76395
|
+
const handles = this.doc.querySelectorAll('.handle');
|
|
76396
|
+
handles.forEach(handle => {
|
|
76397
|
+
handle.removeEventListener('mousedown', this.startResizing);
|
|
76398
|
+
handle.removeEventListener('touchstart', this.startResizing);
|
|
76399
|
+
handle.parentNode.removeChild(handle);
|
|
76400
|
+
});
|
|
76401
|
+
this.ruler.destroy();
|
|
76402
|
+
}
|
|
76403
|
+
}
|
|
76404
|
+
startResizing(event) {
|
|
76405
|
+
const viewportWidth = this.win.innerWidth;
|
|
76406
|
+
if (viewportWidth <= this.disableOnMobile) return;
|
|
76407
|
+
if (event.type === 'touchstart' && event.touches.length !== 1) {
|
|
76408
|
+
return; // Do nothing if more than one touch point is detected
|
|
76409
|
+
}
|
|
76410
|
+
|
|
76411
|
+
if (event.type === 'mousedown' && event.button !== 0) {
|
|
76412
|
+
return; // Do nothing if the right mouse button is clicked
|
|
76413
|
+
}
|
|
76414
|
+
|
|
76415
|
+
this.target = event.target.parentNode; // block
|
|
76416
|
+
|
|
76417
|
+
this.clonedTarget = this.doc.querySelector(this.selector + '.cloned');
|
|
76418
|
+
event.preventDefault();
|
|
76419
|
+
event.stopPropagation();
|
|
76420
|
+
this.dragStartTimeout = setTimeout(() => {
|
|
76421
|
+
// Set a timeout before starting the drag (to differentiate from click)
|
|
76422
|
+
|
|
76423
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
76424
|
+
const handle = event.target.closest('.handle');
|
|
76425
|
+
this.isResizing = true;
|
|
76426
|
+
this.resizeHandle = handle.classList[1];
|
|
76427
|
+
if (event.type === 'mousedown') {
|
|
76428
|
+
this.startX = event.clientX;
|
|
76429
|
+
this.startY = event.clientY;
|
|
76430
|
+
} else if (event.type === 'touchstart') {
|
|
76431
|
+
const touch = event.touches[0];
|
|
76432
|
+
this.startX = touch.clientX;
|
|
76433
|
+
this.startY = touch.clientY;
|
|
76434
|
+
}
|
|
76435
|
+
|
|
76436
|
+
//Initial
|
|
76437
|
+
this.initialWidth = parseFloat(getComputedStyle(this.target).width);
|
|
76438
|
+
this.initialHeight = parseFloat(getComputedStyle(this.target).height);
|
|
76439
|
+
const containerRect = this.common.getRect(this.target.parentNode);
|
|
76440
|
+
const rect = this.common.getRect(this.target);
|
|
76441
|
+
this.initialLeft = rect.left - containerRect.left;
|
|
76442
|
+
this.initialTop = rect.top - containerRect.top;
|
|
76443
|
+
this.common.applyPixels(this.target);
|
|
76444
|
+
}, 120);
|
|
76445
|
+
this.doc.addEventListener('mousemove', this.handleResizeMove);
|
|
76446
|
+
this.doc.addEventListener('mouseup', this.handleResizeEnd);
|
|
76447
|
+
this.doc.addEventListener('touchmove', this.handleResizeMove);
|
|
76448
|
+
this.doc.addEventListener('touchend', this.handleResizeEnd);
|
|
76449
|
+
}
|
|
76450
|
+
handleResizeMove(event) {
|
|
76451
|
+
if (this.isResizing) {
|
|
76452
|
+
let deltaX, deltaY;
|
|
76453
|
+
if (event.type === 'mousemove') {
|
|
76454
|
+
deltaX = event.clientX - this.startX;
|
|
76455
|
+
deltaY = event.clientY - this.startY;
|
|
76456
|
+
} else if (event.type === 'touchmove') {
|
|
76457
|
+
const touch = event.touches[0];
|
|
76458
|
+
deltaX = touch.clientX - this.startX;
|
|
76459
|
+
deltaY = touch.clientY - this.startY;
|
|
76460
|
+
}
|
|
76461
|
+
this.target.style.minWidth = ''; // to ensure no resize limit
|
|
76462
|
+
if (this.clonedTarget) this.clonedTarget.style.minWidth = '';
|
|
76463
|
+
switch (this.resizeHandle) {
|
|
76464
|
+
case 'top-left':
|
|
76465
|
+
this.resizeTopLeft(deltaX, deltaY);
|
|
76466
|
+
break;
|
|
76467
|
+
case 'top-right':
|
|
76468
|
+
this.resizeTopRight(deltaX, deltaY);
|
|
76469
|
+
break;
|
|
76470
|
+
case 'bottom-left':
|
|
76471
|
+
this.resizeBottomLeft(deltaX, deltaY);
|
|
76472
|
+
break;
|
|
76473
|
+
case 'bottom-right':
|
|
76474
|
+
this.resizeBottomRight(deltaX, deltaY);
|
|
76475
|
+
break;
|
|
76476
|
+
case 'top':
|
|
76477
|
+
this.resizeTop(deltaY);
|
|
76478
|
+
break;
|
|
76479
|
+
case 'left':
|
|
76480
|
+
this.resizeLeft(deltaX);
|
|
76481
|
+
break;
|
|
76482
|
+
case 'bottom':
|
|
76483
|
+
this.resizeBottom(deltaY);
|
|
76484
|
+
break;
|
|
76485
|
+
case 'right':
|
|
76486
|
+
this.resizeRight(deltaX);
|
|
76487
|
+
break;
|
|
76488
|
+
}
|
|
76489
|
+
this.ruler.updateRulers(this.target);
|
|
76490
|
+
}
|
|
76491
|
+
}
|
|
76492
|
+
handleResizeEnd() {
|
|
76493
|
+
clearTimeout(this.dragStartTimeout);
|
|
76494
|
+
this.stopResizing();
|
|
76495
|
+
this.doc.removeEventListener('mousemove', this.handleResizeMove);
|
|
76496
|
+
this.doc.removeEventListener('mouseup', this.handleResizeEnd);
|
|
76497
|
+
this.doc.removeEventListener('touchmove', this.handleResizeMove);
|
|
76498
|
+
this.doc.removeEventListener('touchend', this.handleResizeEnd);
|
|
76499
|
+
this.ruler.hideRulers();
|
|
76500
|
+
}
|
|
76501
|
+
resizeTopLeft(deltaX, deltaY) {
|
|
76502
|
+
this.target.style.left = this.initialLeft + deltaX + 'px';
|
|
76503
|
+
this.target.style.top = this.initialTop + deltaY + 'px';
|
|
76504
|
+
this.target.style.width = this.initialWidth - deltaX + 'px';
|
|
76505
|
+
this.target.style.height = this.initialHeight - deltaY + 'px';
|
|
76506
|
+
if (this.clonedTarget) {
|
|
76507
|
+
this.clonedTarget.style.left = this.initialLeft + deltaX + 'px';
|
|
76508
|
+
this.clonedTarget.style.top = this.initialTop + deltaY + 'px';
|
|
76509
|
+
this.clonedTarget.style.width = this.initialWidth - deltaX + 'px';
|
|
76510
|
+
this.clonedTarget.style.height = this.initialHeight - deltaY + 'px';
|
|
76511
|
+
}
|
|
76512
|
+
}
|
|
76513
|
+
resizeTopRight(deltaX, deltaY) {
|
|
76514
|
+
this.target.style.width = this.initialWidth + deltaX + 'px';
|
|
76515
|
+
this.target.style.top = this.initialTop + deltaY + 'px';
|
|
76516
|
+
this.target.style.height = this.initialHeight - deltaY + 'px';
|
|
76517
|
+
if (this.clonedTarget) {
|
|
76518
|
+
this.clonedTarget.style.width = this.initialWidth + deltaX + 'px';
|
|
76519
|
+
this.clonedTarget.style.top = this.initialTop + deltaY + 'px';
|
|
76520
|
+
this.clonedTarget.style.height = this.initialHeight - deltaY + 'px';
|
|
76521
|
+
}
|
|
76522
|
+
}
|
|
76523
|
+
resizeBottomLeft(deltaX, deltaY) {
|
|
76524
|
+
this.target.style.width = this.initialWidth - deltaX + 'px';
|
|
76525
|
+
this.target.style.height = this.initialHeight + deltaY + 'px';
|
|
76526
|
+
this.target.style.left = this.initialLeft + deltaX + 'px';
|
|
76527
|
+
if (this.clonedTarget) {
|
|
76528
|
+
this.clonedTarget.style.width = this.initialWidth - deltaX + 'px';
|
|
76529
|
+
this.clonedTarget.style.height = this.initialHeight + deltaY + 'px';
|
|
76530
|
+
this.clonedTarget.style.left = this.initialLeft + deltaX + 'px';
|
|
76531
|
+
}
|
|
76532
|
+
}
|
|
76533
|
+
resizeBottomRight(deltaX, deltaY) {
|
|
76534
|
+
this.target.style.width = this.initialWidth + deltaX + 'px';
|
|
76535
|
+
this.target.style.height = this.initialHeight + deltaY + 'px';
|
|
76536
|
+
if (this.clonedTarget) {
|
|
76537
|
+
this.clonedTarget.style.width = this.initialWidth + deltaX + 'px';
|
|
76538
|
+
this.clonedTarget.style.height = this.initialHeight + deltaY + 'px';
|
|
76539
|
+
}
|
|
76540
|
+
}
|
|
76541
|
+
resizeTop(deltaY) {
|
|
76542
|
+
this.target.style.top = this.initialTop + deltaY + 'px';
|
|
76543
|
+
this.target.style.height = this.initialHeight - deltaY + 'px';
|
|
76544
|
+
if (this.clonedTarget) {
|
|
76545
|
+
this.clonedTarget.style.top = this.initialTop + deltaY + 'px';
|
|
76546
|
+
this.clonedTarget.style.height = this.initialHeight - deltaY + 'px';
|
|
76547
|
+
}
|
|
76548
|
+
}
|
|
76549
|
+
resizeBottom(deltaY) {
|
|
76550
|
+
this.target.style.height = this.initialHeight + deltaY + 'px';
|
|
76551
|
+
if (this.clonedTarget) {
|
|
76552
|
+
this.clonedTarget.style.height = this.initialHeight + deltaY + 'px';
|
|
76553
|
+
}
|
|
76554
|
+
}
|
|
76555
|
+
resizeLeft(deltaX) {
|
|
76556
|
+
this.target.style.width = this.initialWidth - deltaX + 'px';
|
|
76557
|
+
this.target.style.left = this.initialLeft + deltaX + 'px';
|
|
76558
|
+
if (this.clonedTarget) {
|
|
76559
|
+
this.clonedTarget.style.width = this.initialWidth - deltaX + 'px';
|
|
76560
|
+
this.clonedTarget.style.left = this.initialLeft + deltaX + 'px';
|
|
76561
|
+
}
|
|
76562
|
+
}
|
|
76563
|
+
resizeRight(deltaX) {
|
|
76564
|
+
this.target.style.width = this.initialWidth + deltaX + 'px';
|
|
76565
|
+
if (this.clonedTarget) {
|
|
76566
|
+
this.clonedTarget.style.width = this.initialWidth + deltaX + 'px';
|
|
76567
|
+
}
|
|
76568
|
+
}
|
|
76569
|
+
stopResizing() {
|
|
76570
|
+
if (this.isResizing) {
|
|
76571
|
+
if (this.target) {
|
|
76572
|
+
this.updateBlockStyle(this.target);
|
|
76573
|
+
if (this.clonedTarget) this.updateBlockStyle(this.clonedTarget);
|
|
76574
|
+
}
|
|
76575
|
+
this.isResizing = false;
|
|
76576
|
+
}
|
|
76577
|
+
}
|
|
76578
|
+
updateBlockStyle(target) {
|
|
76579
|
+
if (target.querySelector(this.selector)) ; else {
|
|
76580
|
+
// this.common.updateHeight(target);
|
|
76581
|
+
if (target.classList.contains('height-auto')) target.style.height = '';
|
|
76582
|
+
}
|
|
76583
|
+
|
|
76584
|
+
// Replace with ruler's alignment
|
|
76585
|
+
if (this.ruler.rulerTop !== null) {
|
|
76586
|
+
target.style.top = this.ruler.rulerTop + 'px';
|
|
76587
|
+
// if container has top/left
|
|
76588
|
+
if (target.parentNode.matches(this.selector)) {
|
|
76589
|
+
const containerRect = target.parentNode.getBoundingClientRect();
|
|
76590
|
+
target.style.top = this.ruler.rulerTop - containerRect.top + 'px';
|
|
76591
|
+
}
|
|
76592
|
+
}
|
|
76593
|
+
|
|
76594
|
+
// If resizing by dragging the right corners (top or bottom)
|
|
76595
|
+
if (this.resizeHandle === 'top-right' || this.resizeHandle === 'bottom-right' || this.resizeHandle === 'right') {
|
|
76596
|
+
// Check if vertical right ruler visible (has value)
|
|
76597
|
+
if (this.ruler.rulerRight !== null) {
|
|
76598
|
+
// If so, keep the left position
|
|
76599
|
+
// target.style.left = newLeft + 'px';
|
|
76600
|
+
|
|
76601
|
+
// And update the width to align with vertical right ruler
|
|
76602
|
+
const rect = target.getBoundingClientRect();
|
|
76603
|
+
target.style.width = this.ruler.rulerRight - rect.left + 'px';
|
|
76604
|
+
}
|
|
76605
|
+
} else if (this.resizeHandle === 'top-left' || this.resizeHandle === 'bottom-left' || this.resizeHandle === 'left') {
|
|
76606
|
+
if (this.ruler.rulerLeft !== null) {
|
|
76607
|
+
const currentRight = this.initialLeft + this.initialWidth;
|
|
76608
|
+
|
|
76609
|
+
// if container has top/left
|
|
76610
|
+
const containerRect = target.parentNode.getBoundingClientRect();
|
|
76611
|
+
this.ruler.rulerLeft = this.ruler.rulerLeft - containerRect.left;
|
|
76612
|
+
|
|
76613
|
+
// And update the width to align with vertical left ruler
|
|
76614
|
+
target.style.left = this.ruler.rulerLeft + 'px';
|
|
76615
|
+
let newWidth = currentRight - this.ruler.rulerLeft;
|
|
76616
|
+
target.style.width = newWidth + 'px';
|
|
76617
|
+
}
|
|
76618
|
+
}
|
|
76619
|
+
|
|
76620
|
+
// Convert px to %
|
|
76621
|
+
this.common.applyPercentage(target);
|
|
76622
|
+
setTimeout(() => {
|
|
76623
|
+
const breakpoint = this.doc.body.getAttribute('data-breakpoint');
|
|
76624
|
+
|
|
76625
|
+
// const screenWidth = window.innerWidth;
|
|
76626
|
+
// let defaultPoint;
|
|
76627
|
+
// if(screenWidth<=1920) {
|
|
76628
|
+
// defaultPoint = 1366;
|
|
76629
|
+
// } else {
|
|
76630
|
+
// defaultPoint = 1900;
|
|
76631
|
+
// }
|
|
76632
|
+
|
|
76633
|
+
if (breakpoint && breakpoint < 1920) {
|
|
76634
|
+
target.setAttribute('data--y-' + breakpoint, target.style.top);
|
|
76635
|
+
target.setAttribute('data--x-' + breakpoint, target.style.left);
|
|
76636
|
+
target.setAttribute('data--w-' + breakpoint, target.style.width);
|
|
76637
|
+
target.setAttribute('data--h-' + breakpoint, target.style.height);
|
|
76638
|
+
} else {
|
|
76639
|
+
target.setAttribute('data--y', target.style.top);
|
|
76640
|
+
target.setAttribute('data--x', target.style.left);
|
|
76641
|
+
target.setAttribute('data--w', target.style.width);
|
|
76642
|
+
target.setAttribute('data--h', target.style.height);
|
|
76643
|
+
}
|
|
76644
|
+
target.removeAttribute('data-prev'); // reset
|
|
76645
|
+
target.removeAttribute('data-fluid');
|
|
76646
|
+
}, 30); // delay needed since we use updateHeight() previously that has 20ms process
|
|
76647
|
+
|
|
76648
|
+
if (this.onChange) this.onChange();
|
|
76649
|
+
}
|
|
76650
|
+
}
|
|
76651
|
+
class Draggable {
|
|
76652
|
+
constructor(options) {
|
|
76653
|
+
this.selector = options && options.selector || '.is-block';
|
|
76654
|
+
this.doc = options && options.doc || document;
|
|
76655
|
+
this.win = options && options.win || window;
|
|
76656
|
+
this.onDelete = options && options.onDelete || null;
|
|
76657
|
+
this.onBeforeChange = options && options.onBeforeChange || null;
|
|
76658
|
+
this.onChange = options && options.onChange || null;
|
|
76659
|
+
this.onSelectStart = options && options.onSelectStart || null;
|
|
76660
|
+
this.onSelectClear = options && options.onSelectClear || null;
|
|
76661
|
+
this.disableOnMobile = options && options.disableOnMobile || 0;
|
|
76662
|
+
this.onMultipleSelect = options && options.onMultipleSelect || null;
|
|
76663
|
+
this.onSelectBlock = options && options.onSelectBlock || null;
|
|
76664
|
+
this.isDragging = false;
|
|
76665
|
+
this.startX = 0;
|
|
76666
|
+
this.startY = 0;
|
|
76667
|
+
this.handleDragStart = this.handleDragStart.bind(this);
|
|
76668
|
+
this.handleDragMove = this.handleDragMove.bind(this);
|
|
76669
|
+
this.handleDragEnd = this.handleDragEnd.bind(this);
|
|
76670
|
+
this.handleSelect = this.handleSelect.bind(this);
|
|
76671
|
+
this.handleKeyDown = this.handleKeyDown.bind(this);
|
|
76672
|
+
this.setup();
|
|
76673
|
+
this.ruler = new Ruler({
|
|
76674
|
+
selector: this.selector,
|
|
76675
|
+
doc: this.doc,
|
|
76676
|
+
win: this.win
|
|
76677
|
+
});
|
|
76678
|
+
this.common = new Common({
|
|
76679
|
+
selector: this.selector,
|
|
76680
|
+
doc: this.doc,
|
|
76681
|
+
win: this.win
|
|
76682
|
+
});
|
|
76683
|
+
}
|
|
76684
|
+
setup() {
|
|
76685
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76686
|
+
this.elements.forEach(element => {
|
|
76687
|
+
element.addEventListener('mousedown', this.handleDragStart);
|
|
76688
|
+
element.addEventListener('touchstart', this.handleDragStart, {
|
|
76689
|
+
passive: false
|
|
76690
|
+
});
|
|
76691
|
+
});
|
|
76692
|
+
this.doc.addEventListener('mousedown', this.handleSelect);
|
|
76693
|
+
this.doc.addEventListener('touchstart', this.handleSelect, {
|
|
76694
|
+
passive: false
|
|
76695
|
+
});
|
|
76696
|
+
this.doc.addEventListener('keydown', this.handleKeyDown);
|
|
76697
|
+
}
|
|
76698
|
+
refresh() {
|
|
76699
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76700
|
+
this.elements.forEach(element => {
|
|
76701
|
+
element.removeEventListener('mousedown', this.handleDragStart);
|
|
76702
|
+
element.removeEventListener('touchstart', this.handleDragStart);
|
|
76703
|
+
});
|
|
76704
|
+
this.elements.forEach(element => {
|
|
76705
|
+
element.addEventListener('mousedown', this.handleDragStart);
|
|
76706
|
+
element.addEventListener('touchstart', this.handleDragStart, {
|
|
76707
|
+
passive: false
|
|
76708
|
+
});
|
|
76709
|
+
});
|
|
76710
|
+
this.ruler.refresh();
|
|
76711
|
+
}
|
|
76712
|
+
destroy() {
|
|
76713
|
+
this.ruler.destroy();
|
|
76714
|
+
this.elements.forEach(element => {
|
|
76715
|
+
element.removeEventListener('mousedown', this.handleDragStart);
|
|
76716
|
+
element.removeEventListener('touchstart', this.handleDragStart);
|
|
76717
|
+
});
|
|
76718
|
+
this.doc.removeEventListener('mousedown', this.handleSelect);
|
|
76719
|
+
this.doc.removeEventListener('touchstart', this.handleSelect);
|
|
76720
|
+
this.doc.removeEventListener('keydown', this.handleKeyDown);
|
|
76721
|
+
const blocks = this.doc.querySelectorAll(this.selector);
|
|
76722
|
+
blocks.forEach(elm => elm.classList.remove('active'));
|
|
76723
|
+
}
|
|
76724
|
+
disableDrag(block) {
|
|
76725
|
+
this.elements.forEach(element => {
|
|
76726
|
+
if (block === element) {
|
|
76727
|
+
element.removeEventListener('mousedown', this.handleDragStart);
|
|
76728
|
+
element.removeEventListener('touchstart', this.handleDragStart);
|
|
76729
|
+
}
|
|
76730
|
+
});
|
|
76731
|
+
}
|
|
76732
|
+
enableDrag(block) {
|
|
76733
|
+
this.elements.forEach(element => {
|
|
76734
|
+
if (block === element) {
|
|
76735
|
+
element.addEventListener('mousedown', this.handleDragStart);
|
|
76736
|
+
element.addEventListener('touchstart', this.handleDragStart, {
|
|
76737
|
+
passive: false
|
|
76738
|
+
});
|
|
76739
|
+
}
|
|
76740
|
+
});
|
|
76741
|
+
}
|
|
76742
|
+
handleDragStart(event) {
|
|
76743
|
+
const viewportWidth = this.win.innerWidth;
|
|
76744
|
+
if (viewportWidth <= this.disableOnMobile) return;
|
|
76745
|
+
if (event.target.classList.contains('rotate-handle')) return;
|
|
76746
|
+
if (event.type === 'touchstart' && event.touches.length !== 1) {
|
|
76747
|
+
return; // Do nothing if more than one touch point is detected
|
|
76748
|
+
}
|
|
76749
|
+
|
|
76750
|
+
if (event.type === 'mousedown' && event.button !== 0) {
|
|
76751
|
+
return; // Do nothing if the right mouse button is clicked
|
|
76752
|
+
}
|
|
76753
|
+
|
|
76754
|
+
const currentTarget = event.currentTarget;
|
|
76755
|
+
const clickedBlock = event.target.closest(this.selector);
|
|
76756
|
+
if (currentTarget !== clickedBlock) {
|
|
76757
|
+
// Triggered Group click by child block click
|
|
76758
|
+
return; // Return here, so that when block events are working, group events won't
|
|
76759
|
+
}
|
|
76760
|
+
|
|
76761
|
+
this.clickedBlock = clickedBlock;
|
|
76762
|
+
this.dragStartTimeout = setTimeout(() => {
|
|
76763
|
+
// Set a timeout before starting the drag (to differentiate from click)
|
|
76764
|
+
|
|
76765
|
+
if (event.type === 'mousedown') {
|
|
76766
|
+
this.startDragging(event.clientX, event.clientY, currentTarget);
|
|
76767
|
+
} else if (event.type === 'touchstart') {
|
|
76768
|
+
const touch = event.touches[0];
|
|
76769
|
+
this.startDragging(touch.clientX, touch.clientY, currentTarget);
|
|
76770
|
+
}
|
|
76771
|
+
this.doc.addEventListener('mousemove', this.handleDragMove);
|
|
76772
|
+
this.doc.addEventListener('touchmove', this.handleDragMove);
|
|
76773
|
+
}, 120);
|
|
76774
|
+
this.doc.addEventListener('mouseup', this.handleDragEnd);
|
|
76775
|
+
this.doc.addEventListener('touchend', this.handleDragEnd);
|
|
76776
|
+
}
|
|
76777
|
+
startDragging(startX, startY) {
|
|
76778
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
76779
|
+
this.isDragging = true;
|
|
76780
|
+
const blocks = this.doc.querySelectorAll(this.selector + '.active');
|
|
76781
|
+
blocks.forEach(target => {
|
|
76782
|
+
// const containerRect = target.parentNode.getBoundingClientRect(); // if container has top/left
|
|
76783
|
+
const containerRect = this.common.getRect(target.parentNode); // if container has top/left
|
|
76784
|
+
const rect = this.common.getRect(target);
|
|
76785
|
+
const x = startX - rect.left + containerRect.left;
|
|
76786
|
+
const y = startY - rect.top + containerRect.top;
|
|
76787
|
+
target.setAttribute('data-startx', x);
|
|
76788
|
+
target.setAttribute('data-starty', y);
|
|
76789
|
+
this.common.applyPixels(target);
|
|
76790
|
+
});
|
|
76791
|
+
this.clickedBlock = this.common.getSelectedBlock();
|
|
76792
|
+
}
|
|
76793
|
+
handleDragMove(event) {
|
|
76794
|
+
let clientX, clientY;
|
|
76795
|
+
if (event.type === 'mousemove') {
|
|
76796
|
+
clientX = event.clientX;
|
|
76797
|
+
clientY = event.clientY;
|
|
76798
|
+
} else if (event.type === 'touchmove') {
|
|
76799
|
+
const touch = event.touches[0];
|
|
76800
|
+
clientX = touch.clientX;
|
|
76801
|
+
clientY = touch.clientY;
|
|
76802
|
+
}
|
|
76803
|
+
if (this.isDragging) {
|
|
76804
|
+
// Allows dragging multiple selected blocks
|
|
76805
|
+
|
|
76806
|
+
let blocks = this.doc.querySelectorAll(this.selector + '.active');
|
|
76807
|
+
blocks.forEach(target => {
|
|
76808
|
+
this.updatePosition(clientX, clientY, target);
|
|
76809
|
+
});
|
|
76810
|
+
|
|
76811
|
+
// Ruler works for single block selection only
|
|
76812
|
+
if (this.clickedBlock) this.ruler.updateRulers(this.clickedBlock);
|
|
76813
|
+
}
|
|
76814
|
+
event.preventDefault();
|
|
76815
|
+
event.stopImmediatePropagation();
|
|
76816
|
+
}
|
|
76817
|
+
updatePosition(x, y, target) {
|
|
76818
|
+
if (this.isDragging) {
|
|
76819
|
+
const startX = target.getAttribute('data-startx');
|
|
76820
|
+
const startY = target.getAttribute('data-starty');
|
|
76821
|
+
const newX = x - startX;
|
|
76822
|
+
const newY = y - startY;
|
|
76823
|
+
target.style.left = newX + 'px';
|
|
76824
|
+
target.style.top = newY + 'px';
|
|
76825
|
+
}
|
|
76826
|
+
}
|
|
76827
|
+
handleDragEnd() {
|
|
76828
|
+
clearTimeout(this.dragStartTimeout);
|
|
76829
|
+
if (this.isDragging) {
|
|
76830
|
+
this.doc.removeEventListener('mousemove', this.handleDragMove);
|
|
76831
|
+
this.doc.removeEventListener('touchmove', this.handleDragMove);
|
|
76832
|
+
}
|
|
76833
|
+
this.doc.removeEventListener('mouseup', this.handleDragEnd);
|
|
76834
|
+
this.doc.removeEventListener('touchend', this.handleDragEnd);
|
|
76835
|
+
this.stopDragging();
|
|
76836
|
+
this.ruler.hideRulers();
|
|
76837
|
+
let blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active') && !elm.classList.contains('multi'));
|
|
76838
|
+
if (blocks.length === 1) {
|
|
76839
|
+
const block = blocks[0];
|
|
76840
|
+
if (this.onSelectStart) this.onSelectStart(block); // on first block select (before clone)
|
|
76841
|
+
}
|
|
76842
|
+
}
|
|
76843
|
+
|
|
76844
|
+
stopDragging() {
|
|
76845
|
+
if (this.isDragging) {
|
|
76846
|
+
const blocks = this.doc.querySelectorAll(this.selector + '.active');
|
|
76847
|
+
blocks.forEach(target => {
|
|
76848
|
+
this.updateBlockStyle(target);
|
|
76849
|
+
});
|
|
76850
|
+
this.isDragging = false;
|
|
76851
|
+
}
|
|
76852
|
+
}
|
|
76853
|
+
updateBlockStyle(target) {
|
|
76854
|
+
// Replace with ruler's alignment
|
|
76855
|
+
const containerRect = this.common.getRect(target.parentNode); // if container has top/left
|
|
76856
|
+
const initialWidth = parseFloat(getComputedStyle(target).width);
|
|
76857
|
+
if (this.ruler.rulerTop !== null) target.style.top = this.ruler.rulerTop - containerRect.top + 'px';
|
|
76858
|
+
if (this.ruler.rulerLeft !== null) target.style.left = this.ruler.rulerLeft - containerRect.left + 'px';else if (this.ruler.rulerRight !== null) target.style.left = this.ruler.rulerRight - initialWidth - containerRect.left + 'px';
|
|
76859
|
+
this.doc.querySelectorAll('[data-startx]').forEach(elm => elm.removeAttribute('data-startx'));
|
|
76860
|
+
this.doc.querySelectorAll('[data-starty]').forEach(elm => elm.removeAttribute('data-starty'));
|
|
76861
|
+
this.common.applyPercentage(target);
|
|
76862
|
+
const breakpoint = this.doc.body.getAttribute('data-breakpoint');
|
|
76863
|
+
|
|
76864
|
+
// const screenWidth = window.innerWidth;
|
|
76865
|
+
// let defaultPoint;
|
|
76866
|
+
// if(screenWidth<=1920) {
|
|
76867
|
+
// defaultPoint = 1366;
|
|
76868
|
+
// } else {
|
|
76869
|
+
// defaultPoint = 1900;
|
|
76870
|
+
// }
|
|
76871
|
+
|
|
76872
|
+
if (breakpoint && breakpoint < 1920) {
|
|
76873
|
+
target.setAttribute('data--y-' + breakpoint, target.style.top);
|
|
76874
|
+
target.setAttribute('data--x-' + breakpoint, target.style.left);
|
|
76875
|
+
target.setAttribute('data--w-' + breakpoint, target.style.width);
|
|
76876
|
+
target.setAttribute('data--h-' + breakpoint, target.style.height);
|
|
76877
|
+
} else {
|
|
76878
|
+
target.setAttribute('data--y', target.style.top);
|
|
76879
|
+
target.setAttribute('data--x', target.style.left);
|
|
76880
|
+
target.setAttribute('data--w', target.style.width);
|
|
76881
|
+
target.setAttribute('data--h', target.style.height);
|
|
76882
|
+
}
|
|
76883
|
+
target.removeAttribute('data-prev'); // reset
|
|
76884
|
+
target.removeAttribute('data-fluid');
|
|
76885
|
+
if (this.onChange) this.onChange();
|
|
76886
|
+
}
|
|
76887
|
+
handleSelect(event) {
|
|
76888
|
+
const element = event.target;
|
|
76889
|
+
if (element.classList.contains('rotate-handle')) return;
|
|
76890
|
+
const block = element.closest(this.selector);
|
|
76891
|
+
if (block) {
|
|
76892
|
+
if (block.classList.contains('active')) {
|
|
76893
|
+
let actualBlock = block.classList.contains('clone') ? this.doc.querySelector(this.selector + '.cloned') : null;
|
|
76894
|
+
if (!actualBlock) actualBlock = block;
|
|
76895
|
+
if (this.onSelectBlock) this.onSelectBlock(actualBlock);
|
|
76896
|
+
return; // if clicked block is active
|
|
76897
|
+
}
|
|
76898
|
+
// if(block.parentNode.classList.contains('active')) return; // if group is active
|
|
76899
|
+
|
|
76900
|
+
if (block.matches(this.selector) && block.querySelector(this.selector)) {
|
|
76901
|
+
// if group is clicked, remove active childe's blocks
|
|
76902
|
+
block.querySelectorAll(this.selector).forEach(elm => elm.classList.remove('active'));
|
|
76903
|
+
}
|
|
76904
|
+
if (event.shiftKey || this.doc.body.classList.contains('multi-select')) {
|
|
76905
|
+
// multi select
|
|
76906
|
+
block.classList.add('active');
|
|
76907
|
+
if (this.onMultipleSelect) this.onMultipleSelect();
|
|
76908
|
+
} else {
|
|
76909
|
+
if (this.onSelectClear) this.onSelectClear();
|
|
76910
|
+
this.doc.querySelectorAll(this.selector + '.active').forEach(elm => elm.classList.remove('active'));
|
|
76911
|
+
block.classList.add('active');
|
|
76912
|
+
let actualBlock = block.classList.contains('clone') ? this.doc.querySelector(this.selector + '.cloned') : null;
|
|
76913
|
+
if (!actualBlock) actualBlock = block;
|
|
76914
|
+
if (this.onSelectBlock) this.onSelectBlock(actualBlock);
|
|
76915
|
+
}
|
|
76916
|
+
if (!block.parentNode) return; // just in case
|
|
76917
|
+
|
|
76918
|
+
// Higlight parent group if current child block is clicked
|
|
76919
|
+
if (block.parentNode.matches(this.selector)) {
|
|
76920
|
+
block.parentNode.classList.add('block-active');
|
|
76921
|
+
} else {
|
|
76922
|
+
this.doc.querySelectorAll('.block-active').forEach(elm => elm.classList.remove('block-active'));
|
|
76923
|
+
}
|
|
76924
|
+
} else {
|
|
76925
|
+
if (event.target.closest('.keep-selection')) return;
|
|
76926
|
+
|
|
76927
|
+
// // Make empty height set with value
|
|
76928
|
+
// // if(this.clickedBlock) this.common.updateHeight(this.clickedBlock);
|
|
76929
|
+
// // Check
|
|
76930
|
+
// if(this.clickedBlock && !this.clickedBlock.classList.contains('clone')) {
|
|
76931
|
+
// this.common.updateHeight(this.clickedBlock);
|
|
76932
|
+
// }
|
|
76933
|
+
|
|
76934
|
+
this.doc.querySelectorAll(this.selector + '.active').forEach(elm => elm.classList.remove('active'));
|
|
76935
|
+
this.doc.querySelectorAll('.block-active').forEach(elm => elm.classList.remove('block-active'));
|
|
76936
|
+
if (this.onSelectClear) this.onSelectClear();
|
|
76937
|
+
}
|
|
76938
|
+
|
|
76939
|
+
// Check if multiple selection occurs. If so, add 'multi' class to hide all the handles
|
|
76940
|
+
let blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active') && !elm.classList.contains('clone'));
|
|
76941
|
+
if (blocks.length > 1) {
|
|
76942
|
+
blocks.forEach(block => {
|
|
76943
|
+
block.classList.add('multi');
|
|
76944
|
+
});
|
|
76945
|
+
} else {
|
|
76946
|
+
const elms = this.doc.querySelectorAll('.multi');
|
|
76947
|
+
elms.forEach(elm => elm.classList.remove('multi'));
|
|
76948
|
+
}
|
|
76949
|
+
}
|
|
76950
|
+
delete() {
|
|
76951
|
+
let blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active') && elm.classList.contains('editable'));
|
|
76952
|
+
if (blocks.length > 0) return;
|
|
76953
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
76954
|
+
blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active'));
|
|
76955
|
+
blocks.forEach(element => {
|
|
76956
|
+
element.removeEventListener('mousedown', this.handleDragStart);
|
|
76957
|
+
element.removeEventListener('touchstart', this.handleDragStart);
|
|
76958
|
+
if (this.onDelete) this.onDelete(element);
|
|
76959
|
+
element.parentNode.removeChild(element);
|
|
76960
|
+
});
|
|
76961
|
+
if (this.onChange) this.onChange();
|
|
76962
|
+
}
|
|
76963
|
+
handleKeyDown(event) {
|
|
76964
|
+
if (event.key === 'Delete' || event.key === 'Backspace' || event.keyCode === 46) {
|
|
76965
|
+
this.delete();
|
|
76966
|
+
}
|
|
76967
|
+
}
|
|
76968
|
+
}
|
|
76969
|
+
class Editable {
|
|
76970
|
+
constructor(options) {
|
|
76971
|
+
this.selector = options && options.selector || '.is-block';
|
|
76972
|
+
this.controlSelector = options && options.controlSelector || null;
|
|
76973
|
+
this.onEditStart = options && options.onEditStart || null;
|
|
76974
|
+
this.onEditEnd = options && options.onEditEnd || null;
|
|
76975
|
+
this.doc = options && options.doc || document;
|
|
76976
|
+
this.win = options && options.win || window;
|
|
76977
|
+
this.onContentClick = options && options.onContentClick || null;
|
|
76978
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76979
|
+
this.handleEditStart = this.handleEditStart.bind(this);
|
|
76980
|
+
this.handleMouseClick = this.handleMouseClick.bind(this);
|
|
76981
|
+
this.handleTouchStart = this.handleTouchStart.bind(this);
|
|
76982
|
+
this.setup();
|
|
76983
|
+
}
|
|
76984
|
+
setup() {
|
|
76985
|
+
this.elements.forEach(element => {
|
|
76986
|
+
element.addEventListener('dblclick', this.handleEditStart);
|
|
76987
|
+
element.addEventListener('touchstart', this.handleTouchStart, {
|
|
76988
|
+
passive: false
|
|
76989
|
+
});
|
|
76990
|
+
});
|
|
76991
|
+
}
|
|
76992
|
+
refresh() {
|
|
76993
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
76994
|
+
this.elements.forEach(element => {
|
|
76995
|
+
element.removeEventListener('dblclick', this.handleEditStart);
|
|
76996
|
+
element.removeEventListener('touchstart', this.handleTouchStart);
|
|
76997
|
+
});
|
|
76998
|
+
this.elements.forEach(element => {
|
|
76999
|
+
element.addEventListener('dblclick', this.handleEditStart);
|
|
77000
|
+
element.addEventListener('touchstart', this.handleTouchStart, {
|
|
77001
|
+
passive: false
|
|
77002
|
+
});
|
|
77003
|
+
});
|
|
77004
|
+
}
|
|
77005
|
+
destroy(element) {
|
|
77006
|
+
if (element) {
|
|
77007
|
+
element.removeEventListener('dblclick', this.handleEditStart);
|
|
77008
|
+
element.removeEventListener('touchstart', this.handleTouchStart);
|
|
77009
|
+
} else {
|
|
77010
|
+
this.elements = this.doc.querySelectorAll(this.selector);
|
|
77011
|
+
this.elements.forEach(element => {
|
|
77012
|
+
element.removeEventListener('dblclick', this.handleEditStart);
|
|
77013
|
+
element.removeEventListener('touchstart', this.handleTouchStart);
|
|
77014
|
+
});
|
|
77015
|
+
}
|
|
77016
|
+
}
|
|
77017
|
+
handleEditStart(event) {
|
|
77018
|
+
const currentTarget = event.currentTarget;
|
|
77019
|
+
if (currentTarget.querySelector(this.selector)) {
|
|
77020
|
+
// if group, no edit needed
|
|
77021
|
+
return;
|
|
77022
|
+
}
|
|
77023
|
+
const block = event.target.closest(this.selector);
|
|
77024
|
+
if (currentTarget !== block) {
|
|
77025
|
+
// Triggered Group click by child block click
|
|
77026
|
+
return; // Return here, so that when block events are working, group events won't
|
|
77027
|
+
}
|
|
77028
|
+
|
|
77029
|
+
if (block.parentNode.matches(this.selector) && block.parentNode.classList.contains('active')) {
|
|
77030
|
+
// if group is active, no edit needed
|
|
77031
|
+
return;
|
|
77032
|
+
}
|
|
77033
|
+
this.clickedBlock = currentTarget;
|
|
77034
|
+
|
|
77035
|
+
// currentTarget.classList.add('editable');
|
|
77036
|
+
// currentTarget.setAttribute('contentEditable', true);
|
|
77037
|
+
// currentTarget.style.cursor = 'auto'; // Change cursor to normal
|
|
77038
|
+
// currentTarget.focus();
|
|
77039
|
+
// this.placeCursorAtEnd(currentTarget);
|
|
77040
|
+
|
|
77041
|
+
this.elements.forEach(element => {
|
|
77042
|
+
if (currentTarget === element) {
|
|
77043
|
+
element.removeEventListener('dblclick', this.handleEditStart);
|
|
77044
|
+
element.removeEventListener('touchstart', this.handleTouchStart);
|
|
77045
|
+
const clonedTarget = this.doc.querySelector(this.selector + '.cloned');
|
|
77046
|
+
if (clonedTarget) {
|
|
77047
|
+
clonedTarget.removeEventListener('dblclick', this.handleEditStart);
|
|
77048
|
+
clonedTarget.removeEventListener('touchstart', this.handleTouchStart);
|
|
77049
|
+
this.clickedBlock = clonedTarget;
|
|
77050
|
+
}
|
|
77051
|
+
}
|
|
77052
|
+
});
|
|
77053
|
+
this.doc.addEventListener('mousedown', this.handleMouseClick);
|
|
77054
|
+
this.doc.addEventListener('touchstart', this.handleMouseClick, {
|
|
77055
|
+
passive: false
|
|
77056
|
+
});
|
|
77057
|
+
if (this.onEditStart) this.onEditStart(currentTarget);
|
|
77058
|
+
}
|
|
77059
|
+
handleTouchStart(event) {
|
|
77060
|
+
// Handle Double Tab
|
|
77061
|
+
if (event.touches.length === 1) {
|
|
77062
|
+
const now = new Date().getTime();
|
|
77063
|
+
const lastTouchTime = this.lastTouchTime || now;
|
|
77064
|
+
const timeDiff = now - lastTouchTime;
|
|
77065
|
+
if (timeDiff < 300 && timeDiff > 0) {
|
|
77066
|
+
// Less than 300ms since the last touch, consider it a double-tap
|
|
77067
|
+
this.handleDoubleTap(event);
|
|
77068
|
+
}
|
|
77069
|
+
this.lastTouchTime = now;
|
|
77070
|
+
}
|
|
77071
|
+
}
|
|
77072
|
+
handleDoubleTap(event) {
|
|
77073
|
+
this.handleEditStart(event);
|
|
77074
|
+
}
|
|
77075
|
+
handleMouseClick(event) {
|
|
77076
|
+
const element = event.target;
|
|
77077
|
+
if (element.closest(this.selector) === this.clickedBlock || this.controlSelector && element.closest(this.controlSelector)) {
|
|
77078
|
+
// Do Nothing
|
|
77079
|
+
// Continue editing
|
|
77080
|
+
if (element.parentNode.matches(this.selector)) {
|
|
77081
|
+
if (this.onContentClick) this.onContentClick(event);
|
|
77082
|
+
// this.doc.querySelectorAll('.elm-active').forEach(elm=>elm.classList.remove('elm-active'));
|
|
77083
|
+
// element.classList.add('elm-active');
|
|
77084
|
+
}
|
|
77085
|
+
} else {
|
|
77086
|
+
let clickedBlock = this.clickedBlock;
|
|
77087
|
+
|
|
77088
|
+
// currentTarget.classList.remove('editable');
|
|
77089
|
+
// clickedBlock.removeAttribute('contentEditable');
|
|
77090
|
+
// clickedBlock.style.cursor = '';
|
|
77091
|
+
|
|
77092
|
+
if (this.onEditEnd) this.onEditEnd(this.clickedBlock);
|
|
77093
|
+
this.elements.forEach(element => {
|
|
77094
|
+
if (clickedBlock === element) {
|
|
77095
|
+
element.addEventListener('dblclick', this.handleEditStart);
|
|
77096
|
+
element.addEventListener('touchstart', this.handleTouchStart, {
|
|
77097
|
+
passive: false
|
|
77098
|
+
});
|
|
77099
|
+
}
|
|
77100
|
+
});
|
|
77101
|
+
this.doc.removeEventListener('mousedown', this.handleMouseClick);
|
|
77102
|
+
this.doc.removeEventListener('touchstart', this.handleMouseClick);
|
|
77103
|
+
|
|
77104
|
+
// this.doc.querySelectorAll('.elm-active').forEach(elm=>elm.classList.remove('elm-active'));
|
|
77105
|
+
}
|
|
77106
|
+
}
|
|
77107
|
+
|
|
77108
|
+
quitEditable(block) {
|
|
77109
|
+
if (this.onEditEnd) this.onEditEnd(block);
|
|
77110
|
+
block.addEventListener('dblclick', this.handleEditStart);
|
|
77111
|
+
block.addEventListener('touchstart', this.handleTouchStart, {
|
|
77112
|
+
passive: false
|
|
77113
|
+
});
|
|
77114
|
+
this.doc.removeEventListener('mousedown', this.handleMouseClick);
|
|
77115
|
+
this.doc.removeEventListener('touchstart', this.handleMouseClick);
|
|
77116
|
+
}
|
|
77117
|
+
placeCursorAtEnd(element) {
|
|
77118
|
+
const range = this.doc.createRange();
|
|
77119
|
+
const sel = this.win.getSelection();
|
|
77120
|
+
range.setStart(element, element.childNodes.length);
|
|
77121
|
+
range.collapse(true);
|
|
77122
|
+
sel.removeAllRanges();
|
|
77123
|
+
sel.addRange(range);
|
|
77124
|
+
}
|
|
77125
|
+
}
|
|
77126
|
+
class BlockSelector {
|
|
77127
|
+
constructor(options) {
|
|
77128
|
+
this.selector = options && options.selector || '.is-block';
|
|
77129
|
+
this.parentSelector = options && options.parentSelector || 'body';
|
|
77130
|
+
this.doc = options && options.doc || document;
|
|
77131
|
+
this.win = options && options.win || window;
|
|
77132
|
+
this.disableOnMobile = options && options.disableOnMobile || 0;
|
|
77133
|
+
this.onMultipleSelect = options && options.onMultipleSelect || null;
|
|
77134
|
+
this.isDragging = false;
|
|
77135
|
+
this.startCoords = {
|
|
77136
|
+
x: 0,
|
|
77137
|
+
y: 0
|
|
77138
|
+
};
|
|
77139
|
+
const handleHTML = `
|
|
77140
|
+
<div class="selection-rectangle"></div>`;
|
|
77141
|
+
this.doc.body.insertAdjacentHTML('afterbegin', handleHTML);
|
|
77142
|
+
this.selectionRect = this.doc.querySelector('.selection-rectangle');
|
|
77143
|
+
const styleHTML = `
|
|
77144
|
+
<style id="styleSelector">
|
|
77145
|
+
.selection-rectangle {
|
|
77146
|
+
position: absolute;
|
|
77147
|
+
border: 1px solid #c2e2ff;
|
|
77148
|
+
pointer-events: none;
|
|
77149
|
+
display: none;
|
|
77150
|
+
background-color: #a9c4e442;
|
|
77151
|
+
z-index:1
|
|
77152
|
+
}
|
|
77153
|
+
<style>
|
|
77154
|
+
`;
|
|
77155
|
+
const elmStyle = this.doc.querySelector('#styleSelector');
|
|
77156
|
+
if (!elmStyle) this.doc.head.insertAdjacentHTML('beforeend', styleHTML);
|
|
77157
|
+
this.handleDragStart = this.handleDragStart.bind(this);
|
|
77158
|
+
this.handleDragMove = this.handleDragMove.bind(this);
|
|
77159
|
+
this.handleDragEnd = this.handleDragEnd.bind(this);
|
|
77160
|
+
this.doc.addEventListener('mousedown', this.handleDragStart);
|
|
77161
|
+
this.doc.addEventListener('touchstart', this.handleDragStart, {
|
|
77162
|
+
passive: false
|
|
77163
|
+
});
|
|
77164
|
+
}
|
|
77165
|
+
destroy() {
|
|
77166
|
+
const elmStyle = this.doc.querySelector('#styleSelector');
|
|
77167
|
+
if (elmStyle) elmStyle.parentNode.removeChild(elmStyle);
|
|
77168
|
+
const selectionRect = this.doc.querySelector('.selection-rectangle');
|
|
77169
|
+
if (selectionRect) selectionRect.parentNode.removeChild(selectionRect);
|
|
77170
|
+
this.doc.removeEventListener('mousedown', this.handleDragStart);
|
|
77171
|
+
this.doc.removeEventListener('touchstart', this.handleDragStart);
|
|
77172
|
+
}
|
|
77173
|
+
handleDragStart(event) {
|
|
77174
|
+
const viewportWidth = this.win.innerWidth;
|
|
77175
|
+
if (viewportWidth <= this.disableOnMobile) return;
|
|
77176
|
+
if (event.type === 'touchstart' && event.touches.length !== 1) {
|
|
77177
|
+
return; // Do nothing if more than one touch point is detected
|
|
77178
|
+
}
|
|
77179
|
+
|
|
77180
|
+
if (event.type === 'mousedown' && event.button !== 0) {
|
|
77181
|
+
return; // Do nothing if the right mouse button is clicked
|
|
77182
|
+
}
|
|
77183
|
+
|
|
77184
|
+
if (event.target.closest(this.selector)) return;
|
|
77185
|
+
if (!event.target.closest(this.parentSelector)) return;
|
|
77186
|
+
if (event.target.closest('.keep-selection')) return;
|
|
77187
|
+
this.dragStartTimeout = setTimeout(() => {
|
|
77188
|
+
// Set a timeout before starting the drag (to differentiate from click)
|
|
77189
|
+
|
|
77190
|
+
this.isDragging = true;
|
|
77191
|
+
let clientX, clientY;
|
|
77192
|
+
if (event.type === 'mousedown') {
|
|
77193
|
+
clientX = event.clientX;
|
|
77194
|
+
clientY = event.clientY;
|
|
77195
|
+
} else if (event.type === 'touchstart') {
|
|
77196
|
+
const touch = event.touches[0];
|
|
77197
|
+
clientX = touch.clientX;
|
|
77198
|
+
clientY = touch.clientY;
|
|
77199
|
+
}
|
|
77200
|
+
this.startCoords = {
|
|
77201
|
+
x: clientX,
|
|
77202
|
+
y: clientY
|
|
77203
|
+
};
|
|
77204
|
+
this.updateSelectionRect(this.startCoords, this.startCoords);
|
|
77205
|
+
this.doc.addEventListener('mousemove', this.handleDragMove);
|
|
77206
|
+
this.doc.addEventListener('touchmove', this.handleDragMove);
|
|
77207
|
+
this.doc.body.style.userSelect = 'none';
|
|
77208
|
+
}, 100);
|
|
77209
|
+
this.doc.addEventListener('mouseup', this.handleDragEnd);
|
|
77210
|
+
this.doc.addEventListener('touchend', this.handleDragEnd);
|
|
77211
|
+
}
|
|
77212
|
+
handleDragMove(event) {
|
|
77213
|
+
if (!this.isDragging) return;
|
|
77214
|
+
if (event.target.closest('.keep-selection')) return;
|
|
77215
|
+
let clientX, clientY;
|
|
77216
|
+
if (event.type === 'mousemove') {
|
|
77217
|
+
clientX = event.clientX;
|
|
77218
|
+
clientY = event.clientY;
|
|
77219
|
+
} else if (event.type === 'touchmove') {
|
|
77220
|
+
const touch = event.touches[0];
|
|
77221
|
+
clientX = touch.clientX;
|
|
77222
|
+
clientY = touch.clientY;
|
|
77223
|
+
}
|
|
77224
|
+
this.updateSelectionRect(this.startCoords, {
|
|
77225
|
+
x: clientX,
|
|
77226
|
+
y: clientY
|
|
77227
|
+
});
|
|
77228
|
+
this.selectBlocksInArea(this.startCoords, {
|
|
77229
|
+
x: clientX,
|
|
77230
|
+
y: clientY
|
|
77231
|
+
});
|
|
77232
|
+
}
|
|
77233
|
+
handleDragEnd() {
|
|
77234
|
+
clearTimeout(this.dragStartTimeout);
|
|
77235
|
+
this.isDragging = false;
|
|
77236
|
+
this.selectionRect.style.display = 'none';
|
|
77237
|
+
this.doc.removeEventListener('mousemove', this.handleDragMove);
|
|
77238
|
+
this.doc.removeEventListener('touchmove', this.handleDragMove);
|
|
77239
|
+
this.doc.removeEventListener('mouseup', this.handleDragEnd);
|
|
77240
|
+
this.doc.removeEventListener('touchend', this.handleDragEnd);
|
|
77241
|
+
this.doc.body.style.userSelect = '';
|
|
77242
|
+
const elms = this.doc.querySelectorAll(this.selector + '.active');
|
|
77243
|
+
if (elms.length > 1) this.onMultipleSelect();
|
|
77244
|
+
}
|
|
77245
|
+
updateSelectionRect(start, end) {
|
|
77246
|
+
const minX = Math.min(start.x, end.x);
|
|
77247
|
+
const minY = Math.min(start.y, end.y) + this.win.scrollY;
|
|
77248
|
+
const width = Math.abs(start.x - end.x);
|
|
77249
|
+
const height = Math.abs(start.y - end.y);
|
|
77250
|
+
this.selectionRect.style.left = `${minX}px`;
|
|
77251
|
+
this.selectionRect.style.top = `${minY}px`;
|
|
77252
|
+
this.selectionRect.style.width = `${width}px`;
|
|
77253
|
+
this.selectionRect.style.height = `${height}px`;
|
|
77254
|
+
this.selectionRect.style.display = 'block';
|
|
77255
|
+
}
|
|
77256
|
+
selectBlocksInArea(start, end) {
|
|
77257
|
+
const blocks = this.doc.querySelectorAll(this.selector);
|
|
77258
|
+
blocks.forEach(block => {
|
|
77259
|
+
const rect = block.getBoundingClientRect();
|
|
77260
|
+
if (rect.left < Math.max(start.x, end.x) && rect.right > Math.min(start.x, end.x) && rect.top < Math.max(start.y, end.y) && rect.bottom > Math.min(start.y, end.y)) {
|
|
77261
|
+
if (block.parentNode.matches(this.selector)) ; else {
|
|
77262
|
+
block.classList.add('active');
|
|
77263
|
+
let elms = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active') && !elm.classList.contains('clone'));
|
|
77264
|
+
if (elms.length > 1) block.classList.add('multi');
|
|
77265
|
+
}
|
|
77266
|
+
} else {
|
|
77267
|
+
block.classList.remove('active');
|
|
77268
|
+
block.classList.remove('multi');
|
|
77269
|
+
}
|
|
77270
|
+
});
|
|
77271
|
+
}
|
|
77272
|
+
unSelect() {
|
|
77273
|
+
const blocks = this.doc.querySelectorAll(this.selector);
|
|
77274
|
+
blocks.forEach(elm => elm.classList.remove('active'));
|
|
77275
|
+
}
|
|
77276
|
+
}
|
|
77277
|
+
class EditableBlocks {
|
|
77278
|
+
constructor(options = {}) {
|
|
77279
|
+
const defaults = {
|
|
77280
|
+
selector: '.is-block',
|
|
77281
|
+
parentSelector: 'body',
|
|
77282
|
+
// controlSelector: '.is-tool',
|
|
77283
|
+
doc: document,
|
|
77284
|
+
win: window,
|
|
77285
|
+
// onBeforeChange: () => {},
|
|
77286
|
+
// onChange: () => {},
|
|
77287
|
+
// onContentClick: () => {},
|
|
77288
|
+
// onEditStart: () => {},
|
|
77289
|
+
// onEditEnd: () => {},
|
|
77290
|
+
// onDuplicate: () => {},
|
|
77291
|
+
// onSelectBlock: (block) => {},
|
|
77292
|
+
// onUnSelectBlock: () => {},
|
|
77293
|
+
// onMultipleSelect: () => {},
|
|
77294
|
+
disableOnMobile: 0,
|
|
77295
|
+
rotate: true,
|
|
77296
|
+
clone: true
|
|
77297
|
+
// onDelete: () = {}
|
|
77298
|
+
};
|
|
77299
|
+
|
|
77300
|
+
Object.assign(this, defaults, options);
|
|
77301
|
+
this.init();
|
|
77302
|
+
}
|
|
77303
|
+
checkOverlap(target) {
|
|
77304
|
+
return this.common.checkOverlap(target);
|
|
77305
|
+
}
|
|
77306
|
+
forward(target) {
|
|
77307
|
+
let newZIndex;
|
|
77308
|
+
if (!target.style.zIndex) {
|
|
77309
|
+
newZIndex = 1;
|
|
77310
|
+
} else {
|
|
77311
|
+
newZIndex = parseInt(target.style.zIndex) + 1;
|
|
77312
|
+
}
|
|
77313
|
+
target.style.zIndex = newZIndex;
|
|
77314
|
+
}
|
|
77315
|
+
backward(target) {
|
|
77316
|
+
let newZIndex;
|
|
77317
|
+
if (!target.style.zIndex) {
|
|
77318
|
+
newZIndex = 0;
|
|
77319
|
+
} else {
|
|
77320
|
+
if (parseInt(target.style.zIndex) - 1 < 0) newZIndex = 0;else newZIndex = parseInt(target.style.zIndex) - 1;
|
|
77321
|
+
}
|
|
77322
|
+
target.style.zIndex = newZIndex;
|
|
77323
|
+
}
|
|
77324
|
+
selectStart(block) {
|
|
77325
|
+
if (block.classList.contains('is-shape')) return; // do not clone if block is shape
|
|
77326
|
+
|
|
77327
|
+
if (!this.clone) return;
|
|
77328
|
+
const viewportWidth = this.win.innerWidth;
|
|
77329
|
+
if (block.closest('.autolayout') && viewportWidth <= 760) {
|
|
77330
|
+
return;
|
|
77331
|
+
}
|
|
77332
|
+
if (block.classList.contains('is-group')) return; // do not clone if block is shape
|
|
77333
|
+
|
|
77334
|
+
if (!block.classList.contains('clone')) {
|
|
77335
|
+
let clonedDiv = block.cloneNode(true);
|
|
77336
|
+
clonedDiv.classList.add('clone');
|
|
77337
|
+
block.parentNode.appendChild(clonedDiv);
|
|
77338
|
+
block.classList.add('cloned');
|
|
77339
|
+
this.refresh();
|
|
77340
|
+
}
|
|
77341
|
+
}
|
|
77342
|
+
selectClear() {
|
|
77343
|
+
this.doc.querySelectorAll('.clone').forEach(elm => elm.parentNode.removeChild(elm));
|
|
77344
|
+
this.doc.querySelectorAll('.cloned').forEach(elm => elm.classList.remove('cloned'));
|
|
77345
|
+
}
|
|
77346
|
+
setMultiSelect(multiSelect) {
|
|
77347
|
+
if (multiSelect) this.doc.body.classList.add('multi-select');else this.doc.body.classList.remove('multi-select');
|
|
77348
|
+
}
|
|
77349
|
+
init() {
|
|
77350
|
+
this.doc.body.classList.add('editableblocks');
|
|
77351
|
+
this.draggable = new Draggable({
|
|
77352
|
+
selector: this.selector,
|
|
77353
|
+
disableOnMobile: this.disableOnMobile,
|
|
77354
|
+
doc: this.doc,
|
|
77355
|
+
win: this.win,
|
|
77356
|
+
onDelete: element => {
|
|
77357
|
+
if (this.rotatable) this.rotatable.destroy(element);
|
|
77358
|
+
this.resizable.destroy(element);
|
|
77359
|
+
this.editable.destroy(element);
|
|
77360
|
+
if (this.onDelete) this.onDelete();
|
|
77361
|
+
},
|
|
77362
|
+
onBeforeChange: () => {
|
|
77363
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
77364
|
+
},
|
|
77365
|
+
onChange: () => {
|
|
77366
|
+
if (this.onChange) this.onChange();
|
|
77367
|
+
},
|
|
77368
|
+
onMultipleSelect: this.onMultipleSelect,
|
|
77369
|
+
onSelectStart: block => {
|
|
77370
|
+
// for cloning
|
|
77371
|
+
this.selectStart(block);
|
|
77372
|
+
},
|
|
77373
|
+
onSelectClear: () => {
|
|
77374
|
+
// for removing clones
|
|
77375
|
+
this.selectClear();
|
|
77376
|
+
if (this.onUnselectBlock) this.onUnselectBlock();
|
|
77377
|
+
},
|
|
77378
|
+
onSelectBlock: this.onSelectBlock
|
|
77379
|
+
});
|
|
77380
|
+
this.resizable = new Resizable({
|
|
77381
|
+
selector: this.selector,
|
|
77382
|
+
disableOnMobile: this.disableOnMobile,
|
|
77383
|
+
doc: this.doc,
|
|
77384
|
+
win: this.win,
|
|
77385
|
+
onBeforeChange: () => {
|
|
77386
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
77387
|
+
},
|
|
77388
|
+
onChange: () => {
|
|
77389
|
+
if (this.onChange) this.onChange();
|
|
77390
|
+
}
|
|
77391
|
+
});
|
|
77392
|
+
if (this.rotate) {
|
|
77393
|
+
this.rotatable = new Rotatable({
|
|
77394
|
+
selector: this.selector,
|
|
77395
|
+
disableOnMobile: this.disableOnMobile,
|
|
77396
|
+
doc: this.doc,
|
|
77397
|
+
win: this.win,
|
|
77398
|
+
onBeforeChange: () => {
|
|
77399
|
+
if (this.onBeforeChange) this.onBeforeChange();
|
|
77400
|
+
},
|
|
77401
|
+
onChange: () => {
|
|
77402
|
+
if (this.onChange) this.onChange();
|
|
77403
|
+
}
|
|
77404
|
+
});
|
|
77405
|
+
}
|
|
77406
|
+
this.editable = new Editable({
|
|
77407
|
+
selector: this.selector,
|
|
77408
|
+
controlSelector: this.controlSelector,
|
|
77409
|
+
doc: this.doc,
|
|
77410
|
+
win: this.win,
|
|
77411
|
+
onContentClick: this.onContentClick,
|
|
77412
|
+
onEditStart: block => {
|
|
77413
|
+
if (block.classList.contains('clone')) {
|
|
77414
|
+
const clonedTarget = this.doc.querySelector(this.selector + '.cloned');
|
|
77415
|
+
this.onEditStart(clonedTarget);
|
|
77416
|
+
this.selectClear();
|
|
77417
|
+
|
|
77418
|
+
// Disable drag during editing
|
|
77419
|
+
if (!this.draggable) return;
|
|
77420
|
+
this.draggable.disableDrag(clonedTarget);
|
|
77421
|
+
return;
|
|
77422
|
+
}
|
|
77423
|
+
this.onEditStart(block);
|
|
77424
|
+
|
|
77425
|
+
// Disable drag during editing
|
|
77426
|
+
if (!this.draggable) return;
|
|
77427
|
+
this.draggable.disableDrag(block);
|
|
77428
|
+
},
|
|
77429
|
+
onEditEnd: block => {
|
|
77430
|
+
this.onEditEnd(block);
|
|
77431
|
+
|
|
77432
|
+
// Enable drag
|
|
77433
|
+
if (!this.draggable) return;
|
|
77434
|
+
this.draggable.enableDrag(block);
|
|
77435
|
+
}
|
|
77436
|
+
});
|
|
77437
|
+
this.blockSelector = new BlockSelector({
|
|
77438
|
+
selector: this.selector,
|
|
77439
|
+
parentSelector: this.parentSelector,
|
|
77440
|
+
disableOnMobile: this.disableOnMobile,
|
|
77441
|
+
onMultipleSelect: this.onMultipleSelect,
|
|
77442
|
+
doc: this.doc,
|
|
77443
|
+
win: this.win
|
|
77444
|
+
});
|
|
77445
|
+
this.common = new Common({
|
|
77446
|
+
selector: this.selector,
|
|
77447
|
+
doc: this.doc,
|
|
77448
|
+
win: this.win,
|
|
77449
|
+
onDuplicate: this.onDuplicate
|
|
77450
|
+
});
|
|
77451
|
+
}
|
|
77452
|
+
duplicate() {
|
|
77453
|
+
this.common.duplicate();
|
|
77454
|
+
this.refresh();
|
|
77455
|
+
}
|
|
77456
|
+
delete() {
|
|
77457
|
+
this.draggable.delete();
|
|
77458
|
+
}
|
|
77459
|
+
getBreakpoints(block) {
|
|
77460
|
+
return this.common.getBreakpoints(block);
|
|
77461
|
+
}
|
|
77462
|
+
placeCursorAtEnd(block) {
|
|
77463
|
+
this.editable.placeCursorAtEnd(block);
|
|
77464
|
+
}
|
|
77465
|
+
quitEditable(block) {
|
|
77466
|
+
this.editable.quitEditable(block);
|
|
77467
|
+
}
|
|
77468
|
+
destroy() {
|
|
77469
|
+
if (!this.draggable) return;
|
|
77470
|
+
this.draggable.destroy();
|
|
77471
|
+
this.resizable.destroy();
|
|
77472
|
+
if (this.rotatable) this.rotatable.destroy();
|
|
77473
|
+
this.editable.destroy();
|
|
77474
|
+
this.blockSelector.destroy();
|
|
77475
|
+
this.draggable = null;
|
|
77476
|
+
this.doc.body.classList.remove('editableblocks');
|
|
77477
|
+
}
|
|
77478
|
+
refresh() {
|
|
77479
|
+
// Call refresh() whenever blocks are added
|
|
77480
|
+
this.draggable.refresh();
|
|
77481
|
+
this.resizable.refresh();
|
|
77482
|
+
if (this.rotatable) this.rotatable.refresh();
|
|
77483
|
+
this.editable.refresh();
|
|
77484
|
+
}
|
|
77485
|
+
addBlock(html, container) {
|
|
77486
|
+
this.selectClear(); // clear clones
|
|
77487
|
+
this.blockSelector.unSelect(); // clear active
|
|
77488
|
+
|
|
77489
|
+
const parser = new DOMParser();
|
|
77490
|
+
let doc = parser.parseFromString(html, 'text/html');
|
|
77491
|
+
const block = doc.querySelector('.is-block');
|
|
77492
|
+
block.classList.add('block-dummy');
|
|
77493
|
+
html = doc.body.innerHTML;
|
|
77494
|
+
container.insertAdjacentHTML('beforeend', html);
|
|
77495
|
+
const newBlock = document.querySelector('.block-dummy');
|
|
77496
|
+
if (newBlock) {
|
|
77497
|
+
newBlock.classList.remove('block-dummy');
|
|
77498
|
+
if (this.onAddBlock) this.onAddBlock(newBlock);
|
|
77499
|
+
newBlock.classList.add('active');
|
|
77500
|
+
}
|
|
77501
|
+
this.refresh();
|
|
77502
|
+
}
|
|
77503
|
+
group() {
|
|
77504
|
+
const group = this.common.group('is-block', 'is-group');
|
|
77505
|
+
this.refresh();
|
|
77506
|
+
return group;
|
|
77507
|
+
}
|
|
77508
|
+
unGroup() {
|
|
77509
|
+
this.common.unGroup();
|
|
77510
|
+
}
|
|
77511
|
+
addBreakpoint() {
|
|
77512
|
+
this.common.addBreakpoint();
|
|
77513
|
+
}
|
|
77514
|
+
clearBreakpoint(target) {
|
|
77515
|
+
this.common.clearBreakpoint(target);
|
|
77516
|
+
if (target.classList.contains('cloned')) {
|
|
77517
|
+
const cloneTarget = this.doc.querySelector(this.selector + '.clone');
|
|
77518
|
+
this.common.clearBreakpoint(cloneTarget);
|
|
77519
|
+
}
|
|
77520
|
+
}
|
|
77521
|
+
clearAllBreakpoints(container) {
|
|
77522
|
+
this.common.clearAllBreakpoints(container);
|
|
77523
|
+
}
|
|
77524
|
+
isMultiSelect() {
|
|
77525
|
+
// Check if multiple selection occurs. If so, add 'multi' class to hide all the handles
|
|
77526
|
+
let blocks = Array.from(this.doc.querySelectorAll(this.selector)).filter(elm => elm.classList.contains('active') && !elm.classList.contains('clone'));
|
|
77527
|
+
if (blocks.length > 1) return true;
|
|
77528
|
+
return false;
|
|
77529
|
+
}
|
|
77530
|
+
}
|
|
75405
77531
|
|
|
75406
77532
|
class ContentBuilder {
|
|
75407
77533
|
constructor(opts = {}) {
|
|
@@ -75630,6 +77756,7 @@ class ContentBuilder {
|
|
|
75630
77756
|
customval: '',
|
|
75631
77757
|
moduleConfig: [],
|
|
75632
77758
|
elementAnimate: false,
|
|
77759
|
+
cleanAOS: false,
|
|
75633
77760
|
framework: '',
|
|
75634
77761
|
cellFormat: '',
|
|
75635
77762
|
rowFormat: '',
|
|
@@ -75641,9 +77768,11 @@ class ContentBuilder {
|
|
|
75641
77768
|
defaultEmailSnippetCategory: 14,
|
|
75642
77769
|
undoRedoStyles: false,
|
|
75643
77770
|
// specialElementClasses: ['sl-wrapper', 'sl-overlay'] // specify elements that when clicked will not affect the builder interface (active selection). Usefull for external code, ex lightbox, etc.
|
|
75644
|
-
// onUndo: function () { },
|
|
75645
|
-
// onRedo: function () { }
|
|
75646
77771
|
|
|
77772
|
+
// freeform
|
|
77773
|
+
onUndo: function () {},
|
|
77774
|
+
onRedo: function () {},
|
|
77775
|
+
onBlockCanvasAdd: function () {},
|
|
75647
77776
|
/*
|
|
75648
77777
|
Deprecated:
|
|
75649
77778
|
snippetSampleImage: '',
|
|
@@ -76525,6 +78654,26 @@ class ContentBuilder {
|
|
|
76525
78654
|
this.colTool.lockIndicator.style.display = '';
|
|
76526
78655
|
return ret;
|
|
76527
78656
|
};
|
|
78657
|
+
|
|
78658
|
+
// freeform
|
|
78659
|
+
let oldOnBlockCanvasAdd = this.opts.onBlockCanvasAdd;
|
|
78660
|
+
this.opts.onBlockCanvasAdd = () => {
|
|
78661
|
+
let ret = oldOnBlockCanvasAdd.apply(this, arguments);
|
|
78662
|
+
if (this.eb) this.eb.refresh();
|
|
78663
|
+
return ret;
|
|
78664
|
+
};
|
|
78665
|
+
let oldOnUndo = this.opts.onUndo;
|
|
78666
|
+
this.opts.onUndo = () => {
|
|
78667
|
+
let ret = oldOnUndo.apply(this, arguments);
|
|
78668
|
+
if (this.eb) this.eb.refresh();
|
|
78669
|
+
return ret;
|
|
78670
|
+
};
|
|
78671
|
+
let oldOnRedo = this.opts.onRedo;
|
|
78672
|
+
this.opts.onRedo = () => {
|
|
78673
|
+
let ret = oldOnRedo.apply(this, arguments);
|
|
78674
|
+
if (this.eb) this.eb.refresh();
|
|
78675
|
+
return ret;
|
|
78676
|
+
};
|
|
76528
78677
|
this.elmTool = new ElementTool(this); // Render Element Tool
|
|
76529
78678
|
|
|
76530
78679
|
// Render controls or behavior for handling element editing
|
|
@@ -76592,6 +78741,68 @@ class ContentBuilder {
|
|
|
76592
78741
|
}
|
|
76593
78742
|
*/
|
|
76594
78743
|
|
|
78744
|
+
// freeform
|
|
78745
|
+
if (this.canvas) this.eb = new EditableBlocks({
|
|
78746
|
+
doc: this.doc,
|
|
78747
|
+
win: this.win,
|
|
78748
|
+
selector: '.is-block',
|
|
78749
|
+
controlSelector: '.is-tool,.is-pop,.is-modal,#divImageResizer,.is-rte-tool,is-elementrte-tool,.is-rte-pop,.keep-selection',
|
|
78750
|
+
parentSelector: '.box-canvas',
|
|
78751
|
+
rotate: true,
|
|
78752
|
+
// disableOnMobile: 760,
|
|
78753
|
+
onBeforeChange: () => {
|
|
78754
|
+
this.uo.saveForUndo();
|
|
78755
|
+
},
|
|
78756
|
+
onChange: () => {
|
|
78757
|
+
this.opts.onChange();
|
|
78758
|
+
},
|
|
78759
|
+
onEditStart: block => {
|
|
78760
|
+
block.classList.add('editable');
|
|
78761
|
+
const cols = block.querySelectorAll('[data-click="true"]'); // or [contentEditable="true"]
|
|
78762
|
+
if (cols.length > 0) {
|
|
78763
|
+
let col = cols[cols.length - 1];
|
|
78764
|
+
if (col.lastElementChild) col.lastElementChild.click();
|
|
78765
|
+
}
|
|
78766
|
+
},
|
|
78767
|
+
onEditEnd: block => {
|
|
78768
|
+
block.classList.remove('editable');
|
|
78769
|
+
this.util.clearActiveCell();
|
|
78770
|
+
this.util.clearPops();
|
|
78771
|
+
this.hideElementTools();
|
|
78772
|
+
},
|
|
78773
|
+
onDuplicate: block => {
|
|
78774
|
+
const builder = block.querySelector(this.container);
|
|
78775
|
+
let html = '';
|
|
78776
|
+
if (builder) {
|
|
78777
|
+
html = this.readHtml(builder);
|
|
78778
|
+
}
|
|
78779
|
+
let clonedDiv = block.cloneNode(true);
|
|
78780
|
+
clonedDiv.style.top = '20%';
|
|
78781
|
+
clonedDiv.style.left = '20%';
|
|
78782
|
+
if (builder) {
|
|
78783
|
+
const cloneBuilder = clonedDiv.querySelector(this.container);
|
|
78784
|
+
cloneBuilder.innerHTML = '';
|
|
78785
|
+
block.parentNode.appendChild(clonedDiv);
|
|
78786
|
+
const range = document.createRange();
|
|
78787
|
+
cloneBuilder.appendChild(range.createContextualFragment(html));
|
|
78788
|
+
this.applyBehaviorOn(cloneBuilder);
|
|
78789
|
+
cloneBuilder.click();
|
|
78790
|
+
} else {
|
|
78791
|
+
block.parentNode.appendChild(clonedDiv);
|
|
78792
|
+
}
|
|
78793
|
+
block.classList.remove('active');
|
|
78794
|
+
this.doc.querySelectorAll('.clone').forEach(elm => elm.parentNode.removeChild(elm));
|
|
78795
|
+
this.doc.querySelectorAll('.cloned').forEach(elm => elm.classList.remove('cloned'));
|
|
78796
|
+
},
|
|
78797
|
+
onAddBlock: block => {
|
|
78798
|
+
const builder = block.querySelector(this.container);
|
|
78799
|
+
this.applyBehaviorOn(builder);
|
|
78800
|
+
},
|
|
78801
|
+
onMultipleSelect: this.onMultipleSelect,
|
|
78802
|
+
onDelete: this.onDelete,
|
|
78803
|
+
onSelectBlock: this.onSelectBlock,
|
|
78804
|
+
onUnselectBlock: this.onUnselectBlock
|
|
78805
|
+
});
|
|
76595
78806
|
if (this.iframe) {
|
|
76596
78807
|
this.win.addEventListener('scroll', this.doWindowScroll = () => {
|
|
76597
78808
|
this.util.hidePops();
|
|
@@ -77412,6 +79623,13 @@ class ContentBuilder {
|
|
|
77412
79623
|
this.setZoomOnControl(builder);
|
|
77413
79624
|
}
|
|
77414
79625
|
html(area) {
|
|
79626
|
+
if (this.docContainer) {
|
|
79627
|
+
// freeform
|
|
79628
|
+
|
|
79629
|
+
const docContainer = this.doc.querySelector(this.docContainer);
|
|
79630
|
+
const html = this.readHtml(docContainer, false, true);
|
|
79631
|
+
return html;
|
|
79632
|
+
}
|
|
77415
79633
|
const util = this.util;
|
|
77416
79634
|
const htmlutil = new HtmlUtil(this);
|
|
77417
79635
|
if (area) ; else {
|
|
@@ -77478,7 +79696,87 @@ class ContentBuilder {
|
|
|
77478
79696
|
simpleColorPicker(onPick, mode) {
|
|
77479
79697
|
return this.colorClassPicker.open(onPick, mode);
|
|
77480
79698
|
}
|
|
79699
|
+
|
|
79700
|
+
// freeform
|
|
79701
|
+
refresh() {
|
|
79702
|
+
if (this.eb) this.eb.refresh();
|
|
79703
|
+
}
|
|
79704
|
+
group() {
|
|
79705
|
+
if (!this.eb) return;
|
|
79706
|
+
this.uo.saveForUndo();
|
|
79707
|
+
this.eb.group();
|
|
79708
|
+
this.opts.onChange();
|
|
79709
|
+
}
|
|
79710
|
+
unGroup() {
|
|
79711
|
+
if (!this.eb) return;
|
|
79712
|
+
this.uo.saveForUndo();
|
|
79713
|
+
this.eb.unGroup();
|
|
79714
|
+
this.opts.onChange();
|
|
79715
|
+
}
|
|
79716
|
+
delete() {
|
|
79717
|
+
if (!this.eb) return;
|
|
79718
|
+
this.uo.saveForUndo();
|
|
79719
|
+
this.eb.delete();
|
|
79720
|
+
this.opts.onChange();
|
|
79721
|
+
}
|
|
79722
|
+
forward(target) {
|
|
79723
|
+
if (!this.eb) return;
|
|
79724
|
+
this.uo.saveForUndo();
|
|
79725
|
+
this.eb.forward(target);
|
|
79726
|
+
this.opts.onChange();
|
|
79727
|
+
}
|
|
79728
|
+
backward(target) {
|
|
79729
|
+
if (!this.eb) return;
|
|
79730
|
+
this.uo.saveForUndo();
|
|
79731
|
+
this.eb.backward(target);
|
|
79732
|
+
this.opts.onChange();
|
|
79733
|
+
}
|
|
79734
|
+
enableShape() {
|
|
79735
|
+
if (!this.eb) return;
|
|
79736
|
+
this.uo.saveForUndo();
|
|
79737
|
+
this.eb.enableShape();
|
|
79738
|
+
this.opts.onChange();
|
|
79739
|
+
}
|
|
79740
|
+
removeShape() {
|
|
79741
|
+
if (!this.eb) return;
|
|
79742
|
+
this.uo.saveForUndo();
|
|
79743
|
+
this.eb.removeShape();
|
|
79744
|
+
this.opts.onChange();
|
|
79745
|
+
}
|
|
79746
|
+
addBlock(html, blockContainer) {
|
|
79747
|
+
if (!this.eb) return;
|
|
79748
|
+
this.uo.saveForUndo();
|
|
79749
|
+
this.eb.addBlock(html, blockContainer);
|
|
79750
|
+
this.opts.onChange();
|
|
79751
|
+
this.opts.onRender();
|
|
79752
|
+
}
|
|
79753
|
+
duplicate() {
|
|
79754
|
+
if (!this.eb) return;
|
|
79755
|
+
this.uo.saveForUndo();
|
|
79756
|
+
this.eb.duplicate();
|
|
79757
|
+
this.opts.onChange();
|
|
79758
|
+
this.opts.onRender();
|
|
79759
|
+
}
|
|
79760
|
+
addBreakpoint() {
|
|
79761
|
+
if (!this.eb) return;
|
|
79762
|
+
this.eb.addBreakpoint();
|
|
79763
|
+
}
|
|
79764
|
+
getBreakpoints(target) {
|
|
79765
|
+
if (!this.eb) return;
|
|
79766
|
+
return this.eb.getBreakpoints(target);
|
|
79767
|
+
}
|
|
79768
|
+
clearBreakpoint(target) {
|
|
79769
|
+
if (!this.eb) return;
|
|
79770
|
+
this.uo.saveForUndo();
|
|
79771
|
+
this.eb.clearBreakpoint(target);
|
|
79772
|
+
this.opts.onChange();
|
|
79773
|
+
}
|
|
79774
|
+
quitEditable(target) {
|
|
79775
|
+
if (!this.eb) return;
|
|
79776
|
+
this.eb.quitEditable(target);
|
|
79777
|
+
}
|
|
77481
79778
|
destroy() {
|
|
79779
|
+
if (this.eb) this.eb.destroy();
|
|
77482
79780
|
this.doc.body.classList.remove('data-editor');
|
|
77483
79781
|
document.removeEventListener('click', this.doDocumentClick, false);
|
|
77484
79782
|
document.removeEventListener('keydown', this.doDocumentKeydown, false);
|
|
@@ -78100,7 +80398,7 @@ class ContentBuilder {
|
|
|
78100
80398
|
this.opts.onPluginsLoaded();
|
|
78101
80399
|
}
|
|
78102
80400
|
this.tooltip.setAll();
|
|
78103
|
-
new Draggable$
|
|
80401
|
+
new Draggable$2({
|
|
78104
80402
|
selector: '.is-draggable'
|
|
78105
80403
|
}); //draggable for plugins
|
|
78106
80404
|
|
|
@@ -78161,7 +80459,7 @@ class ContentBuilder {
|
|
|
78161
80459
|
this.opts.onPluginsLoaded();
|
|
78162
80460
|
}
|
|
78163
80461
|
this.tooltip.setAll();
|
|
78164
|
-
new Draggable$
|
|
80462
|
+
new Draggable$2({
|
|
78165
80463
|
selector: '.is-draggable'
|
|
78166
80464
|
}); //draggable for plugins
|
|
78167
80465
|
|
|
@@ -78317,7 +80615,7 @@ class ContentBuilder {
|
|
|
78317
80615
|
}
|
|
78318
80616
|
|
|
78319
80617
|
draggable(selector) {
|
|
78320
|
-
new Draggable$
|
|
80618
|
+
new Draggable$2({
|
|
78321
80619
|
selector: selector
|
|
78322
80620
|
});
|
|
78323
80621
|
}
|
|
@@ -78328,7 +80626,7 @@ class ContentBuilder {
|
|
|
78328
80626
|
embeddedModal = this.builderStuff.querySelector(selector);
|
|
78329
80627
|
}
|
|
78330
80628
|
this.showModal(embeddedModal, overlayStay, cancelCallback, animated, overflowHidden);
|
|
78331
|
-
new Draggable$
|
|
80629
|
+
new Draggable$2({
|
|
78332
80630
|
selector: '.is-draggable'
|
|
78333
80631
|
});
|
|
78334
80632
|
return embeddedModal;
|
|
@@ -78454,6 +80752,10 @@ class ContentBuilder {
|
|
|
78454
80752
|
// /Plugins related
|
|
78455
80753
|
|
|
78456
80754
|
viewHtml(area) {
|
|
80755
|
+
if (this.docContainer) {
|
|
80756
|
+
// freeform
|
|
80757
|
+
area = this.doc.querySelector(this.docContainer);
|
|
80758
|
+
}
|
|
78457
80759
|
const htmlutil = new HtmlUtil(this);
|
|
78458
80760
|
htmlutil.view('full', area);
|
|
78459
80761
|
}
|
|
@@ -78500,6 +80802,20 @@ class ContentBuilder {
|
|
|
78500
80802
|
return false;
|
|
78501
80803
|
}
|
|
78502
80804
|
loadHtml(html, area) {
|
|
80805
|
+
if (this.docContainer) {
|
|
80806
|
+
// freeform
|
|
80807
|
+
const docContainer = this.doc.querySelector(this.docContainer);
|
|
80808
|
+
let range = this.doc.createRange();
|
|
80809
|
+
docContainer.innerHTML = '';
|
|
80810
|
+
docContainer.appendChild(range.createContextualFragment(html)); // We use createContextualFragment so that embedded javascript code (code block) will be executed
|
|
80811
|
+
|
|
80812
|
+
const builders = docContainer.querySelectorAll(this.container);
|
|
80813
|
+
builders.forEach(builder => {
|
|
80814
|
+
this.applyBehaviorOn(builder);
|
|
80815
|
+
});
|
|
80816
|
+
this.refresh();
|
|
80817
|
+
return;
|
|
80818
|
+
}
|
|
78503
80819
|
const util = this.util;
|
|
78504
80820
|
if (area) ; else {
|
|
78505
80821
|
const builders = this.doc.querySelectorAll(this.opts.container);
|
|
@@ -78558,6 +80874,7 @@ class ContentBuilder {
|
|
|
78558
80874
|
// }
|
|
78559
80875
|
loadHTML(html) {
|
|
78560
80876
|
//backward
|
|
80877
|
+
|
|
78561
80878
|
this.loadHtml(html);
|
|
78562
80879
|
}
|
|
78563
80880
|
async setUIColor(mode, csslink) {
|