/*
* Copyright 2017 Anyware Services
*
* 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.
*/
/**
* Singleton to manage the 'edition.richtext' widget for the FormEditionPanel.
* Allow to add CSS files, supported tags and common listeners.
*/
Ext.define('Ametys.form.widget.RichText.RichTextConfiguration', {
extend: 'Ext.util.Observable',
singleton: true,
/**
* @property {Object} _validators A map of cagtegory / list of registered validator. "" is the default category
* @property {Function[]} _validators.key List of registered validator #addValidator used in #validates for a category
* @private
*/
_validators: {},
/**
* @property {Object} __convertorsOnGetContent A map of category / list of registered convertors. "" is the default category.
* @property {Function[]} __convertorsOnGetContent.key List of registered convertors #addConvertors used in #convertOnGetContent for a category
* @private
*/
_convertorsOnGetContent: {},
/**
* @property {Object} __convertorsOnSetContent A map of category / list of registered convertors. "" is the default category
* @property {Function[]} __convertorsOnSetContent.key List of registered convertors #addConvertors used in #convertOnSetContent for a category
* @private
*/
_convertorsOnSetContent: {},
/**
* @event setcontent
* Fires when the editor received new content. This allows to convert storing tags to internal tags. Use object.content to get/set the full html. See Ametys.form.field.RichText#event-setcontent for parameters.
*/
/**
* @event getcontent
* Fires when the editor received content. This allows to convert internal tags to storing tags. Use object.content to get/set the full html. See Ametys.form.field.RichText#event-getcontent for parameters.
*/
/**
* @event keypress
* Fires when the editor has a key press. See Ametys.form.field.RichText#event-keypress for parameters.
*/
/**
* @event keydown
* Fires when the editor has a key down. See Ametys.form.field.RichText#event-keydown for parameters.
*/
/**
* @event keyup
* Fires when the editor has a key up. See Ametys.form.field.RichText#event-keydown for parameters.
*/
/**
* @event visualaid
* Fires when the editor pre process the serialization. See Ametys.form.field.RichText#event-visualaid for parameters.
*/
/**
* @event preprocess
* Fires when the editor pre process the serialization. See Ametys.form.field.RichText#event-preprocess for parameters.
*/
/**
* @event htmlnodeselected
* Fires when a HTML node is selected in editor. See Ametys.form.field.RichText#event-htmlnodeselected for parameters.
*/
constructor: function()
{
this.callParent(arguments);
var me = this;
Ametys.data.ServerComm.callMethod({
role: "org.ametys.core.ui.widgets.richtext.RichTextConfigurationExtensionPoint",
methodName: "toJSON",
parameters: [ Ametys.getAppParameters() ],
callback: {
handler: function(json) { RichTextConfigurationBase.setConfigurationFromServer(json, me); }
},
errorMessage: true
});
},
/**
* Validates the value among the existing validators for the inline editor
* @param {String} value The current field value
* @param {String} [category=""] The category to validates
* @return {Boolean/String} validator.return
*
* - True if the value is valid
* - An error message if the value is invalid
*/
validates: function(value, category)
{
return RichTextConfigurationBase.validates(value, category);
},
/**
* Get all added css files as one string
* @param {String} [category=""] The category to apply.
* @return {String} The comma-separated list of added files
*/
getCSSFiles: function(category)
{
return RichTextConfigurationBase.getCSSFiles(category);
},
/**
* Get all supported tags as a tinymce string. See valid_element tinymce configuration doc for the exact format.
* @param {String} [category=""] The category to apply.
* @return {String} The supported tags.
*/
getTags: function(category)
{
return RichTextConfigurationBase.getTags(category);
},
/**
* Get all supported styles as a tinymce conf object. See valid_styles tinymce configuration doc for the exact format.
* @param {String} [category=""] The category to apply.
* @return {Object} The supported properties for the style attribute.
*/
getStylesForTags: function(category)
{
return RichTextConfigurationBase.getStylesForTags(category);
},
/**
* Get all supported classes as a tinymce conf object. See valid_classes tinymce configuration doc for the exact format.
* @param {String} [category=""] The category to apply.
* @return {Object} The supported properties for the style attribute.
*/
getClassesForTags: function(category)
{
return RichTextConfigurationBase.getClassesForTags(category);
},
/**
* Get tag informations.
* @param {String} tagName The name of the tag to handle in the configuration
* @param {String} [category=""] The category of configuration where to handle
* @return {Object} See #handleTag to know more
*/
getTag: function(tagName, category)
{
return RichTextConfigurationBase.getTag(tagName, category);
},
/**
* Get styles informations of a type.
* @param {String} type The type of element to style. Such as "paragraph", "table", "link", "image", "ol", "ul"...
* @param {String} [category=""] The category of configuration where to handle
* @return {Object[]} The styles available by group. See #handleStyledGroup return value. Can be null or empty.
*/
getStyledElements: function(type, category)
{
return RichTextConfigurationBase.getStyledElements(type, category);
},
/**
* Handle validators
* @param {Object} validators The validators to handle.
*/
handleValidators: function(validators, category)
{
var me = this;
Ext.Array.forEach(validators, function(validator) {
var validatorInstance = Ext.create(validator['class'].name, validator['class'].parameters);
me.addValidator(Ext.bind(validatorInstance.validates, validatorInstance), category);
});
},
/**
* Handle convertors
* @param {Object} convertors The convertor to handle.
*/
handleConvertors: function(convertors, category)
{
var me = this;
Ext.Array.forEach(convertors, function(convertor) {
var convertorInstance = Ext.create(convertor['class'].name, convertor['class'].parameters);
me.addConvertor(convertorInstance.onGetContent ? Ext.bind(convertorInstance.onGetContent, convertorInstance) : null, convertorInstance.onSetContent ? Ext.bind(convertorInstance.onSetContent, convertorInstance) : null, category);
});
},
/**
* @private
* Add a custom validation function to be called during inline editor validation ({@link Ext.form.field.Field#getErrors}).
* @param {Function} validator The new validator to add. This function will have the following signature:
* @param {Object} validator.value The current field value
* @param {Boolean/String} validator.return
* - True if the value is valid
* - An error message if the value is invalid
* @param {String} [category=""] The category where to register.
*/
addValidator: function(validator, category)
{
category = category || "";
this._validators[category] = this._validators[category] || [];
this._validators[category].push(validator);
},
/**
* Validates the value among the existing validators for the inline editor
* @param {String} value The current field value
* @param {String} [category=""] The category to validates
* @return {Boolean/String} validator.return
*
* - True if the value is valid
* - An error message if the value is invalid
*/
validates: function(value, category)
{
this.checkIfInitialized();
category = category || "";
var returnValues = "";
Ext.each(this._validators[category] || [], function (validator) {
var returnValue = validator.apply(null, [value]);
if (returnValue !== true)
{
returnValues += returnValue + "\n";
}
});
return returnValues.length == 0 ? true : returnValues.substring(0, returnValues.length - 1);
},
/**
* @private
* Add a custom convertor function to be called during inline editor conversion process getValue/setValue.
* @param {Function} onGetContent The new function to add that will be called on getValue to convert the internal richtext structure to the external value
* @param {Ametys.form.field.RichText} onGetContent.field The current richtext field
* @param {tinymce.Editor} onGetContent.editor The current richtext editor
* @param {Object} onGetContent.object The object of value to be modified
* @param {Function} onSetContent The new function to add that will be called on setValue to convert the external value to the internal richtext structure
* @param {tinymce.Editor} onSetContent.editor The current richtext editor
* @param {Object} onSetContent.object The object of value to be modified
* @param {String} [category=""] The category where to register.
*/
addConvertor: function(onGetContent, onSetContent, category)
{
category = category || "";
if (onGetContent)
{
this._convertorsOnGetContent[category] = this._convertorsOnGetContent[category] || [];
this._convertorsOnGetContent[category].push(onGetContent);
}
if (onSetContent)
{
this._convertorsOnSetContent[category] = this._convertorsOnSetContent[category] || [];
this._convertorsOnSetContent[category].push(onSetContent);
}
},
/**
* Converts the value on get content
* @param {Ametys.form.field.RichText} field The richtext to convert
* @param {tinymce.Editor} editor The current richtext editor
* @param {Object} object The object of value to be modified
* @param {String} [category=""] The category to apply.
*/
convertOnGetContent: function(field, editor, object, category)
{
this.checkIfInitialized();
category = category || "";
Ext.Array.each(this._convertorsOnGetContent[category] || [], function (convertorOnGetContent) {
convertorOnGetContent.apply(null, [field, editor, object]);
});
this.fireEvent('getcontent', field, editor, object);
},
/**
* Converts the value on set content
* @param {Ametys.form.field.RichText} field The richtext to convert
* @param {tinymce.Editor} editor The current richtext editor
* @param {Object} object The object of value to be modified
* @param {String} [category=""] The category to apply.
*/
convertOnSetContent: function(field, editor, object, category)
{
this.checkIfInitialized();
category = category || "";
Ext.Array.each(this._convertorsOnSetContent[category] || [], function (convertorOnSetContent) {
convertorOnSetContent.apply(null, [field, editor, object]);
});
this.fireEvent('setcontent', field, editor, object);
},
/**
* @private
* Check if RichTextConfiguration is initialized and throw an exception otherwise
*/
checkIfInitialized: function()
{
RichTextConfigurationBase.checkIfInitialized();
},
/**
* Get language code.
* @return {String} language code.
*/
getLanguageCode: function()
{
return Ametys.LANGUAGE_CODE;
},
/**
* Get debug mode.
* @return {Boolean} debug mode.
*/
getDebugMode: function()
{
return Ametys.DEBUG_MODE;
},
/**
* Get Rtl mode.
* @return {Boolean} Rtl mode.
*/
getRtlMode: function()
{
return Ametys.RTL_MODE;
},
/**
* Get context path.
* @return {String} context path.
*/
getContextPath: function()
{
return Ametys.CONTEXT_PATH;
},
});