/* format-plugin.js is part of Aloha Editor project http://aloha-editor.org * * Aloha Editor is a WYSIWYG HTML5 inline editing library and editor. * Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria. * Contributors http://aloha-editor.org/contribution.php * * Aloha Editor is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * Aloha Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As an additional permission to the GNU GPL version 2, you may distribute * non-source (e.g., minimized or compacted) forms of the Aloha-Editor * source code without the copy of the GNU GPL normally required, * provided you include this license notice and a URL through which * recipients can access the Corresponding Source. */ define('format/format-plugin', [ 'aloha', 'aloha/plugin', 'jquery', 'ui/ui', 'ui/toggleButton', 'ui/port-helper-multi-split', 'PubSub', 'i18n!format/nls/i18n', 'i18n!aloha/nls/i18n', 'aloha/selection' ], function ( Aloha, Plugin, jQuery, Ui, ToggleButton, MultiSplitButton, PubSub, i18n, i18nCore ) { 'use strict'; var GENTICS = window.GENTICS, pluginNamespace = 'aloha-format', commandsByElement = { 'b': 'bold', 'strong': 'bold', 'i': 'italic', 'em': 'italic', 'del': 'strikethrough', 'sub': 'subscript', 'sup': 'superscript', 'u': 'underline', 's': 'strikethrough' }, componentNameByElement = { 'strong': 'strong', 'em': 'emphasis', 's': 'strikethrough2' }, textLevelSemantics = { 'u': true, 'em': true, 'strong': true, 'b': true, 'i': true, 'cite': true, 'q': true, 'code': true, 'abbr': true, 'del': true, 's': true, 'sub': true, 'sup': true }, blockLevelSemantics = { 'p': true, 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, 'pre': true }; // extracted selection changed function function onSelectionChanged(formatPlugin, rangeObject) { // iterate over all buttons var statusWasSet = false, effectiveMarkup, foundMultiSplit, i, j, multiSplitItem; jQuery.each(formatPlugin.buttons, function (index, button) { statusWasSet = false; for (i = 0; i < rangeObject.markupEffectiveAtStart.length; i++) { effectiveMarkup = rangeObject.markupEffectiveAtStart[i]; if (Aloha.Selection.standardTextLevelSemanticsComparator(effectiveMarkup, button.markup)) { button.handle.setState(true); statusWasSet = true; } } if (!statusWasSet) { button.handle.setState(false); } }); if (formatPlugin.multiSplitItems.length > 0) { foundMultiSplit = false; // iterate over the markup elements for (i = 0; i < rangeObject.markupEffectiveAtStart.length && !foundMultiSplit; i++) { effectiveMarkup = rangeObject.markupEffectiveAtStart[i]; for (j = 0; j < formatPlugin.multiSplitItems.length && !foundMultiSplit; j++) { multiSplitItem = formatPlugin.multiSplitItems[j]; if (!multiSplitItem.markup) { continue; } // now check whether one of the multiSplitItems fits to the effective markup if (Aloha.Selection.standardTextLevelSemanticsComparator(effectiveMarkup, multiSplitItem.markup)) { formatPlugin.multiSplitButton.setActiveItem(multiSplitItem.name); foundMultiSplit = true; } } } if (!foundMultiSplit) { formatPlugin.multiSplitButton.setActiveItem(null); } } } /** * register the plugin with unique name */ return Plugin.create('format', { /** * default button configuration */ config: [ 'b', 'i', 'sub', 'sup', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'removeFormat' ], /** * available options / buttons * * @todo new buttons needed for 'code' */ availableButtons: [ 'u', 'strong', 'del', 'em', 'b', 'i', 's', 'sub', 'sup', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'removeFormat' ], /** * HotKeys used for special actions */ hotKey: { formatBold: 'ctrl+b', formatItalic: 'ctrl+i', formatParagraph: 'alt+ctrl+0', formatH1: 'alt+ctrl+1', formatH2: 'alt+ctrl+2', formatH3: 'alt+ctrl+3', formatH4: 'alt+ctrl+4', formatH5: 'alt+ctrl+5', formatH6: 'alt+ctrl+6', formatPre: 'ctrl+p', formatDel: 'ctrl+d', formatSub: 'alt+shift+s', formatSup: 'ctrl+shift+s' }, /** * Initialize the plugin and set initialize flag on true */ init: function () { // Prepare var me = this; if ( typeof this.settings.hotKey !== 'undefined' ) { jQuery.extend(true, this.hotKey, this.settings.hotKey); } this.initButtons(); Aloha.bind('aloha-plugins-loaded', function () { // @todo add config option for sidebar panel me.initSidebar(Aloha.Sidebar.right); }); // apply specific configuration if an editable has been activated Aloha.bind('aloha-editable-activated',function (e, params) { me.applyButtonConfig(params.editable.obj); // handle hotKeys params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatBold, function() { me.addMarkup( 'b' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatItalic, function() { me.addMarkup( 'i' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatParagraph, function() { me.changeMarkup( 'p' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatH1, function() { me.changeMarkup( 'h1' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatH2, function() { me.changeMarkup( 'h2' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatH3, function() { me.changeMarkup( 'h3' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatH4, function() { me.changeMarkup( 'h4' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatH5, function() { me.changeMarkup( 'h5' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatH6, function() { me.changeMarkup( 'h6' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatPre, function() { me.changeMarkup( 'pre' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatDel, function() { me.addMarkup( 'del' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatSub, function() { me.addMarkup( 'sub' ); return false; }); params.editable.obj.bind( 'keydown.aloha.format', me.hotKey.formatSup, function() { me.addMarkup( 'sup' ); return false; }); }); Aloha.bind('aloha-editable-deactivated',function (e, params) { params.editable.obj.unbind('keydown.aloha.format'); }); }, /** * applys a configuration specific for an editable * buttons not available in this configuration are hidden * @param {Object} id of the activated editable * @return void */ applyButtonConfig: function (obj) { var config = this.getEditableConfig(obj), button, i, len; if ( typeof config === 'object' ) { var config_old = []; jQuery.each(config, function(j, button) { if ( !(typeof j === 'number' && typeof button === 'string') ) { config_old.push(j); } }); if ( config_old.length > 0 ) { config = config_old; } } this.formatOptions = config; // now iterate all buttons and show/hide them according to the config for ( button in this.buttons) { if (this.buttons.hasOwnProperty(button)) { if (jQuery.inArray(button, config) !== -1) { this.buttons[button].handle.show(); } else { this.buttons[button].handle.hide(); } } } // and the same for multisplit items len = this.multiSplitItems.length; for (i = 0; i < len; i++) { if (jQuery.inArray(this.multiSplitItems[i].name, config) !== -1) { this.multiSplitButton.showItem(this.multiSplitItems[i].name); } else { this.multiSplitButton.hideItem(this.multiSplitItems[i].name); } } }, /** * initialize the buttons and register them on floating menu * @param event event object * @param editable current editable object */ initButtons: function () { var // @TODO: Please remove this when you are done obsoleting // scopes completely. scope = 'Aloha.continuoustext', that = this; // reset this.buttons = {}; // collect the multisplit items here this.multiSplitItems = []; //this.multiSplitButton; //iterate configuration array an push buttons to buttons array jQuery.each(this.availableButtons, function(j, button) { var button_config = false; if ( typeof j !== 'number' && typeof button !== 'string' ) { button_config = button; button = j; } if (textLevelSemantics[button]) { var command = commandsByElement[button]; var componentName = command; if (componentNameByElement.hasOwnProperty(button)) { componentName = componentNameByElement[button]; } var component = Ui.adopt(componentName, ToggleButton, { tooltip : i18n.t('button.' + button + '.tooltip'), icon: 'aloha-icon aloha-icon-' + componentName, scope: scope, click: function () { var selectedCells = jQuery('.aloha-cell-selected'); // formating workaround for table plugin if ( selectedCells.length > 0 ) { var cellMarkupCounter = 0; selectedCells.each( function () { var cellContent = jQuery(this).find('div'), cellMarkup = cellContent.find(button); if ( cellMarkup.length > 0 ) { // unwrap all found markup text //