@innovastudio/contentbuilder 1.4.124 → 1.4.126
Sign up to get free protection for your applications and to get access to all the features.
@@ -1439,7 +1439,7 @@ class Util {
|
|
1439
1439
|
const selection = this.builder.win.getSelection();
|
1440
1440
|
const container = this.builder.dom.getElm();
|
1441
1441
|
if (!container) return;
|
1442
|
-
const sameSelection = container && container.innerText === selection.toString();
|
1442
|
+
const sameSelection = container && container.innerText === selection.toString().trim();
|
1443
1443
|
if (sameSelection || selection.toString().trim() === '') {
|
1444
1444
|
this.builder.selectionElm = container;
|
1445
1445
|
|
@@ -3395,7 +3395,7 @@ class Dom {
|
|
3395
3395
|
if (callback) callback(false);
|
3396
3396
|
return;
|
3397
3397
|
}
|
3398
|
-
const sameSelection = container && container.innerText === selection.toString();
|
3398
|
+
const sameSelection = container && container.innerText === selection.toString().trim();
|
3399
3399
|
let newElement;
|
3400
3400
|
if (sameSelection || selection.toString().trim() === '') {
|
3401
3401
|
newElement = this.updateSelection(action, value, container);
|
@@ -3519,7 +3519,7 @@ class Dom {
|
|
3519
3519
|
const selection = this.builder.win.getSelection();
|
3520
3520
|
let container = this.getElm();
|
3521
3521
|
if (!container) return;
|
3522
|
-
const sameSelection = container && container.innerText === selection.toString();
|
3522
|
+
const sameSelection = container && container.innerText === selection.toString().trim();
|
3523
3523
|
if (currentElement) {
|
3524
3524
|
if (mode === 'block') if (this.getStyle(container, 'display') === 'inline') {
|
3525
3525
|
container = this.getParentBlock(container);
|
@@ -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)) {
|
@@ -3600,6 +3600,21 @@ class Dom {
|
|
3600
3600
|
blocks.push(item);
|
3601
3601
|
}
|
3602
3602
|
});
|
3603
|
+
|
3604
|
+
/*
|
3605
|
+
If a block is double clicked to select the block, the selection goes to the next block as well.
|
3606
|
+
This seems a default behavior (tested with simple contentEditable div). So the blocks contains 2 blocks.
|
3607
|
+
To fix this, perform an extra test here:
|
3608
|
+
*/
|
3609
|
+
if (blocks.length === 2) {
|
3610
|
+
// console.log(blocks[0].innerText.trim());
|
3611
|
+
// console.log(selection.toString().trim());
|
3612
|
+
if (blocks[0].innerText.trim() === selection.toString().trim()) {
|
3613
|
+
blocks.pop();
|
3614
|
+
// console.log('remove last')
|
3615
|
+
}
|
3616
|
+
}
|
3617
|
+
|
3603
3618
|
if (multiSelectBlocks) {
|
3604
3619
|
return blocks;
|
3605
3620
|
} else {
|
@@ -3733,7 +3748,7 @@ class Dom {
|
|
3733
3748
|
const selection = this.builder.win.getSelection();
|
3734
3749
|
const container = this.getElm();
|
3735
3750
|
if (!container) return;
|
3736
|
-
const sameSelection = container && container.innerText === selection.toString();
|
3751
|
+
const sameSelection = container && container.innerText === selection.toString().trim();
|
3737
3752
|
if (sameSelection || selection.toString().trim() === '') {
|
3738
3753
|
this.updateSelectionToggle(action, value, config, container);
|
3739
3754
|
} else {
|
@@ -4155,7 +4170,7 @@ class Dom {
|
|
4155
4170
|
const anchorNode = selection.anchorNode;
|
4156
4171
|
if (!anchorNode) return;
|
4157
4172
|
const container = anchorNode.nodeType !== Node.TEXT_NODE && anchorNode.nodeType !== Node.COMMENT_NODE ? anchorNode : anchorNode.parentElement;
|
4158
|
-
const sameSelection = container && container.innerText === selection.toString();
|
4173
|
+
const sameSelection = container && container.innerText === selection.toString().trim();
|
4159
4174
|
if (sameSelection || selection.toString().trim() === '') {
|
4160
4175
|
this.cleanElement(container);
|
4161
4176
|
} else {
|
@@ -66285,7 +66300,7 @@ class Rte {
|
|
66285
66300
|
} else if (num === '+' || num === '-') {
|
66286
66301
|
for (let i = 0; i < Object.keys(classes).length; i++) {
|
66287
66302
|
let className = Object.values(classes)[i];
|
66288
|
-
if (
|
66303
|
+
if (container.closest('.' + className) && !container.classList.contains('is-builder')) {
|
66289
66304
|
if (num === '+') {
|
66290
66305
|
if (i + 1 === Object.keys(classes).length) return;
|
66291
66306
|
newClassName = Object.values(classes)[i + 1];
|
@@ -76867,8 +76882,10 @@ class ContentBuilder {
|
|
76867
76882
|
// ON PASTE
|
76868
76883
|
// col.addEventListener('paste', this.handleCellPaste.bind(this));
|
76869
76884
|
col.addEventListener('paste', e => {
|
76870
|
-
|
76871
|
-
|
76885
|
+
e.preventDefault();
|
76886
|
+
const clipboardDataText = (e.clipboardData || window.clipboardData).getData('text');
|
76887
|
+
const clipboardDataHtml = (e.clipboardData || window.clipboardData).getData('text/html');
|
76888
|
+
this.handleCellPaste(clipboardDataText, clipboardDataHtml);
|
76872
76889
|
});
|
76873
76890
|
col.setAttribute('data-click', true);
|
76874
76891
|
}
|
@@ -79046,6 +79063,7 @@ class ContentBuilder {
|
|
79046
79063
|
// CMD-B
|
79047
79064
|
|
79048
79065
|
if (this.opts.useCssClasses) {
|
79066
|
+
this.uo.saveForUndo();
|
79049
79067
|
this.dom.execCommandToggle('fontWeight', '', this.opts.cssClasses);
|
79050
79068
|
this.opts.onChange();
|
79051
79069
|
e.preventDefault();
|
@@ -79056,6 +79074,7 @@ class ContentBuilder {
|
|
79056
79074
|
// CMD-I
|
79057
79075
|
|
79058
79076
|
if (this.opts.useCssClasses) {
|
79077
|
+
this.uo.saveForUndo();
|
79059
79078
|
this.dom.execCommandToggle('fontStyle', '', this.opts.cssClasses);
|
79060
79079
|
this.opts.onChange();
|
79061
79080
|
e.preventDefault();
|
@@ -79066,6 +79085,7 @@ class ContentBuilder {
|
|
79066
79085
|
// CMD-U
|
79067
79086
|
|
79068
79087
|
if (this.opts.useCssClasses) {
|
79088
|
+
this.uo.saveForUndo();
|
79069
79089
|
this.dom.execCommandToggle('textUnderline', '', this.opts.cssClasses);
|
79070
79090
|
this.opts.onChange();
|
79071
79091
|
e.preventDefault();
|
@@ -79076,6 +79096,7 @@ class ContentBuilder {
|
|
79076
79096
|
// CMD-S
|
79077
79097
|
|
79078
79098
|
if (this.opts.useCssClasses) {
|
79099
|
+
this.uo.saveForUndo();
|
79079
79100
|
this.dom.execCommandToggle('textLinethrough', '', this.opts.cssClasses);
|
79080
79101
|
this.opts.onChange();
|
79081
79102
|
e.preventDefault();
|
@@ -79083,6 +79104,8 @@ class ContentBuilder {
|
|
79083
79104
|
}
|
79084
79105
|
}
|
79085
79106
|
if (isCmd && e.which === 221) {
|
79107
|
+
this.uo.saveForUndo();
|
79108
|
+
|
79086
79109
|
// CMD-]
|
79087
79110
|
e.preventDefault();
|
79088
79111
|
document.execCommand('indent', false, null);
|
@@ -79091,6 +79114,8 @@ class ContentBuilder {
|
|
79091
79114
|
markSpan();
|
79092
79115
|
}
|
79093
79116
|
if (isCmd && e.which === 219) {
|
79117
|
+
this.uo.saveForUndo();
|
79118
|
+
|
79094
79119
|
// CMD-]
|
79095
79120
|
e.preventDefault();
|
79096
79121
|
document.execCommand('outdent', false, null);
|
@@ -79322,307 +79347,326 @@ class ContentBuilder {
|
|
79322
79347
|
this.opts.onChange();
|
79323
79348
|
}, 2000);
|
79324
79349
|
}
|
79325
|
-
handleCellPaste(clipboardData) {
|
79350
|
+
handleCellPaste(clipboardData, clipboardDataHtml) {
|
79326
79351
|
this.uo.saveForUndo();
|
79327
79352
|
const util = this.util;
|
79328
79353
|
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
79354
|
|
79330
|
-
|
79331
|
-
|
79332
|
-
|
79333
|
-
|
79334
|
-
|
79335
|
-
|
79336
|
-
|
79337
|
-
|
79338
|
-
|
79339
|
-
|
79340
|
-
|
79341
|
-
|
79342
|
-
|
79343
|
-
|
79344
|
-
|
79345
|
-
|
79346
|
-
|
79347
|
-
|
79348
|
-
|
79349
|
-
|
79350
|
-
|
79351
|
-
|
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;
|
79355
|
+
// Create a temporary div to hold the pasted HTML
|
79356
|
+
let contentword = document.createElement('div');
|
79357
|
+
contentword.innerHTML = clipboardDataHtml;
|
79358
|
+
try {
|
79359
|
+
var sPastedText = '';
|
79360
|
+
|
79361
|
+
//Check video embed
|
79362
|
+
var bPasteObject = false;
|
79363
|
+
var src = contentword.innerText;
|
79364
|
+
if (!this.opts.disableAutoEmbedVideo) {
|
79365
|
+
//var youRegex = /^http[s]?:\/\/(((www.youtube.com\/watch\?(feature=player_detailpage&)?)v=)|(youtu.be\/))([^#\&\?]*)/;
|
79366
|
+
var youRegex = /^http[s]?:\/\/(((www.youtube.com\/watch\?(feature=player_detailpage&)?)v=)|(youtu.be\/))([^#&?]*)/;
|
79367
|
+
var vimeoRegex = /^.*(vimeo\.com\/)((channels\/[A-z]+\/)|(groups\/[A-z]+\/videos\/)|(video\/))?([0-9]+)\/?/;
|
79368
|
+
var youRegexMatches = youRegex.exec(src);
|
79369
|
+
var vimeoRegexMatches = vimeoRegex.exec(src);
|
79370
|
+
if (youRegexMatches !== null || vimeoRegexMatches !== null) {
|
79371
|
+
if (youRegexMatches !== null && youRegexMatches.length >= 7) {
|
79372
|
+
var youMatch = youRegexMatches[6];
|
79373
|
+
src = 'https://www.youtube.com/embed/' + youMatch + '?rel=0';
|
79374
|
+
}
|
79375
|
+
if (vimeoRegexMatches !== null && vimeoRegexMatches.length >= 7) {
|
79376
|
+
var vimeoMatch = vimeoRegexMatches[6];
|
79377
|
+
src = 'https://player.vimeo.com/video/' + vimeoMatch;
|
79380
79378
|
}
|
79379
|
+
sPastedText = '<div class="embed-responsive embed-responsive-16by9"><iframe tabindex="0" width="560" height="315" src="' + src + '" frameborder="0" allowfullscreen=""></iframe></div>';
|
79380
|
+
bPasteObject = true;
|
79381
79381
|
}
|
79382
|
-
|
79383
|
-
|
79384
|
-
|
79385
|
-
|
79386
|
-
|
79387
|
-
|
79388
|
-
|
79389
|
-
|
79390
|
-
|
79391
|
-
|
79392
|
-
|
79393
|
-
|
79394
|
-
|
79395
|
-
|
79396
|
-
|
79397
|
-
|
79398
|
-
|
79399
|
-
|
79400
|
-
|
79382
|
+
}
|
79383
|
+
if (!bPasteObject) {
|
79384
|
+
if (this.opts.paste === 'text') {
|
79385
|
+
/*
|
79386
|
+
let elms = contentword.querySelectorAll('p,h1,h2,h3,h4,h5,h6');
|
79387
|
+
Array.prototype.forEach.call(elms, (elm) => {
|
79388
|
+
elm.innerHTML = elm.innerHTML + ' '; //add space ( )
|
79389
|
+
});
|
79390
|
+
// sPastedText = contentword.innerText;
|
79391
|
+
sPastedText = contentword.innerHTML;
|
79392
|
+
sPastedText = sPastedText.replace(/(<([^>]+)>)/ig,'<br>');
|
79393
|
+
sPastedText = sPastedText.replace(/(<br\s*\/?>){3,}/gi, '<br>');
|
79394
|
+
if(sPastedText.indexOf('<br>')===0) {
|
79395
|
+
sPastedText = sPastedText.substring(4);
|
79396
|
+
}
|
79397
|
+
if(sPastedText.substring(sPastedText.length-4)==='<br>'){
|
79398
|
+
sPastedText = sPastedText.substring(0, sPastedText.length-4);
|
79399
|
+
}
|
79400
|
+
sPastedText = sPastedText.trim();
|
79401
|
+
*/
|
79401
79402
|
|
79402
|
-
|
79403
|
-
|
79403
|
+
sPastedText = clipboardData;
|
79404
|
+
// sPastedText = sPastedText.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
79405
|
+
} else {
|
79406
|
+
sPastedText = contentword.innerHTML;
|
79407
|
+
if (this.opts.paste === 'html') {
|
79408
|
+
//with styles
|
79409
|
+
sPastedText = util.cleanHTML(sPastedText, false);
|
79404
79410
|
} else {
|
79405
|
-
|
79406
|
-
|
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;
|
79411
|
+
//html-without-styles (default)
|
79412
|
+
sPastedText = util.cleanHTML(sPastedText, true);
|
79511
79413
|
}
|
79512
|
-
|
79513
|
-
|
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) {
|
79414
|
+
contentword.innerHTML = sPastedText;
|
79415
|
+
|
79524
79416
|
/*
|
79525
|
-
|
79526
|
-
|
79417
|
+
// remove attributes
|
79418
|
+
if(this.opts.paste === 'html'){//with styles
|
79419
|
+
let elms = contentword.querySelectorAll('*');
|
79420
|
+
Array.prototype.forEach.call(elms, (elm) => {
|
79421
|
+
for(let n = 0;n<elm.attributes.length;n++) {
|
79422
|
+
if(elm.attributes[n].name!=='style') elm.removeAttribute(elm.attributes[n].name);
|
79423
|
+
}
|
79424
|
+
});
|
79425
|
+
} else { //html-without-styles (default)
|
79426
|
+
|
79427
|
+
const removeAttributes = (element) => {
|
79428
|
+
while (element.attributes.length > 0) {
|
79429
|
+
element.removeAttribute(element.attributes[0].name);
|
79430
|
+
}
|
79431
|
+
};
|
79432
|
+
let elms = contentword.querySelectorAll('*');
|
79433
|
+
Array.prototype.forEach.call(elms, (elm) => {
|
79434
|
+
removeAttributes(elm);
|
79435
|
+
});
|
79436
|
+
}
|
79527
79437
|
*/
|
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
79438
|
|
79534
79439
|
/*
|
79535
79440
|
Additional Cleanup:
|
79536
|
-
|
79537
|
-
|
79538
|
-
...Sometimes h1, h2, p can be pasted here..
|
79539
|
-
</p>
|
79441
|
+
- Remove p inside li
|
79442
|
+
- Remove li with white-space: pre
|
79540
79443
|
*/
|
79541
|
-
let
|
79542
|
-
|
79543
|
-
|
79544
|
-
|
79545
|
-
|
79546
|
-
|
79547
|
-
|
79548
|
-
|
79549
|
-
|
79550
|
-
|
79551
|
-
|
79552
|
-
span.appendChild(node);
|
79553
|
-
});
|
79554
|
-
if (elmActive.firstElementChild && elmActive.childNodes.length === 1) {
|
79555
|
-
if (elmActive.firstElementChild.tagName === 'SPAN') {
|
79556
|
-
// Paste HTML with styles
|
79444
|
+
let elms = contentword.querySelectorAll('li');
|
79445
|
+
Array.prototype.forEach.call(elms, elm => {
|
79446
|
+
elm.style.whiteSpace = '';
|
79447
|
+
const childNodes = elm.childNodes;
|
79448
|
+
let i = childNodes.length;
|
79449
|
+
while (i--) {
|
79450
|
+
if (childNodes[i].tagName === 'P') {
|
79451
|
+
childNodes[i].outerHTML = childNodes[i].innerHTML;
|
79452
|
+
}
|
79453
|
+
}
|
79454
|
+
});
|
79557
79455
|
|
79558
|
-
|
79456
|
+
// NOTE: paste <h1><p> jadi nempel
|
79559
79457
|
|
79560
|
-
|
79561
|
-
|
79562
|
-
|
79563
|
-
|
79458
|
+
// // Source: https://gist.github.com/sbrin/6801034
|
79459
|
+
// jQuery('p', $editor).each(function(){
|
79460
|
+
// var str = jQuery(this).attr('style');
|
79461
|
+
// var matches = /mso-list:\w+ \w+([0-9]+)/.exec(str);
|
79462
|
+
// if (matches) {
|
79463
|
+
// jQuery(this).data('_listLevel', parseInt(matches[1], 10));
|
79464
|
+
// }
|
79465
|
+
// });
|
79466
|
+
// var last_level=0;
|
79467
|
+
// var pnt = null;
|
79468
|
+
// jQuery('p', $editor).each(function(){
|
79469
|
+
// var cur_level = jQuery(this).data('_listLevel');
|
79470
|
+
// if(cur_level !== undefined){
|
79471
|
+
// var txt = jQuery(this).text();
|
79472
|
+
// var list_tag = '<ul></ul>';
|
79473
|
+
// if (/^\s*\w+\./.test(txt)) {
|
79474
|
+
// var matches = /([0-9])\./.exec(txt);
|
79475
|
+
// if (matches) {
|
79476
|
+
// var start = parseInt(matches[1], 10);
|
79477
|
+
// list_tag = start>1 ? '<ol start="' + start + '"></ol>' : '<ol></ol>';
|
79478
|
+
// }else{
|
79479
|
+
// list_tag = '<ol></ol>';
|
79480
|
+
// }
|
79481
|
+
// }
|
79482
|
+
|
79483
|
+
// if(cur_level>last_level){
|
79484
|
+
// if(last_level===0){
|
79485
|
+
// jQuery(this).before(list_tag);
|
79486
|
+
// pnt = jQuery(this).prev();
|
79487
|
+
// }else{
|
79488
|
+
// pnt = jQuery(list_tag).appendTo(pnt);
|
79489
|
+
// }
|
79490
|
+
// }
|
79491
|
+
// if(cur_level<last_level){
|
79492
|
+
// for(var i=0; i<last_level-cur_level; i++){
|
79493
|
+
// pnt = pnt.parent();
|
79494
|
+
// }
|
79495
|
+
// }
|
79496
|
+
// jQuery('span:first', this).remove();
|
79497
|
+
// pnt.append('<li>' + jQuery(this).html() + '</li>');
|
79498
|
+
// jQuery(this).remove();
|
79499
|
+
// last_level = cur_level;
|
79500
|
+
// }else{
|
79501
|
+
// last_level = 0;
|
79502
|
+
// }
|
79503
|
+
// });
|
79504
|
+
// //jQuery('[style]', $editor).removeAttr('style'); //done (see cleanHTML)
|
79505
|
+
// jQuery('[align]', $editor).removeAttr('align');
|
79506
|
+
// //jQuery('span', $editor).replaceWith(function() {return jQuery(this).contents();}); //done (see cleanHTML)
|
79507
|
+
// jQuery('span:empty', $editor).remove();
|
79508
|
+
// //jQuery("[class^='Mso']", $editor).removeAttr('class'); //done (see cleanHTML)
|
79509
|
+
// jQuery('p:empty', $editor).remove();
|
79564
79510
|
|
79565
|
-
|
79566
|
-
|
79567
|
-
|
79568
|
-
|
79511
|
+
sPastedText = contentword.innerHTML;
|
79512
|
+
}
|
79513
|
+
}
|
79514
|
+
contentword = this.doc.querySelector('#idContentWord');
|
79515
|
+
if (contentword) contentword.parentNode.removeChild(contentword);
|
79516
|
+
util.restoreSelection();
|
79569
79517
|
|
79570
|
-
|
79571
|
-
|
79518
|
+
/*
|
79519
|
+
var oSel = this.win.getSelection();
|
79520
|
+
var range = oSel.getRangeAt(0);
|
79521
|
+
range.extractContents();
|
79522
|
+
range.collapse(true);
|
79523
|
+
var docFrag = range.createContextualFragment(sPastedText);
|
79524
|
+
var lastNode = docFrag.lastChild;
|
79525
|
+
range.insertNode(docFrag);
|
79526
|
+
*/
|
79572
79527
|
|
79573
|
-
|
79574
|
-
|
79575
|
-
|
79576
|
-
|
79577
|
-
|
79528
|
+
/*
|
79529
|
+
When selection is made by double clicking text (to select the entire block),
|
79530
|
+
the actual selection goes to the next block as well (default behavior, tested using a simple contentEditable div).
|
79531
|
+
To fix this, re-select the contents inside.
|
79532
|
+
*/
|
79533
|
+
|
79534
|
+
const blocks = this.dom.getSelectedBlocks();
|
79535
|
+
const selection = this.win.getSelection();
|
79536
|
+
|
79537
|
+
/*
|
79538
|
+
Check same selection for the block first (this is more accurate than the sameSelection checking below).
|
79539
|
+
In case of double click (to select the entire block), for example, on this element:
|
79540
|
+
<h2 class="font-light size-54"><span class="size-24">Heading</span> 2 here</h2>
|
79541
|
+
The sameSelection checking below is failed, since the container = this.getElm() will return not the entire h2, but only
|
79542
|
+
<span class="size-24">Heading</span>
|
79543
|
+
So, blocks checking below is made to fix it.
|
79544
|
+
*/
|
79545
|
+
let blockSelection = false;
|
79546
|
+
if (blocks.length === 1) {
|
79547
|
+
if (blocks[0].innerText.trim() === selection.toString().trim()) {
|
79548
|
+
let range = document.createRange();
|
79549
|
+
range.selectNodeContents(blocks[0]);
|
79550
|
+
selection.removeAllRanges();
|
79551
|
+
selection.addRange(range);
|
79552
|
+
blockSelection = true;
|
79553
|
+
}
|
79554
|
+
}
|
79555
|
+
if (!blockSelection) {
|
79556
|
+
const container = this.dom.getElm();
|
79557
|
+
const sameSelection = container && container.innerText === selection.toString().trim();
|
79558
|
+
if (sameSelection || selection.toString().trim() === '') {
|
79559
|
+
let range = document.createRange();
|
79560
|
+
range.selectNodeContents(container);
|
79561
|
+
selection.removeAllRanges();
|
79562
|
+
selection.addRange(range);
|
79563
|
+
}
|
79564
|
+
}
|
79565
|
+
document.execCommand('insertHTML', false, sPastedText);
|
79566
|
+
if (this.activeCol) {
|
79567
|
+
/*
|
79568
|
+
Additional Cleanup:
|
79569
|
+
- Remove empty elements (empty p, etc)
|
79570
|
+
*/
|
79571
|
+
// this.activeCol.find('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').remove();
|
79572
|
+
// this.activeCol.querySelectorAll('*:empty').forEach((x)=>{x.remove();}); // Makes <img> removed
|
79573
|
+
this.activeCol.querySelectorAll('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').forEach(x => {
|
79574
|
+
x.remove();
|
79575
|
+
});
|
79578
79576
|
|
79579
|
-
|
79580
|
-
|
79577
|
+
/*
|
79578
|
+
Additional Cleanup:
|
79579
|
+
Fix HTML structure. The problem:
|
79580
|
+
<p class="elm-active">
|
79581
|
+
...Sometimes h1, h2, p can be pasted here..
|
79582
|
+
</p>
|
79583
|
+
*/
|
79584
|
+
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');
|
79585
|
+
if (elmActive) {
|
79586
|
+
let elms = elmActive.querySelectorAll('p,h1,h2,h3,h4,h5,h6');
|
79587
|
+
if (elms.length > 0) {
|
79588
|
+
let elmClosestElement = elmActive.nextElementSibling;
|
79589
|
+
|
79590
|
+
//Fix text that doesn't have paragraph
|
79591
|
+
let textNodes = Array.from(elmActive.childNodes).filter(node => node.nodeType === 3 && node.textContent.trim().length > 1);
|
79592
|
+
textNodes.forEach(node => {
|
79593
|
+
const span = document.createElement('p');
|
79594
|
+
node.after(span);
|
79595
|
+
span.appendChild(node);
|
79596
|
+
});
|
79597
|
+
if (elmActive.firstElementChild && elmActive.childNodes.length === 1) {
|
79598
|
+
if (elmActive.firstElementChild.tagName === 'SPAN') {
|
79599
|
+
// Paste HTML with styles
|
79581
79600
|
|
79582
|
-
|
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();
|
79601
|
+
elmActive.outerHTML = elmActive.firstElementChild.innerHTML; //fix
|
79585
79602
|
|
79586
|
-
|
79587
|
-
|
79588
|
-
|
79589
|
-
|
79603
|
+
// Re-clean empty elements
|
79604
|
+
this.activeCol.querySelectorAll('*:empty').forEach(x => {
|
79605
|
+
x.remove();
|
79606
|
+
});
|
79590
79607
|
|
79591
|
-
|
79592
|
-
|
79608
|
+
//place cursor
|
79609
|
+
if (elmClosestElement) this.dom.moveCursorToElement(elmClosestElement.previousElementSibling);else this.dom.moveCursorToElement(this.activeCol);
|
79610
|
+
let builderActive = this.doc.querySelector('.builder-active');
|
79611
|
+
if (builderActive) this.applyBehaviorOn(builderActive);
|
79593
79612
|
|
79594
|
-
|
79595
|
-
|
79596
|
-
|
79613
|
+
//Trigger Change event
|
79614
|
+
this.opts.onChange();
|
79615
|
+
|
79616
|
+
//Trigger Render event
|
79617
|
+
this.opts.onRender();
|
79618
|
+
return;
|
79619
|
+
}
|
79597
79620
|
}
|
79621
|
+
|
79622
|
+
// Paste HTML without styles
|
79623
|
+
elmActive.outerHTML = elmActive.innerHTML; //fix
|
79624
|
+
|
79625
|
+
// Re-clean empty elements
|
79626
|
+
// this.activeCol.querySelectorAll('*:empty').forEach((x)=>{x.remove();}); // Makes <img> removed
|
79627
|
+
this.activeCol.find('h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty,p:empty').remove();
|
79628
|
+
|
79629
|
+
//place cursor
|
79630
|
+
if (elmClosestElement) this.dom.moveCursorToElement(elmClosestElement.previousElementSibling);else this.dom.moveCursorToElement(this.activeCol);
|
79631
|
+
let builderActive = this.doc.querySelector('.builder-active');
|
79632
|
+
if (builderActive) this.applyBehaviorOn(builderActive);
|
79633
|
+
|
79634
|
+
//Trigger Change event
|
79635
|
+
this.opts.onChange();
|
79636
|
+
|
79637
|
+
//Trigger Render event
|
79638
|
+
this.opts.onRender();
|
79639
|
+
return;
|
79598
79640
|
}
|
79599
79641
|
}
|
79600
|
-
|
79601
|
-
|
79602
|
-
|
79603
|
-
|
79604
|
-
|
79605
|
-
|
79606
|
-
|
79607
|
-
|
79608
|
-
|
79642
|
+
}
|
79643
|
+
|
79644
|
+
/*
|
79645
|
+
range.setStartAfter(lastNode);
|
79646
|
+
range.setEndAfter(lastNode);
|
79647
|
+
range.collapse(false);
|
79648
|
+
var comCon = range.commonAncestorContainer;
|
79649
|
+
if (comCon && comCon.parentNode) {
|
79650
|
+
try { comCon.parentNode.normalize(); } catch (e) {
|
79651
|
+
// Do Nothing
|
79609
79652
|
}
|
79610
|
-
|
79611
|
-
|
79612
|
-
|
79613
|
-
|
79614
|
-
if (builderActive) this.applyBehaviorOn(builderActive);
|
79653
|
+
}
|
79654
|
+
oSel.removeAllRanges();
|
79655
|
+
oSel.addRange(range);
|
79656
|
+
*/
|
79615
79657
|
|
79616
|
-
|
79617
|
-
|
79658
|
+
let builderActive = this.doc.querySelector('.builder-active');
|
79659
|
+
if (builderActive) this.applyBehaviorOn(builderActive);
|
79618
79660
|
|
79619
|
-
|
79620
|
-
|
79621
|
-
|
79622
|
-
|
79623
|
-
|
79624
|
-
|
79625
|
-
|
79661
|
+
//Trigger Change event
|
79662
|
+
this.opts.onChange();
|
79663
|
+
|
79664
|
+
//Trigger Render event
|
79665
|
+
this.opts.onRender();
|
79666
|
+
} catch (e) {
|
79667
|
+
|
79668
|
+
// Do Nothing
|
79669
|
+
}
|
79626
79670
|
}
|
79627
79671
|
cellSelected() {
|
79628
79672
|
const util = this.util;
|