Using TinyMCE with CakePHP

This article is also available in the following languages:
By jtreglos
TinyMCE is a nice WYSIWYG web editor by Moxiecode, giving your users a very convenient way to edit HTML content. And guess what, its very easy to use it in your Cake apps !

What is TinyMCE ?

TinyMCE is a WYSIWYG editor by Moxiecode that you can find here : http://tinymce.moxiecode.com
Its very fast to load (much faster than FCKEditor last time i've tried, which is quite a long time ago now, I must admit...), easy to setup and configure. It isn't as powerful as FCKEditor (http://www.fckeditor.net/) in terms of text processing, but if all you need is a small WYSIWYG editor to get clean (X)HTML, TinyMCE is your boy.

Installation

First step, of course, is to download TinyMCE. You can do this here : http://tinymce.moxiecode.com/download.php. At the time of writing, latest version is 2.0.6.1, and has been for a few months. 2.0.6.1 is very stable. Once downloaded, unpack TinyMCE, and copy just the tinymce/jscripts/tiny_mce folder in /webroot/js. You don't need the rest of the archive (documentation, examples, etc.) on your webserver.

Configuration

Next step is to implement it in Cake. Its very easy. First, we need to add this to the layout(s) that will be used on the page(s) that will have the editor. Of course, you need to add the javascript helper to your $helpers array in your controller(s) :

PHP Snippet:

<?php 
if(isset($javascript)):
    ...
    echo 
$javascript->link('tiny_mce/tiny_mce.js');
    ...
endif;
?>

Then, for each page that will have a TinyMCE editor, you'll have to add to the top of the view file :

HTML:


<script type="text/javascript">
    tinyMCE.init({
        theme : "simple",
        mode : "textareas",
        convert_urls : false
    });
</script>

By default, there are 2 themes with TinyMCE : 'simple' and 'advanced'. You specify the one you want to use on your page with the theme parameter. You can create your own themes or modify the existing ones in the webroot/js/tiny_mce/themes folder. The mode parameter is set here to 'textareas', meaning that all textareas of the page will be replaced by TinyMCE editors of the same size. If this behaviour doesn't satisfy you, check the documentation (http://tinymce.moxiecode.com/tinymce/docs/option_mode.html). The last parameter, convert_urls, is set to false so that TinyMCE doesn't try to process URLs for images or links.

There are loads of other parameters (All documented here : http://tinymce.moxiecode.com/tinymce/docs/index.html) to customize the way the editor will work. For example, the file_browser_callback allows you to give a js callback function or method to call a custom file browser for the image insertion popup dialog.

If you want to change the way the text in the editor appears, each theme has a css/editor_content.css file that you can modify to match your site's styles.

Comments

  • Posted 04/05/10 12:57:37 AM
    Ya this working on my page where i am using both Prototype as well as Jquery.

    At the top of the page i have included this block

    tinyMCE.init({
    theme : "simple",
    mode : "none",
    convert_urls : false
    });


    Added this one with the textareas those i want to associated with tinyMCE.

    $javascript->codeBlock("tinyMCE.execCommand('mceAddControl',false,'ModelField');");
  • Posted 08/18/08 10:08:21 AM

    How can I get multiple istances of TinyMCE in the same page?
    [I need for editing 2 languages] Thanks
    • Posted 10/23/08 12:22:29 AM
      How can I get multiple istances of TinyMCE in the same page?
      [I need for editing 2 languages] Thanks

      Andrea,

      That is addressed in the TinyMCE documentation. I haven't used that feature for any production work yet, but from what I remember it should be fairly straightforward. I think you tell TinyMCE to apply itself to all textareas with a specific class.
  • Posted 08/18/08 10:06:52 AM
    How can I get multiple istances of TinyMCE in the same page?
    [I need for editing 2 languages] Thanks
  • Posted 08/04/08 09:30:32 PM
    Sorry, but I didn't want to double post. Here is a fix to what I posted, TinyMceHelper is derived from JavascriptHelper. Instead of HtmlHelper.

    This is an alternative, as a helper. Follow Jean-Baptiste's recommendation on where to copy tiny_mce. Check to see if you are using, $scripts_for_layout in your layout; add it if necessary.

    In your views, call TinyMceHelper::init(). You provide options to the javascript call to tinyMCE.init() as a PHP array.

    Controller Class:

    <?php 
    <?php
    // An example of adding the TinyMce helper in app_controller.php.
    class AppController extends Controller {
        var 
    $helper=array('Javascript','Html','Form','TinyMCE' /*...etc...*/);
    }
    ?>
    ?>

    From somewhere in the view with the textareas:

    View Template:


    <?php
    // Example from a view calling TinyMceHelper::init().
        
    echo $tinyMce->init(array('mode'=>'textareas'));
    ?>

    <?php
    // Example from a view calling TinyMceHelper::init().
        
    echo $tinyMce->init(array(
            
    'mode'=>'textareas',
            
    'theme'=>'spaceballs',
            
    'convert_urls'=>false,
            )
        );
    ?>

    Here is the actual helper.

    Helper Class:

    <?php 
    <?php
    /***********************************************************************
     *
     * Quick TinyMCE Helper for CakePHP
     * Author: C.James Callaway (http://www.cybergod.net) - 08/04/2008
     */
    class TinyMceHelper extends JavascriptHelper {
        var 
    $helpers=array('Javascript');
        var 
    $defaults=array(
            
    'theme'=>'simple',
            
    'mode'=>'textareas',
            
    'convert_urls'=>false,
            );
        function 
    beforeRender(){
            
    $view ClassRegistry::getObject('view');
            if (
    is_object($view)) {
                
    $view->addScript($this->link('tiny_mce/tiny_mce'));
            }
        }
        function 
    init($options=false){
        if(!
    $options){
            
    $options=$this->defaults;
        }
        
    $code='tinyMCE.init('.json_encode($options).');';
        return 
    $this->codeBlock($code);
        }
    }
    ?>

  • Posted 08/04/08 09:20:41 PM
    This is an alternative, as a helper. Follow Jean-Baptiste's recommendation on where to copy tiny_mce. Check to see if you are using, $scripts_for_layout in your layout; add it if necessary.

    In your views, call TinyMceHelper::init(). You provide options to the javascript call to tinyMCE.init() as a PHP array.

    Controller Class:

    <?php 
    <?php
    // An example of adding the TinyMce helper in app_controller.php.
    class AppController extends Controller {
        var 
    $helper=array('Javascript','Html','Form','TinyMCE' /*...etc...*/);
    }
    ?>
    ?>

    From somewhere in the view with the textareas:

    View Template:


    <?php
    // Example from a view calling TinyMceHelper::init().
        
    echo $tinyMce->init(array('mode'=>'textareas'));
    ?>

    <?php
    // Example from a view calling TinyMceHelper::init().
        
    echo $tinyMce->init(array(
            
    'mode'=>'textareas',
            
    'theme'=>'spaceballs',
            
    'convert_urls'=>false,
            )
        );
    ?>

    Here is the actual helper.

    Helper Class:

    <?php 
    <?php
    /***********************************************************************
     *
     * Quick TinyMCE Helper for CakePHP
     * Author: C.James Callaway (http://www.cybergod.net) - 08/04/2008
     */
    class TinyMceHelper extends HtmlHelper {
        var 
    $helpers=array('Javascript');
        var 
    $defaults=array(
            
    'theme'=>'simple',
            
    'mode'=>'textareas',
            
    'convert_urls'=>false,
            );
        function 
    beforeRender(){
            
    $view ClassRegistry::getObject('view');
            if (
    is_object($view)) {
                
    $view->addScript($this->Javascript->link('tiny_mce/tiny_mce'));
            }
        }
        function 
    init($options=false){
        if(!
    $options){
            
    $options=$this->defaults;
        }
        
    $code='tinyMCE.init('.json_encode($options).');';
        return 
    $this->Javascript->codeBlock($code);
        }
    }
    ?>
  • Posted 01/13/08 09:14:43 PM
    Hi, I'm really new with cakephp.
    using this code :

    if(isset($javascript)):
    ...
    echo $javascript->link('tiny_mce/tiny_mce.js');
    ...
    endif;
    ?>

    for include javascript, but I got error from my browser. the tinyMCE not present, cause my FireBug report error with this file (tiny_mce.js)

    can I using javascripts with another way ?
    thank's
    sorry for my language
  • Posted 06/25/07 02:01:35 PM
    Here is my reusable element, its basically the same as Alexander Dolinin's except i've added a little functionality on top an included the spellcheck plugin and php compression, and it ties it all together using jquery :)

    View Template:


    <?php 
    /* SVN FILE: $Id$ */

    /**
     * Reusable element for creating an compressed tinyMCE editor, with jquery. 
     *
     * This element expects 2 varables, $preset which determins the 
     * layout and features of the editor and an array $textareas which is
     * list of the ID's to which the editor should be applied.
     * 
     * Also the code uses the GZip compression to increase speed and the
     * curl based google spell checker plugin.
     * 
     * code taken from : 
     * http://wiki.moxiecode.com/index.php/TinyMCE:Compressor/PHP
     * http://dev.jquery.com/wiki/Plugins/tinyMCE
     * http://bakery.cakephp.org/articles/view/using-tinymce-with-cakephp
     *
     * PHP versions 5
     *
     *
     * Licensed under The MIT License
     * Redistributions of files must retain the above copyright notice.
     *
     * @copyright        Copyright 2006-2008, Alex McFadyen
     * @link                http://www.acmconsulting.eu acmConsulting
     *
     * @package        app
     * @subpackage    views.elements 
     *
     * @version            $Revision$
     * @modifiedby        $LastChangedBy$
     * @lastmodified    $Date$
     *
     * @license            http://www.opensource.org/licenses/mit-license.php The MIT License
     */

    echo($javascript->link("tiny_mce/tiny_mce_gzip.js"));
    ?>
    <script type="text/javascript">
    tinyMCE_GZ.init({
        plugins : 'style,layer,table,save,advhr,advimage,advlink,emotions,iespell,'
                        +'insertdatetime,preview,media,searchreplace,print,contextmenu,'
                        +'paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,'
                        +'xhtmlxtras,spellchecker',
        themes : 'advanced',
        languages : 'en',
        disk_cache : true,
        debug : false
    });
    </script>
    <script defer language="javascript" type="text/javascript">
    <?php 
    switch ($preset) {
        case 
    'basic':
            
    $options '
            mode : "none",
            theme : "advanced",
             plugins : "advhr,advlink,spellchecker,",
            theme_advanced_buttons1 : "bold,italic,underline,separator,justifyleft,justifycenter,justifyright, justifyfull,bullist,numlist,undo,redo,link,unlink,spellchecker,",
            theme_advanced_buttons2 : "",
            theme_advanced_buttons3 : "",
            theme_advanced_toolbar_location : "top",
            theme_advanced_toolbar_align : "center",
            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]",
            content_css : "/css/'
    .$this->layout.'.css"    
            '
    ;
        break;
        
        default:
            
    $options '
             mode : "none",
           theme : "advanced",
           plugins : "advhr,advlink,spellchecker,",
           theme_advanced_layout_manager : "SimpleLayout",
           theme_advanced_disable: "hr,",
           theme_advanced_buttons1: "pasteword,justifyleft,justifycenter,justifyright,justifyfull,separator,removeformat,separator,charmap,advhr,",
           theme_advanced_buttons2: "styleselect,bold,italic,underline,separator,link,separator,bullist,numlist,outdent,indent,spellchecker,",
           theme_advanced_buttons3: "",
           theme_advanced_toolbar_location : "top",
           theme_advanced_toolbar_align : "left",
           content_css : "/css/'
    .$this->layout.'.css"
             '
    ;
        break;
    }

    ?>

        $(document).ready(function(){
    <?php 
        
    foreach($textareas as $id)
            echo(
    "\t\t$('#$id').tinymce();");
    ?>
        });
        $.fn.tinymce = function(options){
            return this.each(function(){
                // I don't think the style declaration is not really used in this sense, but I left it anyway
                preString = "<div class='jqHTML_frame' style='width:"+$(this).css("width")+"px;height:" + ($(this).css("height")+20) + "px;'>";
                postString = "</div>";
                $(this).wrap(preString + postString);
                // this comes last to avoid IE7 bug
                tinyMCE.addMCEControl(document.getElementById(this.id), this.id);
            });
        }
        function initMCE()
        {
            tinyMCE.init({ <?php echo($options); ?>});
        }
        // initialize tiny mce
        initMCE();
    </script>
    • Posted 11/18/07 06:20:31 AM
      I'm not new to PHP, but really new to Cake (started today with Cake). How can i add the Javascripts Helper to the $helpers array?
      • Posted 12/28/07 04:17:47 AM
        I'm not new to PHP, but really new to Cake (started today with Cake). How can i add the Javascripts Helper to the $helpers array?
        Hi there welcome and enjoy the magic..
        i have started this several months ago ...

        so if you have some questions, please do ask, i know the frustrations of the lack of good documentations

        your question's answer :

        in the controller use this

        Class TestController extends AppController {
        var $name = 'Test';
        var $helpers = array('Html','Form','Javascript');

        function index() {
        ... something ...
        }

        }


        hope this helps abit
  • Posted 03/27/07 05:41:36 AM
    I like WYMeditor, but its not ready for production use just yet. Instead I use tinyMCE and modify the settings to replicate the same environment. I even used a stylesheet with similar styles to the WYMeditors to display the type of content the user is typing. At present the code is perfect and the users are very happy.
  • Posted 01/14/07 04:43:35 PM
    As said before, WYSIWYG editors generate most of the time a very ugly html code...

    Everyone should better use a WYSIWYM (what you see is what you MEANT) editor such as WYMeditor, that can be found here : http://www.wymeditor.org/. It's a powerfull tool that generates a beautiful code ;o)

    Unfortunately, it supports only IE and gecko-based browsers, so if you're using Opera...
  • Posted 01/04/07 06:52:24 PM
    As I have titled this comment, I am a beginner with cakePHP, and in general with MVC approach.
    I succeded in testing the blog tutorial, but not the use of the tiny MCE editor. Would you please help me?

    1- According to the DRY advice, I created a file, 'tinymce.thml' in 'app/views/elements'
    2- Then added the suggested links to the javascripts within the default layout i.e 'app/views/layouts/default.thml'; e.g
    echo $javascript->link('tiny_mce/tiny_mce');
    3- Finally, added the following line
    renderElement('tinymce',array('preset' => 'basic')); ?> within my 'add' view i.e 'app/views/posts/add.thml'

    But: it does not work properly
    I have a message like this 'Error rendering Element: tinymce'
  • Posted 11/03/06 11:58:33 AM
    After submiting by ajax request a form, where textarea is handling by tinyMCE, this form (textarea elements) doesn't contain tiny again.

    Was made follow this tutorial.

    Why? Maybe anyone know ?
    • Posted 11/08/06 06:04:34 PM
      In response to Tomek's comment #8:

      There is a solution. I posted a new tutorial(http://bakery.cakephp.org/articles/view/140) that covers TinyMCE and AJAX.

      Hope it helps.
    • Posted 11/03/06 03:11:18 PM
      After submiting by ajax request a form, where textarea is handling by tinyMCE, this form (textarea elements) doesn't contain tiny again.

      I've found the same problem. Basically Tiny replaces the textareas with iframes. Upon Submit, it uses javascript to pull the values from the iframe and populates your original field before the form gets submitted.

      This causes all sorts of errors when used with Ajax.

      [p]I am still working out the details, but the answer lies in passing a command in your ajax call to load tiny again. Once I've got it worked out, I'll post a tutorial.
  • Posted 10/08/06 07:27:52 AM
    here's an excerpt of some code i once wrote:
    app/views/elements/tinymce.thtml:

    View Template:


    <?php echo($javascript->link("tinymce/jscripts/tiny_mce/tiny_mce.js"));
    ?>
    <script language="javascript" type="text/javascript">
    <?php if($preset "basic")
    {
        
    $options '
        mode : "textareas",
        theme : "advanced",
        theme_advanced_buttons1 : "bold,italic,underline,separator,justifyleft,justifycenter,justifyright, justifyfull,bullist,numlist,undo,redo,link,unlink",
        theme_advanced_buttons2 : "",
        theme_advanced_buttons3 : "",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",
        theme_advanced_path_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]",
        content_css : "/css/'
    .$this->layout.'.css"    
        '
    ;
    }
    ?>

    tinyMCE.init({<?php echo($options); ?>});
    </script>

    then, whereever i need it in a view, i just call it like this

    View Template:


    <?php echo $this->renderElement('tinymce',array('preset' => 'basic')); ?>

    the 'basic' preset if one i created myself, change or expand to your likings :)
    • Posted 12/15/06 07:33:23 PM
      Please note a small typo in the excerpt of Dieter's code: the line
      should be
      A small, but important difference.

      here's an excerpt of some code i once wrote:
      app/views/elements/tinymce.thtml:

      View Template:


      <script language="javascript" type="text/javascript">
      <?php if($preset == "basic")
      {
          
      $options '
          ... and so on...
    • Posted 10/08/06 12:05:33 PM
      This is an excellent idea ! Putting those few js lines in an element would avoid repetition of this code, and be evolutive enough to allow for params for specific instanciations.

      I guess I'm not DRY enough ;)
  • Posted 09/25/06 01:24:00 PM
    Jean,

    Should we add TinyMCE to the bakery?
    • Posted 10/08/06 12:15:16 PM
      I'd rather use a WYSIWYG editor like TinyMCE when the editing has to be done by non-techy type of people. I guess (hope !) that people writing to the Bakery are technically savvy enough not to need such a tool...

      Because even if WYSIWYG editors are great tools for the layman, its main drawback is that the generated HTML is most of the time VERY bad code, likely to break a carefully planned CSS layout, and prevent the page from validating correctly.
      • Posted 10/12/06 08:32:04 AM
        Because even if WYSIWYG editors are great tools for the layman, its main drawback is that the generated HTML is most of the time VERY bad code, likely to break a carefully planned CSS layout, and prevent the page from validating correctly.
        if you create an additional theme, you should be able to take out editting features you don't want your clients to use. in a lot of cases all you'll really need is inserting urls, paragraphs, headings, bulletted lists. if you don't want your client to break your css, don't allow any font sizing or coloring.

Comments are closed for articles over a year old