function DataTableView(div) { this._div = div; this._pageSize = 20; this._showRecon = true; this._collapsedColumnNames = {}; this._sorting = { criteria: [] }; this._columnHeaderUIs = []; this._showRows(0); } DataTableView.prototype.getSorting = function() { return this._sorting; }; DataTableView.prototype.resize = function() { var topHeight = this._div.find(".viewPanel-header").outerHeight(true); this._div.find(".data-table-container") .css("height", (this._div.innerHeight() - topHeight - 1) + "px") .css("display", "block"); }; DataTableView.prototype.update = function(onDone) { this._showRows(0, onDone); }; DataTableView.prototype.render = function() { var self = this; var oldTableDiv = this._div.find(".data-table-container"); var scrollLeft = (oldTableDiv.length > 0) ? oldTableDiv[0].scrollLeft : 0; var html = $( '' + '' + '' + '' + '' + '' + '' + '
' + '' ); var elmts = DOM.bind(html); this._renderSummaryText(elmts.summary); this._renderPagingControls(elmts.pageSizeControls, elmts.pagingControls); this._renderDataTable(elmts.table[0]); if (this._sorting.criteria.length > 0) { this._renderSortingControls(elmts.sortingControls); } this._div.empty().append(html); this.resize(); elmts.dataTableContainer[0].scrollLeft = scrollLeft; }; DataTableView.prototype._renderSummaryText = function(elmt) { var summaryText; var units = theProject.rowModel.mode == "row-based" ? "rows" : "records"; 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 + ' of ' + (theProject.rowModel.total) + ' ' + units; } else { summaryText = from + ' – ' + to + ' of ' + (theProject.rowModel.filtered) + ' matching ' + units + ' (' + (theProject.rowModel.total) + ' total)'; } $('').html(summaryText).appendTo(elmt); }; DataTableView.prototype._renderSortingControls = function(sortingControls) { var self = this; $('') .addClass("action") .text("Sorted") .append($('').attr("src", "/images/down-arrow.png")) .appendTo(sortingControls) .click(function() { self._createSortingMenu(this); }); }; DataTableView.prototype._renderPagingControls = function(pageSizeControls, pagingControls) { var self = this; var firstPage = $('« first').appendTo(pagingControls); var previousPage = $('« previous').appendTo(pagingControls); 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"); } $('').appendTo(pagingControls); var nextPage = $('next page »').appendTo(pagingControls); var lastPage = $('last »').appendTo(pagingControls); if (theProject.rowModel.start + theProject.rowModel.limit < theProject.rowModel.filtered) { 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"); } $('Show ').appendTo(pageSizeControls); var sizes = [ 10, 20, 25, 50 ]; var renderPageSize = function(index) { var pageSize = sizes[index]; var a = $('') .addClass("viewPanel-pagingControls-page") .appendTo(pageSizeControls); if (pageSize == self._pageSize) { a.text(pageSize).addClass("inaction"); } else { a.text(pageSize).addClass("action").click(function(evt) { self._pageSize = pageSize; self.update(); }); } }; for (var i = 0; i < sizes.length; i++) { renderPageSize(i); } $('') .text(theProject.rowModel.mode == "record-based" ? ' records' : ' rows') .appendTo(pageSizeControls); }; DataTableView.prototype._renderDataTable = function(table) { var self = this; 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); tr.insertCell(0); // star tr.insertCell(1); // flag tr.insertCell(2); // row index 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]) { $('').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); tr.insertCell(0); // star tr.insertCell(1); // flag tr.insertCell(2); // row index for (var c = 0; c < columns.length; c++) { var foundGroup = false; var columnGroup; for (var g = 0; g < groups.length; g++) { 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 = "#FF6A00"; if (columnGroup.keyColumnIndex >= 0) { keys.push(columnGroup.keyColumnIndex); } c += (columnGroup.columnSpan - 1); if ("subgroups" in columnGroup) { nextLayer = nextLayer.concat(columnGroup.subgroups); } } } } renderColumnKeys(keys); if (nextLayer.length > 0) { renderColumnGroups(nextLayer, []); } }; if (columnGroups.length > 0) { renderColumnGroups( columnGroups, [ theProject.columnModel.keyCellIndex ] ); } /*------------------------------------------------------------ * Column Headers with Menus *------------------------------------------------------------ */ var trHead = table.insertRow(table.rows.length); DOM.bind( $(trHead.insertCell(trHead.cells.length)) .attr("colspan", "3") .addClass("column-header") .html( '' + '' + '' + '
' + ' ' + ' 
' ) ).dropdownMenu.click(function() { self._createMenuForAllColumns(this); }); this._columnHeaderUIs = []; var createColumnHeader = function(column, index) { var td = trHead.insertCell(trHead.cells.length); $(td).addClass("column-header"); if (column.name in self._collapsedColumnNames) { $(td).html(" ").attr("title", column.name).click(function(evt) { delete self._collapsedColumnNames[column.name]; self.render(); }); } else { var columnHeaderUI = new DataTableColumnHeaderUI(self, column, index, td); self._columnHeaderUIs.push(columnHeaderUI); } }; for (var i = 0; i < columns.length; i++) { createColumnHeader(columns[i], i); } /*------------------------------------------------------------ * Data Cells *------------------------------------------------------------ */ var rows = theProject.rowModel.rows; var renderRow = function(tr, r, row, even) { $(tr).empty(); var cells = row.cells; var tdStar = tr.insertCell(tr.cells.length); var star = $(' ') .addClass(row.starred ? "data-table-star-on" : "data-table-star-off") .appendTo(tdStar) .click(function() { var newStarred = !row.starred; Gridworks.postProcess( "annotate-one-row", { row: row.i, starred: newStarred }, null, {}, { onDone: function(o) { row.starred = newStarred; renderRow(tr, r, row, even); } }, "json" ); }); var tdFlag = tr.insertCell(tr.cells.length); var flag = $(' ') .addClass(row.flagged ? "data-table-flag-on" : "data-table-flag-off") .appendTo(tdFlag) .click(function() { var newFlagged = !row.flagged; Gridworks.postProcess( "annotate-one-row", { row: row.i, flagged: newFlagged }, null, {}, { onDone: function(o) { row.flagged = newFlagged; renderRow(tr, r, row, even); } }, "json" ); }); var tdIndex = tr.insertCell(tr.cells.length); if (theProject.rowModel.mode == "record-based") { if ("j" in row) { $(tr).addClass("record"); $('
').html((row.j + 1) + ".").appendTo(tdIndex); } else { $('
').html(" ").appendTo(tdIndex); } } else { $('
').html((row.i + 1) + ".").appendTo(tdIndex); } $(tr).addClass(even ? "even" : "odd"); for (var i = 0; i < columns.length; i++) { var column = columns[i]; var td = tr.insertCell(tr.cells.length); if (column.name in self._collapsedColumnNames) { td.innerHTML = " "; } else { var cell = (column.cellIndex < cells.length) ? cells[column.cellIndex] : null; new DataTableCellUI(self, cell, row.i, column.cellIndex, td); } } }; var even = true; for (var r = 0; r < rows.length; r++) { var row = rows[r]; var tr = table.insertRow(table.rows.length); if (theProject.rowModel.mode == "row-based" || "j" in row) { even = !even; } renderRow(tr, r, row, even); } }; DataTableView.prototype._showRows = function(start, onDone) { var self = this; Gridworks.fetchRows(start, this._pageSize, function() { self.render(); if (onDone) { onDone(); } }, this._sorting); }; DataTableView.prototype._onClickPreviousPage = function(elmt, evt) { this._showRows(theProject.rowModel.start - this._pageSize); }; DataTableView.prototype._onClickNextPage = function(elmt, evt) { this._showRows(theProject.rowModel.start + this._pageSize); }; DataTableView.prototype._onClickFirstPage = function(elmt, evt) { this._showRows(0); }; DataTableView.prototype._onClickLastPage = function(elmt, evt) { this._showRows(Math.floor(theProject.rowModel.filtered / this._pageSize) * this._pageSize); }; DataTableView.prototype._getSortingCriteriaCount = function() { return this._sorting.criteria.length; }; DataTableView.prototype._sortedByColumn = function(columnName) { for (var i = 0; i < this._sorting.criteria.length; i++) { if (this._sorting.criteria[i].column == columnName) { return true; } } return false; }; DataTableView.prototype._getSortingCriterionForColumn = function(columnName) { for (var i = 0; i < this._sorting.criteria.length; i++) { if (this._sorting.criteria[i].column == columnName) { return this._sorting.criteria[i]; } } return null; }; DataTableView.prototype._removeSortingCriterionOfColumn = function(columnName) { for (var i = 0; i < this._sorting.criteria.length; i++) { if (this._sorting.criteria[i].column == columnName) { this._sorting.criteria.splice(i, 1); break; } } this.update(); }; DataTableView.prototype._addSortingCriterion = function(criterion, alone) { if (alone) { this._sorting.criteria = []; } else { for (var i = 0; i < this._sorting.criteria.length; i++) { if (this._sorting.criteria[i].column == criterion.column) { this._sorting.criteria[i] = criterion; this.update(); return; } } } this._sorting.criteria.push(criterion); this.update(); }; DataTableView.prototype._createMenuForAllColumns = function(elmt) { var self = this; MenuSystem.createAndShowStandardMenu([ { label: "Facet", submenu: [ { label: "Facet by Star", click: function() { ui.browsingEngine.addFacet( "list", { "name" : "Starred Rows", "columnName" : "", "expression" : "row.starred" }, { "scroll" : false } ); } }, { label: "Facet by Flag", click: function() { ui.browsingEngine.addFacet( "list", { "name" : "Flagged Rows", "columnName" : "", "expression" : "row.flagged" }, { "scroll" : false } ); } } ] }, { label: "Edit Rows", submenu: [ { label: "Star Rows", click: function() { Gridworks.postProcess("annotate-rows", { "starred" : "true" }, null, { rowMetadataChanged: true }); } }, { label: "Unstar Rows", click: function() { Gridworks.postProcess("annotate-rows", { "starred" : "false" }, null, { rowMetadataChanged: true }); } }, {}, { label: "Flag Rows", click: function() { Gridworks.postProcess("annotate-rows", { "flagged" : "true" }, null, { rowMetadataChanged: true }); } }, { label: "Unflag Rows", click: function() { Gridworks.postProcess("annotate-rows", { "flagged" : "false" }, null, { rowMetadataChanged: true }); } }, {}, { label: "Remove All Matching Rows", click: function() { Gridworks.postProcess("remove-rows", {}, null, { rowMetadataChanged: true }); } } ] }, { label: "View", submenu: [ { label: "Collapse All Columns", click: function() { for (var i = 0; i < theProject.columnModel.columns.length; i++) { self._collapsedColumnNames[theProject.columnModel.columns[i].name] = true; } self.render(); } }, { label: "Expand All Columns", click: function() { self._collapsedColumnNames = []; self.render(); } } ] } ], elmt, { width: "80px", horizontal: false }); }; DataTableView.prototype._createSortingMenu = function(elmt) { var self = this; var items = [ { "label" : "Un-sort", "click" : function() { self._sorting.criteria = []; self.update(); } }, { "label" : "Reorder Rows Permanently", "click" : function() { Gridworks.postProcess( "reorder-rows", null, { "sorting" : JSON.stringify(self._sorting) }, { rowMetadataChanged: true }, { onDone: function() { self._sorting.criteria = []; } } ); } }, {} ]; var getColumnHeaderUI = function(columnName) { for (var i = 0; i < self._columnHeaderUIs.length; i++) { var columnHeaderUI = self._columnHeaderUIs[i]; if (columnHeaderUI.getColumn().name == columnName) { return columnHeaderUI; } } return null; } var createSubmenu = function(criterion) { var columnHeaderUI = getColumnHeaderUI(criterion.column); if (columnHeaderUI != null) { items.push({ "label" : "By " + criterion.column, "submenu" : columnHeaderUI.createSortingMenu() }) } }; for (var i = 0; i < this._sorting.criteria.length; i++) { createSubmenu(this._sorting.criteria[i]); } MenuSystem.createAndShowStandardMenu(items, elmt, { horizontal: false }); }; DataTableView.prototype._updateCell = function(rowIndex, cellIndex, cell) { var rows = theProject.rowModel.rows; for (var r = 0; r < rows.length; r++) { var row = rows[r]; if (row.i === rowIndex) { while (cellIndex >= row.cells.length) { row.cells.push(null); } row.cells[cellIndex] = cell; break; } } }; DataTableView.sampleVisibleRows = function(column) { 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 && column.cellIndex < row.cells.length) { var cell = row.cells[column.cellIndex]; if (cell !== null) { v = cell.v; } } values.push(v); } return { rowIndices: rowIndices, values: values }; }; DataTableView.promptExpressionOnVisibleRows = function(column, title, expression, onDone) { var o = DataTableView.sampleVisibleRows(column); var self = this; new ExpressionPreviewDialog( title, column.cellIndex, o.rowIndices, o.values, expression, onDone ); };