mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
UI: add peek-based column selection control; Scatterplot: use peek-based control for selection of x, y, id axes
This commit is contained in:
@@ -1,55 +1,24 @@
|
||||
<p class="help-text">
|
||||
Use the following controls to change the data used by the chart.
|
||||
Use the following control to change which columns are used by the chart. Click any cell
|
||||
from the last three rows of the table to select the column for the appropriate data.
|
||||
Use the 'Draw' button to render (or re-render) the chart with the current settings.
|
||||
</p>
|
||||
|
||||
{{! column selector containers }}
|
||||
<div class="column-select">
|
||||
<label>Data column for X: </label>
|
||||
<select name="xColumn">
|
||||
{{#each numericColumns}}
|
||||
<option value="{{index}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="column-select">
|
||||
<label>Data column for Y: </label>
|
||||
<select name="yColumn">
|
||||
{{#each numericColumns}}
|
||||
<option value="{{index}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
<ul class="help-text" style="margin-left: 8px">
|
||||
<li><b>X Column</b>: which column values will be used for the x axis of the chart.</li>
|
||||
<li><b>Y Column</b>: which column values will be used for the y axis of the chart.</li>
|
||||
<li><b>ID Column</b>: an additional column value displayed when the user hovers over a data point.
|
||||
It may be useful to select unique or categorical identifiers here (such as gene ids).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="column-selection">
|
||||
<pre class="peek">{{{ peek }}}</pre>
|
||||
</div>
|
||||
|
||||
{{! optional id column }}
|
||||
<div id="include-id">
|
||||
<label for="include-id-checkbox">Include a third column as data point IDs?</label>
|
||||
<input type="checkbox" name="include-id" id="include-id-checkbox" />
|
||||
<p class="help-text-small">
|
||||
These will be displayed (along with the x and y values) when you hover over
|
||||
a data point.
|
||||
</p>
|
||||
</div>
|
||||
<div class="column-select" style="display: none">
|
||||
<label for="ID-select">Data column for IDs: </label>
|
||||
<select name="idColumn">
|
||||
{{#each allColumns}}
|
||||
<option value="{{index}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{! if we're using generic column selection names ('column 1') - allow the user to use the first line }}
|
||||
<div id="first-line-header" style="display: none;">
|
||||
<p>Possible headers: {{ possibleHeaders }}
|
||||
</p>
|
||||
<label for="first-line-header-checkbox">Use the above as column headers?</label>
|
||||
<input type="checkbox" name="include-id" id="first-line-header-checkbox"
|
||||
{{#if usePossibleHeaders }}checked="true"{{/if}}/>
|
||||
<p class="help-text-small">
|
||||
It looks like Galaxy couldn't get proper column headers for this data.
|
||||
Would you like to use the column headers above as column names to select columns?
|
||||
</p>
|
||||
</div>
|
||||
<p class="help-text help-text-small">
|
||||
<b>Note</b>: If it can be determined from the dataset's filetype that column is not numeric, that
|
||||
column choice may be disabled for either the x or y axis.
|
||||
</p>
|
||||
|
||||
<button class="render-button btn btn-primary active">Draw</button>
|
||||
|
||||
@@ -78,73 +78,62 @@ var ScatterplotConfigEditor = Backbone.View.extend( LoggableMixin ).extend({
|
||||
return this;
|
||||
},
|
||||
|
||||
/** get an object with arrays keyed with possible column types (numeric, text, all)
|
||||
* and if metadata_column_types is set on the dataset, add the indeces of each
|
||||
* column into the appropriate array.
|
||||
* Used to disable certain columns from being selected for x, y axes.
|
||||
*/
|
||||
_getColumnIndecesByType : function(){
|
||||
//TODO: not sure these contraints are necc. now
|
||||
var types = {
|
||||
numeric : [],
|
||||
text : [],
|
||||
all : []
|
||||
};
|
||||
_.each( this.dataset.metadata_column_types || [], function( type, i ){
|
||||
if( type === 'int' || type === 'float' ){
|
||||
types.numeric.push( i );
|
||||
} else if( type === 'str' || type === 'list' ){
|
||||
types.text.push( i );
|
||||
}
|
||||
types.all.push( i );
|
||||
});
|
||||
if( types.numeric.length < 2 ){
|
||||
types.numeric = [];
|
||||
}
|
||||
//console.log( 'types:', JSON.stringify( types ) );
|
||||
return types;
|
||||
},
|
||||
|
||||
/** controls for which columns are used to plot datapoints (and ids/additional info to attach if desired) */
|
||||
_render_dataControl : function( $where ){
|
||||
//TODO: better handling of missing column names, column types
|
||||
$where = $where || this.$el;
|
||||
var editor = this,
|
||||
dataset = this.dataset,
|
||||
column_names = dataset.metadata_column_names || [],
|
||||
config = this.model.get( 'config' );
|
||||
//console.log( 'metadata_column_types:', this.dataset.metadata_column_types );
|
||||
//console.log( 'metadata_column_names:', this.dataset.metadata_column_names );
|
||||
|
||||
//TODO: to peek based control
|
||||
var numericColumns = [],
|
||||
allColumns = _.map( dataset.metadata_column_types, function( type, i ){
|
||||
// save column data for select rendering, adding metadata name if available in dataset
|
||||
var column = { index: i, type: type, name: ( column_names[ i ] || ( 'column ' + ( i + 1 )) ) };
|
||||
// also add column to numerics if numeric type
|
||||
if( ( column.type === 'int' ) || ( column.type === 'float' ) ){
|
||||
numericColumns.push( column );
|
||||
}
|
||||
return column;
|
||||
});
|
||||
if( numericColumns.length < 2 ){
|
||||
numericColumns = allColumns;
|
||||
}
|
||||
//console.log( 'allColumns:', allColumns );
|
||||
//console.log( 'numericColumns:', numericColumns );
|
||||
//column_names = dataset.metadata_column_names || [],
|
||||
config = this.model.get( 'config' ),
|
||||
columnTypes = this._getColumnIndecesByType();
|
||||
|
||||
// render the html
|
||||
var $dataControl = $where.find( '.tab-pane#data-control' );
|
||||
$dataControl.html( ScatterplotConfigEditor.templates.dataControl({
|
||||
allColumns : allColumns,
|
||||
numericColumns : numericColumns
|
||||
peek : this.dataset.peek
|
||||
}));
|
||||
|
||||
//TODO: column selection boilerplate
|
||||
// preset to column selectors if they were passed in the config in the query string; set up events
|
||||
var newConfig = {
|
||||
xColumn : ( _.isFinite( config.xColumn ) )? ( config.xColumn ): ( numericColumns[0].index ),
|
||||
yColumn : ( _.isFinite( config.yColumn ) )? ( config.yColumn ): ( numericColumns[1].index ),
|
||||
idColumn : allColumns[0].index
|
||||
};
|
||||
// use an idColumn from the config or attempt to get one different from the numeric
|
||||
if( _.isFinite( config.idColumn ) ){
|
||||
newConfig.idColumn = config.idColumn;
|
||||
} else {
|
||||
if( allColumns.length > 2 ){
|
||||
var uniqueCol = _.find( allColumns, function( column, i ){
|
||||
return i !== newConfig.xColumn && i !== newConfig.yColumn;
|
||||
});
|
||||
newConfig.idColumn = uniqueCol.index;
|
||||
}
|
||||
}
|
||||
config = this.model.set( 'config', newConfig, { silent: true }).get( 'config' );
|
||||
$dataControl.find( '.peek' ).peekControl({
|
||||
controls : [
|
||||
{ label: 'X Column', id: 'xColumn', selected: config.xColumn, disabled: columnTypes.text },
|
||||
{ label: 'Y Column', id: 'yColumn', selected: config.yColumn, disabled: columnTypes.text },
|
||||
{ label: 'ID Column', id: 'idColumn', selected: config.idColumn }
|
||||
]
|
||||
//renameColumns : true
|
||||
|
||||
$dataControl.find( '[name="xColumn"]' ).val( config.xColumn ).on( 'change', function(){
|
||||
editor.model.set( 'config', { xColumn: Number( $( this ).val() ) });
|
||||
}).on( 'peek-control.change', function( ev, data ){
|
||||
//console.info( 'new selection:', data );
|
||||
editor.model.set( 'config', data );
|
||||
|
||||
}).on( 'peek-control.rename', function( ev, data ){
|
||||
//console.info( 'new column names', data );
|
||||
});
|
||||
$dataControl.find( '[name="yColumn"]' ).val( config.yColumn ).on( 'change', function(){
|
||||
editor.model.set( 'config', { yColumn: Number( $( this ).val() ) });
|
||||
});
|
||||
$dataControl.find( 'select[name="idColumn"]' ).val( config.idColumn ).on( 'change', function(){
|
||||
editor.model.set( 'config', { idColumn: Number( $( this ).val() ) });
|
||||
});
|
||||
if( config.idColumn !== undefined ){
|
||||
$dataControl.find( '#include-id-checkbox' ).prop( 'checked', true ).trigger( 'change' );
|
||||
}
|
||||
|
||||
$dataControl.find( '[title]' ).tooltip();
|
||||
return $dataControl;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -87,7 +87,7 @@ $(function(){
|
||||
model : model,
|
||||
dataset : hdaJson
|
||||
}).render();
|
||||
//window.editor = editor;
|
||||
window.editor = editor;
|
||||
|
||||
$( '.chart-header h2' ).click( function(){
|
||||
var returned = prompt( 'Enter a new title:' );
|
||||
|
||||
@@ -1299,3 +1299,310 @@ function dropDownSelect( options, selected ){
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Column selection using the peek display as the control.
|
||||
* Adds rows to the bottom of the peek with clickable areas in each cell
|
||||
* to allow the user to select columns.
|
||||
* Column selection can be limited to a single column or multiple.
|
||||
* (Optionally) adds a left hand column of column selection prompts.
|
||||
* (Optionally) allows the column headers to be clicked/renamed
|
||||
* and set to some initial value.
|
||||
* (Optionally) hides comment rows.
|
||||
* (Optionally) allows pre-selecting and disabling certain columns for
|
||||
* each row control.
|
||||
*
|
||||
* Construct by selecting a peek table to be used with jQuery and
|
||||
* calling 'peekControl' with options.
|
||||
* Options must include a 'controls' array and can include other options
|
||||
* listed below.
|
||||
* @example:
|
||||
* $( 'pre.peek' ).peekControl({
|
||||
* columnNames : ["Chromosome", "Start", "Base", "", "", "Qual" ],
|
||||
* controls : [
|
||||
* { label: 'X Column', id: 'xColumn' },
|
||||
* { label: 'Y Column', id: 'yColumn', selected: 2 },
|
||||
* { label: 'ID Column', id: 'idColumn', selected: 4, disabled: [ 1, 5 ] },
|
||||
* { label: 'Heatmap', id: 'heatmap', selected: [ 2, 4 ], disabled: [ 0, 1 ], multiselect: true,
|
||||
* selectedText: 'Included', unselectedText: 'Excluded' }
|
||||
* ],
|
||||
* renameColumns : true,
|
||||
* hideCommentRows : true,
|
||||
* includePrompts : true,
|
||||
* topLeftContent : 'Data sample:'
|
||||
* }).on( 'peek-control.change', function( ev, selection ){
|
||||
* console.info( 'new selection:', selection );
|
||||
* //{ yColumn: 2 }
|
||||
* }).on( 'peek-control.rename', function( ev, names ){
|
||||
* console.info( 'column names', names );
|
||||
* //[ 'Bler', 'Start', 'Base', '', '', 'Qual' ]
|
||||
* });
|
||||
*
|
||||
* An event is fired when column selection is changed and the event
|
||||
* is passed an object in the form: { the row id : the new selection value }.
|
||||
* An event is also fired when the table headers are re-named and
|
||||
* is passed the new array of column names.
|
||||
*/
|
||||
(function(){
|
||||
|
||||
/** option defaults */
|
||||
var defaults = {
|
||||
/** does this control allow renaming headers? */
|
||||
renameColumns : false,
|
||||
/** does this control allow renaming headers? */
|
||||
columnNames : [],
|
||||
/** the comment character used by the peek's datatype */
|
||||
commentChar : '#',
|
||||
/** should comment rows be shown or hidden in the peek */
|
||||
hideCommentRows : false,
|
||||
/** should a column of row control prompts be used */
|
||||
includePrompts : true,
|
||||
/** what is the content of the top left cell (often a title) */
|
||||
topLeftContent : 'Columns:'
|
||||
},
|
||||
/** the string of the event fired when a control row changes */
|
||||
CHANGE_EVENT = 'peek-control.change',
|
||||
/** the string of the event fired when a column is renamed */
|
||||
RENAME_EVENT = 'peek-control.rename',
|
||||
/** class added to the pre.peek element (to allow css on just the control) */
|
||||
PEEKCONTROL_CLASS = 'peek-control',
|
||||
/** class added to the control rows */
|
||||
ROW_CLASS = 'control',
|
||||
/** class added to the left-hand cells that serve as row prompts */
|
||||
PROMPT_CLASS = 'control-prompt',
|
||||
/** class added to selected _cells_/tds */
|
||||
SELECTED_CLASS = 'selected',
|
||||
/** class added to disabled/un-clickable cells/tds */
|
||||
DISABLED_CLASS = 'disabled',
|
||||
/** class added to the clickable surface within a cell to select it */
|
||||
BUTTON_CLASS = 'button',
|
||||
/** class added to peek table header (th) cells to indicate they can be clicked and are renamable */
|
||||
RENAMABLE_HEADER_CLASS = 'renamable-header',
|
||||
/** the data key used for each cell to store the column index ('data-...') */
|
||||
COLUMN_INDEX_DATA_KEY = 'column-index',
|
||||
/** renamable header data key used to store the column name (w/o the number and dot: '1.Bler') */
|
||||
COLUMN_NAME_DATA_KEY = 'column-name';
|
||||
|
||||
//TODO: not happy with pure functional here - rows should polymorph (multi, single, etc.)
|
||||
//TODO: needs clean up, move handlers to outer scope
|
||||
|
||||
// ........................................................................
|
||||
/** validate the control data sent in for each row */
|
||||
function validateControl( control ){
|
||||
if( control.disabled && jQuery.type( control.disabled ) !== 'array' ){
|
||||
throw new Error( '"disabled" must be defined as an array of indeces: ' + JSON.stringify( control ) );
|
||||
}
|
||||
if( control.multiselect && control.selected && jQuery.type( control.selected ) !== 'array' ){
|
||||
throw new Error( 'Mulitselect rows need an array for "selected": ' + JSON.stringify( control ) );
|
||||
}
|
||||
if( !control.label || !control.id ){
|
||||
throw new Error( 'Peek controls need a label and id for each control row: ' + JSON.stringify( control ) );
|
||||
}
|
||||
if( control.disabled && control.disabled.indexOf( control.selected ) !== -1 ){
|
||||
throw new Error( 'Selected column is in the list of disabled columns: ' + JSON.stringify( control ) );
|
||||
}
|
||||
return control;
|
||||
}
|
||||
|
||||
/** build the inner control surface (i.e. button-like) */
|
||||
function buildButton( control, columnIndex ){
|
||||
return $( '<div/>' ).addClass( BUTTON_CLASS ).text( control.label );
|
||||
}
|
||||
|
||||
/** build the basic (shared) cell structure */
|
||||
function buildControlCell( control, columnIndex ){
|
||||
var $td = $( '<td/>' )
|
||||
.html( buildButton( control, columnIndex ) )
|
||||
.attr( 'data-' + COLUMN_INDEX_DATA_KEY, columnIndex );
|
||||
|
||||
// disable if index in disabled array
|
||||
if( control.disabled && control.disabled.indexOf( columnIndex ) !== -1 ){
|
||||
$td.addClass( DISABLED_CLASS );
|
||||
}
|
||||
return $td;
|
||||
}
|
||||
|
||||
/** set the text of the control based on selected/un */
|
||||
function setSelectedText( $cell, control, columnIndex ){
|
||||
var $button = $cell.children( '.' + BUTTON_CLASS );
|
||||
if( $cell.hasClass( SELECTED_CLASS ) ){
|
||||
$button.html( ( control.selectedText !== undefined )?( control.selectedText ):( control.label ) );
|
||||
} else {
|
||||
$button.html( ( control.unselectedText !== undefined )?( control.unselectedText ):( control.label ) );
|
||||
}
|
||||
}
|
||||
|
||||
/** build a cell for a row that only allows one selection */
|
||||
function buildSingleSelectCell( control, columnIndex ){
|
||||
// only one selection - selected is single index
|
||||
var $cell = buildControlCell( control, columnIndex );
|
||||
if( control.selected === columnIndex ){
|
||||
$cell.addClass( SELECTED_CLASS );
|
||||
}
|
||||
setSelectedText( $cell, control, columnIndex );
|
||||
|
||||
// only add the handler to non-disabled controls
|
||||
if( !$cell.hasClass( DISABLED_CLASS ) ){
|
||||
$cell.click( function selectClick( ev ){
|
||||
var $cell = $( this );
|
||||
// don't re-select or fire event if already selected
|
||||
if( !$cell.hasClass( SELECTED_CLASS ) ){
|
||||
// only one can be selected - remove selected on all others, add it here
|
||||
var $otherSelected = $cell.parent().children( '.' + SELECTED_CLASS ).removeClass( SELECTED_CLASS );
|
||||
$otherSelected.each( function(){
|
||||
setSelectedText( $( this ), control, columnIndex );
|
||||
});
|
||||
|
||||
$cell.addClass( SELECTED_CLASS );
|
||||
setSelectedText( $cell, control, columnIndex );
|
||||
|
||||
// fire the event from the table itself, passing the id and index of selected
|
||||
var eventData = {},
|
||||
key = $cell.parent().attr( 'id' ),
|
||||
val = $cell.data( COLUMN_INDEX_DATA_KEY );
|
||||
eventData[ key ] = val;
|
||||
$cell.parents( '.peek' ).trigger( CHANGE_EVENT, eventData );
|
||||
}
|
||||
});
|
||||
}
|
||||
return $cell;
|
||||
}
|
||||
|
||||
/** build a cell for a row that allows multiple selections */
|
||||
function buildMultiSelectCell( control, columnIndex ){
|
||||
var $cell = buildControlCell( control, columnIndex );
|
||||
// multiple selection - selected is an array
|
||||
if( control.selected && control.selected.indexOf( columnIndex ) !== -1 ){
|
||||
$cell.addClass( SELECTED_CLASS );
|
||||
}
|
||||
setSelectedText( $cell, control, columnIndex );
|
||||
|
||||
// only add the handler to non-disabled controls
|
||||
if( !$cell.hasClass( DISABLED_CLASS ) ){
|
||||
$cell.click( function multiselectClick( ev ){
|
||||
var $cell = $( this );
|
||||
// can be more than one selected - toggle selected on this cell
|
||||
$cell.toggleClass( SELECTED_CLASS );
|
||||
setSelectedText( $cell, control, columnIndex );
|
||||
var selectedColumnIndeces = $cell.parent().find( '.' + SELECTED_CLASS ).map( function( i, e ){
|
||||
return $( e ).data( COLUMN_INDEX_DATA_KEY );
|
||||
});
|
||||
// fire the event from the table itself, passing the id and index of selected
|
||||
var eventData = {},
|
||||
key = $cell.parent().attr( 'id' ),
|
||||
val = jQuery.makeArray( selectedColumnIndeces );
|
||||
eventData[ key ] = val;
|
||||
$cell.parents( '.peek' ).trigger( CHANGE_EVENT, eventData );
|
||||
});
|
||||
}
|
||||
return $cell;
|
||||
}
|
||||
|
||||
/** iterate over columns in peek and create a control for each */
|
||||
function buildControlCells( count, control ){
|
||||
var $cells = [];
|
||||
// build a control for each column - using a build fn based on control
|
||||
for( var columnIndex=0; columnIndex<count; columnIndex+=1 ){
|
||||
$cells.push( control.multiselect? buildMultiSelectCell( control, columnIndex )
|
||||
: buildSingleSelectCell( control, columnIndex ) );
|
||||
}
|
||||
return $cells;
|
||||
}
|
||||
|
||||
/** build a row of controls for the peek */
|
||||
function buildControlRow( cellCount, control, includePrompts ){
|
||||
var $controlRow = $( '<tr/>' ).attr( 'id', control.id ).addClass( ROW_CLASS );
|
||||
if( includePrompts ){
|
||||
var $promptCell = $( '<td/>' ).addClass( PROMPT_CLASS ).text( control.label + ':' );
|
||||
$controlRow.append( $promptCell );
|
||||
}
|
||||
$controlRow.append( buildControlCells( cellCount, control ) );
|
||||
return $controlRow;
|
||||
}
|
||||
|
||||
// ........................................................................
|
||||
/** add to the peek, using options for configuration, return the peek */
|
||||
function peekControl( options ){
|
||||
options = jQuery.extend( true, {}, defaults, options );
|
||||
|
||||
var $peek = $( this ).addClass( PEEKCONTROL_CLASS ),
|
||||
$peektable = $peek.find( 'table' ),
|
||||
// get the size of the tables - width and height, number of comment rows
|
||||
columnCount = $peektable.find( 'th' ).size(),
|
||||
rowCount = $peektable.find( 'tr' ).size(),
|
||||
// get the rows containing text starting with the comment char (also make them grey)
|
||||
$commentRows = $peektable.find( 'td[colspan]' ).map( function( e, i ){
|
||||
var $this = $( this );
|
||||
if( $this.text() && $this.text().match( new RegExp( '^' + options.commentChar ) ) ){
|
||||
return $( this ).css( 'color', 'grey' ).parent().get(0);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
// should comment rows in the peek be hidden?
|
||||
if( options.hideCommentRows ){
|
||||
$commentRows.hide();
|
||||
rowCount -= $commentRows.size();
|
||||
}
|
||||
//console.debug( 'rowCount:', rowCount, 'columnCount:', columnCount, '$commentRows:', $commentRows );
|
||||
|
||||
// should a first column of control prompts be added?
|
||||
if( options.includePrompts ){
|
||||
var $topLeft = $( '<th/>' ).addClass( 'top-left' ).text( options.topLeftContent )
|
||||
.attr( 'rowspan', rowCount );
|
||||
$peektable.find( 'tr' ).first().prepend( $topLeft );
|
||||
}
|
||||
|
||||
// save either the options column name or the parsed text of each column header in html5 data attr and text
|
||||
var $headers = $peektable.find( 'th:not(.top-left)' ).each( function( i, e ){
|
||||
var $this = $( this ),
|
||||
// can be '1.name' or '1'
|
||||
text = $this.text().replace( /^\d+\.*/, '' ),
|
||||
name = options.columnNames[ i ] || text;
|
||||
$this.attr( 'data-' + COLUMN_NAME_DATA_KEY, name )
|
||||
.text( ( i + 1 ) + (( name )?( '.' + name ):( '' )) );
|
||||
});
|
||||
|
||||
// allow renaming of columns when the header is clicked
|
||||
if( options.renameColumns ){
|
||||
$headers.addClass( RENAMABLE_HEADER_CLASS )
|
||||
.click( function renameColumn(){
|
||||
// prompt for new name
|
||||
var $this = $( this ),
|
||||
index = $this.index() + ( options.includePrompts? 0: 1 ),
|
||||
prevName = $this.data( COLUMN_NAME_DATA_KEY ),
|
||||
newColumnName = prompt( 'New column name:', prevName );
|
||||
if( newColumnName !== null && newColumnName !== prevName ){
|
||||
// set the new text and data
|
||||
$this.text( index + ( newColumnName?( '.' + newColumnName ):'' ) )
|
||||
.data( COLUMN_NAME_DATA_KEY, newColumnName )
|
||||
.attr( 'data-', COLUMN_NAME_DATA_KEY, newColumnName );
|
||||
// fire event for new column names
|
||||
var columnNames = jQuery.makeArray(
|
||||
$this.parent().children( 'th:not(.top-left)' ).map( function(){
|
||||
return $( this ).data( COLUMN_NAME_DATA_KEY );
|
||||
}));
|
||||
$this.parents( '.peek' ).trigger( RENAME_EVENT, columnNames );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// build a row for each control
|
||||
options.controls.forEach( function( control, i ){
|
||||
validateControl( control );
|
||||
var $controlRow = buildControlRow( columnCount, control, options.includePrompts );
|
||||
$peektable.find( 'tbody' ).append( $controlRow );
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
// ........................................................................
|
||||
// as jq plugin
|
||||
jQuery.fn.extend({
|
||||
peekControl : function $peekControl( options ){
|
||||
return this.map( function(){
|
||||
return peekControl.call( this, options );
|
||||
});
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1396,6 +1396,17 @@ div.unified-panel-body{position:absolute;top:30px;bottom:0;width:100%}
|
||||
.pagination-scroll-container .pagination-page-list>li:first-child>a,.pagination-scroll-container .pagination-page-list>li:first-child>span{border-radius:0px;border-left:0px}
|
||||
.pagination-scroll-container .pagination-page-list>li:last-child>a,.pagination-scroll-container .pagination-page-list>li:last-child>span{border-radius:0px}
|
||||
.pagination-scroll-container .pagination-page-list>li>a{float:none;position:static;border:1px solid #BFBFBF;border-width:0px 0px 0px 1px}
|
||||
.peek-control{border-radius:3px;border:1px solid #5f6990}
|
||||
.peek-control td,th{padding:4px 10px 4px 4px}
|
||||
.peek-control th:last-child{width:100%}
|
||||
.peek-control .top-left{width:10%;white-space:normal;vertical-align:top;text-align:right;font-family:"Lucida Grande",verdana,arial,helvetica,sans-serif;font-weight:normal}
|
||||
.peek-control .renamable-header:hover{background-color:black}
|
||||
.peek-control .control td.control-prompt{background-color:#5f6990;padding:0px 4px 0px 8px;text-align:right;color:white}
|
||||
.peek-control .control td{padding:1px;font-family:"Lucida Grande",verdana,arial,helvetica,sans-serif;color:grey}
|
||||
.peek-control .control td .button{min-width:28px;border:1px solid grey;border-radius:3px;padding:4px;color:grey}
|
||||
.peek-control .control td:hover .button{background-color:#EEE;border:1px solid black;cursor:pointer;color:black}
|
||||
.peek-control .control td.disabled .button,.peek-control .control td.disabled:hover .button{background-color:transparent;border:1px solid #CCC;cursor:not-allowed;color:#CCC}
|
||||
.peek-control .control td.selected .button{background-color:black;border:1px solid black;color:white}
|
||||
div.metadataForm{border:solid #aaaaaa 1px}
|
||||
div.metadataFormTitle{font-weight:bold;padding:5px;padding-left:10px;padding-right:10px;background:#cccccc;background-repeat:repeat-x;background-position:top;border-bottom:solid #aaaaaa 1px}
|
||||
div.metadataFormBody{background:#FFFFFF;padding:5px 0}
|
||||
|
||||
@@ -544,6 +544,76 @@ div.unified-panel-body {
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------- peek-based column chooser
|
||||
.peek-control {
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgb(95, 105, 144);
|
||||
}
|
||||
|
||||
.peek-control td, th {
|
||||
padding: 4px 10px 4px 4px;
|
||||
}
|
||||
|
||||
.peek-control th:last-child {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.peek-control .top-left {
|
||||
width: 10%;
|
||||
white-space: normal;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
font-family: "Lucida Grande", verdana, arial, helvetica, sans-serif;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.peek-control .renamable-header:hover {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.peek-control .control td.control-prompt {
|
||||
background-color: rgb(95, 105, 144);
|
||||
padding: 0px 4px 0px 8px;
|
||||
text-align: right;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.peek-control .control td {
|
||||
padding: 1px;
|
||||
font-family: "Lucida Grande", verdana, arial, helvetica, sans-serif;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.peek-control .control td .button {
|
||||
min-width: 28px;
|
||||
border: 1px solid grey;
|
||||
border-radius: 3px;
|
||||
padding: 4px;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.peek-control .control td:hover .button {
|
||||
background-color: #EEE;
|
||||
border: 1px solid black;
|
||||
cursor: pointer;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.peek-control .control td.disabled .button,
|
||||
.peek-control .control td.disabled:hover .button {
|
||||
background-color: transparent;
|
||||
border: 1px solid #CCC;
|
||||
cursor: not-allowed;
|
||||
color: #CCC;
|
||||
}
|
||||
|
||||
.peek-control .control td.selected .button {
|
||||
background-color: black;
|
||||
border: 1px solid black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
// ==== Tool form styles ====
|
||||
|
||||
div.metadataForm {
|
||||
|
||||
Reference in New Issue
Block a user