/*
* 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 stands for the logic of a tab of the ribbon for richtext edition that handle show/hide:
* * depending of the current selection
* * depending of the currently focused tool
* * depending on the editor current selection #selection-node-type and #selection-node-attribute
* Default selection detection is:
* * any main target
* * with a 'form' subtarget
* * with a 'field' subsubtarget
* * with a 'node' subsubsubtarget
*/
Ext.define(
"Ametys.ribbon.element.tab.EditionTabController",
{
extend: "Ametys.ribbon.element.tab.TabController",
/**
* @cfg {String} [selection-target-id="^.*$"] The default value is to accept any target type
* @inheritdoc
*/
/**
* @cfg {String} [selection-subtarget-id="^form$"] The default value is to accept any target type
* @inheritdoc
*/
/**
* @cfg {String} [selection-subsubtarget-id="^field$"] The default value is to accept any target type
* @inheritdoc
*/
/**
* @cfg {String} [selection-subsubsubtarget-id="^node$"] The default value is to accept any target type
* @inheritdoc
*/
/**
* @cfg {String} selection-node-type Specify this configuration to obtain a tab that show/hide 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.
*/
/**
* @cfg {String} selection-node-attribute Specify this configuration to obtain a tab that show/hide 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 {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
*/
constructor: function(config)
{
config = Ext.applyIf({
"selection-target-id": "^.*$",
"selection-subtarget-id": "^form$",
"selection-subsubtarget-id": "^field$",
"selection-subsubsubtarget-id": "^node$"
}, config);
this.callParent(arguments);
var nodeType = this.getInitialConfig("selection-node-type") || this.getInitialConfig("node-type");
if (nodeType)
{
this._selectionNodeType = nodeType;
this._selectionNodeAttributes = [];
this._reversedSelectionNodeAttributes = [];
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);
}
}
}
},
_onSelectionChanged: function(message)
{
message = message || Ametys.message.MessageBus.getCurrentSelectionMessage();
if (this._toolFocused === false)
{
// this tab works only with a tool #cfg-tool-id; when the tool is not focused selection message need to be ignored
return;
}
var noSelection = message.getTargets().length == 0;
this._matchingTargets = this._getMatchingSelectionTargets(message);
if (this._selection)
{
if (noSelection || this._matchingTargets.length == 0 || tinyMCE.activeEditor == null || tinyMCE.activeEditor.dom == null)
{
this.hide();
}
else
{
for (var i=0; i < this._matchingTargets.length; i++)
{
var show = true;
var nodeTarget = this._matchingTargets[i].getSubtarget('node');
var node = tinyMCE.activeEditor.dom.getParent(this._getNode(nodeTarget.getParameters()['object']), this._selectionNodeType);
while (node != null)
{
for (var j=0; j < this._selectionNodeAttributes.length; j++)
{
if (node.getAttribute(this._selectionNodeAttributes[j]) == null)
{
show = false;
}
}
for (var j=0; j < this._reversedSelectionNodeAttributes.length; j++)
{
if (node.getAttribute(this._reversedSelectionNodeAttributes[j]) != null)
{
show = false;
}
}
if (show)
{
var shouldForce = node.getAttribute("_mce_ribbon_select") == "1";
this.show(shouldForce ? shouldForce : null);
if (shouldForce)
{
// Disarm the force flag, defer it so other tabs will also receive the flag.
var removeFlag = Ext.defer(tinyMCE.activeEditor.dom.setAttrib, 1, tinyMCE.activeEditor.dom, [node, "_mce_ribbon_select", '']);
}
return;
}
node = tinyMCE.activeEditor.dom.getParent(node.parentNode, this._selectionNodeType);
}
}
this.hide();
}
}
},
/**
* @protected
* Get the node to work with in order to process the new selection
* @param {HTMLElement} node the selected element
* @return {HTMLElement} the element used to process the selection
*/
_getNode: function(node)
{
return node;
}
}
);