galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
January 2014
- 1 participants
- 280 discussions
commit/galaxy-central: jmchilton: Fix workflow editor for changes in 5f6c670.
by commits-noreply@bitbucket.org 14 Jan '14
by commits-noreply@bitbucket.org 14 Jan '14
14 Jan '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fb1c758d0eb9/
Changeset: fb1c758d0eb9
User: jmchilton
Date: 2014-01-14 21:14:33
Summary: Fix workflow editor for changes in 5f6c670.
Affected #: 1 file
diff -r 22757ed4622ee1b975d966e9fe18ce6d83d2b909 -r fb1c758d0eb990f2ce59de422d1184647f051cc8 templates/webapps/galaxy/workflow/editor.mako
--- a/templates/webapps/galaxy/workflow/editor.mako
+++ b/templates/webapps/galaxy/workflow/editor.mako
@@ -291,6 +291,8 @@
</%def><%def name="left_panel()">
+ <% from galaxy.tools import Tool, ToolSection, ToolSectionLabel %>
+
<div class="unified-panel-header" unselectable="on"><div class='unified-panel-header-inner'>
${n_('Tools')}
@@ -306,9 +308,9 @@
<div class="toolSectionList">
%for key, val in app.toolbox.tool_panel.items():
<div class="toolSectionWrapper">
- %if key.startswith( 'tool' ):
+ %if isinstance( val, Tool ):
${render_tool( val, False )}
- %elif key.startswith( 'section' ) and val.elems:
+ %elif isinstance( val, ToolSection ) and val.elems:
<% section = val %><div class="toolSectionTitle" id="title_${section.id}"><span>${section.name}</span>
@@ -316,15 +318,15 @@
<div id="${section.id}" class="toolSectionBody"><div class="toolSectionBg">
%for section_key, section_val in section.elems.items():
- %if section_key.startswith( 'tool' ):
+ %if isinstance( section_val, Tool ):
${render_tool( section_val, True )}
- %elif section_key.startswith( 'label' ):
+ %elif isinstance( section_val, ToolSectionLabel ):
${render_label( section_val )}
%endif
%endfor
</div></div>
- %elif key.startswith( 'label' ):
+ %elif isinstance( val, ToolSectionLabel ):
${render_label( val )}
%endif
</div>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8fca48f410f7/
Changeset: 8fca48f410f7
User: dan
Date: 2014-01-14 19:39:59
Summary: Fix for history api set_as_current().
Affected #: 1 file
diff -r 28575f5bd33b555cf594247f7706679df425085b -r 8fca48f410f7996cb79318118f3799856d1d3628 lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -118,7 +118,7 @@
return history_data
@web.expose_api
- def set_as_current( self, trans, id, *kwd ):
+ def set_as_current( self, trans, id, **kwd ):
"""
set_as_current( trans, id, **kwd )
* POST /api/histories/{id}/set_as_current:
https://bitbucket.org/galaxy/galaxy-central/commits/a96ca602209c/
Changeset: a96ca602209c
Branch: stable
User: dan
Date: 2014-01-14 19:39:59
Summary: Fix for history api set_as_current().
Affected #: 1 file
diff -r 97fd1b009c86ac992716ce6e81d45cb20c06a3c1 -r a96ca602209ca2d4d732cced9530a62b3e4134a8 lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -117,7 +117,7 @@
return history_data
@web.expose_api
- def set_as_current( self, trans, id, *kwd ):
+ def set_as_current( self, trans, id, **kwd ):
"""
set_as_current( trans, id, **kwd )
* POST /api/histories/{id}/set_as_current:
https://bitbucket.org/galaxy/galaxy-central/commits/22757ed4622e/
Changeset: 22757ed4622e
User: dan
Date: 2014-01-14 19:40:43
Summary: Merge stable
Affected #: 1 file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c3a90a311c55/
Changeset: c3a90a311c55
User: martenson
Date: 2014-01-09 18:58:21
Summary: remove visualization and workflows menu items for anonymous users that can’t use them
Affected #: 2 files
diff -r 2d525856226f0115a5f8dea5e7fedfae2fcbcf8a -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a static/scripts/galaxy.menu.js
--- a/static/scripts/galaxy.menu.js
+++ b/static/scripts/galaxy.menu.js
@@ -38,13 +38,16 @@
//
// Workflow tab.
//
- var tab_workflow = new mod_masthead.GalaxyMastheadTab({
- id : "workflow",
- title : "Workflow",
- content : "workflow"
+ if (this.options.user.valid)
+ {
+ var tab_workflow = new mod_masthead.GalaxyMastheadTab({
+ id : "workflow",
+ title : "Workflow",
+ content : "workflow"
- });
- this.masthead.append(tab_workflow);
+ });
+ this.masthead.append(tab_workflow);
+ }
//
// 'Shared Items' or Libraries tab.
@@ -116,22 +119,25 @@
//
// Visualization tab.
//
- var tab_visualization = new mod_masthead.GalaxyMastheadTab({
- id : "visualization",
- title : "Visualization",
- content : "visualization/list"
- });
- tab_visualization.add({
- title : "New Track Browser",
- content : "visualization/trackster",
- target : "_frame"
- });
- tab_visualization.add({
- title : "Saved Visualizations",
- content : "visualization/list",
- target : "_frame"
- });
- this.masthead.append(tab_visualization);
+ if (this.options.user.valid)
+ {
+ var tab_visualization = new mod_masthead.GalaxyMastheadTab({
+ id : "visualization",
+ title : "Visualization",
+ content : "visualization/list"
+ });
+ tab_visualization.add({
+ title : "New Track Browser",
+ content : "visualization/trackster",
+ target : "_frame"
+ });
+ tab_visualization.add({
+ title : "Saved Visualizations",
+ content : "visualization/list",
+ target : "_frame"
+ });
+ this.masthead.append(tab_visualization);
+ }
//
// Cloud menu.
diff -r 2d525856226f0115a5f8dea5e7fedfae2fcbcf8a -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a static/scripts/packed/galaxy.menu.js
--- a/static/scripts/packed/galaxy.menu.js
+++ b/static/scripts/packed/galaxy.menu.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var d=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index"});this.masthead.append(d);var c=new b.GalaxyMastheadTab({id:"workflow",title:"Workflow",content:"workflow"});this.masthead.append(c);var g=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index"});g.add({title:"Data Libraries",content:"library/index"});g.add({title:"New Libraries",content:"library/list",divider:true});g.add({title:"Published Histories",content:"history/list_published"});g.add({title:"Published Workflows",content:"workflow/list_published"});g.add({title:"Published Visualizations",content:"visualization/list_published"});g.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(g);if(this.options.user.requests){var h=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});h.add({title:"Sequencing Requests",content:"requests/index"});h.add({title:"Find Samples",content:"requests/find_samples_index"});h.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(h)}var k=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list"});k.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});k.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"});this.masthead.append(k);if(this.options.enable_cloud_launch){var e=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});e.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(e)}if(this.options.is_admin_user){var f=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only"});this.masthead.append(f)}var j=new b.GalaxyMastheadTab({id:"help",title:"Help"});if(this.options.biostar_url){j.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});j.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}j.add({title:"Support",content:this.options.support_url,target:"_blank"});j.add({title:"Search",content:this.options.search_url,target:"_blank"});j.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});j.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});j.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});j.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){j.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(j);if(!this.options.user.valid){var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only"});i.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){i.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(i)}else{var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only"});i.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){i.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{i.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});i.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});i.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}i.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});i.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});i.add({title:"Saved Pages",content:"page/list",target:"_top"});i.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){i.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(i)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
+define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var d=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index"});this.masthead.append(d);if(this.options.user.valid){var c=new b.GalaxyMastheadTab({id:"workflow",title:"Workflow",content:"workflow"});this.masthead.append(c)}var g=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index"});g.add({title:"Data Libraries",content:"library/index"});g.add({title:"New Libraries",content:"library/list",divider:true});g.add({title:"Published Histories",content:"history/list_published"});g.add({title:"Published Workflows",content:"workflow/list_published"});g.add({title:"Published Visualizations",content:"visualization/list_published"});g.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(g);if(this.options.user.requests){var h=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});h.add({title:"Sequencing Requests",content:"requests/index"});h.add({title:"Find Samples",content:"requests/find_samples_index"});h.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(h)}if(this.options.user.valid){var k=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list"});k.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});k.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"});this.masthead.append(k)}if(this.options.enable_cloud_launch){var e=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});e.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(e)}if(this.options.is_admin_user){var f=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only"});this.masthead.append(f)}var j=new b.GalaxyMastheadTab({id:"help",title:"Help"});if(this.options.biostar_url){j.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});j.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}j.add({title:"Support",content:this.options.support_url,target:"_blank"});j.add({title:"Search",content:this.options.search_url,target:"_blank"});j.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});j.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});j.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});j.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){j.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(j);if(!this.options.user.valid){var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only"});i.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){i.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(i)}else{var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only"});i.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){i.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{i.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});i.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});i.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}i.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});i.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});i.add({title:"Saved Pages",content:"page/list",target:"_top"});i.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){i.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(i)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/a2a02033743a/
Changeset: a2a02033743a
User: martenson
Date: 2014-01-13 18:26:30
Summary: disable visualization and workflows menu items for anonymous users that can’t use them, show notification of clicked, also add possibility to use titles in menu (shown by default on hoover)
Affected #: 6 files
diff -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a -r a2a02033743a08357cf73cb7812006c4a69b7fb2 static/scripts/galaxy.masthead.js
--- a/static/scripts/galaxy.masthead.js
+++ b/static/scripts/galaxy.masthead.js
@@ -3,7 +3,7 @@
*/
// dependencies
-define(["utils/galaxy.utils"], function(mod_utils) {
+define(["utils/galaxy.utils", "libs/toastr"], function(mod_utils, mod_toastr) {
// masthead
var GalaxyMasthead = Backbone.View.extend(
@@ -259,7 +259,9 @@
type : 'url',
scratchbook : false,
on_unload : null,
- visible : true
+ visible : true,
+ disabled : false,
+ title_attribute : ''
},
// location
@@ -288,6 +290,12 @@
// add template for tab
this.setElement($(this._template(this.options)));
+ // disable menu items that are not available to anonymous user
+ // also show title to explain why they are disabled
+ if (this.options.disabled){
+ $(this.el).find('.root').addClass('disabled');
+ }
+
// visiblity
if (!this.options.visible)
this.hide();
@@ -371,9 +379,14 @@
// prevent default
e.preventDefault();
+ if (this.options.disabled){
+ mod_toastr.info('Please <a href="/user/create">register</a> to use this feature');
+ return
+ }
+
// check for menu options
if (!this.$menu) {
- Galaxy.frame.add(this.options);
+ Galaxy.frame.add(this.options);
}
},
@@ -400,7 +413,7 @@
// start template
var tmpl = '<ul id="' + options.id + '" class="nav navbar-nav" border="0" cellspacing="0">' +
'<li class="root dropdown" style="">' +
- '<a class="head dropdown-toggle" data-toggle="dropdown" target="' + options.target + '" href="' + options.content + '">' +
+ '<a class="head dropdown-toggle" data-toggle="dropdown" target="' + options.target + '" href="' + options.content + '" title="' + options.title_attribute + '">' +
options.title + '<b class="symbol"></b>' +
'</a>' +
'</li>' +
diff -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a -r a2a02033743a08357cf73cb7812006c4a69b7fb2 static/scripts/galaxy.menu.js
--- a/static/scripts/galaxy.menu.js
+++ b/static/scripts/galaxy.menu.js
@@ -31,23 +31,28 @@
var tab_analysis = new mod_masthead.GalaxyMastheadTab({
id : "analysis",
title : "Analyze Data",
- content : "root/index"
+ content : "root/index",
+ title_attribute : 'Main analysis page'
});
this.masthead.append(tab_analysis);
//
// Workflow tab.
//
- if (this.options.user.valid)
- {
- var tab_workflow = new mod_masthead.GalaxyMastheadTab({
- id : "workflow",
- title : "Workflow",
- content : "workflow"
- });
- this.masthead.append(tab_workflow);
+ var workflow_options = {
+ id : "workflow",
+ title : "Workflow",
+ content : "workflow",
+ title_attribute : 'Chain tools into workflows'
}
+ if (!this.options.user.valid){
+ workflow_options.disabled = true; // disable workflows for anonymous users
+ workflow_options.title_attribute = 'Please register to use workflows';
+ }
+
+ var tab_workflow = new mod_masthead.GalaxyMastheadTab(workflow_options);
+ this.masthead.append(tab_workflow);
//
// 'Shared Items' or Libraries tab.
@@ -55,7 +60,8 @@
var tab_shared = new mod_masthead.GalaxyMastheadTab({
id : "shared",
title : "Shared Data",
- content : "library/index"
+ content : "library/index",
+ title_attribute : 'Access public data'
});
tab_shared.add({
@@ -64,7 +70,7 @@
});
tab_shared.add({
- title : "New Libraries",
+ title : "Data Libraries Beta",
content : "library/list",
divider : true
});
@@ -124,7 +130,8 @@
var tab_visualization = new mod_masthead.GalaxyMastheadTab({
id : "visualization",
title : "Visualization",
- content : "visualization/list"
+ content : "visualization/list",
+ title_attribute : 'Visualize data'
});
tab_visualization.add({
title : "New Track Browser",
@@ -137,6 +144,16 @@
target : "_frame"
});
this.masthead.append(tab_visualization);
+ } else
+ {
+ var tab_visualization = new mod_masthead.GalaxyMastheadTab({
+ id : "visualization",
+ title : "Visualization",
+ content : "visualization/list",
+ disabled : true,
+ title_attribute : 'Please register to create visualizations'
+ });
+ this.masthead.append(tab_visualization);
}
//
@@ -165,7 +182,8 @@
id : "admin",
title : "Admin",
content : "admin/index",
- extra_class : "admin-only"
+ extra_class : "admin-only",
+ title_attribute : 'Administer this Galaxy'
});
this.masthead.append(tab_admin);
}
@@ -175,7 +193,8 @@
//
var tab_help = new mod_masthead.GalaxyMastheadTab({
id : "help",
- title : "Help"
+ title : "Help",
+ title_attribute : 'Find help with Galaxy'
});
if (this.options.biostar_url)
{
@@ -238,7 +257,8 @@
var tab_user = new mod_masthead.GalaxyMastheadTab({
id : "user",
title : "User",
- extra_class : "loggedout-only"
+ extra_class : "loggedout-only",
+ title_attribute : 'Account information'
});
// login
@@ -264,7 +284,8 @@
var tab_user = new mod_masthead.GalaxyMastheadTab({
id : "user",
title : "User",
- extra_class : "loggedin-only"
+ extra_class : "loggedin-only",
+ title_attribute : 'Account information'
});
// show user logged in info
diff -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a -r a2a02033743a08357cf73cb7812006c4a69b7fb2 static/scripts/packed/galaxy.masthead.js
--- a/static/scripts/packed/galaxy.masthead.js
+++ b/static/scripts/packed/galaxy.masthead.js
@@ -1,1 +1,1 @@
-define(["utils/galaxy.utils"],function(c){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(f){this.options=f;$("body").off();this.setElement($(this._template(f)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var e=this;window.onbeforeunload=function(){var h="";for(key in e.list){if(e.list[key].options.on_unload){var g=e.list[key].options.on_unload();if(g){h+=g+" "}}}if(h!=""){return h}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(e){return this._add(e,true)},prepend:function(e){return this._add(e,false)},highlight:function(f){var e=$(this.el).find("#"+f+"> li");if(e){e.addClass("active")}},_add:function(h,f){var e=$(this.el).find("#"+h.location);if(e){var g=$(h.el);g.addClass("masthead-item");if(f){e.append(g)}else{e.prepend(g)}this.list.push(h)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(e){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+e.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+e.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(f){if(f){this.options=_.defaults(f,this.options)}this.setElement($(this._template(this.options)));var e=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",e.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(e){$(this.el).find(".icon").removeClass(this.options.icon).addClass(e);this.options.icon=e},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(e){$(this.el).find(".number").text(e)},_template:function(f){var e='<div id="'+f.id+'" class="symbol"><div class="icon fa fa-2x '+f.icon+'"></div>';if(f.with_number){e+='<div class="number"></div>'}e+="</div>";return e}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(e){if(e){this.options=_.defaults(e,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(g){var h={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(g){h=_.defaults(g,h)}if(h.content&&h.content.indexOf("//")===-1){h.content=galaxy_config.root+h.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var f=$(this._templateMenuItem(h));this.$menu.append(f);var e=this;f.on("click",function(i){i.preventDefault();if(e.options.target==="_blank"){return true}Galaxy.frame.add(g)});if(h.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(!this.$menu){Galaxy.frame.add(this.options)}},_templateMenuItem:function(e){return'<li><a href="'+e.content+'" target="'+e.target+'">'+e.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(f){var e='<ul id="'+f.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+f.target+'" href="'+f.content+'">'+f.title+'<b class="symbol"></b></a></li></ul>';return e}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
+define(["utils/galaxy.utils","libs/toastr"],function(c,e){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(g){this.options=g;$("body").off();this.setElement($(this._template(g)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var f=this;window.onbeforeunload=function(){var i="";for(key in f.list){if(f.list[key].options.on_unload){var h=f.list[key].options.on_unload();if(h){i+=h+" "}}}if(i!=""){return i}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(f){return this._add(f,true)},prepend:function(f){return this._add(f,false)},highlight:function(g){var f=$(this.el).find("#"+g+"> li");if(f){f.addClass("active")}},_add:function(i,g){var f=$(this.el).find("#"+i.location);if(f){var h=$(i.el);h.addClass("masthead-item");if(g){f.append(h)}else{f.prepend(h)}this.list.push(i)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(f){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+f.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+f.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(g){if(g){this.options=_.defaults(g,this.options)}this.setElement($(this._template(this.options)));var f=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",f.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(f){$(this.el).find(".icon").removeClass(this.options.icon).addClass(f);this.options.icon=f},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(f){$(this.el).find(".number").text(f)},_template:function(g){var f='<div id="'+g.id+'" class="symbol"><div class="icon fa fa-2x '+g.icon+'"></div>';if(g.with_number){f+='<div class="number"></div>'}f+="</div>";return f}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(f){if(f){this.options=_.defaults(f,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled")}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(h){var i={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(h){i=_.defaults(h,i)}if(i.content&&i.content.indexOf("//")===-1){i.content=galaxy_config.root+i.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var g=$(this._templateMenuItem(i));this.$menu.append(g);var f=this;g.on("click",function(j){j.preventDefault();if(f.options.target==="_blank"){return true}Galaxy.frame.add(h)});if(i.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){e.info('Please <a href="/user/create">register</a> to use this feature');return}if(!this.$menu){Galaxy.frame.add(this.options)}},_templateMenuItem:function(f){return'<li><a href="'+f.content+'" target="'+f.target+'">'+f.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(g){var f='<ul id="'+g.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+g.target+'" href="'+g.content+'" title="'+g.title_attribute+'">'+g.title+'<b class="symbol"></b></a></li></ul>';return f}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
diff -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a -r a2a02033743a08357cf73cb7812006c4a69b7fb2 static/scripts/packed/galaxy.menu.js
--- a/static/scripts/packed/galaxy.menu.js
+++ b/static/scripts/packed/galaxy.menu.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var d=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index"});this.masthead.append(d);if(this.options.user.valid){var c=new b.GalaxyMastheadTab({id:"workflow",title:"Workflow",content:"workflow"});this.masthead.append(c)}var g=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index"});g.add({title:"Data Libraries",content:"library/index"});g.add({title:"New Libraries",content:"library/list",divider:true});g.add({title:"Published Histories",content:"history/list_published"});g.add({title:"Published Workflows",content:"workflow/list_published"});g.add({title:"Published Visualizations",content:"visualization/list_published"});g.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(g);if(this.options.user.requests){var h=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});h.add({title:"Sequencing Requests",content:"requests/index"});h.add({title:"Find Samples",content:"requests/find_samples_index"});h.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(h)}if(this.options.user.valid){var k=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list"});k.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});k.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"});this.masthead.append(k)}if(this.options.enable_cloud_launch){var e=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});e.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(e)}if(this.options.is_admin_user){var f=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only"});this.masthead.append(f)}var j=new b.GalaxyMastheadTab({id:"help",title:"Help"});if(this.options.biostar_url){j.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});j.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}j.add({title:"Support",content:this.options.support_url,target:"_blank"});j.add({title:"Search",content:this.options.search_url,target:"_blank"});j.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});j.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});j.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});j.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){j.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(j);if(!this.options.user.valid){var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only"});i.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){i.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(i)}else{var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only"});i.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){i.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{i.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});i.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});i.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}i.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});i.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});i.add({title:"Saved Pages",content:"page/list",target:"_top"});i.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){i.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(i)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
+define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var d=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index",title_attribute:"Main analysis page"});this.masthead.append(d);var f={id:"workflow",title:"Workflow",content:"workflow",title_attribute:"Chain tools into workflows"};if(!this.options.user.valid){f.disabled=true;f.title_attribute="Please register to use workflows"}var c=new b.GalaxyMastheadTab(f);this.masthead.append(c);var h=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index",title_attribute:"Access public data"});h.add({title:"Data Libraries",content:"library/index"});h.add({title:"Data Libraries Beta",content:"library/list",divider:true});h.add({title:"Published Histories",content:"history/list_published"});h.add({title:"Published Workflows",content:"workflow/list_published"});h.add({title:"Published Visualizations",content:"visualization/list_published"});h.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(h);if(this.options.user.requests){var i=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});i.add({title:"Sequencing Requests",content:"requests/index"});i.add({title:"Find Samples",content:"requests/find_samples_index"});i.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(i)}if(this.options.user.valid){var l=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list",title_attribute:"Visualize data"});l.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});l.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"});this.masthead.append(l)}else{var l=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list",disabled:true,title_attribute:"Please register to create visualizations"});this.masthead.append(l)}if(this.options.enable_cloud_launch){var e=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});e.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(e)}if(this.options.is_admin_user){var g=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only",title_attribute:"Administer this Galaxy"});this.masthead.append(g)}var k=new b.GalaxyMastheadTab({id:"help",title:"Help",title_attribute:"Find help with Galaxy"});if(this.options.biostar_url){k.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});k.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}k.add({title:"Support",content:this.options.support_url,target:"_blank"});k.add({title:"Search",content:this.options.search_url,target:"_blank"});k.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});k.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});k.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});k.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){k.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(k);if(!this.options.user.valid){var j=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only",title_attribute:"Account information"});j.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){j.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(j)}else{var j=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only",title_attribute:"Account information"});j.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){j.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{j.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});j.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});j.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}j.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});j.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});j.add({title:"Saved Pages",content:"page/list",target:"_top"});j.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){j.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(j)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
diff -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a -r a2a02033743a08357cf73cb7812006c4a69b7fb2 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1295,7 +1295,7 @@
.toast-title{font-weight:bold}
.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}
.toast-message a:hover{color:#ccc;text-decoration:none}
-.toast-close-button{position:relative;right:-0.3em;top:-0.3em;float:right;font-size:20px;font-weight:bold;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;filter:alpha(opacity=80);opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}.toast-close-button:hover,.toast-close-button:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=40);opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}
+.toast-close-button{position:relative;right:-0.3em;top:-0.3em;float:right;font-size:20px;font-weight:bold;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;filter:alpha(opacity=100);opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100)}.toast-close-button:hover,.toast-close-button:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=100);opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100)}
button.toast-close-button{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}
.toast-top-full-width{top:0;right:0;width:100%}
.toast-bottom-full-width{bottom:0;right:0;width:100%}
@@ -1304,7 +1304,7 @@
.toast-bottom-right{right:12px;bottom:12px}
.toast-bottom-left{bottom:12px;left:12px}
#toast-container{position:fixed;z-index:999999;}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
-#toast-container>div{margin:4em 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;filter:alpha(opacity=80);opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}
+#toast-container>div{margin:4em 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;filter:alpha(opacity=100);opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100)}
#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}
#toast-container>.toast-info{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important}
#toast-container>.toast-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important}
diff -r c3a90a311c55e4ec8e95ebb043e7ad6881c06e9a -r a2a02033743a08357cf73cb7812006c4a69b7fb2 static/style/src/less/toastr.less
--- a/static/style/src/less/toastr.less
+++ b/static/style/src/less/toastr.less
@@ -63,14 +63,14 @@
color: @white;
-webkit-text-shadow: 0 1px 0 rgba(255,255,255,1);
text-shadow: 0 1px 0 rgba(255,255,255,1);
- .opacity(0.8);
+ .opacity(1);
&:hover,
&:focus {
color: @black;
text-decoration: none;
cursor: pointer;
- .opacity(0.4);
+ .opacity(1);
}
}
@@ -138,7 +138,7 @@
background-repeat: no-repeat;
.boxShadow(0 0 12px @grey);
color: @white;
- .opacity(0.8);
+ .opacity(1);
}
> :hover {
https://bitbucket.org/galaxy/galaxy-central/commits/6567a77ae7a5/
Changeset: 6567a77ae7a5
User: martenson
Date: 2014-01-13 20:07:00
Summary: galaxy top menu tweaks, titles, notification
Affected #: 4 files
diff -r a2a02033743a08357cf73cb7812006c4a69b7fb2 -r 6567a77ae7a5f5529e07be0f7594df275c6930af static/scripts/galaxy.masthead.js
--- a/static/scripts/galaxy.masthead.js
+++ b/static/scripts/galaxy.masthead.js
@@ -380,7 +380,7 @@
e.preventDefault();
if (this.options.disabled){
- mod_toastr.info('Please <a href="/user/create">register</a> to use this feature');
+ mod_toastr.info('Please <a href="/user/create">register</a> or <a href="/user/login"> log in</a> to use this feature');
return
}
diff -r a2a02033743a08357cf73cb7812006c4a69b7fb2 -r 6567a77ae7a5f5529e07be0f7594df275c6930af static/scripts/galaxy.menu.js
--- a/static/scripts/galaxy.menu.js
+++ b/static/scripts/galaxy.menu.js
@@ -32,7 +32,7 @@
id : "analysis",
title : "Analyze Data",
content : "root/index",
- title_attribute : 'Main analysis page'
+ title_attribute : 'Analysis home view'
});
this.masthead.append(tab_analysis);
@@ -48,7 +48,6 @@
}
if (!this.options.user.valid){
workflow_options.disabled = true; // disable workflows for anonymous users
- workflow_options.title_attribute = 'Please register to use workflows';
}
var tab_workflow = new mod_masthead.GalaxyMastheadTab(workflow_options);
@@ -61,7 +60,7 @@
id : "shared",
title : "Shared Data",
content : "library/index",
- title_attribute : 'Access public data'
+ title_attribute : 'Access published resources'
});
tab_shared.add({
@@ -125,14 +124,21 @@
//
// Visualization tab.
//
- if (this.options.user.valid)
+
+ var visualization_options = {
+ id : "visualization",
+ title : "Visualization",
+ content : "visualization/list",
+ title_attribute : 'Visualize datasets'
+ }
+ if (!this.options.user.valid){
+ visualization_options.disabled = true; // disable visualizations for anonymous users
+ }
+
+ var tab_visualization = new mod_masthead.GalaxyMastheadTab(visualization_options);
+
+ if (this.options.user.valid) //add submenu only when user is logged in
{
- var tab_visualization = new mod_masthead.GalaxyMastheadTab({
- id : "visualization",
- title : "Visualization",
- content : "visualization/list",
- title_attribute : 'Visualize data'
- });
tab_visualization.add({
title : "New Track Browser",
content : "visualization/trackster",
@@ -143,18 +149,8 @@
content : "visualization/list",
target : "_frame"
});
- this.masthead.append(tab_visualization);
- } else
- {
- var tab_visualization = new mod_masthead.GalaxyMastheadTab({
- id : "visualization",
- title : "Visualization",
- content : "visualization/list",
- disabled : true,
- title_attribute : 'Please register to create visualizations'
- });
- this.masthead.append(tab_visualization);
- }
+ }
+ this.masthead.append(tab_visualization);
//
// Cloud menu.
@@ -194,7 +190,7 @@
var tab_help = new mod_masthead.GalaxyMastheadTab({
id : "help",
title : "Help",
- title_attribute : 'Find help with Galaxy'
+ title_attribute : 'Support, contact, and community hubs'
});
if (this.options.biostar_url)
{
@@ -258,7 +254,7 @@
id : "user",
title : "User",
extra_class : "loggedout-only",
- title_attribute : 'Account information'
+ title_attribute : 'Account registration or login'
});
// login
@@ -285,7 +281,7 @@
id : "user",
title : "User",
extra_class : "loggedin-only",
- title_attribute : 'Account information'
+ title_attribute : 'Account preferences and saved data'
});
// show user logged in info
diff -r a2a02033743a08357cf73cb7812006c4a69b7fb2 -r 6567a77ae7a5f5529e07be0f7594df275c6930af static/scripts/packed/galaxy.masthead.js
--- a/static/scripts/packed/galaxy.masthead.js
+++ b/static/scripts/packed/galaxy.masthead.js
@@ -1,1 +1,1 @@
-define(["utils/galaxy.utils","libs/toastr"],function(c,e){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(g){this.options=g;$("body").off();this.setElement($(this._template(g)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var f=this;window.onbeforeunload=function(){var i="";for(key in f.list){if(f.list[key].options.on_unload){var h=f.list[key].options.on_unload();if(h){i+=h+" "}}}if(i!=""){return i}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(f){return this._add(f,true)},prepend:function(f){return this._add(f,false)},highlight:function(g){var f=$(this.el).find("#"+g+"> li");if(f){f.addClass("active")}},_add:function(i,g){var f=$(this.el).find("#"+i.location);if(f){var h=$(i.el);h.addClass("masthead-item");if(g){f.append(h)}else{f.prepend(h)}this.list.push(i)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(f){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+f.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+f.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(g){if(g){this.options=_.defaults(g,this.options)}this.setElement($(this._template(this.options)));var f=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",f.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(f){$(this.el).find(".icon").removeClass(this.options.icon).addClass(f);this.options.icon=f},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(f){$(this.el).find(".number").text(f)},_template:function(g){var f='<div id="'+g.id+'" class="symbol"><div class="icon fa fa-2x '+g.icon+'"></div>';if(g.with_number){f+='<div class="number"></div>'}f+="</div>";return f}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(f){if(f){this.options=_.defaults(f,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled")}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(h){var i={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(h){i=_.defaults(h,i)}if(i.content&&i.content.indexOf("//")===-1){i.content=galaxy_config.root+i.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var g=$(this._templateMenuItem(i));this.$menu.append(g);var f=this;g.on("click",function(j){j.preventDefault();if(f.options.target==="_blank"){return true}Galaxy.frame.add(h)});if(i.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){e.info('Please <a href="/user/create">register</a> to use this feature');return}if(!this.$menu){Galaxy.frame.add(this.options)}},_templateMenuItem:function(f){return'<li><a href="'+f.content+'" target="'+f.target+'">'+f.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(g){var f='<ul id="'+g.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+g.target+'" href="'+g.content+'" title="'+g.title_attribute+'">'+g.title+'<b class="symbol"></b></a></li></ul>';return f}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
+define(["utils/galaxy.utils","libs/toastr"],function(c,e){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(g){this.options=g;$("body").off();this.setElement($(this._template(g)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var f=this;window.onbeforeunload=function(){var i="";for(key in f.list){if(f.list[key].options.on_unload){var h=f.list[key].options.on_unload();if(h){i+=h+" "}}}if(i!=""){return i}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(f){return this._add(f,true)},prepend:function(f){return this._add(f,false)},highlight:function(g){var f=$(this.el).find("#"+g+"> li");if(f){f.addClass("active")}},_add:function(i,g){var f=$(this.el).find("#"+i.location);if(f){var h=$(i.el);h.addClass("masthead-item");if(g){f.append(h)}else{f.prepend(h)}this.list.push(i)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(f){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+f.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+f.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(g){if(g){this.options=_.defaults(g,this.options)}this.setElement($(this._template(this.options)));var f=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",f.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(f){$(this.el).find(".icon").removeClass(this.options.icon).addClass(f);this.options.icon=f},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(f){$(this.el).find(".number").text(f)},_template:function(g){var f='<div id="'+g.id+'" class="symbol"><div class="icon fa fa-2x '+g.icon+'"></div>';if(g.with_number){f+='<div class="number"></div>'}f+="</div>";return f}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(f){if(f){this.options=_.defaults(f,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled")}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(h){var i={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(h){i=_.defaults(h,i)}if(i.content&&i.content.indexOf("//")===-1){i.content=galaxy_config.root+i.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var g=$(this._templateMenuItem(i));this.$menu.append(g);var f=this;g.on("click",function(j){j.preventDefault();if(f.options.target==="_blank"){return true}Galaxy.frame.add(h)});if(i.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){e.info('Please <a href="/user/create">register</a> or <a href="/user/login"> log in</a> to use this feature');return}if(!this.$menu){Galaxy.frame.add(this.options)}},_templateMenuItem:function(f){return'<li><a href="'+f.content+'" target="'+f.target+'">'+f.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(g){var f='<ul id="'+g.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+g.target+'" href="'+g.content+'" title="'+g.title_attribute+'">'+g.title+'<b class="symbol"></b></a></li></ul>';return f}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
diff -r a2a02033743a08357cf73cb7812006c4a69b7fb2 -r 6567a77ae7a5f5529e07be0f7594df275c6930af static/scripts/packed/galaxy.menu.js
--- a/static/scripts/packed/galaxy.menu.js
+++ b/static/scripts/packed/galaxy.menu.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var d=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index",title_attribute:"Main analysis page"});this.masthead.append(d);var f={id:"workflow",title:"Workflow",content:"workflow",title_attribute:"Chain tools into workflows"};if(!this.options.user.valid){f.disabled=true;f.title_attribute="Please register to use workflows"}var c=new b.GalaxyMastheadTab(f);this.masthead.append(c);var h=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index",title_attribute:"Access public data"});h.add({title:"Data Libraries",content:"library/index"});h.add({title:"Data Libraries Beta",content:"library/list",divider:true});h.add({title:"Published Histories",content:"history/list_published"});h.add({title:"Published Workflows",content:"workflow/list_published"});h.add({title:"Published Visualizations",content:"visualization/list_published"});h.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(h);if(this.options.user.requests){var i=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});i.add({title:"Sequencing Requests",content:"requests/index"});i.add({title:"Find Samples",content:"requests/find_samples_index"});i.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(i)}if(this.options.user.valid){var l=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list",title_attribute:"Visualize data"});l.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});l.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"});this.masthead.append(l)}else{var l=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list",disabled:true,title_attribute:"Please register to create visualizations"});this.masthead.append(l)}if(this.options.enable_cloud_launch){var e=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});e.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(e)}if(this.options.is_admin_user){var g=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only",title_attribute:"Administer this Galaxy"});this.masthead.append(g)}var k=new b.GalaxyMastheadTab({id:"help",title:"Help",title_attribute:"Find help with Galaxy"});if(this.options.biostar_url){k.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});k.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}k.add({title:"Support",content:this.options.support_url,target:"_blank"});k.add({title:"Search",content:this.options.search_url,target:"_blank"});k.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});k.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});k.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});k.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){k.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(k);if(!this.options.user.valid){var j=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only",title_attribute:"Account information"});j.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){j.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(j)}else{var j=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only",title_attribute:"Account information"});j.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){j.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{j.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});j.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});j.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}j.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});j.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});j.add({title:"Saved Pages",content:"page/list",target:"_top"});j.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){j.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(j)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
+define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var e=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index",title_attribute:"Analysis home view"});this.masthead.append(e);var g={id:"workflow",title:"Workflow",content:"workflow",title_attribute:"Chain tools into workflows"};if(!this.options.user.valid){g.disabled=true}var d=new b.GalaxyMastheadTab(g);this.masthead.append(d);var i=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index",title_attribute:"Access published resources"});i.add({title:"Data Libraries",content:"library/index"});i.add({title:"Data Libraries Beta",content:"library/list",divider:true});i.add({title:"Published Histories",content:"history/list_published"});i.add({title:"Published Workflows",content:"workflow/list_published"});i.add({title:"Published Visualizations",content:"visualization/list_published"});i.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(i);if(this.options.user.requests){var j=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});j.add({title:"Sequencing Requests",content:"requests/index"});j.add({title:"Find Samples",content:"requests/find_samples_index"});j.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(j)}var c={id:"visualization",title:"Visualization",content:"visualization/list",title_attribute:"Visualize datasets"};if(!this.options.user.valid){c.disabled=true}var m=new b.GalaxyMastheadTab(c);if(this.options.user.valid){m.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});m.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"})}this.masthead.append(m);if(this.options.enable_cloud_launch){var f=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});f.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(f)}if(this.options.is_admin_user){var h=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only",title_attribute:"Administer this Galaxy"});this.masthead.append(h)}var l=new b.GalaxyMastheadTab({id:"help",title:"Help",title_attribute:"Support, contact, and community hubs"});if(this.options.biostar_url){l.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});l.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}l.add({title:"Support",content:this.options.support_url,target:"_blank"});l.add({title:"Search",content:this.options.search_url,target:"_blank"});l.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});l.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});l.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});l.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){l.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(l);if(!this.options.user.valid){var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only",title_attribute:"Account registration or login"});k.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){k.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(k)}else{var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only",title_attribute:"Account preferences and saved data"});k.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){k.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{k.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});k.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});k.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}k.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});k.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});k.add({title:"Saved Pages",content:"page/list",target:"_top"});k.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){k.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(k)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/d0904bfb2f43/
Changeset: d0904bfb2f43
User: martenson
Date: 2014-01-13 22:51:24
Summary: galaxy top menu tweaks, titles, notification
Affected #: 4 files
diff -r 6567a77ae7a5f5529e07be0f7594df275c6930af -r d0904bfb2f43bca4847b1e3f59b4a57296390cb4 static/scripts/galaxy.masthead.js
--- a/static/scripts/galaxy.masthead.js
+++ b/static/scripts/galaxy.masthead.js
@@ -294,6 +294,7 @@
// also show title to explain why they are disabled
if (this.options.disabled){
$(this.el).find('.root').addClass('disabled');
+ this._attachPopover();
}
// visiblity
@@ -380,8 +381,7 @@
e.preventDefault();
if (this.options.disabled){
- mod_toastr.info('Please <a href="/user/create">register</a> or <a href="/user/login"> log in</a> to use this feature');
- return
+ return // prevent link following if menu item is disabled
}
// check for menu options
@@ -389,7 +389,21 @@
Galaxy.frame.add(this.options);
}
},
-
+
+ _attachPopover : function()
+ {
+ var $popover_element = $(this.el).find('.head');
+ $popover_element.popover({
+ html: true,
+ content: 'Please <a href="/user/login">log in</a> or <a href="/user/create">register</a> to use this feature.',
+ placement: 'bottom'
+ }).on('shown.bs.popover', function() { // hooking on bootstrap event to automatically hide popovers after delay
+ setTimeout(function() {
+ $popover_element.popover('hide');
+ }, 5000);
+ });
+ },
+
// fill template header
_templateMenuItem: function (options)
{
diff -r 6567a77ae7a5f5529e07be0f7594df275c6930af -r d0904bfb2f43bca4847b1e3f59b4a57296390cb4 static/scripts/libs/bootstrap.js
--- a/static/scripts/libs/bootstrap.js
+++ b/static/scripts/libs/bootstrap.js
@@ -729,4 +729,122 @@
.on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
-}(window.jQuery);
\ No newline at end of file
+}(window.jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.0.3
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2013 Twitter, Inc.
+ *
+ * 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.
+ * ======================================================================== */
+
+
++function ($) { "use strict";
+
+ // POPOVER PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+ Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {
+ placement: 'right'
+ , trigger: 'click'
+ , content: ''
+ , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ })
+
+
+ // NOTE: POPOVER EXTENDS tooltip.js
+ // ================================
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+ Popover.prototype.constructor = Popover
+
+ Popover.prototype.getDefaults = function () {
+ return Popover.DEFAULTS
+ }
+
+ Popover.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+ var content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+ $tip.removeClass('fade top bottom left right in')
+
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+ // this manually by checking the contents.
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+ }
+
+ Popover.prototype.hasContent = function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ Popover.prototype.getContent = function () {
+ var $e = this.$element
+ var o = this.options
+
+ return $e.attr('data-content')
+ || (typeof o.content == 'function' ?
+ o.content.call($e[0]) :
+ o.content)
+ }
+
+ Popover.prototype.arrow = function () {
+ return this.$arrow = this.$arrow || this.tip().find('.arrow')
+ }
+
+ Popover.prototype.tip = function () {
+ if (!this.$tip) this.$tip = $(this.options.template)
+ return this.$tip
+ }
+
+
+ // POPOVER PLUGIN DEFINITION
+ // =========================
+
+ var old = $.fn.popover
+
+ $.fn.popover = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+
+ // POPOVER NO CONFLICT
+ // ===================
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(jQuery);
diff -r 6567a77ae7a5f5529e07be0f7594df275c6930af -r d0904bfb2f43bca4847b1e3f59b4a57296390cb4 static/scripts/packed/galaxy.masthead.js
--- a/static/scripts/packed/galaxy.masthead.js
+++ b/static/scripts/packed/galaxy.masthead.js
@@ -1,1 +1,1 @@
-define(["utils/galaxy.utils","libs/toastr"],function(c,e){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(g){this.options=g;$("body").off();this.setElement($(this._template(g)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var f=this;window.onbeforeunload=function(){var i="";for(key in f.list){if(f.list[key].options.on_unload){var h=f.list[key].options.on_unload();if(h){i+=h+" "}}}if(i!=""){return i}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(f){return this._add(f,true)},prepend:function(f){return this._add(f,false)},highlight:function(g){var f=$(this.el).find("#"+g+"> li");if(f){f.addClass("active")}},_add:function(i,g){var f=$(this.el).find("#"+i.location);if(f){var h=$(i.el);h.addClass("masthead-item");if(g){f.append(h)}else{f.prepend(h)}this.list.push(i)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(f){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+f.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+f.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(g){if(g){this.options=_.defaults(g,this.options)}this.setElement($(this._template(this.options)));var f=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",f.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(f){$(this.el).find(".icon").removeClass(this.options.icon).addClass(f);this.options.icon=f},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(f){$(this.el).find(".number").text(f)},_template:function(g){var f='<div id="'+g.id+'" class="symbol"><div class="icon fa fa-2x '+g.icon+'"></div>';if(g.with_number){f+='<div class="number"></div>'}f+="</div>";return f}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(f){if(f){this.options=_.defaults(f,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled")}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(h){var i={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(h){i=_.defaults(h,i)}if(i.content&&i.content.indexOf("//")===-1){i.content=galaxy_config.root+i.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var g=$(this._templateMenuItem(i));this.$menu.append(g);var f=this;g.on("click",function(j){j.preventDefault();if(f.options.target==="_blank"){return true}Galaxy.frame.add(h)});if(i.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){e.info('Please <a href="/user/create">register</a> or <a href="/user/login"> log in</a> to use this feature');return}if(!this.$menu){Galaxy.frame.add(this.options)}},_templateMenuItem:function(f){return'<li><a href="'+f.content+'" target="'+f.target+'">'+f.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(g){var f='<ul id="'+g.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+g.target+'" href="'+g.content+'" title="'+g.title_attribute+'">'+g.title+'<b class="symbol"></b></a></li></ul>';return f}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
+define(["utils/galaxy.utils","libs/toastr"],function(c,e){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(g){this.options=g;$("body").off();this.setElement($(this._template(g)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var f=this;window.onbeforeunload=function(){var i="";for(key in f.list){if(f.list[key].options.on_unload){var h=f.list[key].options.on_unload();if(h){i+=h+" "}}}if(i!=""){return i}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(f){return this._add(f,true)},prepend:function(f){return this._add(f,false)},highlight:function(g){var f=$(this.el).find("#"+g+"> li");if(f){f.addClass("active")}},_add:function(i,g){var f=$(this.el).find("#"+i.location);if(f){var h=$(i.el);h.addClass("masthead-item");if(g){f.append(h)}else{f.prepend(h)}this.list.push(i)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(f){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+f.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+f.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(g){if(g){this.options=_.defaults(g,this.options)}this.setElement($(this._template(this.options)));var f=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",f.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(f){$(this.el).find(".icon").removeClass(this.options.icon).addClass(f);this.options.icon=f},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(f){$(this.el).find(".number").text(f)},_template:function(g){var f='<div id="'+g.id+'" class="symbol"><div class="icon fa fa-2x '+g.icon+'"></div>';if(g.with_number){f+='<div class="number"></div>'}f+="</div>";return f}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(f){if(f){this.options=_.defaults(f,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled");this._attachPopover()}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(h){var i={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(h){i=_.defaults(h,i)}if(i.content&&i.content.indexOf("//")===-1){i.content=galaxy_config.root+i.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var g=$(this._templateMenuItem(i));this.$menu.append(g);var f=this;g.on("click",function(j){j.preventDefault();if(f.options.target==="_blank"){return true}Galaxy.frame.add(h)});if(i.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){return}if(!this.$menu){Galaxy.frame.add(this.options)}},_attachPopover:function(){var f=$(this.el).find(".head");f.popover({html:true,content:'Please <a href="/user/login">log in</a> or <a href="/user/create">register</a> to use this feature.',placement:"bottom"}).on("shown.bs.popover",function(){setTimeout(function(){f.popover("hide")},5000)})},_templateMenuItem:function(f){return'<li><a href="'+f.content+'" target="'+f.target+'">'+f.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(g){var f='<ul id="'+g.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+g.target+'" href="'+g.content+'" title="'+g.title_attribute+'">'+g.title+'<b class="symbol"></b></a></li></ul>';return f}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
diff -r 6567a77ae7a5f5529e07be0f7594df275c6930af -r d0904bfb2f43bca4847b1e3f59b4a57296390cb4 static/scripts/packed/libs/bootstrap.js
--- a/static/scripts/packed/libs/bootstrap.js
+++ b/static/scripts/packed/libs/bootstrap.js
@@ -1,1 +1,1 @@
-+function(b){function a(){var e=document.createElement("bootstrap");var d={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in d){if(e.style[c]!==undefined){return{end:d[c]}}}}b.fn.emulateTransitionEnd=function(e){var d=false,c=this;b(this).one(b.support.transition.end,function(){d=true});var f=function(){if(!d){b(c).trigger(b.support.transition.end)}};setTimeout(f,e);return this};b(function(){b.support.transition=a()})}(window.jQuery);+function(c){var b=function(d){this.element=c(d)};b.prototype.show=function(){var j=this.element;var g=j.closest("ul:not(.dropdown-menu)");var f=j.attr("data-target");if(!f){f=j.attr("href");f=f&&f.replace(/.*(?=#[^\s]*$)/,"")}if(j.parent("li").hasClass("active")){return}var h=g.find(".active:last a")[0];var i=c.Event("show.bs.tab",{relatedTarget:h});j.trigger(i);if(i.isDefaultPrevented()){return}var d=c(f);this.activate(j.parent("li"),g);this.activate(d,d.parent(),function(){j.trigger({type:"shown.bs.tab",relatedTarget:h})})};b.prototype.activate=function(f,e,i){var d=e.find("> .active");var h=i&&c.support.transition&&d.hasClass("fade");function g(){d.removeClass("active").find("> .dropdown-menu > .active").removeClass("active");f.addClass("active");if(h){f[0].offsetWidth;f.addClass("in")}else{f.removeClass("fade")}if(f.parent(".dropdown-menu")){f.closest("li.dropdown").addClass("active")}i&&i()}h?d.one(c.support.transition.end,g).emulateTransitionEnd(150):g();d.removeClass("in")};var a=c.fn.tab;c.fn.tab=function(d){return this.each(function(){var f=c(this);var e=f.data("bs.tab");if(!e){f.data("bs.tab",(e=new b(this)))}if(typeof d=="string"){e[d]()}})};c.fn.tab.Constructor=b;c.fn.tab.noConflict=function(){c.fn.tab=a;return this};c(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(d){d.preventDefault();c(this).tab("show")})}(window.jQuery);+function(c){var b=function(e,d){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null;this.init("tooltip",e,d)};b.DEFAULTS={animation:true,placement:"top",selector:false,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:false,container:"body"};b.prototype.init=function(k,h,f){this.enabled=true;this.type=k;this.$element=c(h);this.options=this.getOptions(f);var j=this.options.trigger.split(" ");for(var g=j.length;g--;){var e=j[g];if(e=="click"){this.$element.on("click."+this.type,this.options.selector,c.proxy(this.toggle,this))}else{if(e!="manual"){var l=e=="hover"?"mouseenter":"focus";var d=e=="hover"?"mouseleave":"blur";this.$element.on(l+"."+this.type,this.options.selector,c.proxy(this.enter,this));this.$element.on(d+"."+this.type,this.options.selector,c.proxy(this.leave,this))}}}this.options.selector?(this._options=c.extend({},this.options,{trigger:"manual",selector:""})):this.fixTitle()};b.prototype.getDefaults=function(){return b.DEFAULTS};b.prototype.getOptions=function(d){d=c.extend({},this.getDefaults(),this.$element.data(),d);if(d.delay&&typeof d.delay=="number"){d.delay={show:d.delay,hide:d.delay}}return d};b.prototype.getDelegateOptions=function(){var d={};var e=this.getDefaults();this._options&&c.each(this._options,function(f,g){if(e[f]!=g){d[f]=g}});return d};b.prototype.enter=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="in";if(!d.options.delay||!d.options.delay.show){return d.show()}d.timeout=setTimeout(function(){if(d.hoverState=="in"){d.show()}},d.options.delay.show)};b.prototype.leave=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="out";if(!d.options.delay||!d.options.delay.hide){return d.hide()}d.timeout=setTimeout(function(){if(d.hoverState=="out"){d.hide()}},d.options.delay.hide)};b.prototype.show=function(){var n=c.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(n);if(n.isDefaultPrevented()){return}var j=this.tip();this.setContent();if(this.options.animation){j.addClass("fade")}var i=typeof this.options.placement=="function"?this.options.placement.call(this,j[0],this.$element[0]):this.options.placement;var r=/\s?auto?\s?/i;var s=r.test(i);if(s){i=i.replace(r,"")||"top"}j.detach().css({top:0,left:0,display:"block"}).addClass(i);this.options.container?j.appendTo(this.options.container):j.insertAfter(this.$element);var o=this.getPosition();var d=j[0].offsetWidth;var l=j[0].offsetHeight;if(s){var h=this.$element.parent();var g=i;var p=document.documentElement.scrollTop||document.body.scrollTop;var q=this.options.container=="body"?window.innerWidth:h.outerWidth();var m=this.options.container=="body"?window.innerHeight:h.outerHeight();var k=this.options.container=="body"?0:h.offset().left;i=i=="bottom"&&o.top+o.height+l-p>m?"top":i=="top"&&o.top-p-l<0?"bottom":i=="right"&&o.right+d>q?"left":i=="left"&&o.left-d<k?"right":i;j.removeClass(g).addClass(i)}var f=this.getCalculatedOffset(i,o,d,l);this.applyPlacement(f,i);this.$element.trigger("shown.bs."+this.type)}};b.prototype.applyPlacement=function(i,j){var g;var k=this.tip();var f=k[0].offsetWidth;var n=k[0].offsetHeight;var e=parseInt(k.css("margin-top"),10);var h=parseInt(k.css("margin-left"),10);if(isNaN(e)){e=0}if(isNaN(h)){h=0}i.top=i.top+e;i.left=i.left+h;k.offset(i).addClass("in");var d=k[0].offsetWidth;var l=k[0].offsetHeight;if(j=="top"&&l!=n){g=true;i.top=i.top+n-l}if(/bottom|top/.test(j)){var m=0;if(i.left<0){m=i.left*-2;i.left=0;k.offset(i);d=k[0].offsetWidth;l=k[0].offsetHeight}this.replaceArrow(m-f+d,d,"left")}else{this.replaceArrow(l-n,l,"top")}if(g){k.offset(i)}};b.prototype.replaceArrow=function(f,e,d){this.arrow().css(d,f?(50*(1-f/e)+"%"):"")};b.prototype.setContent=function(){var e=this.tip();var d=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](d);e.removeClass("fade in top bottom left right")};b.prototype.hide=function(){var f=this;var h=this.tip();var g=c.Event("hide.bs."+this.type);function d(){if(f.hoverState!="in"){h.detach()}}this.$element.trigger(g);if(g.isDefaultPrevented()){return}h.removeClass("in");c.support.transition&&this.$tip.hasClass("fade")?h.one(c.support.transition.end,d).emulateTransitionEnd(150):d();this.$element.trigger("hidden.bs."+this.type);return this};b.prototype.fixTitle=function(){var d=this.$element;if(d.attr("title")||typeof(d.attr("data-original-title"))!="string"){d.attr("data-original-title",d.attr("title")||"").attr("title","")}};b.prototype.hasContent=function(){return this.getTitle()};b.prototype.getPosition=function(){var d=this.$element[0];return c.extend({},(typeof d.getBoundingClientRect=="function")?d.getBoundingClientRect():{width:d.offsetWidth,height:d.offsetHeight},this.$element.offset())};b.prototype.getCalculatedOffset=function(d,g,e,f){return d=="bottom"?{top:g.top+g.height,left:g.left+g.width/2-e/2}:d=="top"?{top:g.top-f,left:g.left+g.width/2-e/2}:d=="left"?{top:g.top+g.height/2-f/2,left:g.left-e}:{top:g.top+g.height/2-f/2,left:g.left+g.width}};b.prototype.getTitle=function(){var f;var d=this.$element;var e=this.options;f=d.attr("data-original-title")||(typeof e.title=="function"?e.title.call(d[0]):e.title);return f};b.prototype.tip=function(){return this.$tip=this.$tip||c(this.options.template)};b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")};b.prototype.validate=function(){if(!this.$element[0].parentNode){this.hide();this.$element=null;this.options=null}};b.prototype.enable=function(){this.enabled=true};b.prototype.disable=function(){this.enabled=false};b.prototype.toggleEnabled=function(){this.enabled=!this.enabled};b.prototype.toggle=function(f){var d=f?c(f.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;d.tip().hasClass("in")?d.leave(d):d.enter(d)};b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var a=c.fn.tooltip;c.fn.tooltip=function(d){return this.each(function(){var g=c(this);var f=g.data("bs.tooltip");var e=typeof d=="object"&&d;if(!f){g.data("bs.tooltip",(f=new b(this,e)))}if(typeof d=="string"){f[d]()}})};c.fn.tooltip.Constructor=b;c.fn.tooltip.noConflict=function(){c.fn.tooltip=a;return this}}(window.jQuery);+function(g){var e=".dropdown-backdrop";var b="[data-toggle=dropdown]";var a=function(i){var h=g(i).on("click.bs.dropdown",this.toggle)};a.prototype.toggle=function(k){var j=g(this);if(j.is(".disabled, :disabled")){return}var i=f(j);var h=i.hasClass("open");d();if(!h){if("ontouchstart" in document.documentElement&&!i.closest(".navbar-nav").length){g('<div class="dropdown-backdrop"/>').insertAfter(g(this)).on("click",d)}i.trigger(k=g.Event("show.bs.dropdown"));if(k.isDefaultPrevented()){return}i.toggleClass("open").trigger("shown.bs.dropdown");j.focus()}return false};a.prototype.keydown=function(l){if(!/(38|40|27)/.test(l.keyCode)){return}var k=g(this);l.preventDefault();l.stopPropagation();if(k.is(".disabled, :disabled")){return}var j=f(k);var i=j.hasClass("open");if(!i||(i&&l.keyCode==27)){if(l.which==27){j.find(b).focus()}return k.click()}var m=g("[role=menu] li:not(.divider):visible a",j);if(!m.length){return}var h=m.index(m.filter(":focus"));if(l.keyCode==38&&h>0){h--}if(l.keyCode==40&&h<m.length-1){h++}if(!~h){h=0}m.eq(h).focus()};function d(){g(e).remove();g(b).each(function(i){var h=f(g(this));if(!h.hasClass("open")){return}h.trigger(i=g.Event("hide.bs.dropdown"));if(i.isDefaultPrevented()){return}h.removeClass("open").trigger("hidden.bs.dropdown")})}function f(j){var h=j.attr("data-target");if(!h){h=j.attr("href");h=h&&/#/.test(h)&&h.replace(/.*(?=#[^\s]*$)/,"")}var i=h&&g(h);return i&&i.length?i:j.parent()}var c=g.fn.dropdown;g.fn.dropdown=function(h){return this.each(function(){var j=g(this);var i=j.data("dropdown");if(!i){j.data("dropdown",(i=new a(this)))}if(typeof h=="string"){i[h].call(j)}})};g.fn.dropdown.Constructor=a;g.fn.dropdown.noConflict=function(){g.fn.dropdown=c;return this};g(document).on("click.bs.dropdown.data-api",d).on("click.bs.dropdown.data-api",".dropdown form",function(h){h.stopPropagation()}).on("click.bs.dropdown.data-api",b,a.prototype.toggle).on("keydown.bs.dropdown.data-api",b+", [role=menu]",a.prototype.keydown)}(window.jQuery);
\ No newline at end of file
++function(b){function a(){var e=document.createElement("bootstrap");var d={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in d){if(e.style[c]!==undefined){return{end:d[c]}}}}b.fn.emulateTransitionEnd=function(e){var d=false,c=this;b(this).one(b.support.transition.end,function(){d=true});var f=function(){if(!d){b(c).trigger(b.support.transition.end)}};setTimeout(f,e);return this};b(function(){b.support.transition=a()})}(window.jQuery);+function(c){var b=function(d){this.element=c(d)};b.prototype.show=function(){var j=this.element;var g=j.closest("ul:not(.dropdown-menu)");var f=j.attr("data-target");if(!f){f=j.attr("href");f=f&&f.replace(/.*(?=#[^\s]*$)/,"")}if(j.parent("li").hasClass("active")){return}var h=g.find(".active:last a")[0];var i=c.Event("show.bs.tab",{relatedTarget:h});j.trigger(i);if(i.isDefaultPrevented()){return}var d=c(f);this.activate(j.parent("li"),g);this.activate(d,d.parent(),function(){j.trigger({type:"shown.bs.tab",relatedTarget:h})})};b.prototype.activate=function(f,e,i){var d=e.find("> .active");var h=i&&c.support.transition&&d.hasClass("fade");function g(){d.removeClass("active").find("> .dropdown-menu > .active").removeClass("active");f.addClass("active");if(h){f[0].offsetWidth;f.addClass("in")}else{f.removeClass("fade")}if(f.parent(".dropdown-menu")){f.closest("li.dropdown").addClass("active")}i&&i()}h?d.one(c.support.transition.end,g).emulateTransitionEnd(150):g();d.removeClass("in")};var a=c.fn.tab;c.fn.tab=function(d){return this.each(function(){var f=c(this);var e=f.data("bs.tab");if(!e){f.data("bs.tab",(e=new b(this)))}if(typeof d=="string"){e[d]()}})};c.fn.tab.Constructor=b;c.fn.tab.noConflict=function(){c.fn.tab=a;return this};c(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(d){d.preventDefault();c(this).tab("show")})}(window.jQuery);+function(c){var b=function(e,d){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null;this.init("tooltip",e,d)};b.DEFAULTS={animation:true,placement:"top",selector:false,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:false,container:"body"};b.prototype.init=function(k,h,f){this.enabled=true;this.type=k;this.$element=c(h);this.options=this.getOptions(f);var j=this.options.trigger.split(" ");for(var g=j.length;g--;){var e=j[g];if(e=="click"){this.$element.on("click."+this.type,this.options.selector,c.proxy(this.toggle,this))}else{if(e!="manual"){var l=e=="hover"?"mouseenter":"focus";var d=e=="hover"?"mouseleave":"blur";this.$element.on(l+"."+this.type,this.options.selector,c.proxy(this.enter,this));this.$element.on(d+"."+this.type,this.options.selector,c.proxy(this.leave,this))}}}this.options.selector?(this._options=c.extend({},this.options,{trigger:"manual",selector:""})):this.fixTitle()};b.prototype.getDefaults=function(){return b.DEFAULTS};b.prototype.getOptions=function(d){d=c.extend({},this.getDefaults(),this.$element.data(),d);if(d.delay&&typeof d.delay=="number"){d.delay={show:d.delay,hide:d.delay}}return d};b.prototype.getDelegateOptions=function(){var d={};var e=this.getDefaults();this._options&&c.each(this._options,function(f,g){if(e[f]!=g){d[f]=g}});return d};b.prototype.enter=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="in";if(!d.options.delay||!d.options.delay.show){return d.show()}d.timeout=setTimeout(function(){if(d.hoverState=="in"){d.show()}},d.options.delay.show)};b.prototype.leave=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="out";if(!d.options.delay||!d.options.delay.hide){return d.hide()}d.timeout=setTimeout(function(){if(d.hoverState=="out"){d.hide()}},d.options.delay.hide)};b.prototype.show=function(){var n=c.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(n);if(n.isDefaultPrevented()){return}var j=this.tip();this.setContent();if(this.options.animation){j.addClass("fade")}var i=typeof this.options.placement=="function"?this.options.placement.call(this,j[0],this.$element[0]):this.options.placement;var r=/\s?auto?\s?/i;var s=r.test(i);if(s){i=i.replace(r,"")||"top"}j.detach().css({top:0,left:0,display:"block"}).addClass(i);this.options.container?j.appendTo(this.options.container):j.insertAfter(this.$element);var o=this.getPosition();var d=j[0].offsetWidth;var l=j[0].offsetHeight;if(s){var h=this.$element.parent();var g=i;var p=document.documentElement.scrollTop||document.body.scrollTop;var q=this.options.container=="body"?window.innerWidth:h.outerWidth();var m=this.options.container=="body"?window.innerHeight:h.outerHeight();var k=this.options.container=="body"?0:h.offset().left;i=i=="bottom"&&o.top+o.height+l-p>m?"top":i=="top"&&o.top-p-l<0?"bottom":i=="right"&&o.right+d>q?"left":i=="left"&&o.left-d<k?"right":i;j.removeClass(g).addClass(i)}var f=this.getCalculatedOffset(i,o,d,l);this.applyPlacement(f,i);this.$element.trigger("shown.bs."+this.type)}};b.prototype.applyPlacement=function(i,j){var g;var k=this.tip();var f=k[0].offsetWidth;var n=k[0].offsetHeight;var e=parseInt(k.css("margin-top"),10);var h=parseInt(k.css("margin-left"),10);if(isNaN(e)){e=0}if(isNaN(h)){h=0}i.top=i.top+e;i.left=i.left+h;k.offset(i).addClass("in");var d=k[0].offsetWidth;var l=k[0].offsetHeight;if(j=="top"&&l!=n){g=true;i.top=i.top+n-l}if(/bottom|top/.test(j)){var m=0;if(i.left<0){m=i.left*-2;i.left=0;k.offset(i);d=k[0].offsetWidth;l=k[0].offsetHeight}this.replaceArrow(m-f+d,d,"left")}else{this.replaceArrow(l-n,l,"top")}if(g){k.offset(i)}};b.prototype.replaceArrow=function(f,e,d){this.arrow().css(d,f?(50*(1-f/e)+"%"):"")};b.prototype.setContent=function(){var e=this.tip();var d=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](d);e.removeClass("fade in top bottom left right")};b.prototype.hide=function(){var f=this;var h=this.tip();var g=c.Event("hide.bs."+this.type);function d(){if(f.hoverState!="in"){h.detach()}}this.$element.trigger(g);if(g.isDefaultPrevented()){return}h.removeClass("in");c.support.transition&&this.$tip.hasClass("fade")?h.one(c.support.transition.end,d).emulateTransitionEnd(150):d();this.$element.trigger("hidden.bs."+this.type);return this};b.prototype.fixTitle=function(){var d=this.$element;if(d.attr("title")||typeof(d.attr("data-original-title"))!="string"){d.attr("data-original-title",d.attr("title")||"").attr("title","")}};b.prototype.hasContent=function(){return this.getTitle()};b.prototype.getPosition=function(){var d=this.$element[0];return c.extend({},(typeof d.getBoundingClientRect=="function")?d.getBoundingClientRect():{width:d.offsetWidth,height:d.offsetHeight},this.$element.offset())};b.prototype.getCalculatedOffset=function(d,g,e,f){return d=="bottom"?{top:g.top+g.height,left:g.left+g.width/2-e/2}:d=="top"?{top:g.top-f,left:g.left+g.width/2-e/2}:d=="left"?{top:g.top+g.height/2-f/2,left:g.left-e}:{top:g.top+g.height/2-f/2,left:g.left+g.width}};b.prototype.getTitle=function(){var f;var d=this.$element;var e=this.options;f=d.attr("data-original-title")||(typeof e.title=="function"?e.title.call(d[0]):e.title);return f};b.prototype.tip=function(){return this.$tip=this.$tip||c(this.options.template)};b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")};b.prototype.validate=function(){if(!this.$element[0].parentNode){this.hide();this.$element=null;this.options=null}};b.prototype.enable=function(){this.enabled=true};b.prototype.disable=function(){this.enabled=false};b.prototype.toggleEnabled=function(){this.enabled=!this.enabled};b.prototype.toggle=function(f){var d=f?c(f.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;d.tip().hasClass("in")?d.leave(d):d.enter(d)};b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var a=c.fn.tooltip;c.fn.tooltip=function(d){return this.each(function(){var g=c(this);var f=g.data("bs.tooltip");var e=typeof d=="object"&&d;if(!f){g.data("bs.tooltip",(f=new b(this,e)))}if(typeof d=="string"){f[d]()}})};c.fn.tooltip.Constructor=b;c.fn.tooltip.noConflict=function(){c.fn.tooltip=a;return this}}(window.jQuery);+function(g){var e=".dropdown-backdrop";var b="[data-toggle=dropdown]";var a=function(i){var h=g(i).on("click.bs.dropdown",this.toggle)};a.prototype.toggle=function(k){var j=g(this);if(j.is(".disabled, :disabled")){return}var i=f(j);var h=i.hasClass("open");d();if(!h){if("ontouchstart" in document.documentElement&&!i.closest(".navbar-nav").length){g('<div class="dropdown-backdrop"/>').insertAfter(g(this)).on("click",d)}i.trigger(k=g.Event("show.bs.dropdown"));if(k.isDefaultPrevented()){return}i.toggleClass("open").trigger("shown.bs.dropdown");j.focus()}return false};a.prototype.keydown=function(l){if(!/(38|40|27)/.test(l.keyCode)){return}var k=g(this);l.preventDefault();l.stopPropagation();if(k.is(".disabled, :disabled")){return}var j=f(k);var i=j.hasClass("open");if(!i||(i&&l.keyCode==27)){if(l.which==27){j.find(b).focus()}return k.click()}var m=g("[role=menu] li:not(.divider):visible a",j);if(!m.length){return}var h=m.index(m.filter(":focus"));if(l.keyCode==38&&h>0){h--}if(l.keyCode==40&&h<m.length-1){h++}if(!~h){h=0}m.eq(h).focus()};function d(){g(e).remove();g(b).each(function(i){var h=f(g(this));if(!h.hasClass("open")){return}h.trigger(i=g.Event("hide.bs.dropdown"));if(i.isDefaultPrevented()){return}h.removeClass("open").trigger("hidden.bs.dropdown")})}function f(j){var h=j.attr("data-target");if(!h){h=j.attr("href");h=h&&/#/.test(h)&&h.replace(/.*(?=#[^\s]*$)/,"")}var i=h&&g(h);return i&&i.length?i:j.parent()}var c=g.fn.dropdown;g.fn.dropdown=function(h){return this.each(function(){var j=g(this);var i=j.data("dropdown");if(!i){j.data("dropdown",(i=new a(this)))}if(typeof h=="string"){i[h].call(j)}})};g.fn.dropdown.Constructor=a;g.fn.dropdown.noConflict=function(){g.fn.dropdown=c;return this};g(document).on("click.bs.dropdown.data-api",d).on("click.bs.dropdown.data-api",".dropdown form",function(h){h.stopPropagation()}).on("click.bs.dropdown.data-api",b,a.prototype.toggle).on("keydown.bs.dropdown.data-api",b+", [role=menu]",a.prototype.keydown)}(window.jQuery);+function(c){var b=function(e,d){this.init("popover",e,d)};if(!c.fn.tooltip){throw new Error("Popover requires tooltip.js")}b.DEFAULTS=c.extend({},c.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'});b.prototype=c.extend({},c.fn.tooltip.Constructor.prototype);b.prototype.constructor=b;b.prototype.getDefaults=function(){return b.DEFAULTS};b.prototype.setContent=function(){var f=this.tip();var e=this.getTitle();var d=this.getContent();f.find(".popover-title")[this.options.html?"html":"text"](e);f.find(".popover-content")[this.options.html?"html":"text"](d);f.removeClass("fade top bottom left right in");if(!f.find(".popover-title").html()){f.find(".popover-title").hide()}};b.prototype.hasContent=function(){return this.getTitle()||this.getContent()};b.prototype.getContent=function(){var d=this.$element;var e=this.options;return d.attr("data-content")||(typeof e.content=="function"?e.content.call(d[0]):e.content)};b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};b.prototype.tip=function(){if(!this.$tip){this.$tip=c(this.options.template)}return this.$tip};var a=c.fn.popover;c.fn.popover=function(d){return this.each(function(){var g=c(this);var f=g.data("bs.popover");var e=typeof d=="object"&&d;if(!f){g.data("bs.popover",(f=new b(this,e)))}if(typeof d=="string"){f[d]()}})};c.fn.popover.Constructor=b;c.fn.popover.noConflict=function(){c.fn.popover=a;return this}}(jQuery);
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/302943e9dfdb/
Changeset: 302943e9dfdb
User: martenson
Date: 2014-01-14 00:04:48
Summary: galaxy top menu disabled items lighter grey….
Affected #: 2 files
diff -r d0904bfb2f43bca4847b1e3f59b4a57296390cb4 -r 302943e9dfdb8df93b0ade4dab1898963b0a3733 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -581,7 +581,7 @@
.navbar-inverse .navbar-text{color:#999}
.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}
.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#181a24}
-.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}
+.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#666;background-color:transparent}
.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}
.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}
.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#1e212d}
@@ -589,7 +589,7 @@
.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}
.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}
.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}
-@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent} .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}
+@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent} .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#666;background-color:transparent}}
.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}
.breadcrumb{padding:8px 15px;margin-bottom:17px;list-style:none;background-color:#f5f5f5;border-radius:3px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}
.breadcrumb>.active{color:#999}
diff -r d0904bfb2f43bca4847b1e3f59b4a57296390cb4 -r 302943e9dfdb8df93b0ade4dab1898963b0a3733 static/style/src/less/galaxy_bootstrap/variables.less
--- a/static/style/src/less/galaxy_bootstrap/variables.less
+++ b/static/style/src/less/galaxy_bootstrap/variables.less
@@ -344,7 +344,7 @@
@navbar-inverse-link-hover-bg: transparent;
@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;
@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);
-@navbar-inverse-link-disabled-color: #444;
+@navbar-inverse-link-disabled-color: #666;
@navbar-inverse-link-disabled-bg: transparent;
// Inverted navbar brand label
https://bitbucket.org/galaxy/galaxy-central/commits/e3d5546bfaab/
Changeset: e3d5546bfaab
User: martenson
Date: 2014-01-14 00:06:51
Summary: toaster removal form masthead
Affected #: 2 files
diff -r 302943e9dfdb8df93b0ade4dab1898963b0a3733 -r e3d5546bfaabc2d0a68e8044d3677b0bfb983831 static/scripts/galaxy.masthead.js
--- a/static/scripts/galaxy.masthead.js
+++ b/static/scripts/galaxy.masthead.js
@@ -3,7 +3,7 @@
*/
// dependencies
-define(["utils/galaxy.utils", "libs/toastr"], function(mod_utils, mod_toastr) {
+define(["utils/galaxy.utils"], function(mod_utils) {
// masthead
var GalaxyMasthead = Backbone.View.extend(
diff -r 302943e9dfdb8df93b0ade4dab1898963b0a3733 -r e3d5546bfaabc2d0a68e8044d3677b0bfb983831 static/scripts/packed/galaxy.masthead.js
--- a/static/scripts/packed/galaxy.masthead.js
+++ b/static/scripts/packed/galaxy.masthead.js
@@ -1,1 +1,1 @@
-define(["utils/galaxy.utils","libs/toastr"],function(c,e){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(g){this.options=g;$("body").off();this.setElement($(this._template(g)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var f=this;window.onbeforeunload=function(){var i="";for(key in f.list){if(f.list[key].options.on_unload){var h=f.list[key].options.on_unload();if(h){i+=h+" "}}}if(i!=""){return i}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(f){return this._add(f,true)},prepend:function(f){return this._add(f,false)},highlight:function(g){var f=$(this.el).find("#"+g+"> li");if(f){f.addClass("active")}},_add:function(i,g){var f=$(this.el).find("#"+i.location);if(f){var h=$(i.el);h.addClass("masthead-item");if(g){f.append(h)}else{f.prepend(h)}this.list.push(i)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(f){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+f.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+f.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(g){if(g){this.options=_.defaults(g,this.options)}this.setElement($(this._template(this.options)));var f=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",f.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(f){$(this.el).find(".icon").removeClass(this.options.icon).addClass(f);this.options.icon=f},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(f){$(this.el).find(".number").text(f)},_template:function(g){var f='<div id="'+g.id+'" class="symbol"><div class="icon fa fa-2x '+g.icon+'"></div>';if(g.with_number){f+='<div class="number"></div>'}f+="</div>";return f}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(f){if(f){this.options=_.defaults(f,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled");this._attachPopover()}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(h){var i={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(h){i=_.defaults(h,i)}if(i.content&&i.content.indexOf("//")===-1){i.content=galaxy_config.root+i.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var g=$(this._templateMenuItem(i));this.$menu.append(g);var f=this;g.on("click",function(j){j.preventDefault();if(f.options.target==="_blank"){return true}Galaxy.frame.add(h)});if(i.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){return}if(!this.$menu){Galaxy.frame.add(this.options)}},_attachPopover:function(){var f=$(this.el).find(".head");f.popover({html:true,content:'Please <a href="/user/login">log in</a> or <a href="/user/create">register</a> to use this feature.',placement:"bottom"}).on("shown.bs.popover",function(){setTimeout(function(){f.popover("hide")},5000)})},_templateMenuItem:function(f){return'<li><a href="'+f.content+'" target="'+f.target+'">'+f.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(g){var f='<ul id="'+g.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+g.target+'" href="'+g.content+'" title="'+g.title_attribute+'">'+g.title+'<b class="symbol"></b></a></li></ul>';return f}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
+define(["utils/galaxy.utils"],function(c){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(f){this.options=f;$("body").off();this.setElement($(this._template(f)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var e=this;window.onbeforeunload=function(){var h="";for(key in e.list){if(e.list[key].options.on_unload){var g=e.list[key].options.on_unload();if(g){h+=g+" "}}}if(h!=""){return h}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(e){return this._add(e,true)},prepend:function(e){return this._add(e,false)},highlight:function(f){var e=$(this.el).find("#"+f+"> li");if(e){e.addClass("active")}},_add:function(h,f){var e=$(this.el).find("#"+h.location);if(e){var g=$(h.el);g.addClass("masthead-item");if(f){e.append(g)}else{e.prepend(g)}this.list.push(h)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(e){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+e.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+e.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(f){if(f){this.options=_.defaults(f,this.options)}this.setElement($(this._template(this.options)));var e=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",e.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(e){$(this.el).find(".icon").removeClass(this.options.icon).addClass(e);this.options.icon=e},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(e){$(this.el).find(".number").text(e)},_template:function(f){var e='<div id="'+f.id+'" class="symbol"><div class="icon fa fa-2x '+f.icon+'"></div>';if(f.with_number){e+='<div class="number"></div>'}e+="</div>";return e}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(e){if(e){this.options=_.defaults(e,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled");this._attachPopover()}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(g){var h={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(g){h=_.defaults(g,h)}if(h.content&&h.content.indexOf("//")===-1){h.content=galaxy_config.root+h.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var f=$(this._templateMenuItem(h));this.$menu.append(f);var e=this;f.on("click",function(i){i.preventDefault();if(e.options.target==="_blank"){return true}Galaxy.frame.add(g)});if(h.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){return}if(!this.$menu){Galaxy.frame.add(this.options)}},_attachPopover:function(){var e=$(this.el).find(".head");e.popover({html:true,content:'Please <a href="/user/login">log in</a> or <a href="/user/create">register</a> to use this feature.',placement:"bottom"}).on("shown.bs.popover",function(){setTimeout(function(){e.popover("hide")},5000)})},_templateMenuItem:function(e){return'<li><a href="'+e.content+'" target="'+e.target+'">'+e.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(f){var e='<ul id="'+f.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+f.target+'" href="'+f.content+'" title="'+f.title_attribute+'">'+f.title+'<b class="symbol"></b></a></li></ul>';return e}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/28575f5bd33b/
Changeset: 28575f5bd33b
User: martenson
Date: 2014-01-14 19:36:06
Summary: Merged in martenson/galaxy-central-marten (pull request #293)
remove visualization and workflows menu items for anonymous users that can’t use them
Affected #: 9 files
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/scripts/galaxy.masthead.js
--- a/static/scripts/galaxy.masthead.js
+++ b/static/scripts/galaxy.masthead.js
@@ -259,7 +259,9 @@
type : 'url',
scratchbook : false,
on_unload : null,
- visible : true
+ visible : true,
+ disabled : false,
+ title_attribute : ''
},
// location
@@ -288,6 +290,13 @@
// add template for tab
this.setElement($(this._template(this.options)));
+ // disable menu items that are not available to anonymous user
+ // also show title to explain why they are disabled
+ if (this.options.disabled){
+ $(this.el).find('.root').addClass('disabled');
+ this._attachPopover();
+ }
+
// visiblity
if (!this.options.visible)
this.hide();
@@ -371,12 +380,30 @@
// prevent default
e.preventDefault();
+ if (this.options.disabled){
+ return // prevent link following if menu item is disabled
+ }
+
// check for menu options
if (!this.$menu) {
- Galaxy.frame.add(this.options);
+ Galaxy.frame.add(this.options);
}
},
-
+
+ _attachPopover : function()
+ {
+ var $popover_element = $(this.el).find('.head');
+ $popover_element.popover({
+ html: true,
+ content: 'Please <a href="/user/login">log in</a> or <a href="/user/create">register</a> to use this feature.',
+ placement: 'bottom'
+ }).on('shown.bs.popover', function() { // hooking on bootstrap event to automatically hide popovers after delay
+ setTimeout(function() {
+ $popover_element.popover('hide');
+ }, 5000);
+ });
+ },
+
// fill template header
_templateMenuItem: function (options)
{
@@ -400,7 +427,7 @@
// start template
var tmpl = '<ul id="' + options.id + '" class="nav navbar-nav" border="0" cellspacing="0">' +
'<li class="root dropdown" style="">' +
- '<a class="head dropdown-toggle" data-toggle="dropdown" target="' + options.target + '" href="' + options.content + '">' +
+ '<a class="head dropdown-toggle" data-toggle="dropdown" target="' + options.target + '" href="' + options.content + '" title="' + options.title_attribute + '">' +
options.title + '<b class="symbol"></b>' +
'</a>' +
'</li>' +
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/scripts/galaxy.menu.js
--- a/static/scripts/galaxy.menu.js
+++ b/static/scripts/galaxy.menu.js
@@ -31,19 +31,26 @@
var tab_analysis = new mod_masthead.GalaxyMastheadTab({
id : "analysis",
title : "Analyze Data",
- content : "root/index"
+ content : "root/index",
+ title_attribute : 'Analysis home view'
});
this.masthead.append(tab_analysis);
//
// Workflow tab.
//
- var tab_workflow = new mod_masthead.GalaxyMastheadTab({
+
+ var workflow_options = {
id : "workflow",
title : "Workflow",
- content : "workflow"
+ content : "workflow",
+ title_attribute : 'Chain tools into workflows'
+ }
+ if (!this.options.user.valid){
+ workflow_options.disabled = true; // disable workflows for anonymous users
+ }
- });
+ var tab_workflow = new mod_masthead.GalaxyMastheadTab(workflow_options);
this.masthead.append(tab_workflow);
//
@@ -52,7 +59,8 @@
var tab_shared = new mod_masthead.GalaxyMastheadTab({
id : "shared",
title : "Shared Data",
- content : "library/index"
+ content : "library/index",
+ title_attribute : 'Access published resources'
});
tab_shared.add({
@@ -61,7 +69,7 @@
});
tab_shared.add({
- title : "New Libraries",
+ title : "Data Libraries Beta",
content : "library/list",
divider : true
});
@@ -116,21 +124,32 @@
//
// Visualization tab.
//
- var tab_visualization = new mod_masthead.GalaxyMastheadTab({
+
+ var visualization_options = {
id : "visualization",
title : "Visualization",
- content : "visualization/list"
- });
- tab_visualization.add({
- title : "New Track Browser",
- content : "visualization/trackster",
- target : "_frame"
- });
- tab_visualization.add({
- title : "Saved Visualizations",
content : "visualization/list",
- target : "_frame"
- });
+ title_attribute : 'Visualize datasets'
+ }
+ if (!this.options.user.valid){
+ visualization_options.disabled = true; // disable visualizations for anonymous users
+ }
+
+ var tab_visualization = new mod_masthead.GalaxyMastheadTab(visualization_options);
+
+ if (this.options.user.valid) //add submenu only when user is logged in
+ {
+ tab_visualization.add({
+ title : "New Track Browser",
+ content : "visualization/trackster",
+ target : "_frame"
+ });
+ tab_visualization.add({
+ title : "Saved Visualizations",
+ content : "visualization/list",
+ target : "_frame"
+ });
+ }
this.masthead.append(tab_visualization);
//
@@ -159,7 +178,8 @@
id : "admin",
title : "Admin",
content : "admin/index",
- extra_class : "admin-only"
+ extra_class : "admin-only",
+ title_attribute : 'Administer this Galaxy'
});
this.masthead.append(tab_admin);
}
@@ -169,7 +189,8 @@
//
var tab_help = new mod_masthead.GalaxyMastheadTab({
id : "help",
- title : "Help"
+ title : "Help",
+ title_attribute : 'Support, contact, and community hubs'
});
if (this.options.biostar_url)
{
@@ -232,7 +253,8 @@
var tab_user = new mod_masthead.GalaxyMastheadTab({
id : "user",
title : "User",
- extra_class : "loggedout-only"
+ extra_class : "loggedout-only",
+ title_attribute : 'Account registration or login'
});
// login
@@ -258,7 +280,8 @@
var tab_user = new mod_masthead.GalaxyMastheadTab({
id : "user",
title : "User",
- extra_class : "loggedin-only"
+ extra_class : "loggedin-only",
+ title_attribute : 'Account preferences and saved data'
});
// show user logged in info
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/scripts/libs/bootstrap.js
--- a/static/scripts/libs/bootstrap.js
+++ b/static/scripts/libs/bootstrap.js
@@ -729,4 +729,122 @@
.on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
-}(window.jQuery);
\ No newline at end of file
+}(window.jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.0.3
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2013 Twitter, Inc.
+ *
+ * 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.
+ * ======================================================================== */
+
+
++function ($) { "use strict";
+
+ // POPOVER PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+ Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {
+ placement: 'right'
+ , trigger: 'click'
+ , content: ''
+ , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ })
+
+
+ // NOTE: POPOVER EXTENDS tooltip.js
+ // ================================
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+ Popover.prototype.constructor = Popover
+
+ Popover.prototype.getDefaults = function () {
+ return Popover.DEFAULTS
+ }
+
+ Popover.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+ var content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+ $tip.removeClass('fade top bottom left right in')
+
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+ // this manually by checking the contents.
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+ }
+
+ Popover.prototype.hasContent = function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ Popover.prototype.getContent = function () {
+ var $e = this.$element
+ var o = this.options
+
+ return $e.attr('data-content')
+ || (typeof o.content == 'function' ?
+ o.content.call($e[0]) :
+ o.content)
+ }
+
+ Popover.prototype.arrow = function () {
+ return this.$arrow = this.$arrow || this.tip().find('.arrow')
+ }
+
+ Popover.prototype.tip = function () {
+ if (!this.$tip) this.$tip = $(this.options.template)
+ return this.$tip
+ }
+
+
+ // POPOVER PLUGIN DEFINITION
+ // =========================
+
+ var old = $.fn.popover
+
+ $.fn.popover = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+
+ // POPOVER NO CONFLICT
+ // ===================
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(jQuery);
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/scripts/packed/galaxy.masthead.js
--- a/static/scripts/packed/galaxy.masthead.js
+++ b/static/scripts/packed/galaxy.masthead.js
@@ -1,1 +1,1 @@
-define(["utils/galaxy.utils"],function(c){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(f){this.options=f;$("body").off();this.setElement($(this._template(f)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var e=this;window.onbeforeunload=function(){var h="";for(key in e.list){if(e.list[key].options.on_unload){var g=e.list[key].options.on_unload();if(g){h+=g+" "}}}if(h!=""){return h}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(e){return this._add(e,true)},prepend:function(e){return this._add(e,false)},highlight:function(f){var e=$(this.el).find("#"+f+"> li");if(e){e.addClass("active")}},_add:function(h,f){var e=$(this.el).find("#"+h.location);if(e){var g=$(h.el);g.addClass("masthead-item");if(f){e.append(g)}else{e.prepend(g)}this.list.push(h)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(e){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+e.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+e.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(f){if(f){this.options=_.defaults(f,this.options)}this.setElement($(this._template(this.options)));var e=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",e.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(e){$(this.el).find(".icon").removeClass(this.options.icon).addClass(e);this.options.icon=e},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(e){$(this.el).find(".number").text(e)},_template:function(f){var e='<div id="'+f.id+'" class="symbol"><div class="icon fa fa-2x '+f.icon+'"></div>';if(f.with_number){e+='<div class="number"></div>'}e+="</div>";return e}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(e){if(e){this.options=_.defaults(e,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(g){var h={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(g){h=_.defaults(g,h)}if(h.content&&h.content.indexOf("//")===-1){h.content=galaxy_config.root+h.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var f=$(this._templateMenuItem(h));this.$menu.append(f);var e=this;f.on("click",function(i){i.preventDefault();if(e.options.target==="_blank"){return true}Galaxy.frame.add(g)});if(h.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(!this.$menu){Galaxy.frame.add(this.options)}},_templateMenuItem:function(e){return'<li><a href="'+e.content+'" target="'+e.target+'">'+e.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(f){var e='<ul id="'+f.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+f.target+'" href="'+f.content+'">'+f.title+'<b class="symbol"></b></a></li></ul>';return e}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
+define(["utils/galaxy.utils"],function(c){var a=Backbone.View.extend({el_masthead:"#everything",options:null,$background:null,list:[],initialize:function(f){this.options=f;$("body").off();this.setElement($(this._template(f)));$(this.el_masthead).append($(this.el));this.$background=$(this.el).find("#masthead-background");var e=this;window.onbeforeunload=function(){var h="";for(key in e.list){if(e.list[key].options.on_unload){var g=e.list[key].options.on_unload();if(g){h+=g+" "}}}if(h!=""){return h}}},events:{click:"_click",mousedown:function(f){f.preventDefault()}},append:function(e){return this._add(e,true)},prepend:function(e){return this._add(e,false)},highlight:function(f){var e=$(this.el).find("#"+f+"> li");if(e){e.addClass("active")}},_add:function(h,f){var e=$(this.el).find("#"+h.location);if(e){var g=$(h.el);g.addClass("masthead-item");if(f){e.append(g)}else{e.prepend(g)}this.list.push(h)}return null},_click:function(h){var g=$(this.el).find(".popup");if(g){g.hide()}var f=$(h.target).closest(".masthead-item").find(".popup");if($(h.target).hasClass("head")){f.show();this.$background.show()}else{this.$background.hide()}},_template:function(e){return'<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse"><div style="position: relative; right: -50%; float: left;"><div id="navbar" style="display: block; position: relative; right: 50%;"></div></div><div class="navbar-brand"><a href="'+e.logo_url+'"><img border="0" src="'+galaxy_config.root+'static/images/galaxyIcon_noText.png"><span id="brand"> Galaxy '+e.brand+'</span></a></div><div class="quota-meter-container"></div><div id="iconbar" class="iconbar"></div></div><div id="masthead-background" style="display: none; position: absolute; top: 33px; width: 100%; height: 100%; z-index: 1010"></div></div>'}});var b=Backbone.View.extend({options:{id:"",icon:"fa-cog",tooltip:"",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},location:"iconbar",initialize:function(f){if(f){this.options=_.defaults(f,this.options)}this.setElement($(this._template(this.options)));var e=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip,placement:"bottom"}).on("mouseup",e.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(e){$(this.el).find(".icon").removeClass(this.options.icon).addClass(e);this.options.icon=e},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(e){$(this.el).find(".number").text(e)},_template:function(f){var e='<div id="'+f.id+'" class="symbol"><div class="icon fa fa-2x '+f.icon+'"></div>';if(f.with_number){e+='<div class="number"></div>'}e+="</div>";return e}});var d=Backbone.View.extend({options:{id:"",title:"",target:"_parent",content:"",type:"url",scratchbook:false,on_unload:null,visible:true,disabled:false,title_attribute:""},location:"navbar",$menu:null,events:{"click .head":"_head"},initialize:function(e){if(e){this.options=_.defaults(e,this.options)}if(this.options.content&&this.options.content.indexOf("//")===-1){this.options.content=galaxy_config.root+this.options.content}this.setElement($(this._template(this.options)));if(this.options.disabled){$(this.el).find(".root").addClass("disabled");this._attachPopover()}if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},add:function(g){var h={title:"Title",content:"",type:"url",target:"_parent",scratchbook:false,divider:false};if(g){h=_.defaults(g,h)}if(h.content&&h.content.indexOf("//")===-1){h.content=galaxy_config.root+h.content}if(!this.$menu){$(this.el).find(".root").append(this._templateMenu());$(this.el).find(".symbol").addClass("caret");this.$menu=$(this.el).find(".popup")}var f=$(this._templateMenuItem(h));this.$menu.append(f);var e=this;f.on("click",function(i){i.preventDefault();if(e.options.target==="_blank"){return true}Galaxy.frame.add(g)});if(h.divider){this.$menu.append($(this._templateDivider()))}},_head:function(f){f.preventDefault();if(this.options.disabled){return}if(!this.$menu){Galaxy.frame.add(this.options)}},_attachPopover:function(){var e=$(this.el).find(".head");e.popover({html:true,content:'Please <a href="/user/login">log in</a> or <a href="/user/create">register</a> to use this feature.',placement:"bottom"}).on("shown.bs.popover",function(){setTimeout(function(){e.popover("hide")},5000)})},_templateMenuItem:function(e){return'<li><a href="'+e.content+'" target="'+e.target+'">'+e.title+"</a></li>"},_templateMenu:function(){return'<ul class="popup dropdown-menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(f){var e='<ul id="'+f.id+'" class="nav navbar-nav" border="0" cellspacing="0"><li class="root dropdown" style=""><a class="head dropdown-toggle" data-toggle="dropdown" target="'+f.target+'" href="'+f.content+'" title="'+f.title_attribute+'">'+f.title+'<b class="symbol"></b></a></li></ul>';return e}});return{GalaxyMasthead:a,GalaxyMastheadTab:d,GalaxyMastheadIcon:b}});
\ No newline at end of file
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/scripts/packed/galaxy.menu.js
--- a/static/scripts/packed/galaxy.menu.js
+++ b/static/scripts/packed/galaxy.menu.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var d=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index"});this.masthead.append(d);var c=new b.GalaxyMastheadTab({id:"workflow",title:"Workflow",content:"workflow"});this.masthead.append(c);var g=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index"});g.add({title:"Data Libraries",content:"library/index"});g.add({title:"New Libraries",content:"library/list",divider:true});g.add({title:"Published Histories",content:"history/list_published"});g.add({title:"Published Workflows",content:"workflow/list_published"});g.add({title:"Published Visualizations",content:"visualization/list_published"});g.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(g);if(this.options.user.requests){var h=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});h.add({title:"Sequencing Requests",content:"requests/index"});h.add({title:"Find Samples",content:"requests/find_samples_index"});h.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(h)}var k=new b.GalaxyMastheadTab({id:"visualization",title:"Visualization",content:"visualization/list"});k.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});k.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"});this.masthead.append(k);if(this.options.enable_cloud_launch){var e=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});e.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(e)}if(this.options.is_admin_user){var f=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only"});this.masthead.append(f)}var j=new b.GalaxyMastheadTab({id:"help",title:"Help"});if(this.options.biostar_url){j.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});j.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}j.add({title:"Support",content:this.options.support_url,target:"_blank"});j.add({title:"Search",content:this.options.search_url,target:"_blank"});j.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});j.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});j.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});j.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){j.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(j);if(!this.options.user.valid){var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only"});i.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){i.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(i)}else{var i=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only"});i.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){i.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{i.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});i.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});i.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}i.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});i.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});i.add({title:"Saved Pages",content:"page/list",target:"_top"});i.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){i.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(i)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
+define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var e=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index",title_attribute:"Analysis home view"});this.masthead.append(e);var g={id:"workflow",title:"Workflow",content:"workflow",title_attribute:"Chain tools into workflows"};if(!this.options.user.valid){g.disabled=true}var d=new b.GalaxyMastheadTab(g);this.masthead.append(d);var i=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index",title_attribute:"Access published resources"});i.add({title:"Data Libraries",content:"library/index"});i.add({title:"Data Libraries Beta",content:"library/list",divider:true});i.add({title:"Published Histories",content:"history/list_published"});i.add({title:"Published Workflows",content:"workflow/list_published"});i.add({title:"Published Visualizations",content:"visualization/list_published"});i.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(i);if(this.options.user.requests){var j=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});j.add({title:"Sequencing Requests",content:"requests/index"});j.add({title:"Find Samples",content:"requests/find_samples_index"});j.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(j)}var c={id:"visualization",title:"Visualization",content:"visualization/list",title_attribute:"Visualize datasets"};if(!this.options.user.valid){c.disabled=true}var m=new b.GalaxyMastheadTab(c);if(this.options.user.valid){m.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});m.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"})}this.masthead.append(m);if(this.options.enable_cloud_launch){var f=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});f.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(f)}if(this.options.is_admin_user){var h=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only",title_attribute:"Administer this Galaxy"});this.masthead.append(h)}var l=new b.GalaxyMastheadTab({id:"help",title:"Help",title_attribute:"Support, contact, and community hubs"});if(this.options.biostar_url){l.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});l.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}l.add({title:"Support",content:this.options.support_url,target:"_blank"});l.add({title:"Search",content:this.options.search_url,target:"_blank"});l.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});l.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});l.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});l.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(!this.options.terms_url){l.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(l);if(!this.options.user.valid){var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only",title_attribute:"Account registration or login"});k.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){k.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(k)}else{var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only",title_attribute:"Account preferences and saved data"});k.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){k.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{k.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});k.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});k.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}k.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});k.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});k.add({title:"Saved Pages",content:"page/list",target:"_top"});k.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){k.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(k)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/scripts/packed/libs/bootstrap.js
--- a/static/scripts/packed/libs/bootstrap.js
+++ b/static/scripts/packed/libs/bootstrap.js
@@ -1,1 +1,1 @@
-+function(b){function a(){var e=document.createElement("bootstrap");var d={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in d){if(e.style[c]!==undefined){return{end:d[c]}}}}b.fn.emulateTransitionEnd=function(e){var d=false,c=this;b(this).one(b.support.transition.end,function(){d=true});var f=function(){if(!d){b(c).trigger(b.support.transition.end)}};setTimeout(f,e);return this};b(function(){b.support.transition=a()})}(window.jQuery);+function(c){var b=function(d){this.element=c(d)};b.prototype.show=function(){var j=this.element;var g=j.closest("ul:not(.dropdown-menu)");var f=j.attr("data-target");if(!f){f=j.attr("href");f=f&&f.replace(/.*(?=#[^\s]*$)/,"")}if(j.parent("li").hasClass("active")){return}var h=g.find(".active:last a")[0];var i=c.Event("show.bs.tab",{relatedTarget:h});j.trigger(i);if(i.isDefaultPrevented()){return}var d=c(f);this.activate(j.parent("li"),g);this.activate(d,d.parent(),function(){j.trigger({type:"shown.bs.tab",relatedTarget:h})})};b.prototype.activate=function(f,e,i){var d=e.find("> .active");var h=i&&c.support.transition&&d.hasClass("fade");function g(){d.removeClass("active").find("> .dropdown-menu > .active").removeClass("active");f.addClass("active");if(h){f[0].offsetWidth;f.addClass("in")}else{f.removeClass("fade")}if(f.parent(".dropdown-menu")){f.closest("li.dropdown").addClass("active")}i&&i()}h?d.one(c.support.transition.end,g).emulateTransitionEnd(150):g();d.removeClass("in")};var a=c.fn.tab;c.fn.tab=function(d){return this.each(function(){var f=c(this);var e=f.data("bs.tab");if(!e){f.data("bs.tab",(e=new b(this)))}if(typeof d=="string"){e[d]()}})};c.fn.tab.Constructor=b;c.fn.tab.noConflict=function(){c.fn.tab=a;return this};c(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(d){d.preventDefault();c(this).tab("show")})}(window.jQuery);+function(c){var b=function(e,d){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null;this.init("tooltip",e,d)};b.DEFAULTS={animation:true,placement:"top",selector:false,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:false,container:"body"};b.prototype.init=function(k,h,f){this.enabled=true;this.type=k;this.$element=c(h);this.options=this.getOptions(f);var j=this.options.trigger.split(" ");for(var g=j.length;g--;){var e=j[g];if(e=="click"){this.$element.on("click."+this.type,this.options.selector,c.proxy(this.toggle,this))}else{if(e!="manual"){var l=e=="hover"?"mouseenter":"focus";var d=e=="hover"?"mouseleave":"blur";this.$element.on(l+"."+this.type,this.options.selector,c.proxy(this.enter,this));this.$element.on(d+"."+this.type,this.options.selector,c.proxy(this.leave,this))}}}this.options.selector?(this._options=c.extend({},this.options,{trigger:"manual",selector:""})):this.fixTitle()};b.prototype.getDefaults=function(){return b.DEFAULTS};b.prototype.getOptions=function(d){d=c.extend({},this.getDefaults(),this.$element.data(),d);if(d.delay&&typeof d.delay=="number"){d.delay={show:d.delay,hide:d.delay}}return d};b.prototype.getDelegateOptions=function(){var d={};var e=this.getDefaults();this._options&&c.each(this._options,function(f,g){if(e[f]!=g){d[f]=g}});return d};b.prototype.enter=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="in";if(!d.options.delay||!d.options.delay.show){return d.show()}d.timeout=setTimeout(function(){if(d.hoverState=="in"){d.show()}},d.options.delay.show)};b.prototype.leave=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="out";if(!d.options.delay||!d.options.delay.hide){return d.hide()}d.timeout=setTimeout(function(){if(d.hoverState=="out"){d.hide()}},d.options.delay.hide)};b.prototype.show=function(){var n=c.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(n);if(n.isDefaultPrevented()){return}var j=this.tip();this.setContent();if(this.options.animation){j.addClass("fade")}var i=typeof this.options.placement=="function"?this.options.placement.call(this,j[0],this.$element[0]):this.options.placement;var r=/\s?auto?\s?/i;var s=r.test(i);if(s){i=i.replace(r,"")||"top"}j.detach().css({top:0,left:0,display:"block"}).addClass(i);this.options.container?j.appendTo(this.options.container):j.insertAfter(this.$element);var o=this.getPosition();var d=j[0].offsetWidth;var l=j[0].offsetHeight;if(s){var h=this.$element.parent();var g=i;var p=document.documentElement.scrollTop||document.body.scrollTop;var q=this.options.container=="body"?window.innerWidth:h.outerWidth();var m=this.options.container=="body"?window.innerHeight:h.outerHeight();var k=this.options.container=="body"?0:h.offset().left;i=i=="bottom"&&o.top+o.height+l-p>m?"top":i=="top"&&o.top-p-l<0?"bottom":i=="right"&&o.right+d>q?"left":i=="left"&&o.left-d<k?"right":i;j.removeClass(g).addClass(i)}var f=this.getCalculatedOffset(i,o,d,l);this.applyPlacement(f,i);this.$element.trigger("shown.bs."+this.type)}};b.prototype.applyPlacement=function(i,j){var g;var k=this.tip();var f=k[0].offsetWidth;var n=k[0].offsetHeight;var e=parseInt(k.css("margin-top"),10);var h=parseInt(k.css("margin-left"),10);if(isNaN(e)){e=0}if(isNaN(h)){h=0}i.top=i.top+e;i.left=i.left+h;k.offset(i).addClass("in");var d=k[0].offsetWidth;var l=k[0].offsetHeight;if(j=="top"&&l!=n){g=true;i.top=i.top+n-l}if(/bottom|top/.test(j)){var m=0;if(i.left<0){m=i.left*-2;i.left=0;k.offset(i);d=k[0].offsetWidth;l=k[0].offsetHeight}this.replaceArrow(m-f+d,d,"left")}else{this.replaceArrow(l-n,l,"top")}if(g){k.offset(i)}};b.prototype.replaceArrow=function(f,e,d){this.arrow().css(d,f?(50*(1-f/e)+"%"):"")};b.prototype.setContent=function(){var e=this.tip();var d=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](d);e.removeClass("fade in top bottom left right")};b.prototype.hide=function(){var f=this;var h=this.tip();var g=c.Event("hide.bs."+this.type);function d(){if(f.hoverState!="in"){h.detach()}}this.$element.trigger(g);if(g.isDefaultPrevented()){return}h.removeClass("in");c.support.transition&&this.$tip.hasClass("fade")?h.one(c.support.transition.end,d).emulateTransitionEnd(150):d();this.$element.trigger("hidden.bs."+this.type);return this};b.prototype.fixTitle=function(){var d=this.$element;if(d.attr("title")||typeof(d.attr("data-original-title"))!="string"){d.attr("data-original-title",d.attr("title")||"").attr("title","")}};b.prototype.hasContent=function(){return this.getTitle()};b.prototype.getPosition=function(){var d=this.$element[0];return c.extend({},(typeof d.getBoundingClientRect=="function")?d.getBoundingClientRect():{width:d.offsetWidth,height:d.offsetHeight},this.$element.offset())};b.prototype.getCalculatedOffset=function(d,g,e,f){return d=="bottom"?{top:g.top+g.height,left:g.left+g.width/2-e/2}:d=="top"?{top:g.top-f,left:g.left+g.width/2-e/2}:d=="left"?{top:g.top+g.height/2-f/2,left:g.left-e}:{top:g.top+g.height/2-f/2,left:g.left+g.width}};b.prototype.getTitle=function(){var f;var d=this.$element;var e=this.options;f=d.attr("data-original-title")||(typeof e.title=="function"?e.title.call(d[0]):e.title);return f};b.prototype.tip=function(){return this.$tip=this.$tip||c(this.options.template)};b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")};b.prototype.validate=function(){if(!this.$element[0].parentNode){this.hide();this.$element=null;this.options=null}};b.prototype.enable=function(){this.enabled=true};b.prototype.disable=function(){this.enabled=false};b.prototype.toggleEnabled=function(){this.enabled=!this.enabled};b.prototype.toggle=function(f){var d=f?c(f.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;d.tip().hasClass("in")?d.leave(d):d.enter(d)};b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var a=c.fn.tooltip;c.fn.tooltip=function(d){return this.each(function(){var g=c(this);var f=g.data("bs.tooltip");var e=typeof d=="object"&&d;if(!f){g.data("bs.tooltip",(f=new b(this,e)))}if(typeof d=="string"){f[d]()}})};c.fn.tooltip.Constructor=b;c.fn.tooltip.noConflict=function(){c.fn.tooltip=a;return this}}(window.jQuery);+function(g){var e=".dropdown-backdrop";var b="[data-toggle=dropdown]";var a=function(i){var h=g(i).on("click.bs.dropdown",this.toggle)};a.prototype.toggle=function(k){var j=g(this);if(j.is(".disabled, :disabled")){return}var i=f(j);var h=i.hasClass("open");d();if(!h){if("ontouchstart" in document.documentElement&&!i.closest(".navbar-nav").length){g('<div class="dropdown-backdrop"/>').insertAfter(g(this)).on("click",d)}i.trigger(k=g.Event("show.bs.dropdown"));if(k.isDefaultPrevented()){return}i.toggleClass("open").trigger("shown.bs.dropdown");j.focus()}return false};a.prototype.keydown=function(l){if(!/(38|40|27)/.test(l.keyCode)){return}var k=g(this);l.preventDefault();l.stopPropagation();if(k.is(".disabled, :disabled")){return}var j=f(k);var i=j.hasClass("open");if(!i||(i&&l.keyCode==27)){if(l.which==27){j.find(b).focus()}return k.click()}var m=g("[role=menu] li:not(.divider):visible a",j);if(!m.length){return}var h=m.index(m.filter(":focus"));if(l.keyCode==38&&h>0){h--}if(l.keyCode==40&&h<m.length-1){h++}if(!~h){h=0}m.eq(h).focus()};function d(){g(e).remove();g(b).each(function(i){var h=f(g(this));if(!h.hasClass("open")){return}h.trigger(i=g.Event("hide.bs.dropdown"));if(i.isDefaultPrevented()){return}h.removeClass("open").trigger("hidden.bs.dropdown")})}function f(j){var h=j.attr("data-target");if(!h){h=j.attr("href");h=h&&/#/.test(h)&&h.replace(/.*(?=#[^\s]*$)/,"")}var i=h&&g(h);return i&&i.length?i:j.parent()}var c=g.fn.dropdown;g.fn.dropdown=function(h){return this.each(function(){var j=g(this);var i=j.data("dropdown");if(!i){j.data("dropdown",(i=new a(this)))}if(typeof h=="string"){i[h].call(j)}})};g.fn.dropdown.Constructor=a;g.fn.dropdown.noConflict=function(){g.fn.dropdown=c;return this};g(document).on("click.bs.dropdown.data-api",d).on("click.bs.dropdown.data-api",".dropdown form",function(h){h.stopPropagation()}).on("click.bs.dropdown.data-api",b,a.prototype.toggle).on("keydown.bs.dropdown.data-api",b+", [role=menu]",a.prototype.keydown)}(window.jQuery);
\ No newline at end of file
++function(b){function a(){var e=document.createElement("bootstrap");var d={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in d){if(e.style[c]!==undefined){return{end:d[c]}}}}b.fn.emulateTransitionEnd=function(e){var d=false,c=this;b(this).one(b.support.transition.end,function(){d=true});var f=function(){if(!d){b(c).trigger(b.support.transition.end)}};setTimeout(f,e);return this};b(function(){b.support.transition=a()})}(window.jQuery);+function(c){var b=function(d){this.element=c(d)};b.prototype.show=function(){var j=this.element;var g=j.closest("ul:not(.dropdown-menu)");var f=j.attr("data-target");if(!f){f=j.attr("href");f=f&&f.replace(/.*(?=#[^\s]*$)/,"")}if(j.parent("li").hasClass("active")){return}var h=g.find(".active:last a")[0];var i=c.Event("show.bs.tab",{relatedTarget:h});j.trigger(i);if(i.isDefaultPrevented()){return}var d=c(f);this.activate(j.parent("li"),g);this.activate(d,d.parent(),function(){j.trigger({type:"shown.bs.tab",relatedTarget:h})})};b.prototype.activate=function(f,e,i){var d=e.find("> .active");var h=i&&c.support.transition&&d.hasClass("fade");function g(){d.removeClass("active").find("> .dropdown-menu > .active").removeClass("active");f.addClass("active");if(h){f[0].offsetWidth;f.addClass("in")}else{f.removeClass("fade")}if(f.parent(".dropdown-menu")){f.closest("li.dropdown").addClass("active")}i&&i()}h?d.one(c.support.transition.end,g).emulateTransitionEnd(150):g();d.removeClass("in")};var a=c.fn.tab;c.fn.tab=function(d){return this.each(function(){var f=c(this);var e=f.data("bs.tab");if(!e){f.data("bs.tab",(e=new b(this)))}if(typeof d=="string"){e[d]()}})};c.fn.tab.Constructor=b;c.fn.tab.noConflict=function(){c.fn.tab=a;return this};c(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(d){d.preventDefault();c(this).tab("show")})}(window.jQuery);+function(c){var b=function(e,d){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null;this.init("tooltip",e,d)};b.DEFAULTS={animation:true,placement:"top",selector:false,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:false,container:"body"};b.prototype.init=function(k,h,f){this.enabled=true;this.type=k;this.$element=c(h);this.options=this.getOptions(f);var j=this.options.trigger.split(" ");for(var g=j.length;g--;){var e=j[g];if(e=="click"){this.$element.on("click."+this.type,this.options.selector,c.proxy(this.toggle,this))}else{if(e!="manual"){var l=e=="hover"?"mouseenter":"focus";var d=e=="hover"?"mouseleave":"blur";this.$element.on(l+"."+this.type,this.options.selector,c.proxy(this.enter,this));this.$element.on(d+"."+this.type,this.options.selector,c.proxy(this.leave,this))}}}this.options.selector?(this._options=c.extend({},this.options,{trigger:"manual",selector:""})):this.fixTitle()};b.prototype.getDefaults=function(){return b.DEFAULTS};b.prototype.getOptions=function(d){d=c.extend({},this.getDefaults(),this.$element.data(),d);if(d.delay&&typeof d.delay=="number"){d.delay={show:d.delay,hide:d.delay}}return d};b.prototype.getDelegateOptions=function(){var d={};var e=this.getDefaults();this._options&&c.each(this._options,function(f,g){if(e[f]!=g){d[f]=g}});return d};b.prototype.enter=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="in";if(!d.options.delay||!d.options.delay.show){return d.show()}d.timeout=setTimeout(function(){if(d.hoverState=="in"){d.show()}},d.options.delay.show)};b.prototype.leave=function(e){var d=e instanceof this.constructor?e:c(e.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(d.timeout);d.hoverState="out";if(!d.options.delay||!d.options.delay.hide){return d.hide()}d.timeout=setTimeout(function(){if(d.hoverState=="out"){d.hide()}},d.options.delay.hide)};b.prototype.show=function(){var n=c.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(n);if(n.isDefaultPrevented()){return}var j=this.tip();this.setContent();if(this.options.animation){j.addClass("fade")}var i=typeof this.options.placement=="function"?this.options.placement.call(this,j[0],this.$element[0]):this.options.placement;var r=/\s?auto?\s?/i;var s=r.test(i);if(s){i=i.replace(r,"")||"top"}j.detach().css({top:0,left:0,display:"block"}).addClass(i);this.options.container?j.appendTo(this.options.container):j.insertAfter(this.$element);var o=this.getPosition();var d=j[0].offsetWidth;var l=j[0].offsetHeight;if(s){var h=this.$element.parent();var g=i;var p=document.documentElement.scrollTop||document.body.scrollTop;var q=this.options.container=="body"?window.innerWidth:h.outerWidth();var m=this.options.container=="body"?window.innerHeight:h.outerHeight();var k=this.options.container=="body"?0:h.offset().left;i=i=="bottom"&&o.top+o.height+l-p>m?"top":i=="top"&&o.top-p-l<0?"bottom":i=="right"&&o.right+d>q?"left":i=="left"&&o.left-d<k?"right":i;j.removeClass(g).addClass(i)}var f=this.getCalculatedOffset(i,o,d,l);this.applyPlacement(f,i);this.$element.trigger("shown.bs."+this.type)}};b.prototype.applyPlacement=function(i,j){var g;var k=this.tip();var f=k[0].offsetWidth;var n=k[0].offsetHeight;var e=parseInt(k.css("margin-top"),10);var h=parseInt(k.css("margin-left"),10);if(isNaN(e)){e=0}if(isNaN(h)){h=0}i.top=i.top+e;i.left=i.left+h;k.offset(i).addClass("in");var d=k[0].offsetWidth;var l=k[0].offsetHeight;if(j=="top"&&l!=n){g=true;i.top=i.top+n-l}if(/bottom|top/.test(j)){var m=0;if(i.left<0){m=i.left*-2;i.left=0;k.offset(i);d=k[0].offsetWidth;l=k[0].offsetHeight}this.replaceArrow(m-f+d,d,"left")}else{this.replaceArrow(l-n,l,"top")}if(g){k.offset(i)}};b.prototype.replaceArrow=function(f,e,d){this.arrow().css(d,f?(50*(1-f/e)+"%"):"")};b.prototype.setContent=function(){var e=this.tip();var d=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](d);e.removeClass("fade in top bottom left right")};b.prototype.hide=function(){var f=this;var h=this.tip();var g=c.Event("hide.bs."+this.type);function d(){if(f.hoverState!="in"){h.detach()}}this.$element.trigger(g);if(g.isDefaultPrevented()){return}h.removeClass("in");c.support.transition&&this.$tip.hasClass("fade")?h.one(c.support.transition.end,d).emulateTransitionEnd(150):d();this.$element.trigger("hidden.bs."+this.type);return this};b.prototype.fixTitle=function(){var d=this.$element;if(d.attr("title")||typeof(d.attr("data-original-title"))!="string"){d.attr("data-original-title",d.attr("title")||"").attr("title","")}};b.prototype.hasContent=function(){return this.getTitle()};b.prototype.getPosition=function(){var d=this.$element[0];return c.extend({},(typeof d.getBoundingClientRect=="function")?d.getBoundingClientRect():{width:d.offsetWidth,height:d.offsetHeight},this.$element.offset())};b.prototype.getCalculatedOffset=function(d,g,e,f){return d=="bottom"?{top:g.top+g.height,left:g.left+g.width/2-e/2}:d=="top"?{top:g.top-f,left:g.left+g.width/2-e/2}:d=="left"?{top:g.top+g.height/2-f/2,left:g.left-e}:{top:g.top+g.height/2-f/2,left:g.left+g.width}};b.prototype.getTitle=function(){var f;var d=this.$element;var e=this.options;f=d.attr("data-original-title")||(typeof e.title=="function"?e.title.call(d[0]):e.title);return f};b.prototype.tip=function(){return this.$tip=this.$tip||c(this.options.template)};b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")};b.prototype.validate=function(){if(!this.$element[0].parentNode){this.hide();this.$element=null;this.options=null}};b.prototype.enable=function(){this.enabled=true};b.prototype.disable=function(){this.enabled=false};b.prototype.toggleEnabled=function(){this.enabled=!this.enabled};b.prototype.toggle=function(f){var d=f?c(f.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;d.tip().hasClass("in")?d.leave(d):d.enter(d)};b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var a=c.fn.tooltip;c.fn.tooltip=function(d){return this.each(function(){var g=c(this);var f=g.data("bs.tooltip");var e=typeof d=="object"&&d;if(!f){g.data("bs.tooltip",(f=new b(this,e)))}if(typeof d=="string"){f[d]()}})};c.fn.tooltip.Constructor=b;c.fn.tooltip.noConflict=function(){c.fn.tooltip=a;return this}}(window.jQuery);+function(g){var e=".dropdown-backdrop";var b="[data-toggle=dropdown]";var a=function(i){var h=g(i).on("click.bs.dropdown",this.toggle)};a.prototype.toggle=function(k){var j=g(this);if(j.is(".disabled, :disabled")){return}var i=f(j);var h=i.hasClass("open");d();if(!h){if("ontouchstart" in document.documentElement&&!i.closest(".navbar-nav").length){g('<div class="dropdown-backdrop"/>').insertAfter(g(this)).on("click",d)}i.trigger(k=g.Event("show.bs.dropdown"));if(k.isDefaultPrevented()){return}i.toggleClass("open").trigger("shown.bs.dropdown");j.focus()}return false};a.prototype.keydown=function(l){if(!/(38|40|27)/.test(l.keyCode)){return}var k=g(this);l.preventDefault();l.stopPropagation();if(k.is(".disabled, :disabled")){return}var j=f(k);var i=j.hasClass("open");if(!i||(i&&l.keyCode==27)){if(l.which==27){j.find(b).focus()}return k.click()}var m=g("[role=menu] li:not(.divider):visible a",j);if(!m.length){return}var h=m.index(m.filter(":focus"));if(l.keyCode==38&&h>0){h--}if(l.keyCode==40&&h<m.length-1){h++}if(!~h){h=0}m.eq(h).focus()};function d(){g(e).remove();g(b).each(function(i){var h=f(g(this));if(!h.hasClass("open")){return}h.trigger(i=g.Event("hide.bs.dropdown"));if(i.isDefaultPrevented()){return}h.removeClass("open").trigger("hidden.bs.dropdown")})}function f(j){var h=j.attr("data-target");if(!h){h=j.attr("href");h=h&&/#/.test(h)&&h.replace(/.*(?=#[^\s]*$)/,"")}var i=h&&g(h);return i&&i.length?i:j.parent()}var c=g.fn.dropdown;g.fn.dropdown=function(h){return this.each(function(){var j=g(this);var i=j.data("dropdown");if(!i){j.data("dropdown",(i=new a(this)))}if(typeof h=="string"){i[h].call(j)}})};g.fn.dropdown.Constructor=a;g.fn.dropdown.noConflict=function(){g.fn.dropdown=c;return this};g(document).on("click.bs.dropdown.data-api",d).on("click.bs.dropdown.data-api",".dropdown form",function(h){h.stopPropagation()}).on("click.bs.dropdown.data-api",b,a.prototype.toggle).on("keydown.bs.dropdown.data-api",b+", [role=menu]",a.prototype.keydown)}(window.jQuery);+function(c){var b=function(e,d){this.init("popover",e,d)};if(!c.fn.tooltip){throw new Error("Popover requires tooltip.js")}b.DEFAULTS=c.extend({},c.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'});b.prototype=c.extend({},c.fn.tooltip.Constructor.prototype);b.prototype.constructor=b;b.prototype.getDefaults=function(){return b.DEFAULTS};b.prototype.setContent=function(){var f=this.tip();var e=this.getTitle();var d=this.getContent();f.find(".popover-title")[this.options.html?"html":"text"](e);f.find(".popover-content")[this.options.html?"html":"text"](d);f.removeClass("fade top bottom left right in");if(!f.find(".popover-title").html()){f.find(".popover-title").hide()}};b.prototype.hasContent=function(){return this.getTitle()||this.getContent()};b.prototype.getContent=function(){var d=this.$element;var e=this.options;return d.attr("data-content")||(typeof e.content=="function"?e.content.call(d[0]):e.content)};b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};b.prototype.tip=function(){if(!this.$tip){this.$tip=c(this.options.template)}return this.$tip};var a=c.fn.popover;c.fn.popover=function(d){return this.each(function(){var g=c(this);var f=g.data("bs.popover");var e=typeof d=="object"&&d;if(!f){g.data("bs.popover",(f=new b(this,e)))}if(typeof d=="string"){f[d]()}})};c.fn.popover.Constructor=b;c.fn.popover.noConflict=function(){c.fn.popover=a;return this}}(jQuery);
\ No newline at end of file
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -581,7 +581,7 @@
.navbar-inverse .navbar-text{color:#999}
.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}
.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#181a24}
-.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}
+.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#666;background-color:transparent}
.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}
.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}
.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#1e212d}
@@ -589,7 +589,7 @@
.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}
.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}
.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}
-@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent} .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}
+@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent} .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#181a24} .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#666;background-color:transparent}}
.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}
.breadcrumb{padding:8px 15px;margin-bottom:17px;list-style:none;background-color:#f5f5f5;border-radius:3px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}
.breadcrumb>.active{color:#999}
@@ -1295,7 +1295,7 @@
.toast-title{font-weight:bold}
.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}
.toast-message a:hover{color:#ccc;text-decoration:none}
-.toast-close-button{position:relative;right:-0.3em;top:-0.3em;float:right;font-size:20px;font-weight:bold;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;filter:alpha(opacity=80);opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}.toast-close-button:hover,.toast-close-button:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=40);opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}
+.toast-close-button{position:relative;right:-0.3em;top:-0.3em;float:right;font-size:20px;font-weight:bold;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;filter:alpha(opacity=100);opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100)}.toast-close-button:hover,.toast-close-button:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=100);opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100)}
button.toast-close-button{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}
.toast-top-full-width{top:0;right:0;width:100%}
.toast-bottom-full-width{bottom:0;right:0;width:100%}
@@ -1304,7 +1304,7 @@
.toast-bottom-right{right:12px;bottom:12px}
.toast-bottom-left{bottom:12px;left:12px}
#toast-container{position:fixed;z-index:999999;}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
-#toast-container>div{margin:4em 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;filter:alpha(opacity=80);opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}
+#toast-container>div{margin:4em 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;filter:alpha(opacity=100);opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100)}
#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}
#toast-container>.toast-info{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important}
#toast-container>.toast-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important}
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/style/src/less/galaxy_bootstrap/variables.less
--- a/static/style/src/less/galaxy_bootstrap/variables.less
+++ b/static/style/src/less/galaxy_bootstrap/variables.less
@@ -344,7 +344,7 @@
@navbar-inverse-link-hover-bg: transparent;
@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;
@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);
-@navbar-inverse-link-disabled-color: #444;
+@navbar-inverse-link-disabled-color: #666;
@navbar-inverse-link-disabled-bg: transparent;
// Inverted navbar brand label
diff -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 -r 28575f5bd33b555cf594247f7706679df425085b static/style/src/less/toastr.less
--- a/static/style/src/less/toastr.less
+++ b/static/style/src/less/toastr.less
@@ -63,14 +63,14 @@
color: @white;
-webkit-text-shadow: 0 1px 0 rgba(255,255,255,1);
text-shadow: 0 1px 0 rgba(255,255,255,1);
- .opacity(0.8);
+ .opacity(1);
&:hover,
&:focus {
color: @black;
text-decoration: none;
cursor: pointer;
- .opacity(0.4);
+ .opacity(1);
}
}
@@ -138,7 +138,7 @@
background-repeat: no-repeat;
.boxShadow(0 0 12px @grey);
color: @white;
- .opacity(0.8);
+ .opacity(1);
}
> :hover {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: inithello: Log when each phase starts and finishes.
by commits-noreply@bitbucket.org 14 Jan '14
by commits-noreply@bitbucket.org 14 Jan '14
14 Jan '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8917614d21d0/
Changeset: 8917614d21d0
User: inithello
Date: 2014-01-14 18:45:33
Summary: Log when each phase starts and finishes.
Affected #: 1 file
diff -r 0b165ce6fac761a9e48cfa007d7e427c7f4b436c -r 8917614d21d03f4c4c3d83a1e00b302e568ea954 install_and_test_tool_shed_repositories.sh
--- a/install_and_test_tool_shed_repositories.sh
+++ b/install_and_test_tool_shed_repositories.sh
@@ -48,10 +48,12 @@
if [ -f /ToolDepsTest/stage_1_complete ] ; then
rm /ToolDepsTest/stage_1_complete
fi
+ echo "Starting stage 1, tool dependency definitions."
python test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py $* -v --with-nosehtml --html-report-file \
test/install_and_test_tool_shed_repositories/tool_dependency_definitions/run_functional_tests.html \
test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py \
test/functional/test_toolbox.py
+ echo "Stage 1 complete, exit code $?"
touch /ToolDepsTest/stage_1_complete
}
@@ -60,11 +62,13 @@
echo 'Stage 1 did not complete its run, exiting.'
exit 1
fi
+ echo "Starting stage 2, repositories with tools."
# Test installation of repositories that contain valid tools with defined functional tests and a test-data directory containing test files.
python test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py $* -v --with-nosehtml --html-report-file \
test/install_and_test_tool_shed_repositories/repositories_with_tools/run_functional_tests.html \
test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py \
test/functional/test_toolbox.py
+ echo "Stage 2 complete, exit code $?"
rm /ToolDepsTest/stage_1_complete
}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/97fd1b009c86/
Changeset: 97fd1b009c86
Branch: stable
User: natefoo
Date: 2014-01-14 17:31:11
Summary: Backed out changeset c40ecf876d68
Affected #: 4 files
diff -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e -r 97fd1b009c86ac992716ce6e81d45cb20c06a3c1 lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
--- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
+++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
@@ -262,7 +262,7 @@
no_tool_dependency_dir_message = "Tool dependencies can be automatically installed only if you set the value of your 'tool_dependency_dir' "
no_tool_dependency_dir_message += "setting in your Galaxy configuration file (universe_wsgi.ini) and restart your Galaxy server."
raise HTTPBadRequest( detail=no_tool_dependency_dir_message )
- new_tool_panel_section_label = payload.get( 'new_tool_panel_section_label', '' )
+ new_tool_panel_section = payload.get( 'new_tool_panel_section_label', '' )
shed_tool_conf = payload.get( 'shed_tool_conf', None )
if shed_tool_conf:
# Get the tool_path setting.
@@ -281,20 +281,15 @@
raise HTTPBadRequest( detail="Missing required parameter 'shed_tool_conf'." )
tool_panel_section_id = payload.get( 'tool_panel_section_id', '' )
if tool_panel_section_id not in [ None, '' ]:
- if tool_panel_section_id not in trans.app.toolbox.tool_panel:
- fixed_tool_panel_section_id = 'section_%s' % tool_panel_section_id
- if fixed_tool_panel_section_id in trans.app.toolbox.tool_panel:
- tool_panel_section_id = fixed_tool_panel_section_id
- else:
- tool_panel_section_id = ''
+ tool_panel_section = trans.app.toolbox.tool_panel[ tool_panel_section_id ]
else:
- tool_panel_section_id = ''
+ tool_panel_section = ''
# Build the dictionary of information necessary for creating tool_shed_repository database records for each repository being installed.
installation_dict = dict( install_repository_dependencies=install_repository_dependencies,
- new_tool_panel_section_label=new_tool_panel_section_label,
+ new_tool_panel_section=new_tool_panel_section,
no_changes_checked=False,
repo_info_dicts=repo_info_dicts,
- tool_panel_section_id=tool_panel_section_id,
+ tool_panel_section=tool_panel_section,
tool_path=tool_path,
tool_shed_url=tool_shed_url )
# Create the tool_shed_repository database records and gather additional information for repository installation.
@@ -311,18 +306,17 @@
install_repository_dependencies=install_repository_dependencies,
install_tool_dependencies=install_tool_dependencies,
message='',
- new_tool_panel_section_label=new_tool_panel_section_label,
+ new_tool_panel_section=new_tool_panel_section,
shed_tool_conf=shed_tool_conf,
status='done',
- tool_panel_section_id=tool_panel_section_id,
+ tool_panel_section=tool_panel_section,
tool_panel_section_keys=tool_panel_section_keys,
tool_path=tool_path,
tool_shed_url=tool_shed_url )
# Prepare the repositories for installation. Even though this method receives a single combination of tool_shed_url, name, owner and
# changeset_revision, there may be multiple repositories for installation at this point because repository dependencies may have added
# additional repositories for installation along with the single specified repository.
- encoded_kwd, query, tool_shed_repositories, encoded_repository_ids = \
- repository_util.initiate_repository_installation( trans, installation_dict )
+ encoded_kwd, query, tool_shed_repositories, encoded_repository_ids = repository_util.initiate_repository_installation( trans, installation_dict )
# Some repositories may have repository dependencies that are required to be installed before the dependent repository, so we'll
# order the list of tsr_ids to ensure all repositories install in the required order.
tsr_ids = [ trans.security.encode_id( tool_shed_repository.id ) for tool_shed_repository in tool_shed_repositories ]
diff -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e -r 97fd1b009c86ac992716ce6e81d45cb20c06a3c1 lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -244,10 +244,9 @@
tool_panel_section_id = section_dict[ 'id' ]
tool_panel_section_name = section_dict[ 'name' ]
if tool_panel_section_id:
- tool_panel_section_key, tool_panel_section = \
- tool_util.get_or_create_tool_section( trans,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section_label=tool_panel_section_name )
+ tool_panel_section_key, tool_panel_section = tool_util.get_or_create_tool_section( trans,
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section=tool_panel_section_name )
else:
tool_dependencies = None
repo_info_dict = create_repo_info_dict( trans=trans,
@@ -433,10 +432,10 @@
def handle_tool_shed_repositories( trans, installation_dict, using_api=False ):
# The following installation_dict entries are all required.
install_repository_dependencies = installation_dict[ 'install_repository_dependencies' ]
- new_tool_panel_section_label = installation_dict[ 'new_tool_panel_section_label' ]
+ new_tool_panel_section = installation_dict[ 'new_tool_panel_section' ]
no_changes_checked = installation_dict[ 'no_changes_checked' ]
repo_info_dicts = installation_dict[ 'repo_info_dicts' ]
- tool_panel_section_id = installation_dict[ 'tool_panel_section_id' ]
+ tool_panel_section = installation_dict[ 'tool_panel_section' ]
tool_path = installation_dict[ 'tool_path' ]
tool_shed_url = installation_dict[ 'tool_shed_url' ]
created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts = \
@@ -446,8 +445,8 @@
repo_info_dicts=repo_info_dicts,
install_repository_dependencies=install_repository_dependencies,
no_changes_checked=no_changes_checked,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
+ tool_panel_section=tool_panel_section,
+ new_tool_panel_section=new_tool_panel_section )
return created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts
def initiate_repository_installation( trans, installation_dict ):
@@ -461,19 +460,18 @@
install_repository_dependencies = installation_dict[ 'install_repository_dependencies' ]
install_tool_dependencies = installation_dict[ 'install_tool_dependencies' ]
message = installation_dict[ 'message' ]
- new_tool_panel_section_label = installation_dict[ 'new_tool_panel_section_label' ]
+ new_tool_panel_section = installation_dict[ 'new_tool_panel_section' ]
shed_tool_conf = installation_dict[ 'shed_tool_conf' ]
status = installation_dict[ 'status' ]
- tool_panel_section_id = installation_dict[ 'tool_panel_section_id' ]
+ tool_panel_section = installation_dict[ 'tool_panel_section' ]
tool_panel_section_keys = installation_dict[ 'tool_panel_section_keys' ]
tool_path = installation_dict[ 'tool_path' ]
tool_shed_url = installation_dict[ 'tool_shed_url' ]
# Handle contained tools.
- if includes_tools_for_display_in_tool_panel and ( new_tool_panel_section_label or tool_panel_section_id ):
- tool_panel_section_key, tool_section = \
- tool_util.handle_tool_panel_section( trans,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
+ if includes_tools_for_display_in_tool_panel and ( new_tool_panel_section or tool_panel_section ):
+ tool_panel_section_key, tool_section = tool_util.handle_tool_panel_section( trans,
+ tool_panel_section=tool_panel_section,
+ new_tool_panel_section=new_tool_panel_section )
else:
tool_panel_section_key = None
tool_section = None
@@ -671,19 +669,16 @@
def order_components_for_installation( trans, tsr_ids, repo_info_dicts, tool_panel_section_keys ):
"""
- Some repositories may have repository dependencies that are required to be installed before the dependent repository.
- This method will inspect the list of repositories about to be installed and make sure to order them appropriately.
- For each repository about to be installed, if required repositories are not contained in the list of repositories about
- to be installed, then they are not considered. Repository dependency definitions that contain circular dependencies
- should not result in an infinite loop, but obviously prior installation will not be handled for one or more of the
- repositories that require prior installation.
+ Some repositories may have repository dependencies that are required to be installed before the dependent repository. This method will inspect the list of
+ repositories about to be installed and make sure to order them appropriately. For each repository about to be installed, if required repositories are not
+ contained in the list of repositories about to be installed, then they are not considered. Repository dependency definitions that contain circular dependencies
+ should not result in an infinite loop, but obviously prior installation will not be handled for one or more of the repositories that require prior installation.
"""
ordered_tsr_ids = []
ordered_repo_info_dicts = []
ordered_tool_panel_section_keys = []
- # Create a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is
- # contained in the received list of tsr_ids and whose associated repository must be installed prior to the repository
- # associated with the tsr_id key.
+ # Create a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained in the received list of tsr_ids
+ # and whose associated repository must be installed prior to the repository associated with the tsr_id key.
prior_install_required_dict = suc.get_prior_import_or_install_required_dict( trans, tsr_ids, repo_info_dicts )
processed_tsr_ids = []
while len( processed_tsr_ids ) != len( prior_install_required_dict.keys() ):
@@ -695,19 +690,17 @@
for prior_install_required_id in prior_install_required_ids:
if prior_install_required_id not in ordered_tsr_ids:
# Install the associated repository dependency first.
- prior_repo_info_dict, prior_tool_panel_section_key = \
- get_repository_components_for_installation( prior_install_required_id,
- tsr_ids,
- repo_info_dicts,
- tool_panel_section_keys=tool_panel_section_keys )
+ prior_repo_info_dict, prior_tool_panel_section_key = get_repository_components_for_installation( prior_install_required_id,
+ tsr_ids,
+ repo_info_dicts,
+ tool_panel_section_keys=tool_panel_section_keys )
ordered_tsr_ids.append( prior_install_required_id )
ordered_repo_info_dicts.append( prior_repo_info_dict )
ordered_tool_panel_section_keys.append( prior_tool_panel_section_key )
- repo_info_dict, tool_panel_section_key = \
- get_repository_components_for_installation( tsr_id,
- tsr_ids,
- repo_info_dicts,
- tool_panel_section_keys=tool_panel_section_keys )
+ repo_info_dict, tool_panel_section_key = get_repository_components_for_installation( tsr_id,
+ tsr_ids,
+ repo_info_dicts,
+ tool_panel_section_keys=tool_panel_section_keys )
ordered_tsr_ids.append( tsr_id )
ordered_repo_info_dicts.append( repo_info_dict )
ordered_tool_panel_section_keys.append( tool_panel_section_key )
@@ -772,12 +765,11 @@
shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, repository )
# Reset the repository attributes to the New state for installation.
if metadata:
- tool_section, tool_panel_section_key = \
- tool_util.handle_tool_panel_selection( trans,
- metadata,
- no_changes_checked=True,
- tool_panel_section_id=None,
- new_tool_panel_section_label=None )
+ tool_section, new_tool_panel_section, tool_panel_section_key = tool_util.handle_tool_panel_selection( trans,
+ metadata,
+ no_changes_checked=True,
+ tool_panel_section=None,
+ new_tool_panel_section=None )
else:
# The tools will be loaded outside of any sections in the tool panel.
tool_panel_section_key = None
diff -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e -r 97fd1b009c86ac992716ce6e81d45cb20c06a3c1 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -96,7 +96,7 @@
return True
def create_repository_dependency_objects( trans, tool_path, tool_shed_url, repo_info_dicts, install_repository_dependencies=False,
- no_changes_checked=False, tool_panel_section_id=None, new_tool_panel_section_label=None ):
+ no_changes_checked=False, tool_panel_section=None, new_tool_panel_section=None ):
"""
Discover all repository dependencies and make sure all tool_shed_repository and associated repository_dependency records exist as well as
the dependency relationships between installed repositories. This method is called when uninstalled repositories are being reinstalled.
@@ -174,30 +174,28 @@
# The database record for the tool shed repository currently being processed can be updated. Get the repository metadata
# to see where it was previously located in the tool panel.
if repository_db_record and repository_db_record.metadata:
- tool_section, tool_panel_section_key = \
+ tool_section, new_tool_panel_section, tool_panel_section_key = \
tool_util.handle_tool_panel_selection( trans=trans,
metadata=repository_db_record.metadata,
no_changes_checked=no_changes_checked,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
+ tool_panel_section=tool_panel_section,
+ new_tool_panel_section=new_tool_panel_section )
else:
# We're installing a new tool shed repository that does not yet have a database record.
- tool_panel_section_key, tool_section = \
- tool_util.handle_tool_panel_section( trans,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
- tool_shed_repository = \
- suc.create_or_update_tool_shed_repository( app=trans.app,
- name=name,
- description=description,
- installed_changeset_revision=changeset_revision,
- ctx_rev=ctx_rev,
- repository_clone_url=repository_clone_url,
- metadata_dict={},
- status=trans.model.ToolShedRepository.installation_status.NEW,
- current_changeset_revision=changeset_revision,
- owner=repository_owner,
- dist_to_shed=False )
+ tool_panel_section_key, tool_section = tool_util.handle_tool_panel_section( trans,
+ tool_panel_section=tool_panel_section,
+ new_tool_panel_section=new_tool_panel_section )
+ tool_shed_repository = suc.create_or_update_tool_shed_repository( app=trans.app,
+ name=name,
+ description=description,
+ installed_changeset_revision=changeset_revision,
+ ctx_rev=ctx_rev,
+ repository_clone_url=repository_clone_url,
+ metadata_dict={},
+ status=trans.model.ToolShedRepository.installation_status.NEW,
+ current_changeset_revision=changeset_revision,
+ owner=repository_owner,
+ dist_to_shed=False )
if tool_shed_repository not in all_created_or_updated_tool_shed_repositories:
all_created_or_updated_tool_shed_repositories.append( tool_shed_repository )
# Only append the tool shed repository to the list of created_or_updated_tool_shed_repositories if it is supposed to be installed.
@@ -461,10 +459,9 @@
common_util.parse_repository_dependency_tuple( repository_dependency )
if suc.tool_shed_is_this_tool_shed( toolshed ):
required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
- required_repository_metadata = \
- metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
- trans.security.encode_id( required_repository.id ),
- changeset_revision )
+ required_repository_metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
+ trans.security.encode_id( required_repository.id ),
+ changeset_revision )
if required_repository_metadata:
# The required_repository_metadata changeset_revision is installable.
required_metadata = required_repository_metadata.metadata
diff -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e -r 97fd1b009c86ac992716ce6e81d45cb20c06a3c1 lib/tool_shed/util/tool_util.py
--- a/lib/tool_shed/util/tool_util.py
+++ b/lib/tool_shed/util/tool_util.py
@@ -108,7 +108,7 @@
for k, v in trans.app.toolbox.tool_panel.items():
if isinstance( v, galaxy.tools.ToolSection ):
options.append( ( v.name, v.id ) )
- select_field = SelectField( name='tool_panel_section_id', display='radio' )
+ select_field = SelectField( name='tool_panel_section', display='radio' )
for option_tup in options:
select_field.add_option( option_tup[ 0 ], option_tup[ 1 ] )
return select_field
@@ -461,28 +461,29 @@
fh.close()
return sample_files, deleted_sample_files
-def get_or_create_tool_section( trans, tool_panel_section_id, new_tool_panel_section_label=None ):
- if tool_panel_section_id.startswith( 'section_' ):
- tool_panel_section_key = tool_panel_section_id
- tool_panel_section_id.lstrip( 'section_' )
- else:
- tool_panel_section_key = 'section_%s' % str( tool_panel_section_id )
+def get_or_create_tool_section( trans, tool_panel_section_id, new_tool_panel_section=None ):
+ tool_panel_section_key = 'section_%s' % str( tool_panel_section_id )
if tool_panel_section_key in trans.app.toolbox.tool_panel:
# Appending a tool to an existing section in trans.app.toolbox.tool_panel
tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
log.debug( "Appending to tool panel section: %s" % str( tool_section.name ) )
else:
# Appending a new section to trans.app.toolbox.tool_panel
- if new_tool_panel_section_label is None:
- # This might add an ugly section label to the tool panel, but, oh well...
- new_tool_panel_section_label = tool_panel_section_id
- elem = XmlET.Element( 'section' )
- elem.attrib[ 'name' ] = new_tool_panel_section_label
- elem.attrib[ 'id' ] = tool_panel_section_id
- elem.attrib[ 'version' ] = ''
- tool_section = galaxy.tools.ToolSection( elem )
- trans.app.toolbox.tool_panel[ tool_panel_section_key ] = tool_section
- log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) )
+ try:
+ new_tool_panel_section_name = new_tool_panel_section.name
+ except:
+ new_tool_panel_section_name = new_tool_panel_section
+ if new_tool_panel_section_name:
+ elem = XmlET.Element( 'section' )
+ elem.attrib[ 'name' ] = new_tool_panel_section_name
+ elem.attrib[ 'id' ] = tool_panel_section_id
+ elem.attrib[ 'version' ] = ''
+ tool_section = galaxy.tools.ToolSection( elem )
+ trans.app.toolbox.tool_panel[ tool_panel_section_key ] = tool_section
+ log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) )
+ else:
+ log.debug( "Unable to create new tool pane section using received new_tool_panel_section: %s" % str( new_tool_panel_section ))
+ return None, None
return tool_panel_section_key, tool_section
def get_tool_path_install_dir( partial_install_dir, shed_tool_conf_dict, tool_dict, config_elems ):
@@ -632,20 +633,16 @@
error = True
return error, message
-def handle_tool_panel_selection( trans, metadata, no_changes_checked, tool_panel_section_id, new_tool_panel_section_label ):
- """
- Handle the selected tool panel location for loading tools included in tool shed repositories when installing
- or reinstalling them.
- """
+def handle_tool_panel_selection( trans, metadata, no_changes_checked, tool_panel_section, new_tool_panel_section ):
+ """Handle the selected tool panel location for loading tools included in tool shed repositories when installing or reinstalling them."""
# Get the location in the tool panel in which each tool was originally loaded.
tool_section = None
tool_panel_section_key = None
if 'tools' in metadata:
# This forces everything to be loaded into the same section (or no section) in the tool panel.
if no_changes_checked:
- # Make sure the no_changes check box overrides the new_tool_panel_section_label if the user checked the check
- # box and entered something into the field.
- new_tool_panel_section_label = None
+ # Make sure the no_changes check box overrides the new_tool_panel_section if the user checked the check box and entered something into the field.
+ new_tool_panel_section = None
if 'tool_panel_section' in metadata:
tool_panel_dict = metadata[ 'tool_panel_section' ]
if not tool_panel_dict:
@@ -659,33 +656,24 @@
original_section_id = tool_section_dict[ 'id' ]
original_section_name = tool_section_dict[ 'name' ]
if original_section_id:
- tool_panel_section_key, tool_section = \
- get_or_create_tool_section( trans,
- tool_panel_section_id=original_section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
+ tool_panel_section_key, tool_section = get_or_create_tool_section( trans,
+ tool_panel_section_id=original_section_id,
+ new_tool_panel_section=new_tool_panel_section )
else:
# The user elected to change the tool panel section to contain the tools.
tool_panel_section_key, tool_section = handle_tool_panel_section( trans,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
- return tool_section, tool_panel_section_key
+ tool_panel_section=tool_panel_section,
+ new_tool_panel_section=new_tool_panel_section )
+ return tool_section, new_tool_panel_section, tool_panel_section_key
-def handle_tool_panel_section( trans, tool_panel_section_id=None, new_tool_panel_section_label=None ):
- """Return a ToolSection object retrieved from the current in-memory tool_panel."""
- # If tool_panel_section_id is received, the section exists in the tool panel. In this case, the value of the
- # received tool_panel_section_id must be the id retrieved from a tool panel config (e.g., tool_conf.xml, which
- # may have getext). If new_tool_panel_section_label is received, a new section will be added to the tool panel.
- if new_tool_panel_section_label:
- section_id = 'section_%s' % str( new_tool_panel_section_label.lower().replace( ' ', '_' ) )
- tool_panel_section_key, tool_section = \
- get_or_create_tool_section( trans,
- tool_panel_section_id=section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
- elif tool_panel_section_id:
- if tool_panel_section_id.startswith( 'section_' ):
- tool_panel_section_key = str( tool_panel_section_id )
- else:
- tool_panel_section_key = 'section_%s' % str( tool_panel_section_id )
+def handle_tool_panel_section( trans, tool_panel_section=None, new_tool_panel_section=None ):
+ if new_tool_panel_section:
+ section_id = new_tool_panel_section.lower().replace( ' ', '_' )
+ tool_panel_section_key, tool_section = get_or_create_tool_section( trans,
+ tool_panel_section_id=section_id,
+ new_tool_panel_section=new_tool_panel_section )
+ elif tool_panel_section:
+ tool_panel_section_key = 'section_%s' % str( tool_panel_section )
tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
else:
return None, None
https://bitbucket.org/galaxy/galaxy-central/commits/0b165ce6fac7/
Changeset: 0b165ce6fac7
User: natefoo
Date: 2014-01-14 17:40:40
Summary: Merge backout from stable.
Affected #: 4 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Visualizations Registry: allow config to contain a visualization description
by commits-noreply@bitbucket.org 14 Jan '14
by commits-noreply@bitbucket.org 14 Jan '14
14 Jan '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cf003cc0101b/
Changeset: cf003cc0101b
User: carlfeberhard
Date: 2014-01-14 17:25:20
Summary: Visualizations Registry: allow config to contain a visualization description
Affected #: 2 files
diff -r 0c20fa551dd90a9d8101bf4f2a8cac3793b9663b -r cf003cc0101b1b07acf8bec871b0e7740ef6b39f config/plugins/visualizations/visualization.dtd
--- a/config/plugins/visualizations/visualization.dtd
+++ b/config/plugins/visualizations/visualization.dtd
@@ -1,10 +1,17 @@
<!-- each visualization must have a template (all other elements are optional) -->
-<!ELEMENT visualization (data_sources*,params*,template_root*,template,link_text*,render_location*)>
-<!-- visualization name (e.g. 'trackster', 'scatterplot', etc.) is required -->
+<!ELEMENT visualization (description*,data_sources*,params*,template_root*,template,link_text*,render_location*)>
+<!-- visualization
+ name: some name for the visualization (e.g. 'trackster', 'scatterplot', etc.) REQUIRED
+ disabled: if included (value does not matter), this attribute will prevent the visualization being loaded
+--><!ATTLIST visualization
name CDATA #REQUIRED
+ disabled CDATA #IMPLIED
>
+<!ELEMENT description (#PCDATA)>
+<!-- a text description of what the visualization does -->
+
<!ELEMENT data_sources (data_source*)><!-- data sources are elements that describe what objects (HDAs, LDDAs, Job, User, etc.)
are applicable to a visualization. Often these are used to fetch applicable links
diff -r 0c20fa551dd90a9d8101bf4f2a8cac3793b9663b -r cf003cc0101b1b07acf8bec871b0e7740ef6b39f lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -397,6 +397,10 @@
if 'disabled' in xml_tree.attrib:
return None
+ # a (for now) text description of what the visualization does
+ description = xml_tree.find( 'description' )
+ returned[ 'description' ] = description.text.strip() if description is not None else None
+
# data_sources are the kinds of objects/data associated with the visualization
# e.g. views on HDAs can use this to find out what visualizations are applicable to them
data_sources = []
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Visualizations Registry: allow disabling via config file
by commits-noreply@bitbucket.org 14 Jan '14
by commits-noreply@bitbucket.org 14 Jan '14
14 Jan '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0c20fa551dd9/
Changeset: 0c20fa551dd9
User: carlfeberhard
Date: 2014-01-14 16:55:22
Summary: Visualizations Registry: allow disabling via config file
Affected #: 3 files
diff -r c5c57ec1af3ca407ce64e52093173be90a2047b7 -r 0c20fa551dd90a9d8101bf4f2a8cac3793b9663b config/plugins/visualizations/sweepster/config/sweepster.xml
--- a/config/plugins/visualizations/sweepster/config/sweepster.xml
+++ b/config/plugins/visualizations/sweepster/config/sweepster.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE visualization SYSTEM "../../visualization.dtd">
-<visualization name="sweepster">
+<visualization name="sweepster" disabled="true"><data_sources><data_source><model_class>HistoryDatasetAssociation</model_class>
diff -r c5c57ec1af3ca407ce64e52093173be90a2047b7 -r 0c20fa551dd90a9d8101bf4f2a8cac3793b9663b lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -375,7 +375,7 @@
def parse_file( self, xml_filepath ):
"""
Parse the given XML file for visualizations data.
- :returns: tuple of ( `visualization_name`, `visualization` )
+ :returns: visualization config dictionary
"""
try:
xml_tree = galaxy.util.parse_xml( xml_filepath )
@@ -393,6 +393,10 @@
"""
returned = {}
+ # allow manually turning off a vis by checking for a disabled property
+ if 'disabled' in xml_tree.attrib:
+ return None
+
# data_sources are the kinds of objects/data associated with the visualization
# e.g. views on HDAs can use this to find out what visualizations are applicable to them
data_sources = []
diff -r c5c57ec1af3ca407ce64e52093173be90a2047b7 -r 0c20fa551dd90a9d8101bf4f2a8cac3793b9663b lib/galaxy/web/base/pluginframework.py
--- a/lib/galaxy/web/base/pluginframework.py
+++ b/lib/galaxy/web/base/pluginframework.py
@@ -119,7 +119,7 @@
try:
plugin = self.load_plugin( plugin_path )
if not plugin:
- log.warn( '%s, plugin load failed: %s. Skipping...', self, plugin_path )
+ log.warn( '%s, plugin load failed or disabled: %s. Skipping...', self, plugin_path )
#NOTE: prevent silent, implicit overwrite here (two plugins in two diff directories)
#TODO: overwriting may be desired
elif plugin.name in self.plugins:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c40ecf876d68/
Changeset: c40ecf876d68
Branch: stable
User: inithello
Date: 2014-01-14 16:29:33
Summary: Backport fix for selecting a tool panel section when installing a repository using the API.
Affected #: 4 files
diff -r d96d5309b5c52bb43c410c7a943808294bee12c0 -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
--- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
+++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
@@ -262,7 +262,7 @@
no_tool_dependency_dir_message = "Tool dependencies can be automatically installed only if you set the value of your 'tool_dependency_dir' "
no_tool_dependency_dir_message += "setting in your Galaxy configuration file (universe_wsgi.ini) and restart your Galaxy server."
raise HTTPBadRequest( detail=no_tool_dependency_dir_message )
- new_tool_panel_section = payload.get( 'new_tool_panel_section_label', '' )
+ new_tool_panel_section_label = payload.get( 'new_tool_panel_section_label', '' )
shed_tool_conf = payload.get( 'shed_tool_conf', None )
if shed_tool_conf:
# Get the tool_path setting.
@@ -281,15 +281,20 @@
raise HTTPBadRequest( detail="Missing required parameter 'shed_tool_conf'." )
tool_panel_section_id = payload.get( 'tool_panel_section_id', '' )
if tool_panel_section_id not in [ None, '' ]:
- tool_panel_section = trans.app.toolbox.tool_panel[ tool_panel_section_id ]
+ if tool_panel_section_id not in trans.app.toolbox.tool_panel:
+ fixed_tool_panel_section_id = 'section_%s' % tool_panel_section_id
+ if fixed_tool_panel_section_id in trans.app.toolbox.tool_panel:
+ tool_panel_section_id = fixed_tool_panel_section_id
+ else:
+ tool_panel_section_id = ''
else:
- tool_panel_section = ''
+ tool_panel_section_id = ''
# Build the dictionary of information necessary for creating tool_shed_repository database records for each repository being installed.
installation_dict = dict( install_repository_dependencies=install_repository_dependencies,
- new_tool_panel_section=new_tool_panel_section,
+ new_tool_panel_section_label=new_tool_panel_section_label,
no_changes_checked=False,
repo_info_dicts=repo_info_dicts,
- tool_panel_section=tool_panel_section,
+ tool_panel_section_id=tool_panel_section_id,
tool_path=tool_path,
tool_shed_url=tool_shed_url )
# Create the tool_shed_repository database records and gather additional information for repository installation.
@@ -306,17 +311,18 @@
install_repository_dependencies=install_repository_dependencies,
install_tool_dependencies=install_tool_dependencies,
message='',
- new_tool_panel_section=new_tool_panel_section,
+ new_tool_panel_section_label=new_tool_panel_section_label,
shed_tool_conf=shed_tool_conf,
status='done',
- tool_panel_section=tool_panel_section,
+ tool_panel_section_id=tool_panel_section_id,
tool_panel_section_keys=tool_panel_section_keys,
tool_path=tool_path,
tool_shed_url=tool_shed_url )
# Prepare the repositories for installation. Even though this method receives a single combination of tool_shed_url, name, owner and
# changeset_revision, there may be multiple repositories for installation at this point because repository dependencies may have added
# additional repositories for installation along with the single specified repository.
- encoded_kwd, query, tool_shed_repositories, encoded_repository_ids = repository_util.initiate_repository_installation( trans, installation_dict )
+ encoded_kwd, query, tool_shed_repositories, encoded_repository_ids = \
+ repository_util.initiate_repository_installation( trans, installation_dict )
# Some repositories may have repository dependencies that are required to be installed before the dependent repository, so we'll
# order the list of tsr_ids to ensure all repositories install in the required order.
tsr_ids = [ trans.security.encode_id( tool_shed_repository.id ) for tool_shed_repository in tool_shed_repositories ]
diff -r d96d5309b5c52bb43c410c7a943808294bee12c0 -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -244,9 +244,10 @@
tool_panel_section_id = section_dict[ 'id' ]
tool_panel_section_name = section_dict[ 'name' ]
if tool_panel_section_id:
- tool_panel_section_key, tool_panel_section = tool_util.get_or_create_tool_section( trans,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section=tool_panel_section_name )
+ tool_panel_section_key, tool_panel_section = \
+ tool_util.get_or_create_tool_section( trans,
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section_label=tool_panel_section_name )
else:
tool_dependencies = None
repo_info_dict = create_repo_info_dict( trans=trans,
@@ -432,10 +433,10 @@
def handle_tool_shed_repositories( trans, installation_dict, using_api=False ):
# The following installation_dict entries are all required.
install_repository_dependencies = installation_dict[ 'install_repository_dependencies' ]
- new_tool_panel_section = installation_dict[ 'new_tool_panel_section' ]
+ new_tool_panel_section_label = installation_dict[ 'new_tool_panel_section_label' ]
no_changes_checked = installation_dict[ 'no_changes_checked' ]
repo_info_dicts = installation_dict[ 'repo_info_dicts' ]
- tool_panel_section = installation_dict[ 'tool_panel_section' ]
+ tool_panel_section_id = installation_dict[ 'tool_panel_section_id' ]
tool_path = installation_dict[ 'tool_path' ]
tool_shed_url = installation_dict[ 'tool_shed_url' ]
created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts = \
@@ -445,8 +446,8 @@
repo_info_dicts=repo_info_dicts,
install_repository_dependencies=install_repository_dependencies,
no_changes_checked=no_changes_checked,
- tool_panel_section=tool_panel_section,
- new_tool_panel_section=new_tool_panel_section )
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
return created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts
def initiate_repository_installation( trans, installation_dict ):
@@ -460,18 +461,19 @@
install_repository_dependencies = installation_dict[ 'install_repository_dependencies' ]
install_tool_dependencies = installation_dict[ 'install_tool_dependencies' ]
message = installation_dict[ 'message' ]
- new_tool_panel_section = installation_dict[ 'new_tool_panel_section' ]
+ new_tool_panel_section_label = installation_dict[ 'new_tool_panel_section_label' ]
shed_tool_conf = installation_dict[ 'shed_tool_conf' ]
status = installation_dict[ 'status' ]
- tool_panel_section = installation_dict[ 'tool_panel_section' ]
+ tool_panel_section_id = installation_dict[ 'tool_panel_section_id' ]
tool_panel_section_keys = installation_dict[ 'tool_panel_section_keys' ]
tool_path = installation_dict[ 'tool_path' ]
tool_shed_url = installation_dict[ 'tool_shed_url' ]
# Handle contained tools.
- if includes_tools_for_display_in_tool_panel and ( new_tool_panel_section or tool_panel_section ):
- tool_panel_section_key, tool_section = tool_util.handle_tool_panel_section( trans,
- tool_panel_section=tool_panel_section,
- new_tool_panel_section=new_tool_panel_section )
+ if includes_tools_for_display_in_tool_panel and ( new_tool_panel_section_label or tool_panel_section_id ):
+ tool_panel_section_key, tool_section = \
+ tool_util.handle_tool_panel_section( trans,
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
else:
tool_panel_section_key = None
tool_section = None
@@ -669,16 +671,19 @@
def order_components_for_installation( trans, tsr_ids, repo_info_dicts, tool_panel_section_keys ):
"""
- Some repositories may have repository dependencies that are required to be installed before the dependent repository. This method will inspect the list of
- repositories about to be installed and make sure to order them appropriately. For each repository about to be installed, if required repositories are not
- contained in the list of repositories about to be installed, then they are not considered. Repository dependency definitions that contain circular dependencies
- should not result in an infinite loop, but obviously prior installation will not be handled for one or more of the repositories that require prior installation.
+ Some repositories may have repository dependencies that are required to be installed before the dependent repository.
+ This method will inspect the list of repositories about to be installed and make sure to order them appropriately.
+ For each repository about to be installed, if required repositories are not contained in the list of repositories about
+ to be installed, then they are not considered. Repository dependency definitions that contain circular dependencies
+ should not result in an infinite loop, but obviously prior installation will not be handled for one or more of the
+ repositories that require prior installation.
"""
ordered_tsr_ids = []
ordered_repo_info_dicts = []
ordered_tool_panel_section_keys = []
- # Create a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained in the received list of tsr_ids
- # and whose associated repository must be installed prior to the repository associated with the tsr_id key.
+ # Create a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is
+ # contained in the received list of tsr_ids and whose associated repository must be installed prior to the repository
+ # associated with the tsr_id key.
prior_install_required_dict = suc.get_prior_import_or_install_required_dict( trans, tsr_ids, repo_info_dicts )
processed_tsr_ids = []
while len( processed_tsr_ids ) != len( prior_install_required_dict.keys() ):
@@ -690,17 +695,19 @@
for prior_install_required_id in prior_install_required_ids:
if prior_install_required_id not in ordered_tsr_ids:
# Install the associated repository dependency first.
- prior_repo_info_dict, prior_tool_panel_section_key = get_repository_components_for_installation( prior_install_required_id,
- tsr_ids,
- repo_info_dicts,
- tool_panel_section_keys=tool_panel_section_keys )
+ prior_repo_info_dict, prior_tool_panel_section_key = \
+ get_repository_components_for_installation( prior_install_required_id,
+ tsr_ids,
+ repo_info_dicts,
+ tool_panel_section_keys=tool_panel_section_keys )
ordered_tsr_ids.append( prior_install_required_id )
ordered_repo_info_dicts.append( prior_repo_info_dict )
ordered_tool_panel_section_keys.append( prior_tool_panel_section_key )
- repo_info_dict, tool_panel_section_key = get_repository_components_for_installation( tsr_id,
- tsr_ids,
- repo_info_dicts,
- tool_panel_section_keys=tool_panel_section_keys )
+ repo_info_dict, tool_panel_section_key = \
+ get_repository_components_for_installation( tsr_id,
+ tsr_ids,
+ repo_info_dicts,
+ tool_panel_section_keys=tool_panel_section_keys )
ordered_tsr_ids.append( tsr_id )
ordered_repo_info_dicts.append( repo_info_dict )
ordered_tool_panel_section_keys.append( tool_panel_section_key )
@@ -765,11 +772,12 @@
shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, repository )
# Reset the repository attributes to the New state for installation.
if metadata:
- tool_section, new_tool_panel_section, tool_panel_section_key = tool_util.handle_tool_panel_selection( trans,
- metadata,
- no_changes_checked=True,
- tool_panel_section=None,
- new_tool_panel_section=None )
+ tool_section, tool_panel_section_key = \
+ tool_util.handle_tool_panel_selection( trans,
+ metadata,
+ no_changes_checked=True,
+ tool_panel_section_id=None,
+ new_tool_panel_section_label=None )
else:
# The tools will be loaded outside of any sections in the tool panel.
tool_panel_section_key = None
diff -r d96d5309b5c52bb43c410c7a943808294bee12c0 -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -96,7 +96,7 @@
return True
def create_repository_dependency_objects( trans, tool_path, tool_shed_url, repo_info_dicts, install_repository_dependencies=False,
- no_changes_checked=False, tool_panel_section=None, new_tool_panel_section=None ):
+ no_changes_checked=False, tool_panel_section_id=None, new_tool_panel_section_label=None ):
"""
Discover all repository dependencies and make sure all tool_shed_repository and associated repository_dependency records exist as well as
the dependency relationships between installed repositories. This method is called when uninstalled repositories are being reinstalled.
@@ -174,28 +174,30 @@
# The database record for the tool shed repository currently being processed can be updated. Get the repository metadata
# to see where it was previously located in the tool panel.
if repository_db_record and repository_db_record.metadata:
- tool_section, new_tool_panel_section, tool_panel_section_key = \
+ tool_section, tool_panel_section_key = \
tool_util.handle_tool_panel_selection( trans=trans,
metadata=repository_db_record.metadata,
no_changes_checked=no_changes_checked,
- tool_panel_section=tool_panel_section,
- new_tool_panel_section=new_tool_panel_section )
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
else:
# We're installing a new tool shed repository that does not yet have a database record.
- tool_panel_section_key, tool_section = tool_util.handle_tool_panel_section( trans,
- tool_panel_section=tool_panel_section,
- new_tool_panel_section=new_tool_panel_section )
- tool_shed_repository = suc.create_or_update_tool_shed_repository( app=trans.app,
- name=name,
- description=description,
- installed_changeset_revision=changeset_revision,
- ctx_rev=ctx_rev,
- repository_clone_url=repository_clone_url,
- metadata_dict={},
- status=trans.model.ToolShedRepository.installation_status.NEW,
- current_changeset_revision=changeset_revision,
- owner=repository_owner,
- dist_to_shed=False )
+ tool_panel_section_key, tool_section = \
+ tool_util.handle_tool_panel_section( trans,
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
+ tool_shed_repository = \
+ suc.create_or_update_tool_shed_repository( app=trans.app,
+ name=name,
+ description=description,
+ installed_changeset_revision=changeset_revision,
+ ctx_rev=ctx_rev,
+ repository_clone_url=repository_clone_url,
+ metadata_dict={},
+ status=trans.model.ToolShedRepository.installation_status.NEW,
+ current_changeset_revision=changeset_revision,
+ owner=repository_owner,
+ dist_to_shed=False )
if tool_shed_repository not in all_created_or_updated_tool_shed_repositories:
all_created_or_updated_tool_shed_repositories.append( tool_shed_repository )
# Only append the tool shed repository to the list of created_or_updated_tool_shed_repositories if it is supposed to be installed.
@@ -459,9 +461,10 @@
common_util.parse_repository_dependency_tuple( repository_dependency )
if suc.tool_shed_is_this_tool_shed( toolshed ):
required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
- required_repository_metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
- trans.security.encode_id( required_repository.id ),
- changeset_revision )
+ required_repository_metadata = \
+ metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
+ trans.security.encode_id( required_repository.id ),
+ changeset_revision )
if required_repository_metadata:
# The required_repository_metadata changeset_revision is installable.
required_metadata = required_repository_metadata.metadata
diff -r d96d5309b5c52bb43c410c7a943808294bee12c0 -r c40ecf876d68ed86ac874f9b8c4b4d0fcb9bc69e lib/tool_shed/util/tool_util.py
--- a/lib/tool_shed/util/tool_util.py
+++ b/lib/tool_shed/util/tool_util.py
@@ -108,7 +108,7 @@
for k, v in trans.app.toolbox.tool_panel.items():
if isinstance( v, galaxy.tools.ToolSection ):
options.append( ( v.name, v.id ) )
- select_field = SelectField( name='tool_panel_section', display='radio' )
+ select_field = SelectField( name='tool_panel_section_id', display='radio' )
for option_tup in options:
select_field.add_option( option_tup[ 0 ], option_tup[ 1 ] )
return select_field
@@ -461,29 +461,28 @@
fh.close()
return sample_files, deleted_sample_files
-def get_or_create_tool_section( trans, tool_panel_section_id, new_tool_panel_section=None ):
- tool_panel_section_key = 'section_%s' % str( tool_panel_section_id )
+def get_or_create_tool_section( trans, tool_panel_section_id, new_tool_panel_section_label=None ):
+ if tool_panel_section_id.startswith( 'section_' ):
+ tool_panel_section_key = tool_panel_section_id
+ tool_panel_section_id.lstrip( 'section_' )
+ else:
+ tool_panel_section_key = 'section_%s' % str( tool_panel_section_id )
if tool_panel_section_key in trans.app.toolbox.tool_panel:
# Appending a tool to an existing section in trans.app.toolbox.tool_panel
tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
log.debug( "Appending to tool panel section: %s" % str( tool_section.name ) )
else:
# Appending a new section to trans.app.toolbox.tool_panel
- try:
- new_tool_panel_section_name = new_tool_panel_section.name
- except:
- new_tool_panel_section_name = new_tool_panel_section
- if new_tool_panel_section_name:
- elem = XmlET.Element( 'section' )
- elem.attrib[ 'name' ] = new_tool_panel_section_name
- elem.attrib[ 'id' ] = tool_panel_section_id
- elem.attrib[ 'version' ] = ''
- tool_section = galaxy.tools.ToolSection( elem )
- trans.app.toolbox.tool_panel[ tool_panel_section_key ] = tool_section
- log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) )
- else:
- log.debug( "Unable to create new tool pane section using received new_tool_panel_section: %s" % str( new_tool_panel_section ))
- return None, None
+ if new_tool_panel_section_label is None:
+ # This might add an ugly section label to the tool panel, but, oh well...
+ new_tool_panel_section_label = tool_panel_section_id
+ elem = XmlET.Element( 'section' )
+ elem.attrib[ 'name' ] = new_tool_panel_section_label
+ elem.attrib[ 'id' ] = tool_panel_section_id
+ elem.attrib[ 'version' ] = ''
+ tool_section = galaxy.tools.ToolSection( elem )
+ trans.app.toolbox.tool_panel[ tool_panel_section_key ] = tool_section
+ log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) )
return tool_panel_section_key, tool_section
def get_tool_path_install_dir( partial_install_dir, shed_tool_conf_dict, tool_dict, config_elems ):
@@ -633,16 +632,20 @@
error = True
return error, message
-def handle_tool_panel_selection( trans, metadata, no_changes_checked, tool_panel_section, new_tool_panel_section ):
- """Handle the selected tool panel location for loading tools included in tool shed repositories when installing or reinstalling them."""
+def handle_tool_panel_selection( trans, metadata, no_changes_checked, tool_panel_section_id, new_tool_panel_section_label ):
+ """
+ Handle the selected tool panel location for loading tools included in tool shed repositories when installing
+ or reinstalling them.
+ """
# Get the location in the tool panel in which each tool was originally loaded.
tool_section = None
tool_panel_section_key = None
if 'tools' in metadata:
# This forces everything to be loaded into the same section (or no section) in the tool panel.
if no_changes_checked:
- # Make sure the no_changes check box overrides the new_tool_panel_section if the user checked the check box and entered something into the field.
- new_tool_panel_section = None
+ # Make sure the no_changes check box overrides the new_tool_panel_section_label if the user checked the check
+ # box and entered something into the field.
+ new_tool_panel_section_label = None
if 'tool_panel_section' in metadata:
tool_panel_dict = metadata[ 'tool_panel_section' ]
if not tool_panel_dict:
@@ -656,24 +659,33 @@
original_section_id = tool_section_dict[ 'id' ]
original_section_name = tool_section_dict[ 'name' ]
if original_section_id:
- tool_panel_section_key, tool_section = get_or_create_tool_section( trans,
- tool_panel_section_id=original_section_id,
- new_tool_panel_section=new_tool_panel_section )
+ tool_panel_section_key, tool_section = \
+ get_or_create_tool_section( trans,
+ tool_panel_section_id=original_section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
else:
# The user elected to change the tool panel section to contain the tools.
tool_panel_section_key, tool_section = handle_tool_panel_section( trans,
- tool_panel_section=tool_panel_section,
- new_tool_panel_section=new_tool_panel_section )
- return tool_section, new_tool_panel_section, tool_panel_section_key
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
+ return tool_section, tool_panel_section_key
-def handle_tool_panel_section( trans, tool_panel_section=None, new_tool_panel_section=None ):
- if new_tool_panel_section:
- section_id = new_tool_panel_section.lower().replace( ' ', '_' )
- tool_panel_section_key, tool_section = get_or_create_tool_section( trans,
- tool_panel_section_id=section_id,
- new_tool_panel_section=new_tool_panel_section )
- elif tool_panel_section:
- tool_panel_section_key = 'section_%s' % str( tool_panel_section )
+def handle_tool_panel_section( trans, tool_panel_section_id=None, new_tool_panel_section_label=None ):
+ """Return a ToolSection object retrieved from the current in-memory tool_panel."""
+ # If tool_panel_section_id is received, the section exists in the tool panel. In this case, the value of the
+ # received tool_panel_section_id must be the id retrieved from a tool panel config (e.g., tool_conf.xml, which
+ # may have getext). If new_tool_panel_section_label is received, a new section will be added to the tool panel.
+ if new_tool_panel_section_label:
+ section_id = 'section_%s' % str( new_tool_panel_section_label.lower().replace( ' ', '_' ) )
+ tool_panel_section_key, tool_section = \
+ get_or_create_tool_section( trans,
+ tool_panel_section_id=section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
+ elif tool_panel_section_id:
+ if tool_panel_section_id.startswith( 'section_' ):
+ tool_panel_section_key = str( tool_panel_section_id )
+ else:
+ tool_panel_section_key = 'section_%s' % str( tool_panel_section_id )
tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
else:
return None, None
https://bitbucket.org/galaxy/galaxy-central/commits/c5c57ec1af3c/
Changeset: c5c57ec1af3c
User: inithello
Date: 2014-01-14 16:35:04
Summary: Merge stable.
Affected #: 4 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Make inclusion of the changeset revision date in the revision label an optional setting and do not include it on some pages.
by commits-noreply@bitbucket.org 14 Jan '14
by commits-noreply@bitbucket.org 14 Jan '14
14 Jan '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0f50bb21db37/
Changeset: 0f50bb21db37
User: greg
Date: 2014-01-14 16:13:53
Summary: Make inclusion of the changeset revision date in the revision label an optional setting and do not include it on some pages.
Affected #: 7 files
diff -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 -r 0f50bb21db37bac8444262d9ee561f4e7f7101b0 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -1137,7 +1137,7 @@
else:
containers_dict = None
export_repository_dependencies_check_box = None
- revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
return trans.fill_template( "/webapps/tool_shed/repository/export_repository.mako",
changeset_revision=changeset_revision,
containers_dict=containers_dict,
@@ -2198,7 +2198,7 @@
selected_value=changeset_revision,
add_id_to_name=False,
downloadable=False )
- revision_label = suc.get_revision_label( trans, repository, repository.tip( trans.app ) )
+ revision_label = suc.get_revision_label( trans, repository, repository.tip( trans.app ), include_date=False )
repository_metadata = None
metadata = None
is_malicious = False
@@ -2207,16 +2207,18 @@
if changeset_revision != suc.INITIAL_CHANGELOG_HASH:
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
- revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=False )
metadata = repository_metadata.metadata
is_malicious = repository_metadata.malicious
else:
- # There is no repository_metadata defined for the changeset_revision, so see if it was defined in a previous changeset in the changelog.
- previous_changeset_revision = suc.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=False )
+ # There is no repository_metadata defined for the changeset_revision, so see if it was defined in a previous
+ # changeset in the changelog.
+ previous_changeset_revision = \
+ suc.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=False )
if previous_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, previous_changeset_revision )
if repository_metadata:
- revision_label = suc.get_revision_label( trans, repository, previous_changeset_revision )
+ revision_label = suc.get_revision_label( trans, repository, previous_changeset_revision, include_date=False )
metadata = repository_metadata.metadata
is_malicious = repository_metadata.malicious
if repository_metadata:
@@ -2383,7 +2385,7 @@
repository_metadata_id = None
metadata = None
repository_dependencies = None
- revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
changeset_revision_select_field = grids_util.build_changeset_revision_select_field( trans,
repository,
selected_value=changeset_revision,
@@ -2457,7 +2459,7 @@
changeset_revision,
metadata_only=True )
repository_type_select_field = rt_util.build_repository_type_select_field( trans, repository=repository )
- revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
return trans.fill_template( '/webapps/tool_shed/repository/rate_repository.mako',
repository=repository,
metadata=metadata,
@@ -3019,7 +3021,7 @@
selected_value=changeset_revision,
add_id_to_name=False,
downloadable=False )
- revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=False )
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
@@ -3081,7 +3083,7 @@
tool = None
guid = None
original_tool_data_path = trans.app.config.tool_data_path
- revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=False )
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
repository_metadata_id = trans.security.encode_id( repository_metadata.id )
diff -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 -r 0f50bb21db37bac8444262d9ee561f4e7f7101b0 lib/tool_shed/grids/admin_grids.py
--- a/lib/tool_shed/grids/admin_grids.py
+++ b/lib/tool_shed/grids/admin_grids.py
@@ -422,7 +422,7 @@
repository = repository_metadata.repository
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
ctx = suc.get_changectx_for_changeset( repo, repository_metadata.changeset_revision )
- return suc.get_revision_label( trans, repository, repository_metadata.changeset_revision )
+ return suc.get_revision_label( trans, repository, repository_metadata.changeset_revision, include_date=True )
class ToolsColumn( grids.TextColumn ):
diff -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 -r 0f50bb21db37bac8444262d9ee561f4e7f7101b0 lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -105,7 +105,7 @@
else:
heads_str = ''
for ctx in heads:
- heads_str += '%s<br/>' % suc.get_revision_label_from_ctx( ctx )
+ heads_str += '%s<br/>' % suc.get_revision_label_from_ctx( ctx, include_date=True )
heads_str.rstrip( '<br/>' )
if multiple_heads:
heads_str += '</font>'
@@ -1160,7 +1160,7 @@
def get_value( self, trans, grid, repository_metadata ):
repository = repository_metadata.repository
changeset_revision = repository_metadata.changeset_revision
- changeset_revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ changeset_revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
return changeset_revision_label
diff -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 -r 0f50bb21db37bac8444262d9ee561f4e7f7101b0 lib/tool_shed/grids/repository_review_grids.py
--- a/lib/tool_shed/grids/repository_review_grids.py
+++ b/lib/tool_shed/grids/repository_review_grids.py
@@ -307,7 +307,8 @@
rval += 'edit_review'
else:
rval +='browse_review'
- rval += '?id=%s">%s</a>' % ( encoded_review_id, suc.get_revision_label( trans, review.repository, review.changeset_revision ) )
+ revision_label = suc.get_revision_label( trans, review.repository, review.changeset_revision, include_date=True )
+ rval += '?id=%s">%s</a>' % ( encoded_review_id, revision_label )
return rval
diff -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 -r 0f50bb21db37bac8444262d9ee561f4e7f7101b0 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -1213,25 +1213,33 @@
reversed_changelog.insert( 0, changeset )
return reversed_changelog
-def get_revision_label( trans, repository, changeset_revision ):
- """Return a string consisting of the human read-able changeset rev and the changeset revision string."""
+def get_revision_label( trans, repository, changeset_revision, include_date=True ):
+ """
+ Return a string consisting of the human read-able changeset rev and the changeset revision string
+ which includes the revision date if the receive include_date is True.
+ """
repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
ctx = get_changectx_for_changeset( repo, changeset_revision )
if ctx:
- return get_revision_label_from_ctx( ctx )
+ return get_revision_label_from_ctx( ctx, include_date=include_date )
else:
return "-1:%s" % changeset_revision
-def get_revision_label_from_ctx( ctx ):
- return '%s:%s <i><font color="#666666">(%s)</font></i>' % \
- ( str( ctx.rev() ), str( ctx ), str( get_readable_ctx_date( ctx ) ) )
+def get_revision_label_from_ctx( ctx, include_date=True ):
+ if include_date:
+ return '%s:%s <i><font color="#666666">(%s)</font></i>' % \
+ ( str( ctx.rev() ), str( ctx ), str( get_readable_ctx_date( ctx ) ) )
+ return '%s:%s' % ( str( ctx.rev() ), str( ctx ) )
-def get_rev_label_from_changeset_revision( repo, changeset_revision ):
- """Given a changeset revision hash, return two strings, the changeset rev and the changeset revision hash."""
+def get_rev_label_from_changeset_revision( repo, changeset_revision, include_date=True ):
+ """
+ Given a changeset revision hash, return two strings, the changeset rev and the changeset revision hash
+ which includes the revision date if the receive include_date is True.
+ """
ctx = get_changectx_for_changeset( repo, changeset_revision )
if ctx:
rev = '%04d' % ctx.rev()
- label = get_revision_label_from_ctx( ctx )
+ label = get_revision_label_from_ctx( ctx, include_date=include_date )
else:
rev = '-1'
label = "-1:%s" % changeset_revision
diff -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 -r 0f50bb21db37bac8444262d9ee561f4e7f7101b0 templates/webapps/tool_shed/repository/manage_repository.mako
--- a/templates/webapps/tool_shed/repository/manage_repository.mako
+++ b/templates/webapps/tool_shed/repository/manage_repository.mako
@@ -125,7 +125,7 @@
from tool_shed.util.shed_util_common import get_revision_label_from_ctx
heads_str = ''
for ctx in heads:
- heads_str += '%s<br/>' % get_revision_label_from_ctx( ctx )
+ heads_str += '%s<br/>' % get_revision_label_from_ctx( ctx, include_date=True )
%>
Contact the administrator of this Tool Shed as soon as possible and let them know that
this repository has the following multiple heads which must be merged.<br/>
diff -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 -r 0f50bb21db37bac8444262d9ee561f4e7f7101b0 templates/webapps/tool_shed/repository/view_repository.mako
--- a/templates/webapps/tool_shed/repository/view_repository.mako
+++ b/templates/webapps/tool_shed/repository/view_repository.mako
@@ -72,7 +72,7 @@
from tool_shed.util.shed_util_common import get_revision_label_from_ctx
heads_str = ''
for ctx in heads:
- heads_str += '%s<br/>' % get_revision_label_from_ctx( ctx )
+ heads_str += '%s<br/>' % get_revision_label_from_ctx( ctx, include_date=True )
%>
Contact the administrator of this Tool Shed as soon as possible and let them know that
this repository has the following multiple heads which must be merged.<br/>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Visualizations Registry: default to on
by commits-noreply@bitbucket.org 14 Jan '14
by commits-noreply@bitbucket.org 14 Jan '14
14 Jan '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0d50efaac5d4/
Changeset: 0d50efaac5d4
User: carlfeberhard
Date: 2014-01-14 16:04:20
Summary: Visualizations Registry: default to on
Affected #: 16 files
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 config/plugins/visualizations/scatterplot/config/scatterplot.xml
--- a/config/plugins/visualizations/scatterplot/config/scatterplot.xml
+++ b/config/plugins/visualizations/scatterplot/config/scatterplot.xml
@@ -7,9 +7,15 @@
<test type="isinstance" test_attr="datatype" result_type="datatype">tabular.Tabular</test><to_param param_attr="id">dataset_id</to_param></data_source>
+ <data_source>
+ <model_class>Visualization</model_class>
+ <test test_attr="type">scatterplot</test>
+ <to_param param_attr="id">visualization_id</to_param>
+ </data_source></data_sources><params><param type="dataset" var_name_in_template="hda" required="true">dataset_id</param>
+ <param type="visualization" var_name_in_template="visualization">visualization_id</param></params><template>scatterplot.mako</template></visualization>
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
--- a/config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
+++ b/config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
@@ -10,6 +10,7 @@
Allow setting perPage of config
Auto render if given data and/or config
Allow option to auto set width/height based on screen real estate avail.
+ Handle large number of pages better (Known genes hg19)
Use d3.nest to allow grouping, pagination/filtration by group (e.g. chromCol)
Semantic HTML (figure, caption)
Save as visualization, load from visualization
@@ -29,26 +30,28 @@
* configuring which data will be used
* configuring the plot display
*/
-var ScatterplotConfigEditor = BaseView.extend( LoggableMixin ).extend({
+var ScatterplotConfigEditor = Backbone.View.extend( LoggableMixin ).extend({
//TODO: !should be a view on a visualization model
//logger : console,
className : 'scatterplot-control-form',
/** initialize requires a configuration Object containing a dataset Object */
initialize : function( attributes ){
- //console.log( this + '.initialize, attributes:', attributes );
- if( !attributes || !attributes.config || !attributes.dataset ){
- throw new Error( "ScatterplotView requires a configuration and dataset" );
+ if( !this.model ){
+ this.model = new Visualization({ type: 'scatterplot' });
}
- //console.log( 'config:', attributes.config );
+ console.log( this + '.initialize, attributes:', attributes );
+ if( !attributes || !attributes.dataset ){
+ throw new Error( "ScatterplotConfigEditor requires a dataset" );
+ }
this.dataset = attributes.dataset;
- //console.log( 'dataset:', this.dataset );
+ console.log( 'dataset:', this.dataset );
//TODO: ScatterplotView -> ScatterplotDisplay, this.plotView -> this.display
this.plotView = new ScatterplotView({
dataset : attributes.dataset,
- config : attributes.config
+ model : this.model
//TODO: if data
});
},
@@ -58,8 +61,7 @@
//console.log( this + '.render' );
// render the tab controls, areas and loading indicator
- this.$el.append( ScatterplotConfigEditor.templates.mainLayout({
- }));
+ this.$el.append( ScatterplotConfigEditor.templates.mainLayout({}));
// render the tab content
this.$el.find( '#data-control' ).append( this._render_dataControl() );
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
--- a/config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
+++ b/config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
@@ -1,1 +1,1 @@
-function scatterplot(a,b,c){function d(){var a={v:{},h:{}};return a.v.lines=p.selectAll("line.v-grid-line").data(m.x.ticks(q.x.fn.ticks()[0])),a.v.lines.enter().append("svg:line").classed("grid-line v-grid-line",!0),a.v.lines.attr("x1",m.x).attr("x2",m.x).attr("y1",0).attr("y2",b.height),a.v.lines.exit().remove(),a.h.lines=p.selectAll("line.h-grid-line").data(m.y.ticks(q.y.fn.ticks()[0])),a.h.lines.enter().append("svg:line").classed("grid-line h-grid-line",!0),a.h.lines.attr("x1",0).attr("x2",b.width).attr("y1",m.y).attr("y2",m.y),a.h.lines.exit().remove(),a}function e(){return t.attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",function(a,b){return m.y(k(a,b))}).style("display","block").filter(function(){var a=d3.select(this).attr("cx"),c=d3.select(this).attr("cy");return 0>a||a>b.width?!0:0>c||c>b.height?!0:!1}).style("display","none")}function f(){q.redraw(),e(),s=d(),$(".chart-info-box").remove(),$(o.node()).trigger("zoom.scatterplot",[])}function g(a,c,d){return c+=8,$(['<div class="chart-info-box" style="position: absolute">',b.idColumn?"<div>"+d[b.idColumn]+"</div>":"","<div>",j(d),"</div>","<div>",k(d),"</div>","</div>"].join("")).css({top:a,left:c,"z-index":2})}var h=function(a,b){return"translate("+a+","+b+")"},i=function(a,b,c){return"rotate("+a+","+b+","+c+")"},j=function(a){return a[b.xColumn]},k=function(a){return a[b.yColumn]},l={x:{extent:d3.extent(c,j)},y:{extent:d3.extent(c,k)}},m={x:d3.scale.linear().domain(l.x.extent).range([0,b.width]),y:d3.scale.linear().domain(l.y.extent).range([b.height,0])},n=d3.behavior.zoom().x(m.x).y(m.y).scaleExtent([1,10]),o=d3.select(a).attr("class","scatterplot").attr("width","100%").attr("height",b.height+(b.margin.top+b.margin.bottom)),p=o.append("g").attr("class","content").attr("transform",h(b.margin.left,b.margin.top)).call(n);p.append("rect").attr("class","zoom-rect").attr("width",b.width).attr("height",b.height).style("fill","transparent");var q={x:{},y:{}};q.x.fn=d3.svg.axis().orient("bottom").scale(m.x).ticks(b.x.ticks).tickFormat(d3.format("s")),q.y.fn=d3.svg.axis().orient("left").scale(m.y).ticks(b.y.ticks).tickFormat(d3.format("s")),q.x.g=p.append("g").attr("class","x axis").attr("transform",h(0,b.height)).call(q.x.fn),q.y.g=p.append("g").attr("class","y axis").call(q.y.fn);var r=4;q.x.label=o.append("text").attr("class","axis-label").text(b.x.label).attr("text-anchor","middle").attr("dominant-baseline","text-after-edge").attr("x",b.width/2+b.margin.left).attr("y",b.height+b.margin.bottom+b.margin.top-r),q.y.label=o.append("text").attr("class","axis-label").text(b.y.label).attr("text-anchor","middle").attr("dominant-baseline","text-before-edge").attr("x",r).attr("y",b.height/2).attr("transform",i(-90,r,b.height/2)),q.redraw=function(){o.select(".x.axis").call(q.x.fn),o.select(".y.axis").call(q.y.fn)};var s=d(),t=p.selectAll(".glyph").data(c).enter().append("svg:circle").classed("glyph",!0).attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",b.height).attr("r",0);t.transition().duration(b.animDuration).attr("cy",function(a,b){return m.y(k(a,b))}).attr("r",b.datapointSize),n.on("zoom",f),t.on("mouseover",function(a,c){var d=d3.select(this);d.style("fill","red").style("fill-opacity",1),p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")-b.datapointSize).attr("y1",d.attr("cy")).attr("x2",0).attr("y2",d.attr("cy")).classed("hoverline",!0),d.attr("cy")<b.height&&p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")).attr("y1",+d.attr("cy")+b.datapointSize).attr("x2",d.attr("cx")).attr("y2",b.height).classed("hoverline",!0);var e=this.getBoundingClientRect();$("body").append(g(e.top,e.right,a)),$(o.node()).trigger("mouseover-datapoint.scatterplot",[this,a,c])}),t.on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",.2),p.selectAll(".hoverline").remove(),$(".chart-info-box").remove()})}this.Templates=this.Templates||{},this.Templates.chartcontrol=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f,g="",h="function",i=this.escapeExpression;return g+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n<div data-config-key="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">',(f=c.datapointSize)?f=f.call(b,{hash:{},data:e}):(f=b.datapointSize,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n</div>\n\n<div data-config-key="width" class="form-input numeric-slider-input">\n <label for="width">Chart width: </label>\n <div class="slider-output">',(f=c.width)?f=f.call(b,{hash:{},data:e}):(f=b.width,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="height" class="form-input numeric-slider-input">\n <label for="height">Chart height: </label>\n <div class="slider-output">',(f=c.height)?f=f.call(b,{hash:{},data:e}):(f=b.height,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="'+i((f=b.x,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<div data-config-key="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="'+i((f=b.y,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.Templates.datacontrol=Handlebars.template(function(a,b,c,d,e){function f(a,b){var d,e="";return e+='\n <option value="',(d=c.index)?d=d.call(a,{hash:{},data:b}):(d=a.index,d=typeof d===j?d.apply(a):d),e+=k(d)+'">',(d=c.name)?d=d.call(a,{hash:{},data:b}):(d=a.name,d=typeof d===j?d.apply(a):d),e+=k(d)+"</option>\n "}function g(){return'checked="true"'}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var h,i="",j="function",k=this.escapeExpression,l=this;return i+='<p class="help-text">\n Use the following controls to change the data used by the chart.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n\n<div class="column-select">\n <label>Data column for X: </label>\n <select name="xColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n<div class="column-select">\n <label>Data column for Y: </label>\n <select name="yColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="include-id">\n <label for="include-id-checkbox">Include a third column as data point IDs?</label>\n <input type="checkbox" name="include-id" id="include-id-checkbox" />\n <p class="help-text-small">\n These will be displayed (along with the x and y values) when you hover over\n a data point.\n </p>\n</div>\n<div class="column-select" style="display: none">\n <label for="ID-select">Data column for IDs: </label>\n <select name="idColumn">\n ',h=c.each.call(b,b.allColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="first-line-header" style="display: none;">\n <p>Possible headers: ',(h=c.possibleHeaders)?h=h.call(b,{hash:{},data:e}):(h=b.possibleHeaders,h=typeof h===j?h.apply(b):h),i+=k(h)+'\n </p>\n <label for="first-line-header-checkbox">Use the above as column headers?</label>\n <input type="checkbox" name="include-id" id="first-line-header-checkbox"\n ',h=c["if"].call(b,b.usePossibleHeaders,{hash:{},inverse:l.noop,fn:l.program(3,g,e),data:e}),(h||0===h)&&(i+=h),i+='/>\n <p class="help-text-small">\n It looks like Galaxy couldn\'t get proper column headers for this data.\n Would you like to use the column headers above as column names to select columns?\n </p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.Templates.editor=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f="";return f+='<div class="scatterplot-editor tabbable tabs-left">\n \n <ul class="nav nav-tabs">\n \n <li class="active">\n <a title="Use this tab to change which data are used"\n href="#data-control" data-toggle="tab">Data Controls</a>\n </li>\n <li>\n <a title="Use this tab to change how the chart is drawn"\n href="#chart-control" data-toggle="tab" >Chart Controls</a>\n </li>\n \n <li class="disabled">\n <a title="This tab will display the chart"\n href="#chart-display" data-toggle="tab">Chart</a>\n </li>\n </ul>\n\n \n <div class="tab-content">\n \n <div id="data-control" class="scatterplot-config-control tab-pane active">\n \n </div>\n \n \n <div id="chart-control" class="scatterplot-config-control tab-pane">\n \n </div>\n\n \n <div id="chart-display" class="scatterplot-display tab-pane"></div>\n\n </div>\n</div>\n'});var ScatterplotConfigEditor=BaseView.extend(LoggableMixin).extend({className:"scatterplot-control-form",initialize:function(a){if(!a||!a.config||!a.dataset)throw new Error("ScatterplotView requires a configuration and dataset");this.dataset=a.dataset,this.plotView=new ScatterplotView({dataset:a.dataset,config:a.config})},render:function(){return this.$el.append(ScatterplotConfigEditor.templates.mainLayout({})),this.$el.find("#data-control").append(this._render_dataControl()),this._render_chartControls(this.$el.find("#chart-control")),this._render_chartDisplay(),this.$el.find("[title]").tooltip(),this},_render_dataControl:function(){var a=this.dataset,b=_.map(a.metadata_column_types,function(b,c){var d={index:c,type:b,name:"column "+(c+1)};return a.metadata_column_names&&a.metadata_column_names[c]&&(d.name=a.metadata_column_names[c]),d}),c=_.filter(b,function(a){return"int"===a.type||"float"===a.type});2>c&&(c=b);var d=this.$el.find(".tab-pane#data-control");return d.html(ScatterplotConfigEditor.templates.dataControl({allColumns:b,numericColumns:c})),d.find('[name="xColumn"]').val(this.plotView.config.xColumn||c[0].index),d.find('[name="yColumn"]').val(this.plotView.config.yColumn||c[1].index),void 0!==this.plotView.config.idColumn&&(d.find("#include-id-checkbox").prop("checked",!0).trigger("change"),d.find('select[name="idColumn"]').val(this.plotView.config.idColumn)),d},_render_chartControls:function(a){function b(){var a=$(this);a.siblings(".slider-output").text(a.slider("value"))}a.html(ScatterplotConfigEditor.templates.chartControl(this.plotView.config));var c=this,d={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};return a.find(".numeric-slider-input").each(function(){var a=$(this),e=a.attr("data-config-key"),f=_.extend(d[e],{value:c.plotView.config[e],change:b,slide:b});a.find(".slider").slider(f)}),this.dataset.metadata_column_names,a},_render_chartDisplay:function(){var a=this.$el.find(".tab-pane#chart-display");return this.plotView.setElement(a),this.plotView.render(),a},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-control .render-button":"renderChart","click #chart-control .render-button":"renderChart"},toggleThirdColumnSelector:function(){this.$el.find('select[name="idColumn"]').parent().toggle()},renderChart:function(){this.$el.find(".nav li.disabled").removeClass("disabled"),this.updateConfigWithDataSettings(),this.updateConfigWithChartSettings(),this.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show"),this.plotView.fetchData()},updateConfigWithDataSettings:function(){var a=this.$el.find("#data-control"),b={xColumn:Number(a.find('[name="xColumn"]').val()),yColumn:Number(a.find('[name="yColumn"]').val())};return a.find("#include-id-checkbox").prop("checked")&&(b.idColumn=a.find('[name="idColumn"]').val()),_.extend(this.plotView.config,b)},updateConfigWithChartSettings:function(){var a=this.plotView,b=this.$el.find("#chart-control");return["datapointSize","width","height"].forEach(function(c){a.config[c]=b.find('.numeric-slider-input[data-config-key="'+c+'"]').find(".slider").slider("value")}),a.config.x.label=b.find('input[name="X-axis-label"]').val(),a.config.y.label=b.find('input[name="Y-axis-label"]').val(),a.config},toString:function(){return"ScatterplotConfigEditor("+(this.dataset?this.dataset.id:"")+")"}});ScatterplotConfigEditor.templates={mainLayout:Templates.editor,dataControl:Templates.datacontrol,chartControl:Templates.chartcontrol};var ScatterplotView=Backbone.View.extend({defaults:{metadata:{dataLines:void 0},pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500},initialize:function(a){this.config=_.extend(_.clone(this.defaults),a.config||{}),this.dataset=a.dataset},updateConfig:function(a){this.config=this.config||{},_.extend(this.config,a)},fetchData:function(){this.showLoadingIndicator("getting data");var a=this;return xhr=jQuery.getJSON("/api/datasets/"+this.dataset.id,{data_type:"raw_data",provider:"dataset-column",limit:this.config.pagination.perPage,offset:this.config.pagination.currPage*this.config.pagination.perPage}),xhr.done(function(b){a.renderData(b.data)}),xhr.fail(function(a,b,c){alert("Error loading data:\n"+a.responseText),console.error(a,b,c)}),xhr.always(function(){a.hideLoadingIndicator()}),xhr},render:function(a){return this.$el.addClass("scatterplot-display").html(['<div class="controls clear"></div>','<div class="loading-indicator">','<span class="fa fa-spinner fa-spin"></span>','<span class="loading-indicator-message"></span>',"</div>","<svg/>",'<div class="stats-display"></div>'].join("")),this.$el.children().hide(),a&&this.renderData(a),this},showLoadingIndicator:function(a,b){a=a||"",b=b||"fast";var c=this.$el.find(".loading-indicator");a&&c.find(".loading-indicator-message").text(a),c.is(":visible")||(this.toggleStats(!1),c.css({left:this.config.width/2,top:this.config.height/2}).show())},hideLoadingIndicator:function(a){a=a||"fast",this.$el.find(".loading-indicator").hide()},renderData:function(a){this.$el.find(".controls").empty().append(this.renderControls(a)).show(),this.renderPlot(a),this.getStats(a)},renderControls:function(a){var b=this,c=$('<div class="left"></div>'),d=$('<div class="right"></div>');return c.append([this.renderPrevNext(a),this.renderPagination(a)]),d.append([this.renderLineInfo(a),$("<button>Stats</button>").addClass("stats-toggle-btn").click(function(){b.toggleStats()}),$("<button>Redraw</button>").addClass("rerender-btn").click(function(){b.renderPlot(a)})]),[c,d]},renderLineInfo:function(a){var b=this.dataset.metadata_data_lines||"an unknown number of",c=this.config.pagination.currPage*this.config.pagination.perPage,d=c+a.length;return $("<p/>").addClass("scatterplot-data-info").text(["Displaying lines",c+1,"to",d,"of",b,"lines"].join(" "))},renderPrevNext:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;var c=this,d=this.dataset.metadata_data_lines,e=d?Math.ceil(d/this.config.pagination.perPage):void 0,f=b("Prev").click(function(){c.config.pagination.currPage>0&&(c.config.pagination.currPage-=1,c.fetchData())}),g=b("Next").click(function(){(!e||c.config.pagination.currPage<e-1)&&(c.config.pagination.currPage+=1,c.fetchData())}),h=$("<ul/>").addClass("pagination data-prev-next").append([f,g]);return 0===c.config.pagination.currPage&&f.addClass("disabled"),e&&c.config.pagination.currPage===e-1&&g.addClass("disabled"),h},renderPagination:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}function c(){d.config.pagination.currPage=$(this).data("page"),d.fetchData()}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;for(var d=this,e=this.dataset.metadata_data_lines,f=e?Math.ceil(e/this.config.pagination.perPage):void 0,g=$("<ul/>").addClass("pagination data-pages"),h=0;f>h;h+=1){var i=b(h+1).attr("data-page",h).click(c);h===this.config.pagination.currPage&&i.addClass("active"),g.append(i)}return g},renderPlot:function(a){this.toggleStats(!1);var b=this.$el.find("svg");b.off().empty().show(),scatterplot(b.get(0),this.config,a)},getStats:function(a){var b=this;meanWorker=new Worker("/plugins/visualizations/scatterplot/static/worker-stats.js"),meanWorker.postMessage({data:a,keys:[this.config.xColumn,this.config.yColumn]}),meanWorker.onerror=function(){meanWorker.terminate()},meanWorker.onmessage=function(a){b.renderStats(a.data)}},renderStats:function(a){var b=this.$el.find(".stats-display"),c=this.config.x.label,d=this.config.y.label,e=$("<table/>").addClass("table").append(["<thead><th></th><th>",c,"</th><th>",d,"</th></thead>"].join("")).append(_.map(a,function(a,b){return $(["<tr><td>",b,"</td><td>",a[0],"</td><td>",a[1],"</td></tr>"].join(""))}));b.empty().append(e)},toggleStats:function(a){var b=this.$el.find(".stats-display");a=void 0===a?b.is(":hidden"):a,a?(this.$el.find("svg").hide(),b.show(),this.$el.find(".controls .stats-toggle-btn").text("Plot")):(b.hide(),this.$el.find("svg").show(),this.$el.find(".controls .stats-toggle-btn").text("Stats"))},toString:function(){return"ScatterplotView()"}});
\ No newline at end of file
+function scatterplot(a,b,c){function d(){var a={v:{},h:{}};return a.v.lines=p.selectAll("line.v-grid-line").data(m.x.ticks(q.x.fn.ticks()[0])),a.v.lines.enter().append("svg:line").classed("grid-line v-grid-line",!0),a.v.lines.attr("x1",m.x).attr("x2",m.x).attr("y1",0).attr("y2",b.height),a.v.lines.exit().remove(),a.h.lines=p.selectAll("line.h-grid-line").data(m.y.ticks(q.y.fn.ticks()[0])),a.h.lines.enter().append("svg:line").classed("grid-line h-grid-line",!0),a.h.lines.attr("x1",0).attr("x2",b.width).attr("y1",m.y).attr("y2",m.y),a.h.lines.exit().remove(),a}function e(){return t.attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",function(a,b){return m.y(k(a,b))}).style("display","block").filter(function(){var a=d3.select(this).attr("cx"),c=d3.select(this).attr("cy");return 0>a||a>b.width?!0:0>c||c>b.height?!0:!1}).style("display","none")}function f(){q.redraw(),e(),s=d(),$(".chart-info-box").remove(),$(o.node()).trigger("zoom.scatterplot",[])}function g(a,c,d){return c+=8,$(['<div class="chart-info-box" style="position: absolute">',b.idColumn?"<div>"+d[b.idColumn]+"</div>":"","<div>",j(d),"</div>","<div>",k(d),"</div>","</div>"].join("")).css({top:a,left:c,"z-index":2})}var h=function(a,b){return"translate("+a+","+b+")"},i=function(a,b,c){return"rotate("+a+","+b+","+c+")"},j=function(a){return a[b.xColumn]},k=function(a){return a[b.yColumn]},l={x:{extent:d3.extent(c,j)},y:{extent:d3.extent(c,k)}},m={x:d3.scale.linear().domain(l.x.extent).range([0,b.width]),y:d3.scale.linear().domain(l.y.extent).range([b.height,0])},n=d3.behavior.zoom().x(m.x).y(m.y).scaleExtent([1,10]),o=d3.select(a).attr("class","scatterplot").attr("width","100%").attr("height",b.height+(b.margin.top+b.margin.bottom)),p=o.append("g").attr("class","content").attr("transform",h(b.margin.left,b.margin.top)).call(n);p.append("rect").attr("class","zoom-rect").attr("width",b.width).attr("height",b.height).style("fill","transparent");var q={x:{},y:{}};q.x.fn=d3.svg.axis().orient("bottom").scale(m.x).ticks(b.x.ticks).tickFormat(d3.format("s")),q.y.fn=d3.svg.axis().orient("left").scale(m.y).ticks(b.y.ticks).tickFormat(d3.format("s")),q.x.g=p.append("g").attr("class","x axis").attr("transform",h(0,b.height)).call(q.x.fn),q.y.g=p.append("g").attr("class","y axis").call(q.y.fn);var r=4;q.x.label=o.append("text").attr("class","axis-label").text(b.x.label).attr("text-anchor","middle").attr("dominant-baseline","text-after-edge").attr("x",b.width/2+b.margin.left).attr("y",b.height+b.margin.bottom+b.margin.top-r),q.y.label=o.append("text").attr("class","axis-label").text(b.y.label).attr("text-anchor","middle").attr("dominant-baseline","text-before-edge").attr("x",r).attr("y",b.height/2).attr("transform",i(-90,r,b.height/2)),q.redraw=function(){o.select(".x.axis").call(q.x.fn),o.select(".y.axis").call(q.y.fn)};var s=d(),t=p.selectAll(".glyph").data(c).enter().append("svg:circle").classed("glyph",!0).attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",b.height).attr("r",0);t.transition().duration(b.animDuration).attr("cy",function(a,b){return m.y(k(a,b))}).attr("r",b.datapointSize),n.on("zoom",f),t.on("mouseover",function(a,c){var d=d3.select(this);d.style("fill","red").style("fill-opacity",1),p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")-b.datapointSize).attr("y1",d.attr("cy")).attr("x2",0).attr("y2",d.attr("cy")).classed("hoverline",!0),d.attr("cy")<b.height&&p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")).attr("y1",+d.attr("cy")+b.datapointSize).attr("x2",d.attr("cx")).attr("y2",b.height).classed("hoverline",!0);var e=this.getBoundingClientRect();$("body").append(g(e.top,e.right,a)),$(o.node()).trigger("mouseover-datapoint.scatterplot",[this,a,c])}),t.on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",.2),p.selectAll(".hoverline").remove(),$(".chart-info-box").remove()})}this.scatterplot=this.scatterplot||{},this.scatterplot.chartcontrol=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f,g="",h="function",i=this.escapeExpression;return g+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n<div data-config-key="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">',(f=c.datapointSize)?f=f.call(b,{hash:{},data:e}):(f=b.datapointSize,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n</div>\n\n<div data-config-key="width" class="form-input numeric-slider-input">\n <label for="width">Chart width: </label>\n <div class="slider-output">',(f=c.width)?f=f.call(b,{hash:{},data:e}):(f=b.width,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="height" class="form-input numeric-slider-input">\n <label for="height">Chart height: </label>\n <div class="slider-output">',(f=c.height)?f=f.call(b,{hash:{},data:e}):(f=b.height,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="'+i((f=b.x,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<div data-config-key="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="'+i((f=b.y,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.scatterplot.datacontrol=Handlebars.template(function(a,b,c,d,e){function f(a,b){var d,e="";return e+='\n <option value="',(d=c.index)?d=d.call(a,{hash:{},data:b}):(d=a.index,d=typeof d===j?d.apply(a):d),e+=k(d)+'">',(d=c.name)?d=d.call(a,{hash:{},data:b}):(d=a.name,d=typeof d===j?d.apply(a):d),e+=k(d)+"</option>\n "}function g(){return'checked="true"'}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var h,i="",j="function",k=this.escapeExpression,l=this;return i+='<p class="help-text">\n Use the following controls to change the data used by the chart.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n\n<div class="column-select">\n <label>Data column for X: </label>\n <select name="xColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n<div class="column-select">\n <label>Data column for Y: </label>\n <select name="yColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="include-id">\n <label for="include-id-checkbox">Include a third column as data point IDs?</label>\n <input type="checkbox" name="include-id" id="include-id-checkbox" />\n <p class="help-text-small">\n These will be displayed (along with the x and y values) when you hover over\n a data point.\n </p>\n</div>\n<div class="column-select" style="display: none">\n <label for="ID-select">Data column for IDs: </label>\n <select name="idColumn">\n ',h=c.each.call(b,b.allColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="first-line-header" style="display: none;">\n <p>Possible headers: ',(h=c.possibleHeaders)?h=h.call(b,{hash:{},data:e}):(h=b.possibleHeaders,h=typeof h===j?h.apply(b):h),i+=k(h)+'\n </p>\n <label for="first-line-header-checkbox">Use the above as column headers?</label>\n <input type="checkbox" name="include-id" id="first-line-header-checkbox"\n ',h=c["if"].call(b,b.usePossibleHeaders,{hash:{},inverse:l.noop,fn:l.program(3,g,e),data:e}),(h||0===h)&&(i+=h),i+='/>\n <p class="help-text-small">\n It looks like Galaxy couldn\'t get proper column headers for this data.\n Would you like to use the column headers above as column names to select columns?\n </p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.scatterplot.editor=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f="";return f+='<div class="scatterplot-editor tabbable tabs-left">\n \n <ul class="nav nav-tabs">\n \n <li class="active">\n <a title="Use this tab to change which data are used"\n href="#data-control" data-toggle="tab">Data Controls</a>\n </li>\n <li>\n <a title="Use this tab to change how the chart is drawn"\n href="#chart-control" data-toggle="tab" >Chart Controls</a>\n </li>\n \n <li class="disabled">\n <a title="This tab will display the chart"\n href="#chart-display" data-toggle="tab">Chart</a>\n </li>\n </ul>\n\n \n <div class="tab-content">\n \n <div id="data-control" class="scatterplot-config-control tab-pane active">\n \n </div>\n \n \n <div id="chart-control" class="scatterplot-config-control tab-pane">\n \n </div>\n\n \n <div id="chart-display" class="scatterplot-display tab-pane"></div>\n\n </div>\n</div>\n'});var ScatterplotConfigEditor=Backbone.View.extend(LoggableMixin).extend({className:"scatterplot-control-form",initialize:function(a){if(this.model||(this.model=new Visualization({type:"scatterplot"})),console.log(this+".initialize, attributes:",a),!a||!a.dataset)throw new Error("ScatterplotConfigEditor requires a dataset");this.dataset=a.dataset,console.log("dataset:",this.dataset),this.plotView=new ScatterplotView({dataset:a.dataset,model:this.model})},render:function(){return this.$el.append(ScatterplotConfigEditor.templates.mainLayout({})),this.$el.find("#data-control").append(this._render_dataControl()),this._render_chartControls(this.$el.find("#chart-control")),this._render_chartDisplay(),this.$el.find("[title]").tooltip(),this},_render_dataControl:function(){var a=this.dataset,b=_.map(a.metadata_column_types,function(b,c){var d={index:c,type:b,name:"column "+(c+1)};return a.metadata_column_names&&a.metadata_column_names[c]&&(d.name=a.metadata_column_names[c]),d}),c=_.filter(b,function(a){return"int"===a.type||"float"===a.type});2>c&&(c=b);var d=this.$el.find(".tab-pane#data-control");return d.html(ScatterplotConfigEditor.templates.dataControl({allColumns:b,numericColumns:c})),d.find('[name="xColumn"]').val(this.plotView.config.xColumn||c[0].index),d.find('[name="yColumn"]').val(this.plotView.config.yColumn||c[1].index),void 0!==this.plotView.config.idColumn&&(d.find("#include-id-checkbox").prop("checked",!0).trigger("change"),d.find('select[name="idColumn"]').val(this.plotView.config.idColumn)),d},_render_chartControls:function(a){function b(){var a=$(this);a.siblings(".slider-output").text(a.slider("value"))}a.html(ScatterplotConfigEditor.templates.chartControl(this.plotView.config));var c=this,d={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};return a.find(".numeric-slider-input").each(function(){var a=$(this),e=a.attr("data-config-key"),f=_.extend(d[e],{value:c.plotView.config[e],change:b,slide:b});a.find(".slider").slider(f)}),this.dataset.metadata_column_names,a},_render_chartDisplay:function(){var a=this.$el.find(".tab-pane#chart-display");return this.plotView.setElement(a),this.plotView.render(),a},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-control .render-button":"renderChart","click #chart-control .render-button":"renderChart"},toggleThirdColumnSelector:function(){this.$el.find('select[name="idColumn"]').parent().toggle()},renderChart:function(){this.$el.find(".nav li.disabled").removeClass("disabled"),this.updateConfigWithDataSettings(),this.updateConfigWithChartSettings(),this.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show"),this.plotView.fetchData()},updateConfigWithDataSettings:function(){var a=this.$el.find("#data-control"),b={xColumn:Number(a.find('[name="xColumn"]').val()),yColumn:Number(a.find('[name="yColumn"]').val())};return a.find("#include-id-checkbox").prop("checked")&&(b.idColumn=a.find('[name="idColumn"]').val()),_.extend(this.plotView.config,b)},updateConfigWithChartSettings:function(){var a=this.plotView,b=this.$el.find("#chart-control");return["datapointSize","width","height"].forEach(function(c){a.config[c]=b.find('.numeric-slider-input[data-config-key="'+c+'"]').find(".slider").slider("value")}),a.config.x.label=b.find('input[name="X-axis-label"]').val(),a.config.y.label=b.find('input[name="Y-axis-label"]').val(),a.config},toString:function(){return"ScatterplotConfigEditor("+(this.dataset?this.dataset.id:"")+")"}});ScatterplotConfigEditor.templates={mainLayout:scatterplot.editor,dataControl:scatterplot.datacontrol,chartControl:scatterplot.chartcontrol};var ScatterplotView=Backbone.View.extend({defaults:{metadata:{dataLines:void 0},pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500},initialize:function(a){this.config=_.extend(_.clone(this.defaults),a.config||{}),this.dataset=a.dataset},updateConfig:function(a){this.config=this.config||{},_.extend(this.config,a)},fetchData:function(){this.showLoadingIndicator("getting data");var a=this;return xhr=jQuery.getJSON("/api/datasets/"+this.dataset.id,{data_type:"raw_data",provider:"dataset-column",limit:this.config.pagination.perPage,offset:this.config.pagination.currPage*this.config.pagination.perPage}),xhr.done(function(b){a.renderData(b.data)}),xhr.fail(function(a,b,c){alert("Error loading data:\n"+a.responseText),console.error(a,b,c)}),xhr.always(function(){a.hideLoadingIndicator()}),xhr},render:function(a){return this.$el.addClass("scatterplot-display").html(['<div class="controls clear"></div>','<div class="loading-indicator">','<span class="fa fa-spinner fa-spin"></span>','<span class="loading-indicator-message"></span>',"</div>","<svg/>",'<div class="stats-display"></div>'].join("")),this.$el.children().hide(),a&&this.renderData(a),this},showLoadingIndicator:function(a,b){a=a||"",b=b||"fast";var c=this.$el.find(".loading-indicator");a&&c.find(".loading-indicator-message").text(a),c.is(":visible")||(this.toggleStats(!1),c.css({left:this.config.width/2,top:this.config.height/2}).show())},hideLoadingIndicator:function(a){a=a||"fast",this.$el.find(".loading-indicator").hide()},renderData:function(a){this.$el.find(".controls").empty().append(this.renderControls(a)).show(),this.renderPlot(a),this.getStats(a)},renderControls:function(a){var b=this,c=$('<div class="left"></div>'),d=$('<div class="right"></div>');return c.append([this.renderPrevNext(a),this.renderPagination(a)]),d.append([this.renderLineInfo(a),$("<button>Stats</button>").addClass("stats-toggle-btn").click(function(){b.toggleStats()}),$("<button>Redraw</button>").addClass("rerender-btn").click(function(){b.renderPlot(a)})]),[c,d]},renderLineInfo:function(a){var b=this.dataset.metadata_data_lines||"an unknown number of",c=this.config.pagination.currPage*this.config.pagination.perPage,d=c+a.length;return $("<p/>").addClass("scatterplot-data-info").text(["Displaying lines",c+1,"to",d,"of",b,"lines"].join(" "))},renderPrevNext:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;var c=this,d=this.dataset.metadata_data_lines,e=d?Math.ceil(d/this.config.pagination.perPage):void 0,f=b("Prev").click(function(){c.config.pagination.currPage>0&&(c.config.pagination.currPage-=1,c.fetchData())}),g=b("Next").click(function(){(!e||c.config.pagination.currPage<e-1)&&(c.config.pagination.currPage+=1,c.fetchData())}),h=$("<ul/>").addClass("pagination data-prev-next").append([f,g]);return 0===c.config.pagination.currPage&&f.addClass("disabled"),e&&c.config.pagination.currPage===e-1&&g.addClass("disabled"),h},renderPagination:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}function c(){d.config.pagination.currPage=$(this).data("page"),d.fetchData()}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;for(var d=this,e=this.dataset.metadata_data_lines,f=e?Math.ceil(e/this.config.pagination.perPage):void 0,g=$("<ul/>").addClass("pagination data-pages"),h=0;f>h;h+=1){var i=b(h+1).attr("data-page",h).click(c);h===this.config.pagination.currPage&&i.addClass("active"),g.append(i)}return g},renderPlot:function(a){this.toggleStats(!1);var b=this.$el.find("svg");b.off().empty().show(),scatterplot(b.get(0),this.config,a)},getStats:function(a){var b=this;meanWorker=new Worker("/plugins/visualizations/scatterplot/static/worker-stats.js"),meanWorker.postMessage({data:a,keys:[this.config.xColumn,this.config.yColumn]}),meanWorker.onerror=function(){meanWorker.terminate()},meanWorker.onmessage=function(a){b.renderStats(a.data)}},renderStats:function(a){var b=this.$el.find(".stats-display"),c=this.config.x.label,d=this.config.y.label,e=$("<table/>").addClass("table").append(["<thead><th></th><th>",c,"</th><th>",d,"</th></thead>"].join("")).append(_.map(a,function(a,b){return $(["<tr><td>",b,"</td><td>",a[0],"</td><td>",a[1],"</td></tr>"].join(""))}));b.empty().append(e)},toggleStats:function(a){var b=this.$el.find(".stats-display");a=void 0===a?b.is(":hidden"):a,a?(this.$el.find("svg").hide(),b.show(),this.$el.find(".controls .stats-toggle-btn").text("Plot")):(b.hide(),this.$el.find("svg").show(),this.$el.find(".controls .stats-toggle-btn").text("Stats"))},toString:function(){return"ScatterplotView()"}}),ScatterplotModel=Visualization.extend({defaults:{type:"scatterplot",config:{metadata:{dataLines:void 0},pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500}}});
\ No newline at end of file
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 config/plugins/visualizations/scatterplot/templates/scatterplot.mako
--- a/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
+++ b/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
@@ -1,3 +1,24 @@
+<%
+ hda_dict = trans.security.encode_dict_ids( hda.to_dict() )
+
+ config = query_args
+ title = "Scatterplot of '" + hda.name + "'"
+ info = hda.info
+
+ visualization = context.get( 'visualization' )
+ if visualization is not None:
+ config = visualization.latest_revision.config
+ config.update( query_args )
+ title = visualization.title
+ info = config.get( 'description', info )
+
+ config[ 'type' ] = 'scatterplot'
+
+ # optionally bootstrap data from dprov
+ ##data = list( hda.datatype.dataset_column_dataprovider( hda, limit=10000 ) )
+%>
+## ----------------------------------------------------------------------------
+
<!DOCTYPE HTML><html><head>
@@ -13,14 +34,15 @@
## ----------------------------------------------------------------------------
<script type="text/javascript" src="/static/scripts/libs/jquery/jquery.js"></script><script type="text/javascript" src="/static/scripts/libs/jquery/jquery.migrate.js"></script>
+<script type="text/javascript" src="/static/scripts/libs/jquery/jquery-ui.js"></script>
+<script type="text/javascript" src="/static/scripts/libs/bootstrap.js"></script><script type="text/javascript" src="/static/scripts/libs/underscore.js"></script><script type="text/javascript" src="/static/scripts/libs/backbone/backbone.js"></script><script type="text/javascript" src="/static/scripts/libs/handlebars.runtime.js"></script><script type="text/javascript" src="/static/scripts/libs/d3.js"></script>
-<script type="text/javascript" src="/static/scripts/libs/bootstrap.js"></script>
-<script type="text/javascript" src="/static/scripts/libs/jquery/jquery-ui.js"></script>
-<script type="text/javascript" src="/static/scripts/utils/LazyDataLoader.js"></script>
+
<script type="text/javascript" src="/static/scripts/mvc/base-mvc.js"></script>
+<script type="text/javascript" src="/static/scripts/mvc/visualization/visualization-model.js"></script><script type="text/javascript" src="/plugins/visualizations/scatterplot/static/scatterplot-edit.js"></script></head>
@@ -30,25 +52,20 @@
%if not embedded:
## dataset info: only show if on own page
<div class="chart-header">
- <h2>Scatterplot of '${hda.name}'</h2>
- <p>${hda.info}</p>
+ <h2>${title}</h2>
+ <p>${info}</p></div><div class="scatterplot-editor"></div><script type="text/javascript">
$(function(){
- <%
- # optionally, bootstrap data from dprov
- data = None
- ##data = list( hda.datatype.dataset_column_dataprovider( hda, limit=10000 ) )
- %>
- var hda = ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ) )};
-
- var editor = new ScatterplotConfigEditor({
- el : $( '.scatterplot-editor' ).attr( 'id', 'scatterplot-editor-hda-' + hda.id ),
- config : ${h.to_json_string( query_args )},
- dataset : ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ) )}
- }).render();
+ var model = new ScatterplotModel( ${h.to_json_string( config )} ),
+ hdaJson = ${h.to_json_string( hda_dict )},
+ editor = new ScatterplotConfigEditor({
+ el : $( '.scatterplot-editor' ).attr( 'id', 'scatterplot-editor-hda-' + hdaJson.id ),
+ model : model,
+ dataset : hdaJson
+ }).render();
window.editor = editor;
// uncomment to auto render for development
//$( '.render-button:visible' ).click();
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 lib/galaxy/app.py
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -87,9 +87,9 @@
load_genome_index_tools( self.toolbox )
# visualizations registry: associates resources with visualizations, controls how to render
self.visualizations_registry = None
- if self.config.visualizations_plugins_directory:
+ if self.config.visualization_plugins_directory:
self.visualizations_registry = VisualizationsRegistry( self,
- directories_setting=self.config.visualizations_plugins_directory,
+ directories_setting=self.config.visualization_plugins_directory,
template_cache_dir=self.config.template_cache )
# Load security policy.
self.security_agent = self.model.security_agent
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -343,7 +343,7 @@
self.fluent_host = kwargs.get( 'fluent_host', 'localhost' )
self.fluent_port = int( kwargs.get( 'fluent_port', 24224 ) )
# visualization plugin framework
- self.visualizations_plugins_directory = kwargs.get( 'visualizations_plugins_directory', None )
+ self.visualization_plugins_directory = kwargs.get( 'visualization_plugins_directory', None )
@property
def sentry_dsn_public( self ):
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -38,6 +38,61 @@
user_pref for ordering/ex/inclusion of particular visualizations
"""
+# ------------------------------------------------------------------- misc
+#TODO: move to utils?
+def getattr_recursive( item, attr_key, *args ):
+ """
+ Allows dot member notation in attribute name when getting an item's attribute.
+
+ NOTE: also searches dictionaries
+ """
+ #print '\n\t getattr_recursive:', item, attr_key
+ using_default = len( args ) >= 1
+ default = args[0] if using_default else None
+ #print '\t defaults:', using_default, default
+
+ for attr_key in attr_key.split( '.' ):
+ try:
+ #print '\t\t attr:', attr_key, 'item:', item
+ if isinstance( item, dict ):
+ item = item.__getitem__( attr_key )
+ else:
+ item = getattr( item, attr_key )
+
+ except ( KeyError, AttributeError ), err:
+ #print '\t\t error:', err
+ if using_default:
+ #print '\t\t\t default:', default
+ return default
+ raise
+
+ return item
+
+def hasattr_recursive( item, attr_key ):
+ """
+ Allows dot member notation in attribute name when getting an item's attribute.
+
+ NOTE: also searches dictionaries
+ """
+ if '.' in attr_key:
+ attr_key, last_key = attr_key.rsplit( '.', 1 )
+ item = getattr_recursive( item, attr_key, None )
+ if item is None:
+ return False
+ attr_key = last_key
+
+ try:
+ #print '\t\t attr:', attr_key, 'item:', item
+ if isinstance( item, dict ):
+ return item.__contains__( attr_key )
+ else:
+ return hasattr( item, attr_key )
+
+ except ( KeyError, AttributeError ), err:
+ return False
+
+ return True
+
# ------------------------------------------------------------------- the registry
class VisualizationsRegistry( pluginframework.PageServingPluginManager ):
"""
@@ -141,21 +196,26 @@
`visualization_name` if it's applicable to `target_object` or
`None` if it's not.
"""
+ #log.debug( 'VisReg.get_visualization: %s, %s', visualization_name, target_object )
visualization = self.plugins.get( visualization_name, None )
if not visualization:
return None
data_sources = visualization.config[ 'data_sources' ]
for data_source in data_sources:
+ #log.debug( 'data_source: %s', data_source )
# currently a model class is required
model_class = data_source[ 'model_class' ]
+ #log.debug( '\t model_class: %s', model_class )
if not isinstance( target_object, model_class ):
continue
+ #log.debug( '\t passed model_class' )
# tests are optional - default is the above class test
tests = data_source[ 'tests' ]
if tests and not self.is_object_applicable( trans, target_object, tests ):
continue
+ #log.debug( '\t passed tests' )
param_data = data_source[ 'to_params' ]
url = self.get_visualization_url( trans, target_object, visualization_name, param_data )
@@ -199,7 +259,7 @@
#NOTE: tests are OR'd, if any test passes - the visualization can be applied
if test_fn( target_object, test_result ):
- #log.debug( 'test passed' )
+ #log.debug( '\t test passed' )
return True
return False
@@ -212,6 +272,8 @@
#precondition: the target_object should be usable by the visualization (accrd. to data_sources)
# convert params using vis.data_source.to_params
params = self.get_url_params( trans, target_object, param_data )
+ #for param in params:
+ # print param
# we want existing visualizations to work as normal but still be part of the registry (without mod'ing)
# so generate their urls differently
@@ -238,13 +300,20 @@
# one or the other is needed
# assign takes precedence (goes last, overwrites)?
#NOTE this is only one level
- if target_attr and hasattr( target_object, target_attr ):
- params[ to_param_name ] = getattr( target_object, target_attr )
+
+ #print 'target_object:', target_object
+ #print 'target_attr:', target_attr
+
+ if target_attr and hasattr_recursive( target_object, target_attr ):
+ params[ to_param_name ] = getattr_recursive( target_object, target_attr )
+ #print 'params[ %s ]:' %( to_param_name ), params[ to_param_name ]
+
if assign:
params[ to_param_name ] = assign
#NOTE!: don't expose raw ids: encode id, _id
if params:
+#TODO: double encodes if from config
params = trans.security.encode_dict_ids( params )
return params
@@ -407,6 +476,7 @@
# these are the allowed classes to associate visualizations with (as strings)
# any model_class element not in this list will throw a parsing ParsingExcepion
ALLOWED_MODEL_CLASSES = [
+ 'Visualization',
'HistoryDatasetAssociation',
'LibraryDatasetDatasetAssociation'
]
@@ -683,6 +753,9 @@
If param is required and not present, raises a `KeyError`.
"""
+ # first parse any params from any visualizations that were passed
+ query_params = self.get_params_from_visualization_param( trans, controller, param_config_dict, query_params )
+
# parse the modifiers first since they modify the params coming next
#TODO: this is all really for hda_ldda - which we could replace with model polymorphism
params_that_modify_other_params = self.parse_parameter_modifiers(
@@ -761,6 +834,44 @@
# (and adding this code to the xml parser)
return self.parse_parameter( trans, param_config, default )
+ def get_params_from_visualization_param( self, trans, controller, param_config_dict, query_params ):
+ log.debug( 'parse_visualization_params: %s', param_config_dict )
+ log.debug( ' : %s', query_params )
+
+ # first, find the visualization in the parameters if any
+ visualization = None
+ #precondition: assume one visualization
+ for param_name, param_config in param_config_dict.items():
+ if param_config.get( 'type' ) == 'visualization':
+ query_val = query_params.get( param_name )
+ if query_val is None:
+ continue
+
+ log.debug( 'found visualization param: %s, %s', param_name, query_val )
+ visualization = self.parse_parameter( trans, controller, param_config, query_val )
+ if visualization:
+ break
+
+ # if no vis is found, can't get any new params from it: return the original query_params
+ if not visualization:
+ log.debug( 'visualization not found' )
+ return query_params
+ log.debug( 'found visualization: %s', visualization )
+
+ # next, attempt to copy any params from the visualizations config
+ visualization_config = visualization.latest_revision.config
+ log.debug( '\t config: %s', visualization_config )
+ params_from_visualization = {}
+ for param_name, param_config in param_config_dict.items():
+ if param_name in visualization_config:
+ params_from_visualization[ param_name ] = visualization_config[ param_name ]
+ log.debug( 'params_from_visualization: %s', params_from_visualization )
+
+ # layer the query_params over the params from the visualization, returning the combined
+ params_from_visualization.update( query_params )
+ return params_from_visualization
+
+#TODO: make parse_visualization separate
def parse_parameter( self, trans, controller, expected_param_data, query_param,
recurse=True, param_modifiers=None ):
"""
@@ -808,6 +919,7 @@
#TODO: subclass here?
elif param_type == 'visualization':
encoded_visualization_id = query_param
+ log.debug( 'visualization param, id : %s', encoded_visualization_id )
#TODO:?? some fallback if there's no get_X in controller that's passed?
parsed_param = controller.get_visualization( trans, encoded_visualization_id,
check_ownership=False, check_accessible=True )
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 static/scripts/mvc/dataset/hda-edit.js
--- a/static/scripts/mvc/dataset/hda-edit.js
+++ b/static/scripts/mvc/dataset/hda-edit.js
@@ -248,7 +248,6 @@
classes : 'dataset-visualize-btn',
faIcon : 'fa-bar-chart-o'
});
- $icon.addClass( 'visualize-icon' ); // needed?
// No need for popup menu because there's a single visualization.
if( _.keys( visualizations ).length === 1 ) {
@@ -259,9 +258,21 @@
} else {
var popup_menu_options = [];
_.each( visualizations, function( linkData ) {
+ linkData.func = function(){
+ if( Galaxy.frame.active ){
+ Galaxy.frame.add({
+ title : "Visualization",
+ type : "url",
+ content : linkData.href
+ });
+ return false;
+ }
+ return true;
+ };
popup_menu_options.push( linkData );
+ return false;
});
- var popup = new PopupMenu( $icon, popup_menu_options );
+ PopupMenu.create( $icon, popup_menu_options );
}
return $icon;
},
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -359,6 +359,10 @@
return 'PopupMenu';
}
});
+/** shortcut to new for when you don't need to preserve the ref */
+PopupMenu.create = function _create( $button, options ){
+ return new PopupMenu( $button, options );
+};
// -----------------------------------------------------------------------------
// the following class functions are bridges from the original make_popupmenu and make_popup_menus
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 static/scripts/mvc/visualization/scatterplotControlForm.js
--- /dev/null
+++ b/static/scripts/mvc/visualization/scatterplotControlForm.js
@@ -0,0 +1,631 @@
+/* =============================================================================
+todo:
+ I'd like to move the svg creation out of the splot constr. to:
+ allow adding splots to an existing canvas
+ allow mult. splots sharing a canvas
+
+
+ outside this:
+ BUG: setting width, height in plot controls doesn't re-interpolate data locations!!
+ BUG?: get metadata_column_names (from datatype if necessary)
+ BUG: single vis in popupmenu should have tooltip with that name NOT 'Visualizations'
+
+ wire label setters, anim setter
+
+ TwoVarScatterplot:
+ ??: maybe better to do this with a canvas...
+ save as visualization
+ to seperate file?
+ remove underscore dependencies
+ add interface to change values (seperate)?
+ download svg -> base64 encode
+ incorporate glyphs, glyph state renderers
+
+ ScatterplotSettingsForm:
+ some css bug that lowers the width of settings form when plot-controls tab is open
+ causes chart to shift
+ what can be abstracted/reused for other graphs?
+ avoid direct manipulation of this.plot
+ allow option to put plot into seperate tab of interface (for small multiples)
+
+ provide callback in view to load data incrementally - for large sets
+ paginate
+ handle rerender
+ use endpoint (here and on the server (fileptr))
+ fetch (new?) data
+ handle rerender
+ use d3.TSV?
+ render warning on long data (> maxDataPoints)
+ adjust endpoint
+
+ selectable list of preset column comparisons (rnaseq etc.)
+ how to know what sort of Tabular the data is?
+ smarter about headers
+ validate columns selection (here or server)
+
+ set stats column names by selected columns
+ move chart into tabbed area...
+
+ Scatterplot.mako:
+ multiple plots on one page (small multiples)
+ ?? ensure svg styles thru d3 or css?
+ d3: configable (easily)
+ css: standard - better maintenance
+ ? override at config
+
+============================================================================= */
+/**
+ * Scatterplot control UI as a backbone view
+ * handles:
+ * getting the desired data
+ * configuring the plot display
+ * showing (general) statistics
+ *
+ * initialize attributes REQUIRES a dataset and an apiDatasetsURL
+ */
+var ScatterplotControlForm = Backbone.View.extend( LoggableMixin ).extend({
+ //logger : console,
+ className : 'scatterplot-control-form',
+
+ //NOTE: should include time needed to render
+ dataLoadDelay : 4000,
+ dataLoadSize : 5000,
+
+ loadingIndicatorImage : 'loading_small_white_bg.gif',
+ fetchMsg : 'Fetching data...',
+ renderMsg : 'Rendering...',
+
+ initialize : function( attributes ){
+ this.log( this + '.initialize, attributes:', attributes );
+
+ this.dataset = null;
+ this.chartConfig = null;
+ this.chart = null;
+ this.loader = null;
+
+ // set up refs to the four tab areas
+ this.$dataControl = null;
+ this.$chartControl = null;
+ this.$statsDisplay = null;
+ this.$chartDisplay = null;
+
+ this.dataFetch = null;
+
+ this.initializeFromAttributes( attributes );
+ this.initializeChart( attributes );
+ this.initializeDataLoader( attributes );
+ },
+
+ initializeFromAttributes : function( attributes ){
+ // required settings: ensure certain vars we need are passed in attributes
+ if( !attributes || !attributes.dataset ){
+ throw( "ScatterplotView requires a dataset" );
+ } else {
+ this.dataset = attributes.dataset;
+ }
+ if( jQuery.type( this.dataset.metadata_column_types ) === 'string' ){
+ this.dataset.metadata_column_types = this.dataset.metadata_column_types.split( ', ' );
+ }
+ this.log( '\t dataset:', this.dataset );
+
+ // attempt to get possible headers from the data's first line
+ if( this.dataset.comment_lines && this.dataset.comment_lines.length ){
+ //TODO:??
+ var firstLine = this.dataset.comment_lines[0],
+ possibleHeaders = firstLine.split( '\t' );
+ if( possibleHeaders.length === this.dataset.metadata_column_types.length ){
+ this.possibleHeaders = possibleHeaders;
+ }
+ }
+
+ // passed from mako helper
+ //TODO: integrate to galaxyPaths
+ //TODO: ?? seems like data loader section would be better
+ if( !attributes.apiDatasetsURL ){
+ throw( "ScatterplotView requires a apiDatasetsURL" );
+ } else {
+ this.dataURL = attributes.apiDatasetsURL + '/' + this.dataset.id + '?';
+ }
+ this.log( '\t dataURL:', this.dataURL );
+ },
+
+ initializeChart : function( attributes ){
+ // set up the basic chart infrastructure and config (if any)
+ this.chartConfig = attributes.chartConfig || {};
+ //if( this.logger ){ this.chartConfig.debugging = true; }
+ this.log( '\t initial chartConfig:', this.chartConfig );
+
+ this.chart = new TwoVarScatterplot( this.chartConfig );
+ //TODO: remove 2nd ref, use this.chart.config
+ this.chartConfig = this.chart.config;
+ },
+
+ initializeDataLoader : function( attributes ){
+ // set up data loader
+ var view = this;
+ this.loader = new LazyDataLoader({
+ //logger : ( this.logger )?( this.logger ):( null ),
+ // we'll generate this when columns are chosen
+ url : null,
+ start : attributes.start || 0,
+ //NOTE: metadata_data_lines can be null (so we won't know the total)
+ total : attributes.total || this.dataset.metadata_data_lines,
+ delay : this.dataLoadDelay,
+ size : this.dataLoadSize,
+
+ buildUrl : function( start, size ){
+ // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params
+ return this.url + '&' + jQuery.param({
+ start_val: start,
+ max_vals: size
+ });
+ }
+ });
+ $( this.loader ).bind( 'error', function( event, status, error ){
+ view.log( 'ERROR:', status, error );
+ alert( 'ERROR fetching data:\n' + status + '\n' + error );
+ view.hideLoadingIndicator();
+ });
+ },
+
+ // ------------------------------------------------------------------------- CONTROLS RENDERING
+ render : function(){
+ this.log( this + '.render' );
+
+ // render the tab controls, areas and loading indicator
+ this.$el.append( ScatterplotControlForm.templates.mainLayout({
+ loadingIndicatorImagePath : galaxy_config.root + 'static/images/' + this.loadingIndicatorImage,
+ message : ''
+ }));
+
+ // render the tab content
+ this.$dataControl = this._render_dataControl();
+ this.$chartControl = this._render_chartControl();
+ this.$statsDisplay = this.$el.find( '.tab-pane#stats-display' );
+ this.$chartDisplay = this._render_chartDisplay();
+
+ // auto render if given both x, y column choices in query for page
+ //TODO:?? add autoRender=1 to query maybe?
+ if( this.chartConfig.xColumn && this.chartConfig.yColumn ){
+ this.renderChart();
+ }
+
+ // set up behaviours
+ this.$el.find( '[title]' ).tooltip();
+
+ // uncomment any of the following to have that tab show on initial load (for testing)
+ //this.$el.find( 'ul.nav' ).find( 'a[href="#data-control"]' ).tab( 'show' );
+ //this.$el.find( 'ul.nav' ).find( 'a[href="#chart-control"]' ).tab( 'show' );
+ //this.$el.find( 'ul.nav' ).find( 'a[href="#stats-display"]' ).tab( 'show' );
+ //this.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
+ return this;
+ },
+
+ _render_dataControl : function(){
+ // controls for which columns are used to plot datapoints (and ids/additional info to attach if desired)
+ var view = this,
+ allColumns = [],
+ numericColumns = [],
+ usePossibleHeaders = ( this.possibleHeaders && this.$dataControl )?
+ ( this.$dataControl.find( '#first-line-header-checkbox' ).is( ':checked' ) ):( false );
+
+ // gather column indeces (from metadata_column_types) and names (from metadata_columnnames)
+ _.each( this.dataset.metadata_column_types, function( type, index ){
+ // use a 1 based index in names/values within the form (will be dec. when parsed out)
+ var oneBasedIndex = index + 1,
+ // default name is 'column <index>'...
+ name = 'column ' + oneBasedIndex;
+
+ // ...but label with the name if available...
+ if( view.dataset.metadata_column_names ){
+ name = view.dataset.metadata_column_names[ index ];
+
+ // ...or, use the first line as headers if the user wants
+ } else if( usePossibleHeaders ){
+ name = view.possibleHeaders[ index ];
+ }
+
+ // cache all columns here
+ allColumns.push({ index: oneBasedIndex, name: name });
+
+ // filter numeric columns to their own list
+ if( type === 'int' || type === 'float' ){
+ numericColumns.push({ index: oneBasedIndex, name: name });
+ }
+ });
+ //TODO: other vals: max_vals, start_val, pagination (chart-settings)
+
+ // render the html
+ var $dataControl = this.$el.find( '.tab-pane#data-control' );
+ $dataControl.html( ScatterplotControlForm.templates.dataControl({
+ allColumns : allColumns,
+ numericColumns : numericColumns,
+ possibleHeaders : ( this.possibleHeaders )?( this.possibleHeaders.join( ', ' ) ):( '' ),
+ usePossibleHeaders : usePossibleHeaders
+ }));
+
+ if( !this.dataset.metadata_column_names && this.possibleHeaders ){
+ $dataControl.find( '#first-line-header' ).show();
+ }
+
+ // preset to column selectors if they were passed in the config in the query string
+ $dataControl.find( '#X-select' ).val( this.chartConfig.xColumn );
+ $dataControl.find( '#Y-select' ).val( this.chartConfig.yColumn );
+ if( this.chartConfig.idColumn !== undefined ){
+ $dataControl.find( '#include-id-checkbox' )
+ .attr( 'checked', true ).trigger( 'change' );
+ $dataControl.find( '#ID-select' ).val( this.chartConfig.idColumn );
+ }
+
+ return $dataControl;
+ },
+
+ _render_chartControl : function(){
+ // tab content to control how the chart is rendered (data glyph size, chart size, etc.)
+ var view = this,
+ $chartControl = this.$el.find( '.tab-pane#chart-control' ),
+ // limits for controls (by control/chartConfig id)
+ //TODO: move into TwoVarScatterplot
+ controlRanges = {
+ 'datapointSize' : { min: 2, max: 10, step: 1 },
+ 'width' : { min: 200, max: 800, step: 20 },
+ 'height' : { min: 200, max: 800, step: 20 }
+ };
+
+ // render the html
+ $chartControl.append( ScatterplotControlForm.templates.chartControl( this.chartConfig ) );
+
+ // set up behaviours, js on sliders
+ $chartControl.find( '.numeric-slider-input' ).each( function(){
+ var $this = $( this ),
+ $output = $this.find( '.slider-output' ),
+ $slider = $this.find( '.slider' ),
+ id = $this.attr( 'id' );
+ //chartControl.log( 'slider set up', 'this:', $this, 'slider:', $slider, 'id', id );
+
+ // what to do when the slider changes: update display and update chartConfig
+ //TODO: move out of loop
+ function onSliderChange(){
+ var $this = $( this ),
+ newValue = $this.slider( 'value' );
+ //chartControl.log( 'slider change', 'this:', $this, 'output:', $output, 'value', newValue );
+ $output.text( newValue );
+ //chartControl.chartConfig[ id ] = newValue;
+ }
+
+ $slider.slider( _.extend( controlRanges[ id ], {
+ value : view.chartConfig[ id ],
+ change : onSliderChange,
+ slide : onSliderChange
+ }));
+ });
+
+ return $chartControl;
+ },
+
+ _render_chartDisplay : function(){
+ // render the tab content where the chart is displayed (but not the chart itself)
+ var $chartDisplay = this.$el.find( '.tab-pane#chart-display' );
+ $chartDisplay.append( ScatterplotControlForm.templates.chartDisplay( this.chartConfig ) );
+ return $chartDisplay;
+ },
+
+ // ------------------------------------------------------------------------- EVENTS
+ events : {
+ 'change #include-id-checkbox' : 'toggleThirdColumnSelector',
+ 'change #first-line-header-checkbox' : 'rerenderDataControl',
+ 'click #data-control #render-button' : 'renderChart',
+ 'click #chart-control #render-button' : 'changeChartSettings'
+ },
+
+ toggleThirdColumnSelector : function(){
+ // show/hide the id selector on the data settings panel
+ this.$el.find( 'select[name="ID"]' ).parent().toggle();
+ },
+
+ rerenderDataControl : function(){
+ this.$dataControl = this._render_dataControl();
+ },
+
+ showLoadingIndicator : function( message, callback ){
+ // display the loading indicator over the tab panels if hidden, update message (if passed)
+ message = message || '';
+ var indicator = this.$el.find( 'div#loading-indicator' );
+ messageBox = indicator.find( '.loading-message' );
+
+ if( indicator.is( ':visible' ) ){
+ if( message ){
+ messageBox.fadeOut( 'fast', function(){
+ messageBox.text( message );
+ messageBox.fadeIn( 'fast', callback );
+ });
+ } else {
+ callback();
+ }
+
+ } else {
+ if( message ){ messageBox.text( message ); }
+ indicator.fadeIn( 'fast', callback );
+ }
+ },
+
+ hideLoadingIndicator : function( callback ){
+ this.$el.find( 'div#loading-indicator' ).fadeOut( 'fast', callback );
+ },
+
+ // ------------------------------------------------------------------------- CHART/STATS RENDERING
+ renderChart : function(){
+ // fetch the data, (re-)render the chart
+ this.log( this + '.renderChart' );
+
+ //TODO: separate data fetch
+
+ // this is a complete re-render, so clear the prev. data
+ this.data = null;
+ this.meta = null;
+
+ // update the chartConfig (here and chart) using chart settings
+ //TODO: separate and improve (used in changeChartSettings too)
+ _.extend( this.chartConfig, this.getChartSettings() );
+ this.log( '\t chartConfig:', this.chartConfig );
+ this.chart.updateConfig( this.chartConfig, false );
+
+ // build the url with the current data settings
+ this.loader.url = this.dataURL + '&' + jQuery.param( this.getDataSettings() );
+ this.log( '\t loader: total lines:', this.loader.total, ' url:', this.loader.url );
+
+ // bind the new data event to: aggregate data, update the chart and stats with new data
+ var view = this;
+ $( this.loader ).bind( 'loaded.new', function( event, response ){
+ view.log( view + ' loaded.new', response );
+
+ // aggregate data and meta
+ view.postProcessDataFetchResponse( response );
+ view.log( '\t postprocessed data:', view.data );
+ view.log( '\t postprocessed meta:', view.meta );
+
+ // update the chart and stats
+ view.showLoadingIndicator( view.renderMsg, function(){
+ view.chart.render( view.data, view.meta );
+ view.renderStats( view.data, view.meta );
+ view.hideLoadingIndicator();
+ });
+ });
+ // when all data loaded - unbind (or we'll start doubling event handlers)
+ $( this.loader ).bind( 'complete', function( event, data ){
+ view.log( view + ' complete', data );
+ $( view.loader ).unbind();
+ });
+
+ // begin loading the data, switch to the chart display tab
+ view.showLoadingIndicator( view.fetchMsg, function(){
+ view.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
+ view.loader.load();
+ });
+ },
+
+ renderStats : function(){
+ this.log( this + '.renderStats' );
+ // render the stats table in the stats panel
+ //TODO: there's a better way
+ this.$statsDisplay.html( ScatterplotControlForm.templates.statsDisplay({
+ stats: [
+ { name: 'Count', xval: this.meta[0].count, yval: this.meta[1].count },
+ { name: 'Min', xval: this.meta[0].min, yval: this.meta[1].min },
+ { name: 'Max', xval: this.meta[0].max, yval: this.meta[1].max },
+ { name: 'Sum', xval: this.meta[0].sum, yval: this.meta[1].sum },
+ { name: 'Mean', xval: this.meta[0].mean, yval: this.meta[1].mean },
+ { name: 'Median', xval: this.meta[0].median, yval: this.meta[1].median }
+ ]
+ }));
+ },
+
+ changeChartSettings : function(){
+ // re-render the chart with new chart settings and OLD data
+ var view = this;
+ newChartSettings = this.getChartSettings();
+
+ // update the chart config from the chartSettings panel controls
+ _.extend( this.chartConfig, newChartSettings );
+ this.log( 'this.chartConfig:', this.chartConfig );
+ this.chart.updateConfig( this.chartConfig, false );
+
+ // if there's current data, call chart.render with it (no data fetch)
+ if( view.data && view.meta ){
+ view.showLoadingIndicator( view.renderMsg, function(){
+ view.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
+ view.chart.render( view.data, view.meta );
+ view.hideLoadingIndicator();
+ });
+
+ // no current data, call renderChart instead (which will fetch data)
+ } else {
+ this.renderChart();
+ }
+ },
+
+ // ------------------------------------------------------------------------- DATA AGGREGATION
+ postProcessDataFetchResponse : function( response ){
+ // the loader only returns new data - it's up to this to munge the fetches together properly
+ //TODO: we're now storing data in two places: loader and here
+ // can't we reduce incoming data into loader.data[0]? are there concurrency problems?
+ this.postProcessData( response.data );
+ this.postProcessMeta( response.meta );
+ },
+
+ postProcessData : function( newData ){
+ // stack the column data on top of each other into this.data
+ //this.log( this + '.postProcessData:', newData );
+ var view = this;
+
+ // if we already have data: aggregate
+ if( view.data ){
+ _.each( newData, function( newColData, colIndex ){
+ //view.log( colIndex + ' data:', newColData );
+ //TODO??: time, space efficiency of this?
+ view.data[ colIndex ] = view.data[ colIndex ].concat( newColData );
+ });
+
+ // otherwise: assign (first load)
+ } else {
+ view.data = newData;
+ }
+ },
+
+ postProcessMeta : function( newMeta ){
+ // munge the meta data (stats) from the server fetches together
+ //pre: this.data must be preprocessed (needed for medians)
+ //this.log( this + '.postProcessMeta:', newMeta );
+ var view = this,
+ colTypes = this.dataset.metadata_column_types;
+
+ // if we already have meta: aggregate
+ if( view.meta ){
+ _.each( newMeta, function( newColMeta, colIndex ){
+ var colMeta = view.meta[ colIndex ],
+ colType = colTypes[ colIndex ];
+ //view.log( '\t ' + colIndex + ' postprocessing meta:', newColMeta );
+ //view.log( colIndex + ' old meta:',
+ // 'min:', colMeta.min,
+ // 'max:', colMeta.max,
+ // 'sum:', colMeta.sum,
+ // 'mean:', colMeta.mean,
+ // 'median:', colMeta.median
+ //);
+
+ //!TODO: at what point are we getting int/float overflow on these?!
+ //??: need to be null safe?
+ colMeta.count += ( newColMeta.count )?( newColMeta.count ):( 0 );
+ //view.log( colIndex, 'count:', colMeta.count );
+
+ if( ( colType === 'int' ) || ( colType === 'float' ) ){
+ //view.log( colIndex + ' incoming meta:',
+ // 'min:', newColMeta.min,
+ // 'max:', newColMeta.max,
+ // 'sum:', newColMeta.sum,
+ // 'mean:', newColMeta.mean,
+ // 'median:', newColMeta.median
+ //);
+
+ colMeta.min = Math.min( newColMeta.min, colMeta.min );
+ colMeta.max = Math.max( newColMeta.max, colMeta.max );
+ colMeta.sum = newColMeta.sum + colMeta.sum;
+ colMeta.mean = ( colMeta.count )?( colMeta.sum / colMeta.count ):( null );
+
+ // median's a pain bc of sorting (requires the data as well)
+ var sortedCol = view.data[ colIndex ].slice().sort(),
+ middleIndex = Math.floor( sortedCol.length / 2 );
+
+ if( sortedCol.length % 2 === 0 ){
+ colMeta.median = ( ( sortedCol[ middleIndex ] + sortedCol[( middleIndex + 1 )] ) / 2 );
+
+ } else {
+ colMeta.median = sortedCol[ middleIndex ];
+ }
+
+ //view.log( colIndex + ' new meta:',
+ // 'min:', colMeta.min,
+ // 'max:', colMeta.max,
+ // 'sum:', colMeta.sum,
+ // 'mean:', colMeta.mean,
+ // 'median:', colMeta.median
+ //);
+ }
+ });
+
+ // otherwise: assign (first load)
+ } else {
+ view.meta = newMeta;
+ //view.log( '\t meta (first load):', view.meta );
+ }
+ },
+
+ // ------------------------------------------------------------------------- GET DATA/CHART SETTINGS
+ getDataSettings : function(){
+ // parse the column values for both indeces (for the data fetch) and names (for the chart)
+ var columnSelections = this.getColumnSelections(),
+ columns = [];
+ this.log( '\t columnSelections:', columnSelections );
+
+ //TODO: validate columns - minimally: we can assume either set by selectors or via a good query string
+
+ // get column indices for params, include the desired ID column (if any)
+ //NOTE: these are presented in human-readable 1 base index (to match the data.peek) - adjust
+ columns = [
+ columnSelections.X.colIndex - 1,
+ columnSelections.Y.colIndex - 1
+ ];
+ if( this.$dataControl.find( '#include-id-checkbox' ).attr( 'checked' ) ){
+ columns.push( columnSelections.ID.colIndex - 1 );
+ }
+ //TODO: other vals: max, start, page
+
+ var params = {
+ data_type : 'raw_data',
+ provider : 'column_with_stats',
+ columns : '[' + columns + ']'
+ };
+ this.log( '\t data settings (url params):', params );
+ return params;
+ },
+
+ getColumnSelections : function(){
+ // gets the current user-selected values for which columns to fetch from the data settings panel
+ // returns a map: { column-select name (eg. X) : { colIndex : column-selector val,
+ // colName : selected option text }, ... }
+ var selections = {};
+ this.$dataControl.find( 'div.column-select select' ).each( function(){
+ var $this = $( this ),
+ val = $this.val();
+ selections[ $this.attr( 'name' ) ] = {
+ colIndex : val,
+ colName : $this.children( '[value="' + val + '"]' ).text()
+ };
+ });
+ return selections;
+ },
+
+ getChartSettings : function(){
+ // gets the user-selected chartConfig from the chart settings panel
+ var settings = {},
+ colSelections = this.getColumnSelections();
+ //this.log( 'colSelections:', colSelections );
+
+ //TODO: simplify with keys and loop
+ settings.datapointSize = this.$chartControl.find( '#datapointSize.numeric-slider-input' )
+ .find( '.slider' ).slider( 'value' );
+ settings.width = this.$chartControl.find( '#width.numeric-slider-input' )
+ .find( '.slider' ).slider( 'value' );
+ settings.height = this.$chartControl.find( '#height.numeric-slider-input' )
+ .find( '.slider' ).slider( 'value' );
+
+ // update axes labels using chartSettings inputs (if not at defaults), otherwise the selects' colName
+ //TODO: a little confusing
+ var chartSettingsXLabel = this.$chartControl.find( 'input#X-axis-label' ).val(),
+ chartSettingsYLabel = this.$chartControl.find( 'input#Y-axis-label' ).val();
+ settings.xLabel = ( chartSettingsXLabel === 'X' )?
+ ( colSelections.X.colName ):( chartSettingsXLabel );
+ settings.yLabel = ( chartSettingsYLabel === 'Y' )?
+ ( colSelections.Y.colName ):( chartSettingsYLabel );
+
+ settings.animDuration = ( this.$chartControl.find( '#animate-chart' ).is( ':checked' ) )?
+ ( this.chart.defaults.animDuration ):( 0 );
+
+ this.log( '\t chartSettings:', settings );
+ return settings;
+ },
+
+ toString : function(){
+ return 'ScatterplotControlForm(' + (( this.dataset )?( this.dataset.id ):( '' )) + ')';
+ }
+});
+
+ScatterplotControlForm.templates = {
+ mainLayout : Handlebars.templates[ 'template-visualization-scatterplotControlForm' ],
+ dataControl : Handlebars.templates[ 'template-visualization-dataControl' ],
+ chartControl : Handlebars.templates[ 'template-visualization-chartControl' ],
+ statsDisplay : Handlebars.templates[ 'template-visualization-statsDisplay' ],
+ chartDisplay : Handlebars.templates[ 'template-visualization-chartDisplay' ]
+};
+
+//==============================================================================
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 static/scripts/mvc/visualization/visualization-model.js
--- /dev/null
+++ b/static/scripts/mvc/visualization/visualization-model.js
@@ -0,0 +1,158 @@
+//define([
+//], function(){
+
+//function saveVis( title, config ){
+// var xhr = jQuery.ajax( '/api/visualizations', {
+// type : 'POST',
+// data : {
+// type : 'scatterplot',
+// title : title,
+// config : JSON.stringify( config )
+// }
+// });
+// xhr.fail( function( xhr, status, message ){
+// console.debug( jQuery.makeArray( arguments ) );
+// console.error( 'Error saving visualization:', xhr.responseJSON.error );
+// });
+// return xhr.then( function( saveInfo ){
+// return saveInfo;
+// });
+//}
+
+//==============================================================================
+/** @class Model for a saved Galaxy visualization.
+ *
+ * @augments Backbone.Model
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var Visualization = Backbone.Model.extend( LoggableMixin ).extend(
+/** @lends Visualization.prototype */{
+
+ ///** logger used to record this.log messages, commonly set to console */
+ //// comment this out to suppress log output
+ //logger : console,
+
+ /** default attributes for a model */
+ defaults : {
+ //id : null,
+ //type : null,
+ //title : null,
+ //dbkey : null,
+ //user_id : null,
+ //slug : null,
+ //revisions : [],
+ //latest_revision : null
+
+ //(this is unusual in that visualizations don't have configs, revisions do)
+ //config : {}
+ },
+
+ url : function(){
+ return galaxy_config.root + 'api/visualizations';
+ },
+
+ /** Set up the model, determine if accessible, bind listeners
+ * @see Backbone.Model#initialize
+ */
+ initialize : function( data ){
+ this.log( this + '.initialize', data, this.attributes );
+ this._setUpListeners();
+ },
+
+ /** set up any event listeners
+ */
+ _setUpListeners : function(){
+ },
+
+ // ........................................................................ config
+ setConfig: function( config ){
+ var oldConfig = this.get( 'config' );
+ // extend if already exists (and clone in order to trigger change)
+ if( _.isObject( oldConfig ) ){
+ config = _.extend( _.clone( oldConfig ), config );
+ }
+ this.set( 'config', config );
+ return this;
+ },
+
+ // ........................................................................ common queries
+ // ........................................................................ ajax
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ var idAndTitle = this.get( 'id' ) || '';
+ if( this.get( 'title' ) ){
+ idAndTitle += ':' + this.get( 'title' );
+ }
+ return 'Visualization(' + idAndTitle + ')';
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection of visualization models
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var VisualizationCollection = Backbone.Collection.extend( LoggableMixin ).extend(
+/** @lends VisualizationCollection.prototype */{
+ model : Visualization,
+
+ ///** logger used to record this.log messages, commonly set to console */
+ //// comment this out to suppress log output
+ //logger : console,
+
+ url : function(){
+ return galaxy_config.root + 'api/visualizations';
+ },
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ //this._setUpListeners();
+ },
+
+ //_setUpListeners : function(){
+ //},
+
+ // ........................................................................ common queries
+ // ........................................................................ ajax
+ // ........................................................................ misc
+ set : function( models, options ){
+ // arrrrrrrrrrrrrrrrrg...
+ // override to get a correct/smarter merge when incoming data is partial (e.g. stupid backbone)
+ // w/o this partial models from the server will fill in missing data with model defaults
+ // and overwrite existing data on the client
+ // see Backbone.Collection.set and _prepareModel
+ var collection = this;
+ models = _.map( models, function( model ){
+ var existing = collection.get( model.id );
+ if( !existing ){ return model; }
+
+ // merge the models _BEFORE_ calling the superclass version
+ var merged = existing.toJSON();
+ _.extend( merged, model );
+ return merged;
+ });
+ // now call superclass when the data is filled
+ Backbone.Collection.prototype.set.call( this, models, options );
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'VisualizationCollection(', [ this.historyId, this.length ].join(), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+//return {
+// Visualization : Visualization,
+// VisualizationCollection : VisualizationCollection
+//};});
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 static/scripts/mvc/visualizations/scatterplotControlForm.js
--- a/static/scripts/mvc/visualizations/scatterplotControlForm.js
+++ /dev/null
@@ -1,631 +0,0 @@
-/* =============================================================================
-todo:
- I'd like to move the svg creation out of the splot constr. to:
- allow adding splots to an existing canvas
- allow mult. splots sharing a canvas
-
-
- outside this:
- BUG: setting width, height in plot controls doesn't re-interpolate data locations!!
- BUG?: get metadata_column_names (from datatype if necessary)
- BUG: single vis in popupmenu should have tooltip with that name NOT 'Visualizations'
-
- wire label setters, anim setter
-
- TwoVarScatterplot:
- ??: maybe better to do this with a canvas...
- save as visualization
- to seperate file?
- remove underscore dependencies
- add interface to change values (seperate)?
- download svg -> base64 encode
- incorporate glyphs, glyph state renderers
-
- ScatterplotSettingsForm:
- some css bug that lowers the width of settings form when plot-controls tab is open
- causes chart to shift
- what can be abstracted/reused for other graphs?
- avoid direct manipulation of this.plot
- allow option to put plot into seperate tab of interface (for small multiples)
-
- provide callback in view to load data incrementally - for large sets
- paginate
- handle rerender
- use endpoint (here and on the server (fileptr))
- fetch (new?) data
- handle rerender
- use d3.TSV?
- render warning on long data (> maxDataPoints)
- adjust endpoint
-
- selectable list of preset column comparisons (rnaseq etc.)
- how to know what sort of Tabular the data is?
- smarter about headers
- validate columns selection (here or server)
-
- set stats column names by selected columns
- move chart into tabbed area...
-
- Scatterplot.mako:
- multiple plots on one page (small multiples)
- ?? ensure svg styles thru d3 or css?
- d3: configable (easily)
- css: standard - better maintenance
- ? override at config
-
-============================================================================= */
-/**
- * Scatterplot control UI as a backbone view
- * handles:
- * getting the desired data
- * configuring the plot display
- * showing (general) statistics
- *
- * initialize attributes REQUIRES a dataset and an apiDatasetsURL
- */
-var ScatterplotControlForm = Backbone.View.extend( LoggableMixin ).extend({
- //logger : console,
- className : 'scatterplot-control-form',
-
- //NOTE: should include time needed to render
- dataLoadDelay : 4000,
- dataLoadSize : 5000,
-
- loadingIndicatorImage : 'loading_small_white_bg.gif',
- fetchMsg : 'Fetching data...',
- renderMsg : 'Rendering...',
-
- initialize : function( attributes ){
- this.log( this + '.initialize, attributes:', attributes );
-
- this.dataset = null;
- this.chartConfig = null;
- this.chart = null;
- this.loader = null;
-
- // set up refs to the four tab areas
- this.$dataControl = null;
- this.$chartControl = null;
- this.$statsDisplay = null;
- this.$chartDisplay = null;
-
- this.dataFetch = null;
-
- this.initializeFromAttributes( attributes );
- this.initializeChart( attributes );
- this.initializeDataLoader( attributes );
- },
-
- initializeFromAttributes : function( attributes ){
- // required settings: ensure certain vars we need are passed in attributes
- if( !attributes || !attributes.dataset ){
- throw( "ScatterplotView requires a dataset" );
- } else {
- this.dataset = attributes.dataset;
- }
- if( jQuery.type( this.dataset.metadata_column_types ) === 'string' ){
- this.dataset.metadata_column_types = this.dataset.metadata_column_types.split( ', ' );
- }
- this.log( '\t dataset:', this.dataset );
-
- // attempt to get possible headers from the data's first line
- if( this.dataset.comment_lines && this.dataset.comment_lines.length ){
- //TODO:??
- var firstLine = this.dataset.comment_lines[0],
- possibleHeaders = firstLine.split( '\t' );
- if( possibleHeaders.length === this.dataset.metadata_column_types.length ){
- this.possibleHeaders = possibleHeaders;
- }
- }
-
- // passed from mako helper
- //TODO: integrate to galaxyPaths
- //TODO: ?? seems like data loader section would be better
- if( !attributes.apiDatasetsURL ){
- throw( "ScatterplotView requires a apiDatasetsURL" );
- } else {
- this.dataURL = attributes.apiDatasetsURL + '/' + this.dataset.id + '?';
- }
- this.log( '\t dataURL:', this.dataURL );
- },
-
- initializeChart : function( attributes ){
- // set up the basic chart infrastructure and config (if any)
- this.chartConfig = attributes.chartConfig || {};
- //if( this.logger ){ this.chartConfig.debugging = true; }
- this.log( '\t initial chartConfig:', this.chartConfig );
-
- this.chart = new TwoVarScatterplot( this.chartConfig );
- //TODO: remove 2nd ref, use this.chart.config
- this.chartConfig = this.chart.config;
- },
-
- initializeDataLoader : function( attributes ){
- // set up data loader
- var view = this;
- this.loader = new LazyDataLoader({
- //logger : ( this.logger )?( this.logger ):( null ),
- // we'll generate this when columns are chosen
- url : null,
- start : attributes.start || 0,
- //NOTE: metadata_data_lines can be null (so we won't know the total)
- total : attributes.total || this.dataset.metadata_data_lines,
- delay : this.dataLoadDelay,
- size : this.dataLoadSize,
-
- buildUrl : function( start, size ){
- // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params
- return this.url + '&' + jQuery.param({
- start_val: start,
- max_vals: size
- });
- }
- });
- $( this.loader ).bind( 'error', function( event, status, error ){
- view.log( 'ERROR:', status, error );
- alert( 'ERROR fetching data:\n' + status + '\n' + error );
- view.hideLoadingIndicator();
- });
- },
-
- // ------------------------------------------------------------------------- CONTROLS RENDERING
- render : function(){
- this.log( this + '.render' );
-
- // render the tab controls, areas and loading indicator
- this.$el.append( ScatterplotControlForm.templates.mainLayout({
- loadingIndicatorImagePath : galaxy_config.root + 'static/images/' + this.loadingIndicatorImage,
- message : ''
- }));
-
- // render the tab content
- this.$dataControl = this._render_dataControl();
- this.$chartControl = this._render_chartControl();
- this.$statsDisplay = this.$el.find( '.tab-pane#stats-display' );
- this.$chartDisplay = this._render_chartDisplay();
-
- // auto render if given both x, y column choices in query for page
- //TODO:?? add autoRender=1 to query maybe?
- if( this.chartConfig.xColumn && this.chartConfig.yColumn ){
- this.renderChart();
- }
-
- // set up behaviours
- this.$el.find( '[title]' ).tooltip();
-
- // uncomment any of the following to have that tab show on initial load (for testing)
- //this.$el.find( 'ul.nav' ).find( 'a[href="#data-control"]' ).tab( 'show' );
- //this.$el.find( 'ul.nav' ).find( 'a[href="#chart-control"]' ).tab( 'show' );
- //this.$el.find( 'ul.nav' ).find( 'a[href="#stats-display"]' ).tab( 'show' );
- //this.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
- return this;
- },
-
- _render_dataControl : function(){
- // controls for which columns are used to plot datapoints (and ids/additional info to attach if desired)
- var view = this,
- allColumns = [],
- numericColumns = [],
- usePossibleHeaders = ( this.possibleHeaders && this.$dataControl )?
- ( this.$dataControl.find( '#first-line-header-checkbox' ).is( ':checked' ) ):( false );
-
- // gather column indeces (from metadata_column_types) and names (from metadata_columnnames)
- _.each( this.dataset.metadata_column_types, function( type, index ){
- // use a 1 based index in names/values within the form (will be dec. when parsed out)
- var oneBasedIndex = index + 1,
- // default name is 'column <index>'...
- name = 'column ' + oneBasedIndex;
-
- // ...but label with the name if available...
- if( view.dataset.metadata_column_names ){
- name = view.dataset.metadata_column_names[ index ];
-
- // ...or, use the first line as headers if the user wants
- } else if( usePossibleHeaders ){
- name = view.possibleHeaders[ index ];
- }
-
- // cache all columns here
- allColumns.push({ index: oneBasedIndex, name: name });
-
- // filter numeric columns to their own list
- if( type === 'int' || type === 'float' ){
- numericColumns.push({ index: oneBasedIndex, name: name });
- }
- });
- //TODO: other vals: max_vals, start_val, pagination (chart-settings)
-
- // render the html
- var $dataControl = this.$el.find( '.tab-pane#data-control' );
- $dataControl.html( ScatterplotControlForm.templates.dataControl({
- allColumns : allColumns,
- numericColumns : numericColumns,
- possibleHeaders : ( this.possibleHeaders )?( this.possibleHeaders.join( ', ' ) ):( '' ),
- usePossibleHeaders : usePossibleHeaders
- }));
-
- if( !this.dataset.metadata_column_names && this.possibleHeaders ){
- $dataControl.find( '#first-line-header' ).show();
- }
-
- // preset to column selectors if they were passed in the config in the query string
- $dataControl.find( '#X-select' ).val( this.chartConfig.xColumn );
- $dataControl.find( '#Y-select' ).val( this.chartConfig.yColumn );
- if( this.chartConfig.idColumn !== undefined ){
- $dataControl.find( '#include-id-checkbox' )
- .attr( 'checked', true ).trigger( 'change' );
- $dataControl.find( '#ID-select' ).val( this.chartConfig.idColumn );
- }
-
- return $dataControl;
- },
-
- _render_chartControl : function(){
- // tab content to control how the chart is rendered (data glyph size, chart size, etc.)
- var view = this,
- $chartControl = this.$el.find( '.tab-pane#chart-control' ),
- // limits for controls (by control/chartConfig id)
- //TODO: move into TwoVarScatterplot
- controlRanges = {
- 'datapointSize' : { min: 2, max: 10, step: 1 },
- 'width' : { min: 200, max: 800, step: 20 },
- 'height' : { min: 200, max: 800, step: 20 }
- };
-
- // render the html
- $chartControl.append( ScatterplotControlForm.templates.chartControl( this.chartConfig ) );
-
- // set up behaviours, js on sliders
- $chartControl.find( '.numeric-slider-input' ).each( function(){
- var $this = $( this ),
- $output = $this.find( '.slider-output' ),
- $slider = $this.find( '.slider' ),
- id = $this.attr( 'id' );
- //chartControl.log( 'slider set up', 'this:', $this, 'slider:', $slider, 'id', id );
-
- // what to do when the slider changes: update display and update chartConfig
- //TODO: move out of loop
- function onSliderChange(){
- var $this = $( this ),
- newValue = $this.slider( 'value' );
- //chartControl.log( 'slider change', 'this:', $this, 'output:', $output, 'value', newValue );
- $output.text( newValue );
- //chartControl.chartConfig[ id ] = newValue;
- }
-
- $slider.slider( _.extend( controlRanges[ id ], {
- value : view.chartConfig[ id ],
- change : onSliderChange,
- slide : onSliderChange
- }));
- });
-
- return $chartControl;
- },
-
- _render_chartDisplay : function(){
- // render the tab content where the chart is displayed (but not the chart itself)
- var $chartDisplay = this.$el.find( '.tab-pane#chart-display' );
- $chartDisplay.append( ScatterplotControlForm.templates.chartDisplay( this.chartConfig ) );
- return $chartDisplay;
- },
-
- // ------------------------------------------------------------------------- EVENTS
- events : {
- 'change #include-id-checkbox' : 'toggleThirdColumnSelector',
- 'change #first-line-header-checkbox' : 'rerenderDataControl',
- 'click #data-control #render-button' : 'renderChart',
- 'click #chart-control #render-button' : 'changeChartSettings'
- },
-
- toggleThirdColumnSelector : function(){
- // show/hide the id selector on the data settings panel
- this.$el.find( 'select[name="ID"]' ).parent().toggle();
- },
-
- rerenderDataControl : function(){
- this.$dataControl = this._render_dataControl();
- },
-
- showLoadingIndicator : function( message, callback ){
- // display the loading indicator over the tab panels if hidden, update message (if passed)
- message = message || '';
- var indicator = this.$el.find( 'div#loading-indicator' );
- messageBox = indicator.find( '.loading-message' );
-
- if( indicator.is( ':visible' ) ){
- if( message ){
- messageBox.fadeOut( 'fast', function(){
- messageBox.text( message );
- messageBox.fadeIn( 'fast', callback );
- });
- } else {
- callback();
- }
-
- } else {
- if( message ){ messageBox.text( message ); }
- indicator.fadeIn( 'fast', callback );
- }
- },
-
- hideLoadingIndicator : function( callback ){
- this.$el.find( 'div#loading-indicator' ).fadeOut( 'fast', callback );
- },
-
- // ------------------------------------------------------------------------- CHART/STATS RENDERING
- renderChart : function(){
- // fetch the data, (re-)render the chart
- this.log( this + '.renderChart' );
-
- //TODO: separate data fetch
-
- // this is a complete re-render, so clear the prev. data
- this.data = null;
- this.meta = null;
-
- // update the chartConfig (here and chart) using chart settings
- //TODO: separate and improve (used in changeChartSettings too)
- _.extend( this.chartConfig, this.getChartSettings() );
- this.log( '\t chartConfig:', this.chartConfig );
- this.chart.updateConfig( this.chartConfig, false );
-
- // build the url with the current data settings
- this.loader.url = this.dataURL + '&' + jQuery.param( this.getDataSettings() );
- this.log( '\t loader: total lines:', this.loader.total, ' url:', this.loader.url );
-
- // bind the new data event to: aggregate data, update the chart and stats with new data
- var view = this;
- $( this.loader ).bind( 'loaded.new', function( event, response ){
- view.log( view + ' loaded.new', response );
-
- // aggregate data and meta
- view.postProcessDataFetchResponse( response );
- view.log( '\t postprocessed data:', view.data );
- view.log( '\t postprocessed meta:', view.meta );
-
- // update the chart and stats
- view.showLoadingIndicator( view.renderMsg, function(){
- view.chart.render( view.data, view.meta );
- view.renderStats( view.data, view.meta );
- view.hideLoadingIndicator();
- });
- });
- // when all data loaded - unbind (or we'll start doubling event handlers)
- $( this.loader ).bind( 'complete', function( event, data ){
- view.log( view + ' complete', data );
- $( view.loader ).unbind();
- });
-
- // begin loading the data, switch to the chart display tab
- view.showLoadingIndicator( view.fetchMsg, function(){
- view.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
- view.loader.load();
- });
- },
-
- renderStats : function(){
- this.log( this + '.renderStats' );
- // render the stats table in the stats panel
- //TODO: there's a better way
- this.$statsDisplay.html( ScatterplotControlForm.templates.statsDisplay({
- stats: [
- { name: 'Count', xval: this.meta[0].count, yval: this.meta[1].count },
- { name: 'Min', xval: this.meta[0].min, yval: this.meta[1].min },
- { name: 'Max', xval: this.meta[0].max, yval: this.meta[1].max },
- { name: 'Sum', xval: this.meta[0].sum, yval: this.meta[1].sum },
- { name: 'Mean', xval: this.meta[0].mean, yval: this.meta[1].mean },
- { name: 'Median', xval: this.meta[0].median, yval: this.meta[1].median }
- ]
- }));
- },
-
- changeChartSettings : function(){
- // re-render the chart with new chart settings and OLD data
- var view = this;
- newChartSettings = this.getChartSettings();
-
- // update the chart config from the chartSettings panel controls
- _.extend( this.chartConfig, newChartSettings );
- this.log( 'this.chartConfig:', this.chartConfig );
- this.chart.updateConfig( this.chartConfig, false );
-
- // if there's current data, call chart.render with it (no data fetch)
- if( view.data && view.meta ){
- view.showLoadingIndicator( view.renderMsg, function(){
- view.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
- view.chart.render( view.data, view.meta );
- view.hideLoadingIndicator();
- });
-
- // no current data, call renderChart instead (which will fetch data)
- } else {
- this.renderChart();
- }
- },
-
- // ------------------------------------------------------------------------- DATA AGGREGATION
- postProcessDataFetchResponse : function( response ){
- // the loader only returns new data - it's up to this to munge the fetches together properly
- //TODO: we're now storing data in two places: loader and here
- // can't we reduce incoming data into loader.data[0]? are there concurrency problems?
- this.postProcessData( response.data );
- this.postProcessMeta( response.meta );
- },
-
- postProcessData : function( newData ){
- // stack the column data on top of each other into this.data
- //this.log( this + '.postProcessData:', newData );
- var view = this;
-
- // if we already have data: aggregate
- if( view.data ){
- _.each( newData, function( newColData, colIndex ){
- //view.log( colIndex + ' data:', newColData );
- //TODO??: time, space efficiency of this?
- view.data[ colIndex ] = view.data[ colIndex ].concat( newColData );
- });
-
- // otherwise: assign (first load)
- } else {
- view.data = newData;
- }
- },
-
- postProcessMeta : function( newMeta ){
- // munge the meta data (stats) from the server fetches together
- //pre: this.data must be preprocessed (needed for medians)
- //this.log( this + '.postProcessMeta:', newMeta );
- var view = this,
- colTypes = this.dataset.metadata_column_types;
-
- // if we already have meta: aggregate
- if( view.meta ){
- _.each( newMeta, function( newColMeta, colIndex ){
- var colMeta = view.meta[ colIndex ],
- colType = colTypes[ colIndex ];
- //view.log( '\t ' + colIndex + ' postprocessing meta:', newColMeta );
- //view.log( colIndex + ' old meta:',
- // 'min:', colMeta.min,
- // 'max:', colMeta.max,
- // 'sum:', colMeta.sum,
- // 'mean:', colMeta.mean,
- // 'median:', colMeta.median
- //);
-
- //!TODO: at what point are we getting int/float overflow on these?!
- //??: need to be null safe?
- colMeta.count += ( newColMeta.count )?( newColMeta.count ):( 0 );
- //view.log( colIndex, 'count:', colMeta.count );
-
- if( ( colType === 'int' ) || ( colType === 'float' ) ){
- //view.log( colIndex + ' incoming meta:',
- // 'min:', newColMeta.min,
- // 'max:', newColMeta.max,
- // 'sum:', newColMeta.sum,
- // 'mean:', newColMeta.mean,
- // 'median:', newColMeta.median
- //);
-
- colMeta.min = Math.min( newColMeta.min, colMeta.min );
- colMeta.max = Math.max( newColMeta.max, colMeta.max );
- colMeta.sum = newColMeta.sum + colMeta.sum;
- colMeta.mean = ( colMeta.count )?( colMeta.sum / colMeta.count ):( null );
-
- // median's a pain bc of sorting (requires the data as well)
- var sortedCol = view.data[ colIndex ].slice().sort(),
- middleIndex = Math.floor( sortedCol.length / 2 );
-
- if( sortedCol.length % 2 === 0 ){
- colMeta.median = ( ( sortedCol[ middleIndex ] + sortedCol[( middleIndex + 1 )] ) / 2 );
-
- } else {
- colMeta.median = sortedCol[ middleIndex ];
- }
-
- //view.log( colIndex + ' new meta:',
- // 'min:', colMeta.min,
- // 'max:', colMeta.max,
- // 'sum:', colMeta.sum,
- // 'mean:', colMeta.mean,
- // 'median:', colMeta.median
- //);
- }
- });
-
- // otherwise: assign (first load)
- } else {
- view.meta = newMeta;
- //view.log( '\t meta (first load):', view.meta );
- }
- },
-
- // ------------------------------------------------------------------------- GET DATA/CHART SETTINGS
- getDataSettings : function(){
- // parse the column values for both indeces (for the data fetch) and names (for the chart)
- var columnSelections = this.getColumnSelections(),
- columns = [];
- this.log( '\t columnSelections:', columnSelections );
-
- //TODO: validate columns - minimally: we can assume either set by selectors or via a good query string
-
- // get column indices for params, include the desired ID column (if any)
- //NOTE: these are presented in human-readable 1 base index (to match the data.peek) - adjust
- columns = [
- columnSelections.X.colIndex - 1,
- columnSelections.Y.colIndex - 1
- ];
- if( this.$dataControl.find( '#include-id-checkbox' ).attr( 'checked' ) ){
- columns.push( columnSelections.ID.colIndex - 1 );
- }
- //TODO: other vals: max, start, page
-
- var params = {
- data_type : 'raw_data',
- provider : 'column_with_stats',
- columns : '[' + columns + ']'
- };
- this.log( '\t data settings (url params):', params );
- return params;
- },
-
- getColumnSelections : function(){
- // gets the current user-selected values for which columns to fetch from the data settings panel
- // returns a map: { column-select name (eg. X) : { colIndex : column-selector val,
- // colName : selected option text }, ... }
- var selections = {};
- this.$dataControl.find( 'div.column-select select' ).each( function(){
- var $this = $( this ),
- val = $this.val();
- selections[ $this.attr( 'name' ) ] = {
- colIndex : val,
- colName : $this.children( '[value="' + val + '"]' ).text()
- };
- });
- return selections;
- },
-
- getChartSettings : function(){
- // gets the user-selected chartConfig from the chart settings panel
- var settings = {},
- colSelections = this.getColumnSelections();
- //this.log( 'colSelections:', colSelections );
-
- //TODO: simplify with keys and loop
- settings.datapointSize = this.$chartControl.find( '#datapointSize.numeric-slider-input' )
- .find( '.slider' ).slider( 'value' );
- settings.width = this.$chartControl.find( '#width.numeric-slider-input' )
- .find( '.slider' ).slider( 'value' );
- settings.height = this.$chartControl.find( '#height.numeric-slider-input' )
- .find( '.slider' ).slider( 'value' );
-
- // update axes labels using chartSettings inputs (if not at defaults), otherwise the selects' colName
- //TODO: a little confusing
- var chartSettingsXLabel = this.$chartControl.find( 'input#X-axis-label' ).val(),
- chartSettingsYLabel = this.$chartControl.find( 'input#Y-axis-label' ).val();
- settings.xLabel = ( chartSettingsXLabel === 'X' )?
- ( colSelections.X.colName ):( chartSettingsXLabel );
- settings.yLabel = ( chartSettingsYLabel === 'Y' )?
- ( colSelections.Y.colName ):( chartSettingsYLabel );
-
- settings.animDuration = ( this.$chartControl.find( '#animate-chart' ).is( ':checked' ) )?
- ( this.chart.defaults.animDuration ):( 0 );
-
- this.log( '\t chartSettings:', settings );
- return settings;
- },
-
- toString : function(){
- return 'ScatterplotControlForm(' + (( this.dataset )?( this.dataset.id ):( '' )) + ')';
- }
-});
-
-ScatterplotControlForm.templates = {
- mainLayout : Handlebars.templates[ 'template-visualization-scatterplotControlForm' ],
- dataControl : Handlebars.templates[ 'template-visualization-dataControl' ],
- chartControl : Handlebars.templates[ 'template-visualization-chartControl' ],
- statsDisplay : Handlebars.templates[ 'template-visualization-statsDisplay' ],
- chartDisplay : Handlebars.templates[ 'template-visualization-chartDisplay' ]
-};
-
-//==============================================================================
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 static/scripts/packed/mvc/dataset/hda-edit.js
--- a/static/scripts/packed/mvc/dataset/hda-edit.js
+++ b/static/scripts/packed/mvc/dataset/hda-edit.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var f=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(g){a.HDABaseView.prototype.initialize.call(this,g);this.hasUser=g.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton];this.tagsEditorShown=g.tagsEditorShown||false;this.annotationEditorShown=g.annotationEditorShown||false},_render_titleButtons:function(){return a.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var i=this.model.get("purged"),g=this.model.get("deleted"),h={title:_l("Edit attributes"),href:this.urls.edit,target:this.linkTarget,classes:"dataset-edit"};if(g||i){h.disabled=true;if(i){h.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(g){h.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){h.disabled=true;h.title=_l("This dataset must finish uploading before it can be edited")}}h.faIcon="fa-pencil";return faIconButton(h)},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var g=this,h={title:_l("Delete"),classes:"dataset-delete",onclick:function(){g.$el.find(".icon-btn.dataset-delete").trigger("mouseout");g.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){h={title:_l("Dataset is already deleted"),disabled:true}}h.faIcon="fa-times";return faIconButton(h)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,classes:"dataset-report-error-btn",target:this.linkTarget,faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,classes:"dataset-rerun-btn",target:this.linkTarget,faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var n=this.model.get("visualizations");if((!this.hasUser)||(!this.model.hasData())||(_.isEmpty(n))){return null}if(_.isObject(n[0])){return this._render_visualizationsFrameworkButton(n)}if(!this.urls.visualization){return null}var k=this.model.get("dbkey"),g=this.urls.visualization,j={},h={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(k){h.dbkey=k}var l=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});var m=this;function i(p){switch(p){case"trackster":return b(g,h,k);case"scatterplot":return e(g,h,m.linkTarget);default:return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:g+"/"+p+"?"+$.param(h)})}}}function o(p){return p.charAt(0).toUpperCase()+p.slice(1)}if(n.length===1){l.attr("data-original-title",_l("Visualize in ")+_l(o(n[0])));l.click(i(n[0]))}else{_.each(n,function(p){j[_l(o(p))]=i(p)});make_popupmenu(l,j)}return l},_render_visualizationsFrameworkButton:function(g){if(!(this.model.hasData())||!(g&&!_.isEmpty(g))){return null}var i=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});i.addClass("visualize-icon");if(_.keys(g).length===1){i.attr("title",_.keys(g)[0]);i.attr("href",_.values(g)[0])}else{var j=[];_.each(g,function(k){j.push(k)});var h=new PopupMenu(i,j)}return i},_buildNewRender:function(){var g=a.HDABaseView.prototype._buildNewRender.call(this);g.find(".dataset-deleted-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk'));g.find(".dataset-hidden-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it'));return g},_render_body_failed_metadata:function(){var h=$("<a/>").attr({href:this.urls.edit,target:this.linkTarget}).text(_l("set it manually or retry auto-detection")),g=$("<span/>").text(". "+_l("You may be able to")+" ").append(h),i=a.HDABaseView.prototype._render_body_failed_metadata.call(this);i.find(".warningmessagesmall strong").append(g);return i},_render_body_error:function(){var g=a.HDABaseView.prototype._render_body_error.call(this);g.find(".dataset-actions .left").prepend(this._render_errButton());return g},_render_body_ok:function(){var g=a.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return g}this.makeDbkeyEditLink(g);if(this.hasUser){g.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(g);this._renderAnnotation(g)}return g},_renderTags:function(g){var h=this;this.tagsEditor=new TagsEditor({model:this.model,el:g.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){h.tagsEditorShown=true},onhide:function(){h.tagsEditorShown=false},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(g.find(".dataset-actions .right"))});if(this.tagsEditorShown){this.tagsEditor.toggle(true)}},_renderAnnotation:function(g){var h=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:g.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){h.annotationEditorShown=true},onhide:function(){h.annotationEditorShown=false},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(g.find(".dataset-actions .right"))});if(this.annotationEditorShown){this.annotationEditor.toggle(true)}},makeDbkeyEditLink:function(h){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){var g=$('<a class="value">?</a>').attr("href",this.urls.edit).attr("target",this.linkTarget);h.find(".dataset-dbkey .value").replaceWith(g)}},events:_.extend(_.clone(a.HDABaseView.prototype.events),{"click .dataset-undelete":function(g){this.model.undelete();return false},"click .dataset-unhide":function(g){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"}),confirmPurge:function c(g){this.model.purge();return false},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDAView("+g+")"}});function e(g,i,h){action=function(){Galaxy.frame.add({title:"Scatterplot",type:"url",content:g+"/scatterplot?"+$.param(i),target:h,scratchbook:true});$("div.popmenu-wrapper").remove();return false};return action}function b(g,i,h){return function(){var j={};if(h){j["f-dbkey"]=h}$.ajax({url:g+"/list_tracks?"+$.param(j),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(k){var l=window.parent;l.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){l.Galaxy.modal.hide()},"View in saved visualization":function(){l.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:k,buttons:{Cancel:function(){l.Galaxy.modal.hide()},"Add to visualization":function(){$(l.document).find("input[name=id]:checked").each(function(){l.Galaxy.modal.hide();var m=$(this).val();i.id=m;l.Galaxy.frame.add({title:"Trackster",type:"url",content:g+"/trackster?"+$.param(i),scratchbook:true})})}}})},"View in new visualization":function(){l.Galaxy.modal.hide();var m=g+"/trackster?"+$.param(i);l.Galaxy.frame.add({title:"Trackster",type:"url",content:m,scratchbook:true})}}})}});return false}}return{HDAEditView:f}});
\ No newline at end of file
+define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var f=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(g){a.HDABaseView.prototype.initialize.call(this,g);this.hasUser=g.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton];this.tagsEditorShown=g.tagsEditorShown||false;this.annotationEditorShown=g.annotationEditorShown||false},_render_titleButtons:function(){return a.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var i=this.model.get("purged"),g=this.model.get("deleted"),h={title:_l("Edit attributes"),href:this.urls.edit,target:this.linkTarget,classes:"dataset-edit"};if(g||i){h.disabled=true;if(i){h.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(g){h.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){h.disabled=true;h.title=_l("This dataset must finish uploading before it can be edited")}}h.faIcon="fa-pencil";return faIconButton(h)},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var g=this,h={title:_l("Delete"),classes:"dataset-delete",onclick:function(){g.$el.find(".icon-btn.dataset-delete").trigger("mouseout");g.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){h={title:_l("Dataset is already deleted"),disabled:true}}h.faIcon="fa-times";return faIconButton(h)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,classes:"dataset-report-error-btn",target:this.linkTarget,faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,classes:"dataset-rerun-btn",target:this.linkTarget,faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var n=this.model.get("visualizations");if((!this.hasUser)||(!this.model.hasData())||(_.isEmpty(n))){return null}if(_.isObject(n[0])){return this._render_visualizationsFrameworkButton(n)}if(!this.urls.visualization){return null}var k=this.model.get("dbkey"),g=this.urls.visualization,j={},h={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(k){h.dbkey=k}var l=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});var m=this;function i(p){switch(p){case"trackster":return b(g,h,k);case"scatterplot":return e(g,h,m.linkTarget);default:return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:g+"/"+p+"?"+$.param(h)})}}}function o(p){return p.charAt(0).toUpperCase()+p.slice(1)}if(n.length===1){l.attr("data-original-title",_l("Visualize in ")+_l(o(n[0])));l.click(i(n[0]))}else{_.each(n,function(p){j[_l(o(p))]=i(p)});make_popupmenu(l,j)}return l},_render_visualizationsFrameworkButton:function(g){if(!(this.model.hasData())||!(g&&!_.isEmpty(g))){return null}var h=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});if(_.keys(g).length===1){h.attr("title",_.keys(g)[0]);h.attr("href",_.values(g)[0])}else{var i=[];_.each(g,function(j){j.func=function(){if(Galaxy.frame.active){Galaxy.frame.add({title:"Visualization",type:"url",content:j.href});return false}return true};i.push(j);return false});PopupMenu.create(h,i)}return h},_buildNewRender:function(){var g=a.HDABaseView.prototype._buildNewRender.call(this);g.find(".dataset-deleted-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk'));g.find(".dataset-hidden-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it'));return g},_render_body_failed_metadata:function(){var h=$("<a/>").attr({href:this.urls.edit,target:this.linkTarget}).text(_l("set it manually or retry auto-detection")),g=$("<span/>").text(". "+_l("You may be able to")+" ").append(h),i=a.HDABaseView.prototype._render_body_failed_metadata.call(this);i.find(".warningmessagesmall strong").append(g);return i},_render_body_error:function(){var g=a.HDABaseView.prototype._render_body_error.call(this);g.find(".dataset-actions .left").prepend(this._render_errButton());return g},_render_body_ok:function(){var g=a.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return g}this.makeDbkeyEditLink(g);if(this.hasUser){g.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(g);this._renderAnnotation(g)}return g},_renderTags:function(g){var h=this;this.tagsEditor=new TagsEditor({model:this.model,el:g.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){h.tagsEditorShown=true},onhide:function(){h.tagsEditorShown=false},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(g.find(".dataset-actions .right"))});if(this.tagsEditorShown){this.tagsEditor.toggle(true)}},_renderAnnotation:function(g){var h=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:g.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){h.annotationEditorShown=true},onhide:function(){h.annotationEditorShown=false},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(g.find(".dataset-actions .right"))});if(this.annotationEditorShown){this.annotationEditor.toggle(true)}},makeDbkeyEditLink:function(h){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){var g=$('<a class="value">?</a>').attr("href",this.urls.edit).attr("target",this.linkTarget);h.find(".dataset-dbkey .value").replaceWith(g)}},events:_.extend(_.clone(a.HDABaseView.prototype.events),{"click .dataset-undelete":function(g){this.model.undelete();return false},"click .dataset-unhide":function(g){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"}),confirmPurge:function c(g){this.model.purge();return false},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDAView("+g+")"}});function e(g,i,h){action=function(){Galaxy.frame.add({title:"Scatterplot",type:"url",content:g+"/scatterplot?"+$.param(i),target:h,scratchbook:true});$("div.popmenu-wrapper").remove();return false};return action}function b(g,i,h){return function(){var j={};if(h){j["f-dbkey"]=h}$.ajax({url:g+"/list_tracks?"+$.param(j),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(k){var l=window.parent;l.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){l.Galaxy.modal.hide()},"View in saved visualization":function(){l.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:k,buttons:{Cancel:function(){l.Galaxy.modal.hide()},"Add to visualization":function(){$(l.document).find("input[name=id]:checked").each(function(){l.Galaxy.modal.hide();var m=$(this).val();i.id=m;l.Galaxy.frame.add({title:"Trackster",type:"url",content:g+"/trackster?"+$.param(i),scratchbook:true})})}}})},"View in new visualization":function(){l.Galaxy.modal.hide();var m=g+"/trackster?"+$.param(i);l.Galaxy.frame.add({title:"Trackster",type:"url",content:m,scratchbook:true})}}})}});return false}}return{HDAEditView:f}});
\ No newline at end of file
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function b(m,l){this.currModeIndex=0;return this.init(m,l)}b.prototype.DATA_KEY="mode-button";b.prototype.defaults={modes:[{mode:"default"}]};b.prototype.init=function f(m,l){l=l||{};this.$element=$(m);this.options=jQuery.extend(true,{},this.defaults,l);var o=this;this.$element.click(function n(p){o.callModeFn();o._incModeIndex();$(this).html(o.options.modes[o.currModeIndex].html)});this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this};b.prototype._getModeIndex=function j(l){for(var m=0;m<this.options.modes.length;m+=1){if(this.options.modes[m].mode===l){return m}}throw new Error("mode not found: "+l)};b.prototype.getCurrMode=function a(){return this.options.modes[this.currModeIndex]};b.prototype.getMode=function g(l){if(!l){return this.getCurrMode()}return this.options.modes[(this._getModeIndex(l))]};b.prototype.hasMode=function k(l){return !!this.getMode(l)};b.prototype.currentMode=function e(){return this.options.modes[this.currModeIndex]};b.prototype.setMode=function c(m){var l=this.getMode(m);this.$element.html(l.html||null);return this};b.prototype._incModeIndex=function d(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};b.prototype.callModeFn=function h(l){var m=this.getMode(l).onclick;if(m&&jQuery.type(m==="function")){return m.call(this)}return undefined};jQuery.fn.extend({modeButton:function i(m){var l=jQuery.makeArray(arguments).slice(1);return this.map(function(){var p=$(this),o=p.data("mode-button");if(jQuery.type(m)==="object"){o=new b(p,m);p.data("mode-button",o)}else{if(o&&jQuery.type(m)==="string"){var n=o[m];if(jQuery.type(n)==="function"){return n.apply(o,l)}}else{if(o){return o}}}return this})}})}());function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function b(m,l){this.currModeIndex=0;return this.init(m,l)}b.prototype.DATA_KEY="mode-button";b.prototype.defaults={modes:[{mode:"default"}]};b.prototype.init=function f(m,l){l=l||{};this.$element=$(m);this.options=jQuery.extend(true,{},this.defaults,l);var o=this;this.$element.click(function n(p){o.callModeFn();o._incModeIndex();$(this).html(o.options.modes[o.currModeIndex].html)});this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this};b.prototype._getModeIndex=function j(l){for(var m=0;m<this.options.modes.length;m+=1){if(this.options.modes[m].mode===l){return m}}throw new Error("mode not found: "+l)};b.prototype.getCurrMode=function a(){return this.options.modes[this.currModeIndex]};b.prototype.getMode=function g(l){if(!l){return this.getCurrMode()}return this.options.modes[(this._getModeIndex(l))]};b.prototype.hasMode=function k(l){return !!this.getMode(l)};b.prototype.currentMode=function e(){return this.options.modes[this.currModeIndex]};b.prototype.setMode=function c(m){var l=this.getMode(m);this.$element.html(l.html||null);return this};b.prototype._incModeIndex=function d(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};b.prototype.callModeFn=function h(l){var m=this.getMode(l).onclick;if(m&&jQuery.type(m==="function")){return m.call(this)}return undefined};jQuery.fn.extend({modeButton:function i(m){var l=jQuery.makeArray(arguments).slice(1);return this.map(function(){var p=$(this),o=p.data("mode-button");if(jQuery.type(m)==="object"){o=new b(p,m);p.data("mode-button",o)}else{if(o&&jQuery.type(m)==="string"){var n=o[m];if(jQuery.type(n)==="function"){return n.apply(o,l)}}else{if(o){return o}}}return this})}})}());function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());
\ No newline at end of file
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 templates/webapps/galaxy/visualization/scatterplot.mako
--- a/templates/webapps/galaxy/visualization/scatterplot.mako
+++ b/templates/webapps/galaxy/visualization/scatterplot.mako
@@ -216,7 +216,7 @@
)}
${h.js(
- "mvc/visualizations/scatterplotControlForm",
+ "mvc/visualization/scatterplotControlForm",
)}
<script type="text/javascript">
diff -r 1afdcafa4b28e246efc0c96987c63e469e2255e7 -r 0d50efaac5d481b173f379a75b64a42b1b43b8a4 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -177,7 +177,7 @@
# Visualizations config directory: where to look for individual visualization plugins.
# The path is relative to the Galaxy root dir. To use an absolute path begin the path
# with '/'.
-#visualizations_plugins_directory = config/plugins/visualizations
+visualization_plugins_directory = config/plugins/visualizations
# Each job is given a unique empty directory as its current working directory.
# This option defines in what parent directory those directories will be
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0