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