/* table-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([ 'aloha', 'jquery', 'aloha/plugin', 'aloha/pluginmanager', 'ui/ui', 'ui/scopes', 'ui/button', 'ui/toggleButton', 'ui/dialog', 'ui/port-helper-attribute-field', 'ui/port-helper-multi-split', 'i18n!table/nls/i18n', 'i18n!aloha/nls/i18n', 'table/table-create-layer', 'table/table', 'table/table-plugin-utils', 'util/dom', 'aloha/console' ], function( Aloha, jQuery, Plugin, PluginManager, Ui, Scopes, Button, ToggleButton, Dialog, AttributeField, MultiSplitButton, i18n, i18nCore, CreateLayer, Table, Utils, Dom, Console ) { var $ = jQuery; var GENTICS = window.GENTICS; /** * Register the TablePlugin as Aloha.Plugin */ var TablePlugin = new Plugin('table'); /** * The Create-Layer Object of the TablePlugin * * @see Table.CreateLayer */ TablePlugin.createLayer = undefined; /** * default button configuration */ TablePlugin.config = [ 'table' ]; /** * An Array which holds all newly created tables contains DOM-Nodes of * table-objects */ TablePlugin.TableRegistry = new Array(); /** * Holds the active table-object */ TablePlugin.activeTable = undefined; /** * parameters-objects for tables * * @param className * The class of activated tables */ TablePlugin.parameters = { className : 'aloha-table', // class of editable tables classSelectionRow : 'aloha-table-selectcolumn', // class for the upper table-row to select columns classSelectionColumn : 'aloha-table-selectrow', // class for the left bound table-cells to select rows classLeftUpperCorner : 'aloha-table-leftuppercorner', // class for the left upper corner cell classTableWrapper : 'aloha-table-wrapper', // class of the outest table-wrapping div classCellSelected : 'aloha-cell-selected', // class of cell which are selected (row/column selection) waiRed : 'aloha-wai-red', // class that shows wai of div waiGreen : 'aloha-wai-green', // class that shows wai of div selectionArea : 10 // width/height of the selection rows (in pixel) }; /** * @hide * {name:'green', text:'Green',tooltip:'Green',iconClass:'GENTICS_table GENTICS_button_green',cssClass:'green'} */ TablePlugin.checkConfig = function (c){ if (typeof c == 'object' && c.length) { var newC = []; for (var i = 0; i < c.length; i++) { if (c[i]) { newC.push({ name : c[i].name, text : c[i].text ? c[i].text : c[i].name, tooltip : c[i].tooltip ? c[i].tooltip : c[i].text, iconClass : c[i].iconClass ? c[i].iconClass : 'aloha-icon-' + c[i].name, cssClass : c[i].cssClass ? c[i].cssClass : c[i].name }); } } c = newC; } else { c = []; } return c; }; /** * Checks whether the given DOM element is nested within a table. * * @param {jQuery.} $element * @return {boolean} True if the given element is nested in a table. */ function isWithinTable($element) { return 0 < $element.parents('.aloha-editable table').length; } /** * Checks whether the given DOM element is nested within an aloha block. * * @param {jQuery.} $element * @return {boolean} True if the given element is nested in an aloha block. */ function isWithinBlock($element) { return 0 < $element.closest('.aloha-block').length; } /** * Checks whether the table is an editable element. * * @return {boolean} True if the table's parent element is contentEditable; * false otherwise. */ function isEditableTable(table) { return GENTICS.Utils.Dom.isEditable(table); } /** * Checks for the presence of nested tables in the given element. * * @param {jQuery.} $element jQuery unit set containing a DOM * element. * @return {boolean} True if nested tables were detected; false otherwise. */ function checkForNestedTables($element) { var selector = $element.is('table') ? 'table' : 'table table'; if ($element.find(selector).length) { Console.warn('Table Plugin', 'Nested tables found. They will not be initialized.'); return true; } return false; } /** * Creates a table, if it is allowed, and registers a new Table object for * the given table DOM element. * * If the table's editable parent is activated, the table will also * automatically be activated. * * @param {HTMLElement} element HTML table element. * @return {Table|null} The created Table object or null if it was not * allowed to create the table. */ function createNewTable(element) { var $table = $(element); var create = isEditableTable(element) && !isWithinTable($table) && !isWithinBlock($table); if (create) { var table = new Table(element, TablePlugin); var $host = $(Dom.getEditingHostOf(element)); table.parentEditable = Aloha.getEditableById($host.attr('id')); TablePlugin.TableRegistry.push(table); checkForNestedTables($table); if (Aloha.activeEditable === table.parentEditable) { table.activate(); } return table; } return null; } /** * Init method of the Table-plugin transforms all tables in the document * * @return void */ TablePlugin.init = function() { var that = this, isEnabled = {}; // apply settings this.tableConfig = this.checkConfig(this.tableConfig||this.settings.tableConfig); this.columnConfig = this.checkConfig(this.columnConfig||this.settings.columnConfig); this.rowConfig = this.checkConfig(this.rowConfig||this.settings.rowConfig); this.cellConfig = this.checkConfig(this.cellConfig||this.settings.cellConfig); // table resize settings this.tableResize = this.settings.tableResize === undefined ? false : this.settings.tableResize; this.colResize = this.settings.colResize === undefined ? false : this.settings.colResize; this.rowResize = this.settings.rowResize === undefined ? false : this.settings.rowResize; // disable table resize settings on browsers below IE8 if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 8) { this.tableResize = false; this.colResize = false; this.rowResize = false; } // add reference to the create layer object this.createLayer = new CreateLayer( this ); // subscribe for the 'editableActivated' event to activate all tables in the editable Aloha.bind( 'aloha-editable-created', function (event, editable) { var config = that.getEditableConfig(editable.obj); isEnabled[editable.getId()] = (-1 !== jQuery.inArray('table', config)); // add a mousedown event to all created editables to check if focus leaves a table editable.obj.bind( 'mousedown', function ( jqEvent ) { TablePlugin.setFocusedTable( undefined ); } ); editable.obj.find('table').each(function (__unused__, elem) { createNewTable(elem); }); } ); // initialize the table buttons this.initTableButtons(); Aloha.bind( 'aloha-table-selection-changed', function () { // check if selected cells are split/merge able and set button status if ( typeof TablePlugin.activeTable !== 'undefined' && TablePlugin.activeTable.selection ) { TablePlugin.updateFloatingMenuScope(); if ( TablePlugin.activeTable.selection.cellsAreSplitable() ) { that._splitcellsButton.enable(true); that._splitcellsRowButton.enable(true); that._splitcellsColumnButton.enable(true); } else { that._splitcellsButton.enable(false); that._splitcellsRowButton.enable(false); that._splitcellsColumnButton.enable(false); } if ( TablePlugin.activeTable.selection.cellsAreMergeable() ) { that._mergecellsButton.enable(true); that._mergecellsRowButton.enable(true); that._mergecellsColumnButton.enable(true); } else { that._mergecellsButton.enable(false); that._mergecellsRowButton.enable(false); that._mergecellsColumnButton.enable(false); } } }); Aloha.bind( 'aloha-selection-changed', function (event, rangeObject) { // this case probably occurs when the selection is empty? if (!rangeObject.startContainer || !Aloha.activeEditable) { return; } // show hide buttons regarding configuration and DOM position if (isEnabled[Aloha.activeEditable.getId()] && Aloha.Selection.mayInsertTag('table') ) { that._createTableButton.show(); } else { that._createTableButton.hide(); } if (!that.activeTable) { return; } // check wheater we are inside a table var table = rangeObject.findMarkup(function() { return this.nodeName === 'TABLE'; }, Aloha.activeEditable.obj); if (table) { TablePlugin.updateFloatingMenuScope(); TablePlugin.setActiveCellStyle(); } else { that.activeTable.selection.cellSelectionMode = false; that.activeTable.selection.baseCellPosition = null; that.activeTable.selection.lastSelectionRange = null; that.activeTable.focusOut(); } }); Aloha.bind('aloha-editable-activated', function (__event__, data) { that._splitcellsButton.enable(false); that._mergecellsButton.enable(false); that._splitcellsRowButton.enable(false); that._mergecellsRowButton.enable(false); that._splitcellsColumnButton.enable(false); that._mergecellsColumnButton.enable(false); data.editable.obj.find('table').each(function () { var registry = TablePlugin.TableRegistry; for (var i = 0; i < registry.length; i++) { if (registry[i].obj.attr('id') === jQuery(this).attr('id')) { registry[i].activate(); return true; } } // Because table this is a new table that is not yet in the // registry. createNewTable(this); }); }); Aloha.bind('aloha-editable-deactivated', function () { if (TablePlugin.activeTable) { TablePlugin.activeTable.selection.unselectCells(); } TablePlugin.setFocusedTable(undefined); var registry = TablePlugin.TableRegistry; for (var i = 0; i < registry.length; i++) { registry[i].deactivate(); } }); Aloha.bind('aloha-smart-content-changed', function () { if (Aloha.activeEditable) { Aloha.activeEditable.obj.find('table').each(function () { if (TablePlugin.indexOfTableInRegistry(this) == -1) { if (createNewTable(this)) { this.id = GENTICS.Utils.guid(); } } }); } }); if (this.settings.summaryinsidebar) { Aloha.bind('aloha-plugins-loaded', function () { that.initSidebar(Aloha.Sidebar.right.show()); }); } }; //namespace prefix for this plugin var tableNamespace = 'aloha-table'; function nsSel () { var stringBuilder = [], prefix = tableNamespace; jQuery.each(arguments, function () { stringBuilder.push('.' + (this == '' ? prefix : prefix + '-' + this)); }); return jQuery.trim(stringBuilder.join(' ')); }; //Creates string with this component's namepsace prefixed the each classname function nsClass () { var stringBuilder = [], prefix = tableNamespace; jQuery.each(arguments, function () { stringBuilder.push(this == '' ? prefix : prefix + '-' + this); }); return jQuery.trim(stringBuilder.join(' ')); }; TablePlugin.initSidebar = function(sidebar) { var pl = this; pl.sidebar = sidebar; pl.sidebarPanel = sidebar.addPanel({ id : nsClass('sidebar-panel'), title : i18n.t('table.sidebar.title'), content : '', expanded : true, activeOn : 'table', onInit : function () { var that = this, content = this.setContent( '' + '