001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.acacia.client.widgets; 029 030import org.opencms.acacia.client.CmsEditorBase; 031import org.opencms.acacia.client.css.I_CmsLayoutBundle; 032import org.opencms.gwt.client.CmsCoreProvider; 033import org.opencms.gwt.client.util.CmsDomUtil; 034import org.opencms.gwt.client.util.CmsDomUtil.Style; 035 036import com.google.gwt.core.client.JavaScriptObject; 037import com.google.gwt.core.client.Scheduler; 038import com.google.gwt.core.client.Scheduler.ScheduledCommand; 039import com.google.gwt.dom.client.Document; 040import com.google.gwt.dom.client.Element; 041import com.google.gwt.dom.client.NativeEvent; 042import com.google.gwt.event.dom.client.ClickEvent; 043import com.google.gwt.event.dom.client.ClickHandler; 044import com.google.gwt.event.dom.client.DomEvent; 045import com.google.gwt.event.logical.shared.HasResizeHandlers; 046import com.google.gwt.event.logical.shared.ResizeEvent; 047import com.google.gwt.event.logical.shared.ResizeHandler; 048import com.google.gwt.event.logical.shared.ValueChangeEvent; 049import com.google.gwt.event.logical.shared.ValueChangeHandler; 050import com.google.gwt.event.shared.HandlerRegistration; 051import com.google.gwt.user.client.DOM; 052 053/** 054 * This class is used to start TinyMCE for editing the content of an element.<p> 055 * 056 * After constructing the instance, the actual editor is opened using the init() method, and destroyed with the close() 057 * method. While the editor is opened, the edited contents can be accessed using the methods of the HasValue interface. 058 */ 059public final class CmsTinyMCEWidget extends A_CmsEditWidget implements HasResizeHandlers, I_CmsHasDisplayDirection { 060 061 /** Use as option to disallow any HTML or formatting the content. */ 062 public static final String NO_HTML_EDIT = "no_html_edit"; 063 064 /** The disabled style element id. */ 065 private static final String DISABLED_STYLE_ID = "editorDisabledStyle"; 066 067 /** The minimum editor height. */ 068 private static final int MIN_EDITOR_HEIGHT = 70; 069 070 /** A flag which indicates whether the editor is currently active. */ 071 protected boolean m_active; 072 073 /** The current content. */ 074 protected String m_currentContent; 075 076 /** The TinyMCE editor instance. */ 077 protected JavaScriptObject m_editor; 078 079 /** The DOM ID of the editable element. */ 080 protected String m_id; 081 082 /** The original HTML content of the editable element. */ 083 protected String m_originalContent; 084 085 /** The maximal width of the widget. */ 086 protected int m_width; 087 088 /** The editor height to set. */ 089 int m_editorHeight; 090 091 /** Flag indicating the editor has been initialized. */ 092 boolean m_initialized; 093 094 /** The element to store the widget content in. */ 095 private Element m_contentElement; 096 097 /** Indicates the value has been set from external, not from within the widget. */ 098 private boolean m_externalValueChange; 099 100 /** Indicating if the widget has been attached yet. */ 101 private boolean m_hasBeenAttached; 102 103 /** Flag indicating if in line editing is used. */ 104 private boolean m_inline; 105 106 /** The editor options. */ 107 private Object m_options; 108 109 private String m_typografLocale; 110 111 /** 112 * Creates a new instance for the given element. Use this constructor for in line editing.<p> 113 * 114 * @param element the DOM element 115 * @param options the tinyMCE editor options to extend the default settings 116 */ 117 public CmsTinyMCEWidget(Element element, Object options) { 118 119 this(element, options, true); 120 } 121 122 /** 123 * Creates a new instance with the given options. Use this constructor for form based editing.<p> 124 * 125 * @param options the tinyMCE editor options to extend the default settings 126 */ 127 public CmsTinyMCEWidget(Object options) { 128 129 this(DOM.createDiv(), options, false); 130 } 131 132 /** 133 * Constructor.<p> 134 * 135 * @param element the DOM element 136 * @param options the tinyMCE editor options to extend the default settings 137 * @param inline flag indicating if in line editing is used 138 */ 139 private CmsTinyMCEWidget(Element element, Object options, boolean inline) { 140 141 super(element); 142 m_originalContent = ""; 143 m_options = options; 144 m_active = true; 145 m_inline = inline; 146 if (m_inline) { 147 m_contentElement = element; 148 } else { 149 // using a child DIV as content element 150 m_contentElement = getElement().appendChild(DOM.createDiv()); 151 } 152 } 153 154 /** 155 * Returns the disabled text color.<p> 156 * 157 * @return the disabled text color 158 */ 159 private static String getDisabledTextColor() { 160 161 return I_CmsLayoutBundle.INSTANCE.constants().css().textColorDisabled(); 162 } 163 164 /** 165 * @see com.google.gwt.event.logical.shared.HasResizeHandlers#addResizeHandler(com.google.gwt.event.logical.shared.ResizeHandler) 166 */ 167 public HandlerRegistration addResizeHandler(ResizeHandler handler) { 168 169 return addHandler(handler, ResizeEvent.getType()); 170 } 171 172 /** 173 * @see org.opencms.acacia.client.widgets.A_CmsEditWidget#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) 174 */ 175 @Override 176 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) { 177 178 return addHandler(handler, ValueChangeEvent.getType()); 179 } 180 181 /** 182 * @see org.opencms.acacia.client.widgets.I_CmsHasDisplayDirection#getDisplayingDirection() 183 */ 184 public Direction getDisplayingDirection() { 185 186 return Direction.above; 187 } 188 189 /** 190 * Gets the main editable element.<p> 191 * 192 * @return the editable element 193 */ 194 public Element getMainElement() { 195 196 return m_contentElement; 197 } 198 199 /** 200 * @see com.google.gwt.user.client.ui.HasValue#getValue() 201 */ 202 @Override 203 public String getValue() { 204 205 if (m_editor != null) { 206 return getContent().trim(); 207 } 208 return m_originalContent.trim(); 209 } 210 211 /** 212 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#isActive() 213 */ 214 public boolean isActive() { 215 216 return m_active; 217 } 218 219 /** 220 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setActive(boolean) 221 */ 222 public void setActive(boolean active) { 223 224 if (m_active == active) { 225 return; 226 } 227 m_active = active; 228 if (m_editor != null) { 229 if (m_active) { 230 getElement().removeClassName(I_CmsLayoutBundle.INSTANCE.form().inActive()); 231 removeEditorDisabledStyle(); 232 fireValueChange(true); 233 } else { 234 getElement().addClassName(I_CmsLayoutBundle.INSTANCE.form().inActive()); 235 setEditorDisabledStyle(); 236 } 237 } 238 } 239 240 /** 241 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setName(java.lang.String) 242 */ 243 public void setName(String name) { 244 245 // no input field so nothing to do 246 247 } 248 249 /** 250 * Sets the Typograf locale for inline editing mode. 251 */ 252 public void setTypografLocale(String typografLocale) { 253 254 m_typografLocale = typografLocale; 255 } 256 257 /** 258 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object) 259 */ 260 public void setValue(String value) { 261 262 setValue(value, false); 263 } 264 265 /** 266 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object, boolean) 267 */ 268 public void setValue(String value, boolean fireEvents) { 269 270 if (value != null) { 271 value = value.trim(); 272 } 273 setPreviousValue(value); 274 if (m_editor == null) { 275 // editor has not been initialized yet 276 m_originalContent = value; 277 } else { 278 m_externalValueChange = true; 279 setContent(value); 280 } 281 if (fireEvents) { 282 fireValueChange(true); 283 } 284 } 285 286 /** 287 * Checks whether the necessary Javascript libraries are available by accessing them. 288 */ 289 protected native void checkLibraries() /*-{ 290 // fail early if tinymce is not available 291 var w = $wnd; 292 var init = w.tinyMCE.init; 293 }-*/; 294 295 /** 296 * Gives an element an id if it doesn't already have an id, and then returns the element's id.<p> 297 * 298 * @param element the element for which we want to add the id 299 * 300 * @return the id 301 */ 302 protected String ensureId(Element element) { 303 304 String id = element.getId(); 305 if ((id == null) || "".equals(id)) { 306 id = Document.get().createUniqueId(); 307 element.setId(id); 308 } 309 return id; 310 } 311 312 /** 313 * Returns the editor parent element.<p> 314 * 315 * @return the editor parent element 316 */ 317 protected Element getEditorParentElement() { 318 319 String parentId = m_id + "_parent"; 320 Element result = getElementById(parentId); 321 return result; 322 } 323 324 /** 325 * Gets an element by its id.<p> 326 * 327 * @param id the id 328 * @return the element with the given id 329 */ 330 protected native Element getElementById(String id) /*-{ 331 return $doc.getElementById(id); 332 }-*/; 333 334 /** 335 * Gets the toolbar element.<p> 336 * 337 * @return the toolbar element 338 */ 339 protected Element getToolbarElement() { 340 341 String toolbarId = m_id + "_external"; 342 Element result = getElementById(toolbarId); 343 return result; 344 } 345 346 /** 347 * Returns if the widget is used in inline mode.<p> 348 * 349 * @return <code>true</code> if the widget is used in inline mode 350 */ 351 protected boolean isInline() { 352 353 return m_inline; 354 } 355 356 /** 357 * @see com.google.gwt.user.client.ui.FocusWidget#onAttach() 358 */ 359 @Override 360 protected void onAttach() { 361 362 super.onAttach(); 363 if (!m_hasBeenAttached) { 364 m_hasBeenAttached = true; 365 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 366 367 public void execute() { 368 369 if (isAttached()) { 370 m_editorHeight = calculateEditorHeight(); 371 m_id = ensureId(getMainElement()); 372 m_width = calculateWidth(); 373 checkLibraries(); 374 if (isInline()) { 375 if (CmsDomUtil.getCurrentStyleInt(getElement(), Style.zIndex) < 1) { 376 getElement().getStyle().setZIndex(1); 377 } 378 addDomHandler(new ClickHandler() { 379 380 public void onClick(ClickEvent event) { 381 382 // prevent event propagation while editing inline, to avoid following links in ancestor nodes 383 event.stopPropagation(); 384 event.preventDefault(); 385 } 386 }, ClickEvent.getType()); 387 } 388 initNative(CmsCoreProvider.get().getWpLanguage()); 389 if (!m_active) { 390 getElement().addClassName(I_CmsLayoutBundle.INSTANCE.form().inActive()); 391 } 392 } else { 393 resetAtachedFlag(); 394 } 395 } 396 }); 397 } 398 } 399 400 /** 401 * @see com.google.gwt.user.client.ui.Widget#onDetach() 402 */ 403 @Override 404 protected void onDetach() { 405 406 try { 407 detachEditor(); 408 } catch (Throwable t) { 409 // may happen in rare cases, can be ignored 410 } 411 super.onDetach(); 412 } 413 414 /** 415 * Propagates the a focus event.<p> 416 */ 417 protected void propagateFocusEvent() { 418 419 if (m_initialized) { 420 NativeEvent nativeEvent = Document.get().createFocusEvent(); 421 DomEvent.fireNativeEvent(nativeEvent, this, getElement()); 422 } 423 } 424 425 /** 426 * Propagates a native mouse event.<p> 427 * 428 * @param eventType the mouse event type 429 * @param eventSource the event source 430 */ 431 protected native void propagateMouseEvent(String eventType, Element eventSource) /*-{ 432 var doc = $wnd.document; 433 var event; 434 if (doc.createEvent) { 435 event = doc.createEvent("MouseEvents"); 436 event.initEvent(eventType, true, true); 437 eventSource.dispatchEvent(event); 438 } else { 439 eventSource.fireEvent("on" + eventType); 440 } 441 }-*/; 442 443 /** 444 * Removes the editor instance.<p> 445 */ 446 protected native void removeEditor() /*-{ 447 var editor = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editor; 448 editor.remove(); 449 }-*/; 450 451 /** 452 * Sets the main content of the element which is inline editable.<p> 453 * 454 * @param html the new content html 455 */ 456 protected native void setMainElementContent(String html) /*-{ 457 var instance = this; 458 var elementId = instance.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_id; 459 var mainElement = $wnd.document.getElementById(elementId); 460 mainElement.innerHTML = html; 461 }-*/; 462 463 /** 464 * Checks if the main element contains the current text selection.<p> 465 * 466 * @return <code>true</code> if the main element contains the current text selection 467 */ 468 protected boolean shouldReceiveFocus() { 469 470 return m_inline && CmsEditorBase.shouldFocusOnInlineEdit(getElement()); 471 } 472 473 /** 474 * Calculates the needed editor height.<p> 475 * 476 * @return the calculated editor height 477 */ 478 int calculateEditorHeight() { 479 480 int result = getElement().getOffsetHeight() + 30; 481 return result > MIN_EDITOR_HEIGHT ? result : MIN_EDITOR_HEIGHT; 482 } 483 484 /** 485 * Calculates the widget width.<p> 486 * 487 * @return the widget width 488 */ 489 int calculateWidth() { 490 491 int result; 492 if (m_inline && CmsDomUtil.getCurrentStyle(getElement(), Style.display).equals("inline")) { 493 com.google.gwt.dom.client.Element parentBlock = getElement().getParentElement(); 494 while (CmsDomUtil.getCurrentStyle(parentBlock, Style.display).equals("inline")) { 495 parentBlock = parentBlock.getParentElement(); 496 } 497 result = parentBlock.getOffsetWidth(); 498 } else { 499 result = getElement().getOffsetWidth(); 500 } 501 return result - 2; 502 } 503 504 /** 505 * Initializes the TinyMCE instance. 506 * 507 * @param locale the UI locale 508 */ 509 native void initNative(String locale) /*-{ 510 511 function merge() { 512 var result = {}, length = arguments.length; 513 for (i = 0; i < length; i++) { 514 for (key in arguments[i]) { 515 if (arguments[i].hasOwnProperty(key)) { 516 result[key] = arguments[i][key]; 517 } 518 } 519 } 520 return result; 521 } 522 523 524 var languageMap = { "it": "it_IT", "cs": "cs_CZ", "ru": "ru_RU", "zh": "zh_CN"}; 525 var translatedLanguage = languageMap[locale]; 526 if (translatedLanguage) { 527 locale = translatedLanguage; 528 } 529 530 531 532 var self = this; 533 var needsRefocus = self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::shouldReceiveFocus()(); 534 var elementId = self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_id; 535 var mainElement = $wnd.document.getElementById(elementId); 536 var editorHeight = self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editorHeight; 537 538 var fireChange = function() { 539 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::fireChangeFromNative()(); 540 }; 541 var options = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_options; 542 if (options != null && options.editorHeight) { 543 editorHeight = options.editorHeight; 544 delete options.editorHeight; 545 } 546 // default options: 547 var defaults; 548 if (@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::NO_HTML_EDIT == options) { 549 // disallow any formatting 550 551 defaults = { 552 selector : mainElement.tagName + "#" + elementId, 553 entity_encoding : "raw", 554 mode : "exact", 555 theme : "silver", 556 plugins : "paste emoticons charmap", 557 paste_as_text : true, 558 toolbar : "undo redo | emoticons charmap", 559 menubar : false, 560 forced_root_block : false 561 }; 562 var typografLocale = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_typografLocale; 563 if (typografLocale) { 564 defaults.plugins = "paste emoticons typograf charmap"; 565 defaults.toolbar = "undo redo | typograf | emoticons charmap"; 566 defaults.typograf = { 567 disableRule: ["*"], 568 enableRule2: ["common/punctuation/quote"], 569 locale: [typografLocale, "en-US"] 570 }; 571 } 572 options = null; 573 } else { 574 defaults = { 575 selector : mainElement.tagName + "#" + elementId, 576 relative_urls : false, 577 remove_script_host : false, 578 entity_encoding : "raw", 579 skin_variant : 'ocms', 580 mode : "exact", 581 theme : "silver", 582 plugins : "autolink lists pagebreak table save codemirror hr image link emoticons spellchecker insertdatetime preview media searchreplace print paste directionality noneditable visualchars nonbreaking template wordcount advlist", 583 paste_as_text : true, 584 menubar : false, 585 }; 586 } 587 if (this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_inline) { 588 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_currentContent = mainElement.innerHTML; 589 defaults.inline = true; 590 defaults.width = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_width; 591 } else { 592 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_currentContent = self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_originalContent; 593 defaults.min_height = 100; 594 defaults.max_height = editorHeight; 595 defaults.width = '100%'; 596 defaults.resize = 'both'; 597 } 598 // extend the defaults with any given options 599 if (options != null) { 600 if (options.style_formats) { 601 // tinymce performs a type test for arrays wich fails in case the array was not created in the same window context 602 var formats = new $wnd.Array(); 603 for (var i = 0; i < options.style_formats.length; i++) { 604 formats[i] = options.style_formats[i]; 605 } 606 options.style_formats = formats; 607 } 608 defaults = merge(defaults, options); 609 } 610 if (this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_inline) { 611 delete defaults.content_css; 612 } else { 613 // enable autoresize 614 defaults.plugins = "autoresize " + defaults.plugins; 615 } 616 if (needsRefocus) { 617 defaults.auto_focus = elementId; 618 } 619 620 // add the setup function 621 defaults.setup = function(ed) { 622 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editor = ed; 623 ed.on('SetContent', fireChange); 624 ed.on('change', fireChange); 625 ed.on('KeyDown', fireChange); 626 ed 627 .on( 628 'LoadContent', 629 function() { 630 if (!self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_inline) { 631 // firing resize event on resize of the editor iframe 632 ed.dom 633 .bind( 634 ed.getWin(), 635 'resize', 636 function() { 637 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::fireResizeEvent()(); 638 }); 639 var content = self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_originalContent; 640 if (content != null) { 641 ed.setContent(content); 642 } 643 } 644 }); 645 ed 646 .on( 647 'init', 648 function() { 649 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::scheduleInitializationDone()(); 650 }); 651 652 if (!self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_inline) { 653 654 ed 655 .on( 656 'Click', 657 function(event) { 658 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::propagateFocusEvent()(); 659 }); 660 ed 661 .on( 662 'activate', 663 function(event) { 664 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::propagateFocusEvent()(); 665 }); 666 ed 667 .on( 668 'focus', 669 function(event) { 670 self.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::propagateFocusEvent()(); 671 }); 672 } 673 }; 674 675 // initialize tinyMCE 676 defaults.language = locale; 677 if (defaults.typograf && $wnd.Typograf && !$wnd.Typograf.hasLocale(defaults.typograf.locale[0])) { 678 delete defaults.typograf; 679 defaults.toolbar1 = defaults.toolbar1.replace("typograf",""); 680 } 681 682 $wnd.tinymce.init(defaults); 683 }-*/; 684 685 /** 686 * Removes the disabled editor styling.<p> 687 */ 688 native void removeEditorDisabledStyle()/*-{ 689 var ed = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editor; 690 var styleEl = ed 691 .getDoc() 692 .getElementById( 693 @org.opencms.acacia.client.widgets.CmsTinyMCEWidget::DISABLED_STYLE_ID); 694 if (styleEl != null) { 695 ed.getDoc().head.removeChild(styleEl); 696 } 697 }-*/; 698 699 /** 700 * Resets the attached flag.<p> 701 */ 702 void resetAtachedFlag() { 703 704 m_hasBeenAttached = false; 705 } 706 707 /** 708 * Scheduling to set the initialized flag.<p> 709 */ 710 void scheduleInitializationDone() { 711 712 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 713 714 public void execute() { 715 716 m_initialized = true; 717 if (m_active) { 718 removeEditorDisabledStyle(); 719 } else { 720 setEditorDisabledStyle(); 721 } 722 } 723 }); 724 } 725 726 /** 727 * Sets the editor disabled styling.<p> 728 */ 729 native void setEditorDisabledStyle()/*-{ 730 var ed = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editor; 731 if (ed 732 .getDoc() 733 .getElementById( 734 @org.opencms.acacia.client.widgets.CmsTinyMCEWidget::DISABLED_STYLE_ID) == null) { 735 var styleEl = ed.getDoc().createElement("style"); 736 styleEl 737 .setAttribute("id", 738 @org.opencms.acacia.client.widgets.CmsTinyMCEWidget::DISABLED_STYLE_ID); 739 var styleText = ed 740 .getDoc() 741 .createTextNode( 742 "body, body *{ color: " 743 + @org.opencms.acacia.client.widgets.CmsTinyMCEWidget::getDisabledTextColor()() 744 + " !important;}"); 745 styleEl.appendChild(styleText); 746 ed.getDoc().head.appendChild(styleEl); 747 } 748 }-*/; 749 750 /** 751 * Removes the editor.<p> 752 */ 753 private native void detachEditor() /*-{ 754 755 var ed = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editor; 756 if (ed != null) { 757 ed.remove(); 758 } 759 // in IE somehow the whole document will be selected, empty the selection to resolve that 760 if ($wnd.document.selection != null) { 761 $wnd.document.selection.empty(); 762 } 763 }-*/; 764 765 /** 766 * Used to fire the value changed event from native code.<p> 767 */ 768 private void fireChangeFromNative() { 769 770 // skip firing the change event, if the external flag is set 771 if (m_initialized && !m_externalValueChange && m_active) { 772 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 773 774 public void execute() { 775 776 try { 777 fireValueChange(false); 778 } catch (Throwable t) { 779 // this may happen when returning from full screen mode, nothing to be done 780 } 781 } 782 }); 783 } 784 // reset the external flag 785 m_externalValueChange = false; 786 } 787 788 /** 789 * Fires the resize event.<p> 790 */ 791 private void fireResizeEvent() { 792 793 ResizeEvent.fire(this, getOffsetWidth(), getOffsetHeight()); 794 } 795 796 /** 797 * Returns the editor content.<p> 798 * 799 * @return the editor content 800 */ 801 private native String getContent() /*-{ 802 var editor = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editor; 803 return editor.getContent(); 804 }-*/; 805 806 /** 807 * Sets the content of the TinyMCE editor.<p> 808 * 809 * @param newContent the new content 810 */ 811 private native void setContent(String newContent) /*-{ 812 var editor = this.@org.opencms.acacia.client.widgets.CmsTinyMCEWidget::m_editor; 813 editor.setContent(newContent); 814 }-*/; 815 816}