Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
template.js.tinymce.plugins.table.classes.ResizeBars.js Maven / Gradle / Ivy
/**
* ResizeBars.js
*
* Released under LGPL License.
* Copyright (c) 1999-2015 Ephox Corp. All rights reserved
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/**
* This class handles table column and row resizing by adding divs over the columns and rows of the table.
* These divs are then manipulated using mouse events to resize the underlying table.
*
* @class tinymce.tableplugin.ResizeBars
* @private
*/
define("tinymce/tableplugin/ResizeBars", [
"tinymce/util/Tools",
"tinymce/util/VK"
], function(Tools, VK) {
var hoverTable;
return function(editor) {
var RESIZE_BAR_CLASS = 'mce-resize-bar',
RESIZE_BAR_ROW_CLASS = 'mce-resize-bar-row',
RESIZE_BAR_ROW_CURSOR_STYLE = 'row-resize',
RESIZE_BAR_ROW_DATA_ATTRIBUTE = 'data-row',
RESIZE_BAR_ROW_DATA_INITIAL_TOP_ATTRIBUTE = 'data-initial-top',
RESIZE_BAR_COL_CLASS = 'mce-resize-bar-col',
RESIZE_BAR_COL_CURSOR_STYLE = 'col-resize',
RESIZE_BAR_COL_DATA_ATTRIBUTE = 'data-col',
RESIZE_BAR_COL_DATA_INITIAL_LEFT_ATTRIBUTE = 'data-initial-left',
RESIZE_BAR_THICKNESS = 4,
RESIZE_MINIMUM_WIDTH = 10,
RESIZE_MINIMUM_HEIGHT = 10,
RESIZE_BAR_DRAGGING_CLASS = 'mce-resize-bar-dragging';
var percentageBasedSizeRegex = new RegExp(/(\d+(\.\d+)?%)/),
pixelBasedSizeRegex = new RegExp(/px|em/);
var delayDrop, dragging, blockerElement, dragBar, lastX, lastY;
// Get the absolute position's top edge.
function getTopEdge(index, row) {
return {
index: index,
y: editor.dom.getPos(row).y
};
}
// Get the absolute position's bottom edge.
function getBottomEdge(index, row) {
return {
index: index,
y: editor.dom.getPos(row).y + row.offsetHeight
};
}
// Get the absolute position's left edge.
function getLeftEdge(index, cell) {
return {
index: index,
x: editor.dom.getPos(cell).x
};
}
// Get the absolute position's right edge.
function getRightEdge(index, cell) {
return {
index: index,
x: editor.dom.getPos(cell).x + cell.offsetWidth
};
}
function isRtl() {
var dir = editor.getBody().dir;
return dir === 'rtl';
}
function isInline() {
return editor.inline;
}
function getBody() {
return isInline ? editor.getBody().ownerDocument.body : editor.getBody();
}
function getInnerEdge(index, cell) {
return isRtl() ? getRightEdge(index, cell) : getLeftEdge(index, cell);
}
function getOuterEdge(index, cell) {
return isRtl() ? getLeftEdge(index, cell) : getRightEdge(index, cell);
}
function getPercentageWidthFallback(element, table) {
return getComputedStyleSize(element, 'width') / getComputedStyleSize(table, 'width') * 100;
}
function getComputedStyleSize(element, property) {
var widthString = editor.dom.getStyle(element, property, true);
var width = parseInt(widthString, 10);
return width;
}
function getCurrentTablePercentWidth(table) {
var tableWidth = getComputedStyleSize(table, 'width');
var tableParentWidth = getComputedStyleSize(table.parentElement, 'width');
return tableWidth / tableParentWidth * 100;
}
function getCellPercentDelta(table, delta) {
var tableWidth = getComputedStyleSize(table, 'width');
return delta / tableWidth * 100;
}
function getTablePercentDelta(table, delta) {
var tableParentWidth = getComputedStyleSize(table.parentElement, 'width');
return delta / tableParentWidth * 100;
}
// Find the left/right (ltr/rtl) or top side locations of the cells to measure.
// This is the location of the borders we need to draw over.
function findPositions(getInner, getOuter, thingsToMeasure) {
var tablePositions = [];
// Skip the first item in the array = no left (LTR), right (RTL) or top bars
for (var i = 1; i < thingsToMeasure.length; i++) {
// Get the element from the details
var item = thingsToMeasure[i].element;
// We need to zero index this again
tablePositions.push(getInner(i - 1, item));
}
var lastTableLineToMake = thingsToMeasure[thingsToMeasure.length - 1];
tablePositions.push(getOuter(thingsToMeasure.length - 1, lastTableLineToMake.element));
return tablePositions;
}
// Clear the bars.
function clearBars() {
var bars = editor.dom.select('.' + RESIZE_BAR_CLASS, getBody());
Tools.each(bars, function(bar) {
editor.dom.remove(bar);
});
}
// Refresh the bars.
function refreshBars(tableElement) {
clearBars();
drawBars(tableElement);
}
// Generates a resize bar object for the editor to add.
function generateBar(classToAdd, cursor, left, top, height, width, indexAttr, index) {
var bar = {
'data-mce-bogus': 'all',
'class': RESIZE_BAR_CLASS + ' ' + classToAdd,
'unselectable': 'on',
'data-mce-resize': false,
style: 'cursor: ' + cursor + '; ' +
'margin: 0; ' +
'padding: 0; ' +
'position: absolute; ' +
'left: ' + left + 'px; ' +
'top: ' + top + 'px; ' +
'height: ' + height + 'px; ' +
'width: ' + width + 'px; '
};
bar[indexAttr] = index;
return bar;
}
// Draw the row bars over the row borders.
function drawRows(rowPositions, tableWidth, tablePosition) {
Tools.each(rowPositions, function(rowPosition) {
var left = tablePosition.x,
top = rowPosition.y - RESIZE_BAR_THICKNESS / 2,
height = RESIZE_BAR_THICKNESS,
width = tableWidth;
editor.dom.add(getBody(), 'div',
generateBar(RESIZE_BAR_ROW_CLASS, RESIZE_BAR_ROW_CURSOR_STYLE,
left, top, height, width, RESIZE_BAR_ROW_DATA_ATTRIBUTE, rowPosition.index));
});
}
// Draw the column bars over the column borders.
function drawCols(cellPositions, tableHeight, tablePosition) {
Tools.each(cellPositions, function(cellPosition) {
var left = cellPosition.x - RESIZE_BAR_THICKNESS / 2,
top = tablePosition.y,
height = tableHeight,
width = RESIZE_BAR_THICKNESS;
editor.dom.add(getBody(), 'div',
generateBar(RESIZE_BAR_COL_CLASS, RESIZE_BAR_COL_CURSOR_STYLE,
left, top, height, width, RESIZE_BAR_COL_DATA_ATTRIBUTE, cellPosition.index));
});
}
// Get a matrix of the cells in each row and the rows in the table.
function getTableDetails(table) {
return Tools.map(table.rows, function(row) {
var cells = Tools.map(row.cells, function(cell) {
var rowspan = cell.hasAttribute('rowspan') ? parseInt(cell.getAttribute('rowspan'), 10) : 1;
var colspan = cell.hasAttribute('colspan') ? parseInt(cell.getAttribute('colspan'), 10) : 1;
return {
element: cell,
rowspan: rowspan,
colspan: colspan
};
});
return {
element: row,
cells: cells
};
});
}
// Get a grid model of the table.
function getTableGrid(tableDetails) {
function key(rowIndex, colIndex) {
return rowIndex + ',' + colIndex;
}
function getAt(rowIndex, colIndex) {
return access[key(rowIndex, colIndex)];
}
function getAllCells() {
var allCells = [];
Tools.each(rows, function(row) {
allCells = allCells.concat(row.cells);
});
return allCells;
}
function getAllRows() {
return rows;
}
var access = {};
var rows = [];
var maxRows = 0;
var maxCols = 0;
Tools.each(tableDetails, function(row, rowIndex) {
var currentRow = [];
Tools.each(row.cells, function(cell) {
var start = 0;
while (access[key(rowIndex, start)] !== undefined) {
start++;
}
var current = {
element: cell.element,
colspan: cell.colspan,
rowspan: cell.rowspan,
rowIndex: rowIndex,
colIndex: start
};
for (var i = 0; i < cell.colspan; i++) {
for (var j = 0; j < cell.rowspan; j++) {
var cr = rowIndex + j;
var cc = start + i;
access[key(cr, cc)] = current;
maxRows = Math.max(maxRows, cr + 1);
maxCols = Math.max(maxCols, cc + 1);
}
}
currentRow.push(current);
});
rows.push({
element: row.element,
cells: currentRow
});
});
return {
grid: {
maxRows: maxRows,
maxCols: maxCols
},
getAt: getAt,
getAllCells: getAllCells,
getAllRows: getAllRows
};
}
function range(start, end) {
var r = [];
for (var i = start; i < end; i++) {
r.push(i);
}
return r;
}
// Attempt to get a representative single block for this column.
// If we can't find a single block, all blocks in this row/column are spanned
// and we'll need to fallback to getting the first cell in the row/column.
function decide(getBlock, isSingle, getFallback) {
var inBlock = getBlock();
var singleInBlock;
for (var i = 0; i < inBlock.length; i++) {
if (isSingle(inBlock[i])) {
singleInBlock = inBlock[i];
}
}
return singleInBlock ? singleInBlock : getFallback();
}
// Attempt to get representative blocks for the width of each column.
function getColumnBlocks(tableGrid) {
var cols = range(0, tableGrid.grid.maxCols);
var rows = range(0, tableGrid.grid.maxRows);
return Tools.map(cols, function(col) {
function getBlock() {
var details = [];
for (var i = 0; i < rows.length; i++) {
var detail = tableGrid.getAt(i, col);
if (detail && detail.colIndex === col) {
details.push(detail);
}
}
return details;
}
function isSingle(detail) {
return detail.colspan === 1;
}
function getFallback() {
var item;
for (var i = 0; i < rows.length; i++) {
item = tableGrid.getAt(i, col);
if (item) {
return item;
}
}
return null;
}
return decide(getBlock, isSingle, getFallback);
});
}
// Attempt to get representative blocks for the height of each row.
function getRowBlocks(tableGrid) {
var cols = range(0, tableGrid.grid.maxCols);
var rows = range(0, tableGrid.grid.maxRows);
return Tools.map(rows, function(row) {
function getBlock() {
var details = [];
for (var i = 0; i < cols.length; i++) {
var detail = tableGrid.getAt(row, i);
if (detail && detail.rowIndex === row) {
details.push(detail);
}
}
return details;
}
function isSingle(detail) {
return detail.rowspan === 1;
}
function getFallback() {
return tableGrid.getAt(row, 0);
}
return decide(getBlock, isSingle, getFallback);
});
}
// Draw resize bars over the left/right (ltr/rtl) or top side locations of the cells to measure.
// This is the location of the borders we need to draw over.
function drawBars(table) {
var tableDetails = getTableDetails(table);
var tableGrid = getTableGrid(tableDetails);
var rows = getRowBlocks(tableGrid);
var cols = getColumnBlocks(tableGrid);
var tablePosition = editor.dom.getPos(table);
var rowPositions = rows.length > 0 ? findPositions(getTopEdge, getBottomEdge, rows) : [];
var colPositions = cols.length > 0 ? findPositions(getInnerEdge, getOuterEdge, cols) : [];
drawRows(rowPositions, table.offsetWidth, tablePosition);
drawCols(colPositions, table.offsetHeight, tablePosition);
}
// Attempt to deduce the width/height of a column/row that has more than one cell spanned.
function deduceSize(deducables, index, isPercentageBased, table) {
if (index < 0 || index >= deducables.length - 1) {
return "";
}
var current = deducables[index];
if (current) {
current = {
value: current,
delta: 0
};
} else {
var reversedUpToIndex = deducables.slice(0, index).reverse();
for (var i = 0; i < reversedUpToIndex.length; i++) {
if (reversedUpToIndex[i]) {
current = {
value: reversedUpToIndex[i],
delta: i + 1
};
}
}
}
var next = deducables[index + 1];
if (next) {
next = {
value: next,
delta: 1
};
} else {
var rest = deducables.slice(index + 1);
for (var j = 0; j < rest.length; j++) {
if (rest[j]) {
next = {
value: rest[j],
delta: j + 1
};
}
}
}
var extras = next.delta - current.delta;
var pixelWidth = Math.abs(next.value - current.value) / extras;
return isPercentageBased ? pixelWidth / getComputedStyleSize(table, 'width') * 100 : pixelWidth;
}
function getStyleOrAttrib(element, property) {
var sizeString = editor.dom.getStyle(element, property);
if (!sizeString) {
sizeString = editor.dom.getAttrib(element, property);
}
if (!sizeString) {
sizeString = editor.dom.getStyle(element, property, true);
}
return sizeString;
}
function getWidth(element, isPercentageBased, table) {
var widthString = getStyleOrAttrib(element, 'width');
var widthNumber = parseInt(widthString, 10);
var getWidthFallback = isPercentageBased ? getPercentageWidthFallback(element, table) : getComputedStyleSize(element, 'width');
// If this is percentage based table, but this cell isn't percentage based.
// Or if this is a pixel based table, but this cell isn't pixel based.
if (isPercentageBased && !isPercentageBasedSize(widthString) ||
!isPercentageBased && !isPixelBasedSize(widthString)) {
// set the widthnumber to 0
widthNumber = 0;
}
return !isNaN(widthNumber) && widthNumber > 0 ?
widthNumber : getWidthFallback;
}
// Attempt to get the css width from column representative cells.
function getWidths(tableGrid, isPercentageBased, table) {
var cols = getColumnBlocks(tableGrid);
var backups = Tools.map(cols, function(col) {
return getInnerEdge(col.colIndex, col.element).x;
});
var widths = [];
for (var i = 0; i < cols.length; i++) {
var span = cols[i].element.hasAttribute('colspan') ? parseInt(cols[i].element.getAttribute('colspan'), 10) : 1;
// Deduce if the column has colspan of more than 1
var width = span > 1 ? deduceSize(backups, i) : getWidth(cols[i].element, isPercentageBased, table);
// If everything's failed and we still don't have a width
width = width ? width : RESIZE_MINIMUM_WIDTH;
widths.push(width);
}
return widths;
}
// Attempt to get the pixel height from a cell.
function getPixelHeight(element) {
var heightString = getStyleOrAttrib(element, 'height');
var heightNumber = parseInt(heightString, 10);
if (isPercentageBasedSize(heightString)) {
heightNumber = 0;
}
return !isNaN(heightNumber) && heightNumber > 0 ?
heightNumber : getComputedStyleSize(element, 'height');
}
// Attempt to get the css height from row representative cells.
function getPixelHeights(tableGrid) {
var rows = getRowBlocks(tableGrid);
var backups = Tools.map(rows, function(row) {
return getTopEdge(row.rowIndex, row.element).y;
});
var heights = [];
for (var i = 0; i < rows.length; i++) {
var span = rows[i].element.hasAttribute('rowspan') ? parseInt(rows[i].element.getAttribute('rowspan'), 10) : 1;
var height = span > 1 ? deduceSize(backups, i) : getPixelHeight(rows[i].element);
height = height ? height : RESIZE_MINIMUM_HEIGHT;
heights.push(height);
}
return heights;
}
// Determine how much each column's css width will need to change.
// Sizes = result = pixels widths OR percentage based widths
function determineDeltas(sizes, column, step, min, isPercentageBased) {
var result = sizes.slice(0);
function generateZeros(array) {
return Tools.map(array, function() {
return 0;
});
}
function onOneColumn() {
var deltas;
if (isPercentageBased) {
// If we have one column in a percent based table, that column should be 100% of the width of the table.
deltas = [100 - result[0]];
} else {
var newNext = Math.max(min, result[0] + step);
deltas = [newNext - result[0]];
}
return deltas;
}
function onLeftOrMiddle(index, next) {
var startZeros = generateZeros(result.slice(0, index));
var endZeros = generateZeros(result.slice(next + 1));
var deltas;
if (step >= 0) {
var newNext = Math.max(min, result[next] - step);
deltas = startZeros.concat([step, newNext - result[next]]).concat(endZeros);
} else {
var newThis = Math.max(min, result[index] + step);
var diffx = result[index] - newThis;
deltas = startZeros.concat([newThis - result[index], diffx]).concat(endZeros);
}
return deltas;
}
function onRight(previous, index) {
var startZeros = generateZeros(result.slice(0, index));
var deltas;
if (step >= 0) {
deltas = startZeros.concat([step]);
} else {
var size = Math.max(min, result[index] + step);
deltas = startZeros.concat([size - result[index]]);
}
return deltas;
}
var deltas;
if (sizes.length === 0) { // No Columns
deltas = [];
} else if (sizes.length === 1) { // One Column
deltas = onOneColumn();
} else if (column === 0) { // Left Column
deltas = onLeftOrMiddle(0, 1);
} else if (column > 0 && column < sizes.length - 1) { // Middle Column
deltas = onLeftOrMiddle(column, column + 1);
} else if (column === sizes.length - 1) { // Right Column
deltas = onRight(column - 1, column);
} else {
deltas = [];
}
return deltas;
}
function total(start, end, measures) {
var r = 0;
for (var i = start; i < end; i++) {
r += measures[i];
}
return r;
}
// Combine cell's css widths to determine widths of colspan'd cells.
function recalculateWidths(tableGrid, widths) {
var allCells = tableGrid.getAllCells();
return Tools.map(allCells, function(cell) {
var width = total(cell.colIndex, cell.colIndex + cell.colspan, widths);
return {
element: cell.element,
width: width,
colspan: cell.colspan
};
});
}
// Combine cell's css heights to determine heights of rowspan'd cells.
function recalculateCellHeights(tableGrid, heights) {
var allCells = tableGrid.getAllCells();
return Tools.map(allCells, function(cell) {
var height = total(cell.rowIndex, cell.rowIndex + cell.rowspan, heights);
return {
element: cell.element,
height: height,
rowspan: cell.rowspan
};
});
}
// Calculate row heights.
function recalculateRowHeights(tableGrid, heights) {
var allRows = tableGrid.getAllRows();
return Tools.map(allRows, function(row, i) {
return {
element: row.element,
height: heights[i]
};
});
}
function isPercentageBasedSize(size) {
return percentageBasedSizeRegex.test(size);
}
function isPixelBasedSize(size) {
return pixelBasedSizeRegex.test(size);
}
// Adjust the width of the column of table at index, with delta.
function adjustWidth(table, delta, index) {
var tableDetails = getTableDetails(table);
var tableGrid = getTableGrid(tableDetails);
function setSizes(newSizes, styleExtension) {
Tools.each(newSizes, function(cell) {
editor.dom.setStyle(cell.element, 'width', cell.width + styleExtension);
editor.dom.setAttrib(cell.element, 'width', null);
});
}
function getNewTablePercentWidth() {
return index < tableGrid.grid.maxCols - 1 ? getCurrentTablePercentWidth(table) :
getCurrentTablePercentWidth(table) + getTablePercentDelta(table, delta);
}
function getNewTablePixelWidth() {
return index < tableGrid.grid.maxCols - 1 ? getComputedStyleSize(table, 'width') :
getComputedStyleSize(table, 'width') + delta;
}
function setTableSize(newTableWidth, styleExtension, isPercentBased) {
if (index == tableGrid.grid.maxCols - 1 || !isPercentBased) {
editor.dom.setStyle(table, 'width', newTableWidth + styleExtension);
editor.dom.setAttrib(table, 'width', null);
}
}
var percentageBased = isPercentageBasedSize(table.width) ||
isPercentageBasedSize(table.style.width);
var widths = getWidths(tableGrid, percentageBased, table);
var step = percentageBased ? getCellPercentDelta(table, delta) : delta;
// TODO: change the min for percentage maybe?
var deltas = determineDeltas(widths, index, step, RESIZE_MINIMUM_WIDTH, percentageBased, table);
var newWidths = [];
for (var i = 0; i < deltas.length; i++) {
newWidths.push(deltas[i] + widths[i]);
}
var newSizes = recalculateWidths(tableGrid, newWidths);
var styleExtension = percentageBased ? '%' : 'px';
var newTableWidth = percentageBased ? getNewTablePercentWidth() :
getNewTablePixelWidth();
editor.undoManager.transact(function() {
setSizes(newSizes, styleExtension);
setTableSize(newTableWidth, styleExtension, percentageBased);
});
}
// Adjust the height of the row of table at index, with delta.
function adjustHeight(table, delta, index) {
var tableDetails = getTableDetails(table);
var tableGrid = getTableGrid(tableDetails);
var heights = getPixelHeights(tableGrid);
var newHeights = [], newTotalHeight = 0;
for (var i = 0; i < heights.length; i++) {
newHeights.push(i === index ? delta + heights[i] : heights[i]);
newTotalHeight += newTotalHeight[i];
}
var newCellSizes = recalculateCellHeights(tableGrid, newHeights);
var newRowSizes = recalculateRowHeights(tableGrid, newHeights);
editor.undoManager.transact(function() {
Tools.each(newRowSizes, function(row) {
editor.dom.setStyle(row.element, 'height', row.height + 'px');
editor.dom.setAttrib(row.element, 'height', null);
});
Tools.each(newCellSizes, function(cell) {
editor.dom.setStyle(cell.element, 'height', cell.height + 'px');
editor.dom.setAttrib(cell.element, 'height', null);
});
editor.dom.setStyle(table, 'height', newTotalHeight + 'px');
editor.dom.setAttrib(table, 'height', null);
});
}
function scheduleDelayedDropEvent() {
delayDrop = setTimeout(function() {
drop();
}, 200);
}
function cancelDelayedDropEvent() {
clearTimeout(delayDrop);
}
function getBlockerElement() {
var blocker = document.createElement('div');
blocker.setAttribute('style', 'margin: 0; ' +
'padding: 0; ' +
'position: fixed; ' +
'left: 0px; ' +
'top: 0px; ' +
'height: 100%; ' +
'width: 100%;');
blocker.setAttribute('data-mce-bogus', 'all');
return blocker;
}
function bindBlockerEvents(blocker, dragHandler) {
editor.dom.bind(blocker, 'mouseup', function() {
drop();
});
editor.dom.bind(blocker, 'mousemove', function(e) {
cancelDelayedDropEvent();
if (dragging) {
dragHandler(e);
}
});
editor.dom.bind(blocker, 'mouseout', function() {
scheduleDelayedDropEvent();
});
}
function drop() {
editor.dom.remove(blockerElement);
if (dragging) {
editor.dom.removeClass(dragBar, RESIZE_BAR_DRAGGING_CLASS);
dragging = false;
var index, delta;
if (isCol(dragBar)) {
var initialLeft = parseInt(editor.dom.getAttrib(dragBar, RESIZE_BAR_COL_DATA_INITIAL_LEFT_ATTRIBUTE), 10);
var newLeft = editor.dom.getPos(dragBar).x;
index = parseInt(editor.dom.getAttrib(dragBar, RESIZE_BAR_COL_DATA_ATTRIBUTE), 10);
delta = isRtl() ? initialLeft - newLeft : newLeft - initialLeft;
adjustWidth(hoverTable, delta, index);
} else if (isRow(dragBar)) {
var initialTop = parseInt(editor.dom.getAttrib(dragBar, RESIZE_BAR_ROW_DATA_INITIAL_TOP_ATTRIBUTE), 10);
var newTop = editor.dom.getPos(dragBar).y;
index = parseInt(editor.dom.getAttrib(dragBar, RESIZE_BAR_ROW_DATA_ATTRIBUTE), 10);
delta = newTop - initialTop;
adjustHeight(hoverTable, delta, index);
}
refreshBars(hoverTable);
editor.nodeChanged();
}
}
function setupBaseDrag(bar, dragHandler) {
blockerElement = blockerElement ? blockerElement : getBlockerElement();
dragging = true;
editor.dom.addClass(bar, RESIZE_BAR_DRAGGING_CLASS);
dragBar = bar;
bindBlockerEvents(blockerElement, dragHandler);
editor.dom.add(getBody(), blockerElement);
}
function isCol(target) {
return editor.dom.hasClass(target, RESIZE_BAR_COL_CLASS);
}
function isRow(target) {
return editor.dom.hasClass(target, RESIZE_BAR_ROW_CLASS);
}
function colDragHandler(event) {
lastX = lastX !== undefined ? lastX : event.clientX; // we need a firstX
var deltaX = event.clientX - lastX;
lastX = event.clientX;
var oldLeft = editor.dom.getPos(dragBar).x;
editor.dom.setStyle(dragBar, 'left', oldLeft + deltaX + 'px');
}
function rowDragHandler(event) {
lastY = lastY !== undefined ? lastY : event.clientY;
var deltaY = event.clientY - lastY;
lastY = event.clientY;
var oldTop = editor.dom.getPos(dragBar).y;
editor.dom.setStyle(dragBar, 'top', oldTop + deltaY + 'px');
}
function setupColDrag(bar) {
lastX = undefined;
setupBaseDrag(bar, colDragHandler);
}
function setupRowDrag(bar) {
lastY = undefined;
setupBaseDrag(bar, rowDragHandler);
}
function mouseDownHandler(e) {
var target = e.target, body = editor.getBody();
// Since this code is working on global events we need to work on a global hoverTable state
// and make sure that the state is correct according to the events fired
if (!editor.$.contains(body, hoverTable) && hoverTable !== body) {
return;
}
if (isCol(target)) {
e.preventDefault();
var initialLeft = editor.dom.getPos(target).x;
editor.dom.setAttrib(target, RESIZE_BAR_COL_DATA_INITIAL_LEFT_ATTRIBUTE, initialLeft);
setupColDrag(target);
} else if (isRow(target)) {
e.preventDefault();
var initialTop = editor.dom.getPos(target).y;
editor.dom.setAttrib(target, RESIZE_BAR_ROW_DATA_INITIAL_TOP_ATTRIBUTE, initialTop);
setupRowDrag(target);
}
}
editor.on('init', function() {
// Needs to be like this for inline mode, editor.on does not bind to elements in the document body otherwise
editor.dom.bind(getBody(), 'mousedown', mouseDownHandler);
});
// If we're updating the table width via the old mechanic, we need to update the constituent cells' widths/heights too.
editor.on('ObjectResized', function(e) {
var table = e.target;
if (table.nodeName === 'TABLE') {
var newCellSizes = [];
Tools.each(table.rows, function(row) {
Tools.each(row.cells, function(cell) {
var width = editor.dom.getStyle(cell, 'width', true);
newCellSizes.push({
cell: cell,
width: width
});
});
});
Tools.each(newCellSizes, function(newCellSize) {
editor.dom.setStyle(newCellSize.cell, 'width', newCellSize.width);
editor.dom.setAttrib(newCellSize.cell, 'width', null);
});
}
});
editor.on('mouseover', function(e) {
if (!dragging) {
var tableElement = editor.dom.getParent(e.target, 'table');
if (e.target.nodeName === 'TABLE' || tableElement) {
hoverTable = tableElement;
refreshBars(tableElement);
}
}
});
// Prevents the user from moving the caret inside the resize bars on Chrome
// Only does it on arrow keys since clearBars might be an epxensive operation
// since it's querying the DOM
editor.on('keydown', function(e) {
switch (e.keyCode) {
case VK.LEFT:
case VK.RIGHT:
case VK.UP:
case VK.DOWN:
clearBars();
break;
}
});
editor.on('remove', function() {
clearBars();
editor.dom.unbind(getBody(), 'mousedown', mouseDownHandler);
});
return {
adjustWidth: adjustWidth,
adjustHeight: adjustHeight,
clearBars: clearBars,
drawBars: drawBars,
determineDeltas: determineDeltas,
getTableGrid: getTableGrid,
getTableDetails: getTableDetails,
getWidths: getWidths,
getPixelHeights: getPixelHeights,
isPercentageBasedSize: isPercentageBasedSize,
isPixelBasedSize: isPixelBasedSize,
recalculateWidths: recalculateWidths,
recalculateCellHeights: recalculateCellHeights,
recalculateRowHeights: recalculateRowHeights
};
};
});