从 TinyMCE 选择中提取样式

Pulling a style from a TinyMCE selection

我正在尝试实现一个 TinyMCE 按钮,它将选择的样式应用到整个框。 I'm having trouble, though, reading the style of the selection when the selection is buried in a span in a span in a paragraph.让我们以 'color' 为例。下面我有一个带有一些文本的框,我在段落中选择了 "here" 并将其设为红色。

该段落的 HTML 现在是:

将选择的样式应用于框的按钮背后的代码是

 var selected_color = $(ed.selection.getNode()).css('color');
 console.log("color pulled is ", selected_color);
$(ed.bodyElement).css('color', selected_color);

它不起作用,因为拉出的颜色是黑色,而不是红色,所以第三行只是重新应用已经存在的黑色。 (如果我将第三行的 selected_color 替换为 'blue' 一切都会变成蓝色。)所以问题是拉动当前选择的颜色。

有谁知道我如何才能可靠地做到这一点,无论选择多么隐蔽?

感谢您的帮助。

我也注意到有些奇怪的行为,有嵌套跨度和 div 的选择,但老实说我无法识别这是否是 TinyMCE 的错误,浏览器问题或两者的结合(最有可能)。

因此,在等待您提供更多信息(也许还有您的插件代码)的同时,我意识到 两个 提议来实现您想要的:第一个插件的行为类似于在 word 格式刷中,第二个是简单地将当前检测到的前景色应用于整个段落。

当您使用键盘或鼠标在编辑器中移动时,您会看到当前检测到的前景色 突出显示并作为背景应用到第二个插件按钮。

这里的关键点是从光标位置取回样式的两个函数:

  function findStyle(el, attr) {
    var styles, style, color;
    try {
      styles = $(el).attr('style');
      if(typeof styles !== typeof undefined && styles !== false) {
        styles.split(";").forEach(function(e) {
          style = e.split(":");
          if($.trim(style[0]) === attr) {
            color = $(el).css(attr);
          }
        });
      }
    } catch (err) {}
    return color;
  }

  function findForeColor(node) {
    var $el = $(node), color;
    while ($el.prop("tagName").toUpperCase() != "BODY") {
      color = findStyle($el, "color");
      if (color) break;
      $el = $el.parent();
    }
    return color;
  }

需要 try...catch 块来避免在重新设置所选文本样式时偶尔出现一些错误。如果您查看 TinyMCE 源代码,您会注意到大量的计时事件,这是处理样式和 css 时不可避免的常见做法,在用户交互时更是如此。 TinyMCE 的作者在制作编辑器 cross-browser.

方面做得非常出色

您可以试用下面Fiddle中的第一个插件。第二个插件比第一个更简单。 lastForeColor是在ed.on('NodeChange')中确定的,所以点击按钮的代码非常简单。

  tinymce.PluginManager.add('example2', function(ed, url) {
    // Add a button that opens a window
    ed.addButton('example2', {
      text: '',
      icon: "apply-forecolor",
      onclick: function() {
        if(lastForeColor) {
          var applyColor = lastForeColor;
          ed.execCommand('SelectAll');
          ed.fire('SelectionChange');
          ed.execCommand('forecolor', false, applyColor);
          ed.selection.collapse(false);
          ed.fire('SelectionChange');
        }
        return false;
      }
    });
  });

此外:我认为您的代码片段存在潜在问题:

$(ed.bodyElement).css('color', selected_color);

我想应该以不同的方式应用样式,所以在我的示例中,我使用标准的 TinyMCE 命令将前景色应用于所有对象,因为我无法完全 将您的屏幕截图转换为代码。请在评论中分享您的想法。

Fiddle 两个插件:https://jsfiddle.net/ufp0Lvow/

去块剂,

很棒的作品!谢谢!

您的 jsfiddle 成功了。我用示例中的内容替换了 HTML,并将 tinymce.init 中的选择器从文本区域更改为 div,它完美地从示例中提取了颜色。修改后的 jsfiddle 位于 https://jsfiddle.net/79r3vkyq/3/ 。我会长期研究和学习你的代码。

关于您关于

的问题
$(ed.bodyElement).css('color', selected_color);

我将 tinymce 附加到的 divs 都有 id,编辑器当前附加到的那个在 ed.bodyElement 中报告。我使用这个没有任何问题,但我使用你的

没有问题
ed.execCommand('SelectAll');
ed.fire('SelectionChange');
ed.execCommand('forecolor', false, applyColor);

再次感谢!干得好!