Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "tinymce"

perform an Ajax in Place Rich editor combining inPlaceRichEditor and TinyMCE

A few days ago i found a problem about how to edit some term of a contract explicitly or with the WYSIWYG way. So I tried to googling and found this fancy example about how to cover my problem, that was inPlaceRichEditor. The first step, i tried to create A helper that could render the rich editor easily by modified the JavascriptHelper that is included in sf directory. You should notice that this stuff need Prototype 1.6, scriptaculous 1.8 and tinyMCE 2.1.3. put this code on your apps/lib/helper directory;

<?php
/*
 * AjaxEditInPlaceEditor.php
 * Helper for in place rich editor 
 */
function input_in_place_rich_editor_tag($name, $url, $editor_options = array())
  {
    $response = sfContext::getInstance()->getResponse();
    $response->addJavascript('/js/prototype');
    $response->addJavascript('/js/scriptaculous');
    $response->addJavascript('/js/controls');
    $response->addJavascript('/js/effects');
    $response->addJavascript('/js/tiny_mce/tiny_mce');
    $response->addJavascript('/js/inplacericheditor');
    $response->addJavascript('/js/tiny_mce_init');
 
 
    $editor_options = _convert_options($editor_options);
    $default_options = array('tag' => 'span', 'id' => '\''.$name.'_in_place_editor', 'class' => 'in_place_editor_field');
 
    return _in_place_rich_editor($name, $url, array_merge($default_options, $editor_options));
  }
function _in_place_rich_editor($field_id, $url, $options = array())
    {
      $javascript = "new Ajax.InPlaceRichEditor(";
 
      $javascript .= "'$field_id', ";
      $javascript .= "'" . url_for($url) . "'";
 
      $js_options = array();
 
      if (isset($options['tokens'])) $js_options['tokens'] = _array_or_string_for_javascript($options['tokens']);
 
      if (isset($options['cancel_text']))
      {
        $js_options['cancelText'] = "'".$options['cancel_text']."'";
      }
      if (isset($options['save_text']))
      {
        $js_options['okText'] = "'".$options['save_text']."'";
      }
      if (isset($options['external_control']))
      {
        $js_options['externalControl'] = "'".$options['external_control']."'";
      }
      if (isset($options['options']))
      {
        $js_options['ajaxOptions'] = $options['options'];
      }
      if (isset($options['with']))
      {
        $js_options['callback'] = "function(form, value) { return ".$options['with']." }";
      }
      if (isset($options['highlightcolor']))
      {
        $js_options['highlightcolor'] = "'".$options['highlightcolor']."'";
      }
      if (isset($options['highlightendcolor']))
      {
        $js_options['highlightendcolor'] = "'".$options['highlightendcolor']."'";
      }
      if (isset($options['loadTextURL']))
      {
        $js_options['loadTextURL'] =  "'".$options['loadTextURL']."'";
      }
 
 
      $javascript .= ', '._options_for_javascript($js_options);
      $javascript .= ');';
 
      return javascript_tag($javascript);
    }
 

As my experience,the inPlaceRichEditor need prototype.js,scriptaculous.js, inplacericheditor.js, controls.js and effects.js exists in the same directory (in /web/js directory). I don't know if you may be could cover this problem if u stay using alias or using sf_prototype_web_dir(/sf/prototype).

and then, here we go.. put this code on your template to perform the ajax in place rich editor

<?php use_helper('AjaxInPlaceRichEditor') ?>
<div id="term1">
your text ready to edit
</div>
<?php echo input_in_place_rich_editor_tag('term1', 'myModule/myAction',array('options'     =>"{method: 'post'}")) ?> 
 

that's it, very simple and very nice stuff.

PS:i'm sorry if my english sounds pretty awkward, cause i don't speak english well

by Imron Setio Widodo on 2008-02-03, tagged ajax  tinymce 
(1 comment)

Integration of the TinyFCK widget

There are two big open source rich text editors:

Some people prefer the first, some other the second, but there’s a problem for who likes to use TinyMCE: it lacks of a free file manager/uploader.

What we actually need is to have a TinyMCE installation with a free file manager/uploader, thus we take it from FCKEditor.

This is TinyFCK: a TinyMCE with the FCKEditor’s file manager/uploader, nothing less, nothing more.

Installation of TinyFCK rich text editing is described here. You need to download the editor from the project website (http://p4a.crealabsfoundation.org/tinyfck) and unpack it in a temporary folder. Copy the tiny_fck/ directory into your project web/js/ directory, and define the path to the library and new rich editor class in settings.yml.

all:
  .settings:
    rich_text_editor_class: TinyFCK
    rich_text_js_dir:  js/tiny_fck
 

After that create new text editor class file sfRichTextEditorTinyFCK.class.php in your project or application lib/ folder.

<?php
 
/*
 * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
 * (c) 2007 Eugene Krasichkov <megazlo@megazlo.com>
 *  
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
 
/**
 * sfRichTextEditorTinyFCK implements the TinyFCK rich text editor.
 *
 * <b>Options:</b>
 *  - css - Path to the TinyFCK editor stylesheet
 *
 *    <b>Css example:</b>
 *    <code>
 *    / * user: foo * / => without spaces. 'foo' is the name in the select box
 *    .foobar
 *    {
 *      color: #f00;
 *    }
 *    </code>
 *
 */
class sfRichTextEditorTinyFCK extends sfRichTextEditor
{
  /**
   * Returns the rich text editor as HTML.
   *
   * @return string Rich text editor HTML representation
   */
  public function toHTML()
  {
    $options = $this->options;
 
    // we need to know the id for things the rich text editor
    // in advance of building the tag
    $id = _get_option($options, 'id', $this->name);
 
    // use tinymce's gzipped js?
    $tinymce_file = _get_option($options, 'tinymce_gzip') ? '/tiny_mce_gzip.php' : '/tiny_mce.js';
 
    // tinymce installed?
    $js_path = sfConfig::get('sf_rich_text_js_dir') ? '/'.sfConfig::get('sf_rich_text_js_dir').$tinymce_file : '/sf/tinymce/js'.$tinymce_file;
    if (!is_readable(sfConfig::get('sf_web_dir').$js_path))
    {
      throw new sfConfigurationException('You must install TinyFCK to use this helper (see rich_text_js_dir settings).');
    }
 
    sfContext::getInstance()->getResponse()->addJavascript($js_path);
 
    use_helper('Javascript');
 
    $tinymce_options = '';
    $style_selector  = '';
 
    // custom CSS file?
    if ($css_file = _get_option($options, 'css'))
    {
      $css_path = stylesheet_path($css_file);
 
      sfContext::getInstance()->getResponse()->addStylesheet($css_path);
 
      $css    = file_get_contents(sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.$css_path);
      $styles = array();
      preg_match_all('#^/\*\s*user:\s*(.+?)\s*\*/\s*\015?\012\s*\.([^\s]+)#Smi', $css, $matches, PREG_SET_ORDER);
      foreach ($matches as $match)
      {
        $styles[] = $match[1].'='.$match[2];
      }
 
      $tinymce_options .= '  content_css: "'.$css_path.'",'."\n";
      $tinymce_options .= '  theme_advanced_styles: "'.implode(';', $styles).'"'."\n";
      $style_selector   = 'styleselect,separator,';
    }
 
    $culture = sfContext::getInstance()->getUser()->getCulture();
 
    $tinymce_js = '
tinyMCE.init({
  mode: "exact",
  language: "'.strtolower(substr($culture, 0, 2)).'",
  elements: "'.$id.'",
  plugins : "table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,zoom,flash,searchreplace,print,paste,directionality,fullscreen,noneditable,contextmenu",
  theme: "advanced",
  theme_advanced_buttons1_add_before : "save,newdocument,separator",
    theme_advanced_buttons1_add : "fontselect,fontsizeselect",
    theme_advanced_buttons2_add : "separator,insertdate,inserttime,preview,zoom,separator,forecolor,backcolor,liststyle",
    theme_advanced_buttons2_add_before: "cut,copy,paste,pastetext,pasteword,separator,search,replace,separator",
    theme_advanced_buttons3_add_before : "tablecontrols,separator",
    theme_advanced_buttons3_add : "emotions,iespell,flash,advhr,separator,print,separator,ltr,rtl,separator,fullscreen",
    theme_advanced_toolbar_location : "top",
    theme_advanced_toolbar_align : "left",
    theme_advanced_statusbar_location : "bottom",
  theme_advanced_resizing : true,
  theme_advanced_resize_horizontal : false,
  plugin_insertdate_dateFormat : "%Y-%m-%d",
  plugin_insertdate_timeFormat : "%H:%M:%S",
  file_browser_callback : "tinyFCKFileBrowserCallBack",
  paste_use_dialog : false,
  extended_valid_elements: "img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name]",
  apply_source_formatting : true,
  relative_urls: false,
  debug: false
  '.($tinymce_options ? ','.$tinymce_options : '').'
  '.(isset($options['tinymce_options']) ? ','.$options['tinymce_options'] : '').'
});
 
  function tinyFCKFileBrowserCallBack(field_name, url, type, win) {
    var connector = "../../filemanager/browser.html?Connector=connectors/php/connector.php";
    var enableAutoTypeSelection = true;
 
    var cType;
    tinyfck_field = field_name;
    tinyfck = win;
 
    switch (type) {
      case "image":
        cType = "Image";
        break;
      case "flash":
        cType = "Flash";
        break;
      case "file":
        cType = "File";
        break;
    }
 
    if (enableAutoTypeSelection && cType) {
      connector += "&Type=" + cType;
    }
 
    window.open(connector, "tinyfck", "modal,width=600,height=400");
  }';
 
    if (isset($options['tinymce_options']))
    {
      unset($options['tinymce_options']);
    }
 
    return
      content_tag('script', javascript_cdata_section($tinymce_js), array('type' => 'text/javascript')).
      content_tag('textarea', $this->content, array_merge(array('name' => $this->name, 'id' => get_id_from_name($id, null)), _convert_options($options)));
  }
}
 

Then clear cache:

symfony cc
 

Once this is done, toggle the use of rich text editing in text areas by adding the rich=true option. You can also specify custom options for the TinyFCK editor using the tinymce_options option.

<?php echo textarea_tag('name', 'default content', 'rich=true size=10x20')) ?>
 => a rich text edit zone powered by TinyFCK
<?php echo textarea_tag('name', 'default content', 'rich=true size=10x20tinymce_options=language:"fr",theme_advanced_buttons2:"separator"')) ?>
=> a rich text edit zone powered by TinyFCK with custom parameters
 
by Eugene Krasichkov on 2007-12-27, tagged editor  fckeditor  form  forms  helper  rich  tinyfck  tinymce 
(1 comment)

Change detection for admin generator

This JavaScript code registers a change detection mechanism in every form field and notifies the user about unsaved changes. No changes need to be applied to existing modules/actions. Additionaly, the TinyMCE helper can be changed in order to detect changes there as well.

Only requirement: the links for leaving the page need to be in a container with id "header". This can of course be changed.

Add this to the head of the page (or to an external js-file):

var changesDetected = false;
 
/**
 * Registers a change detection mechanism that notifies users about unsaved changes whenever they click on a link.
 */
function registerChangeDetection() {
    /**
     * Notifies user about unsaved changes
     */
    function notifyAboutChanges(e) {
        if(changesDetected){
            //My choice: modal dialog using modalbox (http://www.wildbit.com/labs/modalbox/)
            //Modalbox.show('<div class=\'warning\'><p>Before continuing, you need to save you changes.</p> <input type=\'button\' value=\'Ignore changes\' onclick=\'changesDetected=false;Modalbox.hide()\' style=\'color: #999\' /> <input type=\'button\' value=\'OK\' onclick=\'Modalbox.hide()\' /></div>',  {title: 'Warning', width: 300});
            //Alternative:
            alert('Before continuing, you need to save your changes.');
            return false;
        }
    }
 
    /* Add change detection to every form field */
    if(document.forms.sf_admin_edit_form != null) {
        var elements = Form.getElements(document.forms.sf_admin_edit_form);
        elements.each(function(item) {
            item.onchange = function(e) { changesDetected = true; }
        });
    }
 
    /* Add an onclick handler to every link in the container with id "header" */
    var links = $$('#header a');
    links.each(function(item) {
        if(!(item.onclick instanceof Function)) { //Avoid overwriting existing onclick handlers
            item.onclick = notifyAboutChanges;
        }
    });
}
 

Register the change detection in the body tag:

<body onload="registerChangeDetection()">
 

I also modified the sfRichTextEditorTinyMCE helper in order to use TinyMCE 3 (currently beta). Here is the code relevant to change detection to be put into TinyMCE.init({...}) (Go to http://wiki.moxiecode.com/index.php/TinyMCE:API/tinymce.Editor/onChange for more information):

setup: function(ed) {
    var i = 0;
    ed.onChange.add(function(ed, l) {
        if(i == 0) i++ //Ignore the first change
        else changesDetected = true;
    });
}
 
by Michel Weimerskirch on 2007-12-05, tagged admin  changes  detection  generator  javascript  tinymce 

TinyMCE in AJAX call

If you want to use a TinyMCE editor in a form called by ajax, you have to make some additional changes to the code. It's not complicated.

Include TinyMCE

In view.yml include TinyMCE and Prototype:

  javascripts:    [/sf/js/prototype/prototype.js, /js/tiny_mce/tiny_mce.js]

Init TinyMCE

In your main decoration template include the javascript code bellow (best at the end of the file). In most cases this code will be the layout.php.

<?php echo javascript_tag('
var activatedAreas = new Array();   
 
function setTextareaToTinyMCE(sEditorID) 
{
  var oEditor = document.getElementById(sEditorID);
    if(oEditor) 
  {
    if(activatedAreas[sEditorID] == true)
      unsetTextareaToTinyMCE(sEditorID);
    try {
      activatedAreas[sEditorID] = true;
      tinyMCE.execCommand("mceAddControl", true, sEditorID);                    
    }
    catch(e)
    {
      alert("Error activating element " + sEditorID + "\n" + e);
    }
  }
}
 
function unsetTextareaToTinyMCE(sEditorID) 
{
  var oEditor = document.getElementById(sEditorID);
  if(oEditor && (activatedAreas[sEditorID] == true)) 
  {
    try 
    {
      tinyMCE.execCommand("mceRemoveControl", true, sEditorID);
      activatedAreas[sEditorID] = false;
    }
    catch(e)
    {
      alert("Error deactivating element " + sEditorID + "\n" + e);
    }
  }
}
 
function tinymceDeactivate()
{
  try {
    tinyMCE.triggerSave(true,true);         
  }
  catch(e)
  {
    alert("Error saving form\n" + e);
  }
 
  for(var i in activatedAreas)
  {
    if(activatedAreas[i] == true) 
    {
      unsetTextareaToTinyMCE(i);
    }
  }
}
 
function submitForm(formId)
{
 if($(formId).onsubmit())
 {
    $(formId).submit();
 }
}
 
tinyMCE.init({
  theme : "advanced",
  language : "en",
  mode : "exact",
  relative_urls : false,
  debug : false,  
  valid_elements : "*[*]",
  height:"100%",
  width:"100%",
  theme_advanced_resize_horizontal : false,
  theme_advanced_resizing : true,
  auto_reset_designmode : true
});
') ?>

Action AJAX call

And now finally in the action template which is called by ajax, use the code fragment bellow. The link_to_remote call has to have script => true.

Form:

  <form id="form_id">
 
    ......
 
    <?php echo textarea_tag('article','article','size=10x30'); ?>
 
    ......
 
  </form>

At the end of the action template (e. g. editSuccess.php):

  <a class="button save" alt="SAVE" href="#" onclick="tinymceDeactivate();submitForm('form_id'); return false">SAVE</a>  
  <?php echo javascript_tag(' 
    setTextareaToTinyMCE("article");  
  ') ?>

The important thing was to deactivate the tinymce editor on textarea before submitting the form, otherwise there were errors after re-appearing of the form.

by František Tröster on 2006-08-31, tagged ajax  tinymce 
(1 comment)