Commit 88d8eb71 authored by Joshua Gould's avatar Joshua Gould

include column dendrogram

parent ec5d8e3e
/*global module:false*/
module.exports = function(grunt) {
module.exports = function (grunt) {
grunt
.initConfig({
pkg : grunt.file.readJSON('package.json'),
meta : {
banner : '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - '
+ '<%= grunt.template.today("yyyy-mm-dd") %>\n'
+ '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>'
+ '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>; %> */'
.initConfig({
pkg: grunt.file.readJSON('package.json'),
meta: {
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - '
+ '<%= grunt.template.today("yyyy-mm-dd") %>\n'
+ '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>'
+ '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>; %> */'
},
uglify: {
morpheus: {
options: {
mangle: false,
preserveComments: false
},
uglify : {
morpheus : {
options : {
mangle : false,
preserveComments : false
},
files : {
'js/morpheus-latest.min.js' : [ 'js/morpheus.js' ]
}
},
extJs : {
options : {
mangle : false,
preserveComments : false
},
files : {
'js/morpheus-external.min.js' : [ 'js/morpheus-external.js' ]
}
}
},
cssmin : {
css : {
src : 'css/morpheus.all.css',
dest : 'css/morpheus-latest.min.css'
}
},
concat : {
css : {
src : [ 'css/bootstrap.min.css',
'css/bootstrap-select.min.css',
'css/jquery-ui.min.css',
'css/font-awesome.min.css',
'css/hopscotch.min.css', 'css/slick.grid.css',
'css/animate.css', 'css/morpheus.css' ],
dest : 'css/morpheus.all.css'
},
extJsAll : {
src : [ 'js/morpheus-external.min.js',
'js/plotly-latest.min.js' ],
dest : 'js/morpheus-external-latest.min.js'
},
extJs : {
nonull : true,
dest : 'js/morpheus-external.js',
src : [ 'js/d3.min.js', 'js/jquery-1.11.1.min.js',
'js/bootstrap.min.js', 'js/underscore-min.js',
'js/newick.js', 'js/hammer.min.js',
'js/jquery.mousewheel.min.js',
'js/bootstrap-select.min.js',
'js/xlsx.full.min.js', 'js/canvas2svg.js',
'js/canvg.js', 'js/rgbcolor.js',
'js/jquery-ui.min.js', 'js/parser.js',
'js/FileSaver.min.js', 'js/Blob.js',
'js/canvas-toBlob.js', 'js/colorbrewer.js',
'js/hopscotch.min.js', 'js/typed.min.js',
'js/jquery.event.drag-2.2.js',
'js/clipboard.min.js', 'js/slick.min.js',
'js/js.cookie.js', 'js/d3.layout.cloud.js' ]
},
morpheus : {
nonull : true,
dest : 'js/morpheus.js',
src : [ 'src/util/util.js', 'src/util/*.js',
'src/io/*.js', 'src/matrix/vector_adapter.js',
'src/matrix/*.js', 'src/*.js',
'src/tools/*.js', 'src/ui/*.js', 'src/**/*.js' ]
}
files: {
'js/morpheus-latest.min.js': ['js/morpheus.js']
}
},
extJs: {
options: {
mangle: false,
preserveComments: false
},
watch : {
files : [ 'src/*.js', 'src/**/*.js' ],
tasks : [ 'concat:morpheus' ]
files: {
'js/morpheus-external.min.js': ['js/morpheus-external.js']
}
});
}
},
cssmin: {
css: {
src: 'css/morpheus.all.css',
dest: 'css/morpheus-latest.min.css'
}
},
concat: {
css: {
src: ['css/bootstrap.min.css',
'css/bootstrap-select.min.css',
'css/jquery-ui.min.css',
'css/font-awesome.min.css',
'css/hopscotch.min.css', 'css/slick.grid.css', 'css/morpheus.grid.css',
'css/animate.css', 'css/morpheus.css'],
dest: 'css/morpheus.all.css'
},
extJsAll: {
src: ['js/morpheus-external.min.js',
'js/plotly-latest.min.js'],
dest: 'js/morpheus-external-latest.min.js'
},
extJs: {
nonull: true,
dest: 'js/morpheus-external.js',
src: ['js/d3.min.js', 'js/jquery-1.11.1.min.js',
'js/bootstrap.min.js', 'js/underscore-min.js',
'js/newick.js', 'js/hammer.min.js',
'js/jquery.mousewheel.min.js',
'js/bootstrap-select.min.js',
'js/xlsx.full.min.js', 'js/canvas2svg.js',
'js/canvg.js', 'js/rgbcolor.js',
'js/jquery-ui.min.js', 'js/parser.js',
'js/FileSaver.min.js', 'js/Blob.js',
'js/canvas-toBlob.js', 'js/colorbrewer.js',
'js/hopscotch.min.js', 'js/typed.min.js',
'js/jquery.event.drag-2.2.js',
'js/clipboard.min.js', 'js/slick.min.js',
'js/js.cookie.js', 'js/d3.layout.cloud.js']
},
morpheus: {
nonull: true,
dest: 'js/morpheus.js',
src: ['src/util/util.js', 'src/util/*.js',
'src/io/*.js', 'src/matrix/vector_adapter.js',
'src/matrix/*.js', 'src/*.js',
'src/tools/*.js', 'src/ui/*.js', 'src/**/*.js']
}
},
watch: {
files: ['src/*.js', 'src/**/*.js'],
tasks: ['concat:morpheus']
}
});
// rebuild js and css:
// grunt concat:morpheus concat:extJs uglify concat:extJsAll
......
This source diff could not be displayed because it is too large. You can view the blob instead.
.slick-cell {
margin: 0px;
border: none;
padding: 0px;
background-color: inherit;
white-space: normal !important;
}
.slick-row {
font-size: 13px;
line-height: 100%;
padding: 0px;
margin: 0px;
}
.slick-header-column.ui-state-default {
height: 20px;
line-height: 20px;
padding: 0px;
background: none;
background-color: #f6f7f8;
}
.slick-header-columns {
background-color: white;
}
.slick-table .ui-widget-content {
background: none;
}
.slick-table-compact .slick-row {
font-size: 12px;
}
.slick-table .slick-row {
background-color: white;
}
.slick-striped-table .slick-row.odd {
background-color: #fafafa;
}
.slick-bordered-table .ui-widget-content {
border-bottom: 1px solid #eee !important;
}
.slick-header-column {
color: black;
background-color: white;
font-weight: bold;
border-left: 1px solid black;
}
.slick-cell, .slick-headerrow-column {
overflow: hidden;
text-overflow: ellipsis;
}
.slick-header {
background-color: white;
border: none !important;
}
.slick-cell.selected {
background-color: #d9edf7;
}
.slick-stacked .slick-visible-stacked {
display: block;
}
.slick-table:not (.slick-stacked) .slick-visible-not-stacked {
display: block;
}
.slick-visible-not-stacked {
display: none;
}
.slick-visible-stacked {
display: none;
}
.slick-sort-indicator-desc {
background: none;
}
.slick-sort-indicator-asc {
background: none;
}
.slick-sort-indicator-desc::after {
content: "\f0dd";
font-family: FontAwesome;
margin-right: 3px;
margin-left: 4px;
margin-top: -3px;
}
.slick-sort-indicator {
float: none !important;
margin: 0 !important;
}
.slick-header-column-sorted {
font-style: normal;
}
.slick-column-name {
margin-left: 4px;
}
.slick-sort-indicator-asc::after {
content: "\f0de";
font-family: FontAwesome;
margin-right: 3px;
margin-left: 4px;
margin-top: -3px;
float: none;
}
.slick-cell-wrapper {
max-width: 0;
overflow: hidden;
vertical-align: middle;
display: table-cell;
text-overflow: ellipsis;
}
.slick-table-wrapper {
display: table;
height: 100%;
padding-left: 2px;
width: 100%;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3,22 +3,22 @@
* options.set set of selected items
* @see morpheus.Table
*/
morpheus.CheckBoxList = function(options) {
morpheus.CheckBoxList = function (options) {
var _this = this;
var set = options.set || new morpheus.Set();
options = $.extend(true, {}, {
height : '138px',
showHeader : false,
select : false,
search : true,
checkBoxSelectionOnTop : false,
rowHeader : function(item) {
height: '150px',
showHeader: false,
select: false,
search: true,
checkBoxSelectionOnTop: false,
rowHeader: function (item) {
var header = [];
// header
// .push('<div style="overflow: hidden;text-overflow: ellipsis;"
// class="morpheus-hover">');
header.push('<span><input name="toggle" type="checkbox" '
+ (set.has(_this.getter(item)) ? ' checked' : '') + '/> ');
+ (set.has(_this.getter(item)) ? ' checked' : '') + '/> ');
header.push('</span>');
// header
// .push('<button
......@@ -48,42 +48,44 @@ morpheus.CheckBoxList = function(options) {
var html = [];
var table = new morpheus.Table(options);
if (options.columns.length === 1) {
options.$el.find('.slick-table-header').find('[name=right]').remove();
}
this.table = table;
var html = [];
html.push('<div style="font-size:12px;">');
html.push('<div style="display:inline;">');
html.push('<div style="display:inline;" class="dropdown">');
html
.push('<button type="button" data-toggle="dropdown" class="btn btn-default btn-xs dropdown-toggle" aria-haspopup="true" aria-expanded="false">');
.push('<button type="button" data-toggle="dropdown" class="btn btn-default btn-xs dropdown-toggle" aria-haspopup="true" aria-expanded="false">');
html.push('<span class="caret"></span>');
html.push('</button>');
html.push('<ul style="font-size:12px;" class="dropdown-menu">');
html.push('<li><a name="selectAll" href="#">All</a></li>');
html.push('<li><a name="selectNone" href="#">None</a></li>');
html.push('<li><a name="invertSel" href="#">Invert</a></li>');
html.push('<li><a name="selectAll" href="#">Select All</a></li>');
html.push('<li><a name="selectNone" href="#">Select None</a></li>');
html.push('<li><a name="invertSel" href="#">Invert Selection</a></li>');
html.push('</ul>');
html.push('</div>');
html.push('<span name="checkBoxResults" style="padding-left:6px;"></span>');
html.push('</div>');
var $div = $(html.join(''));
var $checkBoxResults = $div.find('[name=checkBoxResults]');
table.$gridDiv.before($div);
var $selectAll = $div.find('[name=selectAll]');
var $selectNone = $div.find('[name=selectNone]');
$selectAll.on('click', function(e) {
var $checkBoxEl = $(html.join(''));
table.$header.find('[name=left]').html($checkBoxEl);
var $checkBoxResults = $checkBoxEl.find('[name=checkBoxResults]');
var $selectAll = $checkBoxEl.find('[name=selectAll]');
var $selectNone = $checkBoxEl.find('[name=selectNone]');
$selectAll.on('click', function (e) {
var items = table.getItems();
for (var i = 0, nitems = items.length; i < nitems; i++) {
set.add(_this.getter(items[i]));
}
_this.table.trigger('checkBoxSelectionChanged', {
source : _this,
set : set
source: _this,
set: set
});
e.preventDefault();
_this.table.redraw();
});
$div.find('[name=invertSel]').on('click', function(e) {
$checkBoxEl.find('[name=invertSel]').on('click', function (e) {
// selected become unselected, unselected become selected
var items = table.getItems();
for (var i = 0, nitems = items.length; i < nitems; i++) {
......@@ -96,20 +98,20 @@ morpheus.CheckBoxList = function(options) {
}
_this.table.trigger('checkBoxSelectionChanged', {
source : _this,
set : set
source: _this,
set: set
});
e.preventDefault();
_this.table.redraw();
});
$selectNone.on('click', function(e) {
$selectNone.on('click', function (e) {
var items = table.getItems();
for (var i = 0, nitems = items.length; i < nitems; i++) {
set.remove(_this.getter(items[i]));
}
_this.table.trigger('checkBoxSelectionChanged', {
source : _this,
set : set
source: _this,
set: set
});
e.preventDefault();
......@@ -119,10 +121,10 @@ morpheus.CheckBoxList = function(options) {
this.set = set;
this.table = table;
$checkBoxResults.html('selected ' + morpheus.Util.intFormat(set.size())
+ ' of ' + morpheus.Util.intFormat(table.getAllItemCount()));
+ ' of ' + morpheus.Util.intFormat(table.getAllItemCount()));
var priorCount = 0;
this.table.on('checkBoxSelectionChanged', function() {
this.table.on('checkBoxSelectionChanged', function () {
// if (options.checkBoxSelectionOnTop) {
// var selectedItems = set.values();
// selectedItems.sort();
......@@ -146,91 +148,91 @@ morpheus.CheckBoxList = function(options) {
// priorCount = set.size();
// }
$checkBoxResults.html('selected ' + morpheus.Util.intFormat(set.size())
+ ' of ' + morpheus.Util.intFormat(table.getAllItemCount()));
+ ' of ' + morpheus.Util.intFormat(table.getAllItemCount()));
_this.table.redraw();
});
table.on('click',
function(e) {
var $target = $(e.target);
var item = table.getItems()[e.row];
var value = _this.getter(item);
if ($target.is('.morpheus-hover-show')) { // only
set.clear();
function (e) {
var $target = $(e.target);
var item = table.getItems()[e.row];
var value = _this.getter(item);
if ($target.is('.morpheus-hover-show')) { // only
set.clear();
set.add(value);
_this.table.trigger('checkBoxSelectionChanged', {
source: _this,
set: set
});
} else if (!options.select
|| ($target.is('[type=checkbox]') && $target
.attr('name') === 'toggle')) {
if (set.has(value)) {
set.remove(value);
} else {
set.add(value);
_this.table.trigger('checkBoxSelectionChanged', {
source : _this,
set : set
});
} else if (!options.select
|| ($target.is('[type=checkbox]') && $target
.attr('name') === 'toggle')) {
if (set.has(value)) {
set.remove(value);
} else {
set.add(value);
}
_this.table.trigger('checkBoxSelectionChanged', {
source : _this,
set : set
});
}
_this.table.trigger('checkBoxSelectionChanged', {
source: _this,
set: set
});
}
});
});
};
morpheus.CheckBoxList.prototype = {
searchWithPredicates : function(predicates) {
searchWithPredicates: function (predicates) {
this.table.searchWithPredicates(predicates);
},
autocomplete : function(tokens, cb) {
autocomplete: function (tokens, cb) {
this.table.autocomplete(tokens, cb);
},
setHeight : function(height) {
setHeight: function (height) {
this.table.setHeight(height);
},
resize : function() {
resize: function () {
this.table.resize();
},
setSearchVisible : function(visible) {
setSearchVisible: function (visible) {
this.table.setSearchVisible(visible);
},
getSelectedRows : function() {
getSelectedRows: function () {
return this.table.getSelectedRows();
},
getSelectedItems : function() {
getSelectedItems: function () {
return this.table.getSelectedItems();
},
setSelectedRows : function(rows) {
setSelectedRows: function (rows) {
this.table.setSelectedRows(rows);
},
getItems : function(items) {
getItems: function (items) {
return this.table.getItems();
},
getAllItemCount : function() {
getAllItemCount: function () {
return this.table.getAllItemCount();
},
getFilteredItemCount : function() {
getFilteredItemCount: function () {
return this.table.getFilteredItemCount();
},
setFilter : function(f) {
setFilter: function (f) {
this.table.setFilter(f);
},
redraw : function() {
redraw: function () {
this.table.redraw();
},
getSelection : function() {
getSelection: function () {
return this.set;
},
clearSelection : function(values) {
clearSelection: function (values) {
this.set.clear();
this.table.redraw();
},
setValue : function(values) {
setValue: function (values) {
this.setSelectedValues(values);
},
setSelectedValues : function(values) {
setSelectedValues: function (values) {
this.set.clear();
if (morpheus.Util.isArray(values)) {
......@@ -242,17 +244,17 @@ morpheus.CheckBoxList.prototype = {
}
this.table.redraw();
},
val : function() {
val: function () {
return this.set.values();
},
on : function(evtStr, handler) {
on: function (evtStr, handler) {
this.table.on(evtStr, handler);
return this;
},
off : function(evtStr, handler) {
off: function (evtStr, handler) {
this.table.off(evtStr, handler);
},
setItems : function(items) {
setItems: function (items) {
// remove items in selection that are not in new items
var newItems = new morpheus.Set();
var getter = this.getter;
......@@ -261,21 +263,16 @@ morpheus.CheckBoxList.prototype = {
}
var selection = this.set;
selection.forEach(function(val) {
selection.forEach(function (val) {
if (!newItems.has(val)) {
selection.remove(val);
}
});
// if (this.table.tableSearch) {
// this.table.tableSearch.$el.css('display',
// items.length <= 6 ? 'none' : '');
// }
this.table.setItems(items);
this.table.trigger('checkBoxSelectionChanged', {
source : this,
set : selection
source: this,
set: selection
});
}
};
......@@ -14,6 +14,7 @@ morpheus.Grid = function (options) {
return column.getter(item);
}
this.filter = new morpheus.CombinedGridFilter();
var model = {
getLength: function () {
return _this.viewOrder != null ? _this.viewOrder.length
......@@ -115,10 +116,7 @@ morpheus.Grid = function (options) {
}
}
if (column != null) {
sortCols.push({
sortCol: column,
sortAsc: c.sortAsc
});
gridSortColumns.push({
columnId: column.id,
sortAsc: c.sortAsc
......@@ -127,10 +125,7 @@ morpheus.Grid = function (options) {
console.log(c.name + ' not found.');
}
});
grid.setSortColumns(gridSortColumns);
this.sortCols = sortCols;
this._updateMappings();
grid.invalidate();
this.setSortColumns(gridSortColumns);
}
this.grid.invalidate();
......@@ -138,6 +133,23 @@ morpheus.Grid = function (options) {
};
morpheus.Grid.prototype = {
columnsAutosized: false,
setSortColumns: function (gridSortColumns) {
this.grid.setSortColumns(gridSortColumns);
this.sortCols = [];
for (var i = 0; i < gridSortColumns.length; i++) {
var column = this.grid.getColumns()[this.grid.getColumnIndex(gridSortColumns[i].columnId)];
if (column == null) {
throw "Unable to find column " + gridSortColumns[i];
}
this.sortCols.push({
sortCol: column,
sortAsc: gridSortColumns[i].sortAsc
});
}
this._updateMappings();
this.grid.invalidate();
},
setColumns: function (columns) {
this.grid.setColumns(columns);
this.grid.resizeCanvas();
......@@ -200,10 +212,12 @@ morpheus.Grid.prototype = {
this.grid.setSelectedRows([]);
}
this.setFilter(this.filter);
this.maybeAutoResizeColumns();
},
maybeAutoResizeColumns: function () {
if (!this.columnsAutosized) {
this.autosizeColumns();
}
},
convertModelIndexToView: function (modelIndex) {
if (this.modelToView !== null) {
......@@ -229,14 +243,16 @@ morpheus.Grid.prototype = {
}
this.viewOrder = null;
if (this.filter != null) {
this.viewOrder = [];
for (var i = 0, length = this.items.length; i < length; i++) {
if (this.filter(this.items[i])) {
this.viewOrder.push(i);
this.filter.init();
if (!this.filter.isEmpty()) {
this.viewOrder = [];
for (var i = 0, length = this.items.length; i < length; i++) {
if (this.filter.accept(this.items[i])) {
this.viewOrder.push(i);
}
}
}
}
var cols = this.sortCols;
if (cols && cols.length > 0) {
if (this.viewOrder == null) {
......@@ -247,14 +263,15 @@ morpheus.Grid.prototype = {
}
var ncols = cols.length;
var items = this.items;
// nulls always go at end
this.viewOrder.sort(function (index1, index2) {
for (var i = 0; i < ncols; i++) {
var getter = cols[i].sortCol.getter;
var sign = cols[i].sortAsc ? 1 : -1;
var comparator = cols[i].sortAsc ? morpheus.SortKey.ASCENDING_COMPARATOR : morpheus.SortKey.DESCENDING_COMPARATOR;
var value1 = getter(items[index1]);
var value2 = getter(items[index2]);
var comparator = cols[i].sortCol.comparator;
var result = comparator(value1, value2) * sign;
var result = comparator(value1, value2);
if (result !== 0) {
return result;
}
......@@ -295,78 +312,78 @@ morpheus.Grid.prototype = {
return this.filter;
},
autosizeColumns: function () {
var columns = this.grid.getColumns();
var items = this.getItems();
if (!items || items.length == 0) {
if (!items || items.length === 0 || !columns || columns.length === 0) {
return;
}
if (!columns || columns.length === 0) {
var gridWidth = this.options.$el.width() - 30;
if (gridWidth <= 0) {
return;
}
this.columnsAutosized = true;
if (columns.length <= 1) {
return;
}
var div = document.createElement('div');
document.body.appendChild(div);
var $d = $(div);
if (columns.length > -1) {
var div = document.createElement('div');
document.body.appendChild(div);
var $d = $(div);
$d.css({
position: 'absolute',
left: -1000,
top: -1000
});
$d.css({
position: 'absolute',
left: -1000,
top: -1000
});
var $row = $('<div class="slick-table">'
+ '<div class="ui-state-default slick-header-column slick-header-sortable ui-sortable-handle"></div>'
+ '<div class="ui-widget-content slick-row"><div class="slick-cell selected"></div></div>'
+ '</div>');
var $cell = $row.find('.slick-cell');
var $header = $row.find('.slick-header-column');
$row.appendTo($d);
var $row = $('<div class="slick-table">'
+ '<div class="ui-state-default slick-header-column slick-header-sortable ui-sortable-handle"></div>'
+ '<div class="ui-widget-content slick-row"><div class="slick-cell selected"></div></div>'
+ '</div>');
var $cell = $row.find('.slick-cell');
var $header = $row.find('.slick-header-column');
$row.appendTo($d);
var gridWidth = this.options.$el.width() - 30;
var maxWidth = Math.min(parseInt(gridWidth / 2), 400);
var getColumnWidth = function (column) {
var w = $header.html(column.name).outerWidth() + 13; // leave space for sort indicator
var maxWidth = Math.min(parseInt(gridWidth / 2), 400);
var getColumnWidth = function (column) {
var w = $header.html(column.name).outerWidth() + 13; // leave space for sort indicator
if (column.prototypeValue) {
$cell.html(column.prototypeValue);
w = Math.max($cell.outerWidth(), w);
} else {
for (var i = 0, nrows = Math.min(items.length, 10); i < nrows; i++) {
var html = column.formatter(i, null, column
.getter(items[i]), column, items[i]);
var $html = $(html);
$html.find('.slick-cell-wrapper').attr('class', '');
$cell.html($html);
if (column.prototypeValue) {
$cell.html(column.prototypeValue);
w = Math.max($cell.outerWidth(), w);
} else {
for (var i = 0, nrows = Math.min(items.length, 10); i < nrows; i++) {
var html = column.formatter(i, null, column
.getter(items[i]), column, items[i]);
var $html = $(html);
$html.find('.slick-cell-wrapper').attr('class', '');
$cell.html($html);
w = Math.max($cell.outerWidth(), w);
}
}
column.width = parseInt(Math.min(maxWidth, w));
};
var totalWidth = 0;
for (var i = 0; i < columns.length; i++) {
getColumnWidth(columns[i]);
totalWidth += columns[i].width;
}
column.width = parseInt(Math.min(maxWidth, w));
};
var totalWidth = 0;
for (var i = 0; i < columns.length; i++) {
getColumnWidth(columns[i]);
totalWidth += columns[i].width;
}
if (totalWidth < gridWidth) {
// grow columns
// var delta = parseInt((gridWidth - totalWidth) / columns.length);
// for (var i = 0; i < columns.length; i++) {
// //columns[i].width += delta;
// }
} else if (totalWidth > gridWidth) {
// shrink
//columns[columns.length - 1].width -= (totalWidth - gridWidth);
// shrink last column
if (totalWidth < gridWidth) {
// grow columns
// var delta = parseInt((gridWidth - totalWidth) / columns.length);
// for (var i = 0; i < columns.length; i++) {
// //columns[i].width += delta;
// }
} else if (totalWidth > gridWidth) {
// shrink
//columns[columns.length - 1].width -= (totalWidth - gridWidth);
// shrink last column
}
$d.remove();
this.grid.resizeCanvas();
}
$d.remove();
this.grid.resizeCanvas();
}
};
......@@ -524,3 +541,42 @@ morpheus.AutoTooltips2 = function (options) {
});
};
morpheus.CombinedGridFilter = function () {
this.filters = [];
};
morpheus.CombinedGridFilter.prototype = {
add: function (filter) {
this.filters.push(filter);
},
getFilters: function () {
return this.filters;
},
get: function (index) {
return this.filters[index];
},
set: function (index, f) {
this.filters[index] = f;
},
init: function () {
for (var i = 0; i < this.filters.length; i++) {
this.filters[i].init();
}
this.activeFilters = this.filters.filter(function (f) {
return !f.isEmpty();
});
this.nActiveFilters = this.activeFilters.length;
},
accept: function (item) {
for (var i = 0; i < this.nActiveFilters; i++) {
if (!this.activeFilters[i].accept(item)) {
return false;
}
}
return true;
},
isEmpty: function () {
return this.activeFilters.length === 0;
}
};
......@@ -2949,10 +2949,10 @@ morpheus.HeatMap.prototype = {
height: heatmapPrefSize.height
};
if (this.isDendrogramVisible(false)) { // row dendrogram
totalSize.width += this.rowDendrogram.getUnscaledWidth();
totalSize.width += this.rowDendrogram.getUnscaledWidth() + morpheus.HeatMap.SPACE_BETWEEN_HEAT_MAP_AND_ANNOTATIONS;
}
if (this.isDendrogramVisible(true)) {
totalSize.height += this.columnDendrogram.getUnscaledHeight();
totalSize.height += this.columnDendrogram.getUnscaledHeight() + morpheus.HeatMap.SPACE_BETWEEN_HEAT_MAP_AND_ANNOTATIONS;
}
var maxRowHeaderHeight = 0;
for (var i = 0, length = this.rowTracks.length; i < length; i++) {
......@@ -3067,12 +3067,13 @@ morpheus.HeatMap.prototype = {
context.restore();
legendHeight += Math.max(rowTrackLegend.getPreferredSize().height,
columnTrackLegendSize.height);
var heatmapY = this.isDendrogramVisible(true) ? this.columnDendrogram
.getUnscaledHeight() : 0;
var heatmapY = this.isDendrogramVisible(true) ? (this.columnDendrogram
.getUnscaledHeight() + morpheus.HeatMap.SPACE_BETWEEN_HEAT_MAP_AND_ANNOTATIONS) : 0;
heatmapY += legendHeight;
var columnTrackY = heatmapY;
var heatmapX = this.isDendrogramVisible(false) ? this.rowDendrogram
.getUnscaledWidth() : 0;
var heatmapX = this.isDendrogramVisible(false) ? (this.rowDendrogram
.getUnscaledWidth() + morpheus.HeatMap.SPACE_BETWEEN_HEAT_MAP_AND_ANNOTATIONS) : 0;
var isColumnTrackVisible = false;
for (var i = 0, length = this.columnTracks.length; i < length; i++) {
var track = this.columnTracks[i];
......@@ -3095,6 +3096,19 @@ morpheus.HeatMap.prototype = {
heatmapY = Math.max(heatmapY, header.getPrintSize().height);
}
}
if (this.isDendrogramVisible(true)) {
var columnDendrogramClip = {
x: 0,
y: 0,
height: this.columnDendrogram.getUnscaledHeight(),
width: heatmapPrefSize.width
};
context.save();
context.translate(heatmapX, legendHeight);
this.columnDendrogram.prePaint(columnDendrogramClip, context);
this.columnDendrogram.draw(columnDendrogramClip, context);
context.restore();
}
if (this.isDendrogramVisible(false)) {
var rowDendrogramClip = {
x: 0,
......
......@@ -32,6 +32,7 @@ morpheus.Table = function (options) {
this.$gridDiv = $gridDiv;
$gridDiv.appendTo(options.$el);
// all columns (including those that are currently not visible */
var columns = options.columns;
this.columns = columns;
var visibleColumns = columns.filter(function (c) {
......@@ -51,16 +52,36 @@ morpheus.Table = function (options) {
columns: visibleColumns
});
this.grid = grid;
this.searchFunction = null;
var searchFilter = {
isEmpty: function () {
return _this.searchFunction == null;
},
init: function () {
},
accept: function (item) {
return _this.searchFunction(item);
}
};
// add empty search filter
this.grid
.getFilter().add(searchFilter);
var $header = $('<div class="slick-table-header"><div name="top"></div><div style="display: inline-block;" name="left" class="pad-bottom-8 pad-top-8"></div><div name="right" class="pull-right pad-bottom-8' +
' pad-top-8"></div></div>');
this.$header = $header;
var $right = $header.find('.pull-right');
if (options.search) {
var tableSearch = new morpheus.TableSearchUI();
tableSearch.$el.prependTo(options.$el);
var tableSearch = new morpheus.TableSearchUI({
$el: $header.find('[name=top]'),
$right: $right
});
tableSearch.setTable(this);
this.tableSearch = tableSearch;
}
if (visibleColumns.length !== this.columns.length) {
if (options.columnPicker && visibleColumns.length !== this.columns.length) {
var select = [];
select
.push('<select data-selected-text-format="static" title="Columns..." multiple class="form-control selectpicker show-tick pull-right">');
.push('<select data-width="90px" data-selected-text-format="static" title="Columns..." multiple class="pad-left-4 selectpicker show-tick">');
// sort column names
var sortedColumns = this.columns.slice().sort(function (a, b) {
a = a.name.toLowerCase();
......@@ -78,32 +99,49 @@ morpheus.Table = function (options) {
});
select.push('</select>');
var $select = $(select.join(''));
var $div = $('<div class="pull-right"></div>');
$select.appendTo($div);
$div.prependTo(options.$el);
$select.appendTo($right);
$select.selectpicker({
iconBase: 'fa',
tickIcon: 'fa-check',
style: 'btn-default btn-sm'
style: 'btn-default btn-xs'
});
$select.on('change', function () {
var selectedItems = $select.val();
var selectedItemsSet = new morpheus.Set();
selectedItems.forEach(function (item) {
selectedItemsSet.add(parseInt(item));
var oldColumns = grid.getColumns().map(function (c) {
return c.id;
});
var selectedColumnIndices = $select.val();
visibleColumns = [];
_this.columns.forEach(function (c, i) {
if (selectedItemsSet.has(i)) {
visibleColumns.push(c);
}
for (var i = 0; i < selectedColumnIndices.length; i++) {
visibleColumns.push(sortedColumns[parseInt(selectedColumnIndices[i])]);
}
var newColumns = visibleColumns.map(function (c) {
return c.id;
});
grid.setColumns(visibleColumns);
if (newColumns.length > oldColumns.length) {
var set = new morpheus.Set();
for (var i = 0; i < newColumns.length; i++) {
set.add(newColumns[i]);
}
for (var i = 0; i < oldColumns.length; i++) {
set.remove(oldColumns[i]);
}
var added = set.values();
grid.setSortColumns([{
columnId: added[0],
sortAsc: true
}]);
}
// if column added, sort by added column
_this.resize();
_this.redraw();
});
}
$header.prependTo(options.$el);
var collapsed = false;
var lastWidth = -1;
var resize = function () {
......@@ -180,6 +218,7 @@ morpheus.Table = function (options) {
$gridDiv.find('.slick-header').hide();
_this.grid.grid.resizeCanvas();
_this.grid.grid.invalidate();
} else if (collapsed && gridWidth >= options.collapseBreakpoint) {
$gridDiv.removeClass('slick-stacked');
collapsed = false;
......@@ -198,6 +237,7 @@ morpheus.Table = function (options) {
_this.grid.grid.resizeCanvas();
_this.grid.grid.invalidate();
}
_this.grid.maybeAutoResizeColumns();
};
if (!options.showHeader) {
......@@ -215,11 +255,40 @@ morpheus.Table = function (options) {
&& options.items.length > 0) {
this.setItems(options.items);
}
if (!$gridDiv.is(':visible')) {
// find 1st parent that is not visible
var $parent = $gridDiv;
var observer = new MutationObserver(function (mutations) {
if (window.getComputedStyle($parent[0]).display !== 'none') {
observer.disconnect();
resize();
}
});
};
while ($parent.length > 0) {
if (window.getComputedStyle($parent[0]).display === 'none') {
break;
}
$parent = $parent.parent();
}
if ($parent.length > 0) {
observer.observe($parent[0], {
attributes: true,
childList: false,
characterData: false
});
}
}
}
;
morpheus.Table.defaultRenderer = function (item, value) {
if (_.isNumber(value)) {
if (value == null) {
return '';
} else if (_.isNumber(value)) {
return morpheus.Util.nf(value);
} else if (morpheus.Util.isArray(value)) {
var s = [];
......@@ -237,7 +306,32 @@ morpheus.Table.defaultRenderer = function (item, value) {
};
morpheus.Table.prototype = {
toText: function () {
var text = [];
var items = this.getItems();
var columns = this.columns.filter(function (c) {
return c.visible;
});
for (var j = 0; j < columns.length; j++) {
if (j > 0) {
text.push('\t');
}
text.push(columns[j].name);
}
text.push('\n');
for (var i = 0; i < items.length; i++) {
var item = items[i];
for (var j = 0; j < columns.length; j++) {
if (j > 0) {
text.push('\t');
}
var value = columns[j].getter(item);
text.push(morpheus.Util.toString(value));
}
text.push('\n');
}
return text.join('');
},
setHeight: function (height) {
this.options.height = height;
if (height === 'auto') {
......@@ -258,13 +352,7 @@ morpheus.Table.prototype = {
},
setSearchVisible: function (visible) {
if (this.tableSearch) {
if (!visible) {
this.tableSearch.$el.hide();
} else {
this.tableSearch.$el.show();
}
}
this.$header.find('[name=search]').css('display', visible ? '' : 'none');
},
autocomplete: function (tokens, response) {
var matches = [];
......@@ -272,7 +360,7 @@ morpheus.Table.prototype = {
: '';
token = $.trim(token);
var columns = this.columns.filter(function (c) {
return c.searchable && c.visible;
return (c.searchable && c.visible) || c.alwaysSearch;
});
var ncolumns = columns.length;
......@@ -355,7 +443,7 @@ morpheus.Table.prototype = {
}
}
if (dataType === 'string' || dataType === '[string]') {
dataTypes.push('string');
dataTypes.push(dataType);
filteredColumns.push(c);
}
});
......@@ -369,7 +457,7 @@ morpheus.Table.prototype = {
var value = columns[j].getter(item);
var dataType = dataTypes[j];
if (dataType === '[string]') {
var nvalues = value.length;
var nvalues = value == null ? 0 : value.length;
for (var k = 0; k < nvalues; k++) {
var val = value[k];
if (regex.test(val) && !set.has(val)) {
......@@ -419,11 +507,14 @@ morpheus.Table.prototype = {
},
searchWithPredicates: function (predicates) {
if (predicates == null || predicates.length === 0) {
this.grid.setFilter(null);
this.searchFunction = null;
this.grid
.setFilter(this.grid
.getFilter());
return;
}
var columns = this.columns.filter(function (c) {
return c.searchable && c.visible;
return (c.searchable && c.visible) || c.alwaysSearch;
});
var columnNameToColumn = new morpheus.Map();
var columnNames = columns.map(function (c) {
......@@ -450,8 +541,7 @@ morpheus.Table.prototype = {
}
predicates = filteredPredicates;
npredicates = predicates.length;
this.grid
.setFilter(function (item) {
var f = function (item) {
for (var p = 0; p < npredicates; p++) {
var predicate = predicates[p];
var searchColumns;
......@@ -480,16 +570,22 @@ morpheus.Table.prototype = {
}
return false;
});
};
this.searchFunction = f;
this.grid
.setFilter(this.grid
.getFilter());
},
search: function (text) {
if (text === '') {
this.grid.setFilter(null);
this.searchFunction = null;
this.grid
.setFilter(this.grid
.getFilter());
} else {
var tokens = morpheus.Util.getAutocompleteTokens(text);
var columns = this.columns.filter(function (c) {
return c.searchable && c.visible;
return (c.searchable && c.visible) || c.alwaysSearch;
});
var columnNames = columns.map(function (c) {
return c.name;
......@@ -525,6 +621,9 @@ morpheus.Table.prototype = {
setFilter: function (f) {
this.grid.setFilter(f);
},
getFilter: function () {
return this.grid.getFilter();
},
setItems: function (items) {
this.grid.setItems(items);
this.grid.redraw();
......@@ -554,12 +653,13 @@ morpheus.Table.createOptions = function (options) {
options = $.extend(true, {}, {
items: [],
height: '564px',
collapseBreakpoint: 500,
collapseBreakpoint: 400,
showHeader: true,
select: true,
rowHeader: null,
responsive: true,
fixedWidth: '320px'
fixedWidth: '320px',
columnPicker: true
}, options);
if (!options.columns) {
......@@ -637,36 +737,29 @@ morpheus.Table.createOptions = function (options) {
if (!options.rowHeight) {
// options.rowHeight = options.tableClass === 'slick-table-compact' ? 18
// : 20;
options.rowHeight = 20;
options.rowHeight = 22;
}
return options;
};
morpheus.TableSearchUI = function () {
morpheus.TableSearchUI = function (options) {
var _this = this;
var html = [];
html.push('<div name="searchDiv">');
html.push('<form class="form">');
html
.push('<div class="form-group" style="max-width:525px; width:95%; margin:0px;">');
html
.push('<input name="search" type="text" class="form-control input-sm" placeholder="Search" autocomplete="off">');
html.push('<h6 name="searchResults" style="margin:0px;"></h6>');
html.push('</div>');
html.push('</form>');
html.push('</div>');
var $el = $(html.join(''));
this.$el = $el;
$el.find('form').on('submit', function (e) {
var $search = $('<input name="search" type="text" class="form-control input-sm"' +
' placeholder="Search" autocomplete="off">');
$search.appendTo(options.$el);
this.$search = $search;
this.$searchResults = $('<span class="pad-top-2 tableview-rowcount" name="search"></span>');
this.$showAll = $('<div style="display:inline-block;min-width:60px;" name="search" class="pad-left-8 text-button-copy tableview-rowcount">Show' +
' all</div>');
this.$searchResults.appendTo(options.$right);
this.$showAll.appendTo(options.$right);
this.$showAll.on('click', function (e) {
e.preventDefault();
});
var $search = $el.find('[name=search]');
var $searchResults = $el.find('[name=searchResults]');
this.$searchResults = $searchResults;
$search.val('');
_this.table.search('');
_this.table.trigger('showAll', {table: _this.table});
});
$search.on('keyup', _.debounce(function () {
_this.table.search($.trim($(this).val()));
}, 100));
......@@ -684,20 +777,13 @@ morpheus.TableSearchUI = function () {
morpheus.TableSearchUI.prototype = {
updateSearchLabel: function () {
var filteredCount = this.table.getFilteredItemCount();
var text = '';
if (filteredCount !== this.table.getAllItemCount()) {
text += morpheus.Util.intFormat(filteredCount) + ' match'
+ (filteredCount !== 1 ? 'es' : '');
}
var text = 'Showing: ' + morpheus.Util.intFormat(this.table.getFilteredItemCount()) + ' / ' + morpheus.Util.intFormat(this.table.getAllItemCount());
this.$searchResults.html(text);
},
setTable: function (table) {
this.table = table;
var _this = this;
if (!table.options.responsive) {
this.$el.css('width', table.options.fixedWidth);
}
table.on('filter', function () {
_this.updateSearchLabel();
});
......@@ -705,3 +791,4 @@ morpheus.TableSearchUI.prototype = {
}
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment