/*
* Copyright 2013 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.
*/
/**
* This class controls a ribbon button for edition only.
* It can call a configured function when the selection changed in inline editor.
*/
Ext.define('Ametys.cms.editor.EditorFieldController', {
extend: 'Ametys.ribbon.element.ui.FieldController',
/**
* @cfg {String} selection-target-id Not supported
* @private
*/
/**
* @cfg {String} selection-subtarget-id Not supported
* @private
*/
/**
* @cfg {String} selection-subsubtarget-id Not supported
* @private
*/
/**
* @cfg {String} selection-subsubsubtarget-id Not supported
* @private
*/
/**
* @cfg {String} selection-listener The function name to call when the selection has changed.
*/
/**
* @property {String} _selectionListener See #cfg-selection-listener.
* @private
*/
/**
* @cfg {String} selection-node-type Specify this configuration to obtain a button that enable/disable depending on the type of current HTML node in edition mode. The string is a CSS selector which go from the current selection up to the required element: so it can be the tag name of the HTML element that have to match the current selection. A leading '!' will reverse the condition.
*/
/**
* @cfg {String} selection-node-attribute Specify this configuration to obtain a button that enable/disable depending on the current HTML node attributes. The string is list of regexp separated by ';' that have to match the attributes of current HTML element. A leading '!' will reverse the regexp condition.
*/
/**
* @property {String} _selectionNodeType See #cfg-selection-node-type.
* @private
*/
/**
* @property {Boolean} _reversedSelectionNodeType See #cfg-selection-node-type.
* @private
*/
/**
* @property {String[]} _selectionNodeAttributes See #cfg-selection-node-attribute. The leading '!' is transmitted to {@link #_reversedSelectionNodeAttributes}
* @private
*/
/**
* @property {String[]} _reversedSelectionNodeAttributes The leading '!' from {@link #cfg-selection-node-attribute} converted to true.
* @private
*/
/**
* @property {String} _currentField The current selected field.
* @private
*/
/**
* @property {String} _currentNode The current selected node.
* @private
*/
constructor: function (config)
{
this.callParent(arguments);
this._selectionListener = this.getInitialConfig('selection-listener');
this._selectionNodeType = null;
this._reversedSelectionNodeType = false;
this._selectionNodeAttributes = [];
this._reversedSelectionNodeAttributes = [];
this._currentField = null;
this._currentNode = null;
var nodeType = this.getInitialConfig("selection-node-type") || this.getInitialConfig("node-type");
if (nodeType)
{
var i = nodeType.indexOf('!');
if (i == 0)
{
this._selectionNodeType = nodeType.substring(1);
this._reversedSelectionNodeType = true;
}
else
{
this._selectionNodeType = nodeType;
}
var attributes = this.getInitialConfig('selection-node-attribute') || this.getInitialConfig('attribute');
var attributesAsArray = attributes != null ? attributes.split(";") : [];
for (var j=0; j < attributesAsArray.length; j++)
{
var attribute = attributesAsArray[j];
var i = attribute.indexOf('!');
if (i == 0)
{
this._reversedSelectionNodeAttributes.push(attribute.substring(1));
}
else
{
this._selectionNodeAttributes.push(attribute);
}
}
}
Ametys.message.MessageBus.on(Ametys.message.Message.SELECTION_CHANGED, this._onSelectionChanged, this);
},
_onSelectionChanged: function(message)
{
var me = this;
function getMatchingParentNode(editor, node)
{
if (me._reversedSelectionNodeType)
{
var n = node;
while (n != null)
{
if (editor.dom.is(n, me._selectionNodeType))
{
return null;
}
else
{
n = n.parentNode;
}
}
return node;
}
else
{
return editor.dom.getParent(node, me._selectionNodeType);
}
}
message = message || Ametys.message.MessageBus.getCurrentSelectionMessage();
this._currentField = null;
this._currentNode = null;
var targets = message.getTargets();
var formTarget = message.getTarget('form');
var fieldTarget = message.getTarget('field');
if (formTarget != null && fieldTarget != null && formTarget.getParameters().object != null && !formTarget.getParameters().object.destroyed && fieldTarget.getParameters().name != null)
{
this._currentField = formTarget.getParameters().object.findField(fieldTarget.getParameters().name);
}
var editor = this._currentField && typeof this._currentField.getEditor == "function" ? this._currentField.getEditor() : null;
var nodeTarget = message.getTarget('node');
this._currentNode = nodeTarget != null && editor != null && editor.dom != null ? getMatchingParentNode(editor, nodeTarget.getParameters()['object']) : null;
var enable = this._currentNode != null;
while (this._currentNode != null)
{
for (var j=0; j < this._selectionNodeAttributes.length; j++)
{
if (this._currentNode.getAttribute(this._selectionNodeAttributes[j]) == null)
{
enable = false;
}
}
for (var j=0; j < this._reversedSelectionNodeAttributes.length; j++)
{
if (this._currentNode.getAttribute(this._reversedSelectionNodeAttributes[j]) != null)
{
enable = false;
}
}
if (enable)
{
break;
}
this._currentNode = getMatchingParentNode(editor, this._currentNode.parentNode);
}
this.setDisabled(!enable);
this._updateAdditionalDescription(targets, this._currentNode != null);
if (this._selectionListener)
{
Ametys.executeFunctionByName (this._selectionListener, null, null, this, this._currentField, this._currentNode);
}
},
/**
* Update the additional description.
* @param {Ametys.message.MessageTarget[]} targets The list of message targets
* @param {boolean} match True if the current selection matches the button configuration
* @private
*/
_updateAdditionalDescription: function (targets, match)
{
if (targets.length === 0)
{
this.setAdditionalDescription(this.getInitialConfig("selection-description-empty") || this.getInitialConfig("no-selection-description"));
}
else if (!match)
{
this.setAdditionalDescription(this.getInitialConfig("selection-description-nomatch"));
}
else
{
this.setAdditionalDescription("");
}
},
/**
* Retrieve the currently selected field
* @return {Ametys.cms.form.widget.RichText} The current field
*/
getCurrentField: function ()
{
return this._currentField;
},
/**
* Retrieve the currently selected node
* @return {HTMLElement} The current node
*/
getCurrentNode: function ()
{
return this._currentNode;
}
});