Files
galaxy/static/scripts/mvc/tools/tools-section.js
T

574 lines
20 KiB
JavaScript

/*
This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _addRow() function.
*/
define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-select-dataset'],
function(Utils, Table, Ui, Tabs, SelectDataset) {
// input field element wrapper
var InputElement = Backbone.View.extend({
// initialize input wrapper
initialize: function(options) {
this.setElement(this._template(options));
},
// set error text
error: function(text) {
// set text
this.$el.find('.ui-table-form-error-text').html(text);
this.$el.find('.ui-table-form-error').fadeIn();
},
// reset
reset: function() {
this.$el.find('.ui-table-form-error').hide();
},
// template
_template: function(options) {
var $input;
if (options.highlight) {
$input = $('<div class="ui-table-element ui-table-form-section"/>');
} else {
$input = $('<div class="ui-table-element"/>');
}
// add error
$input.append('<div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>');
// add label
if (options.label) {
$input.append('<div class="ui-table-form-title-strong">' + options.label + '</div>');
}
// add input element
$input.append(options.$el);
// add help
if (options.help) {
$input.append('<div class="ui-table-form-info">' + options.help + '</div>');
}
// return input element
return $input;
}
});
// create form view
var View = Backbone.View.extend({
// initialize
initialize: function(app, options) {
// link app
this.app = app;
// link inputs
this.inputs = options.inputs;
// add table class for tr tag
// this assist in transforming the form into a json structure
options.cls_tr = 'section-row';
// create table
this.table = new Table.View(options);
// configure portlet and form table
this.setElement(this.table.$el);
// render tool section
this.render();
},
// update
render: function() {
// reset table
this.table.delAll();
// load settings elements into table
for (var i in this.inputs) {
this._add(this.inputs[i]);
}
},
// add table row
_add: function(input) {
// link this
var self = this;
// clone definition
var input_def = jQuery.extend(true, {}, input);
// create unique id
input_def.id = Utils.uuid();
// add to sequential list of inputs
this.app.input_list[input_def.id] = input_def;
// identify field type
var type = input_def.type;
switch(type) {
// conditional field
case 'conditional':
this._addConditional(input_def);
break;
// repeat block
case 'repeat':
this._addRepeat(input_def);
break;
// default single element row
default:
this._addRow(type, input_def);
}
},
// add conditional block
_addConditional: function(input_def) {
// add label to input definition root
input_def.label = input_def.test_param.label;
// add value to input definition root
input_def.value = input_def.test_param.value;
// build options field
var table_row = this._addRow('conditional', input_def);
// add fields
for (var i in input_def.cases) {
// create id tag
var sub_section_id = input_def.id + '-section-' + i;
// create sub section
var sub_section = new View(this.app, {
inputs : input_def.cases[i].inputs,
cls : 'ui-table-plain'
});
// create input field wrapper
var input_element = new InputElement({
label : '',
help : input_def.help,
$el : sub_section.$el,
highlight : true
});
// create table row
this.table.add(input_element.$el);
// append to table
this.table.append(sub_section_id);
}
},
// add repeat block
_addRepeat: function(input_def) {
// link this
var self = this;
//
// create tab field
//
var tabs = new Tabs.View({
title_new : 'Add ' + input_def.title,
max : input_def.max,
onnew : function() {
// create id tag
var sub_section_id = input_def.id + '-section-' + Utils.uuid();
// create sub section
var sub_section = new View(self.app, {
inputs : input_def.inputs,
cls : 'ui-table-plain'
});
// add new tab
tabs.add({
id : sub_section_id,
title : input_def.title,
$el : sub_section.$el,
ondel : function() {
// delete tab
tabs.del(sub_section_id);
// retitle tabs
tabs.retitle(input_def.title);
// trigger refresh
self.app.refresh();
}
});
// retitle tabs
tabs.retitle(input_def.title);
// show tab
tabs.show(sub_section_id);
// trigger refresh
self.app.refresh();
}
});
//
// add min number of tabs
//
for (var i = 0; i < input_def.min; i++) {
// create id tag
var sub_section_id = input_def.id + '-section-' + Utils.uuid();
// create sub section
var sub_section = new View(self.app, {
inputs : input_def.inputs,
cls : 'ui-table-plain'
});
// add tab
tabs.add({
id : sub_section_id,
title : input_def.title,
$el : sub_section.$el
});
}
// retitle tabs
tabs.retitle(input_def.title);
// create input field wrapper
var input_element = new InputElement({
label : input_def.title,
help : input_def.help,
$el : tabs.$el,
highlight : true
});
// create table row
this.table.add(input_element.$el);
// append row to table
this.table.append(input_def.id);
},
// add table row
_addRow: function(field_type, input_def) {
// get id
var id = input_def.id;
// field wrapper
var field = null;
// identify field type
switch(field_type) {
// text input field
case 'text' :
field = this._field_text(input_def);
break;
// select field
case 'select' :
field = this._field_select(input_def);
break;
// dataset
case 'data':
field = this._field_data(input_def);
break;
// dataset column
case 'data_column':
field = this._field_select(input_def);
break;
// conditional select field
case 'conditional':
field = this._field_conditional(input_def);
break;
// hidden field
case 'hidden':
field = this._field_hidden(input_def);
break;
// integer field
case 'integer':
field = this._field_slider(input_def);
break;
// float field
case 'float':
field = this._field_slider(input_def);
break;
// boolean field
case 'boolean':
field = this._field_boolean(input_def);
break;
}
// pick a generic field if specific mapping failed
if (!field) {
if (input_def.options) {
// assign select field
field = this._field_select(input_def);
} else {
// assign text field
field = this._field_text(input_def);
}
// log
console.debug('tools-form::_addRow() : Auto matched field type (' + field_type + ').');
}
// set field value
if (input_def.value !== undefined) {
field.value(input_def.value);
}
// add to field list
this.app.field_list[id] = field;
// create input field wrapper
var input_element = new InputElement({
label : input_def.label,
help : input_def.help,
$el : field.$el
});
// add to element list
this.app.element_list[id] = input_element;
// create table row
this.table.add(input_element.$el);
// append to table
this.table.append(id);
// return table row
return this.table.get(id)
},
// conditional input field
_field_conditional : function(input_def) {
// link this
var self = this;
// configure options fields
var options = [];
for (var i in input_def.test_param.options) {
var option = input_def.test_param.options[i];
options.push({
label: option[0],
value: option[1]
});
}
// select field
return new Ui.Select.View({
id : 'field-' + input_def.id,
data : options,
onchange : function(value) {
// check value in order to hide/show options
for (var i in input_def.cases) {
// get case
var case_def = input_def.cases[i];
// identify subsection name
var section_id = input_def.id + '-section-' + i;
// identify row
var section_row = self.table.get(section_id);
// check if non-hidden elements exist
var nonhidden = false;
for (var j in case_def.inputs) {
var type = case_def.inputs[j].type;
if (type && type !== 'hidden') {
nonhidden = true;
break;
}
}
// show/hide sub form
if (case_def.value == value && nonhidden) {
section_row.fadeIn('fast');
} else {
section_row.hide();
}
}
}
});
},
// data input field
_field_data : function(input_def) {
// link this
var self = this;
// get element id
var id = input_def.id;
// select field
return new SelectDataset.View(this.app, {
id : 'field-' + id,
extensions : input_def.extensions,
multiple : input_def.multiple,
onchange : function(value) {
// pick the first dataset if multiple might be selected
// TODO: iterate over all datasets and filter common/consistent columns
if (value instanceof Array) {
value = value[0];
}
// get referenced columns
var column_list = self.app.tree.references(id, 'data_column');
// find selected dataset
var dataset = self.app.datasets.filter(value);
// check dataset
if (dataset && column_list.length > 0) {
// log selection
console.debug('tool-form::field_data() - Selected dataset ' + value + '.');
// get meta data
var meta = dataset.get('metadata_column_types');
// check meta data
if (!meta) {
console.debug('tool-form::field_data() - FAILED: Could not find metadata for dataset ' + value + '.');
}
// update referenced columns
for (var i in column_list) {
// get column input/field
var column_input = self.app.input_list[column_list[i]];
var column_field = self.app.field_list[column_list[i]];
if (!column_input || !column_field) {
console.debug('tool-form::field_data() - FAILED: Column not found.');
}
// is numerical?
var numerical = column_input.numerical;
// identify column options
var columns = [];
for (var key in meta) {
// get column type
var column_type = meta[key];
// column index
var column_index = (parseInt(key) + 1);
// column type label
var column_label = 'Text';
if (column_type == 'int' || column_type == 'float') {
column_label = 'Number';
}
// add to selection
if (column_type == 'int' || column_type == 'float' || !numerical) {
columns.push({
'label' : 'Column: ' + column_index + ' [' + column_label + ']',
'value' : column_index
});
}
}
// update field
if (column_field) {
column_field.update(columns);
if (!column_field.exists(column_field.value())) {
column_field.value(column_field.first());
}
}
}
} else {
// log failure
console.debug('tool-form::field_data() - FAILED: Could not find dataset ' + value + '.');
}
}
});
},
// select field
_field_select : function (input_def) {
// configure options fields
var options = [];
for (var i in input_def.options) {
var option = input_def.options[i];
options.push({
label: option[0],
value: option[1]
});
}
// identify display type
var SelectClass = Ui.Select;
switch (input_def.display) {
case 'checkboxes':
SelectClass = Ui.Checkbox;
break;
case 'radio':
SelectClass = Ui.RadioButton;
break;
}
// select field
return new SelectClass.View({
id : 'field-' + input_def.id,
data : options,
multiple: input_def.multiple
});
},
// column field
_field_data_colum : function (input_def) {
return new Ui.Select.View({
id : 'field-' + input_def.id,
multiple: input_def.multiple
});
},
// text input field
_field_text : function(input_def) {
return new Ui.Input({
id : 'field-' + input_def.id,
area : input_def.area
});
},
// slider field
_field_slider: function(input_def) {
// calculate step size
var step = 1;
if (input_def.type == 'float') {
step = (input_def.max - input_def.min) / 10000;
}
// create slider
return new Ui.Slider.View({
id : 'field-' + input_def.id,
min : input_def.min || 0,
max : input_def.max || 1000,
step : step
});
},
// hidden field
_field_hidden : function(input_def) {
return new Ui.Hidden({
id : 'field-' + input_def.id
});
},
// boolean field
_field_boolean : function(input_def) {
return new Ui.RadioButton.View({
id : 'field-' + input_def.id,
data : [ { label : 'Yes', value : 'true' },
{ label : 'No', value : 'false' }]
});
}
});
return {
View: View
};
});