TinyMCE helper

By David Boyer (daibach)
This is a basic helper to make it really easy to use TinyMCE inside CakePHP.

Notes

To specify any TinyMCE options, provide the extra $tinyoptions array with the information. It'll be converted to JavaScript and used when creating the editor.

Tiny MCE

Go and grab TinyMCE from its website http://tinymce.moxiecode.com/download.php and copy the /tinymce/jscripts/tiny_mce folder to the /app/webroot/js

Controller

Download code
var $helpers = Array('Form', 'Tinymce');

Helper code

app/views/helpers/tinymce.php
Download code
<?php
class TinyMceHelper extends AppHelper {
    
// Take advantage of other helpers
    
var $helpers = array('Javascript''Form');
    
// Check if the tiny_mce.js file has been added or not
    
var $_script false;
    
    
/**
     * Adds the tiny_mce.js file and constructs the options
     *
     * @param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
     * @param array $tinyoptions Array of TinyMCE attributes for this textarea
     * @return string JavaScript code to initialise the TinyMCE area
     */
    
function _build($fieldName$tinyoptions = array()) {
        if (!
$this->_script) {
            
// We don't want to add this every time, it's only needed once
            
$this->_script true;
            
$this->Javascript->link('/js/tiny_mce/tiny_mce.js'false);
        }
        
// Ties the options to the field
        
$tinyoptions['mode'] = 'exact';
        
$tinyoptions['elements'] = $this->__name($fieldName);
        return 
$this->Javascript->codeBlock('tinyMCE.init(' $this->Javascript->object($tinyoptions) . ');');
    }
    
    
/**
     * Creates a TinyMCE textarea.
     *
     * @param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
     * @param array $options Array of HTML attributes.
     * @param array $tinyoptions Array of TinyMCE attributes for this textarea
     * @return string An HTML textarea element with TinyMCE
     */
    
function textarea($fieldName$options = array(), $tinyoptions = array()) {
        return 
$this->Form->textarea($fieldName$options) . $this->_build($fieldName$tinyoptions);
    }

    
/**
     * Creates a TinyMCE textarea.
     *
     * @param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
     * @param array $options Array of HTML attributes.
     * @param array $tinyoptions Array of TinyMCE attributes for this textarea
     * @return string An HTML textarea element with TinyMCE
     */
    
function input($fieldName$options = array(), $tinyoptions = array()) {
        
$options['type'] = 'textarea';
        return 
$this->Form->input($fieldName$options) . $this->_build($fieldName$tinyoptions);
    }
}
?>

View example

Download code
<div class="form-container">
  <?php echo $form->create('Page'); ?>
    <fieldset>
      <legend>Page</legend>
      <?php
        
echo $form->input('title');
        echo 
$tinymce->input('content');
      
?>
    </fieldset>
  <?php echo $form->end('Save'); ?>
</div>
Here's an example supplying some extra tinyMCE configuration options
Download code
<div class="form-container">
  <?php echo $form->create('Page'); ?>
    <fieldset>
      <legend>Page</legend>
      <?php
        
echo $form->input('title');
        echo 
$tinymce->input('content'null, array(
          
'theme'                             => 'advanced',
          
'theme_advanced_toolbar_location'   => 'top',
          
'theme_advanced_toolbar_align'      => 'left',
          
'theme_advanced_statusbar_location' => 'bottom',
        ));
      
?>
    </fieldset>
  <?php echo $form->end('Save'); ?>
</div>

Suggestions


Everyone should know that letting users submit HTML can be a bit risky when it comes to displaying it, unless you trust them of couse (like an admin user). If you want more general users taking advantage of something like this, I'd suggest looking into something like http://htmlpurifier.org/. This parses the HTML and can remove anything you don't want submitted.

 

Comments 725

CakePHP Team Comments Author Comments
 

Question

1 TinyMCE attributes for the textarea

Could you please give an example to set the $tinyoptions array .

Actually I need a configuration like the following one:


tinyMCE.init({
mode : "textareas",
theme : "advanced",
plugins : "inlinepopups,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras",
theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,|,visualchars,nonbreaking",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_statusbar_location : "bottom",
extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]"
});

Thank you very much for you help.
Posted Jul 10, 2008 by greg saram
 

Comment

2 TinyMCE attributes example

Hi Greg, I've updated the article to include an example of setting TinyMCE options.

You basically pass the helper a third parameter that is a php array similar to the JavaScript object that TinyMCE usually gets.

Note that you shouldn't supply a "mode" since the helper will create that bit for you and tie it to the textarea automatically.

Hope that explains things,
Dave
Posted Jul 11, 2008 by David Boyer
 

Comment

3 solve the tinyMcc issue

The following code is working....

View Template:


<div>
 <?php echo $form->create('Page'); ?> 
  <?php        
        
echo $tinymce->input('content'null, array( 
         
'theme' => 'advanced',                                
        
"plugins" => "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
          
"theme_advanced_buttons1" => "newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,formatselect,fontselect,fontsizeselect",
        
"theme_advanced_buttons2"=> "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,image,code,|,insertdate,inserttime,preview,|,forecolor,backcolor,advhr,|,print,|fullscreen",
        
"theme_advanced_buttons3" => "",
        
//theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak",
         
"theme_advanced_toolbar_location" => "top",
         
"theme_advanced_toolbar_align" => "left",
         
"theme_advanced_statusbar_location" => "bottom",
         
"theme_advanced_resizing" => true,
          
        )); 
      
?> 
 <?php echo $form->end('Save'); ?> 
</div>
Posted Aug 1, 2008 by Mohsin Kabir
 

Comment

4 Multiple Instances in Same page

How can I get multiple instances of it in the same page?
I need for multiple language editing.
Thanks
Posted Aug 18, 2008 by Andrea
 

Comment

5 great helper

great helper, simple and effective
Posted Aug 26, 2008 by Guillermo Nuñez
 

Comment

6 Multiple Instances

Like the above comment, I am also wondering how I can get multiple instances working on a page, my current code is as follows:

View Template:


        echo $form->label('description', 'Description:');
        echo $tinymce->input('description', array('label' => false, 'rows' => 20, 'cols' => 50));
        
        echo $form->label('tech_description', 'Technical Description:');
        echo $tinymce->input('tech_description', array('label' => false, 'rows' => 20, 'cols' => 50));

However this does not create two instances, the first one works fine, but the second one just creates a normal textarea box. Any suggestions?
Posted Dec 4, 2008 by Dustin Nielsen
 

Comment

7 Reply to: Multiple Instances

In order to use multiple instances of TinyMce you can't use the script in that form anymore.

First you have to choose between a way:

If it's easier to convert all textareas to TinyMce-Editors (and optionally exclude some of them by CSS-class):



<?php
function _build($fieldName$tinyoptions = array()) {
        [...]
        
// Converts all textareas to TinyMCE-Editors, excluding textareas having the CSS-Class 'mceNoEditor'
        
$tinyoptions['mode'] = 'textareas';
        
$tinyoptions['editor_deselector'] = 'mceNoEditor';
        [...]
}
?>

If you want have only editors on textareas having a certain CSS-class.


<?php
function _build($fieldName$tinyoptions = array()) {
        [...]
        
// converts only these textareas to TinyMCE-Editors having the CSS-Class 'mceEditor'
        
$tinyoptions['mode'] = 'specific_textareas';
        
$tinyoptions['editor_selector'] = 'mceEditor';
        [...]
}
?>

For the second option you can modify to code of the input/textarea function to always insert the class. So if you use $tinymce->input the area will automatically turned into tinymce fields but fields created by $forms->textarea won't.

To achieve that you have to insert:

<?php
function textarea($fieldName$options = array(), $tinyoptions = array()) {
        if(isset(
$options['class'])){
            
$options['class'] = $options['class'].' mceEditor';
        }else{
            
$options['class'] = 'mceEditor';
        }
        return 
$this->Form->textarea($fieldName$options) . $this->__build($fieldName$tinyoptions);
}
?>

(Do the same with function input.)

Hope that helps, Stevie :)
Posted Jan 3, 2009 by Stevie
 

Comment

8 Suggestion to extension

Great code, David!

Really cool, though I found one problem: One of my entries in the tinyMCE.init is not a variable, but a function:

setup : function(ed) {
    ed.onDblClick.add(function(ed, e) {
        var attribute = ed.dom.getAttrib(e.target,'class');
        // make sure it is the MathML span tag which has been doubleclicked
        if(e.target.nodeName=="IMG" && attribute=="InteractiveGraph"){
            var id = ed.dom.getAttrib(e.target,'id');
            ed.execCommand("mceinteractivegraphs",false,id);
        }
    });
},
When using $this->Javascript->object, it assumes that all values in the array are to be quoted, but this function is not.

Hence, I came up with this extension:

Helper Class:

<?php 
function _build($fieldName$tinyoptions = array()) {
    if (!
$this->_script) {
        
// We don't want to add this every time, it's only needed once
        
$this->_script true;
        
$this->Javascript->link('/js/tiny_mce/tiny_mce.js'false);
    }
    
// Ties the options to the field
    
$tinyoptions['mode'] = 'exact';
    
$tinyoptions['elements'] = $this->domId($fieldName);

    
$manual_json $tinyoptions['manual_json'];
    unset(
$tinyoptions['manual_json']);
    
$json $this->Javascript->object($tinyoptions);
    
$json substr($json,0,strlen($json)-1).',';
    if (!empty(
$manual_json)) {
        foreach (
$manual_json as $k => $v) {
            
$json .= '"'.$k.'":'.$v;
        }
    }
    
$json .= "}";
    return 
$this->Javascript->codeBlock('tinyMCE.init(' $json ');',array('inline'=>false));
}
?>

I furthermore changed $this_>__name() to $this->domId(), because the 'elements' should be passed the id of the textarea, not the name.

My textarea element looks like this:

View Template:


<?php print $tinymce->textarea('Lesson.source',array(),array(
    
"theme" => "advanced",
    
"cleanup" => "true",
    
"manual_json" => array(
        
"setup" => str_replace("\n","",str_replace("\t","","function(ed) {
            ed.onDblClick.add(function(ed, e) {
                var attribute = ed.dom.getAttrib(e.target,'class');
                if(e.target.nodeName=='IMG' && attribute=='InteractiveGraph') {
                    var id = ed.dom.getAttrib(e.target,'id');
                    ed.execCommand('mceinteractivegraphs',false,id);
                }
            });
        }"
))
    ),
));
?>

I hope that is is of some help to others using advanced tinymce techniques!

Best regards,
Jesper :-)
Posted Feb 6, 2009 by Jesper Skytte Hansen
 

Comment

9 More? :)

Hope that helps, Stevie :)
Stevie any chance you can give a little more explanation? I tried what you did, and when I save my data is getting lost somewhere... it's not showing up in $this->data. Do you have any idea what the issue may be?
Posted Jun 8, 2009 by rocket
 

Question

10 problem when running under debug 0

I'm having some problem when the debug is set to 0 (all the javascript and css files are packed so I guess they couldn't link up with each other). I have followed the instruction to put "/tinymce/jscripts/tiny_mce" folder to the "/app/webroot/js"
Posted Jun 18, 2009 by Phuc Tran