2011-11-30 14:54:11 +00:00
|
|
|
'use strict';
|
|
|
|
|
2012-05-21 10:38:18 +00:00
|
|
|
/*@
|
2012-05-31 10:32:54 +00:00
|
|
|
Ox.Spreadsheet <f> Spreadsheet
|
|
|
|
([options[, self]]) -> <o:Ox.Element> Spreadsheet
|
2012-05-21 10:38:18 +00:00
|
|
|
options <o> Options
|
|
|
|
self <o> Shared private variable
|
|
|
|
@*/
|
2011-11-30 14:54:11 +00:00
|
|
|
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: '',
|
2011-12-30 09:33:01 +00:00
|
|
|
value: {}
|
2011-11-30 14:54:11 +00:00
|
|
|
})
|
|
|
|
.options(options || {})
|
|
|
|
.addClass('OxSpreadsheet');
|
|
|
|
|
2011-12-30 09:33:01 +00:00
|
|
|
if (Ox.isEmpty(self.options.value)) {
|
|
|
|
self.options.value = {
|
|
|
|
columns: [],
|
|
|
|
rows: [],
|
|
|
|
values: []
|
|
|
|
}
|
|
|
|
Ox.loop(4, function(i) {
|
|
|
|
self.options.value.columns.push('');
|
|
|
|
self.options.value.rows.push('');
|
|
|
|
self.options.value.values.push([0, 0, 0, 0]);
|
|
|
|
});
|
2012-06-14 13:46:57 +00:00
|
|
|
} else {
|
|
|
|
self.options.value.values = self.options.value.values || [];
|
|
|
|
if (Ox.isEmpty(self.options.value.values)) {
|
|
|
|
self.options.value.values = [];
|
|
|
|
self.options.value.rows.forEach(function(row, r) {
|
|
|
|
self.options.value.values.push([]);
|
|
|
|
self.options.value.columns.forEach(function(column, c) {
|
|
|
|
self.options.value.values[r].push(0);
|
|
|
|
});
|
2011-12-30 09:33:01 +00:00
|
|
|
});
|
2012-06-14 13:46:57 +00:00
|
|
|
}
|
2011-12-30 09:33:01 +00:00
|
|
|
}
|
|
|
|
|
2011-11-30 14:54:11 +00:00
|
|
|
renderSpreadsheet();
|
|
|
|
|
|
|
|
function addColumn(index) {
|
2011-12-30 09:33:01 +00:00
|
|
|
self.options.value.columns.splice(index, 0, '');
|
|
|
|
self.options.value.values.forEach(function(columns) {
|
2011-11-30 16:35:50 +00:00
|
|
|
columns.splice(index, 0, 0);
|
2011-11-30 14:54:11 +00:00
|
|
|
});
|
|
|
|
renderSpreadsheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
function addRow(index) {
|
2011-12-30 09:33:01 +00:00
|
|
|
self.options.value.rows.splice(index, 0, '');
|
|
|
|
self.options.value.values.splice(index, 0, Ox.repeat([0], self.columns));
|
2011-11-30 14:54:11 +00:00
|
|
|
renderSpreadsheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
function getSums() {
|
|
|
|
var sums = {
|
|
|
|
column: Ox.repeat([0], self.columns),
|
|
|
|
row: Ox.repeat([0], self.rows),
|
|
|
|
sheet: 0
|
|
|
|
};
|
2011-12-30 09:33:01 +00:00
|
|
|
self.options.value.values.forEach(function(columns, r) {
|
2011-11-30 14:54:11 +00:00
|
|
|
columns.forEach(function(value, c) {
|
|
|
|
sums.column[c] += value;
|
|
|
|
sums.row[r] += value;
|
|
|
|
sums.sheet += value;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return sums;
|
|
|
|
}
|
|
|
|
|
|
|
|
function removeColumn(index) {
|
2011-12-30 09:33:01 +00:00
|
|
|
self.options.value.columns.splice(index, 1);
|
|
|
|
self.options.value.values.forEach(function(columns) {
|
2011-11-30 16:35:50 +00:00
|
|
|
columns.splice(index, 1);
|
2011-11-30 14:54:11 +00:00
|
|
|
});
|
|
|
|
renderSpreadsheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
function removeRow(index) {
|
2011-12-30 09:33:01 +00:00
|
|
|
self.options.value.rows.splice(index, 1);
|
|
|
|
self.options.value.values.splice(index, 1);
|
2011-11-30 14:54:11 +00:00
|
|
|
renderSpreadsheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderSpreadsheet() {
|
|
|
|
|
2011-12-30 09:33:01 +00:00
|
|
|
self.columns = self.options.value.columns.length;
|
|
|
|
self.rows = self.options.value.rows.length;
|
2011-11-30 14:54:11 +00:00
|
|
|
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'
|
|
|
|
});
|
|
|
|
|
2012-05-24 07:45:33 +00:00
|
|
|
[self.options.title].concat(Ox.clone(self.options.value.rows), ['Total']).forEach(function(row, r) {
|
2011-11-30 14:54:11 +00:00
|
|
|
r--;
|
2012-05-24 07:45:33 +00:00
|
|
|
[''].concat(Ox.clone(self.options.value.columns), ['Total']).forEach(function(column, c) {
|
2011-11-30 14:54:11 +00:00
|
|
|
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 {
|
2011-12-20 07:20:37 +00:00
|
|
|
Ox.MenuButton({
|
2011-11-30 14:54:11 +00:00
|
|
|
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) {
|
2011-12-30 09:33:01 +00:00
|
|
|
self.options.value.columns[c] = data.value;
|
2011-11-30 14:54:11 +00:00
|
|
|
triggerChangeEvent();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.appendTo(that);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (c == -1) {
|
|
|
|
if (r < self.rows) {
|
2011-12-20 07:20:37 +00:00
|
|
|
Ox.MenuButton({
|
2011-11-30 14:54:11 +00:00
|
|
|
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) {
|
2011-12-30 09:33:01 +00:00
|
|
|
self.options.value.rows[r] = data.value;
|
2011-11-30 14:54:11 +00:00
|
|
|
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]
|
2011-12-30 09:33:01 +00:00
|
|
|
: self.options.value.values[r][c],
|
2011-11-30 14:54:11 +00:00
|
|
|
width: self.options.columnWidth
|
|
|
|
})
|
|
|
|
.appendTo(that);
|
|
|
|
!isSum && self.$input[id].bindEvent({
|
|
|
|
change: function(data) {
|
2012-06-13 08:28:21 +00:00
|
|
|
self.options.value.values[r][c] = parseInt(data.value, 10);
|
2011-11-30 14:54:11 +00:00
|
|
|
self.sums = getSums();
|
2011-12-21 15:33:52 +00:00
|
|
|
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);
|
2011-11-30 14:54:11 +00:00
|
|
|
triggerChangeEvent();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function triggerChangeEvent() {
|
|
|
|
that.triggerEvent('change', {
|
2011-12-30 09:33:01 +00:00
|
|
|
value: self.options.value
|
2011-11-30 14:54:11 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return that;
|
|
|
|
|
2012-05-21 10:38:18 +00:00
|
|
|
};
|