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

7

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

以下是我的widget.xml文件中的重要部分:

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

我想知道是否有一种方法可以扩展Magento的功能以允许类似于这样的所见即所得编辑器:
<parameters>            
    <description translate="label">
        <required>0</required>
        <visible>1</visible>
        <label>Description</label>
        <type>WYSIWYG</type>
    </description>
</parameters>

有没有人遇到类似的问题?.. 或者有没有人知道如何实现这个功能?也许可以通过自定义渲染器来调用所见即所得编辑器,但是如何实现呢..?

提前致谢。

4个回答

7

我终于自己完成了。对于所有遇到同样问题的人,这是我的解决方法:

在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>

为了在小部件的文本区域上启用所见即所得编辑器,我在我的自定义模块中创建了一个新的块类,并扩展了 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编辑器视图中的小部件时将单引号转换为双引号。
希望对某些人有所帮助。

1
这里有一个问题 -- 在 MyCompany_MyModule_Block_Widget_Wysiwyg 中添加 $editor->getConfig()->setPlugins(array());,否则你会收到一个警告: /path/to/root/lib/Varien/Data/Form/Element/Editor.php 中的 Invalid argument supplied for foreach() - Phil Birnie
我尝试了你的代码,但是出现了“error in [unknown object].fireEvent(): event name: formSubmit error message: Cannot set property 'value' of null”的错误。我正在使用Magento版本1.9.0.1。(编辑器显示正确,但在保存后出现此错误)请帮帮我。 - VijayS91

3

我认为这种方法不再兼容Magento 1.9。 我尝试了这种方法,但在保存添加了小部件的CMS块/页面时,我一直收到JavaScript错误消息。

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


我也是。我把小部件代码从Magento 1.8复制到1.9,然后开始出现这个错误。 - Alan

1

所以,已知的解决方案在1.9+上似乎不再起作用,因此我提供了一种替代方案,它添加了所见即所得编辑器,但使用了另一种编辑器。

我使用了这个编辑器:

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

最终结果如下:

enter image description here

步骤1:下载编辑器文件并放置在adminhtml皮肤区域:

例如,我将它们放置在skin/adminhtml/default/js/wysiwyg中。

enter image description here

步骤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;
    }

}

在那里,您还可以注意到这个片段:

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

这里的目的是将任何双引号(")更改为正确的HTML实体&quot,以防止在小部件参数中存储被双引号包围的文本数据。

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

<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>

完成。

希望这对某人有用。


0

基于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> 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接