title: Insert custom classes into WYSIWIG output rendered by tinyMCE via jQuery (handling images with captions in Wordpress)
body: <h2>Preface / the initial problem:</h2>
  
  <p>I want users to be able to apply custom classes to images in Wordpress posts using the visual editor (i.e. the "classic editor" / tinyMCE - I can't use Gutenberg since these are are custom post types created with PODS where the block editor isn't available). These classes are defined in the stylesheet I created. Their main characteristic is that <code>width</code> has a percentage value and a fixed 100% value for smaller screens in media queries - I don't like the Wordpress system of fixed image sizes which at some point / screen width look ridiculous when floated. I am using the "TinyMCE Custom Styles" plugin to put these classes into the "Format" menu of the editor. Users can apply them to images by selecting the image and choosing the class from that menu.</p>
  
  <p><strong>This works perfectly if these classes are applied to images which <em>don't</em>  have a caption</strong>: These are rendered as regular <code>img</code> tags, optionally with <code>a</code> tags around them if any link option is chosen: The class has its expected effect, all styles in it apply.</p>
  
  <p>However, <strong>if a user decides to use a caption, images are handled completely different</strong>: Wordpress autmatically creates a <code>figure</code> tag around it which contains the <code>img</code> and a <code>figcaption</code> element. Although the internal Wordpress classes like <code>align-left</code> and the <code>width</code> and <code>height</code> attributes are now applied to the <code>figure</code> tag instead of the <code>img</code> tag, <strong>the custom class is * not*  moved to the <code>figure</code> tag</strong>, but remains an attribute of the <code>img</code> tag and therefore completely looses its effect: The <code>figure</code> element (and with it the contained image) won't have the percentage width defined in the custom class, but the fixed width defined by the <code>width</code> and <code>height</code> attributes.</p>
  
  <p>The whole thing becomes more complex through the fact that, <strong>in the tinyMCE editor, the <code>figure</code> element doesn't appear at all</strong>: In "text mode" (= HTML code) the figure is represented by a <code>[caption]</code> shortcode which which on the real page is rendered as a <code>figure</code> element as described above, and for the WYSIWYG mode of the editor is rendered as a div with class <code>.mceTemp</code> containing a <code>dl</code> tag which contains the image in a <code>dt</code> tag and the caption text in a <code>dl</code> tag. The <code>[caption]</code> shortcode is also what is saved to the database, btw.</p>
  
  <p>Now, although it <em>is</em>  possible to write class attributes into the shortcode in "text mode" (i.e. HTML code), <strong>in visual mode there is no way to select the figure/caption/shortcode</strong>/whatever - it's only possible to select (and apply classes to) the image itself, which is useless in this case (see above).</p>
  
  <p>Since I can't expect clients to work in text mode (and wouldn't want them to - too much danger of messing up the code), i need a solution that can be performed entirely in visual mode. </p>
  
  <h2>Part 1 of the solution:</h2>
  
  <p>Since in visual mode one cannot apply classes to the <code>figure</code> tag, I need a way to remove the custom classes applied to <code>img</code> tags from those <code>img</code> tags and apply them to their parent <code>figure</code> tags. For the final page output I created a jQuery script which does exactly that: On page load, it <strong>searches for instances of my custom classes applied to <code>img</code> tags which are wrapped in <code>figure</code> tags, removes the custom class from the <code>img</code> tag and adds the class to the ancestor <code>figure</code> tag</strong>:</p>
  
  <pre><code>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);
    });
  });
  </code></pre>
  
  <p>This produces exactly the output I want - great, but not enough…</p>
  
  <h2>Part 2 - unsolved / the current problem:</h2>
  
  <p>I am using an <code>editor-styles.css</code> stylesheet to provide users with as much of a WYSIWIG representation as possible. Now, <strong>in the editor, the handling of captions is different</strong>: the shortcode which is available only in text mode is rendered as a <code>dl</code> tag instead of <code>figure</code> etc. for the WYSIWIG output - see above.</p>
  
  <p>So the above script adapted to the code which is rendered for the WYSIWIG display here would be:</p>
  
  <pre><code>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'});
    });
  });
  </code></pre>
  
  <p>(Here I try to add the custom class to the <code>dl</code> container and make the wrapping <code>div.mceTemp</code> an inline element in order let the styles of the <code>dl</code> tag become effective.)</p>
  
  <p>But: It doesn't work at all, i.e. the output code is not altered in any way. Probably because the editor renders the output in an iframe, which I can't access using these methods (can I?).</p>
  
  <p>So here is my question: How could I accomplish that this script is applied to the code tinyMCE renders as its WYSIWIG output?</p>