mirror of
https://github.com/moodle/moodle.git
synced 2025-04-22 17:02:03 +02:00
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:
parent
ad32dda90c
commit
3a6511a530
@ -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
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user