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