Chapter Three LLC

tinymce

HOWTO: Use TinyMCE in a Panel Pane Popup

Matt Cheney

The magic of Panels 2 is just the sort of thing you might expect from a wizard. Users can create pages with flexible and customizable layouts, they can populate those pages through an extensible block system, and they can configure and drag-and-drop those blocks around the page. Check out the demo page.

Sadly, the panels system does not allow its textareas to be used as TinyMCE WYSIWYG areas because of the way javascript and javascript events are handled. The basic problem is that TinyMCE runs on page load and is not set up to be activated on the Panel pane textareas that are created after the fact. This is a problem that hopefully the Drupal 6 version of Panels can resolve, but for Drupal 5.x the following hook_form_alter solution is possible.

First you need to set up a hook_form_alter callback as part of a new custom module or as part of an existing module you are modifying.

function my_module_form_alter($form_id, &$form) {
  switch($form_id) {

Second you need to render a hidden TinyMCE field on each panels editing page. This is not a particular clean way to proceed, but it will ensure that all of the appropriate TinyMCE .js is loaded on each page.

    case 'panels_edit_display':
      $form['tinymce_hidden'] = array(
        '#type' => 'fieldset',
        '#attributes' => array('style' => 'display: none'),
      );
      $form['tinymce_hidden']['tinymce_prerender'] = array(
        '#type' => 'textarea',
      );
      break;

Third you need to assign a special submit handler javascript call to convert all TinyMCE content back into its normal textarea content so it can be appropriately saved when the Panel pane is submitted.

     case 'panels_content_config_form':
       $form['next']['#attributes'] = array('onclick' => 'tinyMCE.triggerSave(true,true);');

Finally each of the textareas that are being rendered on the panel pane page need to have a special enable/disable TinyMCE link assigned to them. This allows users to turn on the TinyMCE functionality if they want. The code belows assumes your default TinyMCE state is off. I am sure there is a better and more generalized way to add these links, but this is a first step.

       // Load a disable or enable link below each textarea
       global $user;
       $enable  = t('enable rich-text');
       $disable = t('disable rich-text');
       $user = user_load(array('uid' => $user->uid));
       $profile = tinymce_user_get_profile($user);
       $status = tinymce_user_get_status($user, $profile);
       $link_text = $status == 'true' ? $disable : $enable;
       foreach($form['configuration'] as $index_raw => $value) {
         $index = str_replace('_','-', $index_raw);
         if ($value['#type'] == 'textarea') {
           $form['configuration'][$index_raw]['#description'] .= "<div><a href=
\"javascript:mceToggle('edit-configuration-$index', 'wysiwyg4-configuration-$index');\" class=\"wysiwyg-editor\" title=\"edit-configuration-\"" . $index . "\" id=\"wysiwyg4-configuration-$index\">$link_text</a></div>";
         } else {
           if (is_array($value)) {
             foreach($form['configuration'][$index_raw] as $index2_raw => $value2) {
               $index2 = str_replace('_', '-', $index2_raw);
               if ($value2['#type'] == 'textarea') {
                 $form['configuration'][$index_raw][$index2_raw]['#description'] .= "<div><a href=\"javascript:mceToggle('edit-configuration-$index-$index2', 'wysiwyg4-configuration-$index-$index2'); \"  class=\"wysiwyg-editor\" title=\"edit-configuration-\"" . $index . '-' . $index2 . "\" id=\"wysiwyg4-configuration-$index-$index2\">$link_text</a></div>";
               }
             }
           }
         }
       }
      break;

And you should be good to go.

  }
}

A Few Suggestions for TinyMCE Best Practices

Matt Cheney

Earlier this week I spent an afternoon setting up and configuring WYSIWYG editing for a client’s website. Although at Chapter Three we are big fans of HTML Literacy, we realize that many users would feel more comfortable in a WYSIWYG environment. We did a little brainstorming and came up with some basic recommendations to make TinyMCE work better.

1.) Keep the Interface Simple - TinyMCE out of the box has all of its bells and whistles displayed which is in some ways cool - TinyMCE can do a lot. However, much like the selection at Old Country Buffet, sometimes too many options can be confusing and hard to narrow down. There is a temptation to leave options there that “may be useful”. Instead, we first started by disabling all of the options and then selectively enabling only the options we really needed. This ended up being just the bold, italics, underline, font size, and ordered list buttons. Keep it simple or you will end up showing your users something monstrous like:

Bad:

Good:

2.) Resizing Good, Path Bad - TinyMCE allows for textareas to be resizable and this is a wonderful feature. It gives users more space to work and is far less annoying than having to compose a page long post by scrolling through a four line tall textarea. The problem is that in order to enable this feature in TinyMCE you also need to turn on the “Path Display” option. This feature allows users to see their current depth and path in the HTML code and can be useful in some cases - including building HTML literacy, but in most cases its both cluttering and confusing. To remove it and keep the resizing option, we simply enabled them both and then used CSS to hide the information:

.mceStatusbarPathText { visibility: hidden; }

3.) HTML Literacy is Still a Good Thing - Even though the user is working in a WYSIWYG environment, allowing the user the ability to be exposed to and maybe even edit the HTML code can be a really good thing. TinyMCE allows for the creation of a “HTML” button that creates (in a separate window) a rendering of the textareas HTML content and allows the user to edit the code. Now, it is best to keep the interface simple, but helping to educate users about HTML can be a really good step to improved HTML literacy.

4.) Only Use TinyMCE When You Have To - The easiest way to simplify the way TinyMCE is used on your site is to only use it in cases where you really need WYSIWYG editing capabilities. This is, unfortunately, a little tricky to do in Drupal since the Drupal implementation of TinyMCE only allows the display of WYSIWYG editing on a per page basis instead of a per field basis. This is typically not a problem since most pages just have one textarea, but if you have a page (say the editing of a particular node) with multiple textareas, but only want TinyMCE on one or two of them, its sort of tricky how to do it.

One possible solution - that we ended up using - is to use a theme override for the TinyMCE theme to enable or disable textareas based on name. This solution works in tandem with the built in display controls and simply adds the finer grain control needed. In this example, we have only enabled TinyMCE to show on node/* pages but have four different textfields that we do not want TinyMCE to show on. To accomplish this we use the following theme override:

<?php
function themename_tinymce_theme($init, $textarea_name, $theme_name, $is_running) {
   
// Determine what Textarea we are working with
   
switch($textarea) {
        case
"field-quotes-0-value":
        case
"field-shortcomments-0-value":
        case
"field-blurbs-0-value":
        case
"field-shoutouts-0-value":
           
// If it is a textarea we do not want TinyMCE to show, remove the $init variable
           
unset($init);
        break;
    }

   
// Return the $init variable
 
return $init;
}
?>

Syndicate content