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:
Vendored
+51
-16
@@ -179,30 +179,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 edit table dialogue content, attaching any required
|
||||
* events.
|
||||
@@ -247,6 +244,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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Change a node from one type to another, copying all attributes and children.
|
||||
*
|
||||
|
||||
Vendored
+3
-3
File diff suppressed because one or more lines are too long
Vendored
+51
-16
@@ -179,30 +179,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 edit table dialogue content, attaching any required
|
||||
* events.
|
||||
@@ -247,6 +244,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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Change a node from one type to another, copying all attributes and children.
|
||||
*
|
||||
|
||||
+51
-16
@@ -177,30 +177,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 edit table dialogue content, attaching any required
|
||||
* events.
|
||||
@@ -245,6 +242,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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Change a node from one type to another, copying all attributes and children.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user