TinyMCE the Magento Way

Last modified by Jonathon Harris on Fri, June 25, 2010 10:33
Source|Old Revisions  

This is an old revision of the document!


Preface

Objective

This tutorial gives detailed steps on adding the TinyMCE - JavaScript WYSYWYG Editor to Magento. When complete, the editor will be available in the Magento administrative interface. It affects the following HTML textarea input fields in the Magento interface:

  • Product Description
  • Product Short Description
  • CMS Page Content
  • CMS Static Block Content

Credits

A large part of the code is based off of the original written by “Web Master”, and the many contributions posted in the Message Board. I want to give credit to all of those people involved. Thank you to “jimfraseruk” for offering the setTimeout() function in lib/Varien/Data/Form/Element/Editor.php on the Message Board. This seemed to fix the bug in which the TinyMCE would appear, but no text could be entered into the field.

Why a new article?

I’ve decided to create a new WYSIWYG wiki instead of updating the existing one. This approach is different, as it makes use of the app/code/local and custom theme directories to avoid changing the Magento core code. The only exception is the lib/Varien/Data/Form/Element/Editor.php file. This file will be approached in a slightly different manner.

This method also avoids a few bad practices that were previously used as workarounds in the Message Board. These include using the fully qualified domain to reference the tiny_mce.js file, and calling the tiny_mce.js file from within several different template files.

Version(s) tested

This Wiki has been successfully implemented and tested on versions 1.2.02 and 1.3.0. I will update the Wiki when I test on 1.3.1, althought I have already received feedback that it works in 1.3.1.

Prerequisites

The tutorial assumes you are already familiar with the concept of adding custom modules to Magento using the app/code/local directory. If you haven’t already, please review the wiki titled “Changing and Customizing Magento Code” located at http://www.magentocommerce.com/wiki/groups/174/changing_and_customizing_magento_code.

Naming Conventions

In this example, we will use MyCompany as the class name for the custom modules. We will use myadmintheme as the name of the adminhtml theme.

You will be replacing the following strings from my article with your own:

  • myadmintheme → The name of your custom adminhtml theme
  • MyCompany → The namespace for your custom modules

Step by Step Instructions

Create Adminhtml theme

Create the following theme directories:

app/design/adminhtml/default/myadmintheme
skin/adminhtml/default/myadmintheme

Create and Activate local Adminhtml modules

Create the following directories:

app/code/local/MyCompany
app/code/local/MyCompany/Adminhtml
app/code/local/MyCompany/Adminhtml/etc
app/etc/modules

Create the following file:

app/code/local/MyCompany/Adminhtml/etc/config.xml

The contents of this file are as follows:

<?xml version="1.0"?>
<config>
  <stores>
      <admin>
          <design>
              <package>
                  <name>default</name>
              </package>
              <theme>
                  <default>myadmintheme</default>
              </theme>
          </design>
      </admin>
  </stores>
  <modules>
    <MyCompany_Adminhtml>
      <version>0.1.0</version>
    </MyCompany_Adminhtml>
  </modules>
</config>

Create the following file:

app/etc/modules/MyCompany_Adminhtml.xml

File contents are as follows:

<?xml version="1.0"?>
<config>
  <modules>
    <MyCompany_Adminhtml>
      <active>true</active>
      <codePool>local</codePool>
    </MyCompany_Adminhtml>
  </modules>
</config>

At this point, you could clear your cache files and reload your admin interface. Your site should now be using your myadminhtml theme for the admin interface. You can customize it as you wish and test it, but theming the adminhtml is beyond the scope of this tutorial.

Download and extract tiny_mce into the js directory

  1. Download the latest version of tiny_mce from http://tinymce.moxiecode.com/
  2. Once you have downloaded tinymce_x_x_x_x.zip, extract the files somewhere locally.
  3. You can now move the tinymce/jscripts/tiny_mce folder to the js/ directory on your server.

( Note: It is up to you, but I choose to place tiny_mce elsewhere, and then place a symlink to the directory in the sites’ js folder. That is also beyond the scope of this tutorial. )

Copy theme files from the default adminhtml to custom adminhtml

Make the following directories:

app/design/adminhtml/default/myadmintheme/template
app/design/adminhtml/default/myadmintheme/template/page
app/design/adminhtml/default/myadmintheme/template/catalog
app/design/adminhtml/default/myadmintheme/template/catalog/product

Copy the following files: ( from → to )

app/design/adminhtml/default/default/template/page.phtml -> app/design/adminhtml/default/myadmintheme/template/page.phtml
app/design/adminhtml/default/default/template/page/head.phtml -> app/design/adminhtml/default/myadmintheme/template/page/head.phtml
app/design/adminhtml/default/default/template/catalog/product/edit.phtml -> app/design/adminhtml/default/myadmintheme/template/catalog/product/edit.phtml

Copy module files from the core code to local code

Make the following directories:

app/code/local/MyCompany/Adminhtml/Block
app/code/local/MyCompany/Adminhtml/Block/Cms
app/code/local/MyCompany/Adminhtml/Block/Cms/Block
app/code/local/MyCompany/Adminhtml/Block/Cms/Block/Edit
app/code/local/MyCompany/Adminhtml/Block/Cms/Page
app/code/local/MyCompany/Adminhtml/Block/Cms/Page/Edit
app/code/local/MyCompany/Adminhtml/Block/Cms/Page/Edit/Tab

Copy the following files: ( from → to )

app/code/core/Mage/Adminhtml/Block/Cms/Block/Edit/Form.php -> app/code/local/MyCompany/Adminhtml/Block/Cms/Block/Edit/Form.php
app/code/core/Mage/Adminhtml/Block/Cms/Page/Edit/Tab/Main.php -> app/code/local/MyCompany/Adminhtml/Block/Cms/Page/Edit/Tab/Main.php

Edit your custom Adminhtml modules config file

This step will tell Magento to override the existing app/code/core/Mage/Adminhtml/Block/Cms/Page/Edit/Tab/Main.phtml and app/code/core/Mage/Adminhtml/Block/Cms/Block/Edit/Form.phtml files with the files from your app/code/local directory.

Edit the following file:

app/code/local/MyCompany/Adminhtml/etc/config.xml

Just before the closing </config> tag, add the following code:

<global>
  <blocks>
    <adminhtml>
      <rewrite>
        <cms_page_edit_tab_main>MyCompany_Adminhtml_Block_Cms_Page_Edit_Tab_Main</cms_page_edit_tab_main>
      </rewrite>
      <rewrite>
        <cms_block_edit_form>MyCompany_Adminhtml_Block_Cms_Block_Edit_Form</cms_block_edit_form>
      </rewrite>
    </adminhtml>
  </blocks>
</global>

The resulting file should look like this:

<?xml version="1.0"?>
<config>
  <stores>
      <admin>
          <!-- default admin design package and theme -->
          <design>
              <package>
                  <name>default</name>
              </package>
              <theme>
                  <default>myadmintheme</default>
              </theme>
          </design>
      </admin>
  </stores>
  <modules>
    <MyCompany_Adminhtml>
      <version>0.1.0</version>
    </MyCompany_Adminhtml>
  </modules>
  <global>
    <blocks>
      <adminhtml>
        <rewrite>
          <cms_page_edit_tab_main>MyCompany_Adminhtml_Block_Cms_Page_Edit_Tab_Main</cms_page_edit_tab_main>
        </rewrite>
        <rewrite>
          <cms_block_edit_form>MyCompany_Adminhtml_Block_Cms_Block_Edit_Form</cms_block_edit_form>
        </rewrite>
      </adminhtml>
    </blocks>
  </global>
</config>

Edit the CMS Block Edit Form

Edit the following file:

app/code/local/MyCompany/Adminhtml/Block/Cms/Block/Edit/Form.php

1. On the line that reads

class Mage_Adminhtml_Block_Cms_Block_Edit_Form extends Mage_Adminhtml_Block

Change

Mage_Adminhtml_Block_Cms_Block_Edit_Form

to

MyCompany_Adminhtml_Block_Cms_Block_Edit_Form

Resulting in the following:

class MyCompany_Adminhtml_Block_Cms_Block_Edit_Form extends Mage_Adminhtml_Block

2. On the line that reads “‘wysiwyg’ ⇒ false,“, change false to true.

Change

'wysiwyg'   => false,

to

'wysiwyg'   => true,

Edit the CMS Page Edit Form

Edit the following file:

app/code/local/MyCompany/Adminhtml/Block/Cms/Page/Edit/Tab/Main.php

1. On the line that reads

class Mage_Adminhtml_Block_Cms_Page_Edit_Tab_Main extends Mage_Adminhtml_Block_Widget_Form

Change

Mage_Adminhtml_Block_Cms_Page_Edit_Tab_Main

to

MyCompany_Adminhtml_Block_Cms_Page_Edit_Tab_Main

Resulting in the following:

class MyCompany_Adminhtml_Block_Cms_Page_Edit_Tab_Main extends Mage_Adminhtml_Block_Widget_Form

2. On the line that reads “‘wysiwyg’ ⇒ false,“, change false to true.

Change

'wysiwyg'   => false,

to

'wysiwyg'   => true,

Edit the template files in your custom adminhtml theme

1. Edit the following file:

app/design/adminhtml/default/myadmintheme/template/page.phtml

After the line that reads

<?php echo $this->getChildHtml('head') ?>

Add the following code:

<script type="text/javascript" src="<?php echo $this->getJsUrl('tiny_mce/tiny_mce.js') ?>" language="javascript"></script>

2. Edit the following file:

app/design/adminhtml/default/myadmintheme/template/page/head.phtml

Just before the line that reads

<?php echo $this->helper('core/js')->getTranslatorScript() ?>

Add the following code:

<script language="javascript" type="text/javascript">
  window.onload = function() {
    if(document.getElementById('page_content')){
      if(document.getElementById('page_content').value == ''){
      document.getElementById('page_content').value = "<p>Page Content</p>";
    }
  }
}

3. Edit the following file:

app/design/adminhtml/default/myadmintheme/template/catalog/product/edit.phtml

After the line that reads

//<![CDATA[

Add the following code:

Event.observe(window, 'load', function() {
  if(document.getElementById('description')){
    if(document.getElementById('description').value == ''){
      document.getElementById('description').value = "<p>Enter description</p>";
      document.getElementById('short_description').value = "<p>Enter short description</p>";
    }
  }
  tinyMCE.init({
      mode : "exact",
      theme : "advanced",
      strict_loading_mode : true,
      elements : "description,short_description",
      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]",
      theme_advanced_resize_horizontal : "true",
      theme_advanced_resizing : "true",
      apply_source_formatting : "true",
      convert_urls : "false",
      force_br_newlines : "true",
      doctype : '&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;'
  });
});

After the following lines:

if(document.getElementById('description')){
        if(document.getElementById('description').value == ''){
          document.getElementById('description').value = "<p>Enter description</p>";

add the following code:

        }
        if(document.getElementById('short_description').value == ''){

This is required in case the description field contains data, but the short description is initially blank. Otherwise, the form submission will err with a message stating that the short description is a required field, even after information is entered.

Edit the Form Element Editor library

I have not figured out how to override any file in the lib/ directory by creating and activating a custom module. Instead, a Varien directory must be created in app/code/local. This isn’t ideal, but it will work because of how the Magento module namespace works.

Create the following directories:

app/code/local/Varien/
app/code/local/Varien/Data/
app/code/local/Varien/Data/Form/
app/code/local/Varien/Data/Form/Element/

Copy the following file: ( from → to )

lib/Varien/Data/Form/Element/Editor.php -> app/code/local/Varien/Data/Form/Element/Editor.php

Edit the following file:

app/code/local/Varien/Data/Form/Element/Editor.php

1. After the line that reads

//<![CDATA[

Add the following line:

setTimeout(function(){

2. Change the following line:

/* tinyMCE.init({

to

tinyMCE.init({

In other words, remove the “/* “.

3. Change the following line:

theme : "'.$this->getTheme().'",

to

theme : "advanced",

4. Directly after the line in above step, add the following line:

strict_loading_mode : "true",

5. Change the line reading

});*/

to

});

In other words, remove the “*/

6. Directly after the line in the above step, add the following line:

},1000)

The result should look like this

//<![CDATA[
setTimeout(function(){
   tinyMCE.init({
       mode : "exact",
       theme : "advanced",
       strict_loading_mode : "true",
       elements : "' . $element . '",
       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]",
       theme_advanced_resize_horizontal : "false",
       theme_advanced_resizing : "false",
       apply_source_formatting : "true",
       convert_urls : "false",
       force_br_newlines : "true",
       doctype : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
   });
},1000)
//]]>

7. Replace the following line

<textarea name="'.$this->getName().'" title="'.$this->getTitle().'" id="'.$this->getHtmlId().'" class="textarea '.$this->getClass().'" '.$this->serialize($this->getHtmlAttributes()).' >'.$this->getEscapedValue().'</textarea>

with this

<textarea name="'.$this->getName().'" title="'.$this->getTitle().'" id="'.$this->getHtmlId().'" class="textarea '.$this->getClass().'" '.$this->serialize($this->getHtmlAttributes()).' >'. ( $this->getEscapedValue() ? $this->getEscapedValue() : 'Content Here' ) .'</textarea>

This step will add the text ‘Content Here’ into the text block if it does not contain an initial value. This is required. Otherwise, you will not be able to save the form. It will err with a message reading, “This is a required field.”

Adding extra functionality to TinyMCE

Adding extra functionality to TinyMCE via plugins and additional toolbar buttons is fairly easy. You should read the documentation and examples that come with TinyMCE to do so.

Edit the following file:

app/code/local/Varien/Data/Form/Element/Editor.php

After the line:

theme_advanced_resize_horizontal : "false",

These code below works with my TinyMCE version 3.2.1.1. For most of my sites, I add the following:

plugins : "inlinepopups,style,table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras",//,zoom,layer,preview
theme_advanced_buttons1 : "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,|,styleprops,|,cite,abbr,acronym,del,ins,|,visualchars,nonbreaking",//insertlayer,moveforward,movebackward,absolute

In the strings “theme_advanced_buttons1“, “theme_advanced_buttons2“, and “theme_advanced_buttons3“, the numbers 1 through 3 correspond to the toolbar row on which that the buttons will appear. A pipe “|“, will appear as a separator between buttons that you wish to group together.

Note that I have commented out the following plugins for the following reasons:

//,zoom,layer,preview
  • zoom” → caused the editor to not display
  • preview” → did not work for me
  • layer” → removed for my own personal preference.

In the line starting with “theme_advanced_buttons3“, I have chosen to comment out the following buttons:

//insertlayer,moveforward,movebackward,absolute,|

These buttons correspond to the “layer” plugin I removed and allowing for the user to edit absolute positioning of elements. Again, this was just personal preference, as I didn’t want my users to have the ability to create new z-indexed layers, or use absolute positioning. Although, these will function as intended if you choose to use them.

luispic wrote:

I’m not sure if it’s Magento’s issue or tinyMCE but the editor won’t start if we leave the fourth line of buttons “theme_advanced_buttons4“, I’ve tested this on Magento version: 1.3.2.4 and TinyMCE version: 3.2.7

This appears to be a regression in the newer version of TinyMCE. You may now have only 3 lines. The documentation at http://wiki.moxiecode.com/index.php/TinyMCE:Configuration/theme_advanced_buttons_1_n reads “You may only use theme_advanced_buttons<1-n> once for each value of n where n is a whole number in the range of 1 through 3.”. The previous buttons from line 4 have been appended to line 3.

You're finished!

Be sure to remove your cache files and refresh the pages in your browser to load the javascript files.




 

Magento 2 GitHub Repository

Magento Job Board - Some sort of tag line goes here

Latest Posts| View all Jobs