@innovastudio/contentbuilder 1.4.124 → 1.4.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbuilder",
3
3
  "type": "module",
4
- "version": "1.4.124",
4
+ "version": "1.4.125",
5
5
  "description": "",
6
6
  "main": "public/contentbuilder/contentbuilder.esm.js",
7
7
  "files": [
@@ -3592,7 +3592,7 @@ class Dom {
3592
3592
  }
3593
3593
  }
3594
3594
  let blocks = [];
3595
- const blockElms = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'pre'];
3595
+ const blockElms = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'pre', 'td', 'th'];
3596
3596
  elements.forEach(item => {
3597
3597
  const tagName = item.tagName.toLowerCase();
3598
3598
  if (blockElms.includes(tagName)) {
@@ -76867,8 +76867,10 @@ class ContentBuilder {
76867
76867
  // ON PASTE
76868
76868
  // col.addEventListener('paste', this.handleCellPaste.bind(this));
76869
76869
  col.addEventListener('paste', e => {
76870
- const clipboardData = (e.clipboardData || window.clipboardData).getData('text');
76871
- this.handleCellPaste(clipboardData);
76870
+ e.preventDefault();
76871
+ const clipboardDataText = (e.clipboardData || window.clipboardData).getData('text');
76872
+ const clipboardDataHtml = (e.clipboardData || window.clipboardData).getData('text/html');
76873
+ this.handleCellPaste(clipboardDataText, clipboardDataHtml);
76872
76874
  });
76873
76875
  col.setAttribute('data-click', true);
76874
76876
  }
@@ -79046,6 +79048,7 @@ class ContentBuilder {
79046
79048
  // CMD-B
79047
79049
 
79048
79050
  if (this.opts.useCssClasses) {
79051
+ this.uo.saveForUndo();
79049
79052
  this.dom.execCommandToggle('fontWeight', '', this.opts.cssClasses);
79050
79053
  this.opts.onChange();
79051
79054
  e.preventDefault();
@@ -79056,6 +79059,7 @@ class ContentBuilder {
79056
79059
  // CMD-I
79057
79060
 
79058
79061
  if (this.opts.useCssClasses) {
79062
+ this.uo.saveForUndo();
79059
79063
  this.dom.execCommandToggle('fontStyle', '', this.opts.cssClasses);
79060
79064
  this.opts.onChange();
79061
79065
  e.preventDefault();
@@ -79066,6 +79070,7 @@ class ContentBuilder {
79066
79070
  // CMD-U
79067
79071
 
79068
79072
  if (this.opts.useCssClasses) {
79073
+ this.uo.saveForUndo();
79069
79074
  this.dom.execCommandToggle('textUnderline', '', this.opts.cssClasses);
79070
79075
  this.opts.onChange();
79071
79076
  e.preventDefault();
@@ -79076,6 +79081,7 @@ class ContentBuilder {
79076
79081
  // CMD-S
79077
79082
 
79078
79083
  if (this.opts.useCssClasses) {
79084
+ this.uo.saveForUndo();
79079
79085
  this.dom.execCommandToggle('textLinethrough', '', this.opts.cssClasses);
79080
79086
  this.opts.onChange();
79081
79087
  e.preventDefault();
@@ -79083,6 +79089,8 @@ class ContentBuilder {
79083
79089
  }
79084
79090
  }
79085
79091
  if (isCmd && e.which === 221) {
79092
+ this.uo.saveForUndo();
79093
+
79086
79094
  // CMD-]
79087
79095
  e.preventDefault();
79088
79096
  document.execCommand('indent', false, null);
@@ -79091,6 +79099,8 @@ class ContentBuilder {
79091
79099
  markSpan();
79092
79100
  }
79093
79101
  if (isCmd && e.which === 219) {
79102
+ this.uo.saveForUndo();
79103
+
79094
79104
  // CMD-]
79095
79105
  e.preventDefault();
79096
79106
  document.execCommand('outdent', false, null);
@@ -79322,307 +79332,288 @@ class ContentBuilder {
79322
79332
  this.opts.onChange();
79323
79333
  }, 2000);
79324
79334
  }
79325
- handleCellPaste(clipboardData) {
79335
+ handleCellPaste(clipboardData, clipboardDataHtml) {
79326
79336
  this.uo.saveForUndo();
79327
79337
  const util = this.util;
79328
79338
  util.saveSelection(); //required. Without this, CTRL-A (select element) & CTRL-V won't replace the element, but will paste at the end of the element.
79329
79339
 
79330
- let contentword = this.doc.querySelector('#idContentWord');
79331
- if (contentword) contentword.parentNode.removeChild(contentword);
79332
- var el;
79333
- var curr;
79334
- if (this.win.getSelection) {
79335
- curr = this.win.getSelection().getRangeAt(0).commonAncestorContainer;
79336
- if (curr.nodeType === 3) {
79337
- //ini text node
79338
- el = curr.parentNode;
79339
- } else {
79340
- el = curr;
79341
- }
79342
- } else if (this.doc.selection) {
79343
- curr = this.doc.selection.createRange();
79344
- el = this.doc.selection.createRange().parentElement();
79345
- }
79346
- var tmptop = el.getBoundingClientRect().top + this.win.pageYOffset;
79347
- const html = '<div style="position:absolute;z-index:-1000;top:' + tmptop + 'px;left:-1000px;width:100px;height:100px;overflow:auto;" name="idContentWord" id="idContentWord" contenteditable="true"></div>';
79348
- if (!this.iframe) {
79349
- this.dom.appendHtml(this.builderStuff, html);
79350
- } else {
79351
- this.dom.appendHtml(this.contentStuff, html);
79352
- }
79353
- contentword = this.doc.querySelector('#idContentWord');
79354
- contentword.focus();
79355
- setTimeout(() => {
79356
- try {
79357
- var sPastedText = '';
79358
- let contentword = this.doc.querySelector('#idContentWord');
79359
-
79360
- //Check video embed
79361
- var bPasteObject = false;
79362
- var src = contentword.innerText;
79363
- if (!this.opts.disableAutoEmbedVideo) {
79364
- //var youRegex = /^http[s]?:\/\/(((www.youtube.com\/watch\?(feature=player_detailpage&)?)v=)|(youtu.be\/))([^#\&\?]*)/;
79365
- var youRegex = /^http[s]?:\/\/(((www.youtube.com\/watch\?(feature=player_detailpage&)?)v=)|(youtu.be\/))([^#&?]*)/;
79366
- var vimeoRegex = /^.*(vimeo\.com\/)((channels\/[A-z]+\/)|(groups\/[A-z]+\/videos\/)|(video\/))?([0-9]+)\/?/;
79367
- var youRegexMatches = youRegex.exec(src);
79368
- var vimeoRegexMatches = vimeoRegex.exec(src);
79369
- if (youRegexMatches !== null || vimeoRegexMatches !== null) {
79370
- if (youRegexMatches !== null && youRegexMatches.length >= 7) {
79371
- var youMatch = youRegexMatches[6];
79372
- src = 'https://www.youtube.com/embed/' + youMatch + '?rel=0';
79373
- }
79374
- if (vimeoRegexMatches !== null && vimeoRegexMatches.length >= 7) {
79375
- var vimeoMatch = vimeoRegexMatches[6];
79376
- src = 'https://player.vimeo.com/video/' + vimeoMatch;
79377
- }
79378
- sPastedText = '<div class="embed-responsive embed-responsive-16by9"><iframe tabindex="0" width="560" height="315" src="' + src + '" frameborder="0" allowfullscreen=""></iframe></div>';
79379
- bPasteObject = true;
79340
+ // Create a temporary div to hold the pasted HTML
79341
+ let contentword = document.createElement('div');
79342
+ contentword.innerHTML = clipboardDataHtml;
79343
+ try {
79344
+ var sPastedText = '';
79345
+
79346
+ //Check video embed
79347
+ var bPasteObject = false;
79348
+ var src = contentword.innerText;
79349
+ if (!this.opts.disableAutoEmbedVideo) {
79350
+ //var youRegex = /^http[s]?:\/\/(((www.youtube.com\/watch\?(feature=player_detailpage&)?)v=)|(youtu.be\/))([^#\&\?]*)/;
79351
+ var youRegex = /^http[s]?:\/\/(((www.youtube.com\/watch\?(feature=player_detailpage&)?)v=)|(youtu.be\/))([^#&?]*)/;
79352
+ var vimeoRegex = /^.*(vimeo\.com\/)((channels\/[A-z]+\/)|(groups\/[A-z]+\/videos\/)|(video\/))?([0-9]+)\/?/;
79353
+ var youRegexMatches = youRegex.exec(src);
79354
+ var vimeoRegexMatches = vimeoRegex.exec(src);
79355
+ if (youRegexMatches !== null || vimeoRegexMatches !== null) {
79356
+ if (youRegexMatches !== null && youRegexMatches.length >= 7) {
79357
+ var youMatch = youRegexMatches[6];
79358
+ src = 'https://www.youtube.com/embed/' + youMatch + '?rel=0';
79359
+ }
79360
+ if (vimeoRegexMatches !== null && vimeoRegexMatches.length >= 7) {
79361
+ var vimeoMatch = vimeoRegexMatches[6];
79362
+ src = 'https://player.vimeo.com/video/' + vimeoMatch;
79380
79363
  }
79364
+ sPastedText = '<div class="embed-responsive embed-responsive-16by9"><iframe tabindex="0" width="560" height="315" src="' + src + '" frameborder="0" allowfullscreen=""></iframe></div>';
79365
+ bPasteObject = true;
79381
79366
  }
79382
- if (!bPasteObject) {
79383
- if (this.opts.paste === 'text') {
79384
- /*
79385
- let elms = contentword.querySelectorAll('p,h1,h2,h3,h4,h5,h6');
79386
- Array.prototype.forEach.call(elms, (elm) => {
79387
- elm.innerHTML = elm.innerHTML + ' '; //add space (&nbsp;)
79388
- });
79389
- // sPastedText = contentword.innerText;
79390
- sPastedText = contentword.innerHTML;
79391
- sPastedText = sPastedText.replace(/(<([^>]+)>)/ig,'<br>');
79392
- sPastedText = sPastedText.replace(/(<br\s*\/?>){3,}/gi, '<br>');
79393
- if(sPastedText.indexOf('<br>')===0) {
79394
- sPastedText = sPastedText.substring(4);
79395
- }
79396
- if(sPastedText.substring(sPastedText.length-4)==='<br>'){
79397
- sPastedText = sPastedText.substring(0, sPastedText.length-4);
79398
- }
79399
- sPastedText = sPastedText.trim();
79400
- */
79367
+ }
79368
+ if (!bPasteObject) {
79369
+ if (this.opts.paste === 'text') {
79370
+ /*
79371
+ let elms = contentword.querySelectorAll('p,h1,h2,h3,h4,h5,h6');
79372
+ Array.prototype.forEach.call(elms, (elm) => {
79373
+ elm.innerHTML = elm.innerHTML + ' '; //add space (&nbsp;)
79374
+ });
79375
+ // sPastedText = contentword.innerText;
79376
+ sPastedText = contentword.innerHTML;
79377
+ sPastedText = sPastedText.replace(/(<([^>]+)>)/ig,'<br>');
79378
+ sPastedText = sPastedText.replace(/(<br\s*\/?>){3,}/gi, '<br>');
79379
+ if(sPastedText.indexOf('<br>')===0) {
79380
+ sPastedText = sPastedText.substring(4);
79381
+ }
79382
+ if(sPastedText.substring(sPastedText.length-4)==='<br>'){
79383
+ sPastedText = sPastedText.substring(0, sPastedText.length-4);
79384
+ }
79385
+ sPastedText = sPastedText.trim();
79386
+ */
79401
79387
 
79402
- sPastedText = clipboardData;
79403
- // sPastedText = sPastedText.replace(/(?:\r\n|\r|\n)/g, '<br>');
79388
+ sPastedText = clipboardData;
79389
+ // sPastedText = sPastedText.replace(/(?:\r\n|\r|\n)/g, '<br>');
79390
+ } else {
79391
+ sPastedText = contentword.innerHTML;
79392
+ if (this.opts.paste === 'html') {
79393
+ //with styles
79394
+ sPastedText = util.cleanHTML(sPastedText, false);
79404
79395
  } else {
79405
- sPastedText = contentword.innerHTML;
79406
- if (this.opts.paste === 'html') {
79407
- //with styles
79408
- sPastedText = util.cleanHTML(sPastedText, false);
79409
- } else {
79410
- //html-without-styles (default)
79411
- sPastedText = util.cleanHTML(sPastedText, true);
79412
- }
79413
- contentword.innerHTML = sPastedText;
79414
-
79415
- /*
79416
- // remove attributes
79417
- if(this.opts.paste === 'html'){//with styles
79418
- let elms = contentword.querySelectorAll('*');
79419
- Array.prototype.forEach.call(elms, (elm) => {
79420
- for(let n = 0;n<elm.attributes.length;n++) {
79421
- if(elm.attributes[n].name!=='style') elm.removeAttribute(elm.attributes[n].name);
79422
- }
79423
- });
79424
- } else { //html-without-styles (default)
79425
-
79426
- const removeAttributes = (element) => {
79427
- while (element.attributes.length > 0) {
79428
- element.removeAttribute(element.attributes[0].name);
79429
- }
79430
- };
79431
- let elms = contentword.querySelectorAll('*');
79432
- Array.prototype.forEach.call(elms, (elm) => {
79433
- removeAttributes(elm);
79434
- });
79435
- }
79436
- */
79437
-
79438
- /*
79439
- Additional Cleanup:
79440
- - Remove p inside li
79441
- - Remove li with white-space: pre
79442
- */
79443
- let elms = contentword.querySelectorAll('li');
79444
- Array.prototype.forEach.call(elms, elm => {
79445
- elm.style.whiteSpace = '';
79446
- const childNodes = elm.childNodes;
79447
- let i = childNodes.length;
79448
- while (i--) {
79449
- if (childNodes[i].tagName === 'P') {
79450
- childNodes[i].outerHTML = childNodes[i].innerHTML;
79451
- }
79452
- }
79453
- });
79454
-
79455
- // NOTE: paste <h1><p> jadi nempel
79456
-
79457
- // // Source: https://gist.github.com/sbrin/6801034
79458
- // jQuery('p', $editor).each(function(){
79459
- // var str = jQuery(this).attr('style');
79460
- // var matches = /mso-list:\w+ \w+([0-9]+)/.exec(str);
79461
- // if (matches) {
79462
- // jQuery(this).data('_listLevel', parseInt(matches[1], 10));
79463
- // }
79464
- // });
79465
- // var last_level=0;
79466
- // var pnt = null;
79467
- // jQuery('p', $editor).each(function(){
79468
- // var cur_level = jQuery(this).data('_listLevel');
79469
- // if(cur_level !== undefined){
79470
- // var txt = jQuery(this).text();
79471
- // var list_tag = '<ul></ul>';
79472
- // if (/^\s*\w+\./.test(txt)) {
79473
- // var matches = /([0-9])\./.exec(txt);
79474
- // if (matches) {
79475
- // var start = parseInt(matches[1], 10);
79476
- // list_tag = start>1 ? '<ol start="' + start + '"></ol>' : '<ol></ol>';
79477
- // }else{
79478
- // list_tag = '<ol></ol>';
79479
- // }
79480
- // }
79481
-
79482
- // if(cur_level>last_level){
79483
- // if(last_level===0){
79484
- // jQuery(this).before(list_tag);
79485
- // pnt = jQuery(this).prev();
79486
- // }else{
79487
- // pnt = jQuery(list_tag).appendTo(pnt);
79488
- // }
79489
- // }
79490
- // if(cur_level<last_level){
79491
- // for(var i=0; i<last_level-cur_level; i++){
79492
- // pnt = pnt.parent();
79493
- // }
79494
- // }
79495
- // jQuery('span:first', this).remove();
79496
- // pnt.append('<li>' + jQuery(this).html() + '</li>');
79497
- // jQuery(this).remove();
79498
- // last_level = cur_level;
79499
- // }else{
79500
- // last_level = 0;
79501
- // }
79502
- // });
79503
- // //jQuery('[style]', $editor).removeAttr('style'); //done (see cleanHTML)
79504
- // jQuery('[align]', $editor).removeAttr('align');
79505
- // //jQuery('span', $editor).replaceWith(function() {return jQuery(this).contents();}); //done (see cleanHTML)
79506
- // jQuery('span:empty', $editor).remove();
79507
- // //jQuery("[class^='Mso']", $editor).removeAttr('class'); //done (see cleanHTML)
79508
- // jQuery('p:empty', $editor).remove();
79509
-
79510
- sPastedText = contentword.innerHTML;
79396
+ //html-without-styles (default)
79397
+ sPastedText = util.cleanHTML(sPastedText, true);
79511
79398
  }
79512
- }
79513
- contentword = this.doc.querySelector('#idContentWord');
79514
- if (contentword) contentword.parentNode.removeChild(contentword);
79515
- util.restoreSelection();
79516
- var oSel = this.win.getSelection();
79517
- var range = oSel.getRangeAt(0);
79518
- range.extractContents();
79519
- range.collapse(true);
79520
- var docFrag = range.createContextualFragment(sPastedText);
79521
- var lastNode = docFrag.lastChild;
79522
- range.insertNode(docFrag);
79523
- if (this.activeCol) {
79399
+ contentword.innerHTML = sPastedText;
79400
+
79524
79401
  /*
79525
- Additional Cleanup:
79526
- - Remove empty elements (empty p, etc)
79402
+ // remove attributes
79403
+ if(this.opts.paste === 'html'){//with styles
79404
+ let elms = contentword.querySelectorAll('*');
79405
+ Array.prototype.forEach.call(elms, (elm) => {
79406
+ for(let n = 0;n<elm.attributes.length;n++) {
79407
+ if(elm.attributes[n].name!=='style') elm.removeAttribute(elm.attributes[n].name);
79408
+ }
79409
+ });
79410
+ } else { //html-without-styles (default)
79411
+
79412
+ const removeAttributes = (element) => {
79413
+ while (element.attributes.length > 0) {
79414
+ element.removeAttribute(element.attributes[0].name);
79415
+ }
79416
+ };
79417
+ let elms = contentword.querySelectorAll('*');
79418
+ Array.prototype.forEach.call(elms, (elm) => {
79419
+ removeAttributes(elm);
79420
+ });
79421
+ }
79527
79422
  */
79528
- // this.activeCol.find('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').remove();
79529
- // this.activeCol.querySelectorAll('*:empty').forEach((x)=>{x.remove();}); // Makes <img> removed
79530
- this.activeCol.querySelectorAll('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').forEach(x => {
79531
- x.remove();
79532
- });
79533
79423
 
79534
79424
  /*
79535
79425
  Additional Cleanup:
79536
- Fix HTML structure. The problem:
79537
- <p class="elm-active">
79538
- ...Sometimes h1, h2, p can be pasted here..
79539
- </p>
79426
+ - Remove p inside li
79427
+ - Remove li with white-space: pre
79540
79428
  */
79541
- let elmActive = this.activeCol.querySelector('p.elm-active,h1.elm-active,h2.elm-active,h3.elm-active,h4.elm-active,h5.elm-active,h6.elm-active');
79542
- if (elmActive) {
79543
- let elms = elmActive.querySelectorAll('p,h1,h2,h3,h4,h5,h6');
79544
- if (elms.length > 0) {
79545
- let elmClosestElement = elmActive.nextElementSibling;
79546
-
79547
- //Fix text that doesn't have paragraph
79548
- let textNodes = Array.from(elmActive.childNodes).filter(node => node.nodeType === 3 && node.textContent.trim().length > 1);
79549
- textNodes.forEach(node => {
79550
- const span = document.createElement('p');
79551
- node.after(span);
79552
- span.appendChild(node);
79553
- });
79554
- if (elmActive.firstElementChild && elmActive.childNodes.length === 1) {
79555
- if (elmActive.firstElementChild.tagName === 'SPAN') {
79556
- // Paste HTML with styles
79429
+ let elms = contentword.querySelectorAll('li');
79430
+ Array.prototype.forEach.call(elms, elm => {
79431
+ elm.style.whiteSpace = '';
79432
+ const childNodes = elm.childNodes;
79433
+ let i = childNodes.length;
79434
+ while (i--) {
79435
+ if (childNodes[i].tagName === 'P') {
79436
+ childNodes[i].outerHTML = childNodes[i].innerHTML;
79437
+ }
79438
+ }
79439
+ });
79557
79440
 
79558
- elmActive.outerHTML = elmActive.firstElementChild.innerHTML; //fix
79441
+ // NOTE: paste <h1><p> jadi nempel
79559
79442
 
79560
- // Re-clean empty elements
79561
- this.activeCol.querySelectorAll('*:empty').forEach(x => {
79562
- x.remove();
79563
- });
79443
+ // // Source: https://gist.github.com/sbrin/6801034
79444
+ // jQuery('p', $editor).each(function(){
79445
+ // var str = jQuery(this).attr('style');
79446
+ // var matches = /mso-list:\w+ \w+([0-9]+)/.exec(str);
79447
+ // if (matches) {
79448
+ // jQuery(this).data('_listLevel', parseInt(matches[1], 10));
79449
+ // }
79450
+ // });
79451
+ // var last_level=0;
79452
+ // var pnt = null;
79453
+ // jQuery('p', $editor).each(function(){
79454
+ // var cur_level = jQuery(this).data('_listLevel');
79455
+ // if(cur_level !== undefined){
79456
+ // var txt = jQuery(this).text();
79457
+ // var list_tag = '<ul></ul>';
79458
+ // if (/^\s*\w+\./.test(txt)) {
79459
+ // var matches = /([0-9])\./.exec(txt);
79460
+ // if (matches) {
79461
+ // var start = parseInt(matches[1], 10);
79462
+ // list_tag = start>1 ? '<ol start="' + start + '"></ol>' : '<ol></ol>';
79463
+ // }else{
79464
+ // list_tag = '<ol></ol>';
79465
+ // }
79466
+ // }
79467
+
79468
+ // if(cur_level>last_level){
79469
+ // if(last_level===0){
79470
+ // jQuery(this).before(list_tag);
79471
+ // pnt = jQuery(this).prev();
79472
+ // }else{
79473
+ // pnt = jQuery(list_tag).appendTo(pnt);
79474
+ // }
79475
+ // }
79476
+ // if(cur_level<last_level){
79477
+ // for(var i=0; i<last_level-cur_level; i++){
79478
+ // pnt = pnt.parent();
79479
+ // }
79480
+ // }
79481
+ // jQuery('span:first', this).remove();
79482
+ // pnt.append('<li>' + jQuery(this).html() + '</li>');
79483
+ // jQuery(this).remove();
79484
+ // last_level = cur_level;
79485
+ // }else{
79486
+ // last_level = 0;
79487
+ // }
79488
+ // });
79489
+ // //jQuery('[style]', $editor).removeAttr('style'); //done (see cleanHTML)
79490
+ // jQuery('[align]', $editor).removeAttr('align');
79491
+ // //jQuery('span', $editor).replaceWith(function() {return jQuery(this).contents();}); //done (see cleanHTML)
79492
+ // jQuery('span:empty', $editor).remove();
79493
+ // //jQuery("[class^='Mso']", $editor).removeAttr('class'); //done (see cleanHTML)
79494
+ // jQuery('p:empty', $editor).remove();
79564
79495
 
79565
- //place cursor
79566
- if (elmClosestElement) this.dom.moveCursorToElement(elmClosestElement.previousElementSibling);else this.dom.moveCursorToElement(this.activeCol);
79567
- let builderActive = this.doc.querySelector('.builder-active');
79568
- if (builderActive) this.applyBehaviorOn(builderActive);
79496
+ sPastedText = contentword.innerHTML;
79497
+ }
79498
+ }
79499
+ contentword = this.doc.querySelector('#idContentWord');
79500
+ if (contentword) contentword.parentNode.removeChild(contentword);
79501
+ util.restoreSelection();
79569
79502
 
79570
- //Trigger Change event
79571
- this.opts.onChange();
79503
+ /*
79504
+ var oSel = this.win.getSelection();
79505
+ var range = oSel.getRangeAt(0);
79506
+ range.extractContents();
79507
+ range.collapse(true);
79508
+ var docFrag = range.createContextualFragment(sPastedText);
79509
+ var lastNode = docFrag.lastChild;
79510
+ range.insertNode(docFrag);
79511
+ */
79512
+ document.execCommand('insertHTML', false, sPastedText);
79513
+ if (this.activeCol) {
79514
+ /*
79515
+ Additional Cleanup:
79516
+ - Remove empty elements (empty p, etc)
79517
+ */
79518
+ // this.activeCol.find('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').remove();
79519
+ // this.activeCol.querySelectorAll('*:empty').forEach((x)=>{x.remove();}); // Makes <img> removed
79520
+ this.activeCol.querySelectorAll('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').forEach(x => {
79521
+ x.remove();
79522
+ });
79572
79523
 
79573
- //Trigger Render event
79574
- this.opts.onRender();
79575
- return;
79576
- }
79577
- }
79524
+ /*
79525
+ Additional Cleanup:
79526
+ Fix HTML structure. The problem:
79527
+ <p class="elm-active">
79528
+ ...Sometimes h1, h2, p can be pasted here..
79529
+ </p>
79530
+ */
79531
+ let elmActive = this.activeCol.querySelector('p.elm-active,h1.elm-active,h2.elm-active,h3.elm-active,h4.elm-active,h5.elm-active,h6.elm-active');
79532
+ if (elmActive) {
79533
+ let elms = elmActive.querySelectorAll('p,h1,h2,h3,h4,h5,h6');
79534
+ if (elms.length > 0) {
79535
+ let elmClosestElement = elmActive.nextElementSibling;
79536
+
79537
+ //Fix text that doesn't have paragraph
79538
+ let textNodes = Array.from(elmActive.childNodes).filter(node => node.nodeType === 3 && node.textContent.trim().length > 1);
79539
+ textNodes.forEach(node => {
79540
+ const span = document.createElement('p');
79541
+ node.after(span);
79542
+ span.appendChild(node);
79543
+ });
79544
+ if (elmActive.firstElementChild && elmActive.childNodes.length === 1) {
79545
+ if (elmActive.firstElementChild.tagName === 'SPAN') {
79546
+ // Paste HTML with styles
79578
79547
 
79579
- // Paste HTML without styles
79580
- elmActive.outerHTML = elmActive.innerHTML; //fix
79548
+ elmActive.outerHTML = elmActive.firstElementChild.innerHTML; //fix
79581
79549
 
79582
- // Re-clean empty elements
79583
- // this.activeCol.querySelectorAll('*:empty').forEach((x)=>{x.remove();}); // Makes <img> removed
79584
- this.activeCol.find('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').remove();
79550
+ // Re-clean empty elements
79551
+ this.activeCol.querySelectorAll('*:empty').forEach(x => {
79552
+ x.remove();
79553
+ });
79585
79554
 
79586
- //place cursor
79587
- if (elmClosestElement) this.dom.moveCursorToElement(elmClosestElement.previousElementSibling);else this.dom.moveCursorToElement(this.activeCol);
79588
- let builderActive = this.doc.querySelector('.builder-active');
79589
- if (builderActive) this.applyBehaviorOn(builderActive);
79555
+ //place cursor
79556
+ if (elmClosestElement) this.dom.moveCursorToElement(elmClosestElement.previousElementSibling);else this.dom.moveCursorToElement(this.activeCol);
79557
+ let builderActive = this.doc.querySelector('.builder-active');
79558
+ if (builderActive) this.applyBehaviorOn(builderActive);
79590
79559
 
79591
- //Trigger Change event
79592
- this.opts.onChange();
79560
+ //Trigger Change event
79561
+ this.opts.onChange();
79593
79562
 
79594
- //Trigger Render event
79595
- this.opts.onRender();
79596
- return;
79563
+ //Trigger Render event
79564
+ this.opts.onRender();
79565
+ return;
79566
+ }
79597
79567
  }
79568
+
79569
+ // Paste HTML without styles
79570
+ elmActive.outerHTML = elmActive.innerHTML; //fix
79571
+
79572
+ // Re-clean empty elements
79573
+ // this.activeCol.querySelectorAll('*:empty').forEach((x)=>{x.remove();}); // Makes <img> removed
79574
+ this.activeCol.find('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').remove();
79575
+
79576
+ //place cursor
79577
+ if (elmClosestElement) this.dom.moveCursorToElement(elmClosestElement.previousElementSibling);else this.dom.moveCursorToElement(this.activeCol);
79578
+ let builderActive = this.doc.querySelector('.builder-active');
79579
+ if (builderActive) this.applyBehaviorOn(builderActive);
79580
+
79581
+ //Trigger Change event
79582
+ this.opts.onChange();
79583
+
79584
+ //Trigger Render event
79585
+ this.opts.onRender();
79586
+ return;
79598
79587
  }
79599
79588
  }
79600
- range.setStartAfter(lastNode);
79601
- range.setEndAfter(lastNode);
79602
- range.collapse(false);
79603
- var comCon = range.commonAncestorContainer;
79604
- if (comCon && comCon.parentNode) {
79605
- try {
79606
- comCon.parentNode.normalize();
79607
- } catch (e) {
79608
- // Do Nothing
79589
+ }
79590
+
79591
+ /*
79592
+ range.setStartAfter(lastNode);
79593
+ range.setEndAfter(lastNode);
79594
+ range.collapse(false);
79595
+ var comCon = range.commonAncestorContainer;
79596
+ if (comCon && comCon.parentNode) {
79597
+ try { comCon.parentNode.normalize(); } catch (e) {
79598
+ // Do Nothing
79609
79599
  }
79610
- }
79611
- oSel.removeAllRanges();
79612
- oSel.addRange(range);
79613
- let builderActive = this.doc.querySelector('.builder-active');
79614
- if (builderActive) this.applyBehaviorOn(builderActive);
79600
+ }
79601
+ oSel.removeAllRanges();
79602
+ oSel.addRange(range);
79603
+ */
79615
79604
 
79616
- //Trigger Change event
79617
- this.opts.onChange();
79605
+ let builderActive = this.doc.querySelector('.builder-active');
79606
+ if (builderActive) this.applyBehaviorOn(builderActive);
79618
79607
 
79619
- //Trigger Render event
79620
- this.opts.onRender();
79621
- } catch (e) {
79622
- let contentword = this.doc.querySelector('#idContentWord');
79623
- if (contentword) contentword.parentNode.removeChild(contentword);
79624
- }
79625
- }, 800);
79608
+ //Trigger Change event
79609
+ this.opts.onChange();
79610
+
79611
+ //Trigger Render event
79612
+ this.opts.onRender();
79613
+ } catch (e) {
79614
+
79615
+ // Do Nothing
79616
+ }
79626
79617
  }
79627
79618
  cellSelected() {
79628
79619
  const util = this.util;