237 lines
No EOL
9.2 KiB
JavaScript
237 lines
No EOL
9.2 KiB
JavaScript
'use strict';
|
|
|
|
Ox.Spreadsheet = function(options, self) {
|
|
|
|
self = self || {};
|
|
var that = Ox.Element({}, self)
|
|
.defaults({
|
|
columnPlaceholder: '',
|
|
columns: [],
|
|
columnTitleType: 'str',
|
|
columnWidth: 64,
|
|
rowPlaceholder: '',
|
|
rows: [],
|
|
rowTitleType: 'str',
|
|
rowTitleWidth: 128,
|
|
title: '',
|
|
value: []
|
|
})
|
|
.options(options || {})
|
|
.addClass('OxSpreadsheet');
|
|
|
|
self.values = [];
|
|
self.options.rows.forEach(function(row, r) {
|
|
self.values.push([]);
|
|
self.options.columns.forEach(function(column, c) {
|
|
self.values[r].push(0);
|
|
});
|
|
});
|
|
self.sums = getSums();
|
|
|
|
renderSpreadsheet();
|
|
|
|
function addColumn(index) {
|
|
self.options.columns.splice(index, 0, '');
|
|
self.values.forEach(function(columns) {
|
|
columns.splice(index, 0, 0);
|
|
});
|
|
renderSpreadsheet();
|
|
}
|
|
|
|
function addRow(index) {
|
|
self.options.rows.splice(index, 0, '');
|
|
self.values.splice(index, 0, Ox.repeat([0], self.columns));
|
|
renderSpreadsheet();
|
|
}
|
|
|
|
function getSums() {
|
|
var sums = {
|
|
column: Ox.repeat([0], self.columns),
|
|
row: Ox.repeat([0], self.rows),
|
|
sheet: 0
|
|
};
|
|
self.values.forEach(function(columns, r) {
|
|
columns.forEach(function(value, c) {
|
|
sums.column[c] += value;
|
|
sums.row[r] += value;
|
|
sums.sheet += value;
|
|
});
|
|
});
|
|
return sums;
|
|
}
|
|
|
|
function removeColumn(index) {
|
|
self.options.columns.splice(index, 1);
|
|
self.values.forEach(function(columns) {
|
|
columns.splice(index, 1);
|
|
});
|
|
renderSpreadsheet();
|
|
}
|
|
|
|
function removeRow(index) {
|
|
self.options.rows.splice(index, 1);
|
|
self.values.splice(index, 1);
|
|
renderSpreadsheet();
|
|
}
|
|
|
|
function renderSpreadsheet() {
|
|
|
|
self.columns = self.options.columns.length;
|
|
self.rows = self.options.rows.length;
|
|
self.sums = getSums();
|
|
self.$input = {};
|
|
|
|
that.empty()
|
|
.css({
|
|
width: self.options.rowTitleWidth
|
|
+ self.options.columnWidth * (self.columns + 1) + 'px',
|
|
height: 16 * (self.rows + 2) + 'px'
|
|
});
|
|
|
|
Ox.merge([self.options.title], Ox.clone(self.options.rows), ['Total']).forEach(function(row, r) {
|
|
r--;
|
|
Ox.merge([''], Ox.clone(self.options.columns), ['Total']).forEach(function(column, c) {
|
|
c--;
|
|
if (r == -1) {
|
|
if (c == -1 || c == self.columns) {
|
|
Ox.Label({
|
|
style: 'square',
|
|
textAlign: c == -1 ? 'left' : 'right',
|
|
title: c == -1 ? self.options.title : 'Total',
|
|
width: c == -1 ? self.options.rowTitleWidth : self.options.columnWidth
|
|
})
|
|
.appendTo(that);
|
|
} else {
|
|
Ox.MenuButton({
|
|
style: 'square',
|
|
type: 'image',
|
|
items: [
|
|
{id: 'before', title: 'Add column before'},
|
|
{id: 'after', title: 'Add column after'},
|
|
{id: 'remove', title: 'Remove this column', disabled: self.columns == 1}
|
|
]
|
|
})
|
|
.bindEvent({
|
|
click: function(data) {
|
|
if (data.id == 'remove') {
|
|
removeColumn(c);
|
|
} else {
|
|
addColumn(c + (data.id == 'after'));
|
|
}
|
|
triggerChangeEvent();
|
|
}
|
|
})
|
|
.appendTo(that);
|
|
Ox.Input({
|
|
placeholder: self.options.columnPlaceholder,
|
|
style: 'square',
|
|
type: self.options.columnTitleType,
|
|
value: column,
|
|
width: self.options.columnWidth - 16
|
|
})
|
|
.bindEvent({
|
|
change: function(data) {
|
|
self.options.columns[c] = data.value;
|
|
triggerChangeEvent();
|
|
}
|
|
})
|
|
.appendTo(that);
|
|
}
|
|
} else {
|
|
if (c == -1) {
|
|
if (r < self.rows) {
|
|
Ox.MenuButton({
|
|
style: 'square',
|
|
type: 'image',
|
|
items: [
|
|
{id: 'before', title: 'Add row above'},
|
|
{id: 'after', title: 'Add row below'},
|
|
{id: 'remove', title: 'Remove this row', disabled: self.rows == 1}
|
|
]
|
|
})
|
|
.bindEvent({
|
|
click: function(data) {
|
|
if (data.id == 'remove') {
|
|
removeRow(r);
|
|
} else {
|
|
addRow(r + (data.id == 'after'));
|
|
}
|
|
triggerChangeEvent();
|
|
}
|
|
})
|
|
.appendTo(that);
|
|
Ox.Input({
|
|
placeholder: self.options.rowPlaceholder,
|
|
style: 'square',
|
|
type: self.options.rowTitleType,
|
|
value: row,
|
|
width: self.options.rowTitleWidth - 16
|
|
})
|
|
.bindEvent({
|
|
change: function(data) {
|
|
self.options.rows[r] = data.value;
|
|
triggerChangeEvent();
|
|
}
|
|
})
|
|
.appendTo(that);
|
|
} else {
|
|
Ox.Label({
|
|
style: 'square',
|
|
textAlign: 'right',
|
|
title: row,
|
|
width: self.options.rowTitleWidth
|
|
})
|
|
.appendTo(that);
|
|
}
|
|
} else {
|
|
var id = c + ',' + r,
|
|
isColumnSum = r == self.rows,
|
|
isRowSum = c == self.columns,
|
|
isSheetSum = isColumnSum && isRowSum,
|
|
isSum = isColumnSum || isRowSum;
|
|
self.$input[id] = Ox.Input({
|
|
//changeOnKeypress: true,
|
|
disabled: isSum,
|
|
style: 'square',
|
|
type: 'int',
|
|
value: isSheetSum ? self.sums.sheet
|
|
: isColumnSum ? self.sums.column[c]
|
|
: isRowSum ? self.sums.row[r]
|
|
: self.values[r][c],
|
|
width: self.options.columnWidth
|
|
})
|
|
.appendTo(that);
|
|
!isSum && self.$input[id].bindEvent({
|
|
change: function(data) {
|
|
self.values[r][c] = parseInt(data.value);
|
|
self.sums = getSums();
|
|
self.$input[c + ',' + self.rows].value(self.sums.column[c]);
|
|
self.$input[self.columns + ',' + r].value(self.sums.row[r]);
|
|
self.$input[self.columns + ',' + self.rows].value(self.sums.sheet);
|
|
triggerChangeEvent();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
}
|
|
|
|
function triggerChangeEvent() {
|
|
that.triggerEvent('change', {
|
|
value: that.value()
|
|
});
|
|
}
|
|
|
|
that.value = function() {
|
|
return {
|
|
columns: self.options.columns,
|
|
rows: self.options.rows,
|
|
values: self.values
|
|
};
|
|
};
|
|
|
|
return that;
|
|
|
|
}; |