Browse Source

Ticket #5384 - Add some way to disable visual editor.

AntonLV 6 months ago
parent
commit
2b6f296efc

+ 16 - 2
inc/classes/BxDolEditor.php

@@ -179,13 +179,27 @@ class BxDolEditor extends BxDolFactory implements iBxDolFactoryObject
      * Attach editor to HTML element, in most cases - textarea.
      * @param $sSelector - jQuery selector to attach editor to.
      * @param $iViewMode - editor view mode: BX_EDITOR_STANDARD, BX_EDITOR_MINI, BX_EDITOR_FULL
-     * @param $bDynamicMode - is AJAX mode or not, the HTML with editor area is loaded synamically.
+     * @param $bDynamicMode - is AJAX mode or not, the HTML with editor area is loaded dynamically.
+     * @param $aAttrs - array of additional attributes/parameters
      */
-    public function attachEditor ($sSelector, $iViewMode, $bDynamicMode = false)
+    public function attachEditor ($sSelector, $iViewMode, $bDynamicMode = false, $aAttrs = [])
     {
         // override this function in particular editor class
     }
 
+    /**
+     * Get HTML editors info.
+     * @param $sSelector - jQuery selector to attach editor to.
+     * @param $iViewMode - editor view mode: BX_EDITOR_STANDARD, BX_EDITOR_MINI, BX_EDITOR_FULL
+     * @param $bDynamicMode - is AJAX mode or not, the HTML with editor area is loaded dynamically.
+     * @param $aAttrs - array of additional attributes/parameters
+     */
+    public function getEditorInfo ($sSelector, $iViewMode, $bDynamicMode = false, $aAttrs = [])
+    {
+        // override this function in particular editor class
+        return [];
+    }
+
     /**
      * Add css/js files which are needed for editor display and functionality.
      */

+ 26 - 22
inc/js/editor.quill.js

@@ -5,7 +5,9 @@
  * @defgroup    UnaCore UNA Core
  * @{
  */
-function bx_editor_init(oEditor, oParams){
+function bx_editor_init(oParams) {
+    var oEditor = null;
+
     hljs.configure({   
         languages: ['javascript', 'php', 'html', 'css']
     });
@@ -360,7 +362,10 @@ function bx_editor_init(oEditor, oParams){
     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) => {
@@ -422,9 +427,9 @@ function bx_editor_init(oEditor, oParams){
     $(oParams.selector).next().find('span.ql-background').attr('title', _t('_sys_txt_quill_tooltip_background'));
     $(oParams.selector).next().find('span.ql-align').attr('title', _t('_sys_txt_quill_tooltip_align'));
     $(oParams.selector).next().find('span.ql-header').attr('title', _t('_sys_txt_quill_tooltip_header'));
-	
-	$('#' + oParams.name).find('.ql-editor').addClass('bx-def-vanilla-html');
-    
+
+    $('#' + oParams.name).find('.ql-editor').addClass('bx-def-vanilla-html');
+
     if (bEmptyToolbar)
         $(oParams.selector).next().hide();
 
@@ -434,23 +439,23 @@ function bx_editor_init(oEditor, oParams){
         return delta; 
     });
     
-    if (oParams.insert_as_plain_text){
+    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
+            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 => {
+            delta.forEach(e => {
                 //if(typeof e.insert == 'string' && e.attributes == null)
                 //    e.insert = e.insert.replace(/\n/g, '') + "\n";
 
@@ -487,7 +492,7 @@ function bx_editor_init(oEditor, oParams){
         }
         $(oParams.selector).val(sVal); 
     });
-    
+
     return oEditor
 }
     
@@ -498,8 +503,7 @@ function bx_editor_activate(oEditor)
 
 function bx_editor_insert_html (sEditorId, sImgId, sHtml) 
 {
-
-    if ($('#' + sEditorId) &&  $('#' + sEditorId).attr('object_editor')){
+    if ($('#' + sEditorId) &&  $('#' + sEditorId).attr('object_editor')) {
         eval ('oEditor = ' + $('#' + sEditorId).attr('object_editor'));
         if (oEditor.getSelection())
             oEditor.clipboard.dangerouslyPasteHTML(oEditor.getSelection().index, sHtml, 'api');
@@ -512,7 +516,7 @@ function bx_editor_insert_img (sEditorId, sImgId, sImgUrl, sClasses)
 {
     if ('undefined' == typeof(sClasses))
         sClasses = '';
-    
+
     bx_editor_insert_html(sEditorId, sImgId, '<img id="' + sImgId + '" class="' + sClasses + '" src="' + sImgUrl + '" />')
 }
 
@@ -520,7 +524,7 @@ 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

+ 1 - 0
modules/boonex/english/data/langs/system/en.xml

@@ -3006,6 +3006,7 @@ If it is not enabled then please consider implement this optimization, since it
         <string name="_sys_form_input_labels_placeholder"><![CDATA[Add Label]]></string>
         <string name="_sys_form_input_password_show"><![CDATA[Show password]]></string>
         <string name="_sys_form_input_password_hide"><![CDATA[Hide password]]></string>
+        <string name="_sys_form_input_textarea_editor"><![CDATA[Editor:]]></string>
         <string name="_sys_form_labels"><![CDATA[Labels]]></string>
         <string name="_sys_form_labels_display_select"><![CDATA[Select labels display]]></string>
         <string name="_sys_form_labels_input_caption_system_name"><![CDATA[Name]]></string>

+ 1 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -2982,6 +2982,7 @@
 	<string name="_sys_form_input_labels_placeholder"><![CDATA[Добавить метку]]></string>
         <string name="_sys_form_input_password_show"><![CDATA[Показать пароль]]></string>
         <string name="_sys_form_input_password_hide"><![CDATA[Скрыть пароль]]></string>
+        <string name="_sys_form_input_textarea_editor"><![CDATA[Редактор:]]></string>
         <string name="_sys_form_labels"><![CDATA[Метки]]></string>
         <string name="_sys_form_labels_display_select"><![CDATA[Выбор метки]]></string>
         <string name="_sys_form_labels_input_caption_system_name"><![CDATA[Имя]]></string>

+ 8 - 0
template/form_field_textarea.html

@@ -1 +1,9 @@
+<bx_if:show_switcher>
+    <div class="__class__ relative">
+        <div class="flex absolute -top-7 right-0 space-x-2">
+            <div>__title__</div>
+            <div>__switcher__</div>
+        </div>
+    </div>
+</bx_if:show_switcher>
 <textarea __attrs__>__value__</textarea>

+ 62 - 39
template/scripts/BxBaseEditorQuill.php

@@ -16,21 +16,37 @@ class BxBaseEditorQuill extends BxDolEditor
     /**
      * Common initialization params
      */
-    
     protected static $CONF_COMMON = "
-        var oParams = {              
-            skin: '{bx_var_skin}',
-            name: '{bx_var_editor_name}',
-            selector: '{bx_var_selector}',
-            css_class: '{bx_var_css_additional_class}',
-            toolbar: {toolbar},
-            root_url: '{bx_url_root}',
-            query_params: {bx_var_query_params},
-            insert_as_plain_text: {insert_as_plain_text},
-            empty_tags: {empty_tags},
-            allowed_tags: {allowed_tags}
-        }
-        {bx_var_editor_name} = bx_editor_init({bx_var_editor_name}, oParams);";
+        window.{bx_var_editor_call_init} = function() {
+            var oTextarea = $('{bx_var_selector}');
+            if(!oTextarea.length || typeof({bx_var_editor_name}) != 'undefined')
+                return;
+
+            {bx_var_editor_name} = bx_editor_init({              
+                skin: '{bx_var_skin}',
+                name: '{bx_var_editor_name}',
+                selector: '{bx_var_selector}',
+                css_class: '{bx_var_css_additional_class}',
+                toolbar: {toolbar},
+                root_url: '{bx_url_root}',
+                query_params: {bx_var_query_params},
+                insert_as_plain_text: {insert_as_plain_text},
+                empty_tags: {empty_tags},
+                allowed_tags: {allowed_tags}
+            });
+
+            oTextarea.addClass('bx-form-input-html').hide();
+        };
+        window.{bx_var_editor_call_destroy} = function() {
+            var oTextarea = $('{bx_var_selector}');
+            if(!oTextarea.length || typeof({bx_var_editor_name}) == 'undefined')
+                return;
+
+            {bx_var_editor_name} = undefined;
+
+            oTextarea.siblings('.ql-toolbar,.ql-container').remove();
+            oTextarea.removeClass('bx-form-input-html').show();
+        };";
    
     /**
      * Standard view initialization params
@@ -68,37 +84,38 @@ class BxBaseEditorQuill extends BxDolEditor
      */
     public function attachEditor ($sSelector, $iViewMode = BX_EDITOR_STANDARD, $bDynamicMode = false, $aAttrs = [])
     {
+        // set visual mode
         $sAllowedTags = '';
         $sToolbarItems = '';
-        // set visual mode
         switch ($iViewMode) {
             case BX_EDITOR_MINI:
                 $sToolbarItems = getParam('sys_quill_toolbar_mini');
                 $sAllowedTags = getParam('sys_quill_allowed_tags_mini');
                 $sCustomInit = self::$CONF_MINI;
                 break;
-                
+
             case BX_EDITOR_FULL:
                 $sToolbarItems = getParam('sys_quill_toolbar_full');
                 $sAllowedTags = getParam('sys_quill_allowed_tags_full');
                 $sCustomInit = self::$CONF_FULL;
-            break;
-                
+                break;
+
             case BX_EDITOR_STANDARD:
             default:
                 $sToolbarItems = getParam('sys_quill_toolbar_standard');
                 $sAllowedTags = getParam('sys_quill_allowed_tags_standard');
                 $sCustomInit = self::$CONF_STANDARD;
         }
-        
-        if ($this->_sButtonsCustom !== false) {
+
+        if($this->_sButtonsCustom !== false)
             $sToolbarItems = $this->_sButtonsCustom;
-        }
 
         $sEditorName = 'quill_' . str_replace(['-', ' '], '_', $aAttrs['form_id'] . '_' . $aAttrs['element_name'] . '_' . $aAttrs['uniq']);
-        
+        $sEditorCallInit = $sEditorName . '_init';
+        $sEditorCallDestroy = $sEditorName . '_destroy';
+
         // initialize editor
-        $sInitEditor = $this->_replaceMarkers(self::$CONF_COMMON, array(
+        $sInitEditor = $this->_replaceMarkers(self::$CONF_COMMON, [
             'bx_var_custom_init' => $sCustomInit,
             'bx_var_selector' => bx_js_string($sSelector. '.' . $aAttrs['uniq'], BX_ESCAPE_STR_APOS),
             'bx_var_query_params' => isset($aAttrs['query_params']) ? json_encode($aAttrs['query_params']) : "''",
@@ -110,36 +127,42 @@ class BxBaseEditorQuill extends BxDolEditor
             'bx_var_css_additional_class' => $sToolbarItems ? '' : 'bx-form-input-html-quill-empty',
             'bx_var_element_name' => str_replace(['-', ' '], '_', $aAttrs['element_name']),
             'bx_var_editor_name' => $sEditorName,
+            'bx_var_editor_call_init' => $sEditorCallInit,
+            'bx_var_editor_call_destroy' => $sEditorCallDestroy,
             'bx_var_skin' => bx_js_string($this->_aObject['skin'], BX_ESCAPE_STR_APOS),
             'bx_url_root' => bx_js_string(BX_DOL_URL_ROOT, BX_ESCAPE_STR_APOS)
-        ));
-        $sInitEditor = "
-            if(!Quill.imports['modules/imageUploader'])
-                Quill.register('modules/imageUploader', ImageUploader);
-        " . $sInitEditor;
-
-        $sInitCallBack = "
-            bQuillEditorInited = true;
-        " . $sInitEditor;
+        ]);
 
-        if ($bDynamicMode) {
+        $sScript = "var " . $sEditorName . " = undefined; ";
+        if($bDynamicMode) {
             list($aJs, $aJsTranslations, $aCss) = $this->_getJsCss(true);
 
-            $sScript = "var " . $sEditorName . ";"; 
-            $sScript .= $this->_oTemplate->addJsPreloaded($aJs, $sInitCallBack, "typeof bQuillEditorInited === 'undefined'", $sInitEditor . ';');
+            $sInitAndCall = $sInitEditor . $sEditorCallInit . '();';
+            $sScript .= $this->_oTemplate->addJsPreloaded($aJs, $sInitAndCall, "typeof(Quill) === 'undefined'", $sInitAndCall);
             $sScript = $this->_oTemplate->_wrapInTagJsCode($sScript);
-            $sScript .= $this->_oTemplate->addJsTranslation($aJsTranslations, true);
 
+            $sScript = $this->_oTemplate->addJsTranslation($aJsTranslations, true) . $sScript;
             $sScript = $this->_oTemplate->addCss($aCss, true) . $sScript;
-        } 
+        }
         else {
-            $sScript = "var " . $sEditorName . "; " . $this->_oTemplate->addJsCodeOnLoad($sInitCallBack);
+            $sScript .= $sInitEditor . $this->_oTemplate->addJsCodeOnLoad($sEditorCallInit . '()');
             $sScript = $this->_oTemplate->_wrapInTagJsCode($sScript);
         }
 
         return $this->_addJsCss($bDynamicMode) . $sScript;
     }
-    
+
+    public function getEditorInfo ($sSelector, $iViewMode = BX_EDITOR_STANDARD, $bDynamicMode = false, $aAttrs = [])
+    {
+        $sEditorName = 'quill_' . str_replace(['-', ' '], '_', $aAttrs['form_id'] . '_' . $aAttrs['element_name'] . '_' . $aAttrs['uniq']);
+
+        return [
+            'name' => $sEditorName,
+            'selector' => $sSelector. '.' . $aAttrs['uniq'],
+            'js_call_init' => $sEditorName . '_init()',
+            'js_call_destroy' => $sEditorName . '_destroy()'
+        ];
+    }
 
     /**
      * Add css/js files which are needed for editor display and functionality.

+ 51 - 8
template/scripts/BxBaseFormView.php

@@ -1621,21 +1621,46 @@ BLAH;
         $aAttrs = $this->_genInputTextareaAttrs($aInput);
 
         $sUniq = genRndPwd(10, false);
-        
         $sClassAdd = "bx-def-font-inputs bx-form-input-{$aInput['type']}";
-        if(isset($aInput['html']) && $aInput['html'] && $this->addHtmlEditor($aInput['html'], $aInput, $sUniq)){
+
+        $bHtml = $bHtmlEditor = false;
+        if(($bHtmlEditor = ($bHtml = (bool)($aInput['html'] ?? false)) && $this->addHtmlEditor($aInput['html'], $aInput, $sUniq))) {
             $sClassAdd .= ' bx-form-input-html ' . $sUniq;
         }
 
-        if(isset($aInput['code']) && $aInput['code'] && $this->addCodeEditor($aInput['code'], $aInput, $sUniq)){
+        $bCode = $bCodeEditor = false;
+        if(($bCodeEditor = ($bCode = (bool)($aInput['code'] ?? false)) && $this->addCodeEditor($aInput['code'], $aInput, $sUniq))) {
             $sClassAdd .= ' bx-form-input-code ' . $sUniq;
         }
 
-        $sValue = isset($aInput['value']) ? bx_process_output((isset($aInput['html']) && $aInput['html']) || (isset($aInput['code']) && $aInput['code']) ? $aInput['value'] : strip_tags($aInput['value']), BX_DATA_TEXT, array('no_process_macros')) : '';
+        $aTmplVarsSwitcher = [];
+        if($bHtmlEditor && ($aHtmlEditor = $this->getHtmlEditorInfo($aInput['html'], $aInput, $sUniq))) {
+            if(($sJsInit = ($aHtmlEditor['js_call_init'] ?? false)) && ($sJsDestroy = ($aHtmlEditor['js_call_destroy'] ?? false))) {
+                $aInputSwitcher = [
+                    'type' => 'switcher',
+                    'name' => $aInput['name'] . '_switcher',
+                    'checked' => true,
+                    'attrs' => [
+                        'onchange' => "if($(this).prop('checked')) " . $sJsInit . "; else " . $sJsDestroy . ";",
+                    ],
+                ];
+                $aTmplVarsSwitcher = [
+                    'class' => 'bx-form-input-' . $aInput['type'] . '-switcher',
+                    'title' => _t('_sys_form_input_textarea_editor'),
+                    'switcher' => $this->genInputSwitcher($aInputSwitcher)
+                ];
+            }
+        }
+
+        $sValue = isset($aInput['value']) ? bx_process_output($bHtml || $bCode ? $aInput['value'] : strip_tags($aInput['value']), BX_DATA_TEXT, ['no_process_macros']) : '';
 
         return $this->oTemplate->parseHtmlByName('form_field_textarea.html', [
             'attrs' => bx_convert_array2attrs($aAttrs, $sClassAdd),
-            'value' => $sValue
+            'value' => $sValue,
+            'bx_if:show_switcher' => [
+                'condition' => !empty($aTmplVarsSwitcher),
+                'content' => $aTmplVarsSwitcher
+            ]
         ]);
     }
 
@@ -1654,19 +1679,37 @@ BLAH;
 
     function isHtmlEditor($iViewMode, &$aInput)
     {
-		return BxDolEditor::getObjectInstance(false, $this->oTemplate) !== false;
+        return BxDolEditor::getObjectInstance(false, $this->oTemplate) !== false;
     }
 
     function addHtmlEditor($iViewMode, &$aInput, $sUniq)
     {
         $oEditor = BxDolEditor::getObjectInstance(false, $this->oTemplate);
-        if (!$oEditor)
+        if(!$oEditor)
             return false;
 
-        $this->_sCodeAdd .= $oEditor->attachEditor ('#' . $this->aFormAttrs['id'] . ' [name=' . $aInput['name'] . ']', $iViewMode, $this->_bDynamicMode, ['form_id' => $this->aFormAttrs['id'], 'element_name' => $aInput['name'], 'query_params' => $this->getHtmlEditorQueryParams($aInput), 'uniq' => $sUniq]);
+        $this->_sCodeAdd .= $oEditor->attachEditor ('#' . $this->aFormAttrs['id'] . ' [name=' . $aInput['name'] . ']', $iViewMode, $this->_bDynamicMode, [
+            'form_id' => $this->aFormAttrs['id'], 
+            'element_name' => $aInput['name'], 
+            'query_params' => $this->getHtmlEditorQueryParams($aInput), 
+            'uniq' => $sUniq
+        ]);
 
         return true;
     }
+
+    function getHtmlEditorInfo($iViewMode, &$aInput, $sUniq)
+    {
+        $oEditor = BxDolEditor::getObjectInstance(false, $this->oTemplate);
+        if(!$oEditor)
+            return false;
+
+        return $oEditor->getEditorInfo('#' . $this->aFormAttrs['id'] . ' [name=' . $aInput['name'] . ']', $iViewMode, $this->_bDynamicMode, [
+            'form_id' => $this->aFormAttrs['id'], 
+            'element_name' => $aInput['name'], 
+            'uniq' => $sUniq
+        ]);
+    }
     
     function addCodeEditor($iViewMode, &$aInput, $sUniq)
     {