3 * THtmlArea class file.
5 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6 * @link http://www.pradosoft.com/
7 * @copyright Copyright © 2005-2014 PradoSoft
8 * @license http://www.pradosoft.com/license/
9 * @package System.Web.UI.WebControls
13 * Includes TTextBox class
15 Prado::using('System.Web.UI.WebControls.TTextBox');
20 * THtmlArea wraps the visual editting functionalities provided by the
21 * TinyMCE project {@link http://tinymce.moxiecode.com/}.
23 * THtmlArea displays a WYSIWYG text area on the Web page for user input
24 * in the HTML format. The text displayed in the THtmlArea component is
25 * specified or determined by using the <b>Text</b> property.
27 * To enable the visual editting on the client side, set the property
28 * <b>EnableVisualEdit</b> to true (which is default value).
29 * To set the size of the editor when the visual editting is enabled,
30 * set the <b>Width</b> and <b>Height</b> properties instead of
31 * <b>Columns</b> and <b>Rows</b> because the latter has no meaning
32 * under the situation.
34 * The default editor gives only the basic tool bar. To change or add
35 * additional tool bars, use the {@link setOptions Options} property to add additional
36 * editor options with each options on a new line.
37 * See http://tinymce.moxiecode.com/tinymce/docs/index.html
38 * for a list of options. The options can be change/added as shown in the
43 * plugins : "contextmenu,paste"
50 * The client-side visual editting capability is supported by
51 * Internet Explorer 5.0+ for Windows and Gecko-based browser.
52 * If the browser does not support the visual editting,
53 * a traditional textarea will be displayed.
58 * Windows XP MacOS X 10.4
59 * ----------------------------------------------------
66 * Safari 2.0 (412) OK(1)
67 * Opera 9 Preview 1 OK(1) OK(1)
68 * ----------------------------------------------------
69 * * (1) - Partialy working
70 * ----------------------------------------------------
73 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
74 * @package System.Web.UI.WebControls
77 class THtmlArea extends TTextBox
80 * @var array list of locale => language file pairs.
82 private static $_langs = array(
165 * @var array list of default plugins to load, override using getAvailablePlugins();
167 private static $_plugins = array(
209 * @var array default themes to load
211 private static $_themes = array(
218 * Sets default width and height.
220 public function __construct()
222 $this->setWidth('470px');
223 $this->setHeight('250px');
227 * Overrides the parent implementation.
228 * TextMode for THtmlArea control is always 'MultiLine'
229 * @return string the behavior mode of the THtmlArea component.
231 public function getTextMode()
237 * Overrides the parent implementation.
238 * TextMode for THtmlArea is always 'MultiLine' and cannot be changed to others.
239 * @param string the text mode
241 public function setTextMode($value)
243 throw new TInvalidOperationException("htmlarea_textmode_readonly");
247 * @return boolean whether change of the content should cause postback. Return false if EnableVisualEdit is true.
249 public function getAutoPostBack()
251 return $this->getEnableVisualEdit() ? false : parent::getAutoPostBack();
255 * @return boolean whether to show WYSIWYG text editor. Defaults to true.
257 public function getEnableVisualEdit()
259 return $this->getViewState('EnableVisualEdit',true);
263 * Sets whether to show WYSIWYG text editor.
264 * @param boolean whether to show WYSIWYG text editor
266 public function setEnableVisualEdit($value)
268 $this->setViewState('EnableVisualEdit',TPropertyValue::ensureBoolean($value),true);
272 * Gets the current culture.
273 * @return string current culture, e.g. en_AU.
275 public function getCulture()
277 return $this->getViewState('Culture', '');
281 * Sets the culture/language for the html area
282 * @param string a culture string, e.g. en_AU.
284 public function setCulture($value)
286 $this->setViewState('Culture', $value, '');
290 * Gets the list of options for the WYSIWYG (TinyMCE) editor
291 * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
292 * @return string options
294 public function getOptions()
296 return $this->getViewState('Options', '');
300 * Sets the list of options for the WYSIWYG (TinyMCE) editor
301 * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
302 * @param string options
304 public function setOptions($value)
306 $this->setViewState('Options', $value, '');
310 * @param string path to custom plugins to be copied.
312 public function setCustomPluginPath($value)
314 $this->setViewState('CustomPluginPath', $value);
318 * @return string path to custom plugins to be copied.
320 public function getCustomPluginPath()
322 return $this->getViewState('CustomPluginPath');
326 * @return boolean enable compression of the javascript files, default is true.
328 public function getEnableCompression()
330 return $this->getViewState('EnableCompression', true);
334 * @param boolean enable compression of the javascript files, default is true.
336 public function setEnableCompression($value)
338 $this->setViewState('EnableCompression', TPropertyValue::ensureBoolean($value));
342 * Adds attribute name-value pairs to renderer.
343 * This method overrides the parent implementation by registering
344 * additional javacript code.
345 * @param THtmlWriter the writer used for the rendering purpose
347 protected function addAttributesToRender($writer)
349 if($this->getEnableVisualEdit() && $this->getEnabled(true))
351 $writer->addAttribute('id',$this->getClientID());
352 $this->registerEditorClientScript($writer);
355 parent::addAttributesToRender($writer);
359 * Returns a list of plugins to be loaded.
360 * Override this method to customize.
361 * @return array list of plugins to be loaded
363 public function getAvailablePlugins()
365 return self::$_plugins;
369 * @return array list of available themese
371 public function getAvailableThemes()
373 return self::$_themes;
376 protected function getCompressionOptions()
379 'plugins' => implode(',', $this->getAvailablePlugins()),
380 'themes' => implode(',', $this->getAvailableThemes()),
381 'languages' => $this->getLanguageSuffix($this->getCulture()),
382 'disk_cache' => true,
387 protected function loadJavascriptLibrary()
389 $scripts = $this->getPage()->getClientScript();
390 $scripts->registerPradoScript('htmlarea');
391 $scripts->registerScriptFile('prado:THtmlArea', $this->getScriptUrl());
395 * Registers the editor javascript file and code to initialize the editor.
397 protected function registerEditorClientScript($writer)
399 $this->loadJavascriptLibrary();
400 $scripts = $this->getPage()->getClientScript();
402 'EditorOptions' => $this->getEditorOptions()
404 if($this->getEnableCompression())
405 $options['CompressionOptions'] = $this->getCompressionOptions();
407 $options = TJavaScript::encode($options,true,true);
408 $script = "new Prado.WebUI.THtmlArea($options)";
409 $scripts->registerEndScript('prado:THtmlArea'.$this->ClientID,$script);
413 * @return string editor script URL.
415 protected function getScriptUrl()
417 if($this->getEnableCompression())
418 return $this->getScriptDeploymentPath().'/tiny_mce/tiny_mce_gzip.js';
420 return $this->getScriptDeploymentPath().'/tiny_mce/tiny_mce.js';
424 * Gets the editor script base URL by publishing the tarred source via TTarAssetManager.
425 * @return string URL base path to the published editor script
427 protected function getScriptDeploymentPath()
429 $tarfile = Prado::getPathOfNamespace('System.3rdParty.TinyMCE.tiny_mce', '.tar');
430 $md5sum = Prado::getPathOfNamespace('System.3rdParty.TinyMCE.tiny_mce', '.md5');
431 if($tarfile===null || $md5sum===null)
432 throw new TConfigurationException('htmlarea_tarfile_invalid');
433 $url = $this->getApplication()->getAssetManager()->publishTarFile($tarfile, $md5sum);
434 $this->copyCustomPlugins($url);
438 protected function copyCustomPlugins($url)
440 if($plugins = $this->getCustomPluginPath())
442 $assets = $this->getApplication()->getAssetManager();
443 $path = is_dir($plugins) ? $plugins : Prado::getPathOfNameSpace($plugins);
444 $dest = $assets->getBasePath().'/'.basename($url).'/tiny_mce/plugins/';
445 if(!is_dir($dest) || $this->getApplication()->getMode()!==TApplicationMode::Performance)
446 $assets->copyDirectory($path, $dest);
451 * Default editor options gives basic tool bar only.
452 * @return array editor initialization options.
454 protected function getEditorOptions()
456 $options['mode'] = 'exact';
457 $options['elements'] = $this->getClientID();
458 $options['language'] = $this->getLanguageSuffix($this->getCulture());
459 $options['theme'] = 'advanced';
461 //make it basic advanced to fit into 1 line of buttons.
462 //$options['theme_advanced_buttons1'] = 'bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright, justifyfull,separator,bullist,numlist,separator,undo,redo,separator,link,unlink,separator,charmap,separator,code,help';
463 //$options['theme_advanced_buttons2'] = ' ';
464 $options['theme_advanced_buttons1'] = 'formatselect,fontselect,fontsizeselect,separator,bold,italic,underline,strikethrough,sub,sup';
465 $options['theme_advanced_buttons2'] = 'justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,outdent,indent,separator,forecolor,backcolor,separator,hr,link,unlink,image,charmap,separator,removeformat,code,help';
466 $options['theme_advanced_buttons3'] = '';
468 $options['theme_advanced_toolbar_location'] = 'top';
469 $options['theme_advanced_toolbar_align'] = 'left';
470 $options['theme_advanced_path_location'] = 'bottom';
471 $options['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]';
472 if($this->getReadOnly())
473 $options['readonly'] = true;
475 $options = array_merge($options, $this->parseEditorOptions($this->getOptions()));
480 * Parse additional options set in the Options property.
481 * @return array additional custom options
483 protected function parseEditorOptions($string)
486 $substrings = preg_split('/,\s*\n|\n/', trim($string));
487 foreach($substrings as $bits)
489 $option = explode(":",$bits,2);
491 if(count($option) == 2)
493 $value=trim(trim($option[1]),"'\"");
494 if (($s=strtolower($value))==='false')
498 $options[trim($option[0])] = $value;
505 * @return string localized editor interface language extension.
507 protected function getLanguageSuffix($culture)
509 $app = $this->getApplication()->getGlobalization();
510 if(empty($culture) && ($app!==null))
511 $culture = $app->getCulture();
514 $variants = $app->getCultureVariants($culture);
516 foreach($variants as $variant)
518 if(isset(self::$_langs[$variant]))
519 return self::$_langs[$variant];
526 * Gets the name of the javascript class responsible for performing postback for this control.
527 * This method overrides the parent implementation.
528 * @return string the javascript class name
530 protected function getClientClassName()
532 return 'Prado.WebUI.THtmlArea';