通过 jQuery 将自定义 类 插入由 tinyMCE 呈现的 WYSIWIG 输出(在 Wordpress 中处理带有字幕的图像)

Insert custom classes into WYSIWIG output rendered by tinyMCE via jQuery (handling images with captions in Wordpress)

前言/初始问题:

我希望用户能够使用可视化编辑器(即 "classic editor" / tinyMCE - 我无法使用Gutenberg,因为这些是使用 PODS 创建的自定义 post 类型,其中块编辑器不可用)。这些 classes 是在我创建的样式表中定义的。他们的主要特征是 width 有一个百分比值和一个固定的 100% 值用于媒体查询中的较小屏幕 - 我不喜欢固定图像大小的 Wordpress 系统,在某些时候/屏幕宽度在浮动时看起来很荒谬.我正在使用 "TinyMCE Custom Styles" 插件将这些 classes 放入编辑器的 "Format" 菜单中。用户可以通过 select 编辑图像并从该菜单中选择 class 将它们应用于图像。

如果将这些 class 应用于 没有标题的图像,这将完美工作:这些是呈现为常规 img 标签,如果选择任何 link 选项,则可以选择在它们周围使用 a 标签: class 具有预期效果,其中的所有样式都适用。

但是,如果用户决定使用标题,图像的处理方式将完全不同:Wordpress 会自动在其周围创建一个 figure 标签,其中包含 img 和一个 figcaption 元素。虽然内部 Wordpress classes 像 align-leftwidthheight 属性现在应用于 figure 标签而不是 img 标签, 自定义 class * 没有* 移动到 figure 标签 ,但仍然是 img 标签的一个属性,因此完全失去了它的作用: figure 元素(及其包含的图像)不会具有自定义 class 中定义的百分比宽度,而是 width 和 [=22= 定义的固定宽度]属性。

整个事情变得更加复杂,因为 在 tinyMCE 编辑器中,figure 元素根本没有出现:在 "text mode"(= HTML 代码)该图由 [caption] 短代码表示,如上所述,在实际页面上呈现为 figure 元素,并且用于编辑器的所见即所得模式呈现为 div 和 class .mceTemp 包含 dl 标签,该标签包含 dt 标签中的图像和 [=34= 中的标题文本] 标签。 [caption] 短代码也是保存到数据库中的内容,顺便说一句。

现在,虽然 可以将 class 属性写入 "text mode" 中的短代码(即 HTML 代码),在视觉模式下无法 select figure/caption/shortcode/whatever - 它只能 select(并应用 classes)图片本身,在这种情况下是无用的(见上文)。

由于我不能期望客户端在文本模式下工作(并且不希望他们这样做 - 搞乱代码的危险太大),我需要一个可以完全在可视模式下执行的解决方案。

解决方案的第 1 部分:

由于在可视化模式下不能将 classes 应用于 figure 标签,我需要一种方法来删除应用于 img 标签的自定义 classes这些 img 标签并将它们应用到他们的 parent figure 标签。对于最终的页面输出,我创建了一个 jQuery 脚本,它确实做到了这一点:在页面加载时,它 搜索我的自定义 classes 应用于 img 标签的实例包装在 figure 标签中,从 img 标签中删除自定义 class 并将 class 添加到祖先 figure 标签

jQuery(document).ready(function() {
  var allMyClasses = [
        "img_left_30percent",
        "img_right_30percent",
        "img_left_40percent",
        "img_right_40percent",
        "img_left_50percent",
        "img_right_50percent",
    ];
  jQuery.each(allMyClasses, function(i, val) {
    jQuery("figure img." + val)
      .removeClass(val)
      .parents("figure")
      .addClass(val);
  });
});

这正好产生了我想要的输出——很好,但还不够……

第 2 部分 - 未解决/当前问题:

我正在使用 editor-styles.css 样式表为用户提供尽可能多的 WYSIWIG 表示。现在,在编辑器中,字幕的处理方式有所不同:仅在文本模式下可用的短代码呈现为 dl 标签而不是 figure 等. 对于 WYSIWIG 输出 - 见上文。

因此,上面的脚本适用于此处为所见即所得显示呈现的代码:

jQuery(document).ready(function() {
  var allMyClasses = [
        "img_left_30percent",
        "img_right_30percent",
        "img_left_40percent",
        "img_right_40percent",
        "img_left_50percent",
        "img_right_50percent",
    ];
  jQuery.each(allMyClasses, function(i, val) {
        jQuery("div.mceTemp dl.wp-caption img." + val)
            .removeClass(val)
            .addClass("wrapped_img_reset")
            .parents("dl.wp-caption")
            .addClass(val)
            .parents("div.mceTemp")
            .css({display: 'inline'});
  });
});

(这里我尝试将自定义 class 添加到 dl 容器中,并使包装 div.mceTemp 成为内联元素,以使 dl 的样式标签生效。)

但是:它根本不起作用,即输出代码没有以任何方式改变。可能是因为编辑器在 iframe 中呈现输出,我无法使用这些方法访问它(可以吗?)。

所以这是我的问题:我怎样才能将此脚本应用于 tinyMCE 呈现的代码作为其 WYSIWIG 输出?

好的,所以我自己找到了答案:要更改编辑器 DOM,必须在编辑器代码 (= tinyMCE) 中进行。所以我学会了如何为 tinyMCE 编辑器编写和注册一个插件(第一次...)。

该插件的代码如下所示。它完全符合我在问题中描述的内容:

tinymce.PluginManager.add('my_first_mceplugin', function(editor, url) {

 tinymce.activeEditor.on('GetContent', function() {
     imagecaptionclasstweak();
 });
 
 function imagecaptionclasstweak() {
   var allMyClasses = [
           "img_left_30percent",
           "img_right_30percent",
           "img_left_40percent",
           "img_right_40percent",
           "img_left_50percent",
           "img_right_50percent"
          ];
 jQuery.each(allMyClasses, function(i, val) {
          tinymce.activeEditor.dom.$('dl.wp-caption img.' + val)
            .removeClass(val)
            .addClass('wrapped_img_reset')
            .parents('dl.wp-caption')
            .removeAttr('class')
            .addClass('wp-caption')
            .addClass(val)
            .parents('div.mceTemp')
            .css({display: 'inline'});
         });
     }
});

这实际上比我预期的还要好:它不仅将自定义 class 写入编辑器所见即所得输出中的临时 dl 父级,而且还作为 class 属性进入 [caption] 短代码,这是保存到数据库的代码,在实际页面上被转换为相应的 figure 标签,包括 class。因此,在我的问题中我发布为 "Part 1 of the solution" 的 jQuery 函数不再是必需的。

为父项添加的 .removeAttr('class') 还确保在更改自定义 class 时删除任何先前的自定义 class。唯一不可能的是在 [caption] 短代码中包含其他 classes(除了额外添加的 'wp-caption'),但我不需要那个。