/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.gui.components.form.flexible.impl.elements.richText;
import java.util.Locale;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
import org.olat.core.gui.components.form.flexible.impl.Form;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.elements.AbstractTextElement;
import org.olat.core.gui.control.Disposable;
import org.olat.core.helpers.Settings;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.filter.Filter;
import org.olat.core.util.filter.FilterFactory;
/**
*
* Description:<br>
* This class implements a rich text form element based on the TinyMCE
* javascript library.
*
* <P>
* Initial Date: 21.04.2009 <br>
*
* @author gnaegi
*/
public class RichTextElementImpl extends AbstractTextElement implements
RichTextElement, Disposable {
private static final OLog log = Tracing.createLoggerFor(RichTextElementImpl.class);
private final RichTextElementComponent component;
private RichTextConfiguration configuration;
/**
* Constructor for specialized TextElements, i.e. IntegerElementImpl.
*
* @param name
* @param predefinedValue
* Initial value
* @param rows
* the number of lines or -1 to use default value (resizeable)
* @param cols
* the number of characters per line or -1 to use 100% of the
* available space
* @param form The dispatch ID of the root form that deals with the submit button
* @param windowBackOffice The window back office used to properly cleanup code in browser window
*/
public RichTextElementImpl(String name, String predefinedValue, int rows, int cols, Form form, Locale locale) {
this(name, rows, cols, form, locale);
setValue(predefinedValue);
}
/**
* Constructor for specialized TextElements, i.e. IntegerElementImpl.
*
* @param name
* @param rows
* the number of lines or -1 to use default value (resizeable)
* @param cols
* the number of characters per line or -1 to use 100% of the
* available space
* @param form The dispatch ID of the root form that deals with the submit button
* @param windowBackOffice The window back office used to properly cleanup code in browser window
*/
protected RichTextElementImpl(String name, int rows, int cols, Form rootForm, Locale locale) {
super(name);
// initialize the component
component = new RichTextElementComponent(this, rows, cols);
// configure tiny (must be after component initialization)
// init editor on our form element
configuration = new RichTextConfiguration(getFormDispatchId(), rootForm.getDispatchFieldId(), locale);
}
@Override
public String getForId() {
return isEnabled() ? super.getForId() : null;
}
/**
* @see org.olat.core.gui.components.form.flexible.impl.elements.AbstractTextElement#getValue()
* The returned value is XSS save and
* does not contain executable JavaScript code. If you want to get the raw
* user data use the getRawValue() method.
*/
@Override
public String getValue() {
String val = getRawValue();
Filter xssFilter = FilterFactory.getXSSFilter(val.length() + 1);
return xssFilter.filter(val);
}
@Override
public String getValue(Filter filter) {
String val = getRawValue();
return filter.filter(val);
}
@Override
public void setDomReplacementWrapperRequired(boolean required) {
component.setDomReplacementWrapperRequired(required);
}
/**
* This apply a filter to remove some buggy conditional comment
* of Word
*
* @see org.olat.core.gui.components.form.flexible.elements.RichTextElement#getRawValue()
*/
@Override
public String getRawValue() {
if(value != null) {
value = value.replace("<!--[endif] -->", "<![endif]-->");
}
return value;
}
/**
* @see org.olat.core.gui.components.form.flexible.FormItemImpl#evalFormRequest(org.olat.core.gui.UserRequest)
*/
@Override
public void evalFormRequest(UserRequest ureq) {
String paramId = component.getFormDispatchId();
String cmd = getRootForm().getRequestParameter("cmd");
String submitValue = getRootForm().getRequestParameter(paramId);
if("saveinlinedtiny".equals(cmd)) {
if(submitValue != null) {
setValue(submitValue);
getRootForm().fireFormEvent(ureq, new FormEvent(cmd, this, FormEvent.ONCLICK));
}
} else if (submitValue != null) {
setValue(submitValue);
// don't re-render component, value in GUI already correct
component.setDirty(false);
} else if(cmd != null) {
getRootForm().fireFormEvent(ureq, new FormEvent(cmd, this, FormEvent.ONCLICK));
component.setDirty(false);
}
}
/**
* @see org.olat.core.gui.components.form.flexible.elements.RichTextElement#getRichTextConfiguration()
*/
@Override
public RichTextConfiguration getEditorConfiguration() {
return configuration;
}
/**
* @see org.olat.core.gui.components.form.flexible.impl.FormItemImpl#getFormItemComponent()
*/
@Override
protected Component getFormItemComponent() {
return component;
}
/**
* @see org.olat.core.gui.control.Disposable#dispose()
*/
@Override
public void dispose() {
// cleanup stuff in the configuration (base url maper)
if (configuration != null) {
configuration.dispose();
configuration = null;
}
}
@Override
public void setNewOriginalValue(String value) {
if (value == null) value = "";
original = new String(value);
originalInitialised = true;
//the check is made on the raw values instead of the getValue()
if (getRawValue() != null && !getRawValue().equals(value)) {
getComponent().setDirty(true);
}
}
/**
* DO NOT USE THE ONCHANGE EVENT with TEXTAREAS!
* @see org.olat.core.gui.components.form.flexible.impl.FormItemImpl#addActionListener(org.olat.core.gui.control.Controller, int)
*/
@Override
public void addActionListener(int actionType) {
super.addActionListener(actionType);
if (action == FormEvent.ONCHANGE && Settings.isDebuging()) {
log.warn("Do not use the onChange event in Textfields / TextAreas as this has often unwanted side effects. " +
"As the onchange event is only tiggered when you click outside a field or navigate with the tab to the next element " +
"it will suppress the first attempt to the submit click as by clicking " +
"the submit button first the onchange event will be triggered and you have to click twice to submit the data. ");
}
}
}