• Signup
  • Hosting Hub
  • Publish with Us
  • Newsroom
  • Explore Us
  • Login
  • SEO Tutor
  • |
  • Indoor Herbs
  • |
  • b2b Skills
J
HARAPHULA
OneStop Shop of Information

Updates

  • The Role of Gaming in Education: How Games are used to Teach and Engage
    •
  • Mobile Repairing Course in Rawalpindi – Learn to Fix iPhones and Android Phones
    •
  • The Role of Pricing Procedures in SAP SD and their Configuration
    •
  • Top-rated best Commerce Coaching in Patna for 11 and 12
    •
  • BCA Distance Education in India – Best Universities, Fees and Career Guide
    •
  • Why Pursuing a Cisco Certification Course Can Transform your IT Career?
    •
  • The 9 Things you must know to Prepare for IIT JEE
    •
  • CMA US – Your Pathway to a Rewarding Career in Management Accounting
    •
  • Top 8 Advantages of Taking the IIT JAM Exam
    •
  • How LMS Tools Empower Collaborative Learning Experiences?
    •
  • Explore the Leading Computer Teacher Training Diploma Courses in 2025
    •
  • How to Choose the best ADCA Institute for your Career Goals?
    •
  • Is CCA the Right Course for Non-IT Background Students?
    •
  • Your Guide to MBBS in Russia – Eligibility, Fees, and Admission
    •
  • Understanding the Core Concepts of ADCA
    •

Design MS-Excel like Table using KineticJS on HTML5 Canvas?

KineticJS Examples
May 13, 2016
5 (1 votes)
Design MS-Excel like Table using KineticJS on HTML5 Canvas? Design MS-Excel like Table using KineticJS on HTML5 Canvas?
5 5 78
Making you Earn. Developing Web2 Blogs with CPM Ads

During my software development experiences I never faced such a challenging stuff to design a table like Microsoft word or excel. Recently with my Ex-employer in a project I found me to design a table like MS-Word. The skills I used here are KineticJS, HTML5 & Jquery.

A table looks very easy to Operate but during the development of a table I faced many critical logical games to handle. In this article I am sharing the complete class for creating a table. The JavaScript class I am sharing here is TableShape which accepts row & column numbers with KineticJS stage & layer. In real-time this class is capable to draw table for you depending upon the row & column values. To implement this you need to copy this js file to your application & while creating the instance for the class TableShape you need to pass parameters only.

In the below TableShape class I have all the ready mate method to do operation with a table. createCell is the method which creates cell for table. Used Splitters to handle cells & rows adjustments. To insert a row into the table we created a function insertRow(). Where by passing the index you can add a row to your table. To delete a row in this class we implemented deleteRow() function. This function accepts index of the row which one you want to delete. Depending upon the index this external function is capable to delete row from your table. Similar to insertRow() & deleteRow() we have insertColumn() & deleteColumn() method. Using getHeight() & getWidth() external function you can retrieve table width & height in your class. During operations to retrieve the x & y positions of table in this class we declared two additional methods getX() & getY(). These methods are added to the exports array of this method. Which you can easily access from your class. Using setWidth() & setHeight() functions you can set table width & height from your external class. To select the table or it’s cells this class contains Select & Deselect methods. You just need to call them from your class to use. Like this there are plenty of functionality you can get with this class.

This class is well tested by our QA team. I don’t think you will get any problems to implement this class. What problems we faced during a table design I don’t want to give you the same pain. Let us reuse the code.

tableShape.js

/*Table Cell related default values*/
var DEFAULT_CELL_STROKE_WIDTH = 1;
var DEFAULT_CELL_WIDTH = 200;
var DEFAULT_CELL_HEIGHT = 100;
var MIN_CELL_DIM = 25;
var DEFAULT_SPANNER_WIDTH = 5;
/*Table Slitter Default Stroke & Width*/
var DEFAULT_SPLITTER_STROKE = "#000000";
var DEFAULT_SPLITTER_WIDTH = 3;

var DEFAULT_SPANNER_STROKE = "darkgray";
/*Table default cell settings*/
var DEFAULT_CELL_FILL = "#FFFFFF";
var DEFAULT_CELL_STROKE = "#000000";
var DEFAULT_CELL_STROKE_SELECTED = "#000000";

var TableShape = function (totalRows, totalColumns, stage, layer) {

var exports = {};
var _rows = null;
var _columns = null;
var _stage = null;
var _tbllayer = null;
var _tblgroup = null;
var _embeddedShapes = [];
var _tableIndex = [];

/* Initial values related to Table */
function init() {

_tbllayer = layer;
_tblgroup = new Kinetic.Group({
x: -(_columns / 2) * DEFAULT_CELL_WIDTH,
y: -(_rows / 2) * DEFAULT_CELL_HEIGHT,
width: _columns * DEFAULT_CELL_WIDTH,
height: _rows * DEFAULT_CELL_HEIGHT,
draggable: true
});

var xDisp = (2 * DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH);
var yDisp = (2 * DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH);

for (var row = 0; row < _rows; row++) {

_tableIndex[row] = new Array();

for (var col = 0; col < _columns; col++) {

var box = createCell((col == 0) ? (2 * DEFAULT_CELL_STROKE_WIDTH) : (col * DEFAULT_CELL_WIDTH) + (col * xDisp),
(row == 0) ? (2 * DEFAULT_CELL_STROKE_WIDTH) : (row * DEFAULT_CELL_HEIGHT) + (row * yDisp),
DEFAULT_CELL_WIDTH, DEFAULT_CELL_HEIGHT);

_tblgroup.add(box);
_tableIndex[row][col] = box;
}
}

//nameCells();
createSpanners(true);

_tblgroup.on('mouseout', function (e) {
document.body.style.cursor = 'default';
});

_tblgroup.on('click', function (e) {

if (e.shape.getId() != "tableCell" &&
e.shape.getId() != "vSplitter" && e.shape.getId() != "hSplitter" &&
e.shape.getName() != "spanLineCol" && e.shape.getName() != "spanLineRow" &&
event.shiftKey) {
e.shape.parent.setX(_tblgroup.parent.getX() + e.shape.parent.getX() - _tblgroup.parent.getOffset().x);
e.shape.parent.setY(_tblgroup.parent.getY() + e.shape.parent.getY() - _tblgroup.parent.getOffset().y);
e.shape.parent.moveTo(_tbllayer);
e.shape.parentTable = null;
}
else {
// table in table
if (e.shape.getId() == "tableCell" && e.shape.parent != _tblgroup && event.shiftKey) {
//Nothing ToDo
}
else {
groupEmbeddedShapes();
}
}
});
_tblgroup.on('dblclick', function (e) {
});

_tbllayer.add(_tblgroup);
_tblgroup._id = exports._id;
selectCell(_tableIndex[0][0]);
_stage.draw();
}

/* Funtion to Create Cells in Table */
function createCell(cellX, cellY, cellWidth, cellHeight, cellName) {

var cell = new Kinetic.Rect({
id: "tableCell",
name: cellName ? cellName : randomString(5),
x: cellX,
y: cellY,
width: cellWidth,
height: cellHeight,
fill: DEFAULT_CELL_FILL,
stroke: DEFAULT_CELL_STROKE,
strokeWidth: DEFAULT_CELL_STROKE_WIDTH
});

cell.on('click', function (evt) {
selectCell(this);

if (event.ctrlLeft) {
addSplitter(cell, "vertical");
}

if (event.altLeft) {
addSplitter(cell, "horizontal");
}
});

cell.on('mouseover', function (e) {
document.body.style.cursor = 'crosshair';
});

return cell;
}

function updateSplitters(cell) {

if (cell.vSplitters) {

for (var i = 0; i < cell.vSplitters.length; i++) {
var vSplit = cell.vSplitters[i];
var points = vSplit.getPoints();

var curSpltrX = points[0].x + vSplit.getX();

if (curSpltrX < cell.getX()) {
vSplit.setX(cell.getX() - points[0].x + DEFAULT_SPANNER_WIDTH);
}

if (curSpltrX > cell.getX() + cell.getWidth()) {
vSplit.setX(cell.getX() + cell.getWidth() - points[0].x - DEFAULT_SPANNER_WIDTH);
}
points[0].y = cell.getY();
points[1].y = cell.getY() + cell.getHeight();
vSplit.setPoints(points);
vSplit.setY(cell.getY() - points[0].y);
}
}

if (cell.hSplitters) {
for (var i = 0; i < cell.hSplitters.length; i++) {
var hSplit = cell.hSplitters[i];
var points = hSplit.getPoints();

var curSpltrY = points[0].y + hSplit.getY();

if (curSpltrY < cell.getY()) {
hSplit.setY(cell.getY() - points[0].y + DEFAULT_SPANNER_WIDTH);
}

if (curSpltrY > cell.getY() + cell.getHeight()) {
hSplit.setY(cell.getY() + cell.getHeight() - points[0].y - DEFAULT_SPANNER_WIDTH);
}
points[0].x = cell.getX();
points[1].x = cell.getX() + cell.getWidth();
hSplit.setPoints(points);
hSplit.setX(cell.getX() - points[0].x);
}
}
}

function addSplitter(cell, type, evt) {

switch (type) {
case "vertical":
var x, y;

if (evt && evt.x) {
transformEventCoordsToCellCoords(cell, evt);
x = cell.getX() + evt.x;
y = cell.getY();
}
else {
x = cell.getX() + cell.getWidth() / 2;
y = cell.getY();
}

var lineVSplitter = new Kinetic.Line({
id: "vSplitter",
name: cell.getName() + "vSplitter",
points: [x, y, x, y + cell.getHeight()],
stroke: cell.getStroke(),
strokeWidth: DEFAULT_SPLITTER_WIDTH,
draggable: true,
dragOnTop: false
});

lineVSplitter.on('mouseover', function (e) {
$("body").css("cursor", "col-resize");
});

lineVSplitter.on('dragmove', function (e) {
this.setY(0);

var curSpltrX = this.getPoints()[0].x + this.getX();

if (curSpltrX < cell.getX()) {
this.setX(cell.getX() - this.getPoints()[0].x + DEFAULT_SPANNER_WIDTH);
return;
}

if (curSpltrX > cell.getX() + cell.getWidth()) {
this.setX(cell.getX() + cell.getWidth() - this.getPoints()[0].x - DEFAULT_SPANNER_WIDTH);
return;
}
});

lineVSplitter.on('mouseout', function (e) {
$("body").css("cursor", "default");
});

lineVSplitter.on("mousedown dragstart", function () {
_tblgroup.setDraggable(false);
_tblgroup.parent.setDraggable(false);
});

lineVSplitter.on("mouseup dragend", function () {
_tblgroup.setDraggable(true);
_tblgroup.parent.setDraggable(true);
});

_tblgroup.add(lineVSplitter);
if (!cell.vSplitters) cell.vSplitters = [];
cell.vSplitters.push(lineVSplitter);
break;

case "horizontal":
var x, y;

if (evt && evt.y) {
transformEventCoordsToCellCoords(cell, evt);
x = cell.getX();
y = cell.getY() + evt.y;
}
else {
x = cell.getX();
y = cell.getY() + cell.getHeight() / 2;
}

var lineHSplitter = new Kinetic.Line({
id: "hSplitter",
name: cell.getName() + "hSplitter",
points: [x, y, x + cell.getWidth(), y],
stroke: cell.getStroke(),
strokeWidth: DEFAULT_SPLITTER_WIDTH,
draggable: true,
dragOnTop: false
});

lineHSplitter.on('mouseover', function (e) {
$("body").css("cursor", "row-resize");
});

lineHSplitter.on('dragmove', function (e) {
this.setX(0);

var curSpltrY = this.getPoints()[0].y + this.getY();

if (curSpltrY < cell.getY()) {
this.setY(cell.getY() - this.getPoints()[0].y + DEFAULT_SPANNER_WIDTH);
return;
}

if (curSpltrY > cell.getY() + cell.getHeight()) {
this.setY(cell.getY() + cell.getHeight() - this.getPoints()[0].y - DEFAULT_SPANNER_WIDTH);
return;
}
});

lineHSplitter.on('mouseout', function (e) {
$("body").css("cursor", "default");
});

lineHSplitter.on("mousedown dragstart", function () {
_tblgroup.setDraggable(false);
_tblgroup.parent.setDraggable(false);
});

lineHSplitter.on("mouseup dragend", function () {
_tblgroup.setDraggable(true);
_tblgroup.parent.setDraggable(true);
});

_tblgroup.add(lineHSplitter);
if (!cell.hSplitters) cell.hSplitters = [];
cell.hSplitters.push(lineHSplitter);
break;

default:
break;
}
}

function removeSplitters(cell, type, evt) {

switch (type) {
case "vertical":

if (cell.vSplitters) {
if (evt && evt.x) {
transformEventCoordsToCellCoords(cell, evt);
var nearest = 0;

for (var i = 1; i < cell.vSplitters.length; i++) {
var vSplit = cell.vSplitters[i];
var vSplitNearest = cell.vSplitters[nearest];
var splitX = vSplit.getPoints()[0].x + vSplit.getX();
var splitXnearest = vSplitNearest.getPoints()[0].x + vSplitNearest.getX();

if (Math.abs(evt.x - splitXnearest) > Math.abs(evt.x - splitX)) {
nearest = i;
}
}

cell.vSplitters[nearest].remove();
cell.vSplitters.splice(nearest, 1);
if (0 == cell.vSplitters.length) cell.vSplitters = null;
}
else {
for (var i = 0; i < cell.vSplitters.length; i++) {
cell.vSplitters[i].remove();
}

cell.vSplitters = null;
}
}
break;

case "horizontal":
if (cell.hSplitters) {

if (evt && evt.y) {
transformEventCoordsToCellCoords(cell, evt);
var nearest = 0;

for (var i = 1; i < cell.hSplitters.length; i++) {
var hSplit = cell.hSplitters[i];
var hSplitNearest = cell.hSplitters[nearest];
var splitY = hSplit.getPoints()[0].y + hSplit.getY();
var splitYnearest = hSplitNearest.getPoints()[0].y + hSplitNearest.getY();

if (Math.abs(evt.y - splitYnearest) > Math.abs(evt.y - splitY)) {
nearest = i;
}
}

cell.hSplitters[nearest].remove();
cell.hSplitters.splice(nearest, 1);
if (0 == cell.hSplitters.length) cell.hSplitters = null;
}
else {
for (var i = 0; i < cell.hSplitters.length; i++) {
cell.hSplitters[i].remove();
}

cell.hSplitters = null;
}
}
break;

default:
break;
}
}

function moveSplitters(cell, disp) {

if (cell.vSplitters) {
for (var i = 0; i < cell.vSplitters.length; i++) {
cell.vSplitters[i].move(disp.x, disp.y);
}
}

if (cell.hSplitters) {
for (var i = 0; i < cell.hSplitters.length; i++) {
cell.hSplitters[i].move(disp.x, disp.y);
}
}

updateSplitters(cell);
}

function createSpanners(init) {

if (!init) {
// remove previous ones
var rowSpans = _tblgroup.get(".spanLineRow");

for (var i = 0; i < rowSpans.length; i++) {
rowSpans[i].remove();
}

var colSpans = _tblgroup.get(".spanLineCol");

for (var i = 0; i < colSpans.length; i++) {
colSpans[i].remove();
}
}

var row = 0;
for (var col = 1; col < _tableIndex[row].length; col++) {

var cell = _tableIndex[row][col];

var lineCol = new Kinetic.Line({
name: "spanLineCol",
id: col,
points: [cell.getX() - DEFAULT_SPANNER_WIDTH + (2 * DEFAULT_CELL_STROKE_WIDTH), cell.getY(),
cell.getX() - DEFAULT_SPANNER_WIDTH + (2 * DEFAULT_CELL_STROKE_WIDTH), exports.getHeight()],

stroke: DEFAULT_SPANNER_STROKE,
strokeWidth: DEFAULT_SPANNER_WIDTH,
dashArray: [DEFAULT_SPANNER_WIDTH, DEFAULT_SPANNER_WIDTH, DEFAULT_SPANNER_WIDTH, DEFAULT_SPANNER_WIDTH],
lineCap: 'round',
lineJoin: 'round',
draggable: true,
dragOnTop: false
});

lineCol.on('mouseover', function (e) {
$("body").css("cursor", "col-resize");
});

lineCol.on('dragmove', function (e) {
this.setY(0);
spanColumn(e.shape);
});

lineCol.on('mouseout', function (e) {
$("body").css("cursor", "default");
});

lineCol.on("mousedown dragstart", function () {
_tblgroup.setDraggable(false);
_tblgroup.parent.setDraggable(false);
});

lineCol.on("mouseup dragend", function () {
_tblgroup.setDraggable(true);
_tblgroup.parent.setDraggable(true);
});

_tblgroup.add(lineCol);
}

var col = 0;
for (var row = 1; row < _tableIndex.length; row++) {

var cell = _tableIndex[row][col];

var lineRow = new Kinetic.Line({
name: "spanLineRow",
id: row,
points: [cell.getX(), cell.getY() - DEFAULT_SPANNER_WIDTH + (2 * DEFAULT_CELL_STROKE_WIDTH),
exports.getWidth(), cell.getY() - DEFAULT_SPANNER_WIDTH + (2 * DEFAULT_CELL_STROKE_WIDTH)],
stroke: DEFAULT_SPANNER_STROKE,
strokeWidth: DEFAULT_SPANNER_WIDTH,
dashArray: [DEFAULT_SPANNER_WIDTH, DEFAULT_SPANNER_WIDTH, DEFAULT_SPANNER_WIDTH, DEFAULT_SPANNER_WIDTH],
lineCap: 'round',
lineJoin: 'round',
draggable: true,
dragOnTop: false
});

lineRow.on('mouseover', function (e) {
$("body").css("cursor", "row-resize");
});

lineRow.on('dragmove', function (e) {
this.setX(0);
spanRow(e.shape);
});

lineRow.on('mouseout', function (e) {
$("body").css("cursor", "default");
});

lineRow.on("mousedown dragstart", function () {
_tblgroup.setDraggable(false);
_tblgroup.parent.setDraggable(false);
});

lineRow.on("mouseup dragend", function () {
_tblgroup.setDraggable(true);
_tblgroup.parent.setDraggable(true);
});

_tblgroup.add(lineRow);
}

if (exports.selectedCell) {
exports.selectedCell.show();
}
}

function spanColumn(spanner) {

var col = Number(spanner.getId());
var curSpanX = spanner.getPoints()[0].x + spanner.getX();

for (var row = 0; row < _tableIndex.length; row++) {

var lCell = _tableIndex[row][col - 1];
var rCell = _tableIndex[row][col];

if (lCell.getWidth() <= MIN_CELL_DIM && (curSpanX - DEFAULT_SPANNER_WIDTH) <= (lCell.getX() + lCell.getWidth())) {
spanner.setX((lCell.getX() + lCell.getWidth() + (4 * DEFAULT_CELL_STROKE_WIDTH)) - spanner.getPoints()[0].x);
return;
}

if (rCell.getWidth() <= MIN_CELL_DIM && curSpanX >= rCell.getX()) {
spanner.setX((rCell.getX() - (4 * DEFAULT_CELL_STROKE_WIDTH)) - spanner.getPoints()[0].x);
return;
}

var diff = curSpanX - rCell.getX() + (4 * DEFAULT_CELL_STROKE_WIDTH);

lCell.setWidth(lCell.getWidth() + diff);
rCell.setWidth(rCell.getWidth() - diff);

var embShapes = _tblgroup.get("." + rCell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].setX(embShapes[i].getX() + diff);
}

updateSplitters(lCell);
updateSplitters(rCell);
}
}

function spanRow(spanner) {

var row = Number(spanner.getId());
var curSpanY = spanner.getPoints()[0].y + spanner.getY();

for (var col = 0; col < _tableIndex[row].length; col++) {

var tCell = _tableIndex[row - 1][col];
var bCell = _tableIndex[row][col];

if (tCell.getHeight() <= MIN_CELL_DIM && (curSpanY - DEFAULT_SPANNER_WIDTH) <= (tCell.getY() + tCell.getHeight())) {
spanner.setY((tCell.getY() + tCell.getHeight() + (4 * DEFAULT_CELL_STROKE_WIDTH)) - spanner.getPoints()[0].y);
return;
}

if (bCell.getHeight() <= MIN_CELL_DIM && curSpanY >= bCell.getY()) {
spanner.setY((bCell.getY() - (4 * DEFAULT_CELL_STROKE_WIDTH)) - spanner.getPoints()[0].y);
return;
}

var diff = curSpanY - bCell.getY() + (4 * DEFAULT_CELL_STROKE_WIDTH);

tCell.setHeight(tCell.getHeight() + diff);
bCell.setHeight(bCell.getHeight() - diff);

var embShapes = _tblgroup.get("." + bCell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].setY(embShapes[i].getY() + diff);
}

updateSplitters(tCell);
updateSplitters(bCell);
}
}

/* Function to Select Indivisual Cell in Table*/
function selectCell(cell) {

if (exports.selectedCell && exports.selectedCell.sCell() == cell) return;

if (exports.selectedCell) {
exports.selectedCell.hide();
}
exports.selectedCell = new SelectedCell(cell, null);
exports.selectedCell.show();
_stage.draw();
}

function selectTable() {

if (exports.selectedCell) {
exports.selectedCell.hide();
}

exports.selectedCell = new SelectedCell(null, _tableIndex);
exports.selectedCell.show();
_stage.draw();
}

function resizeRowSpanners(diff, bLeft) {

var rowSpans = _tblgroup.get(".spanLineRow");

for (var i = 0; i < rowSpans.length; i++) {
rowSpans[i].attrs.points[1].x += diff;
}

if (bLeft) {
var colSpans = _tblgroup.get(".spanLineCol");

for (var i = 0; i < colSpans.length; i++) {
colSpans[i].attrs.points[0].x += diff;
colSpans[i].attrs.points[1].x += diff;
}
}

_tblgroup.setWidth(_tblgroup.getWidth() + diff);
}

function resizeColSpanners(diff, bTop) {
var colSpans = _tblgroup.get(".spanLineCol");

for (var i = 0; i < colSpans.length; i++) {
colSpans[i].attrs.points[1].y += diff;
}

if (bTop) {
var rowSpans = _tblgroup.get(".spanLineRow");

for (var i = 0; i < rowSpans.length; i++) {
rowSpans[i].attrs.points[0].y += diff;
rowSpans[i].attrs.points[1].y += diff;
}
}

_tblgroup.setHeight(_tblgroup.getHeight() + diff);
}

function groupEmbeddedShapes() {

var oldRot = _tblgroup.parent.getRotation();
_tblgroup.parent.setRotation(0);

for (var key in _embeddedShapes) {

if (_embeddedShapes.hasOwnProperty(key)) {
var shape = _embeddedShapes[key];
var oldChld = _tblgroup.children.length;

shape.moveTo(_tblgroup);

if (oldChld != _tblgroup.children.length) {

shape.setX(shape.getX() - _tblgroup.parent.getX() + _tblgroup.parent.getOffset().x);
shape.setY(shape.getY() - _tblgroup.parent.getY() + _tblgroup.parent.getOffset().y);

shape.setName("");
bInside = false;

for (var row = 0; row < _tableIndex.length && bInside == false; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
cell = _tableIndex[row][col];
if (exports.areShapesOverlapping(cell, shape)) {
shape.setName(cell.getName());
bInside = true;
break;
}
}
}
}

if (!bInside) {
shape.setX(_tblgroup.parent.getX() + shape.getX() - _tblgroup.parent.getOffset().x);
shape.setY(_tblgroup.parent.getY() + shape.getY() - _tblgroup.parent.getOffset().y);
shape.moveTo(_tbllayer);
}
}
}

_tblgroup.parent.setRotation(oldRot);
}

function transformEventCoordsToCellCoords(cell, evt) {

if (cell && evt) {
var m = cell.getAbsoluteTransform();
var n = new Kinetic.Transform();
n.multiply(m);
n.invert();
n.translate(evt.x, evt.y)
evt.x = n.getMatrix()[4];
evt.y = n.getMatrix()[5];
}
}

/* Function to insert Row into the Table */
exports.insertRow = function (index) {

if (index < 0) index = 0;
if (index == undefined || index >= _rows) index = _rows;

var row = new Array();

if (index >= _tableIndex.length) {
for (var col = 0; col < _tableIndex[index - 1].length; col++) {
var refCell = _tableIndex[index - 1][col];
var cell = createCell(refCell.getX(), refCell.getY() + DEFAULT_SPANNER_WIDTH + refCell.getHeight(), refCell.getWidth(), DEFAULT_CELL_HEIGHT);
row.push(cell);
_tblgroup.add(cell);
}

_tableIndex.splice(index, 0, row);
}
else {
for (var col = 0; col < _tableIndex[index].length; col++) {
var refCell = _tableIndex[index][col];
var cell = createCell(refCell.getX(), refCell.getY(), refCell.getWidth(), DEFAULT_CELL_HEIGHT);
row.push(cell);
_tblgroup.add(cell);
}

_tableIndex.splice(index, 0, row);

for (var rowInd = index + 1; rowInd < _tableIndex.length; rowInd++) {
for (var col = 0; col < _tableIndex[rowInd].length; col++) {
var cell = _tableIndex[rowInd][col];

// move linked shapes too
var embShapes = _tblgroup.get("." + cell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(0, DEFAULT_CELL_HEIGHT + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH);
}

moveSplitters(cell, { x: 0, y: DEFAULT_CELL_HEIGHT + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH });
}
}
}

_rows++;

createSpanners();
_stage.draw();
}

/* Function to delete Row from the Table */
exports.deleteRow = function (index) {

if (_rows == 1) return;

if (index == undefined) index = _rows - 1;

var diff = _tableIndex[index][0].getHeight();

for (var row = index; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {

var cell = _tableIndex[row][col];
var embShapes = _tblgroup.get("." + cell.getName());

if (row == index) {
// delete linked shapes too
for (var i = 0; i < embShapes.length; i++) {
embShapes[i].remove();
}

removeSplitters(cell, "vertical");
removeSplitters(cell, "horizontal");
}
else {
for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(0, -(diff + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH));
}

moveSplitters(cell, { x: 0, y: -(diff + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH) });
}
}
}

_tableIndex.splice(index, 1);
_rows--;

createSpanners();
_stage.draw();
}

/* Function to insert Column into the Table */
exports.insertColumn = function (index) {

if (index < 0) index = 0;
if (index == undefined || index >= _columns) index = _columns;

for (var row = 0; row < _tableIndex.length; row++) {

if (index >= _tableIndex[row].length) {

var refCell = _tableIndex[row][index - 1];
var cell = createCell(refCell.getX() + refCell.getWidth() + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH, refCell.getY(), DEFAULT_CELL_WIDTH, refCell.getHeight());
_tableIndex[row].push(cell);
_tblgroup.add(cell);
}
else {
var refCell = _tableIndex[row][index];
var newCell = createCell(refCell.getX(), refCell.getY(), DEFAULT_CELL_WIDTH, refCell.getHeight());
_tableIndex[row].splice(index, 0, newCell);
_tblgroup.add(newCell);

for (var colInd = index + 1; colInd < _tableIndex[row].length; colInd++) {
var cell = _tableIndex[row][colInd];

// move linked shapes too
var embShapes = _tblgroup.get("." + cell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(DEFAULT_CELL_WIDTH + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH, 0);
}

moveSplitters(cell, { x: DEFAULT_CELL_WIDTH + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH, y: 0 });
}
}
}

_columns++;
createSpanners();
_stage.draw();
}

/* Function to delete column from the Table */
exports.deleteColumn = function (index) {

if (_columns == 1) return;

if (index == undefined) index = _columns - 1;

var diff = _tableIndex[0][index].getWidth();

for (var row = 0; row < _tableIndex.length; row++) {
for (var col = index; col < _tableIndex[row].length; col++) {

var cell = _tableIndex[row][col];

var embShapes = _tblgroup.get("." + cell.getName());

if (col == index) {
// delete linked shapes too
for (var i = 0; i < embShapes.length; i++) {
embShapes[i].remove();
}

removeSplitters(cell, "vertical");
removeSplitters(cell, "horizontal");
}
else {
for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(-(diff + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH), 0);
}

moveSplitters(cell, { x: -(diff + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH), y: 0 });
}
}

_tableIndex[row].splice(index, 1);
}

_columns--;
createSpanners();
_stage.draw();
}

exports.rows = function () {
return _rows;
}

exports.columns = function () {
return _columns;
}

exports.group = function () {
return _tblgroup;
}

exports.getCell = function (row, col) {
if (row >= 0 && row < _rows && col >= 0 && col < _columns) {
return _tableIndex[row][col];
}
}

exports.addShape = function (shape) {

_embeddedShapes[shape._id] = shape;

shape.parentTable = exports;
}

exports.removeShape = function (shape) {

if (_embeddedShapes[shape._id]) {
delete _embeddedShapes[shape._id]
}
}

exports.getSelectedIndex = function () {

var cell = exports.selectedCell.sCell();

if (cell) {
for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
if (_tableIndex[row][col] == cell) {
return { row: row, column: col };
}
}
}
}

return null;
}

exports.update = function () {
groupEmbeddedShapes();
}

exports.initDone = function () {

if (_tblgroup.parent && _tblgroup.parent.getId() == "marquee") {
var borderLine = _tblgroup.parent.get(".borderLines")[0];

if (borderLine) {
borderLine.on("click", function (e) {
selectTable();
});
}
}
}

exports.splitCellVertical = function (row, col, evt) {
if (row >= 0 && row < _rows && col >= 0 && col < _columns) {
var cell = _tableIndex[row][col];

addSplitter(cell, "vertical", evt);
}
}

exports.mergeCellVertical = function (row, col, evt) {
if (row >= 0 && row < _rows && col >= 0 && col < _columns) {
var cell = _tableIndex[row][col];

removeSplitters(cell, "vertical", evt);
}
}

exports.splitCellHorizontal = function (row, col, evt) {
if (row >= 0 && row < _rows && col >= 0 && col < _columns) {
var cell = _tableIndex[row][col];

addSplitter(cell, "horizontal", evt);
}
}

exports.mergeCellHorizontal = function (row, col, evt) {
if (row >= 0 && row < _rows && col >= 0 && col < _columns) {
var cell = _tableIndex[row][col];

removeSplitters(cell, "horizontal", evt);
}
}

exports.hasVertSplitters = function (row, col) {
if (row >= 0 && row < _rows && col >= 0 && col < _columns) {
var cell = _tableIndex[row][col];

if (cell.vSplitters) return true;
}

return false;
}

exports.hasHorizSplitters = function (row, col) {
if (row >= 0 && row < _rows && col >= 0 && col < _columns) {
var cell = _tableIndex[row][col];

if (cell.hSplitters) return true;
}
return false;
}

// getters
exports.getId = function () {
return null;
}

exports.getName = function () {
return null;
}

exports.getLayer = function () {
return _tbllayer;
}

exports.getStage = function () {
return _stage;
}

exports.getZIndex = function () {
return _tblgroup.getZIndex();
}

exports.getOffset = function () {
if (_tblgroup.parent && _tblgroup.parent.getId() == "marquee") {
return _tblgroup.parent.getOffset();
}
else {
return _tblgroup.getOffset();
}
}

exports.getScale = function () {
return _tblgroup.getScale();
}

/* Function to get width of the Table */
exports.getWidth = function () {
var row = _rows - 1;
var width = 0 - (2 * DEFAULT_CELL_STROKE_WIDTH);

for (var i = 0; i < _tableIndex[row].length; i++) {
width += _tableIndex[row][i].getWidth() + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH;
}

_tblgroup.setWidth(width);

return width;
}

/* Function to get height of the Table */
exports.getHeight = function () {
var col = _columns - 1
var height = 0 - (2 * DEFAULT_CELL_STROKE_WIDTH);

for (var i = 0; i < _tableIndex.length; i++) {
height += _tableIndex[i][col].getHeight() + DEFAULT_CELL_STROKE_WIDTH + DEFAULT_SPANNER_WIDTH;
}

_tblgroup.setHeight(height);

return height;
}

exports.getX = function () {
if (_tblgroup.parent && _tblgroup.parent.getId() == "marquee") {
return _tblgroup.parent.getX();
}
else {
return _tblgroup.getX();
}
}

exports.getY = function () {
if (_tblgroup.parent && _tblgroup.parent.getId() == "marquee") {
return _tblgroup.parent.getY();
}
else {
return _tblgroup.getY();
}
}

// setters
exports.setX = function (val) {
_tblgroup.setX(val);
}

exports.setY = function (val) {
_tblgroup.setY(val);
}

exports.moveTo = function (shp) {
_tblgroup.moveTo(shp);
}

exports.setDraggable = function (val) {
_tblgroup.setDraggable(val);
}

exports.setWidth = function (val, anchor) {

var diff = val - exports.getWidth();

if (anchor) {
var anchorName = anchor.getName();

switch (anchorName) {

case "cpLeft":
for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {

var cell = _tableIndex[row][col];

if (col == 0) {
var newWidth = cell.getWidth() + diff;

if (newWidth > MIN_CELL_DIM) {
cell.setWidth(newWidth);
if (row == 0) resizeRowSpanners(diff, true);
}
else {
_tblgroup.parent.move(diff, 0);
diff = 0;
}
}
else {
var embShapes = _tblgroup.get("." + cell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(diff, 0);
}
}

updateSplitters(cell);
}
}
break;

case "cpRight":
var col = _columns - 1;

for (var row = 0; row < _tableIndex.length; row++) {
var cell = _tableIndex[row][col];
var newWidth = cell.getWidth() + diff;

if (newWidth > MIN_CELL_DIM) {
cell.setWidth(newWidth);
if (row == 0) resizeRowSpanners(diff, false);
}

updateSplitters(cell);
}
break;

case "cpTopRight":
case "cpBottomRight":
case "cpTopLeft":
case "cpBottomLeft":
var frac = diff / _columns;
var action = false;

for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {

var cell = _tableIndex[row][col];
var newWidth = cell.getWidth() + frac;

if (newWidth > MIN_CELL_DIM) {
action = true;
cell.setWidth(newWidth);

for (var cc = col + 1; cc < _tableIndex[row].length; cc++) {
var nCell = _tableIndex[row][cc];

var embShapes = _tblgroup.get("." + nCell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(frac, 0);
}
}
}

updateSplitters(cell);
}
}

if (action) {
createSpanners();
}
else {
if (anchorName != "cpBottomRight" && anchorName != "cpTopRight") {
_tblgroup.parent.move(diff, 0);
}
}

break;

default:
break;
}
}
}

exports.setHeight = function (val, anchor) {

var diff = val - exports.getHeight();

if (anchor) {
var anchorName = anchor.getName();

switch (anchorName) {

case "cpTop":

for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
var cell = _tableIndex[row][col];

if (row == 0) {
var newHeight = cell.getHeight() + diff;

if (newHeight > MIN_CELL_DIM) {
cell.setHeight(newHeight);
if (col == 0) resizeColSpanners(diff, true);
}
else {
_tblgroup.parent.move(0, diff);
diff = 0;
}
}
else {
var embShapes = _tblgroup.get("." + cell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(0, diff);
}
}

updateSplitters(cell);
}
}
break;

case "cpBottom":
var row = _rows - 1;

for (var col = 0; col < _tableIndex[row].length; col++) {
var cell = _tableIndex[row][col];
var newHeight = cell.getHeight() + diff;

if (newHeight > MIN_CELL_DIM) {
cell.setHeight(newHeight);
if (col == 0) resizeColSpanners(diff, false);
}

updateSplitters(cell);
}
break;

case "cpBottomRight":
case "cpBottomLeft":
case "cpTopLeft":
case "cpTopRight":
var frac = diff / _rows;
var action = false;

for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {

var cell = _tableIndex[row][col];
var newHeight = cell.getHeight() + frac;

if (newHeight > MIN_CELL_DIM) {
action = true;
cell.setHeight(newHeight);

for (var rr = row + 1; rr < _tableIndex.length; rr++) {
var nCell = _tableIndex[rr][col];

var embShapes = _tblgroup.get("." + nCell.getName());

for (var i = 0; i < embShapes.length; i++) {
embShapes[i].move(0, frac);
}
}
}

updateSplitters(cell);
}
}

if (action) {
createSpanners();
}
else {
if (anchorName != "cpBottomLeft" && anchorName != "cpBottomRight") {
_tblgroup.parent.move(0, diff);
}
}

break;

default:
break;
}
}
}

exports.deSelect = function () {
exports.selectedCell.hide();
_stage.draw();
}

exports.select = function () {
exports.selectedCell.show();
_stage.draw();
}

function randomString() {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = 3;
var randomstring = '';

for (var i = 0; i < string_length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum, rnum + 1);
}

return randomstring;
}

exports.checkTableIntersections = function(marquees, shape, core) {

if (core && core.shapeType == "Table") {
return;
}

for (var key in marquees) {
if (marquees.hasOwnProperty(key) && marquees[key].shape().shapeType == "Table") {
var tab = marquees[key].shape();

if (exports.areShapesOverlapping(shape, tab)) {
tab.addShape(shape);
}
else {
tab.removeShape(shape);
}
}
}
}

exports.areShapesOverlapping = function(shape1, shape2) {

var shape1Width = shape1.getWidth();
var shape1Height = shape1.getHeight();
var shape1X = shape1.getX() - shape1.getOffset().x;
var shape1XW = shape1X + shape1Width;
var shape1Y = shape1.getY() - shape1.getOffset().y;
var shape1YH = shape1Y + shape1Height;

var shape2Width = shape2.getWidth();
var shape2Height = shape2.getHeight();
var shape2X = shape2.getX() - shape2.getOffset().x;
var shape2XW = shape2X + shape2Width;
var shape2Y = shape2.getY() - shape2.getOffset().y;
var shape2YH = shape2Y + shape2Height;

// any part of shape on the table
if (((shape1X > shape2X && shape1X < shape2XW) || (shape2X > shape1X && shape2X < shape1XW)) &&
((shape1Y > shape2Y && shape1Y < shape2YH) || (shape2Y > shape1Y && shape2Y < shape1YH))) {
return true;
}
else {
return false;
}
}

exports.shapeType = "Table";
exports._id = randomString(3);
exports.selectedCell = null;

_rows = totalRows;
_columns = totalColumns;
_stage = stage;

init();

exports.parent = _tblgroup;
return exports;
}

var SelectedCell = function (cell, tblIndex) {
var exports = {};
var _selectedCell = cell;
var _tableIndex = tblIndex;

exports.getFill = function () {
if (_selectedCell) {
return _selectedCell.getFill();
}

if (_tableIndex) {
return _tableIndex[0][0].getFill();
}
}

exports.getStroke = function () {
if (_selectedCell) {
return _selectedCell.getStroke();
}

if (_tableIndex) {
return _tableIndex[0][0].getStroke();
}
}

exports.getStrokeWidth = function () {
if (_selectedCell) {
return _selectedCell.getStrokeWidth();
}

if (_tableIndex) {
return _tableIndex[0][0].getStrokeWidth();
}
}

exports.setFill = function (val) {
if (_selectedCell) {
_selectedCell.setFill(val);
return;
}

if (_tableIndex) {
for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
_tableIndex[row][col].setFill(val);
}
}
}
}

/* Funtion to set stroke for selected table cell */
exports.setStroke = function (val) {
if (_selectedCell) {
_selectedCell.setStroke(val);

if (_selectedCell.vSplitters) {
for (var i = 0; i < _selectedCell.vSplitters.length; i++) {
_selectedCell.vSplitters[i].setStroke(val);
}
}

if (_selectedCell.hSplitters) {
for (var i = 0; i < _selectedCell.hSplitters.length; i++) {
_selectedCell.hSplitters[i].setStroke(val);
}
}
return;
}

if (_tableIndex) {
for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
var cell = _tableIndex[row][col];
cell.setStroke(val);

if (cell.vSplitters) {
for (var i = 0; i < cell.vSplitters.length; i++) {
cell.vSplitters[i].setStroke(val);
}
}

if (cell.hSplitters) {
for (var i = 0; i < cell.hSplitters.length; i++) {
cell.hSplitters[i].setStroke(val);
}
}
}
}
}
}

exports.setStrokeWidth = function (val) {
if (_selectedCell) {
_selectedCell.setStrokeWidth(val);
return;
}

if (_tableIndex) {
for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
_tableIndex[row][col].setStrokeWidth(val);
}
}
}
}

exports.sCell = function () {
return _selectedCell;
}

exports.show = function () {

if (_selectedCell) {

_selectedCell.setStrokeWidth(DEFAULT_CELL_STROKE_WIDTH * 4);
_selectedCell.setStroke(_selectedCell.getStroke());
}
else {

for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
cl = _tableIndex[row][col];
cl.setStrokeWidth(DEFAULT_CELL_STROKE_WIDTH * 4);
cl.setStroke(cl.getStroke());
}
}
}
}

exports.hide = function () {

if (_selectedCell) {

_selectedCell.setStrokeWidth(DEFAULT_CELL_STROKE_WIDTH);
_selectedCell.setStroke(_selectedCell.getStroke());
}
else {

for (var row = 0; row < _tableIndex.length; row++) {
for (var col = 0; col < _tableIndex[row].length; col++) {
cl = _tableIndex[row][col];
cl.setStrokeWidth(DEFAULT_CELL_STROKE_WIDTH);
cl.setStroke(cl.getStroke());
}
}
}
}

return exports;
}

Email Marketing plan for Small/Medium Size Businesses

Tags:HTML5 Canvas, KineticJS on HTML5 Canvas, MS-Excel like Table, Table using KineticJS
How to Draw Grid on KineticJS Stage?
How to Save image Offline using HTML5 Local Storage?
Cloud Hosting Plans
AI Agents for Business Tasks
AI Website Builder
Agency Hosting Packages
Premium Business Email
VPS Hosting
AI Automation Apps

Related Posts

  • Jquery Interview Questions and Answers for Experienced & Freshers
    25 Jquery Interview Questions and Answers for Experienced or Freshers
  • HTML5 Canvas Examples to draw Circle, Rectangle, Line, Text & Image
    HTML5 Canvas Examples to draw Circle, Rectangle, Line, Text & Image
  • How to Create div based CSS Table without using HTML Table tag?
    How to Create div based CSS3 Table without using HTML5 Table tag?
  • Advanced HTML5 interview Questions and Answers
    Frequently asked advanced HTML5 interview Questions and Answers
  • How to drawimage on HTML5 Canvas using Scripting?
    How to drawimage on HTML5 Canvas using Scripting?
  • List of HTML5 new Tags introduced in 5th revision of HTML
    List of HTML5 new Tags introduced in 5th revision of HTML
  • Jquery Mobile Tutorial for Beginners with Examples
    Jquery Mobile Tutorial for Beginners with Examples
  • UI Developer Interview Questions for Experienced Professionals
    UI Developer Interview Questions for Experienced Professionals
  • Tips for Choosing Canvas Printing for your Business
    Tips for Choosing Canvas Printing for your Business
  • Example of Resume for IT professionals to get their Dream Job
    Example of Resume for IT professionals to get their Dream Job
  • Online free HTML Tutorial for beginners - Learn Web Design
    Online free HTML Tutorial for beginners - Learn Web Design
  • Responsive Bootstrap grid system Tutorial with Examples
    Responsive Bootstrap grid system Tutorial with Examples

banner

OUR FACILITIES

  • Signup
  • Login
  • Our Background
  • Policies
  • WordPress.org

CONTACT INFO

  • Reach Us
  • WhatsApp +919096266548

PUBLISH WITH US

Small Business Owners try the power of Article Marketing to grab Leads from Google or Local Search. Organic viewers are the real buyers. Double your Sales with our high DA lifelong SEO backlinks.

WHY ONESTOP?

We are here to develop high Quality Information. As a Multi-niche platform, We worked Several years for Collecting various useful Stories. Dream to establish a Domain where you can get all your day-to-day required information. We Covers Animals to Zoology.
©2014-2026 JHARAPHULA, ALL RIGHTS RESERVED.