HOWTO: Use TinyMCE in a Panel Pane Popup

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'] .= "
";
         } 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'] .= "

And you should be good to go.