MDL-44758 editor-atto: prevent table-in-table creation

Prevent new table creation, displaying table context menu instead when cursor is within caption, when multiple cells are selected, when selection contains both nodes within and outside of the table, and when selection contains nodes from multiple tables.
This commit is contained in:
Jetha Chan 2014-04-01 12:40:33 +08:00
parent ad32dda90c
commit 3a6511a530
4 changed files with 155 additions and 50 deletions

View File

@ -150,30 +150,27 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
* @private
*/
_displayTableEditor: function(e) {
var selection = this.get('host').getSelectionParentNode(),
cell;
if (!selection) {
// We don't have a current selection at all, so show the standard dialogue.
return this._displayDialogue(e);
}
// Check all of the table cells found in the selection.
Y.one(selection).ancestors('th, td', true).each(function(node) {
if (this.editor.contains(node)) {
cell = node;
}
}, this);
var cell = this._getSuitableTableCell();
if (cell) {
// Add the cell to the EventFacade to save duplication in when showing the menu.
e.tableCell = cell;
return this._showTableMenu(e);
}
return this._displayDialogue(e);
},
/**
* Returns whether or not the parameter node exists within the editor.
*
* @method _stopAtContentEditableFilter
* @param {Node} node
* @private
* @return {boolean} whether or not the parameter node exists within the editor.
*/
_stopAtContentEditableFilter: function(node) {
this.editor.contains(node);
},
/**
* Return the dialogue content for the tool, attaching any required
* events.
@ -196,6 +193,44 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
return this._content;
},
/**
* Given the current selection, return a table cell suitable for table editing
* purposes, i.e. the first table cell selected, or the first cell in the table
* that the selection exists in, or null if not within a table.
*
* @method _getSuitableTableCell
* @private
* @return {Node} suitable target cell, or null if not within a table
*/
_getSuitableTableCell: function() {
var targetcell = null,
host = this.get('host');
host.getSelectedNodes().some(function (node) {
if (node.ancestor('td, th, caption', true, this._stopAtContentEditableFilter)) {
targetcell = node;
var caption = node.ancestor('caption', true, this._stopAtContentEditableFilter);
if (caption) {
var table = caption.get('parentNode');
if (table) {
targetcell = table.one('td, th');
}
}
// Once we've found a cell to target, we shouldn't need to keep looking.
return true;
}
});
if (targetcell) {
var selection = host.getSelectionFromNode(targetcell);
host.setSelection(selection);
}
return targetcell;
},
/**
* Handle creation of a new table.
*

File diff suppressed because one or more lines are too long

View File

@ -150,30 +150,27 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
* @private
*/
_displayTableEditor: function(e) {
var selection = this.get('host').getSelectionParentNode(),
cell;
if (!selection) {
// We don't have a current selection at all, so show the standard dialogue.
return this._displayDialogue(e);
}
// Check all of the table cells found in the selection.
Y.one(selection).ancestors('th, td', true).each(function(node) {
if (this.editor.contains(node)) {
cell = node;
}
}, this);
var cell = this._getSuitableTableCell();
if (cell) {
// Add the cell to the EventFacade to save duplication in when showing the menu.
e.tableCell = cell;
return this._showTableMenu(e);
}
return this._displayDialogue(e);
},
/**
* Returns whether or not the parameter node exists within the editor.
*
* @method _stopAtContentEditableFilter
* @param {Node} node
* @private
* @return {boolean} whether or not the parameter node exists within the editor.
*/
_stopAtContentEditableFilter: function(node) {
this.editor.contains(node);
},
/**
* Return the dialogue content for the tool, attaching any required
* events.
@ -196,6 +193,44 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
return this._content;
},
/**
* Given the current selection, return a table cell suitable for table editing
* purposes, i.e. the first table cell selected, or the first cell in the table
* that the selection exists in, or null if not within a table.
*
* @method _getSuitableTableCell
* @private
* @return {Node} suitable target cell, or null if not within a table
*/
_getSuitableTableCell: function() {
var targetcell = null,
host = this.get('host');
host.getSelectedNodes().some(function (node) {
if (node.ancestor('td, th, caption', true, this._stopAtContentEditableFilter)) {
targetcell = node;
var caption = node.ancestor('caption', true, this._stopAtContentEditableFilter);
if (caption) {
var table = caption.get('parentNode');
if (table) {
targetcell = table.one('td, th');
}
}
// Once we've found a cell to target, we shouldn't need to keep looking.
return true;
}
});
if (targetcell) {
var selection = host.getSelectionFromNode(targetcell);
host.setSelection(selection);
}
return targetcell;
},
/**
* Handle creation of a new table.
*

View File

@ -148,30 +148,27 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
* @private
*/
_displayTableEditor: function(e) {
var selection = this.get('host').getSelectionParentNode(),
cell;
if (!selection) {
// We don't have a current selection at all, so show the standard dialogue.
return this._displayDialogue(e);
}
// Check all of the table cells found in the selection.
Y.one(selection).ancestors('th, td', true).each(function(node) {
if (this.editor.contains(node)) {
cell = node;
}
}, this);
var cell = this._getSuitableTableCell();
if (cell) {
// Add the cell to the EventFacade to save duplication in when showing the menu.
e.tableCell = cell;
return this._showTableMenu(e);
}
return this._displayDialogue(e);
},
/**
* Returns whether or not the parameter node exists within the editor.
*
* @method _stopAtContentEditableFilter
* @param {Node} node
* @private
* @return {boolean} whether or not the parameter node exists within the editor.
*/
_stopAtContentEditableFilter: function(node) {
this.editor.contains(node);
},
/**
* Return the dialogue content for the tool, attaching any required
* events.
@ -194,6 +191,44 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
return this._content;
},
/**
* Given the current selection, return a table cell suitable for table editing
* purposes, i.e. the first table cell selected, or the first cell in the table
* that the selection exists in, or null if not within a table.
*
* @method _getSuitableTableCell
* @private
* @return {Node} suitable target cell, or null if not within a table
*/
_getSuitableTableCell: function() {
var targetcell = null,
host = this.get('host');
host.getSelectedNodes().some(function (node) {
if (node.ancestor('td, th, caption', true, this._stopAtContentEditableFilter)) {
targetcell = node;
var caption = node.ancestor('caption', true, this._stopAtContentEditableFilter);
if (caption) {
var table = caption.get('parentNode');
if (table) {
targetcell = table.one('td, th');
}
}
// Once we've found a cell to target, we shouldn't need to keep looking.
return true;
}
});
if (targetcell) {
var selection = host.getSelectionFromNode(targetcell);
host.setSelection(selection);
}
return targetcell;
},
/**
* Handle creation of a new table.
*