/**
* Copyright (c) 2011 PolicyStat LLC.
* MIT licensed (MIT-license.txt)
*
* @author Wes Winham (winhamwr@gmail.com)
*/
// Fugue icons by Yusuke Kamiyamane http://p.yusukekamiyamane.com/
// and licensed under Creative Commons Attribution
/**
* A Table editing plugin that gives the user ability to add and remove
* rows and columns as well as merge rows and columns.
*
* @param options A configuration object.
* @param wym The WYMeditor instance to which the TableEditor should attach.
* @class
*/
function TableEditor(options, wym) {
options = jQuery.extend({
sMergeRowButtonHtml: String() +
'
).
*
* @param elmnt The node whose parent tr will be removed.
*/
TableEditor.prototype.removeRow = function (elmnt) {
var wym = this._wym,
tr = this._wym.findUp(elmnt, 'tr'),
table;
if (tr === null) {
return false;
}
table = wym.findUp(elmnt, 'table');
$(tr).remove();
this.removeEmptyTable(table);
return false;
};
/**
* Add a column to the given elmnt (representing a or a child of a | ).
*
* @param elmnt The node which will have a column appended afterward.
*/
TableEditor.prototype.addColumn = function (elmnt) {
var wym = this._wym,
td = this._wym.findUp(elmnt, ['td', 'th']),
prevTds,
tdIndex,
tr,
newTd = ' | | ',
newTh = ' | ',
insertionElement;
if (td === null) {
return false;
}
prevTds = $(td).prevAll();
tdIndex = prevTds.length;
tr = wym.findUp(td, 'tr');
$(tr).siblings('tr').andSelf().each(function (index, element) {
insertionElement = newTd;
if ($(element).find('th').length > 0) {
// The row has a TH, so insert a th
insertionElement = newTh;
}
$(element).find('td,th').eq(tdIndex).after(insertionElement);
});
return false;
};
/**
* Remove the column to the right of the given elmnt (representing a or a
* child of a | ).
*/
TableEditor.prototype.removeColumn = function (elmnt) {
var wym = this._wym,
td = this._wym.findUp(elmnt, ['td', 'th']),
table,
prevTds,
tdIndex,
tr;
if (td === null) {
return false;
}
table = wym.findUp(elmnt, 'table');
prevTds = $(td).prevAll();
tdIndex = prevTds.length;
tr = wym.findUp(td, 'tr');
$(tr).siblings('tr').each(function (index, element) {
$(element).find('td,th').eq(tdIndex).remove();
});
$(td).remove();
this.removeEmptyTable(table);
return false;
};
/**
* keyDown event handler used for consistent tab key cell movement.
*/
TableEditor.prototype.keyDown = function (evt) {
//'this' is the doc
var wym = WYMeditor.INSTANCES[this.title],
tableEditor = wym.tableEditor;
if (evt.keyCode === WYMeditor.KEY.TAB) {
return tableEditor.selectNextCell(wym.selected());
}
return null;
};
/**
* Move the focus to the next cell.
*/
TableEditor.prototype.selectNextCell = function (elmnt) {
var wym = this._wym,
tableEditor = this,
cell = wym.findUp(elmnt, ['td', 'th']),
nextCells,
tr,
nextRows;
if (cell === null) {
return null;
}
// Try moving to the next cell to the right
nextCells = $(cell).next('td,th');
if (nextCells.length > 0) {
tableEditor.selectElement(nextCells[0]);
return false;
}
// There was no cell to the right, use the first cell in the next row
tr = wym.findUp(cell, 'tr');
nextRows = $(tr).next('tr');
if (nextRows.length !== 0) {
nextCells = $(nextRows).children('td,th');
if (nextCells.length > 0) {
tableEditor.selectElement(nextCells[0]);
return false;
}
}
// There is no next row. Do a normal tab
return null;
};
/**
* Select the given element using rangy selectors.
*/
TableEditor.prototype.selectElement = function (elmnt) {
var sel = rangy.getIframeSelection(this._wym._iframe),
range = rangy.createRange(this._wym._doc);
range.setStart(elmnt, 0);
range.setEnd(elmnt, 0);
range.collapse(false);
try {
sel.setSingleRange(range);
} catch (err) {
// ie8 can raise an "unkown runtime error" trying to empty the range
}
// IE selection hack
if ($.browser.msie) {
this._wym.saveCaret();
}
};
/**
* Get the common parent tr for the given table cell nodes. If the closest parent
* tr for each cell isn't the same, returns null.
*/
TableEditor.prototype.getCommonParentTr = function (cells) {
var firstCell,
parentTrList,
rootTr;
cells = $(cells).filter('td,th');
if (cells.length === 0) {
return null;
}
firstCell = cells[0];
parentTrList = $(firstCell).parent('tr');
if (parentTrList.length === 0) {
return null;
}
rootTr = parentTrList[0];
// Ensure that all of the cells have the same parent tr
$(cells).each(function (index, elmnt) {
parentTrList = $(elmnt).parent('tr');
if (parentTrList.length === 0 || parentTrList[0] !== rootTr) {
return null;
}
});
return rootTr;
};
|