2010-01-26 20:54:14 +01:00
|
|
|
function DataTableView(div) {
|
|
|
|
this._div = div;
|
2010-01-29 01:46:15 +01:00
|
|
|
this._pageSize = 20;
|
2010-02-01 21:57:52 +01:00
|
|
|
this._showRecon = true;
|
2010-01-29 01:46:15 +01:00
|
|
|
this._showRows(0);
|
2010-01-26 20:54:14 +01:00
|
|
|
}
|
|
|
|
|
2010-02-02 21:50:35 +01:00
|
|
|
DataTableView.prototype.update = function(reset) {
|
2010-02-05 00:38:40 +01:00
|
|
|
if (reset) {
|
|
|
|
var self = this;
|
|
|
|
reinitializeProjectData(function() {
|
|
|
|
self._showRows(0);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this._showRows(theProject.rowModel.start);
|
|
|
|
}
|
2010-02-02 21:50:35 +01:00
|
|
|
};
|
|
|
|
|
2010-01-26 20:54:14 +01:00
|
|
|
DataTableView.prototype.render = function() {
|
|
|
|
var self = this;
|
|
|
|
var container = this._div.empty();
|
|
|
|
|
|
|
|
var divSummary = $('<div></div>').addClass("viewPanel-summary").appendTo(container);
|
2010-02-23 20:18:25 +01:00
|
|
|
|
|
|
|
var summaryText;
|
|
|
|
|
|
|
|
var from = (theProject.rowModel.start + 1);
|
|
|
|
var to = Math.min(theProject.rowModel.filtered, theProject.rowModel.start + theProject.rowModel.limit);
|
|
|
|
if (theProject.rowModel.filtered == theProject.rowModel.total) {
|
|
|
|
summaryText = from + ' to ' + to + ' of <span class="viewPanel-summary-row-count">' + (theProject.rowModel.total) + '</span> rows';
|
|
|
|
} else {
|
|
|
|
summaryText = from + ' to ' + to + ' of <span class="viewPanel-summary-row-count">' +
|
|
|
|
(theProject.rowModel.filtered) + '</span> rows (filtered from ' + (theProject.rowModel.total) + ' rows total)';
|
|
|
|
}
|
|
|
|
$('<span>').html(summaryText).appendTo(divSummary);
|
2010-01-26 20:54:14 +01:00
|
|
|
|
2010-02-02 19:43:19 +01:00
|
|
|
/*
|
|
|
|
* Paging controls
|
|
|
|
*/
|
|
|
|
|
2010-02-23 20:18:25 +01:00
|
|
|
var pagingControls = $('<table width="100%"><tr><td align="right"></td><td align="right"></td></tr></table>').addClass("viewPanel-pagingControls").appendTo(container);
|
2010-02-02 19:43:19 +01:00
|
|
|
var pagingControls0 = pagingControls[0].rows[0].cells[0];
|
|
|
|
var pagingControls1 = pagingControls[0].rows[0].cells[1];
|
|
|
|
|
|
|
|
var firstPage = $('<a href="javascript:{}">« first</a>').appendTo(pagingControls0);
|
|
|
|
var previousPage = $('<a href="javascript:{}">« previous</a>').appendTo(pagingControls0);
|
2010-01-26 20:54:14 +01:00
|
|
|
if (theProject.rowModel.start > 0) {
|
|
|
|
firstPage.addClass("action").click(function(evt) { self._onClickFirstPage(this, evt); });
|
|
|
|
previousPage.addClass("action").click(function(evt) { self._onClickPreviousPage(this, evt); });
|
|
|
|
} else {
|
|
|
|
firstPage.addClass("inaction");
|
|
|
|
previousPage.addClass("inaction");
|
|
|
|
}
|
2010-02-02 19:43:19 +01:00
|
|
|
$('<span> • </span>').appendTo(pagingControls0);
|
|
|
|
var nextPage = $('<a href="javascript:{}">next page »</a>').appendTo(pagingControls0);
|
|
|
|
var lastPage = $('<a href="javascript:{}">last »</a>').appendTo(pagingControls0);
|
2010-01-30 02:05:30 +01:00
|
|
|
if (theProject.rowModel.start + theProject.rowModel.limit < theProject.rowModel.filtered) {
|
2010-01-26 20:54:14 +01:00
|
|
|
nextPage.addClass("action").click(function(evt) { self._onClickNextPage(this, evt); });
|
|
|
|
lastPage.addClass("action").click(function(evt) { self._onClickLastPage(this, evt); });
|
|
|
|
} else {
|
|
|
|
nextPage.addClass("inaction");
|
|
|
|
lastPage.addClass("inaction");
|
|
|
|
}
|
|
|
|
|
2010-02-02 19:43:19 +01:00
|
|
|
$('<span>page size: </span>').appendTo(pagingControls1);
|
|
|
|
var sizes = [ 5, 10, 15, 20, 25, 50 ];
|
|
|
|
var renderPageSize = function(index) {
|
|
|
|
var pageSize = sizes[index];
|
|
|
|
var a = $('<a href="javascript:{}"></a>').appendTo(pagingControls1)
|
|
|
|
if (pageSize == self._pageSize) {
|
|
|
|
a.text("[" + pageSize + "]").addClass("inaction");
|
|
|
|
} else {
|
|
|
|
a.text(pageSize).addClass("action").click(function(evt) {
|
|
|
|
self._pageSize = pageSize;
|
|
|
|
self.update(true);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
for (var i = 0; i < sizes.length; i++) {
|
|
|
|
renderPageSize(i);
|
|
|
|
}
|
|
|
|
|
2010-02-05 02:27:14 +01:00
|
|
|
/*============================================================
|
|
|
|
* Data Table
|
|
|
|
*============================================================
|
2010-02-02 19:43:19 +01:00
|
|
|
*/
|
2010-02-10 19:54:53 +01:00
|
|
|
var tableDiv = $('<div></div>')
|
|
|
|
.addClass("data-table-container")
|
|
|
|
.css("width", container.width() + "px")
|
|
|
|
.appendTo(container);
|
2010-02-03 02:24:41 +01:00
|
|
|
|
2010-01-26 20:54:14 +01:00
|
|
|
var table = document.createElement("table");
|
2010-02-10 19:54:53 +01:00
|
|
|
$(table)
|
|
|
|
.attr("cellspacing", "0")
|
|
|
|
.addClass("data-table")
|
|
|
|
.appendTo(tableDiv);
|
2010-01-26 20:54:14 +01:00
|
|
|
|
2010-02-05 02:27:14 +01:00
|
|
|
var columns = theProject.columnModel.columns;
|
|
|
|
var columnGroups = theProject.columnModel.columnGroups;
|
|
|
|
|
|
|
|
/*------------------------------------------------------------
|
|
|
|
* Column Group Headers
|
|
|
|
*------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
var renderColumnKeys = function(keys) {
|
|
|
|
if (keys.length > 0) {
|
|
|
|
var tr = table.insertRow(table.rows.length);
|
2010-02-23 08:45:12 +01:00
|
|
|
tr.insertCell(0); // star
|
|
|
|
tr.insertCell(1); // row index
|
2010-02-05 02:27:14 +01:00
|
|
|
|
|
|
|
for (var c = 0; c < columns.length; c++) {
|
|
|
|
var td = tr.insertCell(tr.cells.length);
|
|
|
|
|
|
|
|
for (var k = 0; k < keys.length; k++) {
|
|
|
|
if (c == keys[k]) {
|
|
|
|
$('<img />').attr("src", "images/down-arrow.png").appendTo(td);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
var renderColumnGroups = function(groups, keys) {
|
|
|
|
var nextLayer = [];
|
|
|
|
|
|
|
|
if (groups.length > 0) {
|
|
|
|
var tr = table.insertRow(table.rows.length);
|
2010-02-23 08:45:12 +01:00
|
|
|
tr.insertCell(0); // star
|
|
|
|
tr.insertCell(1); // row index
|
2010-02-05 02:27:14 +01:00
|
|
|
|
|
|
|
for (var c = 0; c < columns.length; c++) {
|
|
|
|
var foundGroup = false;
|
|
|
|
|
|
|
|
for (var g = 0; g < groups.length; g++) {
|
|
|
|
var columnGroup = groups[g];
|
|
|
|
if (columnGroup.startColumnIndex == c) {
|
|
|
|
foundGroup = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var td = tr.insertCell(tr.cells.length);
|
|
|
|
if (foundGroup) {
|
|
|
|
td.setAttribute("colspan", columnGroup.columnSpan);
|
|
|
|
td.style.background = "blue";
|
|
|
|
|
|
|
|
if (columnGroup.keyColumnIndex >= 0) {
|
|
|
|
keys.push(columnGroup.keyColumnIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
c += (columnGroup.columnSpan - 1);
|
|
|
|
|
|
|
|
nextLayer = nextLayer.concat(columnGroup.subgroups);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
renderColumnKeys(keys);
|
|
|
|
|
|
|
|
if (nextLayer.length > 0) {
|
|
|
|
renderColumnGroups(nextLayer, []);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
renderColumnGroups(
|
|
|
|
columnGroups,
|
|
|
|
[ theProject.columnModel.keyCellIndex ]
|
|
|
|
);
|
|
|
|
|
|
|
|
/*------------------------------------------------------------
|
|
|
|
* Column Headers with Menus
|
|
|
|
*------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
var trHead = table.insertRow(table.rows.length);
|
2010-01-26 20:54:14 +01:00
|
|
|
|
2010-02-23 08:45:12 +01:00
|
|
|
var tdHeadIndex = trHead.insertCell(trHead.cells.length);
|
|
|
|
$(tdHeadIndex).attr("colspan", "2").addClass("column-header");
|
|
|
|
$('<img src="/images/menu-dropdown.png" />').addClass("column-header-menu").appendTo(tdHeadIndex).click(function() {
|
2010-01-26 20:54:14 +01:00
|
|
|
self._createMenuForAllColumns(this);
|
|
|
|
});
|
|
|
|
|
|
|
|
var createColumnHeader = function(column, index) {
|
|
|
|
var td = trHead.insertCell(trHead.cells.length);
|
|
|
|
$(td).addClass("column-header");
|
|
|
|
|
|
|
|
if (column.collapsed) {
|
|
|
|
$(td).html(" ").attr("title", column.headerLabel).click(function(evt) {
|
|
|
|
column.collapsed = false;
|
|
|
|
self.render();
|
|
|
|
});
|
|
|
|
} else {
|
2010-02-09 20:23:11 +01:00
|
|
|
new DataTableColumnHeaderUI(self, column, index, td);
|
2010-01-26 20:54:14 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
for (var i = 0; i < columns.length; i++) {
|
|
|
|
createColumnHeader(columns[i], i);
|
|
|
|
}
|
|
|
|
|
2010-02-05 02:27:14 +01:00
|
|
|
/*------------------------------------------------------------
|
|
|
|
* Data Cells
|
|
|
|
*------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
2010-01-26 20:54:14 +01:00
|
|
|
var rows = theProject.rowModel.rows;
|
2010-02-23 08:45:12 +01:00
|
|
|
var renderRow = function(tr, r, row, even) {
|
2010-01-26 20:54:14 +01:00
|
|
|
var cells = row.cells;
|
|
|
|
|
2010-02-23 08:45:12 +01:00
|
|
|
var tdStar = tr.insertCell(tr.cells.length);
|
|
|
|
var star = $('<a href="javascript:{}"> </a>')
|
|
|
|
.addClass(row.starred ? "data-table-star-on" : "data-table-star-off")
|
|
|
|
.appendTo(tdStar)
|
|
|
|
.click(function() {
|
|
|
|
var newStarred = !row.starred;
|
|
|
|
$.post(
|
|
|
|
"/command/annotate-one-row?" + $.param({ project: theProject.id, row: row.i, starred: newStarred }),
|
|
|
|
null,
|
|
|
|
function(o) {
|
|
|
|
if (o.code == "ok") {
|
|
|
|
row.starred = newStarred;
|
|
|
|
|
|
|
|
$(tr).empty();
|
|
|
|
|
|
|
|
renderRow(tr, r, row, even);
|
|
|
|
|
|
|
|
ui.historyWidget.update();
|
|
|
|
} else {
|
|
|
|
ui.processWidget.update();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"json"
|
|
|
|
);
|
|
|
|
|
|
|
|
});
|
2010-02-10 19:54:53 +01:00
|
|
|
|
2010-02-23 08:45:12 +01:00
|
|
|
var tdIndex = tr.insertCell(tr.cells.length);
|
2010-02-10 19:54:53 +01:00
|
|
|
if ("j" in row) {
|
|
|
|
$(tr).addClass("record");
|
2010-02-23 08:45:12 +01:00
|
|
|
$('<div></div>').html((row.j + 1) + ".").appendTo(tdIndex);
|
2010-02-10 19:54:53 +01:00
|
|
|
} else {
|
2010-02-23 08:45:12 +01:00
|
|
|
$('<div></div>').html(" ").appendTo(tdIndex);
|
2010-02-10 19:54:53 +01:00
|
|
|
}
|
2010-01-26 20:54:14 +01:00
|
|
|
|
2010-02-06 00:05:00 +01:00
|
|
|
if ("contextual" in row && row.contextual) {
|
|
|
|
$(tr).addClass("contextual");
|
|
|
|
}
|
|
|
|
|
2010-02-10 19:54:53 +01:00
|
|
|
$(tr).addClass(even ? "even" : "odd");
|
2010-01-26 20:54:14 +01:00
|
|
|
|
|
|
|
for (var i = 0; i < columns.length; i++) {
|
|
|
|
var column = columns[i];
|
|
|
|
var td = tr.insertCell(tr.cells.length);
|
|
|
|
if (column.collapsed) {
|
|
|
|
td.innerHTML = " ";
|
2010-02-09 20:23:11 +01:00
|
|
|
} else {
|
|
|
|
var cell = (column.cellIndex < cells.length) ? cells[column.cellIndex] : null;
|
2010-02-23 21:20:14 +01:00
|
|
|
new DataTableCellUI(self, cell, row.i, column.cellIndex, td);
|
2010-01-26 20:54:14 +01:00
|
|
|
}
|
|
|
|
}
|
2010-02-23 08:45:12 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
var even = true;
|
|
|
|
for (var r = 0; r < rows.length; r++) {
|
|
|
|
var row = rows[r];
|
|
|
|
var tr = table.insertRow(table.rows.length);
|
|
|
|
if ("j" in row) {
|
|
|
|
even = !even;
|
|
|
|
}
|
|
|
|
renderRow(tr, r, row, even);
|
2010-01-26 20:54:14 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
DataTableView.prototype._showRows = function(start, onDone) {
|
|
|
|
var self = this;
|
2010-01-29 01:46:15 +01:00
|
|
|
|
|
|
|
$.post(
|
|
|
|
"/command/get-rows?" + $.param({ project: theProject.id, start: start, limit: this._pageSize }),
|
|
|
|
{ engine: JSON.stringify(ui.browsingEngine.getJSON()) },
|
2010-01-26 20:54:14 +01:00
|
|
|
function(data) {
|
|
|
|
theProject.rowModel = data;
|
|
|
|
self.render();
|
2010-01-29 01:46:15 +01:00
|
|
|
|
|
|
|
if (onDone) {
|
|
|
|
onDone();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"json"
|
2010-01-26 20:54:14 +01:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
DataTableView.prototype._onClickPreviousPage = function(elmt, evt) {
|
2010-01-29 01:46:15 +01:00
|
|
|
this._showRows(theProject.rowModel.start - this._pageSize);
|
2010-01-26 20:54:14 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
DataTableView.prototype._onClickNextPage = function(elmt, evt) {
|
2010-01-29 01:46:15 +01:00
|
|
|
this._showRows(theProject.rowModel.start + this._pageSize);
|
2010-01-26 20:54:14 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
DataTableView.prototype._onClickFirstPage = function(elmt, evt) {
|
2010-01-29 01:46:15 +01:00
|
|
|
this._showRows(0);
|
2010-01-26 20:54:14 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
DataTableView.prototype._onClickLastPage = function(elmt, evt) {
|
2010-01-30 02:05:30 +01:00
|
|
|
this._showRows(Math.floor(theProject.rowModel.filtered / this._pageSize) * this._pageSize);
|
2010-01-26 20:54:14 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
DataTableView.prototype._createMenuForAllColumns = function(elmt) {
|
|
|
|
self = this;
|
|
|
|
MenuSystem.createAndShowStandardMenu([
|
|
|
|
{
|
|
|
|
label: "Collapse All Columns",
|
|
|
|
click: function() {
|
|
|
|
for (var i = 0; i < theProject.columnModel.columns.length; i++) {
|
|
|
|
theProject.columnModel.columns[i].collapsed = true;
|
|
|
|
}
|
|
|
|
self.render();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: "Expand All Columns",
|
|
|
|
click: function() {
|
|
|
|
for (var i = 0; i < theProject.columnModel.columns.length; i++) {
|
|
|
|
theProject.columnModel.columns[i].collapsed = false;
|
|
|
|
}
|
|
|
|
self.render();
|
|
|
|
}
|
2010-02-23 08:45:12 +01:00
|
|
|
},
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
label: "Star Rows",
|
|
|
|
click: function() {
|
|
|
|
self.doPostThenUpdate("annotate-rows", { "starred" : "true" }, false);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: "Unstar Rows",
|
|
|
|
click: function() {
|
|
|
|
self.doPostThenUpdate("annotate-rows", { "starred" : "false" }, false);
|
|
|
|
}
|
2010-01-26 20:54:14 +01:00
|
|
|
}
|
|
|
|
], elmt);
|
|
|
|
};
|
|
|
|
|
2010-02-09 20:23:11 +01:00
|
|
|
DataTableView.prototype.createUpdateFunction = function(onBefore) {
|
2010-02-02 21:50:35 +01:00
|
|
|
var self = this;
|
|
|
|
return function(data) {
|
|
|
|
if (data.code == "ok") {
|
2010-02-05 00:38:40 +01:00
|
|
|
var onDone = function() {
|
|
|
|
self.update();
|
|
|
|
ui.historyWidget.update();
|
|
|
|
};
|
2010-02-02 21:50:35 +01:00
|
|
|
} else {
|
2010-02-05 00:38:40 +01:00
|
|
|
var onDone = function() {
|
|
|
|
ui.processWidget.update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (onBefore) {
|
|
|
|
onBefore(onDone);
|
|
|
|
} else {
|
|
|
|
onDone();
|
2010-02-02 21:50:35 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2010-02-09 20:23:11 +01:00
|
|
|
DataTableView.prototype.doPostThenUpdate = function(command, params, updateColumnModel) {
|
2010-02-02 21:50:35 +01:00
|
|
|
params.project = theProject.id;
|
|
|
|
$.post(
|
|
|
|
"/command/" + command + "?" + $.param(params),
|
|
|
|
{ engine: JSON.stringify(ui.browsingEngine.getJSON()) },
|
2010-02-09 20:23:11 +01:00
|
|
|
this.createUpdateFunction(updateColumnModel ? reinitializeProjectData : undefined),
|
2010-02-02 21:50:35 +01:00
|
|
|
"json"
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2010-02-03 10:27:53 +01:00
|
|
|
DataTableView.promptExpressionOnVisibleRows = function(column, title, expression, onDone) {
|
|
|
|
var rowIndices = [];
|
|
|
|
var values = [];
|
|
|
|
|
|
|
|
var rows = theProject.rowModel.rows;
|
|
|
|
for (var r = 0; r < rows.length; r++) {
|
|
|
|
var row = rows[r];
|
|
|
|
|
|
|
|
rowIndices.push(row.i);
|
|
|
|
|
|
|
|
var v = null;
|
|
|
|
if (column.cellIndex < row.cells.length) {
|
|
|
|
var cell = row.cells[column.cellIndex];
|
|
|
|
if (cell != null) {
|
|
|
|
v = cell.v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
values.push(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
new ExpressionPreviewDialog(
|
|
|
|
title,
|
|
|
|
column.cellIndex,
|
|
|
|
rowIndices,
|
|
|
|
values,
|
|
|
|
expression,
|
|
|
|
onDone
|
|
|
|
);
|
2010-01-30 02:05:30 +01:00
|
|
|
};
|
|
|
|
|
2010-02-05 00:38:40 +01:00
|
|
|
|