【问题标题】:How to detect when a menu is rendered in tinymce 4?如何检测何时在tinymce 4中呈现菜单?
【发布时间】:2016-04-22 21:29:04
【问题描述】:

tinymce 4 中,会呈现菜单栏,但每个菜单仅在单击时呈现。

为了说明这一点,请注意菜单栏中的每个菜单都有mce-menu 类。

在任何时候,如果没有打开菜单,如果您尝试获取菜单集,您将失败,因为它们尚未呈现:

var menuSet = $('.mce-menu');
// menuSet.length : 0

但是,如果您单击菜单栏标题,比如说insert 菜单,它将被渲染并打开。现在,保持打开状态,转到控制台并重试:

var menuSet = $('.mce-menu');
// menuSet.length : 1

你会得到打开的菜单。

现在,如果您在打开的菜单外单击任意位置关闭它,然后重试:

var menuSet = $('.mce-menu');
// menuSet.length : 1

...菜单不会从 DOM 中删除。这是一个好消息:由于菜单被渲染一次,我们可以获取和操作它。

我对每个 .mce-menu 元素都有一些 DOM 操作,但是当第一次打开每个菜单时,我现在必须这样做。

但是如何处理这样的事件?

我无法从官方文档、论坛或任何地方获得任何线索。

【问题讨论】:

  • 我有完全相同的问题:我想根据编辑器中当前发生的情况来条件激活菜单项。我设法拦截了文档正文上的单击事件,但不幸的是,TinyMCE 拦截了我也需要处理的其他事件,例如焦点、鼠标输入等。问题是应用程序实现了自己的特殊方式来管理和冒泡事件,我还看不到干预这个过程的方法。
  • 嘿,我忘记了那个问题......自从我发布它以来,我找到了一个处理这个问题的好方法。我会在几个小时内回家后在这里发布完整的答案。
  • @Countzero,抱歉耽搁了。您现在可以阅读我的回答:stackoverflow.com/a/42773812/3197383

标签: javascript jquery tinymce tinymce-4


【解决方案1】:

这绝对是可能的,但我们都没有足够了解 JS 事件是如何管理的。

我尝试用旧方式编写事件处理程序:

$('body').on('click', function() { 
    do_stuff();
});

虽然我必须以新的、正确的方式来做:

$('body').on('click', '.mce-btn', function() { 
    do_stuff();
});

这样,事件就得到了正确的管理。

【讨论】:

    【解决方案2】:

    尝试使用 onPostrender 函数:

    editor.addMenuItem("mybtn", {
        type: "menuitem",
        name: 'mybtn',
        onPostRender:function (){
            // write your code here//
        },
    

    【讨论】:

      【解决方案3】:

      我通过编写一个专注于该目的的方便的 `Tinymce 4 插件解决了这个问题。

      当然,这个插件是按照 GNU GPL v2 许可开源的,遵循最初的 Tinymce 许可政策。

      Tinymce 插件菜单控制器:

      https://github.com/sirap-group/tinymce-plugin-menuscontroller

      但是我还没有写文档,我很抱歉。

      但是,您可以通过以下方式使用它:

      安装插件

      从 github 下载最新版本的 tarball,或者更好的是,从 bower 安装它:

      bower install tinymce-plugin-menuscontroller
      

      如果您不知道bower,请在此处发现:https://bower.io (npm i -g bower; bower --help)。

      npm 包尚不可用,我会尽快提供(但欢迎 github 上的任何 Pull Request...)。

      默认情况下,插件文件夹将被下载并放置在./bower_components。如果你以同样的方式安装了 tinymce,你也会得到 ./bower_components/tinymce./bower_components/tinymce-dist

      不需要将脚本添加到您的index.html 文件中,因为如果您正确设置,tinymce 会自行加载它。

      所以你需要:

      1. 将其符号链接到 tinymce 插件文件夹:

        $ cd ./bower_components/tinymce/plugins
        $ ln -s ../../tinymce-plugin-menuscontroller menuscontroller
        
      2. 在tinymce init 中加载它。例如:

        tinymce.init({ 选择器:'textarea', // [...] 插件:“菜单控制器” })

      获取插件实例:

      var editor = window.tinymce.activeEditor
      var menusCtl = editor.plugins.menuscontroller
      // at this point, if menusCtl is undefined, something gone wrong in the setup step: please check the previous steps.
      

      插件 API (v0.2.1)

      实例方法

      获取菜单栏:

      menusCtl.getMenubar()
      

      通过注册名称获取每个菜单:

      menusCtl.getMenuByName(String: name)
      

      获取工具栏

      menusCtl.getToolbars
      

      活动

      事件:menusController:mceMenuRendered 事件

      当任何 tinymce 菜单被渲染时

      $('body').on('menusController:mceMenuRendered', function (evt, menuDomNode) {
        console.log(menuDomNode)
      })
      

      menusController:mceMenuRendered 事件在呈现时为活动编辑器菜单栏的每个菜单调用一个,因此当用户单击下拉菜单时(File 链接用于“文件”菜单,Insert 用于“插入”菜单等...)。

      事件:menusController:mceMenuItemRendered:<menuDomID>

      当任何菜单项被渲染时。假设我们创建了一个带有my-custom-menu-item 标识符的菜单项。所以 tinymce 将其 DOM ID 设置为my-custom-menu-item。因此,MenusController 插件将创建并绑定到主体以下事件:

      menusController:mceMenuItemRendered:my-custom-menu-item
      

      这样你就可以处理你的自定义菜单项的渲染事件了:

      $('body').on('menusController:mceMenuItemRendered:my-custom-menu-item',
        function (evt, menuItemDomNode) {
          console.log(menuItemDomNode)
        }
      )
      

      MenusController API (v0.3.0+)

      写作时间(2017 年 3 月 13 日星期一),最后发布的版本是 v0.2.1。但是v0.3.0 计划很快就会发布,并且会提供一个新的事件,比上一个更有用。

      事件:menusController:mceMenuItemRendered

      当您需要知道菜单项 ID 来处理事件 menusController:mceMenuItemRendered:<menuDomID> 并获取菜单项 DOM 节点作为回调参数时,事件 menusController:mceMenuItemRendered 不需要它,而是将它作为回调参数提供给每个新渲染菜单项:

      $('body').on('menusController:mceMenuItemRendered',
        function (evt, menuItemID) {
          console.log(menuItemID) // 'my-custom-menu-item'
      
          // So you can hanlde all menu item even if you don't know its ID
          // And you can also handle the DOM Node with the selector by ID
          var selector = '#' + menuItemID
          var menuItem = $(selector)
          console.log(menuItem) // jQuery object (the menu item)
        }
      )
      

      【讨论】:

        【解决方案4】:

        使用 tinymce,您可以通过 editor 对象完全自定义菜单按钮:

        tinymce.init({
          /*....*/
          setup: function(editor) {
            editor.addButton('mybutton', {
              type: 'menubutton',
              text: 'My button',
              icon: false,
              onclick: function(){
                alert('Some Message');
              },
              menu: [{
                text: 'Menu item 1',
                onclick: function() {
                  alert('Some Message');
                }
              }]
            });
          }
         /*....*/
        });
        

        不幸的是,您不能在 text 属性中插入 html,但我认为您可以通过更多研究来做到这一点。也可以为菜单按钮的点击事件创建回调函数。

        就我个人而言,我会使用 tinymce 官方 api 来修改 dom,而不是做一些其他事件驱动的 dom 操作。

        你可以找到更多的好例子here

        【讨论】:

        • 不要认为这些信息与 OP 试图做的事情有关:问题是关于在初始化之后操作菜单,所以暗示在这个阶段发生的事情没有帮助。跨度>
        • 在我看来,操纵 javascript 驱动的 DOM 监听未记录的事件从来都不是一个安全/好主意。特别是在像 tinyMce 这样的复杂插件中。这种事情总是以不可预知的方式适得其反。因为 OP 没有解释所需的操作类型,所以我建议阅读官方 api,看看是否有办法通过记录的 api 实现相同的 api。
        • 我可以看到你来自哪里,并且绝对同意适得其反的问题。尽管如此,我们中的一些人还是以一些奇怪的方式使用 TinyMCE(在我的例子中,我试图让它管理 XML/TEI 标记)并且需要那种信息。恕我直言,这取决于询问者是否考虑尝试这种体验是否是个好主意。顺便说一句,我很快就会在下面发布一个解决方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-22
        • 2018-08-08
        • 1970-01-01
        • 1970-01-01
        • 2013-09-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多