1

There are several posts here on stackoverflow describing the same issue, however none of the suggested solutions have worked for me.

When wrapping an anchor tag around a block element, such as a div, the TinyMCE Visual Editor changes this anchor tag and moves it "up". I've shown this behaviour beneath:

"Wished" DOM:

<a href="#">
  <div></div>
</a>

TinyMCe changes that to the following:

<a href="#"></a>
<div></div>

What i've tried so far:

The below is expected by several answers to work, however it doesn't in my case. According to this answer it requires to turn autop off, which isn't a valid option in my case.

add_filter('tiny_mce_before_init', 'modify_valid_children', 99);
function modify_valid_children($settings){     
    $settings['valid_children']="+a[div|p|ul|ol|li|h1|span|h2|h3|h4|h5|h5|h6]";
    return $settings;
}

I've also found the documentation from TinyMCE themselves, stating the following should do the job:

tinyMCE.init({
    valid_children: '+a[div|p|h1|h2|h3|img]'; 
}); 

However, I'm not quite sure where to insert this, as it has to be in scope of the TinyMCE .js file, while not being overwritten in case of a core update from wordpress. Any ideas?

I even tried editing the core file of wordpress (wp-includes/js/tinymce/tinymce.min.js) and adding the above directly in here, without any luck either.

The above source from wordpress.stackexchange explains it thoroughly in detail, but I was hoping that some new options/information had come forth since 2016.

Chri.s
  • 1,386
  • 1
  • 12
  • 23

1 Answers1

1

The HTML you want to create is not valid as block elements (e.g. <div>) don't go inside inline elements (<a>). A valid alternative would be:

<a href="#">
  <span></span>
</a>

That aside, if you want to inject new options into TinyMCE (in WordPress) you can build a simple WordPress plugin and inject additional settings into the array WP uses to setup TinyMCE's configuration.

Look at the tiny_mce_before_init hook in the WP documentation. You do something like this:

add_filter('tiny_mce_before_init', 'function_to_add_options', 1002);

...then you use that referenced function to inject your settings:

function add_powerpaste_options($opt) {
  $opt['valid_children'] = '+a[div|p|h1|h2|h3|img]';
  return $opt;
}
Michael Fromin
  • 13,131
  • 2
  • 20
  • 31
  • Actually in HTML5 it's valid to place a block element inside an anchor tag: [according to this answer](https://stackoverflow.com/a/1828032/5480830). I cant seem to make the above code work (Also after adjusting the function names to match). Will it require a custom plug-in or is it sufficient to add it to functions.php? – Chri.s Apr 04 '18 at 13:54
  • 1
    I have always just made a separate plugin but I would think it could run in `functions.php` as well. – Michael Fromin Apr 04 '18 at 14:22
  • 3
    After some research I can confirm that TinyMCE won't allow you to place a `div` inside an `a` tag regardless of configuration. The internal document model for TinyMCE treats a given tag as either block or inline but not both so it will always treat a `div` as a block element and move it outside the `a` tag. (Full disclosure - I work for the company that develops TinyMCE) – Michael Fromin Apr 05 '18 at 01:50
  • thank you for the response and research - it's nice to finally have a closure for my issue that's valid! I saw an option in which you could define tags that are treated as block/inline. Would it cause too many issues defining a div as an inline element? Furthermore, Will you add the last comment to the answer? Then I Will accept as correct – Chri.s Apr 05 '18 at 06:50