/*
* 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 menu for semantic annotation in editor.
* It can call a configured function when the selection changed in inline editor.
* @private
*/
Ext.define('Ametys.plugins.cms.editor.controller.SemanticAnnotationController', {
extend: 'Ametys.cms.editor.EditorButtonController',
createUI: function()
{
var elt = this.callParent(arguments);
elt.on('menushow', this._onMenuShow, this);
return elt;
},
_getMenuPanel: function()
{
var menuPanel = Ext.create("Ametys.ui.fluent.ribbon.controls.gallery.MenuPanel", {
title: "{{i18n CONTENT_EDITION_SEMANTIC_ANNOTATION_MENUGALLERY_GROUP}}",
items: []
});
return this._createGalleryWrapper([menuPanel]);
},
/**
* Listener on 'menushow' event<br>
* @param {Ext.button.Button} btn The button
* @param {Ext.menu.Menu} menu The menu
* @private
*/
_onMenuShow: function(btn, menu)
{
var message = Ametys.message.MessageBus.getCurrentSelectionMessage();
var target = message.getTarget('node');
var node = target != null ? target.getParameters()['object'] : null;
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
var nodesel = tinyMCE.activeEditor.selection.getNode();
var elt = tinyMCE.activeEditor.dom.getParent(nodesel, 'span[annotation]');
var sel = tinyMCE.activeEditor.selection.getContent();
var overlapAnnotation = elt == null && new RegExp("<span[^>]*annotation=").test(sel);
var currentAnnotations = [];
if (overlapAnnotation)
{
var matches = sel.match(/<span[^>]*annotation=\"([^\"]*)\"/g);
if (matches != null)
{
for (var i=0; i < matches.length; i++)
{
currentAnnotations.push(/<span[^>]*annotation=\"([^\"]*)\"/.exec(matches[i])[1]);
}
}
}
else if (elt != null)
{
currentAnnotations.push(elt.getAttribute('annotation'));
}
this._getGalleries(btn).get(0).items.each(function(item) {
var off = !target || !node;
var state = !off;
var disabled = false;
if (!off)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
disabled = (/<p[> \/]|<td[> \/]|<th[> \/]|<li[> \/]|<div[> \/]/.test(sel)) || (sel == '' && !elt) || nodesel != null && tinyMCE.activeEditor.dom.hasClass(nodesel, 'mceNonEditable');
disabled = disabled || overlapAnnotation || (currentAnnotations.length > 0 && !Ext.Array.contains (currentAnnotations, item.annotationName))
state = Ext.Array.contains (currentAnnotations, item.annotationName);
}
item.setDisabled(off || disabled);
item.toggle(state, true);
});
},
/**
* Updates the menu gallery.
* Removes the items of the gallery and add new item form existing semantic annotation of the new focused rich text.
* @param {String} fieldName The field name of focused rich text
* @param {Ametys.form.field.RichText} richtext The focused rich text
*/
updateMenuGallery: function(fieldName, richtext)
{
if (richtext != null && this._currentFieldName != fieldName)
{
this._currentFieldName = fieldName;
var me = this;
this._getGalleries().each(function(menuPanel) {
// Remove old items
menuPanel.removeAll();
// Sort by alphabetical order on label
var annotations = Ext.Array.sort(richtext.getSemanticAnnotations(), function(a1, a2) {
if (a1.label == a2.label)
{
return 0;
}
return (Ext.data.SortTypes.asNonAccentedUCString(a1.label) < Ext.data.SortTypes.asNonAccentedUCString(a2.label)) ? -1 : 1;
});
var gpItems = [];
for (var i=0; i < annotations.length; i++)
{
var element = Ext.create("Ametys.ui.fluent.ribbon.controls.Button", {
text: annotations[i].label,
tooltip: annotations[i].description || annotations[i].label,
icon: Ametys.getPluginResourcesPrefix('cms') + '/img/content/edition/annotations/xml_32.png',
scale: 'large',
controlId: me.getId(),
annotationName: annotations[i].name,
toggleHandler: Ext.bind(me._onItemPress, me),
enableToggle: true,
pressed: false
});
gpItems.push(element);
}
menuPanel.add(gpItems);
});
}
},
/**
* This function is called when an item of the gallery is pressed
* @param {Ametys.ui.fluent.ribbon.controls.Button} button The pressed button
* @param {Boolean} pressed The button state.
* @private
*/
_onItemPress: function(button, pressed)
{
Ametys.plugins.cms.editor.SemanticAnnotation.apply(this, button, pressed);
}
});