/**
* Copyright (c) UNA, Inc - https://una.io
* MIT License - https://opensource.org/licenses/MIT
*
* @defgroup UnaCore UNA Core
* @{
*/
function bx_editor_init(oParams) {
var oEditor = null;
hljs.configure({
languages: ['javascript', 'php', 'html', 'css']
});
bEmptyToolbar = oParams.toolbar == false ? true : false;
if (oParams.query_params == undefined)
oParams.query_params = {};
oParams.toolbar = {
container: bEmptyToolbar ? [] : oParams.toolbar,
handlers: {
'show-html': function() {
bx_alert('',function() {
oEditor.container.firstChild.innerHTML = $('#'+oParams.name+'_code').val();
});
},
'embed': function(value) {
var range = oEditor.getSelection();
bx_prompt(_t('_sys_txt_quill_tooltip_embed_popup_header'), '', function(oPopup){
sLink = $(oPopup).find("input[type = 'text']").val()
$.getJSON(oParams.root_url + 'embed.php?', {a: 'get_link', l: sLink}, function(aData){
if (range) {
oEditor.clipboard.dangerouslyPasteHTML(range.index, "
", 'api');
oEditor.insertEmbed(range.index+2, 'embed-link', {source: sLink, inlinecode : aData.code}, 'api');
}
else{
oEditor.insertEmbed(0, 'embed-link', {source: sLink, inlinecode : aData.code}, 'api');
}
if ($(oParams.selector).next().next().find('.bx-embed-link a[href="' + aData.link + '"]').length > 0)
bx_embed_link($(oParams.selector).next().next().find('.bx-embed-link a[href="' + aData.link + '"]')[0]);
else
bx_embed_link();
});
});
},
'link': function(value) {
if (value) {
var range = oEditor.getSelection();
bx_prompt(_t('_sys_txt_quill_tooltip_link_popup_header'), '', function(oPopup){
var sLink = $(oPopup).find("input[type = 'text']").val();
if (range) {
if (range.length > 0){
oEditor.format('link', sLink);
}
else{
oEditor.insertText(range.index, sLink, 'link', sLink);
}
}
else{
oEditor.insertText(0, sLink, 'link', sLink);
}
});
} else {
oEditor.format('link', false);
}
}
}
}
sVal = $(oParams.selector).val();
if(!oParams.empty_tags){
sVal = sVal.replaceAll('
','');
}
$(oParams.selector).after("" + sVal + "
" );
$(oParams.selector).hide();
$(oParams.selector).attr('object_editor', oParams.name);
if (typeof bQuillRegistred === 'undefined' ) {
var Embed = Quill.import('blots/embed');
const BaseLink = Quill.import("formats/link");
class Link extends BaseLink {
format(name, value) {
if (["href", "target"].indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value);
} else {
this.domNode.removeAttribute(name);
}
} else {
super.format(name, value);
if (name == 'link'){
if (value){
if (!value.startsWith(oParams.root_url) && (value.startsWith('http://') || value.startsWith('https://'))){
this.domNode.setAttribute("target", "_blank");
}
else{
this.domNode.removeAttribute('target');
}
}
}
}
}
static create(value) {
const node = super.create(value);
node.setAttribute("href", this.sanitize(value));
if (!value.startsWith(oParams.root_url) && (value.startsWith('http://') || value.startsWith('https://'))){
node.setAttribute("target", "_blank");
}
else{
node.removeAttribute('target');
}
return node;
}
}
Quill.register(Link, true);
class MenthionLink extends Embed {
static create(value) {
let node = super.create(value);
if (value.id && value.value){
node.setAttribute('href', value.id);
node.innerHTML = value.denotationChar + value.value;
node.setAttribute('title', value.value);
node.setAttribute('dchar', value.denotationChar);
node.setAttribute('data-profile-id', value.dataProfileId);
}
if (value.url && value.title && value.dataProfileId){
node.setAttribute('href', value.url);
node.innerHTML = value.text;
node.setAttribute('title', value.title);
if (value.dchar)
node.setAttribute('dchar', value.dchar);
else
node.setAttribute('dchar', '@');
node.setAttribute('data-profile-id', value.dataProfileId);
}
const sDenotationChar = node.getAttribute('dchar');
if(sDenotationChar == '@')
node.setAttribute('class', 'bx-mention-link');
else if(sDenotationChar == '#')
node.setAttribute('class', 'bx-tag-link');
return node;
}
format(name, value) {
if (name === 'href' || name === 'title' || name === 'dchar' || name === 'data-profile-id' || name === 'dataProfileId') {
if (value) {
if (name === 'dchar'){
this.domNode.innerHTML = value + this.domNode.getAttribute('title');
}
if (name === 'dataProfileId'){
this.domNode.setAttribute('data-profile-id', value);
}
else{
this.domNode.setAttribute(name, value);
}
} else {
this.domNode.removeAttribute(name, value);
}
}
else {
super.format(name, value);
}
};
static value(node) {
return { url: node.getAttribute('href') ,title: node.getAttribute('title'), dchar: node.getAttribute('dchar'), dataProfileId: node.getAttribute('data-profile-id'), text: node.innerText }
}
static formats(node) {
let format = {};
if (node.hasAttribute('href')) {
format.href = node.getAttribute('href');
}
if (node.hasAttribute('title')) {
format.title = node.getAttribute('title');
}
else{
format.title = node.innerText.replace(node.getAttribute('dchar'), '');
}
if (node.hasAttribute('dchar')) {
format.dchar = node.getAttribute('dchar');
}
if (node.hasAttribute('data-profile-id')) {
format['data-profile-id'] = node.getAttribute('data-profile-id');
}
if (node.hasAttribute('dataProfileId')) {
format.dataProfileId = node.getAttribute('dataProfileId');
}
return format;
}
}
MenthionLink.blotName = 'menthion-link';
//MenthionLink.className = '1';
MenthionLink.tagName = 'a';
Quill.register({
'formats/menthion-link': MenthionLink
});
class EmbedCode extends Embed {
static create(value) {
let node = super.create(value);
if (value.source && value.inlinecode){
node.setAttribute('source', value.source);
node.innerHTML = value.inlinecode + " ";
return node;
}
return node;
};
format(name, value) {
if (name === 'source') {
if (value) {
this.domNode.setAttribute(name, value);
} else {
this.domNode.removeAttribute(name, value);
}
}
else {
super.format(name, value);
}
};
static value(node) {
return { source: node.getAttribute('source'), inlinecode: "emded"}
}
static formats(node) {
let format = {};
if (node.hasAttribute('source')) {
format.source = node.getAttribute('source');
}
return format;
}
}
EmbedCode.className = 'bx-embed-link';
EmbedCode.blotName = 'embed-link';
EmbedCode.tagName = 'div';
Quill.register({
'formats/embed-link': EmbedCode
});
var AlignStyle = Quill.import('attributors/style/align');
Quill.register(AlignStyle, true);
var DirectionStyle = Quill.import('attributors/style/direction');
Quill.register(DirectionStyle, true);
const ImageFormatAttributesList = [
'alt',
'height',
'width',
'style'
];
const BaseImageFormat = Quill.import('formats/image');
class ImageFormat extends BaseImageFormat {
static formats(domNode) {
return ImageFormatAttributesList.reduce(function(formats, attribute) {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute);
}
return formats;
}, {});
}
format(name, value) {
if (ImageFormatAttributesList.indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value);
} else {
this.domNode.removeAttribute(name);
}
} else {
super.format(name, value);
}
}
}
Quill.register(ImageFormat, true);
const Parchment = Quill.import("parchment");
const pixelLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
const TAB_MULTIPLIER = 30
class IndentAttributor extends Parchment.Attributor.Style {
add(node, value) {
return super.add(node, `${+value * TAB_MULTIPLIER}px`)
}
value(node) {
return parseFloat(super.value(node)) / TAB_MULTIPLIER || undefined // Don't return NaN
}
}
const IndentStyle = new IndentAttributor("indent", "margin-left", {
scope: Parchment.Scope.BLOCK,
whitelist: pixelLevels.map(value => `${value * TAB_MULTIPLIER}px`),
})
Quill.register({"formats/indent": IndentStyle}, true);
bQuillRegistred = true;
var icons = Quill.import('ui/icons');
icons['embed'] = '';
icons['show-html'] = '';
}
var oConfig = {
theme: oParams.skin,
modules: {
clipboard: {
matchVisual: false
},
syntax: true,
imageResize: {},
toolbar: oParams.toolbar,
"emoji-toolbar": true,
mention: {
allowedChars: /^[\S]*$/,
mentionDenotationChars: ["@", "#"],
showDenotationChar: true,
blotName: 'menthion-link',
mentionContainerClass: 'bx-popup bx-popup-trans bx-popup-border bx-popup-color-bg',
mentionListClass: 'ql-mention-list bx-menu-ver',
dataAttributes: ['id', 'value', 'denotationChar', 'link', 'target','disabled', 'dataProfileId'],
listItemClass: 'bx-menu-item bx-def-color-bg-hl-hover',
source: function (searchTerm, renderList, mentionChar) {
var aFlds = oParams.query_params['fi'].split(",");
aFlds.forEach(fld => {
oParams.query_params[fld] = $('#' + oParams.query_params['f'] + ' [name="' + fld + '"]').val()
});
$.getJSON(oParams.root_url + 'searchExtended.php?action=get_mention', $.extend({}, {symbol: mentionChar, term: searchTerm}, oParams.query_params), function(data){
renderList(data, searchTerm);
});
},
renderItem: function(item, searchTerm){
item.id = item.url;
item.dataProfileId = item.value;
item.value = item.label;
return item.symbol + item.value;
},
onSelect: function(item, insertItem){
insertItem(item, false)
}
},
}
};
if (oParams.allowed_tags){
oConfig.formats = oParams.allowed_tags;
}
if(!Quill.imports['modules/imageUploader'])
Quill.register('modules/imageUploader', ImageUploader);
oConfig.modules.imageUploader = {
upload: file => {
return new Promise((resolve, reject) => {
var bProcessed = false;
if (typeof glOnInsertImageInEditor !== 'undefined' && glOnInsertImageInEditor instanceof Array && glOnInsertImageInEditor.length > 0) {
for (var i = 0; i < glOnInsertImageInEditor.length; i++) {
if (typeof glOnInsertImageInEditor[i] === "function") {
var bTmp = glOnInsertImageInEditor[i](file,oParams.selector);
if (bTmp)
bProcessed = true;
}
}
if(bProcessed)
reject("External uploader");
}
if(!bProcessed){
const formData = new FormData();
formData.append("file", file);
fetch(oParams.root_url + "storage.php?o=sys_images_editor&t=sys_images_editor&a=upload", {
method: "POST",
body: formData
}
)
.then(response => response.json())
.then(result => {
if ('undefined' != typeof(result.link))
resolve(result.link);
else
reject("Upload failed");
})
.catch(error => {
reject("Upload failed");
});
}
});
}
}
oEditor = new Quill('#' + oParams.name, oConfig)
$(oParams.selector).next().find('button.ql-bold').attr('title', _t('_sys_txt_quill_tooltip_bold'));
$(oParams.selector).next().find('button.ql-italic').attr('title', _t('_sys_txt_quill_tooltip_italic'));
$(oParams.selector).next().find('button.ql-underline').attr('title', _t('_sys_txt_quill_tooltip_underline'));
$(oParams.selector).next().find('button.ql-clean').attr('title', _t('_sys_txt_quill_tooltip_clean'));
$(oParams.selector).next().find('button.ql-list[value = "ordered"]').attr('title', _t('_sys_txt_quill_tooltip_list_ordered'));
$(oParams.selector).next().find('button.ql-list[value = "bullet"]').attr('title', _t('_sys_txt_quill_tooltip_list_bullet'));
$(oParams.selector).next().find('button.ql-indent[value = "-1"]').attr('title', _t('_sys_txt_quill_tooltip_indent_1'));
$(oParams.selector).next().find('button.ql-indent[value = "+1"]').attr('title', _t('_sys_txt_quill_tooltip_indent_2'));
$(oParams.selector).next().find('button.ql-blockquote').attr('title', _t('_sys_txt_quill_tooltip_blockquote'));
$(oParams.selector).next().find('button.ql-direction').attr('title', _t('_sys_txt_quill_tooltip_direction'));
$(oParams.selector).next().find('button.ql-script[value="sub"]').attr('title', _t('_sys_txt_quill_tooltip_script_sub'));
$(oParams.selector).next().find('button.ql-script[value="super"]').attr('title', _t('_sys_txt_quill_tooltip_script_super'));
$(oParams.selector).next().find('button.ql-link').attr('title', _t('_sys_txt_quill_tooltip_link'));
$(oParams.selector).next().find('button.ql-image').attr('title', _t('_sys_txt_quill_tooltip_image'));
$(oParams.selector).next().find('button.ql-code-block').attr('title', _t('_sys_txt_quill_tooltip_code_block'));
$(oParams.selector).next().find('button.ql-embed').attr('title', _t('_sys_txt_quill_tooltip_embed'));
$(oParams.selector).next().find('button.ql-emoji').attr('title', _t('_sys_txt_quill_tooltip_emoji'));
$(oParams.selector).next().find('button.ql-show-html').attr('title', _t('_sys_txt_quill_tooltip_show_html'));
$(oParams.selector).next().find('span.ql-color .ql-picker-label').attr({'title': _t('_sys_txt_quill_tooltip_color'), 'aria-label': _t('_sys_txt_quill_tooltip_color')});
$(oParams.selector).next().find('span.ql-background .ql-picker-label').attr({'title': _t('_sys_txt_quill_tooltip_background'), 'aria-label': _t('_sys_txt_quill_tooltip_background')});
$(oParams.selector).next().find('span.ql-align .ql-picker-label').attr({'title': _t('_sys_txt_quill_tooltip_align'), 'aria-label': _t('_sys_txt_quill_tooltip_align')});
//--- a mini toolbar renders alignment as four separate buttons rather than one picker
$(oParams.selector).next().find('button.ql-align[value=""]').attr('title', _t('_sys_txt_quill_tooltip_align_left'));
$(oParams.selector).next().find('button.ql-align[value="center"]').attr('title', _t('_sys_txt_quill_tooltip_align_center'));
$(oParams.selector).next().find('button.ql-align[value="right"]').attr('title', _t('_sys_txt_quill_tooltip_align_right'));
$(oParams.selector).next().find('button.ql-align[value="justify"]').attr('title', _t('_sys_txt_quill_tooltip_align_justify'));
$(oParams.selector).next().find('span.ql-header .ql-picker-label').attr({'title': _t('_sys_txt_quill_tooltip_header'), 'aria-label': _t('_sys_txt_quill_tooltip_header')});
//--- quill-mention points aria-owns at its list, but only inserts that list into the document when
//--- the list opens, so the reference dangles and every page with an editor reports an invalid
//--- ARIA value. The editor is not a combobox, so the attribute has nothing to say here.
$('#' + oParams.name).find('.ql-editor').addClass('bx-def-vanilla-html').removeAttr('aria-owns');
if (bEmptyToolbar)
$(oParams.selector).next().hide();
oEditor.clipboard.addMatcher (Node.TEXT_NODE, function (node, delta) {
const Delta = Quill.import('delta')
bx_editor_on_space_enter(node.data, oParams.selector, false);
return delta;
});
if (oParams.insert_as_plain_text) {
oEditor.clipboard.addMatcher (Node.ELEMENT_NODE, function (node, delta) {
let ops = []
delta.ops.forEach(op => {
if (op.insert && typeof op.insert === 'string') {
ops.push({
insert: op.insert
})
}
})
delta.ops = ops
return delta
});
}
else{
oEditor.clipboard.addMatcher (Node.ELEMENT_NODE, function (node, delta) {
delta.forEach(e => {
//if(typeof e.insert == 'string' && e.attributes == null)
// e.insert = e.insert.replace(/\n/g, '') + "\n";
if(e.attributes){
e.attributes.color = '';
e.attributes.background = '';
}
});
return delta;
});
}
oEditor.keyboard.addBinding({
key: ' ',
handler: function(range, context) {
bx_editor_on_space_enter (oEditor.container.firstChild.innerHTML, oParams.selector);
return true;
}
});
oEditor.container.addEventListener('keydown', function(event) {
if (event.key === 'Enter' || event.keyCode === 13) {
bx_editor_on_space_enter (oEditor.container.firstChild.innerHTML, oParams.selector);
}
});
oEditor.on('editor-change', function(delta, oldDelta, source) {
sVal = oEditor.container.firstChild.innerHTML;
if(!oParams.empty_tags){
sVal = sVal.replaceAll('
','');
}
if ((oEditor.getContents()['ops'] || []).length == 1 && oEditor.getText().trim().length === 0) {
sVal = ''
}
$(oParams.selector).val(sVal);
});
return oEditor
}
function bx_editor_activate(oEditor)
{
oEditor.focus();
}
function bx_editor_insert_html (sEditorId, sImgId, sHtml)
{
if ($('#' + sEditorId) && $('#' + sEditorId).attr('object_editor')) {
eval ('oEditor = ' + $('#' + sEditorId).attr('object_editor'));
if (oEditor.getSelection())
oEditor.clipboard.dangerouslyPasteHTML(oEditor.getSelection().index, sHtml, 'api');
else
oEditor.clipboard.dangerouslyPasteHTML(0, sHtml, 'api');
}
}
function bx_editor_insert_img (sEditorId, sImgId, sImgUrl, sClasses)
{
if ('undefined' == typeof(sClasses))
sClasses = '';
bx_editor_insert_html(sEditorId, sImgId, '
')
}
function bx_editor_on_space_enter (sCode, sEditorId, bSpace = true)
{
if (typeof glBxEditorOnSpaceEnterTimer !== 'undefined')
clearTimeout(glBxEditorOnSpaceEnterTimer);
if (bSpace)
glBxEditorOnSpaceEnterTimer = setTimeout(bx_editor_on_space_enter_in, 500, sCode, sEditorId);
else
bx_editor_on_space_enter_in(sCode, sEditorId);
}
function bx_editor_on_space_enter_in(sCode, sEditorId) {
glBxEditorOnSpaceEnterTimer = undefined;
if (typeof glOnSpaceEnterInEditor !== 'undefined' && glOnSpaceEnterInEditor instanceof Array) {
for (var i = 0; i < glOnSpaceEnterInEditor.length; i++) {
if (typeof glOnSpaceEnterInEditor[i] === "function") {
glOnSpaceEnterInEditor[i](sCode, sEditorId);
}
}
}
}
function bx_editor_remove_img (aEditorIds, aMarkers)
{
for (var i = 0; i < aEditorIds.length; i++) {
var eEditor = $('#' + $('#' + aEditorIds[i]).attr('object_editor'));
// delete images in html editor
for (var k = 0; k < aMarkers.length; k++) {
var jFiles = eEditor.find(aMarkers[k]);
jFiles.each(function () {
$(this).remove();
});
}
}
}
/** @} */