mountainlab
Version:
MountainLab data analysis environment
407 lines (375 loc) • 11.6 kB
JavaScript
/*
* Copyright 2016-2017 Flatiron Institute, Simons Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
exports.MLTableWidget=MLTableWidget;
var JSQWidget=require('../mlscore/jsqcore/jsqwidget.js').JSQWidget;
var JSQObject=require('../mlscore/jsqcore/jsqobject.js').JSQObject;
require('./mltablewidget.css');
function MLTableWidget(O) {
O=O||this;
JSQWidget(O);
O.div().addClass('MLTableWidget');
O.div().addClass('h-100');
this.setColumnCount=function(num) {setColumnCount(num);};
this.clearRows=function() {m_rows=[]; schedule_refresh();};
this.createRow=function() {return createRow();};
this.addRow=function(row) {m_rows.push(row); schedule_refresh();}
this.rowCount=function() {return m_rows.length;};
this.row=function(i) {return m_rows[i];};
this.headerRow=function() {return m_header_row;};
this.columnCount=function() {return m_column_properties.length;}
this.setColumnProperties=function(colnum,props) {setColumnProperties(colnum,props);};
this.setRowsMoveable=function(val) {m_rows_moveable=val; schedule_refresh();};
this.rowsMoveable=function() {return m_rows_moveable;};
this.setSelectionMode=function(mode) {m_selection_mode=mode;}; //none,single,multiple
this.selectionMode=function() {return m_selection_mode;};
this.currentRow=function() {return m_current_row;};
this.setCurrentRow=function(row) {setCurrentRow(row);};
this.selectedRows=function() {return selectedRows();};
this.onCurrentRowChangedByUser=function(handler) {JSQ.connect(O,'current_row_changed_by_user',O,handler);};
//var m_table=$('<table class=Table1></table>');
var m_table=$('<table class=table></table>'); //moving to bootstrap
O.div().append(m_table);
O.div().css({'overflow':'auto'})
var m_header_row=new MLTableWidgetHeaderRow(0,O);
var m_rows=[];
var m_column_properties=[];
var m_rows_moveable=false;
var m_current_row=null;
var m_selection_mode='none'; //see above for list of possibilities
var m_select_all_checkbox=$('<input id="select_all_checkbox" type=checkbox class=mls_checkbox></input>');
m_select_all_checkbox.click(on_select_all_rows);
function setColumnCount(num) {
m_header_row.setColumnCount(num);
m_column_properties=[];
for (var i=0; i<num; i++) {
m_column_properties.push({});
}
schedule_refresh();
}
function setColumnProperties(colnum,props) {
for (var key in props) {
if ((key=='max-width')||(key=='min-width')||(key=='width')) {
m_header_row.cell(colnum).css({key:props[key]});
}
}
schedule_refresh();
}
function setCurrentRow(row) {
if (m_current_row==row) return;
m_current_row=row;
O.emit('current_row_changed');
update_row_highlighting();
}
function selectedRows() {
if (m_selection_mode=='multiple') {
var ret=[];
for (var i=0; i<O.rowCount(); i++) {
if (O.row(i).isSelected())
ret.push(O.row(i));
}
return ret;
}
else {
if (O.currentRow())
return [O.currentRow()];
else
return [];
}
}
function createRow() {
var row=new MLTableWidgetRow(0,O);
row.onSelectedChanged(function() {
update_row_highlighting();
O.emit('selected_rows_changed');
});
JSQ.connect(row,'clicked',O,function(sender,evt) {
if ((m_selection_mode=='single')||(m_selection_mode=='multiple')) {
if (m_current_row!=row) {
setCurrentRow(row);
O.emit('current_row_changed_by_user');
}
}
});
return row;
}
var m_refresh_scheduled=false;
function schedule_refresh() {
if (m_refresh_scheduled) return;
m_refresh_scheduled=true;
setTimeout(function() {
m_refresh_scheduled=false;
refresh();
},10);
}
function refresh() {
m_table.children().detach(); //important to do this before empty so we retain the jquery data on the elements!
m_table.empty();
m_table.append(m_header_row.tr());
var tbody=$('<tbody />');
m_table.append(tbody);
for (var i=0; i<m_rows.length; i++) {
tbody.append(m_rows[i].tr());
}
if (m_selection_mode=='multiple') {
var elmt=$(m_header_row.tr().find('th')[0]);
elmt.children().detach();
elmt.empty();
elmt.append(m_select_all_checkbox);
}
update_row_highlighting();
}
function on_select_all_rows() {
if (O.div().find('#select_all_checkbox').is(':checked')) {
for (var i=0; i<m_rows.length; i++) {
m_rows[i].setSelected(true);
}
}
else {
for (var i=0; i<m_rows.length; i++) {
m_rows[i].setSelected(false);
}
}
update_row_highlighting();
}
function update_row_highlighting() {
for (var i in m_rows) {
m_rows[i].tr().removeClass('mltablewidget-current');
}
if (m_current_row) {
m_current_row.tr().addClass('mltablewidget-current');
}
var all_selected=true;
var at_least_one_selected=false;
for (var i=0; i<m_rows.length; i++) {
if (m_rows[i].isSelected()) {
m_rows[i].tr().addClass('mltablewidget-selected');
at_least_one_selected=true;
}
else {
m_rows[i].tr().removeClass('mltablewidget-selected');
all_selected=false;
}
}
if ((all_selected)&&(at_least_one_selected)) {
m_select_all_checkbox.prop('checked',true);
m_select_all_checkbox.prop('indeterminate',false);
}
else if (at_least_one_selected) {
m_select_all_checkbox.prop('checked',true);
m_select_all_checkbox.prop('indeterminate',true);
}
else {
m_select_all_checkbox.prop('checked',false);
m_select_all_checkbox.prop('indeterminate',false);
}
}
function move_row(src_row_index,dst_row_index) {
if (src_row_index==dst_row_index) return;
var row0=m_rows[src_row_index];
m_rows.splice(src_row_index,1); //remove
if (src_row_index<dst_row_index) dst_row_index--;
m_rows.splice(dst_row_index,0,row0); //insert
refresh();
O.emit('rows_moved');
}
var m_is_dragging=false;
var m_drag_row_index=-1;
var m_drop_row_index=-1;
O.div().mousedown(function(evt) {
var x0=evt.pageX;
var y0=evt.pageY;
var ind=drag_handle_at(x0,y0);
if (ind>=0) {
m_is_dragging=true;
m_drag_row_index=ind;
m_drop_row_index=ind;
update_drag_animation();
evt.preventDefault();
}
});
O.div().mousemove(function(evt) {
if (!m_is_dragging) return;
var x0=evt.pageX;
var y0=evt.pageY;
var ind=row_at(x0,y0);
if ((ind>=0)&&(m_rows[ind].isMoveable())) {
if (ind<=m_drag_row_index)
m_drop_row_index=ind;
else
m_drop_row_index=ind+1;
update_drag_animation();
}
evt.preventDefault();
});
O.div().mouseup(function(evt) {
if (!m_is_dragging) return;
move_row(m_drag_row_index,m_drop_row_index);
m_is_dragging=false;
update_drag_animation();
evt.preventDefault();
});
function update_drag_animation() {
for (var i in m_rows) {
var row=m_rows[i];
if ((m_is_dragging)&&(m_drop_row_index==i)) {
row.setDragDropDestination(true);
}
else {
row.setDragDropDestination(false);
}
if ((m_is_dragging)&&(m_drag_row_index==i)) {
row.setDragDropSource(true);
}
else {
row.setDragDropSource(false);
}
}
}
function row_at(x0,y0) {
for (var i=0; i<m_rows.length; i++) {
var X=m_rows[i].tr();
var offset0=X.offset();
var x1=offset0.left,y1=offset0.top;
var w1=X.innerWidth(),h1=X.innerHeight();
if ((x1<=x0)&&(x0<=x1+w1)&&(y1<=y0)&&(y0<=y1+h1))
return i;
}
return -1;
}
function drag_handle_at(x0,y0) {
for (var i=0; i<m_rows.length; i++) {
var DH=m_rows[i].dragHandle();
if (DH) {
var offset0=DH.offset();
var x1=offset0.left,y1=offset0.top;
var w1=DH.innerWidth(),h1=DH.innerHeight();
if ((x1<=x0)&&(x0<=x1+w1)&&(y1<=y0)&&(y0<=y1+h1))
return i;
}
}
return -1;
}
refresh();
}
function MLTableWidgetHeaderRow(O,table_widget) {
this.tr=function() {return m_tr;};
this.setColumnCount=function(num) {setColumnCount(num);};
this.cell=function(index) {return m_cells[index];};
var m_tr=$('<tr />');
var m_cells=[];
function setColumnCount(num) {
m_tr.empty();
if ((table_widget.rowsMoveable())||(table_widget.selectionMode()=='multiple')) {
var wid=5;
if (table_widget.rowsMoveable()) {
wid+=10;
}
if (table_widget.selectionMode()=='multiple') {
wid+=10;
}
m_tr.append(`<th style="width:${wid}px" />`);
}
m_cells=[];
for (var i=0; i<num; i++) {
var cell=$('<th></th>');
m_cells.push(cell);
m_tr.append(cell);
}
}
}
function MLTableWidgetRow(O,table_widget) {
O=O||this;
JSQObject(O);
this.tr=function() {return m_tr;};
this.cell=function(index) {return m_cells[index];};
this.isMoveable=function() {return m_is_moveable;};
this.setIsMoveable=function(val) {setIsMoveable(val);};
this.dragHandle=function() {if (m_is_moveable) return m_drag_handle; else return null;};
this.setDragDropSource=function(val) {if (m_drag_drop_source==val) return; m_drag_drop_source=val; update_drag_animation();};
this.setDragDropDestination=function(val) {if (m_drag_drop_destination==val) return; m_drag_drop_destination=val; update_drag_animation();};
this.isSelected=function() {return isSelected();};
this.setSelected=function(val) {setSelected(val);};
this.onSelectedChanged=function(handler) {JSQ.connect(O,'selected-changed',O,handler);};
var m_tr=$('<tr />');
var m_cells=[];
var m_is_moveable=false;
var m_table_widget=table_widget;
var m_drag_handle=$('<span class=table_row_drag_handle />');
var m_drag_drop_source=false;
var m_drag_drop_destination=false;
var m_selection_checkbox=$('<input type=checkbox class="mltable_selection_checkbox" />');
m_selection_checkbox.change(function() {
O.emit('selected-changed');
});
m_tr.click(function(evt) {
O.emit('clicked',evt);
});
setIsMoveable(false);
function setIsMoveable(val) {
m_is_moveable=val;
if (m_is_moveable) {
m_drag_handle.css({visibility:''});
m_drag_handle.css({cursor:'move'});
}
else {
m_drag_handle.css({visibility:'hidden'});
m_drag_handle.css({cursor:'default'});
}
}
function update_drag_animation() {
if (m_drag_drop_source)
m_tr.addClass('drag_drop_source');
else
m_tr.removeClass('drag_drop_source');
if (m_drag_drop_destination)
m_tr.addClass('drag_drop_destination');
else
m_tr.removeClass('drag_drop_destination');
}
function set_column_count(num) {
m_tr.empty();
if ((m_table_widget.rowsMoveable())||(m_table_widget.selectionMode()=='multiple')) {
var td0=$('<td />');
td0.click(function(evt) {
evt.stopPropagation();
});
if (m_table_widget.rowsMoveable())
td0.append(m_drag_handle);
if (m_table_widget.selectionMode()=='multiple')
td0.append(m_selection_checkbox);
m_tr.append(td0);
}
for (var i=0; i<num; i++) {
var cell=$('<td />');
m_cells.push(cell);
m_tr.append(cell);
}
}
function isSelected() {
var cb=m_tr.find('.mltable_selection_checkbox');
if (cb.length>0) {
return $(cb[0]).is(':checked');
}
else return false;
}
function setSelected(val) {
var cb=m_tr.find('.mltable_selection_checkbox');
if (cb.length>0) {
$(cb[0]).prop('checked',val);
}
}
set_column_count(m_table_widget.columnCount());
}