package org.gwtbootstrap3.extras.summernote.client.ui.base;
/*
* #%L
* GwtBootstrap3
* %%
* Copyright (C) 2016 GwtBootstrap3
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.gwtbootstrap3.client.ui.html.Div;
import org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteBlurEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteBlurHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteChangeEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteChangeHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteEnterEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteEnterHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteFocusEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteFocusHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteImageUploadEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteImageUploadEvent.ImageFile;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteImageUploadHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteInitEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteInitHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteKeyDownEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteKeyDownHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteKeyUpEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernoteKeyUpHandler;
import org.gwtbootstrap3.extras.summernote.client.event.SummernotePasteEvent;
import org.gwtbootstrap3.extras.summernote.client.event.SummernotePasteHandler;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.ScriptInjector;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.UIObject;
/**
* Wrapper for the Summernote WYSIWYG Editor
* <p/>
* See: http://summernote.org/
*
* @author Xiaodong Sun
*/
public class SummernoteBase extends Div implements HasAllSummernoteHandlers, HasEnabled {
/**
* Language; defaults to {@link SummernoteLanguage#EN_US}
*/
private SummernoteLanguage language = SummernoteLanguage.EN_US;
/**
* Initialize options
*/
private SummernoteOptions options = SummernoteOptions.newOptions();
/**
* Enabled/Disabled state
*/
private boolean enabled = true;
private boolean hasInitHandler = false;
private boolean hasEnterHandler = false;
private boolean hasFocusHandler = false;
private boolean hasBlurHandler = false;
private boolean hasKeyUpHandler = false;
private boolean hasKeyDownHandler = false;
private boolean hasPasteHandler = false;
private boolean hasUploadImageHandler = false;
private boolean hasChangeHandler = false;
/**
*
*/
public SummernoteBase() {}
/**
* Sets the default height of the editor (in pixel).<br>
* <br>
* <b>Note</b>: DO NOT renamed this method to <em>setHeight</em>
* to avoid UiBinder name clash with {@link UIObject#setHeight(String)}.
*
* @param height
*/
public void setDefaultHeight(final int height) {
options.setHeight(height);
}
/**
* Sets the maximum height of the editor (in pixel).
*
* @param maxHeight
*/
public void setMaxHeight(final int maxHeight) {
options.setMaxHeight(maxHeight);
}
/**
* Sets the minimum height of the editor (in pixel).
*
* @param minHeight
*/
public void setMinHeight(final int minHeight) {
options.setMinHeight(minHeight);
}
/**
* If <code>false</code> the toolbar will be hidden.<br>
* <br>
* Defaults to <code>true</code>.
*
* @param showToolbar
*/
public void setShowToolbar(final boolean showToolbar) {
options.setShowToolbar(showToolbar);
}
/**
* Customizes the toolbar.<br>
* <br>
* Example:
* <pre>
* summernote.setToolbar(new Toolbar()
* .addGroup(ToolbarButton.OL, ToolbarButton.BOLD)
* .addGroup(ToolbarButton.HELP));
* </pre>
*
* @param toolbar
*/
public void setToolbar(final Toolbar toolbar) {
options.setToolbar(toolbar);
}
/**
* Set the focus of the editor.
*
* @param focus if <code>true</code>, focus on the editor
*/
public void setHasFocus(final boolean focus) {
options.setFocus(focus);
}
/**
* Set placeholder of the editor.
*
* @param placeholder placeholder of the editor
*/
public void setPlaceholder(final String placeholder) {
options.setPlaceholder(placeholder);
}
/**
* Set customized font names.
*
* @param fontNames customized font names
* @see SummernoteFontName
*/
public void setFontNames(final SummernoteFontName... fontNames) {
JsArrayString array = JavaScriptObject.createArray().cast();
for (SummernoteFontName fontName : fontNames) {
array.push(fontName.getName());
}
options.setFontNames(array);
}
/**
* Set a list for Web fonts to be ignored. <br>
* <br>
* Summernote tests font in fontNames before adding them to drop-down.
* This is problem while using Web fonts. It’s not easy picking up
* nice time to check availabilities of Web fonts.
*
* @param fontNames
*/
public void setFontNamesIgnoreCheck(final SummernoteFontName... fontNames) {
JsArrayString array = JavaScriptObject.createArray().cast();
for (SummernoteFontName fontName : fontNames) {
array.push(fontName.getName());
}
options.setFontNamesIgnoreCheck(array);
}
/**
* Set the air mode of the editor. Air-mode gives clearer interface with
* hidden toolbar. To reveal toolbar, select a text where you want to
* shape up.<br>
* <br>
* Defaults to <code>false</code>.
*
* @param airMode if <code>true</code>, the air mode is turn on
*/
public void setAirMode(final boolean airMode) {
options.setAirMode(airMode);
}
/**
* Set <code>false</code> to disable custom shortcuts.<br>
* <br>
* Defaults to <code>true</code>.
*
* @param shortcuts if <code>false</code>, disable custom shortcuts
*/
public void setShortcuts(final boolean shortcuts) {
options.setShortcuts(shortcuts);
}
/**
* Set <code>true</code> to place dialogs in <body>
* rather than in the editor.<br>
* <br>
* Defaults to <code>false</code>.
*
* @param dialogsInBody if <code>true</code>, place dialogs in <body>
*/
public void setDialogsInBody(final boolean dialogsInBody) {
options.setDialogsInBody(dialogsInBody);
}
/**
* Set <code>true</code> to turn on dialogs fading effect
* when showing or hiding.<br>
* <br>
* Defaults to <code>false</code>.
*
* @param dialogsFade if <code>true</code>, turn on dialogs fading effect
*/
public void setDialogsFade(final boolean dialogsFade) {
options.setDialogsFade(dialogsFade);
}
/**
* Set <code>true</code> to disable drag and drop.<br>
* <br>
* Defaults to <code>false</code>.
*
* @param disableDragAndDrop if <code>true</code>, disable drag and drop
*/
public void setDisableDragAndDrop(final boolean disableDragAndDrop) {
options.setDisableDragAndDrop(disableDragAndDrop);
}
/**
* Summernote support hint (autocomplete) feature. You can define custom hint
* with options.
*
* @param matchRegexp
* @param hintHandler
*/
public void setHint(String matchRegexp, HintHandler hintHandler) {
options.setHint(matchRegexp, hintHandler);
}
/**
* Set the editor language.
*
* @param language supported editor language
*/
public void setLanguage(final SummernoteLanguage language) {
options.setLanguage(language);
this.language = language;
}
/**
* Returns the editor language.
*
* @return
*/
public SummernoteLanguage getLanguage() {
return language;
}
@Override
public HandlerRegistration addSummernoteInitHandler(final SummernoteInitHandler handler) {
hasInitHandler = true;
return addHandler(handler, SummernoteInitEvent.getType());
}
@Override
public HandlerRegistration addSummernoteEnterHandler(final SummernoteEnterHandler handler) {
hasEnterHandler = true;
return addHandler(handler, SummernoteEnterEvent.getType());
}
@Override
public HandlerRegistration addSummernoteFocusHandler(final SummernoteFocusHandler handler) {
hasFocusHandler = true;
return addHandler(handler, SummernoteFocusEvent.getType());
}
@Override
public HandlerRegistration addSummernoteBlurHandler(final SummernoteBlurHandler handler) {
hasBlurHandler = true;
return addHandler(handler, SummernoteBlurEvent.getType());
}
@Override
public HandlerRegistration addSummernoteKeyUpHandler(final SummernoteKeyUpHandler handler) {
hasKeyUpHandler = true;
return addHandler(handler, SummernoteKeyUpEvent.getType());
}
@Override
public HandlerRegistration addSummernoteKeyDownHandler(final SummernoteKeyDownHandler handler) {
hasKeyDownHandler = true;
return addHandler(handler, SummernoteKeyDownEvent.getType());
}
@Override
public HandlerRegistration addSummernotePasteHandler(final SummernotePasteHandler handler) {
hasPasteHandler = true;
return addHandler(handler, SummernotePasteEvent.getType());
}
@Override
public HandlerRegistration addSummernoteImageUploadHandler(final SummernoteImageUploadHandler handler) {
hasUploadImageHandler = true;
return addHandler(handler, SummernoteImageUploadEvent.getType());
}
@Override
public HandlerRegistration addSummernoteChangeHandler(final SummernoteChangeHandler handler) {
hasChangeHandler = true;
return addHandler(handler, SummernoteChangeEvent.getType());
}
/**
* Gets the HTML code generated from the editor
*
* @return generated code
*/
public String getCode() {
if (isAttached()) {
return getCode(getElement());
}
return getElement().getInnerHTML();
}
/**
* Sets the given HTML code to the editor.
*
* @param code
*/
public void setCode(final String code) {
if (isAttached()) {
setCode(getElement(), code);
} else {
getElement().setInnerHTML(code);
}
}
/**
* Returns <code>true</code> if the content is empty.<br>
* <br>
* Editing area needs <code><p><br></p></code></code>
* for focus, even if contents is empty. So summernote supports this method
* for helping to check contents is empty.
*
* @return <code>true</code> if the editor is empty
*/
public boolean isEmpty() {
if (isAttached()) {
return isEmpty(getElement());
}
return getElement().getInnerHTML().isEmpty();
}
/**
* Removes all contents and restores the editable instance
* to an <code>_emptyPara_</code>: <p><br></p>
*/
@Override
public void clear() {
if (isAttached()) {
command(getElement(), "empty");
} else {
super.clear();
getElement().removeAllChildren();
}
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
if (isAttached()) {
command(getElement(), enabled ? "enable" : "disable");
}
}
@Override
public boolean isEnabled() {
return enabled;
}
/**
* Clear editor contents and remove all stored history.
*/
public void reset() {
if (isAttached()) {
command(getElement(), "reset");
} else {
clear();
}
}
/**
* Call this when updating options to ensure everything is up to date
*/
public void reconfigure() {
destroy(getElement());
initialize();
}
private void initialize() {
// Inject the language JS is necessary
if (language.getJs() != null) {
ScriptInjector.fromString(language.getJs().getText())
.setWindow(ScriptInjector.TOP_WINDOW).inject();
}
// Initialize
initialize(getElement(), options);
// Enable/Disable editor
setEnabled(enabled);
}
@Override
protected void onLoad() {
super.onLoad();
// Initialize
initialize();
}
@Override
protected void onUnload() {
super.onUnload();
// Destroy
destroy(getElement());
}
/**
* Inserts the given images to the editor.<br>
* <br>
* This method should be used only when you customize
* the image upload handler.
*
* @param images
*/
public void insertImages(JsArray<ImageFile> images) {
insertImages(getElement(), images);
}
private native void initialize(Element e, SummernoteOptions options) /*-{
var target = this;
options.callbacks = {};
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasInitHandler) {
options.callbacks.onInit = function() {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteInitEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteInitHandlers;)(target);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasEnterHandler) {
options.callbacks.onEnter = function () {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteEnterEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteEnterHandlers;)(target);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasFocusHandler) {
options.callbacks.onFocus = function() {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteFocusEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteFocusHandlers;)(target);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasBlurHandler) {
options.callbacks.onBlur = function() {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteBlurEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteBlurHandlers;)(target);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasKeyUpHandler) {
options.callbacks.onKeyup = function(e) {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteKeyUpEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteKeyUpHandlers;Lcom/google/gwt/dom/client/NativeEvent;)(target, e.originalEvent);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasKeyDownHandler) {
options.callbacks.onKeydown = function(e) {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteKeyDownEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteKeyDownHandlers;Lcom/google/gwt/dom/client/NativeEvent;)(target, e.originalEvent);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasUploadImageHandler) {
options.callbacks.onImageUpload = function(files) {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteImageUploadEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteImageUploadHandlers;Lcom/google/gwt/core/client/JsArray;)(target, files);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasPasteHandler) {
options.callbacks.onPaste = function() {
@org.gwtbootstrap3.extras.summernote.client.event.SummernotePasteEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernotePasteHandlers;)(target);
};
}
if (this.@org.gwtbootstrap3.extras.summernote.client.ui.base.SummernoteBase::hasChangeHandler) {
options.callbacks.onChange = function() {
@org.gwtbootstrap3.extras.summernote.client.event.SummernoteChangeEvent::fire(Lorg/gwtbootstrap3/extras/summernote/client/event/HasSummernoteChangeHandlers;)(target);
};
}
$wnd.jQuery(e).summernote(options);
}-*/;
private native void destroy(Element e) /*-{
$wnd.jQuery(e).summernote('destroy');
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_INIT_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_ENTER_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_FOCUS_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_BLUR_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_KEYUP_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_KEYDOWN_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_PASTE_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_IMAGE_UPLOAD_EVENT);
$wnd.jQuery(e).off(@org.gwtbootstrap3.extras.summernote.client.event.HasAllSummernoteHandlers::SUMMERNOTE_CHANGE_EVENT);
}-*/;
private native void setCode(Element e, String code) /*-{
$wnd.jQuery(e).summernote('code', code);
}-*/;
private native String getCode(Element e)/*-{
return $wnd.jQuery(e).summernote('code');
}-*/;
private native boolean isEmpty(Element e)/*-{
return $wnd.jQuery(e).summernote('isEmpty');
}-*/;
private native void command(Element e, String command)/*-{
$wnd.jQuery(e).summernote(command);
}-*/;
private native void insertImages(Element e, JsArray<ImageFile> images) /*-{
$wnd.jQuery(e).summernote('insertImages', images);
}-*/;
}