Magento - 将所见即所得编辑器添加到自定义小部件

Posted

技术标签:

【中文标题】Magento - 将所见即所得编辑器添加到自定义小部件【英文标题】:Magento - add WYSIWYG editor to custom widget 【发布时间】:2013-03-23 23:17:47 【问题描述】:

我在自定义模块中创建了一个小部件。一切正常,小部件可以嵌入到 CMS 页面上。但是,我想添加一个所见即所得的编辑器,而不是 textarea 参数类型。

这是我的 widget.xml 中的重要部分:

<parameters>            
    <description translate="label">
        <required>0</required>
        <visible>1</visible>
        <label>Description</label>
        <type>textarea</type>
    </description>
</parameters>

我想知道是否有一种方法可以扩展 Magento 的功能以允许类似于这样的 WYSIWYG 编辑器:

<parameters>            
    <description translate="label">
        <required>0</required>
        <visible>1</visible>
        <label>Description</label>
        <type>WYSIWYG</type>
    </description>
</parameters>

有人遇到过类似的问题吗? ..或者有谁知道如何做到这一点?也许通过调用 WYSIWYG 编辑器的自定义渲染器,但是如何..?

提前感谢。

【问题讨论】:

【参考方案1】:

我终于自己做到了。对于所有有同样问题的人,我就是这样做的:

在widget.xml我有如下参数设置:

<parameters>            
    <text translate="label">
        <required>1</required>
        <visible>1</visible>
        <label>Specify text</label>
        <description>No double quotes allowed, use single quotes instead!</description>
        <type>cmswidget/widget_wysiwyg</type>
    </text>
</parameters>

为了在小部件的 textarea 上启用 WYSIWYG 编辑器,我在自定义模块中创建了一个新的块类,扩展了 Mage_Adminhtml_Block_Widget_Form_Renderer_Fieldset_Element 类并覆盖了 render() 函数:

class MyCompany_MyModule_Block_Widget_Wysiwyg extends Mage_Adminhtml_Block_Widget_Form_Renderer_Fieldset_Element

    public function render(Varien_Data_Form_Element_Abstract $element)
    
        $editor = new Varien_Data_Form_Element_Editor($element->getData());
        $editor->setId($element->getId());
        $editor->setForm($element->getForm());
        $editor->setWysiwyg(true);
        $editor->setForceLoad(true);
        return parent::render($editor);
    

现在,我很高兴看到小部件中的编辑器。不幸的是,仍然存在问题。由于编辑器使用双引号创建内联样式和属性并将其作为小部件属性放置到 CMS 页面 - 它本身也是双引号,因此无法正确呈现小部件。为了解决这个问题,我扩展了 Mage_Widget_Model_Widget 类并将编辑器双引号替换为单引号,如下所示:

class MyCompany_MyModule_Model_Widget extends Mage_Widget_Model_Widget

    public function getWidgetDeclaration($type, $params = array(), $asIs = true)
    

        if( preg_match('~(^mymodule/myblockclass)~', $type) )
        
            $params['text'] = str_replace('"', "'", $params['text']);

        
        return parent::getWidgetDeclaration($type, $params, $asIs);
    

在 getWidgetDeclaration() 函数中,我检查小部件类型是否是我想要处理的类型。小部件类型在 widget.xml 中为每个小部件指定,如下所示:

<MyCompany_MyModule_MyWidgetName type="mymodule/myblockclass" translate="name description" module="mymodule">
<!-- ... -->
</MyCompany_MyModule_MyWidgetName>

现在我的一切都按照我想要的方式运行了。编辑器生成的 HTML 将其双引号替换为单引号,并且输出将完美运行。在我像这样转义双引号之前 - \"some text \"。起初这似乎可行,但是当通过单击图标(编辑器视图)编辑小部件时,html 被切断了。 Magento 的 javascript 似乎以自己的方式转义了字符串。但是,上述方法将起作用,因为我只是在插入小部件时将双引号替换为单引号,而 Magento 在 CMS 编辑器视图中打开小部件时会将单引号转换为双引号。

希望这对某人有用。

【讨论】:

这里有一个问题——将$editor-&gt;getConfig()-&gt;setPlugins(array());添加到MyCompany_MyModule_Block_Widget_Wysiwyg,否则你会收到警告:Invalid argument supplied for foreach() in /path/to/root/lib/Varien/Data/Form/Element/Editor.php 我已经在您的代码上方尝试过,我收到“[未知对象].fireEvent() 中的错误:事件名称:formSubmit 错误消息:无法设置属性‘值’为空”这个错误。我正在使用 Magento 1.9.0.1 版。 (编辑器显示正确,但在节省时间后我收到此错误)。请帮助我【参考方案2】:

我认为这不再与 Magento 1.9 兼容。 我已经尝试过这种方法,但在保存添加了小部件的 cms 块/页面时,我不断收到 javascript 错误

错误:[未知对象].fireEvent() 中的错误: 事件名称:formSubmit 错误信息:无法将属性“值”设置为 null

【讨论】:

这里也一样。我将小部件代码从 Magento 1.8 复制到 1.9 并开始出现此错误。【参考方案3】:

基于 Rouzbeh,我添加了小的 jQuery 代码来验证是否使用了双引号:

<description>
<![CDATA[
<script>
jQuery("#widget_options textarea").keyup(function()
if(jQuery(this).val().indexOf('"') > -1)
  jQuery(this).val(jQuery(this).val().replace('"',"'"));
  alert('No double quotes allowed, use single quotes instead.')

);
</script>
]]>                
</description> 

【讨论】:

【参考方案4】:

因此,已知的解决方案似乎不再适用于 1.9+,所以我制作了一个替代方案,它添加了所见即所得,但使用了替代编辑器。

我用过这个编辑器:

https://alex-d.github.io/Trumbowyg/

最终结果如下:

第一步:在adminhtml皮肤区下载编辑器文件和速度:

在我的示例中,我将它们放在skin/adminhtml/default/js/wysiwyg

第 2 步:在您的模块中,您需要定义管理布局更新,并在您的 adminhtml 布局文件中,添加指令以加载库文件(和 jquery)

因为我希望它只显示 n CMS 页面编辑,所以我通过适当的句柄添加:

<adminhtml_cms_page_edit>
        <reference name="head">
            <action method="addJs">
                <script>lib/jquery/jquery-1.12.0.js</script>
            </action>
            <action method="addJs">
                <script>lib/jquery/noconflict.js</script>
            </action>
            <action method="addItem"><type>skin_js</type><name>js/wysiwyg/trumbowyg.min.js</name></action>
            <action method="addItem"><type>skin_css</type><name>js/wysiwyg/ui/trumbowyg.min.css</name></action>
        </reference>
    </adminhtml_cms_page_edit>

第 3 步:创建一个新的小部件类来呈现元素:

在我的示例中,我将这是一个模块放在 BLOCKS 下

基本上,这需要小部件 xml 定义的元素,并将其转换为 textarea 元素,然后附加所需的 javascript (jquery) 以初始化所见即所得的编辑器。

您将看到传递给编辑器的选项,在 $options 中定义

<?php
class ProxiBlue_Landingpage_Block_Widgets_Wysiwyg extends Mage_Adminhtml_Block_Widget_Form_Renderer_Fieldset_Element

    public function render(Varien_Data_Form_Element_Abstract $element)
    
        $textarea = new Varien_Data_Form_Element_Textarea();
        $textarea->setForm($element->getForm())
            ->setId($element->getHtmlId())
            ->setName($element->getName())
            ->setLabel($element->getLabel())
            ->setClass('widget-option input-area input-text');
        if ($element->getRequired()) 
            $textarea->addClass('required-entry');
        
        if ($element->getValue()) 
            $textarea->setValue($element->getValue());
        
        $options = "btns: ['viewHTML', 'strong', 'em', 'del', 'undo', 'redo', 'formatting', 'superscript', 'subscript', 'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull', 'unorderedList', 'orderedList', 'horizontalRule', 'fullscreen'],
                    semantic: true,
                    removeformatPasted: true,
                    autogrow: false";

        $textarea->setData('after_element_html',
            "<script>jQuery(document).ready(
                function()  
                    jQuery(" . $element->getHtmlId() .").trumbowyg( " . $options . " )
                    .on('tbwblur', function() 
                        var html = jQuery(this).trumbowyg('html');
                        html = html.replace(/\"/g, '&quot;');
                        jQuery(this).trumbowyg('html', html);
                    ); 
                    );</script>");

        $html = parent::render($textarea);

        return $html;
    


在那里你可能还会注意到这个sn-p:

.on('tbwblur', function() 
   var html = jQuery(this).trumbowyg('html');
   html = html.replace(/\"/g, '&quot;');
   jQuery(this).trumbowyg('html', html);
); 

这里的目的是将任何双引号(“)更改为&amp;quot的正确html实体 这是为了防止将文本数据存储在用双引号括起来的小部件参数中。

第 4 步:定义小部件元素:

<text_blurb translate="label">
                <sort_order>50</sort_order>
                <label>Textual Content</label>
                <visible>1</visible>
                <required>1</required>
                <type>landingpage/widgets_wysiwyg</type>
            </text_blurb>

完成。

希望这对某人有用。

【讨论】:

以上是关于Magento - 将所见即所得编辑器添加到自定义小部件的主要内容,如果未能解决你的问题,请参考以下文章

2sxc 10+,是否可以向TinyMCE所见即所得编辑器添加菜单/命令?

向WordPress所见即所得编辑器添加按钮

什么是最好的非所见即所得文本区域编辑器?

集成 Markdown 所见即所得文本编辑器

Summernote 所见即所得编辑器无法使用 Laravel 5.8 正确呈现数据

GWT 的所见即所得编辑器组件