Been troubleshooting for some time, trying to figure out where on earth my script tags were going when using TinyMCE.

Eventually I managed to figure out that the problem was coming from the Media module tinyMCE plugin. But after reviewing the code in that module, I determined the problem wasn't with that module. It's with the WYSIWYG module.

In tinymce-3.js, there's the following method that gets invoked IFF a drupal tinymce plugin is present:

  prepareContent: function(content) {
    // Certain content elements need to have additional DOM properties applied
    // to prevent this editor from highlighting an internal button in addition
    // to the button of a Drupal plugin.
    var specialProperties = {
      img: { 'class': 'mceItem' }
    };
    var $content = $('<div>' + content + '</div>'); // No .outerHTML() in jQuery :(
    // Find all placeholder/replacement content of Drupal plugins.
    $content.find('.drupal-content').each(function() {
      // Recursively process DOM elements below this element to apply special
      // properties.
      var $drupalContent = $(this);
      $.each(specialProperties, function(element, properties) {
        $drupalContent.find(element).andSelf().each(function() {
          for (var property in properties) {
            if (property == 'class') {
              $(this).addClass(properties[property]);
            }
            else {
              $(this).attr(property, properties[property]);
            }
          }
        });
      });
    });
    return $content.html();
  },

Unfortunately, in jQuery versions lower than 1.9.1 (and of course Drupal 7 ships with <1.9.1, with upgrading to 1.9.1 posing problems for lots of modules), the html() method strips out

tags. You can argue that allowing script tags isn't generally a good idea, and I'd agree with you... but there's a time and a place to configure tinyMCE to (dis)allow such things, and having this plugin kill those tags when another drupal tinyMCE plugin is present is not desirable behavior.

Comments

drywall’s picture

I haven't played with it directly yet, but maybe changing

return $content.html();

to

return $content[0].innerHTML; 

would work?

EDIT Nope, nevermind $content[0] doesn't contain the script tags within.

inversed’s picture

I haven't had a chance to do extensive testing nor am I suggesting this is the long term solution, but innerHTML worked for me on the front end and I used jQuery update to set the version to 1.10 on my admin theme to handle the backend. I'm using TinyMCE 3.5.8, WYSIWYG 7.x-2.2 and I made the edit to tinymce-2.js and tinymce-3.js.

One weird thing is that the script tags in the WYSIWYG field work on the frontend but when inspecting the field's element in Chrome, it's not visible. End result works, but I think this problem is bigger than just hacking the file until a proper solution is decided on.

Edit: Or not as well. Bleh!

TwoD’s picture

.html() uses .innerHTML internally.

This is a known issue and is caused by most Drupal plugins (including Teaser Break) using jQuery - which in turn uses the browser's .innerHTML - to parse markup to a DOM and serialize it back to markup again. That's what drywall is seeing in the original post.

I was trying to work around this by including a custom "innerXHTML" library a while back, but that stalled due to other issues taking priority, and I'm not quite sure how far I got. I think it was fairly reliable (I do remember preserving whitespaces was very difficult), but it did depend on all Drupal plugins using it. As soon as anything passes content via the browser, it becomes unpredictable since browsers pretty much can't agree on anything. The behavior also changes depending on the DOCTYPE used since that can mean "output HTML instead of XHTML"...

Using script tags in WYSIWYG editors are a bit risky, since you can't always trust the editor to escape them correctly (you certainly don't want them to try to interpret the script either!), and when they do, they may not leave them in the correct spot. We've not officially supported using script tags in editors for this reason (and Drupal generally doesn't include inline scripts in content either).
Yes, I agree there are times when it's simply more convenient (for the end users) to allow script tags than to tell them to "use this macro/token/thingy for X and this other macro/tag/token thingy for Y instead", but then you also trust your users won't take advantage of the fact that scripts are enabled (and that no malicious types out there figure out it's possible either).

Conclusion; I currently have no idea how to apply both a proper and easy fix to this either. In the long run, the innerXHTML functionality is most likely the way to go, but dang, that was hard... :(

There are probably other, much older, issues which this one could be linked to (they'll give some more pros/cons backstory too), but I'm at work and in a bit of a hurry right now, so I'll leave that search for later.

sun’s picture

That library still exists at https://github.com/sun/innerXHTML (but wasn't really used actively)