Ever gotten sick of clicking on your special Rich-Text input filter for TinyMCE when you use the editor? Ever forgotten to? Ever had a user nuke all the whitespace in a node by editing it in TinyMCE with the "filtered HTML" input format on? Well... I have! And now I've made a solution.

How to make TinyMCE automatically select an input format you designate

Steps:

  1. Find out the id(s) of the "safe" input format(s) you use for TinyMCE. If you're unsure, you can look in the filter_formats table in your database.
  2. Add the following function to template.php for your theme:
    function phptemplate_tinymce_theme($init, $textarea_name, $theme_name,$is_running) {
      $init = theme_tinymce_theme($init, $textarea_name, $theme_name, $is_running);
    
      if (isset($init)) {
        $init['init_instance_callback'] = "set_input_format";
      }
      return $init;
    }
    

    (Or, if you already have a TinyMCE theme function set up, just add the line $init['init_instance_callback'] = "set_input_format"; where appropriate.

  3. Put the following javascript function somewhere such that it will be loaded on the page in question (in any old js file for your theme, or you can tack it onto the end of tiny_mce_src.js, or stick it in the $js_toggle variable in tinymce.module around line 155, or do it the right way with a drupal_add_js()--all up to you).

    The function is heavily commented for you to modify or debug it.
    You will need to replace the numbers in the line var filter_array = new Array(6,4); with the ids of your input formats.

     //php tags are just for formatting; this is a JS function
    function set_input_format(tinymce_instance) {
      // sets the input format to a TinyMCE-compatible one.
      // TODO: make this filter configurable via TinyMCE profile
    
      //this gives us the textarea id of the instance:
      textbox_id = tinymce_instance.oldTargetElement.id;
    
      // we expect an array ordered from top choice to last choice
      // 6 is my "rich text for doc authors," 4 is plain ol' "rich text"
      var filter_array = new Array(6,4);  //ids of input formats
    
      // First, get the index of the form that contains the element
      // There's gotta be a better way to do this
      for (i=0; i < document.forms.length; i++) {
        for (j=0; j < document.forms[i].elements.length; j++) {
          if (document.forms[i].elements[j].id == textbox_id) {
            var form_id = i;
          }
        }
      }
    
      // The textbox_id will be in the format (e.g.)
      // edit-field_body-0-value
      // Corresponding input format radio will be (e.g.) 
      // edit[field_body][0][format]
      // So, we split the string up around '-'
      var textbox_id_array = textbox_id.split("-");
    
      // name for input format radios begins with a normal string, 
      // then the rest in [] array-style
      var radio_id = textbox_id_array[0];
      for (i=1; i < textbox_id_array.length-1; i++) {
        radio_id += "[" + textbox_id_array[i] + "]";
      }
      // format at the end instead of edit
      radio_id += "[format]";
    
      // go through filters bottom priority -> top priority 
      // thus the radio button for the highest *existing* priority is
      // the final one checked      
      for (i=filter_array.length-1; i >= 0; i--) {
        // check the radio option for filter_array[i] if it's there 
        for (j=0; j < document.forms[form_id].elements[radio_id].length; j++) {
          if (document.forms[form_id].elements[radio_id][j].value == filter_array[i]) {
       document.forms[form_id].elements[radio_id][j].checked = true;
          }
        }
      }
    }
    
    

And there you have it! Caveats:

  • YMMV
  • Not tested in IE. ATM there just ain't a PC in the house.
  • TinyMCE is usually broken in Safari, so I didn't bother to test it there, either.
  • Always back stuff up before hacking it, etc.
  • This isn't idiot-proof, although it's more idiot-proof than nothing. A user can still willfully select the wrong input format after the page loads or TinyMCE is toggled on. It could be made even more idiot-proof by setting the TinyMCE save_callback to be "set_input_format" just like we did for init_instance_callback, but I prefer to have the ability to override the filter choice if I deem appropriate.

So what next? It wouldn't be too difficult to create a patch for tinymce.module that allows a user to select the input format(s) that work with TinyMCE at admin/settings/tinymce, and (if there are multiples), weight the filters from most preferred to least preferred. Then, if we moved the JS set_input_format() function inside tinymce.module, the function could be automatically printed with those values in filter_array.

Any feedback or testing you can offer would be appreciated. :)