/*
* 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.
*/
/**
* Class to handle link insertion in inline editor
* @private
*/
Ext.define('Ametys.plugins.cms.editor.Links', {
singleton: true,
/**
* @private
* @type {Boolean} true to allow drag and drop in attachments and resources tree
*/
_allowDragAndDrop: true,
/**
* @property {Object[]} The registered handlers
*/
handlers: [],
/**
* Add a link handler for a type of link
* @param {String} type The type of the link (mail, resource, ...) concerned by this handler. Can be null for default type.
* @param {Ametys.cms.editor.LinkHandler} handler The handler link handler
*/
addLinkHandler: function (type, handler)
{
this.handlers[type] = handler;
},
/**
* Get the link handler associated with the type
* @param {String} type The type of link (mail, resource, ...). Can be null to get the default handler.
* @return {Ametys.cms.editor.LinkHandler} The link handler
*/
getLinkHandler: function (type)
{
return this.handlers[type];
},
/**
* Register "a" as a valid tag
*/
initialize: function ()
{
this.addLinkHandler (null, Ext.create('Ametys.plugins.cms.editor.Links.WebLinkHandler', {}));
},
/**
* Remove a link
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
remove: function(controller)
{
var editor = controller.getCurrentField().getEditor();
editor.execCommand('mceBeginUndoLevel');
editor.execCommand('UnLink');
editor.execCommand('mceEndUndoLevel');
},
//------------------------------------------------------//
// WEB LINK //
//------------------------------------------------------//
/**
* Insert a web external link
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
insertWebLink: function(controller)
{
var currentUrl = "";
var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
if (node != null && (node.getAttribute("data-ametys-type") == null || node.getAttribute("data-ametys-type") == ""))
{
currentUrl = node.getAttribute("href");
}
this._doInsertWebLink (currentUrl == '' ? 'http://' : '');
},
/**
* Open dialog to enter the external link url
* @param {String} currentUrl The default URL value
* @private
*/
_doInsertWebLink: function (currentUrl)
{
Ametys.helper.EnterURL.open({
iconCls: "ametysicon-link23",
title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_LINK}}",
helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_URL_DESC}}",
footermessage: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_HINT}}",
callback: this._insertWebLinkCb,
defaultValue: currentUrl
});
},
/**
* Callback function called when user has entered the link URL. Inserts the link to the cursor position
* @param {String} url The entered URL
* @private
*/
_insertWebLinkCb: function(url)
{
if (url != null)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
{
tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + url + "{$caret}</a> ");
node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
tinyMCE.activeEditor.selection.select(node);
}
tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": url, "href": url, "class": "external", "target": "_blank", "data-ametys-type": "", "_mce_ribbon_select": "1" });
tinyMCE.activeEditor.selection.collapse();
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
}
// Delayed to wait for the dialog box to hide.
window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
},
//------------------------------------------------------//
// MAIL LINK //
//------------------------------------------------------//
/**
* Initialize function to add a link handler for mail
*/
initializeMailLink: function (controller)
{
this.addLinkHandler ('mail', Ext.create('Ametys.plugins.cms.editor.Links.MailLinkHandler', {}));
},
/**
* Insert a link of type 'mailto'
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
insertMailtoLink: function (controller)
{
var editor = controller.getCurrentField().getEditor();
this._insertMailtoLink(editor);
},
/**
* @private
* Insert a link of type 'mailto'
* @param {tinymce.Editor} editor The tinymce active editor
*/
_insertMailtoLink: function(editor)
{
var currentUrl = "";
var node = editor.dom.getParent(editor.selection.getNode(), 'a');
if (node != null && (node.getAttribute("data-ametys-type") == "mail"))
{
currentUrl = node.getAttribute("href");
}
this._doInsertMailtoLink(currentUrl);
},
/**
* Open dialog to enter the mail address
* @param {String} currentUrl The default mail
* @private
*/
_doInsertMailtoLink: function(currentUrl)
{
currentUrl = currentUrl || '';
if (currentUrl.indexOf('mailto:') == 0)
{
currentUrl = currentUrl.substring('mailto:'.length);
}
Ametys.helper.EnterURL.open({
iconCls: "ametysicon-dark4",
title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_MAILTO}}",
helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_MAILTO_DESC}}",
footermessage: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_EMAIL_HINT}}",
callback: this._insertMailtoLinkCb,
defaultValue: currentUrl,
regex: '^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9][A-Za-z0-9]+)+$',
regexText: "{{i18n CONTENT_EDITION_LINK_INSERT_MAILTO_INVALID_EMAIL}}"
});
},
/**
* Callback function called when user has entered mailto link. Inserts the link to the cursor position.
* @param {String} email The entered email
* @private
*/
_insertMailtoLinkCb: function(email)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.focus();
if (email != null)
{
var url = 'mailto:' + email;
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
{
tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + email + "{$caret}</a> ");
node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
tinyMCE.activeEditor.selection.select(node);
}
tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": url, "href": url, "class": "mailto", "data-ametys-type": "mail", "_mce_ribbon_select": "1" });
tinyMCE.activeEditor.selection.collapse();
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
}
// Delayed to wait for the dialog box to hide.
window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
},
//------------------------------------------------------//
// PHONE LINK //
//------------------------------------------------------//
/**
* Initialize function to add a link handler for phone
*/
initializePhoneLink: function (controller)
{
this.addLinkHandler ('phone', Ext.create('Ametys.plugins.cms.editor.Links.PhoneLinkHandler', {}));
},
/**
* Insert a link of type 'tel'
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
insertPhoneLink: function (controller)
{
var editor = controller.getCurrentField().getEditor();
this._insertPhoneLink(editor);
},
/**
* @private
* Insert a link of type 'tel'
* @param {tinymce.Editor} editor The tinymce active editor
*/
_insertPhoneLink: function(editor)
{
var currentUrl = "";
var node = editor.dom.getParent(editor.selection.getNode(), 'a');
if (node != null && (node.getAttribute("data-ametys-type") == "phone"))
{
currentUrl = node.getAttribute("href");
}
this._doInsertPhoneLink(currentUrl);
},
/**
* Open dialog to enter the phone number
* @param {String} currentUrl The default number
* @private
*/
_doInsertPhoneLink: function(currentUrl)
{
currentUrl = currentUrl || '';
if (currentUrl.indexOf('tel:') == 0)
{
currentUrl = currentUrl.substring('tel:'.length);
}
Ametys.helper.EnterURL.open({
iconCls: "ametysicon-phone",
title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_PHONE}}",
helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_PHONE_DESC}}",
footermessage: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_PHONE_HINT}}",
fieldlabel: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_PHONE_FIELD_LABEL}}",
callback: this._insertPhoneLinkCb,
defaultValue: currentUrl,
regex: '^\\+?\\s*(\\d+\\s?){2,}$',
regexText: "{{i18n CONTENT_EDITION_LINK_INSERT_PHONE_INVALID_NUMBER}}"
});
},
/**
* Callback function called when user has entered phone link. Inserts the link to the cursor position.
* @param {String} phone The entered phone
* @private
*/
_insertPhoneLinkCb: function(phone)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.focus();
if (phone != null)
{
var url = 'tel:' + phone;
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
{
tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + phone + "{$caret}</a> ");
node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
tinyMCE.activeEditor.selection.select(node);
}
tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": url, "href": url, "class": "phone", "data-ametys-type": "phone", "_mce_ribbon_select": "1" });
tinyMCE.activeEditor.selection.collapse();
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
}
// Delayed to wait for the dialog box to hide.
window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
},
//------------------------------------------------------//
// RESOURCE LINK //
//------------------------------------------------------//
/**
* Initialize function to add a link handler for resources
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
initializeResourcesLink: function (controller)
{
this.addLinkHandler ('explorer', Ext.create('Ametys.plugins.cms.editor.Links.ResourceLinkHandler', {}));
},
/**
* Insert a link from the resource explorer.
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
insertResourcesLink: function(controller)
{
var currentId = null;
var editor = controller.getCurrentField().getEditor();
var node = editor.dom.getParent(editor.selection.getNode(), 'a');
if (node != null && (node.getAttribute("data-ametys-type") == "explorer"))
{
currentId = node.getAttribute("data-ametys-href");
}
this._doInsertResourcesLink(currentId);
},
/**
* Open dialog to select the resource from the explorer
* @param {String} currentId The resource id to select when opening the dialog box
* @private
*/
_doInsertResourcesLink: function(currentId)
{
Ametys.cms.uihelper.ChooseResource.open({
title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_RESOURCE_LABEL}}",
helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_RESOURCE_DESCRIPTION}}",
callback: this._insertResourcesLinkCb,
filter: null,
currentId: currentId,
allowDragAndDrop: this._allowDragAndDrop
});
},
/**
* Callback function called when user has selected the resource to link. Inserts the link to the current cursor position
* @param {String} id Id of the resource
* @param {String} filename File name of the resource
* @param {String} filesize File length of the resource
* @param {String} viewHref The URL to view the resource file
* @param {String} downloadHref The URL to download the resource file
* @param {Object} actionResult The result of the upload action. Can be null
* @param {String} [type='explorer'] The type of the resource to insert.
* @private
*/
_insertResourcesLinkCb: function(id, filename, filesize, viewHref, downloadHref, actionResult, type)
{
type = type || 'explorer';
if (id)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
{
var text = "{{i18n PLUGINS_CMS_EDITOR_LINK_DOWNLOAD}} «" + filename + "» (" + Ext.util.Format.fileSize(filesize) + ")";
tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + text + "{$caret}</a>");
node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
tinyMCE.activeEditor.selection.select(node);
}
tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": id, href: downloadHref, "class": "download", "data-ametys-type": type, "_mce_ribbon_select" : "1" });
tinyMCE.activeEditor.selection.collapse();
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
}
// Delayed to wait for the dialog box to hide.
window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
},
/**
* Insert a link from the resource explorer in a HTML expert code
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
insertResourcesLinkHtmlExpert: function (controller)
{
Ametys.cms.uihelper.ChooseResource.open({
title: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_EXPLORER_BOX_TITLE}}",
helpmessage: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_EXPLORER_BOX_HINT}}",
callback: this._insertResourcesLinkHtmlExpertCb,
filter: null
});
},
/**
* Callback function called when user has selected the resource to link. Inserts the link to the current cursor position in the HTML expert code
* @param {String} id Id of the resource
* @param {String} filename File name of the resource
* @param {String} filesize File length of the resource
* @param {String} viewHref The URL to view the resource file
* @param {String} downloadHref The URL to download the resource file
* @private
*/
_insertResourcesLinkHtmlExpertCb: function(id, filename, filesize, viewHref, downloadHref)
{
if (id != null)
{
Ametys.plugins.cms.editor.HTMLExpert.insertAtCaret("${" + "type:explorer#url:" + id + "#download:false}");
}
},
//------------------------------------------------------//
// ATTACHMENT LINK //
//------------------------------------------------------//
/**
* Initialize function to add a link handler for attachments
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
initializeAttachmentLink: function (controller)
{
this.addLinkHandler ('attachment-content', Ext.create('Ametys.plugins.cms.editor.Links.AttachmentLinkHandler', {}));
},
/**
* Insert a link from the attachments of the content.
* @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
insertAttachmentLink: function(controller)
{
var contentTarget = Ametys.message.MessageBus.getCurrentSelectionMessage().getTarget(Ametys.message.MessageTarget.CONTENT);
if (contentTarget)
{
var actionId = controller.getWorkflowActionId();
var currentId = (this._currentNode && this._currentNode.getAttribute('data-ametys-type') == 'attachment-content') ? this._currentNode.getAttribute('data-ametys-href') : null;
this._doInsertAttachmentLink(contentTarget, currentId, actionId);
}
},
/**
* Open a dialog box to select a content attachment.
* @param {String|Ametys.message.MessageTarget} content The content target (attachments' owner) or the content's id.
* @param {String} currentId The resource id to select when opening the dialog box
* @param {String} [actionId] The id of workflow action to execute if any.
* @private
*/
_doInsertAttachmentLink: function(content, currentId, actionId)
{
var contentId = Ext.isString(content) ? content : content.getParameters().id;
var callback = Ext.bind(this._selectAttachmentCb, this, [contentId, actionId], true);
Ametys.cms.uihelper.ChooseAttachmentFile.open({
iconCls: 'ametysicon-clip26',
title: "{{i18n PLUGINS_CMS_EDITOR_LINK_FILE_LABEL}}",
helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_FILE_DESCRIPTION}}",
ownerId: contentId,
callback: callback,
value: currentId,
allowCreation: true,
allowDragAndDrop: this._allowDragAndDrop,
insertAttachmentCallback: Ext.bind(this._changeContentWorkflow, this, [contentId, actionId, Ext.isString(content) ? null : content], 1)
});
},
/**
* Callback function called when user has selected the attachment to link. Inserts the link to the current cursor position
* @param {String} fileid Id of the resource
* @param {String} filename File name of the resource
* @param {String} filesize File length of the resource
* @param {String} viewHref The URL to view the resource file
* @param {String} downloadHref The URL to download the resource file
* @param {String} contentId The id of the content.
* @param {String} [actionId] The id of workflow action to execute if any.
* @private
*/
_selectAttachmentCb: function(fileid, filename, filesize, viewHref, downloadHref, contentId, actionId)
{
this._insertResourcesLinkCb(fileid, filename, filesize, viewHref, downloadHref, null, 'attachment-content');
},
/**
* Insert a link from the attachments of a content in a HTML expert code
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
insertAttachmentLinkHtmlExpert: function(controller)
{
var contentTarget = Ametys.message.MessageBus.getCurrentSelectionMessage().getTarget(Ametys.message.MessageTarget.CONTENT);
if (contentTarget)
{
var ownerId = contentTarget.getParameters()['id'];
var actionId = controller.getInitialConfig('workflow-action-id');
var callback = Ext.bind(this._insertAttachmentLinkHtmlExpertCb, this, [ownerId, actionId], true);
Ametys.cms.uihelper.ChooseAttachmentFile.open({
icon: Ametys.getPluginResourcesPrefix('cms') + '/img/content/attachments/attachment_16.png',
title: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_ATTACHMENT_BOX_TITLE}}",
helpmessage: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_ATTACHMENT_BOX_HINT}}",
ownerId: ownerId,
callback: callback,
allowCreation: true,
rightContext: '/contents/' + contentTarget.getParameters().name
});
}
},
/**
* Callback function called when user has selected the attachment to link. Inserts the link to the current cursor position in the HTML expert code
* @param {String} id Id of the resource
* @param {String} filename File name of the resource
* @param {String} filesize File length of the resource
* @param {String} viewHref The URL to view the resource file
* @param {String} downloadHref The URL to download the resource file
* @param {String} contentId The id of the content.
* @param {String} [actionId] The id of workflow action to execute if any.
* @private
*/
_insertAttachmentLinkHtmlExpertCb: function(id, filename, filesize, viewHref, downloadHref, contentId, actionId)
{
if (id != null)
{
Ametys.plugins.cms.editor.HTMLExpert.insertAtCaret("${" + "type:attachment-content#url:" + id + "#download:false}");
if (actionId)
{
this._changeContentWorkflow(contentId, actionId);
}
}
},
/**
* Executes a workflow action on content
* @param {String} resourceId The id of the attached resource
* @param {String} contentId The id of the content
* @param {Number} actionId The id of workflow action to execute
* @param {Object/Ametys.message.MessageTarget} [contentTarget] The content target or its configuration object. Can be null, but should be provided if available.
* @private
*/
_changeContentWorkflow: function(resourceId, contentId, actionId, contentTarget)
{
if (!actionId)
{
return;
}
contentTarget = contentTarget || {
id: Ametys.message.MessageTarget.CONTENT,
parameters: {ids: [contentId]}
};
var me = this;
var targetCreatedCb = function(targets) {
var target = targets[0];
var params = {
contentId: contentId,
id: contentId,
'with-contents': '/_plugins/cms/contents/info'
};
Ext.create('Ametys.message.Message', {
type: Ametys.message.Message.WORKFLOW_CHANGING,
targets: [target]
});
Ametys.data.ServerComm.send({
plugin: 'cms',
url: 'do-action/' + actionId,
parameters: params,
priority: Ametys.data.ServerComm.PRIORITY_MAJOR,
errorMessage: true,
callback: {
handler: me._changeContentWorkflowCb,
scope: me,
arguments: [target]
}
});
};
if (!(contentTarget instanceof Ametys.message.MessageTarget))
{
Ametys.message.MessageTargetFactory.createTargets(contentTarget, targetCreatedCb);
}
else
{
targetCreatedCb([contentTarget]);
}
},
/**
* @protected
* Callback function called after executing worklow action
* Override if specific behavior is needed.
* @param {Object} response The XML response provided by the {@link Ametys.data.ServerComm}
* @param {Object[]} params The callback parameters passed to the {@link Ametys.data.ServerComm#send} method
*/
_changeContentWorkflowCb: function(response, params)
{
var contentTarget = params[0];
Ext.create('Ametys.message.Message', {
type: Ametys.message.Message.WORKFLOW_CHANGED,
targets: [contentTarget]
});
},
//------------------------------------------------------//
// MISC INTERNAL METHODS //
//------------------------------------------------------//
/**
* Enable/disable controller if the current selected node is a link
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller
* @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
* @param {HTMLElement} node The current selected node. Can be null.
*/
linkSelectionListener: function (controller, field, node)
{
this._currentNode = node;
},
// ---------------------------------------- //
// EDIT LINK //
// ---------------------------------------- //
/**
* Open the edit link dialog.
* @param {Ext.form.field.Text} input The input text.
* @param {Ext.event.Event} e The event object.
*/
editLink: function(input, e)
{
if (this._currentNode != null)
{
var type = this._currentNode.getAttribute('data-ametys-type');
var href = this._currentNode.getAttribute('data-ametys-href') || this._currentNode.getAttribute('href');
if (this.getLinkHandler(type) != null)
{
this.getLinkHandler(type).edit(href);
}
}
},
/**
* Enable/disable the edit link controller.
* @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
* @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
* @param {HTMLElement} node The current selected node. Can be null.
*/
editLinkListener: function(controller, field, node)
{
var handler = this._currentNode != null ? this.getLinkHandler(this._currentNode.getAttribute("data-ametys-type")) : null;
if (this._currentNode && handler && Ext.isFunction(handler.edit))
{
controller.enable();
}
else
{
controller.disable();
}
},
// ---------------------------------------- //
// REMOVE LINK //
// ---------------------------------------- //
/**
* Remove the selected link.
* @param {Ext.form.field.Text} input The input text.
* @param {Ext.event.Event} e The event object.
*/
removeLink: function(input, e)
{
if (this._currentNode != null)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.focus();
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
tinyMCE.activeEditor.execCommand('UnLink');
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
}
},
// ---------------------------------------- //
// OPEN LINK //
// ---------------------------------------- //
/**
* Enable/disable controller and set value according to the selected link.
* @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
* @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
* @param {HTMLElement} node The current selected node. Can be null.
*/
openLinkListener: function(controller, field, node)
{
this._currentNode = node;
if (this._currentNode)
{
var type = this._currentNode.getAttribute('data-ametys-type');
var value = this._currentNode.getAttribute('data-ametys-href') || this._currentNode.getAttribute('href');
var handler = this.getLinkHandler(type);
type = handler != null ? handler.getTypeName() : type;
var title = handler != null ? handler.getTitle(value) : value;
var desc = handler != null ? handler.getDescription(value) : '';
if (this._currentNode.getAttribute("href") != '')
{
controller.setValue('(' + type + ') <a onclick="javascript:Ametys.plugins.cms.editor.Links.openLink(); return false;" href="">' + title + '</a>');
}
else
{
controller.setValue('(' + type + ') ' + title);
}
controller.setDescription (desc);
}
else
{
controller.setValue(null);
}
},
/**
* Open the link.
* @param {Ext.form.field.Text} input The input text.
* @param {Ext.event.Event} e The event object.
*/
openLink: function()
{
var node = this._currentNode;
if (node != null && node.getAttribute("href") != '')
{
if (node.href.indexOf("javascript") == 0)
{
window.location.href = node.href;
}
else
{
window.open(node.href);
}
}
},
// ---------------------------------------- //
// TITLE //
// ---------------------------------------- //
/**
* Set 'title' attribute to current <a> node
* @param {Ext.form.field.Text} input The input text
*/
setTitleOnBlur: function(input)
{
var link = this._currentNode;
var inputValue = input.getValue();
if (this._currentNode && link.getAttribute('title') != inputValue)
{
this.setTitle(inputValue);
}
},
/**
* Set 'title' attribute to current <a> node when pressing ENTER or ESC key.
* @param {Ext.form.field.Text} input The input text.
* @param {Ext.event.Event} e The event object.
*/
setTitleOnSpecialKey: function(input, e)
{
if (e.getKey() == e.ENTER)
{
e.preventDefault();
e.stopPropagation();
this.setTitle(input.getValue());
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.focus();
}
else if (e.getKey() == e.ESC)
{
e.preventDefault();
e.stopPropagation();
input.setValue(this._getTitle());
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.focus();
}
},
/**
* Set 'title' attribute to current <a> node
* @param {String} value The value.
*/
setTitle: function(value)
{
var link = this._currentNode;
if (link != null)
{
if (value == '')
{
link.removeAttribute('title');
}
else
{
link.setAttribute('title', value);
}
tinyMCE.activeEditor.execCommand('mceAddUndoLevel');
}
},
/**
* Enable/disable controller and set input value according to the selected link.
* @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
* @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
* @param {HTMLElement} node The current selected node. Can be null.
*/
titleSelectionListener: function(controller, field, node)
{
if (node)
{
controller.setValue(this._getTitle(node));
}
else
{
controller.setValue('');
}
this._currentNode = node;
},
/**
* Get the 'title' attribute of a <a> node
* @param {HTMLElement} node The <a> node. Can be null to retrieve <a> node from cursor current position.
* @return {String} The title attribute.
* @private
*/
_getTitle: function(node)
{
return node.getAttribute('title') || '';
},
// ---------------------------------------- //
// OPEN IN NEW WINDOW //
// ---------------------------------------- //
/**
* Set the target field.
* @param {Ext.form.field.Checkbox} input The input text.
*/
setOpenNewWindow: function(input)
{
var newValue = input.getValue();
if (newValue != this._getOpenInNewWindow())
{
this._currentNode.setAttribute('target', newValue ? '_blank' : '');
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceAddUndoLevel');
}
tinyMCE.activeEditor.focus();
},
/**
* @private
* Is the link open in new window option activated ?
*/
_getOpenInNewWindow: function()
{
if (this._currentnode)
{
return this._currentnode.getAttribute("target") != null && this._currentnode.getAttribute("target") == "_blank";
}
},
/**
* Enable/disable controller and set input value according to the selected link.
* @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
* @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
* @param {HTMLElement} node The current selected node. Can be null.
*/
openNewWindowSelectionListener: function(controller, field, node)
{
if (!node || node.getAttribute('data-ametys-type') == 'mail')
{
controller.disable();
}
else
{
var target = node.getAttribute('target');
controller.setValue(target != null && target == '_blank');
}
}
});