@innovastudio/contentbuilder 1.4.123 → 1.4.125

Sign up to get free protection for your applications and to get access to all the features.
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;