diff --git a/client/galaxy/scripts/mvc/tools/tools-form-base.js b/client/galaxy/scripts/mvc/tools/tools-form-base.js
index 532bc973a74..96b10ec91f3 100644
--- a/client/galaxy/scripts/mvc/tools/tools-form-base.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -79,6 +79,10 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
/** Highlights errors
*/
_errors: function(options) {
+ // hide previous error statements
+ this.trigger('reset');
+
+ // highlight all errors
if (options && options.errors) {
var error_messages = this.tree.matchResponse(options.errors);
for (var input_id in this.element_list) {
@@ -124,9 +128,6 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
// rebuild the underlying data structure
this.tree.finalize();
- // show errors
- this._errors(options);
-
// add refresh listener
this.on('refresh', function() {
// by using/resetting the deferred ajax queue the number of redundant calls is reduced
diff --git a/client/galaxy/scripts/mvc/tools/tools-form-workflow.js b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
index 5faf0c3b643..efc654b28c0 100644
--- a/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
@@ -272,7 +272,7 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
var process_id = this.deferred.register();
// build model url for request
- var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id;
+ var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id + '&__is_dynamic__=False';
// post job
Utils.request({
@@ -282,7 +282,7 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
success : function(data) {
// update node in workflow module
self.node.update_field_data(data);
-
+
// highlight errors
self._errors(data && data.tool_model);
diff --git a/client/galaxy/scripts/mvc/tools/tools-input.js b/client/galaxy/scripts/mvc/tools/tools-input.js
index 1cb66b264a6..583e6f1e9a5 100644
--- a/client/galaxy/scripts/mvc/tools/tools-input.js
+++ b/client/galaxy/scripts/mvc/tools/tools-input.js
@@ -53,7 +53,7 @@ define([], function() {
error: function(text) {
if (!this.field.skip) {
this.$error_text.html(text);
- this.$error.fadeIn();
+ this.$error.fadeIn('fast');
this.$el.addClass('ui-error');
}
},
diff --git a/client/galaxy/scripts/mvc/tools/tools-section.js b/client/galaxy/scripts/mvc/tools/tools-section.js
index 45b8ba16960..b5eb83592dd 100644
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -449,8 +449,8 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
*/
_fieldData : function(input_def) {
if (this.app.workflow) {
- var extensions = Utils.textify(input_def.extensions.toString());
- input_def.info = 'Data input \'' + input_def.name + '\' (' + extensions + ')';
+ input_def.info = 'Data input \'' + input_def.name + '\' (' + Utils.textify(input_def.extensions.toString()) + ')';
+ input_def.value = null;
return this._fieldHidden(input_def);
}
var self = this;
@@ -471,9 +471,6 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
_fieldSelect : function (input_def) {
// show text field in workflow
if (this.app.workflow && input_def.is_dynamic) {
- if (!Utils.validate(input_def.value)) {
- input_def.value = '';
- }
return this._fieldText(input_def);
}
@@ -515,6 +512,12 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
/** Drill down options field
*/
_fieldDrilldown : function (input_def) {
+ // show text field in workflow
+ if (this.app.workflow && input_def.is_dynamic) {
+ return this._fieldText(input_def);
+ }
+
+ // create drill down field
var self = this;
return new Ui.Drilldown.View({
id : 'field-' + input_def.id,
@@ -529,6 +532,24 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
/** Text input field
*/
_fieldText : function(input_def) {
+ // format field for multiple entries
+ if (input_def.multiple) {
+ // show text area field
+ input_def.area = true;
+
+ // format value to text
+ if (!Utils.validate(input_def.value)) {
+ input_def.value = '';
+ } else {
+ if (input_def.value instanceof Array) {
+ input_def.value = value.toString();
+ } else {
+ input_def.value = String(input_def.value).replace(/[\[\]'"\s]/g, '').replace(/,/g, '\n');
+ }
+ }
+ }
+
+ // create input element
var self = this;
return new Ui.Input({
id : 'field-' + input_def.id,
diff --git a/client/galaxy/scripts/mvc/tools/tools-tree.js b/client/galaxy/scripts/mvc/tools/tools-tree.js
index 56e1fc1d443..4f394aefcab 100644
--- a/client/galaxy/scripts/mvc/tools/tools-tree.js
+++ b/client/galaxy/scripts/mvc/tools/tools-tree.js
@@ -123,7 +123,7 @@ return Backbone.Model.extend({
}
// handle simple value
- if (!field.skip ) {
+ if (!field.skip || self.app.workflow) {
if (field.validate && !field.validate()) {
value = null;
}
diff --git a/client/galaxy/scripts/utils/utils.js b/client/galaxy/scripts/utils/utils.js
index 34cb09a9f16..3479369e890 100644
--- a/client/galaxy/scripts/utils/utils.js
+++ b/client/galaxy/scripts/utils/utils.js
@@ -96,6 +96,9 @@ function get (options) {
* @param{Function} error - Callback on error
*/
function request (options) {
+ // this avoids adding brackets to array parameter names
+ $.ajaxSetup({ traditional: true });
+
// prepare ajax
var ajaxConfig = {
contentType : 'application/json',
diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py
index 3a94e176191..60e8336f87b 100755
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -2251,7 +2251,8 @@ class Tool( object, Dictifiable ):
"""
job_id = kwd.get('job_id', None)
dataset_id = kwd.get('dataset_id', None)
-
+ is_dynamic = string_as_bool(kwd.get('__is_dynamic__', True))
+
# load job details if provided
job = None
if job_id:
@@ -2345,10 +2346,16 @@ class Tool( object, Dictifiable ):
def check_state(trans, input, default_value, context):
value = default_value
error = 'State validation failed.'
+
+ # skip dynamic fields if deactivated
+ if not is_dynamic and input.is_dynamic:
+ return [value, None]
+
+ # validate value content
try:
# resolves the inconsistent definition of boolean parameters (see base.py) without modifying shared code
if input.type == 'boolean' and isinstance(default_value, basestring):
- value, error = [util.string_as_bool(default_value), None]
+ value, error = [string_as_bool(default_value), None]
else:
value, error = check_param(trans, input, default_value, context)
except Exception, err:
@@ -2463,7 +2470,7 @@ class Tool( object, Dictifiable ):
sanitize_state(state[k])
else:
state[k] = jsonify(state[k])
-
+
# do param translation here, used by datasource tools
if self.input_translator:
self.input_translator.translate( params )
diff --git a/lib/galaxy/tools/parameters/basic.py b/lib/galaxy/tools/parameters/basic.py
index 5b63860ac92..75dfaf8de89 100644
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -47,6 +47,7 @@ class ToolParameter( object, Dictifiable ):
self.name = input_source.get("name")
self.type = input_source.get("type")
self.hidden = input_source.get("hidden", False)
+ self.is_dynamic = False
self.label = input_source.parse_label()
self.help = input_source.parse_help()
sanitizer_elem = input_source.parse_sanitizer_elem()
@@ -215,6 +216,7 @@ class ToolParameter( object, Dictifiable ):
tool_dict[ 'model_class' ] = self.__class__.__name__
tool_dict[ 'optional' ] = self.optional
tool_dict[ 'hidden' ] = self.hidden
+ tool_dict[ 'is_dynamic' ] = self.is_dynamic
if hasattr( self, 'value' ):
tool_dict[ 'value' ] = self.value
return tool_dict
@@ -1042,7 +1044,6 @@ class SelectToolParameter( ToolParameter ):
d['display'] = self.display
d['multiple'] = self.multiple
- d['is_dynamic'] = self.is_dynamic
return d
@@ -1451,7 +1452,6 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
if not os.path.isabs( from_file ):
from_file = os.path.join( tool.app.config.tool_data_path, from_file )
elem = XML( "%s" % open( from_file ).read() )
- self.is_dynamic = False
self.dynamic_options = elem.get( 'dynamic_options', None )
if self.dynamic_options:
self.is_dynamic = True
@@ -1541,6 +1541,8 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
else:
value = value.split( "\n" )
return UnvalidatedValue( value )
+ if not value and not self.optional:
+ raise ValueError( "An invalid option was selected for %s, 'None', please verify" % (self.name) )
if not value:
return None
if not isinstance( value, list ):
@@ -1663,9 +1665,8 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
# will sometimes error if self.is_dynamic and self.filtered
# bc we dont/cant fill out other_values above ({})
pass
- d[ 'options' ] = options
- d[ 'display' ] = self.display
- d[ 'is_dynamic' ] = self.is_dynamic
+ d['options'] = options
+ d['display'] = self.display
return d
@@ -1768,6 +1769,7 @@ class DataToolParameter( BaseDataToolParameter ):
self.validators.append( validation.MetadataValidator() )
self._parse_formats( trans, tool, input_source )
self.multiple = input_source.get_bool('multiple', False)
+ self.is_dynamic = True
self._parse_options( input_source )
# Load conversions required for the dataset input
self.conversions = []
@@ -2114,7 +2116,6 @@ class DataToolParameter( BaseDataToolParameter ):
d = super( DataToolParameter, self ).to_dict( trans )
d['extensions'] = self.extensions
d['multiple'] = self.multiple
- d['is_dynamic'] = True
d['options'] = {'hda': [], 'hdca': []}
# return default content if context is not available
@@ -2169,6 +2170,7 @@ class DataCollectionToolParameter( BaseDataToolParameter ):
self._parse_formats( trans, tool, input_source )
self._collection_type = input_source.get("collection_type", None)
self.multiple = False # Accessed on DataToolParameter a lot, may want in future
+ self.is_dynamic = True
self._parse_options( input_source ) # TODO: Review and test.
@property
@@ -2355,7 +2357,6 @@ class DataCollectionToolParameter( BaseDataToolParameter ):
d = super( DataCollectionToolParameter, self ).to_dict( trans )
d['extensions'] = self.extensions
d['multiple'] = self.multiple
- d['is_dynamic'] = False
d['options'] = {'hda': [], 'hdca': []}
# return default content if context is not available
diff --git a/static/scripts/mvc/tools/tools-form-base.js b/static/scripts/mvc/tools/tools-form-base.js
index 532bc973a74..96b10ec91f3 100644
--- a/static/scripts/mvc/tools/tools-form-base.js
+++ b/static/scripts/mvc/tools/tools-form-base.js
@@ -79,6 +79,10 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
/** Highlights errors
*/
_errors: function(options) {
+ // hide previous error statements
+ this.trigger('reset');
+
+ // highlight all errors
if (options && options.errors) {
var error_messages = this.tree.matchResponse(options.errors);
for (var input_id in this.element_list) {
@@ -124,9 +128,6 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
// rebuild the underlying data structure
this.tree.finalize();
- // show errors
- this._errors(options);
-
// add refresh listener
this.on('refresh', function() {
// by using/resetting the deferred ajax queue the number of redundant calls is reduced
diff --git a/static/scripts/mvc/tools/tools-form-workflow.js b/static/scripts/mvc/tools/tools-form-workflow.js
index 5faf0c3b643..efc654b28c0 100644
--- a/static/scripts/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/mvc/tools/tools-form-workflow.js
@@ -272,7 +272,7 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
var process_id = this.deferred.register();
// build model url for request
- var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id;
+ var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id + '&__is_dynamic__=False';
// post job
Utils.request({
@@ -282,7 +282,7 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
success : function(data) {
// update node in workflow module
self.node.update_field_data(data);
-
+
// highlight errors
self._errors(data && data.tool_model);
diff --git a/static/scripts/mvc/tools/tools-input.js b/static/scripts/mvc/tools/tools-input.js
index 1cb66b264a6..583e6f1e9a5 100644
--- a/static/scripts/mvc/tools/tools-input.js
+++ b/static/scripts/mvc/tools/tools-input.js
@@ -53,7 +53,7 @@ define([], function() {
error: function(text) {
if (!this.field.skip) {
this.$error_text.html(text);
- this.$error.fadeIn();
+ this.$error.fadeIn('fast');
this.$el.addClass('ui-error');
}
},
diff --git a/static/scripts/mvc/tools/tools-section.js b/static/scripts/mvc/tools/tools-section.js
index 45b8ba16960..b5eb83592dd 100644
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -449,8 +449,8 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
*/
_fieldData : function(input_def) {
if (this.app.workflow) {
- var extensions = Utils.textify(input_def.extensions.toString());
- input_def.info = 'Data input \'' + input_def.name + '\' (' + extensions + ')';
+ input_def.info = 'Data input \'' + input_def.name + '\' (' + Utils.textify(input_def.extensions.toString()) + ')';
+ input_def.value = null;
return this._fieldHidden(input_def);
}
var self = this;
@@ -471,9 +471,6 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
_fieldSelect : function (input_def) {
// show text field in workflow
if (this.app.workflow && input_def.is_dynamic) {
- if (!Utils.validate(input_def.value)) {
- input_def.value = '';
- }
return this._fieldText(input_def);
}
@@ -515,6 +512,12 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
/** Drill down options field
*/
_fieldDrilldown : function (input_def) {
+ // show text field in workflow
+ if (this.app.workflow && input_def.is_dynamic) {
+ return this._fieldText(input_def);
+ }
+
+ // create drill down field
var self = this;
return new Ui.Drilldown.View({
id : 'field-' + input_def.id,
@@ -529,6 +532,24 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
/** Text input field
*/
_fieldText : function(input_def) {
+ // format field for multiple entries
+ if (input_def.multiple) {
+ // show text area field
+ input_def.area = true;
+
+ // format value to text
+ if (!Utils.validate(input_def.value)) {
+ input_def.value = '';
+ } else {
+ if (input_def.value instanceof Array) {
+ input_def.value = value.toString();
+ } else {
+ input_def.value = String(input_def.value).replace(/[\[\]'"\s]/g, '').replace(/,/g, '\n');
+ }
+ }
+ }
+
+ // create input element
var self = this;
return new Ui.Input({
id : 'field-' + input_def.id,
diff --git a/static/scripts/mvc/tools/tools-tree.js b/static/scripts/mvc/tools/tools-tree.js
index 56e1fc1d443..4f394aefcab 100644
--- a/static/scripts/mvc/tools/tools-tree.js
+++ b/static/scripts/mvc/tools/tools-tree.js
@@ -123,7 +123,7 @@ return Backbone.Model.extend({
}
// handle simple value
- if (!field.skip ) {
+ if (!field.skip || self.app.workflow) {
if (field.validate && !field.validate()) {
value = null;
}
diff --git a/static/scripts/packed/mvc/tools/tools-form-base.js b/static/scripts/packed/mvc/tools/tools-form-base.js
index 43e8dbca60e..2bfbf4f680d 100644
--- a/static/scripts/packed/mvc/tools/tools-form-base.js
+++ b/static/scripts/packed/mvc/tools/tools-form-base.js
@@ -1 +1 @@
-define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("
");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_errors:function(n){if(n&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in this.element_list){var l=this.element_list[m];if(o[m]){this.highlight(m,o[m],true)}}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var m=this.options;this._renderForm(m);this.tree.finalize();this._errors(m);this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var n in this.element_list){this.element_list[n].reset()}});this.trigger("refresh")},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!this.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!this.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!this.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:""+u.name+" "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
+define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_errors:function(n){this.trigger("reset");if(n&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in this.element_list){var l=this.element_list[m];if(o[m]){this.highlight(m,o[m],true)}}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var m=this.options;this._renderForm(m);this.tree.finalize();this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var n in this.element_list){this.element_list[n].reset()}});this.trigger("refresh")},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!this.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!this.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!this.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:""+u.name+" "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
diff --git a/static/scripts/packed/mvc/tools/tools-form-workflow.js b/static/scripts/packed/mvc/tools/tools-form-workflow.js
index 70a5703e302..ed7e3ea41d6 100644
--- a/static/scripts/packed/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/packed/mvc/tools/tools-form-workflow.js
@@ -1 +1 @@
-define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","drill_down"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",expand:this.node.annotation,inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.labelhere for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done.",payload:{host:window.location.host}},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h);d._errors(h&&h.tool_model);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
+define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","drill_down"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",expand:this.node.annotation,inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.labelhere for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done.",payload:{host:window.location.host}},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id+"&__is_dynamic__=False";b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h);d._errors(h&&h.tool_model);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
diff --git a/static/scripts/packed/mvc/tools/tools-input.js b/static/scripts/packed/mvc/tools/tools-input.js
index ed1dbfb9988..661114aa109 100644
--- a/static/scripts/packed/mvc/tools/tools-input.js
+++ b/static/scripts/packed/mvc/tools/tools-input.js
@@ -1 +1 @@
-define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.field=c.field;this.defaultvalue=c.defaultvalue;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&((this.field.validate&&!this.field.validate())||!b||(b==this.defaultvalue)||(Number(b)==Number(this.defaultvalue))||(JSON.stringify(b)==JSON.stringify(this.defaultvalue))));this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){if(!this.field.skip){this.$error_text.html(a);this.$error.fadeIn();this.$el.addClass("ui-error")}},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable")}else{this.reset();this.$field.hide();this.$title_optional.html("Enable");this.field.value&&this.field.value(this.defaultvalue)}this.app.trigger("refresh")},_template:function(a){var b='
";return b}})});
\ No newline at end of file
+define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.field=c.field;this.defaultvalue=c.defaultvalue;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&((this.field.validate&&!this.field.validate())||!b||(b==this.defaultvalue)||(Number(b)==Number(this.defaultvalue))||(JSON.stringify(b)==JSON.stringify(this.defaultvalue))));this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){if(!this.field.skip){this.$error_text.html(a);this.$error.fadeIn("fast");this.$el.addClass("ui-error")}},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable")}else{this.reset();this.$field.hide();this.$title_optional.html("Enable");this.field.value&&this.field.value(this.defaultvalue)}this.app.trigger("refresh")},_template:function(a){var b='