galaxy-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
- 15302 discussions
commit/galaxy-central: dan: Make DatasetListWrapper and DatasetCollectionWrapper subclasses of ToolParameterValueWrapper.
by commits-noreply@bitbucket.org 14 Jan '15
by commits-noreply@bitbucket.org 14 Jan '15
14 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7fd6061e43d5/
Changeset: 7fd6061e43d5
Branch: stable
User: dan
Date: 2015-01-14 20:02:23+00:00
Summary: Make DatasetListWrapper and DatasetCollectionWrapper subclasses of ToolParameterValueWrapper.
Affected #: 1 file
diff -r fd1946912be3f0454e155effc10e5a2127388559 -r 7fd6061e43d5122b2e99f0dc18370af3d190cb34 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -262,7 +262,7 @@
return DatasetFilenameWrapper( dataset, **wrapper_kwds )
-class DatasetListWrapper( list, HasDatasets ):
+class DatasetListWrapper( list, ToolParameterValueWrapper, HasDatasets ):
"""
"""
def __init__( self, datasets, dataset_paths=[], **kwargs ):
@@ -277,7 +277,7 @@
return ','.join( map( str, self ) )
-class DatasetCollectionWrapper( object, HasDatasets ):
+class DatasetCollectionWrapper( ToolParameterValueWrapper, HasDatasets ):
def __init__( self, has_collection, dataset_paths=[], **kwargs ):
super(DatasetCollectionWrapper, self).__init__()
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: dan: Make DatasetListWrapper and DatasetCollectionWrapper subclasses of ToolParameterValueWrapper.
by commits-noreply@bitbucket.org 14 Jan '15
by commits-noreply@bitbucket.org 14 Jan '15
14 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2c10a0baa054/
Changeset: 2c10a0baa054
User: dan
Date: 2015-01-14 20:02:23+00:00
Summary: Make DatasetListWrapper and DatasetCollectionWrapper subclasses of ToolParameterValueWrapper.
Affected #: 1 file
diff -r aea916e9d68d4953003d9b913bea3ddd80749cc9 -r 2c10a0baa054fc325f2abb1d94f2d478ffd765cc lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -262,7 +262,7 @@
return DatasetFilenameWrapper( dataset, **wrapper_kwds )
-class DatasetListWrapper( list, HasDatasets ):
+class DatasetListWrapper( list, ToolParameterValueWrapper, HasDatasets ):
"""
"""
def __init__( self, datasets, dataset_paths=[], **kwargs ):
@@ -277,7 +277,7 @@
return ','.join( map( str, self ) )
-class DatasetCollectionWrapper( object, HasDatasets ):
+class DatasetCollectionWrapper( ToolParameterValueWrapper, HasDatasets ):
def __init__( self, has_collection, dataset_paths=[], **kwargs ):
super(DatasetCollectionWrapper, self).__init__()
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: guerler: Charts: Avoid cursor replacement in label field
by commits-noreply@bitbucket.org 14 Jan '15
by commits-noreply@bitbucket.org 14 Jan '15
14 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/aea916e9d68d/
Changeset: aea916e9d68d
User: guerler
Date: 2015-01-14 16:08:14+00:00
Summary: Charts: Avoid cursor replacement in label field
Affected #: 2 files
diff -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 -r aea916e9d68d4953003d9b913bea3ddd80749cc9 config/plugins/visualizations/charts/static/build-app.js
--- a/config/plugins/visualizations/charts/static/build-app.js
+++ b/config/plugins/visualizations/charts/static/build-app.js
@@ -3,4 +3,4 @@
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
-define("mvc/ui/ui-modal",[],function(){var e=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast"),this.options.closing_callback&&this.options.closing_callback()},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="ui-modal modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:e}}),function(){var e=this,t=e._,n=Array.prototype,r=Object.prototype,i=Function.prototype,s=n.push,o=n.slice,u=n.concat,a=r.toString,f=r.hasOwnProperty,l=Array.isArray,c=Object.keys,h=i.bind,p=function(e){if(e instanceof p)return e;if(!(this instanceof p))return new p(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=p),exports._=p):e._=p,p.VERSION="1.7.0";var d=function(e,t,n){if(t===void 0)return e;switch(n==null?3:n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)};case 4:return function(n,r,i,s){return e.call(t,n,r,i,s)}}return function(){return e.apply(t,arguments)}};p.iteratee=function(e,t,n){return e==null?p.identity:p.isFunction(e)?d(e,t,n):p.isObject(e)?p.matches(e):p.property(e)},p.each=p.forEach=function(e,t,n){if(e==null)return e;t=d(t,n);var r,i=e.length;if(i===+i)for(r=0;r<i;r++)t(e[r],r,e);else{var s=p.keys(e);for(r=0,i=s.length;r<i;r++)t(e[s[r]],s[r],e)}return e},p.map=p.collect=function(e,t,n){if(e==null)return[];t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s=Array(i),o;for(var u=0;u<i;u++)o=r?r[u]:u,s[u]=t(e[o],o,e);return s};var v="Reduce of empty array with no initial value";p.reduce=p.foldl=p.inject=function(e,t,n,r){e==null&&(e=[]),t=d(t,r,4);var i=e.length!==+e.length&&p.keys(e),s=(i||e).length,o=0,u;if(arguments.length<3){if(!s)throw new TypeError(v);n=e[i?i[o++]:o++]}for(;o<s;o++)u=i?i[o]:o,n=t(n,e[u],u,e);return n},p.reduceRight=p.foldr=function(e,t,n,r){e==null&&(e=[]),t=d(t,r,4);var i=e.length!==+e.length&&p.keys(e),s=(i||e).length,o;if(arguments.length<3){if(!s)throw new TypeError(v);n=e[i?i[--s]:--s]}while(s--)o=i?i[s]:s,n=t(n,e[o],o,e);return n},p.find=p.detect=function(e,t,n){var r;return t=p.iteratee(t,n),p.some(e,function(e,n,i){if(t(e,n,i))return r=e,!0}),r},p.filter=p.select=function(e,t,n){var r=[];return e==null?r:(t=p.iteratee(t,n),p.each(e,function(e,n,i){t(e,n,i)&&r.push(e)}),r)},p.reject=function(e,t,n){return p.filter(e,p.negate(p.iteratee(t)),n)},p.every=p.all=function(e,t,n){if(e==null)return!0;t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s,o;for(s=0;s<i;s++){o=r?r[s]:s;if(!t(e[o],o,e))return!1}return!0},p.some=p.any=function(e,t,n){if(e==null)return!1;t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s,o;for(s=0;s<i;s++){o=r?r[s]:s;if(t(e[o],o,e))return!0}return!1},p.contains=p.include=function(e,t){return e==null?!1:(e.length!==+e.length&&(e=p.values(e)),p.indexOf(e,t)>=0)},p.invoke=function(e,t){var n=o.call(arguments,2),r=p.isFunction(t);return p.map(e,function(e){return(r?t:e[t]).apply(e,n)})},p.pluck=function(e,t){return p.map(e,p.property(t))},p.where=function(e,t){return p.filter(e,p.matches(t))},p.findWhere=function(e,t){return p.find(e,p.matches(t))},p.max=function(e,t,n){var r=-Infinity,i=-Infinity,s,o;if(t==null&&e!=null){e=e.length===+e.length?e:p.values(e);for(var u=0,a=e.length;u<a;u++)s=e[u],s>r&&(r=s)}else t=p.iteratee(t,n),p.each(e,function(e,n,s){o=t(e,n,s);if(o>i||o===-Infinity&&r===-Infinity)r=e,i=o});return r},p.min=function(e,t,n){var r=Infinity,i=Infinity,s,o;if(t==null&&e!=null){e=e.length===+e.length?e:p.values(e);for(var u=0,a=e.length;u<a;u++)s=e[u],s<r&&(r=s)}else t=p.iteratee(t,n),p.each(e,function(e,n,s){o=t(e,n,s);if(o<i||o===Infinity&&r===Infinity)r=e,i=o});return r},p.shuffle=function(e){var t=e&&e.length===+e.length?e:p.values(e),n=t.length,r=Array(n);for(var i=0,s;i<n;i++)s=p.random(0,i),s!==i&&(r[i]=r[s]),r[s]=t[i];return r},p.sample=function(e,t,n){return t==null||n?(e.length!==+e.length&&(e=p.values(e)),e[p.random(e.length-1)]):p.shuffle(e).slice(0,Math.max(0,t))},p.sortBy=function(e,t,n){return t=p.iteratee(t,n),p.pluck(p.map(e,function(e,n,r){return{value:e,index:n,criteria:t(e,n,r)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index-t.index}),"value")};var m=function(e){return function(t,n,r){var i={};return n=p.iteratee(n,r),p.each(t,function(r,s){var o=n(r,s,t);e(i,r,o)}),i}};p.groupBy=m(function(e,t,n){p.has(e,n)?e[n].push(t):e[n]=[t]}),p.indexBy=m(function(e,t,n){e[n]=t}),p.countBy=m(function(e,t,n){p.has(e,n)?e[n]++:e[n]=1}),p.sortedIndex=function(e,t,n,r){n=p.iteratee(n,r,1);var i=n(t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n(e[u])<i?s=u+1:o=u}return s},p.toArray=function(e){return e?p.isArray(e)?o.call(e):e.length===+e.length?p.map(e,p.identity):p.values(e):[]},p.size=function(e){return e==null?0:e.length===+e.length?e.length:p.keys(e).length},p.partition=function(e,t,n){t=p.iteratee(t,n);var r=[],i=[];return p.each(e,function(e,n,s){(t(e,n,s)?r:i).push(e)}),[r,i]},p.first=p.head=p.take=function(e,t,n){return e==null?void 0:t==null||n?e[0]:t<0?[]:o.call(e,0,t)},p.initial=function(e,t,n){return o.call(e,0,Math.max(0,e.length-(t==null||n?1:t)))},p.last=function(e,t,n){return e==null?void 0:t==null||n?e[e.length-1]:o.call(e,Math.max(e.length-t,0))},p.rest=p.tail=p.drop=function(e,t,n){return o.call(e,t==null||n?1:t)},p.compact=function(e){return p.filter(e,p.identity)};var g=function(e,t,n,r){if(t&&p.every(e,p.isArray))return u.apply(r,e);for(var i=0,o=e.length;i<o;i++){var a=e[i];!p.isArray(a)&&!p.isArguments(a)?n||r.push(a):t?s.apply(r,a):g(a,t,n,r)}return r};p.flatten=function(e,t){return g(e,t,!1,[])},p.without=function(e){return p.difference(e,o.call(arguments,1))},p.uniq=p.unique=function(e,t,n,r){if(e==null)return[];p.isBoolean(t)||(r=n,n=t,t=!1),n!=null&&(n=p.iteratee(n,r));var i=[],s=[];for(var o=0,u=e.length;o<u;o++){var a=e[o];if(t)(!o||s!==a)&&i.push(a),s=a;else if(n){var f=n(a,o,e);p.indexOf(s,f)<0&&(s.push(f),i.push(a))}else p.indexOf(i,a)<0&&i.push(a)}return i},p.union=function(){return p.uniq(g(arguments,!0,!0,[]))},p.intersection=function(e){if(e==null)return[];var t=[],n=arguments.length;for(var r=0,i=e.length;r<i;r++){var s=e[r];if(p.contains(t,s))continue;for(var o=1;o<n;o++)if(!p.contains(arguments[o],s))break;o===n&&t.push(s)}return t},p.difference=function(e){var t=g(o.call(arguments,1),!0,!0,[]);return p.filter(e,function(e){return!p.contains(t,e)})},p.zip=function(e){if(e==null)return[];var t=p.max(arguments,"length").length,n=Array(t);for(var r=0;r<t;r++)n[r]=p.pluck(arguments,r);return n},p.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},p.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=p.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}for(;r<i;r++)if(e[r]===t)return r;return-1},p.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=e.length;typeof n=="number"&&(r=n<0?r+n+1:Math.min(r,n+1));while(--r>=0)if(e[r]===t)return r;return-1},p.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=n||1;var r=Math.max(Math.ceil((t-e)/n),0),i=Array(r);for(var s=0;s<r;s++,e+=n)i[s]=e;return i};var y=function(){};p.bind=function(e,t){var n,r;if(h&&e.bind===h)return h.apply(e,o.call(arguments,1));if(!p.isFunction(e))throw new TypeError("Bind must be called on a function");return n=o.call(arguments,2),r=function(){if(this instanceof r){y.prototype=e.prototype;var i=new y;y.prototype=null;var s=e.apply(i,n.concat(o.call(arguments)));return p.isObject(s)?s:i}return e.apply(t,n.concat(o.call(arguments)))},r},p.partial=function(e){var t=o.call(arguments,1);return function(){var n=0,r=t.slice();for(var i=0,s=r.length;i<s;i++)r[i]===p&&(r[i]=arguments[n++]);while(n<arguments.length)r.push(arguments[n++]);return e.apply(this,r)}},p.bindAll=function(e){var t,n=arguments.length,r;if(n<=1)throw new Error("bindAll must be passed function names");for(t=1;t<n;t++)r=arguments[t],e[r]=p.bind(e[r],e);return e},p.memoize=function(e,t){var n=function(r){var i=n.cache,s=t?t.apply(this,arguments):r;return p.has(i,s)||(i[s]=e.apply(this,arguments)),i[s]};return n.cache={},n},p.delay=function(e,t){var n=o.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},p.defer=function(e){return p.delay.apply(p,[e,1].concat(o.call(arguments,1)))},p.throttle=function(e,t,n){var r,i,s,o=null,u=0;n||(n={});var a=function(){u=n.leading===!1?0:p.now(),o=null,s=e.apply(r,i),o||(r=i=null)};return function(){var f=p.now();!u&&n.leading===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0||l>t?(clearTimeout(o),o=null,u=f,s=e.apply(r,i),o||(r=i=null)):!o&&n.trailing!==!1&&(o=setTimeout(a,l)),s}},p.debounce=function(e,t,n){var r,i,s,o,u,a=function(){var f=p.now()-o;f<t&&f>0?r=setTimeout(a,t-f):(r=null,n||(u=e.apply(s,i),r||(s=i=null)))};return function(){s=this,i=arguments,o=p.now();var f=n&&!r;return r||(r=setTimeout(a,t)),f&&(u=e.apply(s,i),s=i=null),u}},p.wrap=function(e,t){return p.partial(t,e)},p.negate=function(e){return function(){return!e.apply(this,arguments)}},p.compose=function(){var e=arguments,t=e.length-1;return function(){var n=t,r=e[t].apply(this,arguments);while(n--)r=e[n].call(this,r);return r}},p.after=function(e,t){return function(){if(--e<1)return t.apply(this,arguments)}},p.before=function(e,t){var n;return function(){return--e>0?n=t.apply(this,arguments):t=null,n}},p.once=p.partial(p.before,2),p.keys=function(e){if(!p.isObject(e))return[];if(c)return c(e);var t=[];for(var n in e)p.has(e,n)&&t.push(n);return t},p.values=function(e){var t=p.keys(e),n=t.length,r=Array(n);for(var i=0;i<n;i++)r[i]=e[t[i]];return r},p.pairs=function(e){var t=p.keys(e),n=t.length,r=Array(n);for(var i=0;i<n;i++)r[i]=[t[i],e[t[i]]];return r},p.invert=function(e){var t={},n=p.keys(e);for(var r=0,i=n.length;r<i;r++)t[e[n[r]]]=n[r];return t},p.functions=p.methods=function(e){var t=[];for(var n in e)p.isFunction(e[n])&&t.push(n);return t.sort()},p.extend=function(e){if(!p.isObject(e))return e;var t,n;for(var r=1,i=arguments.length;r<i;r++){t=arguments[r];for(n in t)f.call(t,n)&&(e[n]=t[n])}return e},p.pick=function(e,t,n){var r={},i;if(e==null)return r;if(p.isFunction(t)){t=d(t,n);for(i in e){var s=e[i];t(s,i,e)&&(r[i]=s)}}else{var a=u.apply([],o.call(arguments,1));e=new Object(e);for(var f=0,l=a.length;f<l;f++)i=a[f],i in e&&(r[i]=e[i])}return r},p.omit=function(e,t,n){if(p.isFunction(t))t=p.negate(t);else{var r=p.map(u.apply([],o.call(arguments,1)),String);t=function(e,t){return!p.contains(r,t)}}return p.pick(e,t,n)},p.defaults=function(e){if(!p.isObject(e))return e;for(var t=1,n=arguments.length;t<n;t++){var r=arguments[t];for(var i in r)e[i]===void 0&&(e[i]=r[i])}return e},p.clone=function(e){return p.isObject(e)?p.isArray(e)?e.slice():p.extend({},e):e},p.tap=function(e,t){return t(e),e};var b=function(e,t,n,r){if(e===t)return e!==0||1/e===1/t;if(e==null||t==null)return e===t;e instanceof p&&(e=e._wrapped),t instanceof p&&(t=t._wrapped);var i=a.call(e);if(i!==a.call(t))return!1;switch(i){case"[object RegExp]":case"[object String]":return""+e==""+t;case"[object Number]":if(+e!==+e)return+t!==+t;return+e===0?1/+e===1/t:+e===+t;case"[object Date]":case"[object Boolean]":return+e===+t}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]===e)return r[s]===t;var o=e.constructor,u=t.constructor;if(o!==u&&"constructor"in e&&"constructor"in t&&!(p.isFunction(o)&&o instanceof o&&p.isFunction(u)&&u instanceof u))return!1;n.push(e),r.push(t);var f,l;if(i==="[object Array]"){f=e.length,l=f===t.length;if(l)while(f--)if(!(l=b(e[f],t[f],n,r)))break}else{var c=p.keys(e),h;f=c.length,l=p.keys(t).length===f;if(l)while(f--){h=c[f];if(!(l=p.has(t,h)&&b(e[h],t[h],n,r)))break}}return n.pop(),r.pop(),l};p.isEqual=function(e,t){return b(e,t,[],[])},p.isEmpty=function(e){if(e==null)return!0;if(p.isArray(e)||p.isString(e)||p.isArguments(e))return e.length===0;for(var t in e)if(p.has(e,t))return!1;return!0},p.isElement=function(e){return!!e&&e.nodeType===1},p.isArray=l||function(e){return a.call(e)==="[object Array]"},p.isObject=function(e){var t=typeof e;return t==="function"||t==="object"&&!!e},p.each(["Arguments","Function","String","Number","Date","RegExp"],function(e){p["is"+e]=function(t){return a.call(t)==="[object "+e+"]"}}),p.isArguments(arguments)||(p.isArguments=function(e){return p.has(e,"callee")}),typeof /./!="function"&&(p.isFunction=function(e){return typeof e=="function"||!1}),p.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},p.isNaN=function(e){return p.isNumber(e)&&e!==+e},p.isBoolean=function(e){return e===!0||e===!1||a.call(e)==="[object Boolean]"},p.isNull=function(e){return e===null},p.isUndefined=function(e){return e===void 0},p.has=function(e,t){return e!=null&&f.call(e,t)},p.noConflict=function(){return e._=t,this},p.identity=function(e){return e},p.constant=function(e){return function(){return e}},p.noop=function(){},p.property=function(e){return function(t){return t[e]}},p.matches=function(e){var t=p.pairs(e),n=t.length;return function(e){if(e==null)return!n;e=new Object(e);for(var r=0;r<n;r++){var i=t[r],s=i[0];if(i[1]!==e[s]||!(s in e))return!1}return!0}},p.times=function(e,t,n){var r=Array(Math.max(0,e));t=d(t,n,1);for(var i=0;i<e;i++)r[i]=t(i);return r},p.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))},p.now=Date.now||function(){return(new Date).getTime()};var w={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},E=p.invert(w),S=function(e){var t=function(t){return e[t]},n="(?:"+p.keys(e).join("|")+")",r=RegExp(n),i=RegExp(n,"g");return function(e){return e=e==null?"":""+e,r.test(e)?e.replace(i,t):e}};p.escape=S(w),p.unescape=S(E),p.result=function(e,t){if(e==null)return void 0;var n=e[t];return p.isFunction(n)?e[t]():n};var x=0;p.uniqueId=function(e){var t=++x+"";return e?e+t:t},p.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,N={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},C=/\\|'|\r|\n|\u2028|\u2029/g,k=function(e){return"\\"+N[e]};p.template=function(e,t,n){!t&&n&&(t=n),t=p.defaults({},t,p.templateSettings);var r=RegExp([(t.escape||T).source,(t.interpolate||T).source,(t.evaluate||T).source].join("|")+"|$","g"),i=0,s="__p+='";e.replace(r,function(t,n,r,o,u){return s+=e.slice(i,u).replace(C,k),i=u+t.length,n?s+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?s+="'+\n((__t=("+r+"))==null?'':__t)+\n'":o&&(s+="';\n"+o+"\n__p+='"),t}),s+="';\n",t.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n";try{var o=new Function(t.variable||"obj","_",s)}catch(u){throw u.source=s,u}var a=function(e){return o.call(this,e,p)},f=t.variable||"obj";return a.source="function("+f+"){\n"+s+"}",a},p.chain=function(e){var t=p(e);return t._chain=!0,t};var L=function(e){return this._chain?p(e).chain():e};p.mixin=function(e){p.each(p.functions(e),function(t){var n=p[t]=e[t];p.prototype[t]=function(){var e=[this._wrapped];return s.apply(e,arguments),L.call(this,n.apply(p,e))}})},p.mixin(p),p.each(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=n[e];p.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e==="shift"||e==="splice")&&n.length===0&&delete n[0],L.call(this,n)}}),p.each(["concat","join","slice"],function(e){var t=n[e];p.prototype[e]=function(){return L.call(this,t.apply(this._wrapped,arguments))}}),p.prototype.value=function(){return this._wrapped},typeof define=="function"&&define.amd&&define("underscore",[],function(){return p})}.call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e){return $("<div/>").text(e).html()}function n(e){e instanceof Array||(e=[e]);for(var t in e)if(["None",null,"null",undefined,"undefined"].indexOf(e[t])>-1)return!1;return!0}function r(e){var e=e.toString();if(e){e=e.replace(/,/g,", ");var t=e.lastIndexOf(", ");return t!=-1&&(e=e.substr(0,t)+" or "+e.substr(t+1)),e}return""}function i(e){top.__utils__get__=top.__utils__get__||{},e.cache&&top.__utils__get__[e.url]?(e.success&&e.success(top.__utils__get__[e.url]),console.debug("utils.js::get() - Fetching from cache ["+e.url+"].")):s({url:e.url,data:e.data,success:function(t){top.__utils__get__[e.url]=t,e.success&&e.success(t)},error:function(t){e.error&&e.error(t)}})}function s(e){var t={contentType:"application/json",type:e.type||"GET",data:e.data||{},url:e.url};t.type=="GET"||t.type=="DELETE"?(t.url.indexOf("?")==-1?t.url+="?":t.url+="&",t.url=t.url+$.param(t.data),t.data=null):(t.dataType="json",t.url=t.url,t.data=JSON.stringify(t.data)),$.ajax(t).done(function(t){if(typeof t=="string")try{t=t.replace("Infinity,",'"Infinity",'),t=jQuery.parseJSON(t)}catch(n){console.debug(n)}e.success&&e.success(t)}).fail(function(t){var n=null;try{n=jQuery.parseJSON(t.responseText)}catch(r){n=t.responseText}e.error&&e.error(n,t)})}function o(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function u(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function a(t,n){return t?e.defaults(t,n):n}function f(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function l(){return"x"+Math.random().toString(36).substring(2,9)}function c(e){var t=$("<p></p>");return t.append(e),t}function h(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:u,cssGetAttribute:o,get:i,merge:a,bytesToString:f,uuid:l,time:h,wrap:c,request:s,sanitize:t,textify:r,validate:n}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,scrollable:!0,nopadding:!1,operations:null,placement:"bottom",cls:"ui-portlet",operations_flt:"right"},$title:null,$content:null,$buttons:null,$operations:null,$header:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find(".content"),this.$title=this.$el.find(".portlet-title-text"),this.$header=this.$el.find(".portlet-header");var n=this.$el.find(".portlet-content");this.options.scrollable?n.addClass("scroll"):this.options.title?n.addClass("no-scroll"):n.addClass("no-scroll-no-title"),this.options.nopadding&&(n.css("padding","0px"),this.$content.css("padding","0px")),this.$buttons=$(this.el).find(".buttons");if(this.options.buttons){var r=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),r.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find(".operations");if(this.options.operations){var r=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t,n){n?this.$content.append(t):this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div id="'+e.id+'" class="'+e.cls+'">';return e.title&&(t+='<div class="portlet-header"><div class="operations" style="float: '+e.operations_flt+';"></div>'+'<div class="portlet-title">',e.icon&&(t+='<i class="icon fa '+e.icon+'"> </i>'),t+='<span class="portlet-title-text">'+e.title+"</span>"+"</div>"+"</div>"),t+='<div class="portlet-content">',e.placement=="top"&&(t+='<div class="buttons"></div>'),t+='<div class="content"></div>',e.placement=="bottom"&&(t+='<div class="buttons"></div>'),t+="</div></div>",t}});return{View:t}}),define("mvc/ui/ui-select-default",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",error_text:"No data available",visible:!0,wait:!1,multiple:!1,searchable:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find(".select"),this.$icon=this.$el.find(".icon"),this.$button=this.$el.find(".button"),this.options.multiple?(this.$select.prop("multiple",!0),this.$select.addClass("ui-select-multiple"),this.$icon.remove()):this.$el.addClass("ui-select"),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value),this.options.visible||this.hide(),this.options.wait?this.wait():this.show();var n=this;this.$select.on("change",function(){n._change()}),this.on("change",function(){n._change()})},value:function(e){return e!==undefined&&(this.$select.val(e),this.$select.select2&&this.$select.select2("val",e)),this.$select.val()},first:function(){var e=this.$select.find("option");return e.length>0?e.val():undefined},validate:function(){return e.validate(this.value())},text:function(){return this.$select.find("option:selected").text()},show:function(){this.unwait(),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin")},unwait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down")},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){var t=this.$select.val();this.$select.find("option").remove();for(var n in e)this.$select.append(this._templateOption(e[n]));this._refresh(),this.$select.val(t),this.$select.val()||this.$select.val(this.first()),this.options.searchable&&(this.$button.hide(),this.$select.select2("destroy"),this.$select.select2())},setOnChange:function(e){this.options.onchange=e},exists:function(e){return this.$select.find('option[value="'+e+'"]').length>0},_change:function(){this.options.onchange&&this.options.onchange(this.$select.val())},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.disable(),this.$select.append(this._templateOption({value:"null",label:this.options.error_text}))):this.enable()},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){return'<div id="'+e.id+'">'+'<select id="select" class="select '+e.cls+" "+e.id+'"></select>'+'<div class="button">'+'<i class="icon"/>'+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-slider",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{min:null,max:null,step:null,precise:!1,split:1e4},initialize:function(t){var n=this;this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.useslider=this.options.max!==null&&this.options.min!==null&&this.options.max>this.options.min,this.options.step===null&&(this.options.step=1,this.options.precise&&this.useslider&&(this.options.step=(this.options.max-this.options.min)/this.options.split)),this.useslider?(this.$slider=this.$el.find("#slider"),this.$slider.slider(this.options),this.$slider.on("slide",function(e,t){n.value(t.value)})):this.$el.find(".ui-form-slider-text").css("width","100%"),this.$text=this.$el.find("#text"),this.options.value!==undefined&&this.value(this.options.value),this.$text.on("change",function(){n.value($(this).val())});var r=[];this.$text.on("keyup",function(e){r[e.which]=!1}),this.$text.on("keydown",function(e){var t=e.which;r[t]=!0,t==8||t==9||t==13||t==37||t==39||t>=48&&t<=57||t==190&&$(this).val().indexOf(".")==-1&&n.options.precise||t==189&&$(this).val().indexOf("-")==-1||r[91]||r[17]||event.preventDefault()})},value:function(e){return e!==undefined&&(isNaN(e)&&(e=0),this.options.max!==null&&(e=Math.min(e,this.options.max)),this.options.min!==null&&(e=Math.max(e,this.options.min)),this.options.onchange&&this.options.onchange(e),this.$slider&&this.$slider.slider("value",e),this.$text.val(e)),this.$text.val()},_template:function(e){return'<div id="'+e.id+'" class="ui-form-slider">'+'<input id="text" type="text" class="ui-form-slider-text"/>'+'<div id="slider" class="ui-form-slider-element"/>'+"</div>"}});return{View:t}}),define("mvc/ui/ui-options",["utils/utils"],function(e){var t=Backbone.View.extend({initialize:function(t){this.optionsDefault={visible:!0,data:[],id:e.uuid(),error_text:"No data available.",wait_text:"Please wait..."},this.options=e.merge(t,this.optionsDefault),this.setElement("<div/>"),this.$message=$("<div/>"),this.$options=$(this._template(t)),this.$el.append(this.$message),this.$el.append(this.$options),this.options.visible||this.$el.hide(),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value);var n=this;this.on("change",function(){n._change()})},update:function(e){var t=this._getValue();this.$options.empty();if(this._templateOptions)this.$options.append(this._templateOptions(e));else for(var n in e){var r=$(this._templateOption(e[n]));r.addClass("ui-option"),this.$options.append(r)}var i=this;this.$el.find("input").on("change",function(){i.value(i._getValue()),i._change()}),this._refresh(),this.value(t)},value:function(e){if(e!==undefined){e instanceof Array||(e=[e]),this.$el.find("input").prop("checked",!1);for(var t in e)this.$el.find('input[value="'+e[t]+'"]').first().prop("checked",!0)}return this._getValue()},exists:function(e){if(e!==undefined){e instanceof Array||(e=[e]);for(var t in e)if(this.$el.find('input[value="'+e[t]+'"]').length>0)return!0}return!1},first:function(){var e=this.$el.find("input");return e.length>0?e.val():undefined},validate:function(){return e.validate(this.value())},wait:function(){this._size()==0&&(this._messageShow(this.options.wait_text,"info"),this.$options.hide())},unwait:function(){this._messageHide(),this._refresh()},_change:function(){this.options.onchange&&this.options.onchange(this._getValue())},_refresh:function(){this._size()==0?(this._messageShow(this.options.error_text,"danger"),this.$options.hide()):(this._messageHide(),this.$options.css("display","inline-block"))},_getValue:function(){var e=this.$el.find(":checked");if(e.length==0)return"null";if(this.options.multiple){var t=[];return e.each(function(){t.push($(this).val())}),t}return e.val()},_size:function(){return this.$el.find(".ui-option").length},_messageShow:function(e,t){this.$message.show(),this.$message.removeClass(),this.$message.addClass("ui-message alert alert-"+t),this.$message.html(e)},_messageHide:function(){this.$message.hide()},_template:function(){return'<div class="ui-options"/>'}}),n={};n.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="radio" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var r={};r.View=t.extend({initialize:function(e){e.multiple=!0,t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="checkbox" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var i={};return i.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},value:function(e){return e!==undefined&&(this.$el.find("input").prop("checked",!1),this.$el.find("label").removeClass("active"),this.$el.find('[value="'+e+'"]').prop("checked",!0).closest("label").addClass("active")),this._getValue()},_templateOption:function(e){var t='<label class="btn btn-default">';return e.icon&&(t+='<i class="fa '+e.icon+'"/>'),t+='<input type="radio" name="'+this.options.id+'" value="'+e.value+'">'+e.label+"</label>",t},_template:function(){return'<div class="btn-group ui-radiobutton" data-toggle="buttons"/>'}}),{Base:t,Radio:n,RadioButton:i,Checkbox:r}}),define("mvc/ui/ui-drilldown",["utils/utils","mvc/ui/ui-options"],function(e,t){var n=t.Base.extend({initialize:function(e){this.display=e.display||"checkbox",e.multiple=this.display=="checkbox",t.Base.prototype.initialize.call(this,e)},_templateOption:function(e,t,n){return'<div><input name="'+this.options.id+'" class="ui-option" type="'+this.display+'" value="'+t+'">'+e+"<div/>"},_templateOptions:function(e){function n(e,t){function n(n){n?(t.fadeIn("fast"),e.removeClass("toggle-expand"),e.addClass("toggle"),e.is_expanded=!0):(t.hide(),e.removeClass("toggle"),e.addClass("toggle-expand"),e.is_expanded=!1)}e.on("click",function(){n(!e.is_expanded)})}function r(e,s){for(i in s){var o=s[i],u=o.options.length>0,a=$("<div/>");if(u){var f=$('<span class="ui-drilldown-button form-toggle icon-button toggle-expand" style="position: relative; top: 2px;"/>'),l=$("<div/>");l.append(f),l.append(t._templateOption(o.name,o.value)),a.append(l);var c=$('<div style="display: none; margin-left: 25px;"/>');r(c,o.options),a.append(c),n(f,c)}else a.append(t._templateOption(o.name,o.value));e.append(a)}}var t=this,s=$("<div/>");return r(s,e),s},_template:function(e){return'<div class="ui-options drilldown-container" id="'+e.id+'"/>'}});return{View:n}}),define("mvc/ui/ui-button-menu",["utils/utils"],function(e){return Backbone.View.extend({optionsDefault:{id:"",title:"",floating:"right",icon:null,onclick:null,cls:"ui-button-icon ui-button-menu",tooltip:"",target:"",href:"",onunload:null,visible:!0,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){$(".tooltip").hide(),e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide(),n.tooltip({title:t.tooltip,placement:"bottom"})},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null,cls:"button-menu btn-group"};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a class="dropdown-item" href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t="",n="";e.title?t="width: auto;":n="margin: 0px;";var r='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="dropdown '+e.cls+'">'+'<div class="root button dropdown-toggle" data-toggle="dropdown" style="'+n+'">'+'<i class="icon fa '+e.icon+'"/>';return e.title&&(r+=' <span class="title">'+e.title+"</span>"),r+="</div></div>",r}})}),define("mvc/ui/ui-misc",["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(e,t,n,r,i,s,o){var u=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},_template:function(e){return'<img class="ui-image '+e.cls+'" src="'+e.url+'"/>'}}),a=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<label class="ui-label '+e.cls+'">'+e.title+"</label>"},value:function(){return options.title}}),f=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" class="ui-icon"/> '+e.title+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="float: '+e.floating+';" type="button" class="'+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),c=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$button=this.$el.find(".button");var n=this;$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&!n.disabled&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled"),this.disabled=!0},enable:function(){this.$button.removeClass("disabled"),this.disabled=!1},setIcon:function(e){this.$("i").removeClass(this.options.icon).addClass(e),this.options.icon=e},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div class="button"><i class="icon fa '+e.icon+'"/> '+'<span class="title">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),h=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)" class="ui-anchor '+e.cls+'">'+e.title+"</a></div>"}}),p=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>"),this.options.message&&this.update(this.options)},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.find(".alert").append(t.message),this.$el.fadeIn(),this.timeout&&window.clearTimeout(this.timeout);if(!t.persistent){var n=this;this.timeout=window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="ui-message alert alert-'+e.status+'"/>'}}),d=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),v=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:!1,visible:!0,cls:"",area:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.$el.on("input",function(){n.options.onchange&&n.options.onchange(n.$el.val())})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return e.area?'<textarea id="'+e.id+'" class="ui-textarea '+e.cls+'"></textarea>':'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="ui-input '+e.cls+'">'}}),m=Backbone.View.extend({initialize:function(e){this.options=e,this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value)},value:function(e){return e!==undefined&&this.$("hidden").val(e),this.$("hidden").val()},_template:function(e){var t='<div id="'+e.id+'" >';return e.info&&(t+="<label>"+e.info+"</label>"),t+='<hidden value="'+e.value+'"/>'+"</div>",t}});return{Anchor:h,Button:l,ButtonIcon:c,ButtonMenu:s,Icon:f,Image:u,Input:v,Label:a,Message:p,Modal:o,RadioButton:r.RadioButton,Checkbox:r.Checkbox,Radio:r.Radio,Searchbox:d,Select:t,Hidden:m,Slider:n,Drilldown:i}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e,t,n,r,i){var s=this;e.state("wait","Requesting job results...");var o=e.get("dataset_id_job");o!=""?s._wait(e,r,i):s._submit(e,t,n,r,i)},cleanup:function(t){var n=this,r=t.get("dataset_id_job");r!=""&&(e.request({type:"PUT",url:config.root+"api/histories/none/contents/"+r,data:{deleted:!0},success:function(){n._refreshHdas()}}),t.set("dataset_id_job",""))},_submit:function(t,n,r,i,s){var o=this,u=t.id,a=t.get("type"),f=t.definition;data={tool_id:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,columns:r,settings:n}},t.state("wait","Sending job request..."),e.request({type:"POST",url:config.root+"api/tools",data:data,success:function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response."),s&&s();else{o._refreshHdas();var n=e.outputs[0];t.state("wait","Your job has been queued. You may close the browser window. The job will run in the background."),t.set("dataset_id_job",n.id),o.app.storage.save(),o._wait(t,i,s)}},error:function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the 'charts' tool. Please make sure it is installed. "+n),s&&s()}})},_wait:function(t,n,r){var i=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.get("dataset_id_job"),data:{},success:function(e){var s=!1;switch(e.state){case"ok":t.state("wait","Job completed successfully..."),n&&n(e),s=!0;break;case"error":t.state("failed","Job has failed. Please check the history for details."),r&&r(e),s=!0;break;case"running":t.state("wait","Your job is running. You may close the browser window. The job will continue in the background.")}s||setTimeout(function(){i._wait(t,n,r)},i.app.config.get("query_timeout"))}})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshContents()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e){e.groups?this._get_blocks(e):this._get_dataset(e.id,e.success,e.error)},_get_blocks:function(e){function c(i){l._get(i,function(){var s=!1;for(var o in e.groups){destination_group=e.groups[o],source_group=i.groups[o],destination_group.values||(destination_group.values=[]),destination_group.values=destination_group.values.concat(source_group.values);if(source_group.values.length==0){s=!0;break}}if(++f<u&&!s){n&&n(parseInt(f/u*100));var l=i.start+r;i=$.extend(!0,a,{start:l}),c(i)}else t()})}var t=e.success,n=e.progress,r=this.app.config.get("query_limit"),i=e.start||0,s=i+e.query_limit||i+this.app.config.get("query_limit"),o=Math.abs(s-i);if(o<=0){console.debug("FAILED - Datasets::request() - Invalid query range.");return}var u=Math.ceil(o/r)||1,a=$.extend(!0,{},e),f=0,l=this,h=$.extend(!0,a,{start:i});this._get_dataset(e.id,function(){c(h)})},_get_dataset:function(t,n,r){var i=this.list[t];if(i){n(i);return}var s=this;e.request({type:"GET",url:config.root+"api/datasets/"+t,success:function(e){switch(e.state){case"error":r&&r(e);break;default:s.list[t]=e,n(e)}}})},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.start+this.app.config.get("query_limit")+"_"+t},_get:function(e,t){e.start=e.start||0;var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f]||a==="auto"||a==="zero")continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){var t=e.start;console.debug("Datasets::_fill_from_cache() - Filling request from cache at "+t+".");var n=0;for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s],u=this._block_id(e,o.index),a=this.cache[u];a&&(n=Math.max(n,a.length))}}n==0&&console.debug("Datasets::_fill_from_cache() - Reached data range limit.");for(var r in e.groups){var i=e.groups[r];i.values=[];for(var f=0;f<n;f++)i.values[f]={x:parseInt(f)+t}}for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s];switch(o.index){case"auto":for(var f=0;f<n;f++){var l=i.values[f];l[s]=parseInt(f)+t}break;case"zero":for(var f=0;f<n;f++){var l=i.values[f];l[s]=0}break;default:var u=this._block_id(e,o.index),a=this.cache[u];for(var f=0;f<n;f++){var l=i.values[f],c=a[f];isNaN(c)&&!o.is_label&&(c=0),l[s]=c}}}}},_fetch:function(t,n){var r=t.start?t.start:0,i=this.app.config.get("query_limit"),s=0;t.columns&&(s=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+s+" column(s) at "+r+".")),s==0&&console.debug("Datasets::_fetch() - No columns requested");var o="";for(var u in t.columns)o+=t.columns[u]+",";o=o.substring(0,o.length-1);var a=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.dataset_id,data:{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},success:function(e){var t=new Array(s);for(var r=0;r<s;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var o in i){var u=i[o];u!==undefined&&u!=2147483647&&t[o].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)}})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})}),define("plugin/models/chart",["plugin/models/groups"],function(e){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(t){this.groups=new e,this.settings=new Backbone.Model},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state",e),this.set("state_info",t),this.trigger("set:state"),console.debug("Chart:state() - "+t+" ("+e+")")}})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group","mvc/visualization/visualization-model"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;var t=e.attributes.type;if(!t)return console.debug("Storage::load() - Chart type not provided. Invalid format."),!1;var r=this.app.types.get(t);if(!r)return console.debug("Storage::load() - Chart type not supported. Please re-configure the chart. Resetting chart."),!1;console.debug("Storage::load() - Loading chart type "+t+"."),this.chart.definition=r,this.chart.set(e.attributes),this.chart.state("ok","Loading saved visualization..."),this.chart.settings.set(e.settings);for(var i in e.groups)this.chart.groups.add(new n(e.groups[i]));return this.chart.set("modified",!1),!0}})}),define("utils/deferred",["utils/utils"],function(e){return Backbone.Model.extend({queue:[],process:{},counter:0,initialize:function(){this.on("refresh",function(){if(this.queue.length>0&&this.ready()){var e=this.queue[0];this.queue.splice(0,1),e&&e()}})},execute:function(e){this.queue.push(e),this.trigger("refresh")},register:function(){var t=e.uuid();return this.process[t]=!0,this.counter++,console.debug("Deferred:register() - Registering "+t),t},done:function(e){this.process[e]&&(delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh"))},reset:function(){this.queue=[]},ready:function(){return this.counter==0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({container_list:[],canvas_list:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,100),this._createContainer("div");var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("set:state",function(){var e=r.$el.find("#info"),t=r.$el.find(".charts-viewport-container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var i=r.chart.get("state");switch(i){case"ok":e.hide(),t.show();break;case"failed":n.addClass("icon fa fa-warning"),t.hide();break;default:n.addClass("icon fa fa-spinner fa-spin"),t.show()}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_createContainer:function(e,t){t=t||1;for(var n in this.container_list)this.container_list[n].remove();this.container_list=[],this.canvas_list=[];for(var n=0;n<t;n++){var r=$(this._templateContainer(e,parseInt(100/t)));this.$el.append(r),this.container_list[n]=r,this.canvas_list[n]=r.find(".charts-viewport-canvas").attr("id")}},_draw:function(e){var t=this,n=this.app.deferred.register(),r=e.get("type");this.chart_definition=e.definition;var i=1;e.settings.get("use_panels")==="true"&&(i=e.groups.length),this._createContainer(this.chart_definition.tag,i),e.state("wait","Please wait...");if(!this.chart_definition.execute||this.chart_definition.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+this.app.chartPath(r)+"/wrapper"],function(r){if(t.chart_definition.execute)t.app.jobs.request(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})},function(){this.app.deferred.done(n)});else var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){n++;for(var i in r.chart_definition.columns)t+=i+"_"+n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t={groups:[]};this.chart_definition.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var r=0,i=this;return e.groups.each(function(e){var s={};for(var o in i.chart_definition.columns){var u=i.chart_definition.columns[o];s[o]=n.merge({index:e.get(o)},u)}t.groups.push({key:++r+":"+e.get("key"),columns:s})}),t},_template:function(){return'<div class="charts-viewport"><div id="info" class="info"><span id="icon" class="icon"/><span id="text" class="text" /></div></div>'},_templateContainer:function(e,t){return'<div class="charts-viewport-container" style="width:'+t+'%;">'+'<div id="menu"/>'+"<"+e+' id="'+n.uuid()+'" class="charts-viewport-canvas">'+"</div>"}})}),define("plugin/library/screenshot",["libs/underscore"],function(e){function t(e){e.$el.find("svg").length>0?r(e):n(e)}function n(e){try{var t=e.$el.find(".jqplot-target"),n=t.jqplotToImageStr({});n&&(window.location.href=n.replace("image/png","image/octet-stream"))}catch(r){console.debug("FAILED - Screenshot::_fromCanvas() - "+r),e.error&&e.error("Please reduce your chart to a single panel and try again.")}}function r(e){var t=e.$el,n=e.url,r=e.name,s=new XMLSerializer,o=document.createElement("canvas"),u=$(o),a=t.find("svg").length,f=t.find("svg").first(),l=parseInt(f.css("height")),c=parseInt(f.css("width"));u.attr("width",c*a),u.attr("height",l),(!o.getContext||!o.getContext("2d"))&&alert("Your browser doesn't support this feature, please use a modern browser");var h=o.getContext("2d"),p=0;t.find("svg").each(function(){var e=$(this);e.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:c,height:l});var t=s.serializeToString(this);h.drawSvg(t,p,0,c,l),p+=c}),window.location.href=i(o,o.getContext("2d"),"white").replace("image/png","image/octet-stream")}function i(e,t,n){var r=e.width,i=e.height,s;if(n){s=t.getImageData(0,0,r,i);var o=t.globalCompositeOperation;t.globalCompositeOperation="destination-over",t.fillStyle=n,t.fillRect(0,0,r,i)}var u=e.toDataURL("image/png");return n&&(t.clearRect(0,0,r,i),t.putImageData(s,0,0),t.globalCompositeOperation=o),u}function s(e){window.location.href="data:none/none;base64,"+btoa(a(e).string)}function o(e){for(var t in document.styleSheets){var n=document.styleSheets[t],r=n.cssRules;if(r)for(var i=0,s=r.length;i<s;i++)try{e.find(r[i].selectorText).each(function(e,t){t.style.cssText+=r[i].style.cssText})}catch(o){}}}function u(e){var t=a(e),n={filename:name||"chart",type:"application/pdf",height:t.height,width:t.width,scale:2,svg:t.string},r=$("body"),i=r.find("#viewport-form");i.length===0&&(i=$("<form>",{id:"viewport-form",method:"post",action:"http://export.highcharts.com/",display:"none"}),r.append(i)),i.empty();for(name in n){var s=$("<input/>",{type:"hidden",name:name,value:n[name]});i.append(s)}try{i.submit()}catch(o){console.log(o)}}function a(e){if(e.$el.find("svg").length==0&&e.error){e.error("No SVG found. This chart type does not support SVG/PDF export.");return}var t=e.$el,n=t.find("svg").length,r=parseInt(t.find("svg").first().css("height")),i=parseInt(t.find("svg").first().css("width")),s=new XMLSerializer,u=$("<svg/>");u.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:i*n,height:r});var a="",f=0;return t.find("svg").each(function(){var e=$(this).clone();o(e);var t=$('<g transform="translate('+f+', 0)">');t.append(e.find("g").first()),u.append(t),f+=i}),{string:s.serializeToString(u[0]),height:r,width:i}}return{createPNG:t,createSVG:s,createPDF:u}}),define("plugin/views/viewer",["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-portlet","plugin/views/viewport","plugin/library/screenshot"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,s){this.app=e,this.chart=this.app.chart,this.viewport_view=new r(e);var o=this;this.message=new t.Message;var u=new t.ButtonMenu({icon:"fa-camera",title:"Screenshot",tooltip:"Download as PNG, SVG or PDF file"});u.addMenu({id:"button-png",title:"Save as PNG",icon:"fa-file",onclick:function(){o._wait(o.chart,function(){i.createPNG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-svg",title:"Save as SVG",icon:"fa-file-text-o",onclick:function(){o._wait(o.chart,function(){i.createSVG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-png",title:"Save as PDF",icon:"fa-file-o",onclick:function(){o.app.modal.show({title:"Send chart data for PDF creation",body:"Galaxy does not provide integrated PDF export scripts. You may click 'Continue' to create the PDF by using a 3rd party service (https://export.highcharts.com)",buttons:{Cancel:function(){o.app.modal.hide()},Continue:function(){o.app.modal.hide(),o._wait(o.chart,function(){i.createPDF({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}})}}),this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",scrollable:!1,operations:{edit_button:new t.ButtonIcon({icon:"fa-edit",tooltip:"Customize this chart",title:"Editor",onclick:function(){o._wait(o.chart,function(){o.app.go("editor")})}}),picture_button_menu:u}}),this.portlet.append(this.message.$el),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var o=this;this.chart.on("change:title",function(){o._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){this.app.deferred.ready()?t():this.message.update({message:"Your chart is currently being processed. Please wait and try again."})}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{title_new:"",operations:null,onnew:null,max:null,onchange:null},initialize:function(t){this.visible=!1,this.$nav=null,this.$content=null,this.first_tab=null,this.current_id=null,this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},size:function(){return _.size(this.list)},current:function(){return this.$el.find(".tab-pane.active").attr("id")},add:function(e){var t=this,n=e.id,r=$(this._template_tab(e)),i=$(this._template_tab_content(e));this.list[n]=e.ondel?!0:!1,this.options.onnew?this.$nav.find("#new-tab").before(r):this.$nav.append(r),i.append(e.$el),this.$content.append(i),this.size()==1&&(r.addClass("active"),i.addClass("active"),this.first_tab=n),this.options.max&&this.size()>=this.options.max&&this.$el.find("#new-tab").hide();if(e.ondel){var s=r.find("#delete");s.tooltip({title:"Delete this tab",placement:"bottom",container:t.$el}),s.on("click",function(){return s.tooltip("destroy"),t.$el.find(".tooltip").remove(),e.ondel(),!1})}r.on("click",function(r){r.preventDefault(),e.onclick?e.onclick():t.show(n)}),this.current_id||(this.current_id=n)},del:function(e){this.$el.find("#tab-"+e).remove(),this.$el.find("#"+e).remove(),this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab),this.list[e]&&delete this.list[e],this.size()<this.options.max&&this.$el.find("#new-tab").show()},delRemovable:function(){for(var e in this.list)this.del(e)},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&(this.$el.find("#tab-"+this.current_id).removeClass("active"),this.$el.find("#"+this.current_id).removeClass("active"),this.$el.find("#tab-"+e).addClass("active"),this.$el.find("#"+e).addClass("active"),this.current_id=e),this.options.onchange&&this.options.onchange(e)},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.$el.find("#tab-title-text-"+e);return t&&n.html(t),n.html()},retitle:function(e){var t=0;for(var n in this.list)this.title(n,++t+": "+e)},_template:function(e){return'<div class="ui-tabs tabbable tabs-left"><ul id="tab-navigation" class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div id="tab-content" class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i class="ui-tabs-add fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="tab-'+e.id+'" class="tab-element">'+'<a id="tab-title-link-'+e.id+'" title="" href="#'+e.id+'" data-original-title="">'+'<span id="tab-title-text-'+e.id+'" class="tab-title-text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" class="ui-tabs-delete fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("mvc/ui/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null,cls:"ui-table",cls_tr:""},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=this._row()},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},append:function(e,t){this._commit(e,t,!1)},prepend:function(e,t){this._commit(e,t,!0)},get:function(e){return this.$el.find("#"+e)},del:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},delAll:function(){this.$tbody.empty(),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t,n){this.del(e),this.row.attr("id",e),n?this.$tbody.prepend(this.row):this.$tbody.append(this.row),t&&(this.row.hide(),this.row.fadeIn()),this.row=this._row(),this.row_count++,this._refresh()},_row:function(){return $('<tr class="'+this.options.cls_tr+'"></tr>')},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n!=""&&n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="'+e.cls+'">'+"<thead></thead>"+"<tbody></tbody>"+"</table>"+"<tmessage>"+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(e){s.group.set("key",e)}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.chart.definition;this.table.delAll();var s={};for(var o in i.columns){var u=i.columns[o];if(!u){console.debug("Group::_refreshTable() - Skipping column definition.");continue}var a=new t.Select.View({id:"select_"+o,wait:!0}),f=u.title;u.is_unique&&(f+=" (all data labels)"),this.table.add(f,"25%"),this.table.add(a.$el),this.table.append(o),s[o]=a}this.chart.state("wait","Loading metadata...");var l=this.app.deferred.register(),c={id:e,success:function(e){for(var t in s)r._addRow(t,e,s,i.columns[t]);r.chart.state("ok","Metadata initialized..."),r.app.deferred.done(l)}};this.app.datasets.request(c)},_addRow:function(e,t,n,r){var i=this,s=r.is_label,o=r.is_auto,u=r.is_numeric,a=r.is_unique,f=r.is_zero,l=[],c=n[e];o&&l.push({label:"Column: Row Number",value:"auto"}),f&&l.push({label:"Column: None",value:"zero"});var h=t.metadata_column_types;for(var p in h){var d=!1;h[p]=="int"||h[p]=="float"?d=u:d=s,d&&l.push({label:"Column: "+(parseInt(p)+1)+" ["+h[p]+"]",value:p})}c.update(l),a&&this.chart.groups.first()&&this.group.set(e,this.chart.groups.first().get(e));if(!c.exists(this.group.get(e))){var v=c.first();console.debug('Group()::_addRow() - Switching model value from "'+this.group.get(e)+'" to "'+v+'".'),this.group.set(e,v)}c.value(this.group.get(e)),this.group.off("change:"+e),this.group.on("change:"+e,function(){c.value(i.group.get(e))}),c.setOnChange(function(t){a?i.chart.groups.each(function(n){n.set(e,t)}):i.group.set(e,t),i.chart.set("modified",!0)}),c.show()},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){var r=Backbone.View.extend({optionsDefault:{title:"",content:"",mode:""},list:[],initialize:function(r,i){this.app=r,this.options=n.merge(i,this.optionsDefault),this.table_title=new t.Label({title:this.options.title}),this.table=new e.View({content:this.options.content});var s=$('<div class="ui-table-form"/>');this.options.title&&s.append(n.wrap(this.table_title.$el)),s.append(n.wrap(this.table.$el)),this.setElement(s)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.delAll(),this.list=[];for(var n in e)this._add(e[n].id||n,e[n],t);for(var n in this.list)this.list[n].trigger("change")},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:"field-"+e,placeholder:n.placeholder,value:r.get(e),onchange:function(t){r.set(e,t)}});break;case"radiobutton":s=new t.RadioButton.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"select":s=new t.Select.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"dataset":s=new t.Select.View({id:"field-"+e,onchange:function(t){r.set(e,t)}}),i.app.datasets.on("all",function(){var t=[];i.app.datasets.each(function(e){e.get("datatype_id")==n.data&&t.push({value:e.get("id"),label:e.get("name")})}),s.update(t),r.get(e)||r.set(e,s.first()),s.value(r.get(e))}),i.app.datasets.trigger("all.datasets");break;case"textarea":s=new t.Textarea({id:"field-"+e,onchange:function(){r.set(e,s.value())}});break;case"separator":s=$("<div/>");break;default:s=new t.Input({id:"field-"+e,placeholder:n.placeholder,type:n.type,onchange:function(){r.set(e,s.value())}})}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),n.info&&u.append('<div class="ui-table-form-info">'+n.info+"</div>"),this.options.style=="bold"?(this.table.add((new t.Label({title:n.title,cls:"form-label"})).$el),this.table.add(u)):(this.table.add('<span class="ui-table-form-title">'+n.title+"</span>","25%"),this.table.add(u))}else this.table.add('<div class="ui-table-form-separator">'+n.title+":<div/>"),this.table.add($("<div/>"));this.table.append(e),n.hide&&this.table.get(e).hide()}});return{View:r}}),define("plugin/views/settings",["mvc/ui/ui-misc","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View(e,{title:"Configuration",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refresh()})},_refresh:function(){var e=this.chart.definition;if(!e)return;this.form.title(e.category+" - "+e.title+":"),this.form.update(e.settings,this.chart.settings)}})}),define("plugin/views/types",["utils/utils","mvc/ui/ui-misc"],function(e,t){return Backbone.View.extend({optionsDefault:{onchange:null,ondblclick:null},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(n,r){var i=this;this.app=n,this.options=e.merge(r,this.optionsDefault);var s=$('<div class="charts-grid"/>');s.append(e.wrap((new t.Label({title:"How many data points would you like to analyze?"})).$el)),this.library=new t.RadioButton.View({data:[{label:"Few (<500)",value:"small"},{label:"Some (<10k)",value:"medium"},{label:"Many (>10k)",value:"large"}],onchange:function(e){i._filter(e)}}),s.append(e.wrap(this.library.$el)),this.setElement(s),this._render(),this.library.value("small"),this.library.trigger("change")},value:function(e){var t=this.$el.find(".current").attr("id");e!==undefined&&(this.$el.find(".current").removeClass("current"),this.$el.find("#"+e).addClass("current"));var n=this.$el.find(".current").attr("id");return n===undefined?null:(n!=t&&this.options.onchange&&this.options.onchange(e),n)},_filter:function(e){this.$el.find(".header").hide();var t=this.app.types.attributes;for(var n in t){var r=t[n],i=this.$el.find("#"+n),s=this.$el.find("#types-header-"+this.categories_index[r.category]),o=r.keywords||"";o.indexOf(e)>=0?(i.show(),s.show()):i.hide()}},_render:function(){this.categories={},this.categories_index={};var e=0,t=this.app.types.attributes;for(var n in t){var r=t[n],i=r.category;this.categories[i]||(this.categories[i]={},this.categories_index[i]=e++),this.categories[i][n]=r}for(var i in this.categories){var s=$('<div style="clear: both;"/>');s.append(this._template_header({id:"types-header-"+this.categories_index[i],title:i}));for(var n in this.categories[i]){var r=this.categories[i][n],o=r.title+" ("+r.library+")";r.zoomable&&(o='<span class="fa fa-search-plus"/>'+o),s.append(this._template_item({id:n,title:o,url:config.app_root+"charts/"+this.app.chartPath(n)+"/logo.png"}))}this.$el.append(s)}},_onclick:function(e){var t=this.value(),n=$(e.target).closest(".item").attr("id");n!=""&&n&&t!=n&&this.value(n)},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_template_header:function(e){return'<div id="'+e.id+'" class="header">'+"• "+e.title+"<div>"},_template_item:function(e){return'<div id="'+e.id+'" class="item">'+'<img class="image" src="'+e.url+'">'+'<div class="title">'+e.title+"</div>"+"<div>"}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","mvc/ui/ui-misc","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings","plugin/views/types"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({initialize:function(i,s){var o=this;this.app=i,this.chart=this.app.chart,this.message=new t.Message,this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new t.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){o._saveChart()}}),back:new t.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Cancel",onclick:function(){o.app.go("viewer"),o.app.storage.load()}})}}),this.types=new a(i,{onchange:function(e){var t=o.app.types.get(e);t||console.debug("FAILED - Editor::onchange() - Chart type not supported."),o.chart.definition=t,o.chart.settings.clear(),o.chart.set({type:e}),o.chart.set("modified",!0),console.debug("Editor::onchange() - Switched chart type.")},ondblclick:function(e){o._saveChart()}}),this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=o._addGroupModel();o.tabs.show(e.id)}}),this.title=new t.Input({placeholder:"Chart title",onchange:function(){o.chart.set("title",o.title.value())}});var f=$("<div/>");f.append(r.wrap((new t.Label({title:"Provide a chart title:"})).$el)),f.append(r.wrap(this.title.$el)),f.append(r.wrap(this.types.$el)),this.tabs.add({id:"main",title:"Start",$el:f}),this.settings=new u(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.message.$el),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var o=this;this.chart.on("change:title",function(e){o._refreshTitle()}),this.chart.on("change:type",function(e){o.types.value(e.get("type"))}),this.chart.on("reset",function(e){o._resetChart()}),this.app.chart.on("redraw",function(e){o.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){o._addGroup(e)}),this.app.chart.groups.on("remove",function(e){o._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){o._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){o._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Data label"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new s({id:r.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new o(this.app,{group:e});this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",r.uuid()),this.chart.set("type","nvd3_bar"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.types.value(),title:this.title.value(),date:r.time()});if(this.chart.groups.length==0){this.message.update({message:"Please select data columns before drawing the chart."});var e=this._addGroupModel();this.tabs.show(e.id);return}var t=this,n=!0,i=this.chart.definition;this.chart.groups.each(function(e){if(!n)return;for(var r in i.columns)if(e.attributes[r]=="null"){t.message.update({status:"danger",message:"This chart type requires column types not found in your tabular file."}),t.tabs.show(e.id),n=!1;return}});if(!n)return;this.app.go("viewer");var t=this;this.app.deferred.execute(function(){t.app.storage.save(),t.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e4,query_timeout:100}})}),define("plugin/charts/forms/default",[],function(){return{title:"",category:"",library:"",tag:"",keywords:"",settings:{separator_x:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["x_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["x_axis_precision"]}},{label:"Float",value:"f",operations:{show:["x_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["x_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["x_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["x_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["x_axis_precision"]}}]},x_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_y:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["y_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["y_axis_precision"]}},{label:"Float",value:"f",operations:{show:["y_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["y_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["y_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["y_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["y_axis_precision"]}}]},y_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{title:"Use multi-panels",info:"Would you like to separate your data into individual panels?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),function(){function t(e,t){return(new Date(t,e+1,0)).getDate()}function n(e,t,n){return function(r,i,s){var o=e(r),u=[];o<r&&t(o);if(s>1)while(o<i){var a=new Date(+o);n(a)%s===0&&u.push(a),t(o)}else while(o<i)u.push(new Date(+o)),t(o);return u}}var e=window.nv||{};e.version="1.1.15b",e.dev=!0,window.nv=e,e.tooltip=e.tooltip||{},e.utils=e.utils||{},e.models=e.models||{},e.charts={},e.graphs=[],e.logs={},e.dispatch=d3.dispatch("render_start","render_end"),e.dev&&(e.dispatch.on("render_start",function(t){e.logs.startTime=+(new Date)}),e.dispatch.on("render_end",function(t){e.logs.endTime=+(new Date),e.logs.totalTime=e.logs.endTime-e.logs.startTime,e.log("total",e.logs.totalTime)})),e.log=function(){if(e.dev&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(e.dev&&typeof console.log=="function"&&Function.prototype.bind){var t=Function.prototype.bind.call(console.log,console);t.apply(console,arguments)}return arguments[arguments.length-1]},e.render=function(n){n=n||1,e.render.active=!0,e.dispatch.render_start(),setTimeout(function(){var t,r;for(var i=0;i<n&&(r=e.render.queue[i]);i++)t=r.generate(),typeof r.callback==typeof Function&&r.callback(t),e.graphs.push(t);e.render.queue.splice(0,i),e.render.queue.length?setTimeout(arguments.callee,0):(e.dispatch.render_end(),e.render.active=!1)},0)},e.render.active=!1,e.render.queue=[],e.addGraph=function(t){typeof arguments[0]==typeof Function&&(t={generate:arguments[0],callback:arguments[1]}),e.render.queue.push(t),e.render.active||e.render()},e.identity=function(e){return e},e.strip=function(e){return e.replace(/(\s|&)/g,"")},d3.time.monthEnd=function(e){return new Date(e.getFullYear(),e.getMonth(),0)},d3.time.monthEnds=n(d3.time.monthEnd,function(e){e.setUTCDate(e.getUTCDate()+1),e.setDate(t(e.getMonth()+1,e.getFullYear()))},function(e){return e.getMonth()}),e.interactiveGuideline=function(){function c(o){o.each(function(o){function g(){var e=d3.mouse(this),n=e[0],r=e[1],o=!0,a=!1;l&&(n=d3.event.offsetX,r=d3.event.offsetY,d3.event.target.tagName!=="svg"&&(o=!1),d3.event.target.className.baseVal.match("nv-legend")&&(a=!0)),o&&(n-=i.left,r-=i.top);if(n<0||r<0||n>p||r>d||d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined||a){if(l&&d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined&&d3.event.relatedTarget.className.match(t.nvPointerEventsClass))return;u.elementMouseout({mouseX:n,mouseY:r}),c.renderGuideLine(null);return}var f=s.invert(n);u.elementMousemove({mouseX:n,mouseY:r,pointXValue:f}),d3.event.type==="dblclick"&&u.elementDblclick({mouseX:n,mouseY:r,pointXValue:f})}var h=d3.select(this),p=n||960,d=r||400,v=h.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([o]),m=v.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");m.append("g").attr("class","nv-interactiveGuideLine");if(!f)return;f.on("mousemove",g,!0).on("mouseout",g,!0).on("dblclick",g),c.renderGuideLine=function(t){if(!a)return;var n=v.select(".nv-interactiveGuideLine").selectAll("line").data(t!=null?[e.utils.NaNtoZero(t)]:[],String);n.enter().append("line").attr("class","nv-guideline").attr("x1",function(e){return e}).attr("x2",function(e){return e}).attr("y1",d).attr("y2",0),n.exit().remove()}})}var t=e.models.tooltip(),n=null,r=null,i={left:0,top:0},s=d3.scale.linear(),o=d3.scale.linear(),u=d3.dispatch("elementMousemove","elementMouseout","elementDblclick"),a=!0,f=null,l=navigator.userAgent.indexOf("MSIE")!==-1;return c.dispatch=u,c.tooltip=t,c.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.left=typeof e.left!="undefined"?e.left:i.left,c):i},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.xScale=function(e){return arguments.length?(s=e,c):s},c.showGuideLine=function(e){return arguments.length?(a=e,c):a},c.svgContainer=function(e){return arguments.length?(f=e,c):f},c},e.interactiveBisect=function(e,t,n){if(!e instanceof Array)return null;typeof n!="function"&&(n=function(e,t){return e.x});var r=d3.bisector(n).left,i=d3.max([0,r(e,t)-1]),s=n(e[i],i);typeof s=="undefined"&&(s=i);if(s===t)return i;var o=d3.min([i+1,e.length-1]),u=n(e[o],o);return typeof u=="undefined"&&(u=o),Math.abs(u-t)>=Math.abs(s-t)?i:o},e.nearestValueIndex=function(e,t,n){var r=Infinity,i=null;return e.forEach(function(e,s){var o=Math.abs(t-e);o<=r&&o<n&&(r=o,i=s)}),i},function(){window.nv.tooltip={},window.nv.models.tooltip=function(){function y(){if(a){var e=d3.select(a);e.node().tagName!=="svg"&&(e=e.select("svg"));var t=e.node()?e.attr("viewBox"):null;if(t){t=t.split(" ");var n=parseInt(e.style("width"))/t[2];l.left=l.left*n,l.top=l.top*n}}}function b(e){var t;a?t=d3.select(a):t=d3.select("body");var n=t.select(".nvtooltip");return n.node()===null&&(n=t.append("div").attr("class","nvtooltip "+(u?u:"xy-tooltip")).attr("id",h)),n.node().innerHTML=e,n.style("top",0).style("left",0).style("opacity",0),n.selectAll("div, table, td, tr").classed(p,!0),n.classed(p,!0),n.node()}function w(){if(!c)return;if(!g(n))return;y();var t=l.left,u=o!=null?o:l.top,h=b(m(n));f=h;if(a){var p=a.getElementsByTagName("svg")[0],d=p?p.getBoundingClientRect():a.getBoundingClientRect(),v={left:0,top:0};if(p){var E=p.getBoundingClientRect(),S=a.getBoundingClientRect(),x=E.top;if(x<0){var T=a.getBoundingClientRect();x=Math.abs(x)>T.height?0:x}v.top=Math.abs(x-S.top),v.left=Math.abs(E.left-S.left)}t+=a.offsetLeft+v.left-2*a.scrollLeft,u+=a.offsetTop+v.top-2*a.scrollTop}return s&&s>0&&(u=Math.floor(u/s)*s),e.tooltip.calcTooltipPosition([t,u],r,i,h),w}var t=null,n=null,r="w",i=50,s=25,o=null,u=null,a=null,f=null,l={left:null,top:null},c=!0,h="nvtooltip-"+Math.floor(Math.random()*1e5),p="nv-pointer-events-none",d=function(e,t){return e},v=function(e){return e},m=function(e){if(t!=null)return t;if(e==null)return"";var n=d3.select(document.createElement("table")),r=n.selectAll("thead").data([e]).enter().append("thead");r.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(v(e.value));var i=n.selectAll("tbody").data([e]).enter().append("tbody"),s=i.selectAll("tr").data(function(e){return e.series}).enter().append("tr").classed("highlight",function(e){return e.highlight});s.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(e){return e.color}),s.append("td").classed("key",!0).html(function(e){return e.key}),s.append("td").classed("value",!0).html(function(e,t){return d(e.value,t)}),s.selectAll("td").each(function(e){if(e.highlight){var t=d3.scale.linear().domain([0,1]).range(["#fff",e.color]),n=.6;d3.select(this).style("border-bottom-color",t(n)).style("border-top-color",t(n))}});var o=n.node().outerHTML;return e.footer!==undefined&&(o+="<div class='footer'>"+e.footer+"</div>"),o},g=function(e){return e&&e.series&&e.series.length>0?!0:!1};return w.nvPointerEventsClass=p,w.content=function(e){return arguments.length?(t=e,w):t},w.tooltipElem=function(){return f},w.contentGenerator=function(e){return arguments.length?(typeof e=="function"&&(m=e),w):m},w.data=function(e){return arguments.length?(n=e,w):n},w.gravity=function(e){return arguments.length?(r=e,w):r},w.distance=function(e){return arguments.length?(i=e,w):i},w.snapDistance=function(e){return arguments.length?(s=e,w):s},w.classes=function(e){return arguments.length?(u=e,w):u},w.chartContainer=function(e){return arguments.length?(a=e,w):a},w.position=function(e){return arguments.length?(l.left=typeof e.left!="undefined"?e.left:l.left,l.top=typeof e.top!="undefined"?e.top:l.top,w):l},w.fixedTop=function(e){return arguments.length?(o=e,w):o},w.enabled=function(e){return arguments.length?(c=e,w):c},w.valueFormatter=function(e){return arguments.length?(typeof e=="function"&&(d=e),w):d},w.headerFormatter=function(e){return arguments.length?(typeof e=="function"&&(v=e),w):v},w.id=function(){return h},w},e.tooltip.show=function(t,n,r,i,s,o){var u=document.createElement("div");u.className="nvtooltip "+(o?o:"xy-tooltip");var a=s;if(!s||s.tagName.match(/g|svg/i))a=document.getElementsByTagName("body")[0];u.style.left=0,u.style.top=0,u.style.opacity=0,u.innerHTML=n,a.appendChild(u),s&&(t[0]=t[0]-s.scrollLeft,t[1]=t[1]-s.scrollTop),e.tooltip.calcTooltipPosition(t,r,i,u)},e.tooltip.findFirstNonSVGParent=function(e){while(e.tagName.match(/^g|svg$/i)!==null)e=e.parentNode;return e},e.tooltip.findTotalOffsetTop=function(e,t){var n=t;do isNaN(e.offsetTop)||(n+=e.offsetTop);while(e=e.offsetParent);return n},e.tooltip.findTotalOffsetLeft=function(e,t){var n=t;do isNaN(e.offsetLeft)||(n+=e.offsetLeft);while(e=e.offsetParent);return n},e.tooltip.calcTooltipPosition=function(t,n,r,i){var s=parseInt(i.offsetHeight),o=parseInt(i.offsetWidth),u=e.utils.windowSize().width,a=e.utils.windowSize().height,f=window.pageYOffset,l=window.pageXOffset,c,h;a=window.innerWidth>=document.body.scrollWidth?a:a-16,u=window.innerHeight>=document.body.scrollHeight?u:u-16,n=n||"s",r=r||20;var p=function(t){return e.tooltip.findTotalOffsetTop(t,h)},d=function(t){return e.tooltip.findTotalOffsetLeft(t,c)};switch(n){case"e":c=t[0]-o-r,h=t[1]-s/2;var v=d(i),m=p(i);v<l&&(c=t[0]+r>l?t[0]+r:l-v+c),m<f&&(h=f-m+h),m+s>f+a&&(h=f+a-m+h-s);break;case"w":c=t[0]+r,h=t[1]-s/2;var v=d(i),m=p(i);v+o>u&&(c=t[0]-o-r),m<f&&(h=f+5),m+s>f+a&&(h=f+a-m+h-s);break;case"n":c=t[0]-o/2-5,h=t[1]+r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),m+s>f+a&&(h=f+a-m+h-s);break;case"s":c=t[0]-o/2,h=t[1]-s-r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),f>m&&(h=f);break;case"none":c=t[0],h=t[1]-r;var v=d(i),m=p(i)}return i.style.left=c+"px",i.style.top=h+"px",i.style.opacity=1,i.style.position="absolute",i},e.tooltip.cleanup=function(){var e=document.getElementsByClassName("nvtooltip"),t=[];while(e.length)t.push(e[0]),e[0].style.transitionDelay="0 !important",e[0].style.opacity=0,e[0].className="nvtooltip-pending-removal";setTimeout(function(){while(t.length){var e=t.pop();e.parentNode.removeChild(e)}},500)}}(),e.utils.windowSize=function(){var e={width:640,height:480};return document.body&&document.body.offsetWidth&&(e.width=document.body.offsetWidth,e.height=document.body.offsetHeight),document.compatMode=="CSS1Compat"&&document.documentElement&&document.documentElement.offsetWidth&&(e.width=document.documentElement.offsetWidth,e.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(e.width=window.innerWidth,e.height=window.innerHeight),e},e.utils.windowResize=function(e){if(e===undefined)return;var t=window.onresize;window.onresize=function(n){typeof t=="function"&&t(n),e(n)}},e.utils.getColor=function(t){return arguments.length?Object.prototype.toString.call(t)==="[object Array]"?function(e,n){return e.color||t[n%t.length]}:t:e.utils.defaultColor()},e.utils.defaultColor=function(){var e=d3.scale.category20().range();return function(t,n){return t.color||e[n%e.length]}},e.utils.customTheme=function(e,t,n){t=t||function(e){return e.key},n=n||d3.scale.category20().range();var r=n.length;return function(i,s){var o=t(i);return r||(r=n.length),typeof e[o]!="undefined"?typeof e[o]=="function"?e[o]():e[o]:n[--r]}},e.utils.pjax=function(t,n){function r(r){d3.html(r,function(r){var i=d3.select(n).node();i.parentNode.replaceChild(d3.select(r).select(n).node(),i),e.utils.pjax(t,n)})}d3.selectAll(t).on("click",function(){history.pushState(this.href,this.textContent,this.href),r(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&r(d3.event.state)})},e.utils.calcApproxTextWidth=function(e){if(typeof e.style=="function"&&typeof e.text=="function"){var t=parseInt(e.style("font-size").replace("px","")),n=e.text().length;return n*t*.5}return 0},e.utils.NaNtoZero=function(e){return typeof e!="number"||isNaN(e)||e===null||e===Infinity?0:e},e.utils.optionsFunc=function(e){return e&&d3.map(e).forEach(function(e,t){typeof this[e]=="function"&&this[e](t)}.bind(this)),this},e.models.axis=function(){function m(e){return e.each(function(e){var i=d3.select(this),m=i.selectAll("g.nv-wrap.nv-axis").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),y=g.append("g"),b=m.select("g");p!==null?t.ticks(p):(t.orient()=="top"||t.orient()=="bottom")&&t.ticks(Math.abs(s.range()[1]-s.range()[0])/100),b.call(t),v=v||t.scale();var w=t.tickFormat();w==null&&(w=v.tickFormat());var E=b.selectAll("text.nv-axislabel").data([o||null]);E.exit().remove();switch(t.orient()){case"top":E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",0).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+s(e)+",0)"}).select("text").attr("dy","-0.5em").attr("y",-t.tickPadding()).attr("text-anchor","middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+s.range()[t]+",0)"})}break;case"bottom":var T=36,N=30,C=b.selectAll("g").select("text");if(f%360){C.each(function(e,t){var n=this.getBBox().width;n>N&&(N=n)});var k=Math.abs(Math.sin(f*Math.PI/180)),T=(k?k*N:N)+30;C.attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f%360>0?"start":"end")}E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",T).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data([s.domain()[0],s.domain()[s.domain().length-1]]);x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",t.tickPadding()).attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f?f%360>0?"start":"end":"middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"})}c&&C.attr("transform",function(e,t){return"translate(0,"+(t%2==0?"0":"12")+")"});break;case"right":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"begin").attr("transform",l?"rotate(90)":"").attr("y",l?-Math.max(n.right,r)+12:-10).attr("x",l?s.range()[0]/2:t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+s(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",t.tickPadding()).style("text-anchor","start").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}break;case"left":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"end").attr("transform",l?"rotate(-90)":"").attr("y",l?-Math.max(n.left,r)+d:-10).attr("x",l?-s.range()[0]/2:-t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+v(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-t.tickPadding()).attr("text-anchor","end").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}}E.text(function(e){return e}),u&&(t.orient()==="left"||t.orient()==="right")&&(b.selectAll("g").each(function(e,t){d3.select(this).select("text").attr("opacity",1);if(s(e)<s.range()[1]+10||s(e)>s.range()[0]-10)(e>1e-10||e<-1e-10)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0)}),s.domain()[0]==s.domain()[1]&&s.domain()[0]==0&&m.selectAll("g.nv-axisMaxMin").style("opacity",function(e,t){return t?0:1}));if(u&&(t.orient()==="top"||t.orient()==="bottom")){var L=[];m.selectAll("g.nv-axisMaxMin").each(function(e,t){try{t?L.push(s(e)-this.getBBox().width-4):L.push(s(e)+this.getBBox().width+4)}catch(n){t?L.push(s(e)-4):L.push(s(e)+4)}}),b.selectAll("g").each(function(e,t){if(s(e)<L[0]||s(e)>L[1])e>1e-10||e<-1e-10?d3.select(this).remove():d3.select(this).select("text").remove()})}a&&b.selectAll(".tick").filter(function(e){return!parseFloat(Math.round(e.__data__*1e5)/1e6)&&e.__data__!==undefined}).classed("zero",!0),v=s.copy()}),m}var t=d3.svg.axis(),n={top:0,right:0,bottom:0,left:0},r=75,i=60,s=d3.scale.linear(),o=null,u=!0,a=!0,f=0,l=!0,c=!1,h=!1,p=null,d=12;t.scale(s).orient("bottom").tickFormat(function(e){return e});var v;return m.axis=t,d3.rebind(m,t,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.ticks=function(e){return arguments.length?(p=e,m):p},m.height=function(e){return arguments.length?(i=e,m):i},m.axisLabel=function(e){return arguments.length?(o=e,m):o},m.showMaxMin=function(e){return arguments.length?(u=e,m):u},m.highlightZero=function(e){return arguments.length?(a=e,m):a},m.scale=function(e){return arguments.length?(s=e,t.scale(s),h=typeof s.rangeBands=="function",d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m):s},m.rotateYLabel=function(e){return arguments.length?(l=e,m):l},m.rotateLabels=function(e){return arguments.length?(f=e,m):f},m.staggerLabels=function(e){return arguments.length?(c=e,m):c},m.axisLabelDistance=function(e){return arguments.length?(d=e,m):d},m},e.models.historicalBar=function(){function w(E){return E.each(function(w){var E=n-t.left-t.right,S=r-t.top-t.bottom,T=d3.select(this);s.domain(d||d3.extent(w[0].values.map(u).concat(f))),c?s.range(m||[E*.5/w[0].values.length,E*(w[0].values.length-.5)/w[0].values.length]):s.range(m||[0,E]),o.domain(v||d3.extent(w[0].values.map(a).concat(l))).range(g||[S,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=T.selectAll("g.nv-wrap.nv-historicalBar-"+i).data([w[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+i),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-bars"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){y.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",E).attr("height",S),A.attr("clip-path",h?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-bars").selectAll(".nv-bar").data(function(e){return e},function(e,t){return u(e,t)});O.exit().remove();var M=O.enter().append("rect").attr("x",0).attr("y",function(t,n){return e.utils.NaNtoZero(o(Math.max(0,a(t,n))))}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.abs(o(a(t,n))-o(0)))}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).on("mouseover",function(e,t){if(!b)return;d3.select(this).classed("hover",!0),y.elementMouseover({point:e,series:w[0],pos:[s(u(e,t)),o(a(e,t))],pointIndex:t,seriesIndex:0,e:d3.event})}).on("mouseout",function(e,t){if(!b)return;d3.select(this).classed("hover",!1),y.elementMouseout({point:e,series:w[0],pointIndex:t,seriesIndex:0,e:d3.event})}).on("click",function(e,t){if(!b)return;y.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){if(!b)return;y.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("fill",function(e,t){return p(e,t)}).attr("class",function(e,t,n){return(a(e,t)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+n+"-"+t}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).attr("width",E/w[0].values.length*.9),O.attr("y",function(t,n){var r=a(t,n)<0?o(0):o(0)-o(a(t,n))<1?o(0)-1:o(a(t,n));return e.utils.NaNtoZero(r)}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.max(Math.abs(o(a(t,n))-o(0)),1))})}),w}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[],l=[0],c=!1,h=!0,p=e.utils.defaultColor(),d,v,m,g,y=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),b=!0;return w.highlightPoint=function(e,t){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar-0-"+e).classed("hover",t)},w.clearHighlights=function(){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar.hover").classed("hover",!1)},w.dispatch=y,w.options=e.utils.optionsFunc.bind(w),w.x=function(e){return arguments.length?(u=e,w):u},w.y=function(e){return arguments.length?(a=e,w):a},w.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,w):t},w.width=function(e){return arguments.length?(n=e,w):n},w.height=function(e){return arguments.length?(r=e,w):r},w.xScale=function(e){return arguments.length?(s=e,w):s},w.yScale=function(e){return arguments.length?(o=e,w):o},w.xDomain=function(e){return arguments.length?(d=e,w):d},w.yDomain=function(e){return arguments.length?(v=e,w):v},w.xRange=function(e){return arguments.length?(m=e,w):m},w.yRange=function(e){return arguments.length?(g=e,w):g},w.forceX=function(e){return arguments.length?(f=e,w):f},w.forceY=function(e){return arguments.length?(l=e,w):l},w.padData=function(e){return arguments.length?(c=e,w):c},w.clipEdge=function(e){return arguments.length?(h=e,w):h},w.color=function(t){return arguments.length?(p=e.utils.getColor(t),w):p},w.id=function(e){return arguments.length?(i=e,w):i},w.interactive=function(e){return arguments.length?(b=!1,w):b},w},e.models.bullet=function(){function m(e){return e.each(function(e,n){var p=c-t.left-t.right,m=h-t.top-t.bottom,g=d3.select(this),y=i.call(this,e,n).slice().sort(d3.descending),b=s.call(this,e,n).slice().sort(d3.descending),w=o.call(this,e,n).slice().sort(d3.descending),E=u.call(this,e,n).slice(),S=a.call(this,e,n).slice(),x=f.call(this,e,n).slice(),T=d3.scale.linear().domain(d3.extent(d3.merge([l,y]))).range(r?[p,0]:[0,p]),N=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(T.range());this.__chart__=T;var C=d3.min(y),k=d3.max(y),L=y[1],A=g.selectAll("g.nv-wrap.nv-bullet").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),M=O.append("g"),_=A.select("g");M.append("rect").attr("class","nv-range nv-rangeMax"),M.append("rect").attr("class","nv-range nv-rangeAvg"),M.append("rect").attr("class","nv-range nv-rangeMin"),M.append("rect").attr("class","nv-measure"),M.append("path").attr("class","nv-markerTriangle"),A.attr("transform","translate("+t.left+","+t.top+")");var D=function(e){return Math.abs(N(e)-N(0))},P=function(e){return Math.abs(T(e)-T(0))},H=function(e){return e<0?N(e):N(0)},B=function(e){return e<0?T(e):T(0)};_.select("rect.nv-rangeMax").attr("height",m).attr("width",P(k>0?k:C)).attr("x",B(k>0?k:C)).datum(k>0?k:C),_.select("rect.nv-rangeAvg").attr("height",m).attr("width",P(L)).attr("x",B(L)).datum(L),_.select("rect.nv-rangeMin").attr("height",m).attr("width",P(k)).attr("x",B(k)).attr("width",P(k>0?C:k)).attr("x",B(k>0?C:k)).datum(k>0?C:k),_.select("rect.nv-measure").style("fill",d).attr("height",m/3).attr("y",m/3).attr("width",w<0?T(0)-T(w[0]):T(w[0])-T(0)).attr("x",B(w)).on("mouseover",function(){v.elementMouseover({value:w[0],label:x[0]||"Current",pos:[T(w[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:w[0],label:x[0]||"Current"})});var j=m/6;b[0]?_.selectAll("path.nv-markerTriangle").attr("transform",function(e){return"translate("+T(b[0])+","+m/2+")"}).attr("d","M0,"+j+"L"+j+","+ -j+" "+ -j+","+ -j+"Z").on("mouseover",function(){v.elementMouseover({value:b[0],label:S[0]||"Previous",pos:[T(b[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:b[0],label:S[0]||"Previous"})}):_.selectAll("path.nv-markerTriangle").remove(),A.selectAll(".nv-range").on("mouseover",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseover({value:e,label:n,pos:[T(e),m/2]})}).on("mouseout",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseout({value:e,label:n})})}),m}var t={top:0,right:0,bottom:0,left:0},n="left",r=!1,i=function(e){return e.ranges},s=function(e){return e.markers},o=function(e){return e.measures},u=function(e){return e.rangeLabels?e.rangeLabels:[]},a=function(e){return e.markerLabels?e.markerLabels:[]},f=function(e){return e.measureLabels?e.measureLabels:[]},l=[0],c=380,h=30,p=null,d=e.utils.getColor(["#1f77b4"]),v=d3.dispatch("elementMouseover","elementMouseout");return m.dispatch=v,m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(i=e,m):i},m.markers=function(e){return arguments.length?(s=e,m):s},m.measures=function(e){return arguments.length?(o=e,m):o},m.forceX=function(e){return arguments.length?(l=e,m):l},m.width=function(e){return arguments.length?(c=e,m):c},m.height=function(e){return arguments.length?(h=e,m):h},m.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,m):t},m.tickFormat=function(e){return arguments.length?(p=e,m):p},m.color=function(t){return arguments.length?(d=e.utils.getColor(t),m):d},m},e.models.bulletChart=function(){function m(e){return e.each(function(n,h){var g=d3.select(this),y=(a||parseInt(g.style("width"))||960)-i.left-i.right,b=f-i.top-i.bottom,w=this;m.update=function(){m(e)},m.container=this;if(!n||!s.call(this,n,h)){var E=g.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+y/2).attr("y",18+i.top+b/2).text(function(e){return e}),m}g.selectAll(".nv-noData").remove();var S=s.call(this,n,h).slice().sort(d3.descending),x=o.call(this,n,h).slice().sort(d3.descending),T=u.call(this,n,h).slice().sort(d3.descending),N=g.selectAll("g.nv-wrap.nv-bulletChart").data([n]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-bulletWrap"),k.append("g").attr("class","nv-titles"),N.attr("transform","translate("+i.left+","+i.top+")");var A=d3.scale.linear().domain([0,Math.max(S[0],x[0],T[0])]).range(r?[y,0]:[0,y]),O=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(A.range());this.__chart__=A;var M=function(e){return Math.abs(O(e)-O(0))},_=function(e){return Math.abs(A(e)-A(0))},D=k.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(f-i.top-i.bottom)/2+")");D.append("text").attr("class","nv-title").text(function(e){return e.title}),D.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(e){return e.subtitle}),t.width(y).height(b);var P=L.select(".nv-bulletWrap");d3.transition(P).call(t);var H=l||A.tickFormat(y/100),B=L.selectAll("g.nv-tick").data(A.ticks(y/50),function(e){return this.textContent||H(e)}),j=B.enter().append("g").attr("class","nv-tick").attr("transform",function(e){return"translate("+O(e)+",0)"}).style("opacity",1e-6);j.append("line").attr("y1",b).attr("y2",b*7/6),j.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",b*7/6).text(H);var F=d3.transition(B).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1);F.select("line").attr("y1",b).attr("y2",b*7/6),F.select("text").attr("y",b*7/6),d3.transition(B.exit()).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1e-6).remove(),d.on("tooltipShow",function(e){e.key=n.title,c&&v(e,w.parentNode)})}),d3.timer.flush(),m}var t=e.models.bullet(),n="left",r=!1,i={top:5,right:40,bottom:20,left:120},s=function(e){return e.ranges},o=function(e){return e.markers},u=function(e){return e.measures},a=null,f=55,l=null,c=!0,h=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide"),v=function(t,n){var r=t.pos[0]+(n.offsetLeft||0)+i.left,s=t.pos[1]+(n.offsetTop||0)+i.top,o=h(t.key,t.label,t.value,t,m);e.tooltip.show([r,s],o,t.value<0?"e":"w",null,n)};return t.dispatch.on("elementMouseover.tooltip",function(e){d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),m.dispatch=d,m.bullet=t,d3.rebind(m,t,"color"),m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(s=e,m):s},m.markers=function(e){return arguments.length?(o=e,m):o},m.measures=function(e){return arguments.length?(u=e,m):u},m.width=function(e){return arguments.length?(a=e,m):a},m.height=function(e){return arguments.length?(f=e,m):f},m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.tickFormat=function(e){return arguments.length?(l=e,m):l},m.tooltips=function(e){return arguments.length?(c=e,m):c},m.tooltipContent=function(e){return arguments.length?(h=e,m):h},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.cumulativeLineChart=function(){function D(b){return b.each(function(b){function I(e,t){d3.select(D.container).style("cursor","ew-resize")}function q(e,t){M.x=d3.event.x,M.i=Math.round(O.invert(M.x)),nt()}function R(e,t){d3.select(D.container).style("cursor","auto"),x.index=M.i,k.stateChange(x)}function nt(){tt.data([M]);var e=D.transitionDuration();D.transitionDuration(0),D.update(),D.transitionDuration(e)}var L=d3.select(this).classed("nv-chart-"+S,!0),A=this,H=(f||parseInt(L.style("width"))||960)-u.left-u.right,B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom;D.update=function(){L.call(D)},D.container=this,x.disabled=b.map(function(e){return!!e.disabled});if(!T){var j;T={};for(j in x)x[j]instanceof Array?T[j]=x[j].slice(0):T[j]=x[j]}var F=d3.behavior.drag().on("dragstart",I).on("drag",q).on("dragend",R);if(!b||!b.length||!b.filter(function(e){return e.values.length}).length){var U=L.selectAll(".nv-noData").data([N]);return U.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),U.attr("x",u.left+H/2).attr("y",u.top+B/2).text(function(e){return e}),D}L.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();if(!y){var z=b.filter(function(e){return!e.disabled}).map(function(e,n){var r=d3.extent(e.values,t.y());return r[0]<-0.95&&(r[0]=-0.95),[(r[0]-r[1])/(1+r[1]),(r[1]-r[0])/(1+r[0])]}),W=[d3.min(z,function(e){return e[0]}),d3.max(z,function(e){return e[1]})];t.yDomain(W)}else t.yDomain(null);O.domain([0,b[0].values.length-1]).range([0,H]).clamp(!0);var b=P(M.i,b),X=g?"none":"all",V=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([b]),$=V.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),J=V.select("g");$.append("g").attr("class","nv-interactive"),$.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),$.append("g").attr("class","nv-y nv-axis"),$.append("g").attr("class","nv-background"),$.append("g").attr("class","nv-linesWrap").style("pointer-events",X),$.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),$.append("g").attr("class","nv-legendWrap"),$.append("g").attr("class","nv-controlsWrap"),c&&(i.width(H),J.select(".nv-legendWrap").datum(b).call(i),u.top!=i.height()&&(u.top=i.height(),B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom),J.select(".nv-legendWrap").attr("transform","translate(0,"+ -u.top+")"));if(m){var K=[{key:"Re-scale y-axis",disabled:!y}];s.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),J.select(".nv-controlsWrap").datum(K).attr("transform","translate(0,"+ -u.top+")").call(s)}V.attr("transform","translate("+u.left+","+u.top+")"),d&&J.select(".nv-y.nv-axis").attr("transform","translate("+H+",0)");var Q=b.filter(function(e){return e.tempDisabled});V.select(".tempDisabled").remove(),Q.length&&V.append("text").attr("class","tempDisabled").attr("x",H/2).attr("y","-.71em").style("text-anchor","end").text(Q.map(function(e){return e.key}).join(", ")+" values cannot be calculated for this time period."),g&&(o.width(H).height(B).margin({left:u.left,top:u.top}).svgContainer(L).xScale(w),V.select(".nv-interactive").call(o)),$.select(".nv-background").append("rect"),J.select(".nv-background rect").attr("width",H).attr("height",B),t.y(function(e){return e.display.y}).width(H).height(B).color(b.map(function(e,t){return e.color||a(e,t)}).filter(function(e,t){return!b[t].disabled&&!b[t].tempDisabled}));var G=J.select(".nv-linesWrap").datum(b.filter(function(e){return!e.disabled&&!e.tempDisabled}));G.call(t),b.forEach(function(e,t){e.seriesIndex=t});var Y=b.filter(function(e){return!e.disabled&&!!C(e)}),Z=J.select(".nv-avgLinesWrap").selectAll("line").data(Y,function(e){return e.key}),et=function(e){var t=E(C(e));return t<0?0:t>B?B:t};Z.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(e,n){return t.color()(e,e.seriesIndex)}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.style("stroke-opacity",function(e){var t=E(C(e));return t<0||t>B?0:1}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.exit().remove();var tt=G.selectAll(".nv-indexLine").data([M]);tt.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(F),tt.attr("transform",function(e){return"translate("+O(e.i)+",0)"}).attr("height",B),h&&(n.scale(w).ticks(Math.min(b[0].values.length,H/70)).tickSize(-B,0),J.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),d3.transition(J.select(".nv-x.nv-axis")).call(n)),p&&(r.scale(E).ticks(B/36).tickSize(-H,0),d3.transition(J.select(".nv-y.nv-axis")).call(r)),J.select(".nv-background rect").on("click",function(){M.x=d3.mouse(this)[0],M.i=Math.round(O.invert(M.x)),x.index=M.i,k.stateChange(x),nt()}),t.dispatch.on("elementClick",function(e){M.i=e.pointIndex,M.x=O(M.i),x.index=M.i,k.stateChange(x),nt()}),s.dispatch.on("legendClick",function(e,t){e.disabled=!e.disabled,y=!e.disabled,x.rescaleY=y,k.stateChange(x),D.update()}),i.dispatch.on("stateChange",function(e){x.disabled=e.disabled,k.stateChange(x),D.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,f,l,c=[];b.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,D.x()),t.highlightPoint(r,f,!0);var o=n.values[f];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof l=="undefined"&&(l=D.xScale()(D.x()(o,f))),c.push({key:n.key,value:D.y()(o,f),color:a(n,n.seriesIndex)})});if(c.length>2){var h=D.yScale().invert(i.mouseY),p=Math.abs(D.yScale().domain()[0]-D.yScale().domain()[1]),d=.03*p,m=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);m!==null&&(c[m].highlight=!0)}var g=n.tickFormat()(D.x()(s,f),f);o.tooltip.position({left:l+u.left,top:i.mouseY+u.top}).chartContainer(A.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:g,series:c})(),o.renderGuideLine(l)}),o.dispatch.on("elementMouseout",function(e){k.tooltipHide(),t.clearHighlights()}),k.on("tooltipShow",function(e){v&&_(e,A.parentNode)}),k.on("changeState",function(e){typeof e.disabled!="undefined"&&(b.forEach(function(t,n){t.disabled=e.disabled[n]}),x.disabled=e.disabled),typeof e.index!="undefined"&&(M.i=e.index,M.x=O(M.i),x.index=e.index,tt.data([M])),typeof e.rescaleY!="undefined"&&(y=e.rescaleY),D.update()})}),D}function P(e,n){return n.map(function(n,r){if(!n.values)return n;var i=n.values[e];if(i==null)return n;var s=t.y()(i,e);return s<-0.95&&!A?(n.tempDisabled=!0,n):(n.tempDisabled=!1,n.values=n.values.map(function(e,n){return e.display={y:(t.y()(e,n)-s)/(1+s)},e}),n)})}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:30,bottom:50,left:60},a=e.utils.defaultColor(),f=null,l=null,c=!0,h=!0,p=!0,d=!1,v=!0,m=!0,g=!1,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},w,E,S=t.id(),x={index:0,rescaleY:y},T=null,N="No Data Available.",C=function(e){return e.average},k=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),L=0,A=!1;n.orient("bottom").tickPadding(7),r.orient(d?"right":"left"),s.updateState(!1);var O=d3.scale.linear(),M={i:0,x:0},_=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,D);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],k.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){k.tooltipHide(e)}),k.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),D.dispatch=k,D.lines=t,D.legend=i,D.xAxis=n,D.yAxis=r,D.interactiveLayer=o,d3.rebind(D,t,"defined","isArea","x","y","xScale","yScale","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id"),D.options=e.utils.optionsFunc.bind(D),D.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,D):u},D.width=function(e){return arguments.length?(f=e,D):f},D.height=function(e){return arguments.length?(l=e,D):l},D.color=function(t){return arguments.length?(a=e.utils.getColor(t),i.color(a),D):a},D.rescaleY=function(e){return arguments.length?(y=e,D):y},D.showControls=function(e){return arguments.length?(m=e,D):m},D.useInteractiveGuideline=function(e){return arguments.length?(g=e,e===!0&&(D.interactive(!1),D.useVoronoi(!1)),D):g},D.showLegend=function(e){return arguments.length?(c=e,D):c},D.showXAxis=function(e){return arguments.length?(h=e,D):h},D.showYAxis=function(e){return arguments.length?(p=e,D):p},D.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),D):d},D.tooltips=function(e){return arguments.length?(v=e,D):v},D.tooltipContent=function(e){return arguments.length?(b=e,D):b},D.state=function(e){return arguments.length?(x=e,D):x},D.defaultState=function(e){return arguments.length?(T=e,D):T},D.noData=function(e){return arguments.length?(N=e,D):N},D.average=function(e){return arguments.length?(C=e,D):C},D.transitionDuration=function(e){return arguments.length?(L=e,D):L},D.noErrorCheck=function(e){return arguments.length?(A=e,D):A},D},e.models.discreteBar=function(){function E(e){return e.each(function(e){var i=n-t.left-t.right,E=r-t.top-t.bottom,S=d3.select(this);e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var T=p&&d?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0}})});s.domain(p||d3.merge(T).map(function(e){return e.x})).rangeBands(v||[0,i],.1),o.domain(d||d3.extent(d3.merge(T).map(function(e){return e.y}).concat(f))),c?o.range(m||[E-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(m||[E,0]),b=b||s,w=w||o.copy().range([o(0),o(0)]);var N=S.selectAll("g.nv-wrap.nv-discretebar").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-groups"),N.attr("transform","translate("+t.left+","+t.top+")");var A=N.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),A.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),A.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),A.style("stroke-opacity",1).style("fill-opacity",.75);var O=A.selectAll("g.nv-bar").data(function(e){return e.values});O.exit().remove();var M=O.enter().append("g").attr("transform",function(e,t,n){return"translate("+(s(u(e,t))+s.rangeBand()*.05)+", "+o(0)+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),g.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),g.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){g.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){g.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()});M.append("rect").attr("height",0).attr("width",s.rangeBand()*.9/e.length),c?(M.append("text").attr("text-anchor","middle"),O.select("text").text(function(e,t){return h(a(e,t))}).attr("x",s.rangeBand()*.9/2).attr("y",function(e,t){return a(e,t)<0?o(a(e,t))-o(0)+12:-4})):O.selectAll("text").remove(),O.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(e,t){return e.color||l(e,t)}).style("stroke",function(e,t){return e.color||l(e,t)}).select("rect").attr("class",y).attr("width",s.rangeBand()*.9/e.length),O.attr("transform",function(e,t){var n=s(u(e,t))+s.rangeBand()*.05,r=a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t));return"translate("+n+", "+r+")"}).select("rect").attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(d&&d[0]||0))||1)}),b=s.copy(),w=o.copy()}),E}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=!1,h=d3.format(",.2f"),p,d,v,m,g=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),y="discreteBar",b,w;return E.dispatch=g,E.options=e.utils.optionsFunc.bind(E),E.x=function(e){return arguments.length?(u=e,E):u},E.y=function(e){return arguments.length?(a=e,E):a},E.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.xScale=function(e){return arguments.length?(s=e,E):s},E.yScale=function(e){return arguments.length?(o=e,E):o},E.xDomain=function(e){return arguments.length?(p=e,E):p},E.yDomain=function(e){return arguments.length?(d=e,E):d},E.xRange=function(e){return arguments.length?(v=e,E):v},E.yRange=function(e){return arguments.length?(m=e,E):m},E.forceY=function(e){return arguments.length?(f=e,E):f},E.color=function(t){return arguments.length?(l=e.utils.getColor(t),E):l},E.id=function(e){return arguments.length?(i=e,E):i},E.showValues=function(e){return arguments.length?(c=e,E):c},E.valueFormat=function(e){return arguments.length?(h=e,E):h},E.rectClass=function(e){return arguments.length?(y=e,E):y},E},e.models.discreteBarChart=function(){function w(e){return e.each(function(e){var u=d3.select(this),p=this,y=(s||parseInt(u.style("width"))||960)-i.left-i.right,E=(o||parseInt(u.style("height"))||400)-i.top-i.bottom;w.update=function(){g.beforeUpdate(),u.call(w)},w.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var S=u.selectAll(".nv-noData").data([m]);return S.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),S.attr("x",i.left+y/2).attr("y",i.top+E/2).text(function(e){return e}),w}u.selectAll(".nv-noData").remove(),d=t.xScale(),v=t.yScale().clamp(!0);var T=u.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),C=N.append("defs"),k=T.select("g");N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),N.append("g").attr("class","nv-barsWrap"),k.attr("transform","translate("+i.left+","+i.top+")"),l&&k.select(".nv-y.nv-axis").attr("transform","translate("+y+",0)"),t.width(y).height(E);var L=k.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));L.call(t),C.append("clipPath").attr("id","nv-x-label-clip-"+t.id()).append("rect"),k.select("#nv-x-label-clip-"+t.id()+" rect").attr("width",d.rangeBand()*(c?2:1)).attr("height",16).attr("x",-d.rangeBand()/(c?1:2));if(a){n.scale(d).ticks(y/100).tickSize(-E,0),k.select(".nv-x.nv-axis").attr("transform","translate(0,"+(v.range()[0]+(t.showValues()&&v.domain()[0]<0?16:0))+")"),k.select(".nv-x.nv-axis").call(n);var A=k.select(".nv-x.nv-axis").selectAll("g");c&&A.selectAll("text").attr("transform",function(e,t,n){return"translate(0,"+(n%2==0?"5":"17")+")"})}f&&(r.scale(v).ticks(E/36).tickSize(-y,0),k.select(".nv-y.nv-axis").call(r)),k.select(".nv-zeroLine line").attr("x1",0).attr("x2",y).attr("y1",v(0)).attr("y2",v(0)),g.on("tooltipShow",function(e){h&&b(e,p.parentNode)})}),w}var t=e.models.discreteBar(),n=e.models.axis(),r=e.models.axis(),i={top:15,right:10,bottom:50,left:60},s=null,o=null,u=e.utils.getColor(),a=!0,f=!0,l=!1,c=!1,h=!0,p=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},d,v,m="No Data Available.",g=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate"),y=0;n.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(l?"right":"left").tickFormat(d3.format(",.1f"));var b=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=p(i.series.key,a,f,i,w);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+i.left,e.pos[1]+i.top],g.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){g.tooltipHide(e)}),g.on("tooltipHide",function(){h&&e.tooltip.cleanup()}),w.dispatch=g,w.discretebar=t,w.xAxis=n,w.yAxis=r,d3.rebind(w,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","id","showValues","valueFormat"),w.options=e.utils.optionsFunc.bind(w),w.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,w):i},w.width=function(e){return arguments.length?(s=e,w):s},w.height=function(e){return arguments.length?(o=e,w):o},w.color=function(n){return arguments.length?(u=e.utils.getColor(n),t.color(u),w):u},w.showXAxis=function(e){return arguments.length?(a=e,w):a},w.showYAxis=function(e){return arguments.length?(f=e,w):f},w.rightAlignYAxis=function(e){return arguments.length?(l=e,r.orient(e?"right":"left"),w):l},w.staggerLabels=function(e){return arguments.length?(c=e,w):c},w.tooltips=function(e){return arguments.length?(h=e,w):h},w.tooltipContent=function(e){return arguments.length?(p=e,w):p},w.noData=function(e){return arguments.length?(m=e,w):m},w.transitionDuration=function(e){return arguments.length?(y=e,w):y},w},e.models.distribution=function(){function l(e){return e.each(function(e){var a=n-(i==="x"?t.left+t.right:t.top+t.bottom),l=i=="x"?"y":"x",c=d3.select(this);f=f||u;var h=c.selectAll("g.nv-distribution").data([e]),p=h.enter().append("g").attr("class","nvd3 nv-distribution"),d=p.append("g"),v=h.select("g");h.attr("transform","translate("+t.left+","+t.top+")");var m=v.selectAll("g.nv-dist").data(function(e){return e},function(e){return e.key});m.enter().append("g"),m.attr("class",function(e,t){return"nv-dist nv-series-"+t}).style("stroke",function(e,t){return o(e,t)});var g=m.selectAll("line.nv-dist"+i).data(function(e){return e.values});g.enter().append("line").attr(i+"1",function(e,t){return f(s(e,t))}).attr(i+"2",function(e,t){return f(s(e,t))}),m.exit().selectAll("line.nv-dist"+i).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}).style("stroke-opacity",0).remove(),g.attr("class",function(e,t){return"nv-dist"+i+" nv-dist"+i+"-"+t}).attr(l+"1",0).attr(l+"2",r),g.attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}),f=u.copy()}),l}var t={top:0,right:0,bottom:0,left:0},n=400,r=8,i="x",s=function(e){return e[i]},o=e.utils.defaultColor(),u=d3.scale.linear(),a,f;return l.options=e.utils.optionsFunc.bind(l),l.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,l):t},l.width=function(e){return arguments.length?(n=e,l):n},l.axis=function(e){return arguments.length?(i=e,l):i},l.size=function(e){return arguments.length?(r=e,l):r},l.getData=function(e){return arguments.length?(s=d3.functor(e),l):s},l.scale=function(e){return arguments.length?(u=e,l):u},l.color=function(t){return arguments.length?(o=e.utils.getColor(t),l):o},l},e.models.historicalBarChart=function(){function x(e){return e.each(function(d){var E=d3.select(this),T=this,N=(u||parseInt(E.style("width"))||960)-s.left-s.right,C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom;x.update=function(){E.call(x)},x.container=this,g.disabled=d.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!d||!d.length||!d.filter(function(e){return e.values.length}).length){var L=E.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",s.left+N/2).attr("y",s.top+C/2).text(function(e){return e}),x}E.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();var A=E.selectAll("g.nv-wrap.nv-historicalBarChart").data([d]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),M=A.select("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-barsWrap"),O.append("g").attr("class","nv-legendWrap"),f&&(i.width(N),M.select(".nv-legendWrap").datum(d).call(i),s.top!=i.height()&&(s.top=i.height(),C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom),A.select(".nv-legendWrap").attr("transform","translate(0,"+ -s.top+")")),A.attr("transform","translate("+s.left+","+s.top+")"),h&&M.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)"),t.width(N).height(C).color(d.map(function(e,t){return e.color||o(e,t)}).filter(function(e,t){return!d[t].disabled}));var _=M.select(".nv-barsWrap").datum(d.filter(function(e){return!e.disabled}));_.call(t),l&&(n.scale(v).tickSize(-C,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+m.range()[0]+")"),M.select(".nv-x.nv-axis").call(n)),c&&(r.scale(m).ticks(C/36).tickSize(-N,0),M.select(".nv-y.nv-axis").call(r)),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,d.filter(function(e){return!e.disabled}).length||d.map(function(e){return e.disabled=!1,A.selectAll(".nv-series").classed("disabled",!1),e}),g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),e.call(x)}),i.dispatch.on("legendDblclick",function(e){d.forEach(function(e){e.disabled=!0}),e.disabled=!1,g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),x.update()}),w.on("tooltipShow",function(e){p&&S(e,T.parentNode)}),w.on("changeState",function(e){typeof e.disabled!="undefined"&&(d.forEach(function(t,n){t.disabled=e.disabled[n]}),g.disabled=e.disabled),x.update()})}),x}var t=e.models.historicalBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s={top:30,right:90,bottom:50,left:90},o=e.utils.defaultColor(),u=null,a=null,f=!1,l=!0,c=!0,h=!1,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},v,m,g={},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=0;n.orient("bottom").tickPadding(7),r.orient(h?"right":"left");var S=function(i,s){if(s){var o=d3.select(s).select("svg"),u=o.node()?o.attr("viewBox"):null;if(u){u=u.split(" ");var a=parseInt(o.style("width"))/u[2];i.pos[0]=i.pos[0]*a,i.pos[1]=i.pos[1]*a}}var f=i.pos[0]+(s.offsetLeft||0),l=i.pos[1]+(s.offsetTop||0),c=n.tickFormat()(t.x()(i.point,i.pointIndex)),h=r.tickFormat()(t.y()(i.point,i.pointIndex)),p=d(i.series.key,c,h,i,x);e.tooltip.show([f,l],p,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+s.left,e.pos[1]+s.top],w.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){p&&e.tooltip.cleanup()}),x.dispatch=w,x.bars=t,x.legend=i,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate","highlightPoint","clearHighlights","interactive"),x.options=e.utils.optionsFunc.bind(x),x.margin=function(e){return arguments.length?(s.top=typeof e.top!="undefined"?e.top:s.top,s.right=typeof e.right!="undefined"?e.right:s.right,s.bottom=typeof e.bottom!="undefined"?e.bottom:s.bottom,s.left=typeof e.left!="undefined"?e.left:s.left,x):s},x.width=function(e){return arguments.length?(u=e,x):u},x.height=function(e){return arguments.length?(a=e,x):a},x.color=function(t){return arguments.length?(o=e.utils.getColor(t),i.color(o),x):o},x.showLegend=function(e){return arguments.length?(f=e,x):f},x.showXAxis=function(e){return arguments.length?(l=e,x):l},x.showYAxis=function(e){return arguments.length?(c=e,x):c},x.rightAlignYAxis=function(e){return arguments.length?(h=e,r.orient(e?"right":"left"),x):h},x.tooltips=function(e){return arguments.length?(p=e,x):p},x.tooltipContent=function(e){return arguments.length?(d=e,x):d},x.state=function(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments.length?(b=e,x):b},x.transitionDuration=function(e){return arguments.length?(E=e,x):E},x},e.models.indentedTree=function(){function g(e){return e.each(function(e){function k(e,t,n){d3.event.stopPropagation();if(d3.event.shiftKey&&!n)return d3.event.shiftKey=!1,e.values&&e.values.forEach(function(e){(e.values||e._values)&&k(e,0,!0)}),!0;if(!O(e))return!0;e.values?(e._values=e.values,e.values=null):(e.values=e._values,e._values=null),g.update()}function L(e){return e._values&&e._values.length?h:e.values&&e.values.length?p:""}function A(e){return e._values&&e._values.length}function O(e){var t=e.values||e._values;return t&&t.length}var t=1,n=d3.select(this),i=d3.layout.tree().children(function(e){return e.values}).size([r,f]);g.update=function(){n.call(g)},e[0]||(e[0]={key:a});var s=i.nodes(e[0]),y=d3.select(this).selectAll("div").data([[s]]),b=y.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),w=b.append("table"),E=y.select("table").attr("width","100%").attr("class",c);if(o){var S=w.append("thead"),x=S.append("tr");l.forEach(function(e){x.append("th").attr("width",e.width?e.width:"10%").style("text-align",e.type=="numeric"?"right":"left").append("span").text(e.label)})}var T=E.selectAll("tbody").data(function(e){return e});T.enter().append("tbody"),t=d3.max(s,function(e){return e.depth}),i.size([r,t*f]);var N=T.selectAll("tr").data(function(e){return e.filter(function(e){return u&&!e.children?u(e):!0})},function(e,t){return e.id||e.id||++m});N.exit().remove(),N.select("img.nv-treeicon").attr("src",L).classed("folded",A);var C=N.enter().append("tr");l.forEach(function(e,t){var n=C.append("td").style("padding-left",function(e){return(t?0:e.depth*f+12+(L(e)?0:16))+"px"},"important").style("text-align",e.type=="numeric"?"right":"left");t==0&&n.append("img").classed("nv-treeicon",!0).classed("nv-folded",A).attr("src",L).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(e){return L(e)?"inline-block":"none"}).on("click",k),n.each(function(n){!t&&v(n)?d3.select(this).append("a").attr("href",v).attr("class",d3.functor(e.classes)).append("span"):d3.select(this).append("span"),d3.select(this).select("span").attr("class",d3.functor(e.classes)).text(function(t){return e.format?t[e.key]?e.format(t[e.key]):"-":t[e.key]||"-"})}),e.showCount&&(n.append("span").attr("class","nv-childrenCount"),N.selectAll("span.nv-childrenCount").text(function(e){return e.values&&e.values.length||e._values&&e._values.length?"("+(e.values&&e.values.filter(function(e){return u?u(e):!0}).length||e._values&&e._values.filter(function(e){return u?u(e):!0}).length||0)+")":""}))}),N.order().on("click",function(e){d.elementClick({row:this,data:e,pos:[e.x,e.y]})}).on("dblclick",function(e){d.elementDblclick({row:this,data:e,pos:[e.x,e.y]})}).on("mouseover",function(e){d.elementMouseover({row:this,data:e,pos:[e.x,e.y]})}).on("mouseout",function(e){d.elementMouseout({row:this,data:e,pos:[e.x,e.y]})})}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e4),o=!0,u=!1,a="No Data Available.",f=20,l=[{key:"key",label:"Name",type:"text"}],c=null,h="images/grey-plus.png",p="images/grey-minus.png",d=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),v=function(e){return e.url},m=0;return g.options=e.utils.optionsFunc.bind(g),g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),scatter.color(i),g):i},g.id=function(e){return arguments.length?(s=e,g):s},g.header=function(e){return arguments.length?(o=e,g):o},g.noData=function(e){return arguments.length?(a=e,g):a},g.filterZero=function(e){return arguments.length?(u=e,g):u},g.columns=function(e){return arguments.length?(l=e,g):l},g.tableClass=function(e){return arguments.length?(c=e,g):c},g.iconOpen=function(e){return arguments.length?(h=e,g):h},g.iconClose=function(e){return arguments.length?(p=e,g):p},g.getUrl=function(e){return arguments.length?(v=e,g):v},g},e.models.legend=function(){function c(h){return h.each(function(c){var h=n-t.left-t.right,p=d3.select(this),d=p.selectAll("g.nv-legend").data([c]),v=d.enter().append("g").attr("class","nvd3 nv-legend").append("g"),m=d.select("g");d.attr("transform","translate("+t.left+","+t.top+")");var g=m.selectAll(".nv-series").data(function(e){return e}),y=g.enter().append("g").attr("class","nv-series").on("mouseover",function(e,t){l.legendMouseover(e,t)}).on("mouseout",function(e,t){l.legendMouseout(e,t)}).on("click",function(e,t){l.legendClick(e,t),a&&(f?(c.forEach(function(e){e.disabled=!0}),e.disabled=!1):(e.disabled=!e.disabled,c.every(function(e){return e.disabled})&&c.forEach(function(e){e.disabled=!1})),l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))}).on("dblclick",function(e,t){l.legendDblclick(e,t),a&&(c.forEach(function(e){e.disabled=!0}),e.disabled=!1,l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))});y.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),y.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8"),g.classed("disabled",function(e){return e.disabled}),g.exit().remove(),g.select("circle").style("fill",function(e,t){return e.color||s(e,t)}).style("stroke",function(e,t){return e.color||s(e,t)}),g.select("text").text(i);if(o){var b=[];g.each(function(t,n){var r=d3.select(this).select("text"),i;try{i=r.getComputedTextLength();if(i<=0)throw Error()}catch(s){i=e.utils.calcApproxTextWidth(r)}b.push(i+28)});var w=0,E=0,S=[];while(E<h&&w<b.length)S[w]=b[w],E+=b[w++];w===0&&(w=1);while(E>h&&w>1){S=[],w--;for(var x=0;x<b.length;x++)b[x]>(S[x%w]||0)&&(S[x%w]=b[x]);E=S.reduce(function(e,t,n,r){return e+t})}var T=[];for(var N=0,C=0;N<w;N++)T[N]=C,C+=S[N];g.attr("transform",function(e,t){return"translate("+T[t%w]+","+(5+Math.floor(t/w)*20)+")"}),u?m.attr("transform","translate("+(n-t.right-E)+","+t.top+")"):m.attr("transform","translate(0,"+t.top+")"),r=t.top+t.bottom+Math.ceil(b.length/w)*20}else{var k=5,L=5,A=0,O;g.attr("transform",function(e,r){var i=d3.select(this).select("text").node().getComputedTextLength()+28;return O=L,n<t.left+t.right+O+i&&(L=O=5,k+=20),L+=i,L>A&&(A=L),"translate("+O+","+k+")"}),m.attr("transform","translate("+(n-t.right-A)+","+t.top+")"),r=t.top+t.bottom+k+15}}),c}var t={top:5,right:0,bottom:5,left:0},n=400,r=20,i=function(e){return e.key},s=e.utils.defaultColor(),o=!0,u=!0,a=!0,f=!1,l=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange");return c.dispatch=l,c.options=e.utils.optionsFunc.bind(c),c.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,c):t},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.key=function(e){return arguments.length?(i=e,c):i},c.color=function(t){return arguments.length?(s=e.utils.getColor(t),c):s},c.align=function(e){return arguments.length?(o=e,c):o},c.rightAlign=function(e){return arguments.length?(u=e,c):u},c.updateState=function(e){return arguments.length?(a=e,c):a},c.radioButtonMode=function(e){return arguments.length?(f=e,c):f},c},e.models.line=function(){function m(g){return g.each(function(m){var g=r-n.left-n.right,b=i-n.top-n.bottom,w=d3.select(this);c=t.xScale(),h=t.yScale(),d=d||c,v=v||h;var E=w.selectAll("g.nv-wrap.nv-line").data([m]),S=E.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),T=S.append("defs"),N=S.append("g"),C=E.select("g");N.append("g").attr("class","nv-groups"),N.append("g").attr("class","nv-scatterWrap"),E.attr("transform","translate("+n.left+","+n.top+")"),t.width(g).height(b);var k=E.select(".nv-scatterWrap");k.call(t),T.append("clipPath").attr("id","nv-edge-clip-"+t.id()).append("rect"),E.select("#nv-edge-clip-"+t.id()+" rect").attr("width",g).attr("height",b>0?b:0),C.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":""),k.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":"");var L=E.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});L.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),L.exit().remove(),L.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return s(e,t)}).style("stroke",function(e,t){return s(e,t)}),L.style("stroke-opacity",1).style("fill-opacity",.5);var A=L.selectAll("path.nv-area").data(function(e){return f(e)?[e]:[]});A.enter().append("path").attr("class","nv-area").attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])}),L.exit().selectAll("path.nv-area").remove(),A.attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))}).y1(function(e,t){return h(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])});var O=L.selectAll("path.nv-line").data(function(e){return[e.values]});O.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))})),O.attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))})),d=c.copy(),v=h.copy()}),m}var t=e.models.scatter(),n={top:0,right:0,bottom:0,left:0},r=960,i=500,s=e.utils.defaultColor(),o=function(e){return e.x},u=function(e){return e.y},a=function(e,t){return!isNaN(u(e,t))&&u(e,t)!==null},f=function(e){return e.area},l=!1,c,h,p="linear";t.size(16).sizeDomain([16,256]);var d,v;return m.dispatch=t.dispatch,m.scatter=t,d3.rebind(m,t,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","padData","highlightPoint","clearHighlights"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.height=function(e){return arguments.length?(i=e,m):i},m.x=function(e){return arguments.length?(o=e,t.x(e),m):o},m.y=function(e){return arguments.length?(u=e,t.y(e),m):u},m.clipEdge=function(e){return arguments.length?(l=e,m):l},m.color=function(n){return arguments.length?(s=e.utils.getColor(n),t.color(s),m):s},m.interpolate=function(e){return arguments.length?(p=e,m):p},m.defined=function(e){return arguments.length?(a=e,m):a},m.isArea=function(e){return arguments.length?(f=d3.functor(e),m):f},m},e.models.lineChart=function(){function N(m){return m.each(function(m){var x=d3.select(this),C=this,k=(a||parseInt(x.style("width"))||960)-o.left-o.right,L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom;N.update=function(){x.call(N)},N.container=this,b.disabled=m.map(function(e){return!!e.disabled});if(!w){var A;w={};for(A in b)b[A]instanceof Array?w[A]=b[A].slice(0):w[A]=b[A]}if(!m||!m.length||!m.filter(function(e){return e.values.length}).length){var O=x.selectAll(".nv-noData").data([E]);return O.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),O.attr("x",o.left+k/2).attr("y",o.top+L/2).text(function(e){return e}),N}x.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var M=x.selectAll("g.nv-wrap.nv-lineChart").data([m]),_=M.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),D=M.select("g");_.append("rect").style("opacity",0),_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y nv-axis"),_.append("g").attr("class","nv-linesWrap"),_.append("g").attr("class","nv-legendWrap"),_.append("g").attr("class","nv-interactive"),D.select("rect").attr("width",k).attr("height",L>0?L:0),l&&(i.width(k),D.select(".nv-legendWrap").datum(m).call(i),o.top!=i.height()&&(o.top=i.height(),L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate(0,"+ -o.top+")")),M.attr("transform","translate("+o.left+","+o.top+")"),p&&D.select(".nv-y.nv-axis").attr("transform","translate("+k+",0)"),d&&(s.width(k).height(L).margin({left:o.left,top:o.top}).svgContainer(x).xScale(g),M.select(".nv-interactive").call(s)),t.width(k).height(L).color(m.map(function(e,t){return e.color||u(e,t)}).filter(function(e,t){return!m[t].disabled}));var P=D.select(".nv-linesWrap").datum(m.filter(function(e){return!e.disabled}));P.call(t),c&&(n.scale(g).ticks(k/100).tickSize(-L,0),D.select(".nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),D.select(".nv-x.nv-axis").call(n)),h&&(r.scale(y).ticks(L/36).tickSize(-k,0),D.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),N.update()}),s.dispatch.on("elementMousemove",function(i){t.clearHighlights();var a,f,l,c=[];m.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,N.x()),t.highlightPoint(r,f,!0);var s=n.values[f];if(typeof s=="undefined")return;typeof a=="undefined"&&(a=s),typeof l=="undefined"&&(l=N.xScale()(N.x()(s,f))),c.push({key:n.key,value:N.y()(s,f),color:u(n,n.seriesIndex)})});if(c.length>2){var h=N.yScale().invert(i.mouseY),p=Math.abs(N.yScale().domain()[0]-N.yScale().domain()[1]),d=.03*p,g=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);g!==null&&(c[g].highlight=!0)}var y=n.tickFormat()(N.x()(a,f));s.tooltip.position({left:l+o.left,top:i.mouseY+o.top}).chartContainer(C.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:y,series:c})(),s.renderGuideLine(l)}),s.dispatch.on("elementMouseout",function(e){S.tooltipHide(),t.clearHighlights()}),S.on("tooltipShow",function(e){v&&T(e,C.parentNode)}),S.on("changeState",function(e){typeof e.disabled!="undefined"&&m.length===e.disabled.length&&(m.forEach(function(t,n){t.disabled=e.disabled[n]}),b.disabled=e.disabled),N.update()})}),N}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.interactiveGuideline(),o={top:30,right:20,bottom:50,left:60},u=e.utils.defaultColor(),a=null,f=null,l=!0,c=!0,h=!0,p=!1,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=0;n.orient("bottom").tickPadding(7),r.orient(p?"right":"left");var T=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,N);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),N.dispatch=S,N.lines=t,N.legend=i,N.xAxis=n,N.yAxis=r,N.interactiveLayer=s,d3.rebind(N,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id","interpolate"),N.options=e.utils.optionsFunc.bind(N),N.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,N):o},N.width=function(e){return arguments.length?(a=e,N):a},N.height=function(e){return arguments.length?(f=e,N):f},N.color=function(t){return arguments.length?(u=e.utils.getColor(t),i.color(u),N):u},N.showLegend=function(e){return arguments.length?(l=e,N):l},N.showXAxis=function(e){return arguments.length?(c=e,N):c},N.showYAxis=function(e){return arguments.length?(h=e,N):h},N.rightAlignYAxis=function(e){return arguments.length?(p=e,r.orient(e?"right":"left"),N):p},N.useInteractiveGuideline=function(e){return arguments.length?(d=e,e===!0&&(N.interactive(!1),N.useVoronoi(!1)),N):d},N.tooltips=function(e){return arguments.length?(v=e,N):v},N.tooltipContent=function(e){return arguments.length?(m=e,N):m},N.state=function(e){return arguments.length?(b=e,N):b},N.defaultState=function(e){return arguments.length?(w=e,N):w},N.noData=function(e){return arguments.length?(E=e,N):E},N.transitionDuration=function(e){return arguments.length?(x=e,N):x},N},e.models.linePlusBarChart=function(){function T(e){return e.each(function(e){var l=d3.select(this),c=this,v=(a||parseInt(l.style("width"))||960)-u.left-u.right,N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom;T.update=function(){l.call(T)},b.disabled=e.map(function(e){return!!e.disabled});if(!w){var C;w={};for(C in b)b[C]instanceof Array?w[C]=b[C].slice(0):w[C]=b[C]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var k=l.selectAll(".nv-noData").data([E]);return k.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),k.attr("x",u.left+v/2).attr("y",u.top+N/2).text(function(e){return e}),T}l.selectAll(".nv-noData").remove();var L=e.filter(function(e){return!e.disabled&&e.bar}),A=e.filter(function(e){return!e.bar});m=A.filter(function(e){return!e.disabled}).length&&A.filter(function(e){return!e.disabled})[0].values.length?t.xScale():n.xScale(),g=n.yScale(),y=t.yScale();var O=d3.select(this).selectAll("g.nv-wrap.nv-linePlusBar").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y1 nv-axis"),M.append("g").attr("class","nv-y2 nv-axis"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-linesWrap"),M.append("g").attr("class","nv-legendWrap"),p&&(o.width(v/2),_.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(o),u.top!=o.height()&&(u.top=o.height(),N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom),_.select(".nv-legendWrap").attr("transform","translate("+v/2+","+ -u.top+")")),O.attr("transform","translate("+u.left+","+u.top+")"),t.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar})),n.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar}));var D=_.select(".nv-barsWrap").datum(L.length?L:[{values:[]}]),P=_.select(".nv-linesWrap").datum(A[0]&&!A[0].disabled?A:[{values:[]}]);d3.transition(D).call(n),d3.transition(P).call(t),r.scale(m).ticks(v/100).tickSize(-N,0),_.select(".nv-x.nv-axis").attr("transform","translate(0,"+g.range()[0]+")"),d3.transition(_.select(".nv-x.nv-axis")).call(r),i.scale(g).ticks(N/36).tickSize(-v,0),d3.transition(_.select(".nv-y1.nv-axis")).style("opacity",L.length?1:0).call(i),s.scale(y).ticks(N/36).tickSize(L.length?0:-v,0),_.select(".nv-y2.nv-axis").style("opacity",A.length?1:0).attr("transform","translate("+v+",0)"),d3.transition(_.select(".nv-y2.nv-axis")).call(s),o.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),T.update()}),S.on("tooltipShow",function(e){d&&x(e,c.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),b.disabled=t.disabled),T.update()})}),T}var t=e.models.line(),n=e.models.historicalBar(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.legend(),u={top:30,right:60,bottom:50,left:60},a=null,f=null,l=function(e){return e.x},c=function(e){return e.y},h=e.utils.defaultColor(),p=!0,d=!0,v=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},m,g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.padData(!0),t.clipEdge(!1).padData(!0),r.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),s.orient("right");var x=function(n,o){var u=n.pos[0]+(o.offsetLeft||0),a=n.pos[1]+(o.offsetTop||0),f=r.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?i:s).tickFormat()(t.y()(n.point,n.pointIndex)),c=v(n.series.key,f,l,n,T);e.tooltip.show([u,a],c,n.value<0?"n":"s",null,o)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),n.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),n.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){d&&e.tooltip.cleanup()}),T.dispatch=S,T.legend=o,T.lines=t,T.bars=n,T.xAxis=r,T.y1Axis=i,T.y2Axis=s,d3.rebind(T,t,"defined","size","clipVoronoi","interpolate"),T.options=e.utils.optionsFunc.bind(T),T.x=function(e){return arguments.length?(l=e,t.x(e),n.x(e),T):l},T.y=function(e){return arguments.length?(c=e,t.y(e),n.y(e),T):c},T.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,T):u},T.width=function(e){return arguments.length?(a=e,T):a},T.height=function(e){return arguments.length?(f=e,T):f},T.color=function(t){return arguments.length?(h=e.utils.getColor(t),o.color(h),T):h},T.showLegend=function(e){return arguments.length?(p=e,T):p},T.tooltips=function(e){return arguments.length?(d=e,T):d},T.tooltipContent=function(e){return arguments.length?(v=e,T):v},T.state=function(e){return arguments.length?(b=e,T):b},T.defaultState=function(e){return arguments.length?(w=e,T):w},T.noData=function(e){return arguments.length?(E=e,T):E},T},e.models.lineWithFocusChart=function(){function k(e){return e.each(function(e){function R(e){var t=+(e=="e"),n=t?1:-1,r=O/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function U(){a.empty()||a.extent(w),F.data([a.empty()?g.domain():w]).each(function(e,t){var n=g(e[0])-v.range()[0],r=v.range()[1]-g(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",g(e[1])).attr("width",r<0?0:r)})}function z(){w=a.empty()?null:a.extent();var n=a.empty()?g.domain():a.extent();if(Math.abs(n[0]-n[1])<=1)return;T.brush({extent:n,brush:a}),U();var s=P.select(".nv-focus .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}).map(function(e,r){return{key:e.key,values:e.values.filter(function(e,r){return t.x()(e,r)>=n[0]&&t.x()(e,r)<=n[1]})}}));s.call(t),P.select(".nv-focus .nv-x.nv-axis").call(r),P.select(".nv-focus .nv-y.nv-axis").call(i)}var S=d3.select(this),N=this,L=(h||parseInt(S.style("width"))||960)-f.left-f.right,A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d,O=d-l.top-l.bottom;k.update=function(){S.call(k)},k.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var M=S.selectAll(".nv-noData").data([x]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",f.left+L/2).attr("y",f.top+A/2).text(function(e){return e}),k}S.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale(),g=n.xScale(),y=n.yScale();var _=S.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([e]),D=_.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),P=_.select("g");D.append("g").attr("class","nv-legendWrap");var H=D.append("g").attr("class","nv-focus");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-linesWrap");var B=D.append("g").attr("class","nv-context");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-linesWrap"),B.append("g").attr("class","nv-brushBackground"),B.append("g").attr("class","nv-x nv-brush"),b&&(u.width(L),P.select(".nv-legendWrap").datum(e).call(u),f.top!=u.height()&&(f.top=u.height(),A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d),P.select(".nv-legendWrap").attr("transform","translate(0,"+ -f.top+")")),_.attr("transform","translate("+f.left+","+f.top+")"),t.width(L).height(A).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),n.defined(t.defined()).width(L).height(O).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),P.select(".nv-context").attr("transform","translate(0,"+(A+f.bottom+l.top)+")");var j=P.select(".nv-context .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}));d3.transition(j).call(n),r.scale(v).ticks(L/100).tickSize(-A,0),i.scale(m).ticks(A/36).tickSize(-L,0),P.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+A+")"),a.x(g).on("brush",function(){var e=k.transitionDuration();k.transitionDuration(0),z(),k.transitionDuration(e)}),w&&a.extent(w);var F=P.select(".nv-brushBackground").selectAll("g").data([w||a.extent()]),I=F.enter().append("g");I.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",O),I.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",O);var q=P.select(".nv-x.nv-brush").call(a);q.selectAll("rect").attr("height",O),q.selectAll(".resize").append("path").attr("d",R),z(),s.scale(g).ticks(L/100).tickSize(-O,0),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.transition(P.select(".nv-context .nv-x.nv-axis")).call(s),o.scale(y).ticks(O/36).tickSize(-L,0),d3.transition(P.select(".nv-context .nv-y.nv-axis")).call(o),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),u.dispatch.on("stateChange",function(e){k.update()}),T.on("tooltipShow",function(e){E&&C(e,N.parentNode)})}),k}var t=e.models.line(),n=e.models.line(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.axis(),u=e.models.legend(),a=d3.svg.brush(),f={top:30,right:30,bottom:30,left:60},l={top:0,right:30,bottom:20,left:60},c=e.utils.defaultColor(),h=null,p=null,d=100,v,m,g,y,b=!0,w=null,E=!0,S=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},x="No Data Available.",T=d3.dispatch("tooltipShow","tooltipHide","brush"),N=0;t.clipEdge(!0),n.interactive(!1),r.orient("bottom").tickPadding(5),i.orient("left"),s.orient("bottom").tickPadding(5),o.orient("left");var C=function(n,s){var o=n.pos[0]+(s.offsetLeft||0),u=n.pos[1]+(s.offsetTop||0),a=r.tickFormat()(t.x()(n.point,n.pointIndex)),f=i.tickFormat()(t.y()(n.point,n.pointIndex)),l=S(n.series.key,a,f,n,k);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+f.left,e.pos[1]+f.top],T.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){E&&e.tooltip.cleanup()}),k.dispatch=T,k.legend=u,k.lines=t,k.lines2=n,k.xAxis=r,k.yAxis=i,k.x2Axis=s,k.y2Axis=o,d3.rebind(k,t,"defined","isArea","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),k.options=e.utils.optionsFunc.bind(k),k.x=function(e){return arguments.length?(t.x(e),n.x(e),k):t.x},k.y=function(e){return arguments.length?(t.y(e),n.y(e),k):t.y},k.margin=function(e){return arguments.length?(f.top=typeof e.top!="undefined"?e.top:f.top,f.right=typeof e.right!="undefined"?e.right:f.right,f.bottom=typeof e.bottom!="undefined"?e.bottom:f.bottom,f.left=typeof e.left!="undefined"?e.left:f.left,k):f},k.margin2=function(e){return arguments.length?(l=e,k):l},k.width=function(e){return arguments.length?(h=e,k):h},k.height=function(e){return arguments.length?(p=e,k):p},k.height2=function(e){return arguments.length?(d=e,k):d},k.color=function(t){return arguments.length?(c=e.utils.getColor(t),u.color(c),k):c},k.showLegend=function(e){return arguments.length?(b=e,k):b},k.tooltips=function(e){return arguments.length?(E=e,k):E},k.tooltipContent=function(e){return arguments.length?(S=e,k):S},k.interpolate=function(e){return arguments.length?(t.interpolate(e),n.interpolate(e),k):t.interpolate()},k.noData=function(e){return arguments.length?(x=e,k):x},k.xTickFormat=function(e){return arguments.length?(r.tickFormat(e),s.tickFormat(e),k):r.tickFormat()},k.yTickFormat=function(e){return arguments.length?(i.tickFormat(e),o.tickFormat(e),k):i.tickFormat()},k.brushExtent=function(e){return arguments.length?(w=e,k):w},k.transitionDuration=function(e){return arguments.length?(N=e,k):N},k},e.models.linePlusBarWithFocusChart=function(){function B(e){return e.each(function(e){function tt(e){var t=+(e=="e"),n=t?1:-1,r=I/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function nt(){h.empty()||h.extent(x),Y.data([h.empty()?k.domain():x]).each(function(e,t){var n=k(e[0])-k.range()[0],r=k.range()[1]-k(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",k(e[1])).attr("width",r<0?0:r)})}function rt(){x=h.empty()?null:h.extent(),S=h.empty()?k.domain():h.extent(),D.brush({extent:S,brush:h}),nt(),r.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),t.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var n=$.select(".nv-focus .nv-barsWrap").datum(R.length?R.map(function(e,t){return{key:e.key,values:e.values.filter(function(e,t){return r.x()(e,t)>=S[0]&&r.x()(e,t)<=S[1]})}}):[{values:[]}]),i=$.select(".nv-focus .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U.map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=S[0]&&t.x()(e,n)<=S[1]})}}));R.length?C=r.xScale():C=t.xScale(),s.scale(C).ticks(j/100).tickSize(-F,0),s.domain([Math.ceil(S[0]),Math.floor(S[1])]),$.select(".nv-x.nv-axis").call(s),n.call(r),i.call(t),$.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L.range()[0]+")"),u.scale(L).ticks(F/36).tickSize(-j,0),$.select(".nv-focus .nv-y1.nv-axis").style("opacity",R.length?1:0),a.scale(A).ticks(F/36).tickSize(R.length?0:-j,0),$.select(".nv-focus .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+C.range()[1]+",0)"),$.select(".nv-focus .nv-y1.nv-axis").call(u),$.select(".nv-focus .nv-y2.nv-axis").call(a)}var N=d3.select(this),P=this,j=(v||parseInt(N.style("width"))||960)-p.left-p.right,F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g,I=g-d.top-d.bottom;B.update=function(){N.call(B)},B.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=N.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",p.left+j/2).attr("y",p.top+F/2).text(function(e){return e}),B}N.selectAll(".nv-noData").remove();var R=e.filter(function(e){return!e.disabled&&e.bar}),U=e.filter(function(e){return!e.bar});C=r.xScale(),k=o.scale(),L=r.yScale(),A=t.yScale(),O=i.yScale(),M=n.yScale();var z=e.filter(function(e){return!e.disabled&&e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})}),W=e.filter(function(e){return!e.disabled&&!e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})});C.range([0,j]),k.domain(d3.extent(d3.merge(z.concat(W)),function(e){return e.x})).range([0,j]);var X=N.selectAll("g.nv-wrap.nv-linePlusBar").data([e]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),$=X.select("g");V.append("g").attr("class","nv-legendWrap");var J=V.append("g").attr("class","nv-focus");J.append("g").attr("class","nv-x nv-axis"),J.append("g").attr("class","nv-y1 nv-axis"),J.append("g").attr("class","nv-y2 nv-axis"),J.append("g").attr("class","nv-barsWrap"),J.append("g").attr("class","nv-linesWrap");var K=V.append("g").attr("class","nv-context");K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y1 nv-axis"),K.append("g").attr("class","nv-y2 nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-linesWrap"),K.append("g").attr("class","nv-brushBackground"),K.append("g").attr("class","nv-x nv-brush"),E&&(c.width(j/2),$.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(c),p.top!=c.height()&&(p.top=c.height(),F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g),$.select(".nv-legendWrap").attr("transform","translate("+j/2+","+ -p.top+")")),X.attr("transform","translate("+p.left+","+p.top+")"),i.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),n.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var Q=$.select(".nv-context .nv-barsWrap").datum(R.length?R:[{values:[]}]),G=$.select(".nv-context .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U);$.select(".nv-context").attr("transform","translate(0,"+(F+p.bottom+d.top)+")"),Q.call(i),G.call(n),h.x(k).on("brush",rt),x&&h.extent(x);var Y=$.select(".nv-brushBackground").selectAll("g").data([x||h.extent()]),Z=Y.enter().append("g");Z.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",I),Z.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",I);var et=$.select(".nv-x.nv-brush").call(h);et.selectAll("rect").attr("height",I),et.selectAll(".resize").append("path").attr("d",tt),o.ticks(j/100).tickSize(-I,0),$.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+O.range()[0]+")"),$.select(".nv-context .nv-x.nv-axis").call(o),f.scale(O).ticks(I/36).tickSize(-j,0),$.select(".nv-context .nv-y1.nv-axis").style("opacity",R.length?1:0).attr("transform","translate(0,"+k.range()[0]+")"),$.select(".nv-context .nv-y1.nv-axis").call(f),l.scale(M).ticks(I/36).tickSize(R.length?0:-j,0),$.select(".nv-context .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+k.range()[1]+",0)"),$.select(".nv-context .nv-y2.nv-axis").call(l),c.dispatch.on("stateChange",function(e){B.update()}),D.on("tooltipShow",function(e){T&&H(e,P.parentNode)}),rt()}),B}var t=e.models.line(),n=e.models.line(),r=e.models.historicalBar(),i=e.models.historicalBar(),s=e.models.axis(),o=e.models.axis(),u=e.models.axis(),a=e.models.axis(),f=e.models.axis(),l=e.models.axis(),c=e.models.legend(),h=d3.svg.brush(),p={top:30,right:30,bottom:30,left:60},d={top:0,right:30,bottom:20,left:60},v=null,m=null,g=100,y=function(e){return e.x},b=function(e){return e.y},w=e.utils.defaultColor(),E=!0,S,x=null,T=!0,N=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},C,k,L,A,O,M,_="No Data Available.",D=d3.dispatch("tooltipShow","tooltipHide","brush"),P=0;t.clipEdge(!0),n.interactive(!1),s.orient("bottom").tickPadding(5),u.orient("left"),a.orient("right"),o.orient("bottom").tickPadding(5),f.orient("left"),l.orient("right");var H=function(n,r){S&&(n.pointIndex+=Math.ceil(S[0]));var i=n.pos[0]+(r.offsetLeft||0),o=n.pos[1]+(r.offsetTop||0),f=s.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?u:a).tickFormat()(t.y()(n.point,n.pointIndex)),c=N(n.series.key,f,l,n,B);e.tooltip.show([i,o],c,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),r.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),r.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),D.on("tooltipHide",function(){T&&e.tooltip.cleanup()}),B.dispatch=D,B.legend=c,B.lines=t,B.lines2=n,B.bars=r,B.bars2=i,B.xAxis=s,B.x2Axis=o,B.y1Axis=u,B.y2Axis=a,B.y3Axis=f,B.y4Axis=l,d3.rebind(B,t,"defined","size","clipVoronoi","interpolate"),B.options=e.utils.optionsFunc.bind(B),B.x=function(e){return arguments.length?(y=e,t.x(e),r.x(e),B):y},B.y=function(e){return arguments.length?(b=e,t.y(e),r.y(e),B):b},B.margin=function(e){return arguments.length?(p.top=typeof e.top!="undefined"?e.top:p.top,p.right=typeof e.right!="undefined"?e.right:p.right,p.bottom=typeof e.bottom!="undefined"?e.bottom:p.bottom,p.left=typeof e.left!="undefined"?e.left:p.left,B):p},B.width=function(e){return arguments.length?(v=e,B):v},B.height=function(e){return arguments.length?(m=e,B):m},B.color=function(t){return arguments.length?(w=e.utils.getColor(t),c.color(w),B):w},B.showLegend=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(T=e,B):T},B.tooltipContent=function(e){return arguments.length?(N=e,B):N},B.noData=function(e){return arguments.length?(_=e,B):_},B.brushExtent=function(e){return arguments.length?(x=e,B):x},B},e.models.multiBar=function(){function C(e){return e.each(function(e){var g=n-t.left-t.right,C=r-t.top-t.bottom,k=d3.select(this);d&&e.length&&(d=[{values:e[0].values.map(function(e){return{x:e.x,y:0,series:e.series,size:.01}})}]),c&&(e=d3.layout.stack().offset(h).values(function(e){return e.values}).y(a)(!e.length&&d?d:e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),c&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i,i-=t.size):(t.y1=t.size+r,r+=t.size)})});var L=y&&b?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});i.domain(y||d3.merge(L).map(function(e){return e.x})).rangeBands(w||[0,g],S),s.domain(b||d3.extent(d3.merge(L).map(function(e){return c?e.y>0?e.y1:e.y1+e.y:e.y}).concat(f))).range(E||[C,0]),i.domain()[0]===i.domain()[1]&&(i.domain()[0]?i.domain([i.domain()[0]-i.domain()[0]*.01,i.domain()[1]+i.domain()[1]*.01]):i.domain([-1,1])),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]+s.domain()[0]*.01,s.domain()[1]-s.domain()[1]*.01]):s.domain([-1,1])),T=T||i,N=N||s;var A=k.selectAll("g.nv-wrap.nv-multibar").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),M=O.append("defs"),_=O.append("g"),D=A.select("g");_.append("g").attr("class","nv-groups"),A.attr("transform","translate("+t.left+","+t.top+")"),M.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),A.select("#nv-edge-clip-"+o+" rect").attr("width",g).attr("height",C),D.attr("clip-path",l?"url(#nv-edge-clip-"+o+")":"");var P=A.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});P.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),P.exit().selectAll("rect.nv-bar").attr("y",function(e){return c?N(e.y0):N(0)}).attr("height",0).remove(),P.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return p(e,t)}).style("stroke",function(e,t){return p(e,t)}),P.style("stroke-opacity",1).style("fill-opacity",.75);var H=P.selectAll("rect.nv-bar").data(function(t){return d&&!e.length?d.values:t.values});H.exit().remove();var B=H.enter().append("rect").attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(t,n,r){return c?0:r*i.rangeBand()/e.length}).attr("y",function(e){return N(c?e.y0:0)}).attr("height",0).attr("width",i.rangeBand()/(c?1:e.length)).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"});H.style("fill",function(e,t,n){return p(e,n,t)}).style("stroke",function(e,t,n){return p(e,n,t)}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"}),v&&(m||(m=e.map(function(){return!0})),H.style("fill",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()})),c?H.attr("y",function(e,t){return s(c?e.y1:0)}).attr("height",function(e,t){return Math.max(Math.abs(s(e.y+(c?e.y0:0))-s(c?e.y0:0)),1)}).attr("x",function(t,n){return c?0:t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/(c?1:e.length)):H.attr("x",function(t,n){return t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/e.length).attr("y",function(e,t){return a(e,t)<0?s(0):s(0)-s(a(e,t))<1?s(0)-1:s(a(e,t))||0}).attr("height",function(e,t){return Math.max(Math.abs(s(a(e,t))-s(0)),1)||0}),T=i.copy(),N=s.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=d3.scale.ordinal(),s=d3.scale.linear(),o=Math.floor(Math.random()*1e4),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=!0,c=!1,h="zero",p=e.utils.defaultColor(),d=!1,v=null,m,g=1200,y,b,w,E,S=.1,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(i=e,C):i},C.yScale=function(e){return arguments.length?(s=e,C):s},C.xDomain=function(e){return arguments.length?(y=e,C):y},C.yDomain=function(e){return arguments.length?(b=e,C):b},C.xRange=function(e){return arguments.length?(w=e,C):w},C.yRange=function(e){return arguments.length?(E=e,C):E},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(c=e,C):c},C.stackOffset=function(e){return arguments.length?(h=e,C):h},C.clipEdge=function(e){return arguments.length?(l=e,C):l},C.color=function(t){return arguments.length?(p=e.utils.getColor(t),C):p},C.barColor=function(t){return arguments.length?(v=e.utils.getColor(t),C):v},C.disabled=function(e){return arguments.length?(m=e,C):m},C.id=function(e){return arguments.length?(o=e,C):o},C.hideable=function(e){return arguments.length?(d=e,C):d},C.delay=function(e){return arguments.length?(g=e,C):g},C.groupSpacing=function(e){return arguments.length?(S=e,C):S},C},e.models.multiBarChart=function(){function A(e){return e.each(function(e){var b=d3.select(this),k=this,O=(u||parseInt(b.style("width"))||960)-o.left-o.right,M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom;A.update=function(){b.call(A)},A.container=this,S.disabled=e.map(function(e){return!!e.disabled});if(!x){var _;x={};for(_ in S)S[_]instanceof Array?x[_]=S[_].slice(0):x[_]=S[_]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var D=b.selectAll(".nv-noData").data([T]);return D.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),D.attr("x",o.left+O/2).attr("y",o.top+M/2).text(function(e){return e}),A}b.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();var P=b.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([e]),H=P.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),B=P.select("g");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-barsWrap"),H.append("g").attr("class","nv-legendWrap"),H.append("g").attr("class","nv-controlsWrap"),c&&(i.width(O-C()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),B.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom),B.select(".nv-legendWrap").attr("transform","translate("+C()+","+ -o.top+")"));if(l){var j=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(C()).color(["#444","#444","#444"]),B.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -o.top+")").call(s)}P.attr("transform","translate("+o.left+","+o.top+")"),d&&B.select(".nv-y.nv-axis").attr("transform","translate("+O+",0)"),t.disabled(e.map(function(e){return e.disabled})).width(O).height(M).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var F=B.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));F.call(t);if(h){n.scale(w).ticks(O/100).tickSize(-M,0),B.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),B.select(".nv-x.nv-axis").call(n);var I=B.select(".nv-x.nv-axis > g").selectAll("g");I.selectAll("line, text").style("opacity",1);if(m){var q=function(e,t){return"translate("+e+","+t+")"},R=5,U=17;I.selectAll("text").attr("transform",function(e,t,n){return q(0,n%2==0?R:U)});var z=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;B.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(e,t){return q(0,t===0||z%2!==0?U:R)})}v&&I.filter(function(t,n){return n%Math.ceil(e[0].values.length/(O/100))!==0}).selectAll("text, line").style("opacity",0),g&&I.selectAll(".tick text").attr("transform","rotate("+g+" 0,0)").style("text-anchor",g>0?"start":"end"),B.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}p&&(r.scale(E).ticks(M/36).tickSize(-O,0),B.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){S=e,N.stateChange(S),A.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;j=j.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}S.stacked=t.stacked(),N.stateChange(S),A.update()}),N.on("tooltipShow",function(e){y&&L(e,k.parentNode)}),N.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),S.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),S.stacked=n.stacked),A.update()})}),A}var t=e.models.multiBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=!1,g=0,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},w,E,S={stacked:!1},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=function(){return l?180:0},k=0;t.stacked(!1),n.orient("bottom").tickPadding(7).highlightZero(!0).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(d?"right":"left").tickFormat(d3.format(",.1f")),s.updateState(!1);var L=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,A);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],N.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){y&&e.tooltip.cleanup()}),A.dispatch=N,A.multibar=t,A.legend=i,A.xAxis=n,A.yAxis=r,d3.rebind(A,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","stacked","stackOffset","delay","barColor","groupSpacing"),A.options=e.utils.optionsFunc.bind(A),A.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,A):o},A.width=function(e){return arguments.length?(u=e,A):u},A.height=function(e){return arguments.length?(a=e,A):a},A.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),A):f},A.showControls=function(e){return arguments.length?(l=e,A):l},A.showLegend=function(e){return arguments.length?(c=e,A):c},A.showXAxis=function(e){return arguments.length?(h=e,A):h},A.showYAxis=function(e){return arguments.length?(p=e,A):p},A.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),A):d},A.reduceXTicks=function(e){return arguments.length?(v=e,A):v},A.rotateLabels=function(e){return arguments.length?(g=e,A):g},A.staggerLabels=function(e){return arguments.length?(m=e,A):m},A.tooltip=function(e){return arguments.length?(b=e,A):b},A.tooltips=function(e){return arguments.length?(y=e,A):y},A.tooltipContent=function(e){return arguments.length?(b=e,A):b},A.state=function(e){return arguments.length?(S=e,A):S},A.defaultState=function(e){return arguments.length?(x=e,A):x},A.noData=function(e){return arguments.length?(T=e,A):T},A.transitionDuration=function(e){return arguments.length?(k=e,A):k},A},e.models.multiBarHorizontal=function(){function C(e){return e.each(function(e){var i=n-t.left-t.right,y=r-t.top-t.bottom,C=d3.select(this);p&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),p&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i-t.size,i-=t.size):(t.y1=r,r+=t.size)})});var k=b&&w?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});s.domain(b||d3.merge(k).map(function(e){return e.x})).rangeBands(E||[0,y],.1),o.domain(w||d3.extent(d3.merge(k).map(function(e){return p?e.y>0?e.y1+e.y:e.y1:e.y}).concat(f))),d&&!p?o.range(S||[o.domain()[0]<0?m:0,i-(o.domain()[1]>0?m:0)]):o.range(S||[0,i]),T=T||s,N=N||d3.scale.linear().domain(o.domain()).range([o(0),o(0)]);var L=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([e]),A=L.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),O=A.append("defs"),M=A.append("g"),_=L.select("g");M.append("g").attr("class","nv-groups"),L.attr("transform","translate("+t.left+","+t.top+")");var D=L.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return l(e,t)}).style("stroke",function(e,t){return l(e,t)}),D.style("stroke-opacity",1).style("fill-opacity",.75);var P=D.selectAll("g.nv-bar").data(function(e){return e.values});P.exit().remove();var H=P.enter().append("g").attr("transform",function(t,n,r){return"translate("+N(p?t.y0:0)+","+(p?0:r*s.rangeBand()/e.length+s(u(t,n)))+")"});H.append("rect").attr("width",0).attr("height",s.rangeBand()/(p?1:e.length)),P.on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[o(a(t,n)+(p?t.y0:0)),s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.append("text"),d&&!p?(P.select("text").attr("text-anchor",function(e,t){return a(e,t)<0?"end":"start"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return g(a(e,t))}),P.select("text").attr("x",function(e,t){return a(e,t)<0?-4:o(a(e,t))-o(0)+4})):P.selectAll("text").text(""),v&&!p?(H.append("text").classed("nv-bar-label",!0),P.select("text.nv-bar-label").attr("text-anchor",function(e,t){return a(e,t)<0?"start":"end"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return u(e,t)}),P.select("text.nv-bar-label").attr("x",function(e,t){return a(e,t)<0?o(0)-o(a(e,t))+4:-4})):P.selectAll("text.nv-bar-label").text(""),P.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}),c&&(h||(h=e.map(function(){return!0})),P.style("fill",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()})),p?P.attr("transform",function(e,t){return"translate("+o(e.y1)+","+s(u(e,t))+")"}).select("rect").attr("width",function(e,t){return Math.abs(o(a(e,t)+e.y0)-o(e.y0))}).attr("height",s.rangeBand()):P.attr("transform",function(t,n){return"translate("+(a(t,n)<0?o(a(t,n)):o(0))+","+(t.series*s.rangeBand()/e.length+s(u(t,n)))+")"}).select("rect").attr("height",s.rangeBand()/e.length).attr("width",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)}),T=s.copy(),N=o.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=null,h,p=!1,d=!1,v=!1,m=60,g=d3.format(",.2f"),y=1200,b,w,E,S,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(s=e,C):s},C.yScale=function(e){return arguments.length?(o=e,C):o},C.xDomain=function(e){return arguments.length?(b=e,C):b},C.yDomain=function(e){return arguments.length?(w=e,C):w},C.xRange=function(e){return arguments.length?(E=e,C):E},C.yRange=function(e){return arguments.length?(S=e,C):S},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(p=e,C):p},C.color=function(t){return arguments.length?(l=e.utils.getColor(t),C):l},C.barColor=function(t){return arguments.length?(c=e.utils.getColor(t),C):c},C.disabled=function(e){return arguments.length?(h=e,C):h},C.id=function(e){return arguments.length?(i=e,C):i},C.delay=function(e){return arguments.length?(y=e,C):y},C.showValues=function(e){return arguments.length?(d=e,C):d},C.showBarLabels=function(e){return arguments.length?(v=e,C):v},C.valueFormat=function(e){return arguments.length?(g=e,C):g},C.valuePadding=function(e){return arguments.length?(m=e,C):m},C},e.models.multiBarHorizontalChart=function(){function C(e){return e.each(function(e){var d=d3.select(this),m=this,T=(u||parseInt(d.style("width"))||960)-o.left-o.right,k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom;C.update=function(){d.call(C)},C.container=this,b.disabled=e.map(function(e){return!!e.disabled});if(!w){var L;w={};for(L in b)b[L]instanceof Array?w[L]=b[L].slice(0):w[L]=b[L]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var A=d.selectAll(".nv-noData").data([E]);return A.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),A.attr("x",o.left+T/2).attr("y",o.top+k/2).text(function(e){return e}),C}d.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var O=d.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-legendWrap"),M.append("g").attr("class","nv-controlsWrap"),c&&(i.width(T-x()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),_.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom),_.select(".nv-legendWrap").attr("transform","translate("+x()+","+ -o.top+")"));if(l){var D=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(x()).color(["#444","#444","#444"]),_.select(".nv-controlsWrap").datum(D).attr("transform","translate(0,"+ -o.top+")").call(s)}O.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(e.map(function(e){return e.disabled})).width(T).height(k).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var P=_.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));P.call(t);if(h){n.scale(g).ticks(k/24).tickSize(-T,0),_.select(".nv-x.nv-axis").call(n);var H=_.select(".nv-x.nv-axis").selectAll("g");H.selectAll("line, text")}p&&(r.scale(y).ticks(T/100).tickSize(-k,0),_.select(".nv-y.nv-axis").attr("transform","translate(0,"+k+")"),_.select(".nv-y.nv-axis").call(r)),_.select(".nv-zeroLine line").attr("x1",y(0)).attr("x2",y(0)).attr("y1",0).attr("y2",-k),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),C.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;D=D.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}b.stacked=t.stacked(),S.stateChange(b),C.update()}),S.on("tooltipShow",function(e){v&&N(e,m.parentNode)}),S.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),b.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),b.stacked=n.stacked),C.update()})}),C}var t=e.models.multiBarHorizontal(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend().height(30),s=e.models.legend().height(30),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+" - "+t+"</h3>"+"<p>"+n+"</p>"},g,y,b={stacked:d},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=function(){return l?180:0},T=0;t.stacked(d),n.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("bottom").tickFormat(d3.format(",.1f")),s.updateState(!1);var N=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,C);e.tooltip.show([o,u],l,i.value<0?"e":"w",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),C.dispatch=S,C.multibar=t,C.legend=i,C.xAxis=n,C.yAxis=r,d3.rebind(C,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","delay","showValues","showBarLabels","valueFormat","stacked","barColor"),C.options=e.utils.optionsFunc.bind(C),C.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,C):o},C.width=function(e){return arguments.length?(u=e,C):u},C.height=function(e){return arguments.length?(a=e,C):a},C.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),C):f},C.showControls=function(e){return arguments.length?(l=e,C):l},C.showLegend=function(e){return arguments.length?(c=e,C):c},C.showXAxis=function(e){return arguments.length?(h=e,C):h},C.showYAxis=function(e){return arguments.length?(p=e,C):p},C.tooltip=function(e){return arguments.length?(m=e,C):m},C.tooltips=function(e){return arguments.length?(v=e,C):v},C.tooltipContent=function(e){return arguments.length?(m=e,C):m},C.state=function(e){return arguments.length?(b=e,C):b},C.defaultState=function(e){return arguments.length?(w=e,C):w},C.noData=function(e){return arguments.length?(E=e,C):E},C.transitionDuration=function(e){return arguments.length?(T=e,C):T},C},e.models.multiChart=function(){function C(e){return e.each(function(e){var u=d3.select(this),f=this;C.update=function(){u.call(C)},C.container=this;var k=(r||parseInt(u.style("width"))||960)-t.left-t.right,L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom,A=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==1}),O=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==2}),M=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==1}),_=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==2}),D=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==1}),P=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==2}),H=e.filter(function(e){return!e.disabled&&e.yAxis==1}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})}),B=e.filter(function(e){return!e.disabled&&e.yAxis==2}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})});a.domain(d3.extent(d3.merge(H.concat(B)),function(e){return e.x})).range([0,k]);var j=u.selectAll("g.wrap.multiChart").data([e]),F=j.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");F.append("g").attr("class","x axis"),F.append("g").attr("class","y1 axis"),F.append("g").attr("class","y2 axis"),F.append("g").attr("class","lines1Wrap"),F.append("g").attr("class","lines2Wrap"),F.append("g").attr("class","bars1Wrap"),F.append("g").attr("class","bars2Wrap"),F.append("g").attr("class","stack1Wrap"),F.append("g").attr("class","stack2Wrap"),F.append("g").attr("class","legendWrap");var I=j.select("g");s&&(x.width(k/2),I.select(".legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.yAxis==1?"":" (right axis)"),e})).call(x),t.top!=x.height()&&(t.top=x.height(),L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom),I.select(".legendWrap").attr("transform","translate("+k/2+","+ -t.top+")")),d.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="line"})),v.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="line"})),m.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="bar"})),g.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="bar"})),y.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="area"})),b.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="area"})),I.attr("transform","translate("+t.left+","+t.top+")");var q=I.select(".lines1Wrap").datum(A),R=I.select(".bars1Wrap").datum(M),U=I.select(".stack1Wrap").datum(D),z=I.select(".lines2Wrap").datum(O),W=I.select(".bars2Wrap").datum(_),X=I.select(".stack2Wrap").datum(P),V=D.length?D.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[],$=P.length?P.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[];h.domain(l||d3.extent(d3.merge(H).concat(V),function(e){return e.y})).range([0,L]),p.domain(c||d3.extent(d3.merge(B).concat($),function(e){return e.y})).range([0,L]),d.yDomain(h.domain()),m.yDomain(h.domain()),y.yDomain(h.domain()),v.yDomain(p.domain()),g.yDomain(p.domain()),b.yDomain(p.domain()),D.length&&d3.transition(U).call(y),P.length&&d3.transition(X).call(b),M.length&&d3.transition(R).call(m),_.length&&d3.transition(W).call(g),A.length&&d3.transition(q).call(d),O.length&&d3.transition(z).call(v),w.ticks(k/100).tickSize(-L,0),I.select(".x.axis").attr("transform","translate(0,"+L+")"),d3.transition(I.select(".x.axis")).call(w),E.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y1.axis")).call(E),S.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y2.axis")).call(S),I.select(".y2.axis").style("opacity",B.length?1:0).attr("transform","translate("+a.range()[1]+",0)"),x.dispatch.on("stateChange",function(e){C.update()}),T.on("tooltipShow",function(e){o&&N(e,f.parentNode)})}),C}var t={top:30,right:20,bottom:50,left:60},n=d3.scale.category20().range(),r=null,i=null,s=!0,o=!0,u=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},a,f,l,c,a=d3.scale.linear(),h=d3.scale.linear(),p=d3.scale.linear(),d=e.models.line().yScale(h),v=e.models.line().yScale(p),m=e.models.multiBar().stacked(!1).yScale(h),g=e.models.multiBar().stacked(!1).yScale(p),y=e.models.stackedArea().yScale(h),b=e.models.stackedArea().yScale(p),w=e.models.axis().scale(a).orient("bottom").tickPadding(5),E=e.models.axis().scale(h).orient("left"),S=e.models.axis().scale(p).orient("right"),x=e.models.legend().height(30),T=d3.dispatch("tooltipShow","tooltipHide"),N=function(t,n){var r=t.pos[0]+(n.offsetLeft||0),i=t.pos[1]+(n.offsetTop||0),s=w.tickFormat()(d.x()(t.point,t.pointIndex)),o=(t.series.yAxis==2?S:E).tickFormat()(d.y()(t.point,t.pointIndex)),a=u(t.series.key,s,o,t,C);e.tooltip.show([r,i],a,undefined,undefined,n.offsetParent)};return d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),m.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),m.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),g.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),g.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),y.dispatch.on("tooltipShow",function(e){if(!Math.round(y.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),y.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),b.dispatch.on("tooltipShow",function(e){if(!Math.round(b.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),b.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){o&&e.tooltip.cleanup()}),C.dispatch=T,C.lines1=d,C.lines2=v,C.bars1=m,C.bars2=g,C.stack1=y,C.stack2=b,C.xAxis=w,C.yAxis1=E,C.yAxis2=S,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(getX=e,d.x(e),m.x(e),C):getX},C.y=function(e){return arguments.length?(getY=e,d.y(e),m.y(e),C):getY},C.yDomain1=function(e){return arguments.length?(l=e,C):l},C.yDomain2=function(e){return arguments.length?(c=e,C):c},C.margin=function(e){return arguments.length?(t=e,C):t},C.width=function(e){return arguments.length?(r=e,C):r},C.height=function(e){return arguments.length?(i=e,C):i},C.color=function(e){return arguments.length?(n=e,x.color(e),C):n},C.showLegend=function(e){return arguments.length?(s=e,C):s},C.tooltips=function(e){return arguments.length?(o=e,C):o},C.tooltipContent=function(e){return arguments.length?(u=e,C):u},C},e.models.ohlcBar=function(){function x(e){return e.each(function(e){var g=n-t.left-t.right,x=r-t.top-t.bottom,T=d3.select(this);s.domain(y||d3.extent(e[0].values.map(u).concat(p))),v?s.range(w||[g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range(w||[0,g]),o.domain(b||[d3.min(e[0].values.map(h).concat(d)),d3.max(e[0].values.map(c).concat(d))]).range(E||[x,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([e[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-ticks"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){S.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",x),A.attr("clip-path",m?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-ticks").selectAll(".nv-tick").data(function(e){return e});O.exit().remove();var M=O.enter().append("path").attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"}).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),S.elementMouseover({point:t,series:e[0],pos:[s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),S.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){S.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){S.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}),d3.transition(O).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"})}),x}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=function(e){return e.open},l=function(e){return e.close},c=function(e){return e.high},h=function(e){return e.low},p=[],d=[],v=!1,m=!0,g=e.utils.defaultColor(),y,b,w,E,S=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return x.dispatch=S,x.options=e.utils.optionsFunc.bind(x),x.x=function(e){return arguments.length?(u=e,x):u},x.y=function(e){return arguments.length?(a=e,x):a},x.open=function(e){return arguments.length?(f=e,x):f},x.close=function(e){return arguments.length?(l=e,x):l},x.high=function(e){return arguments.length?(c=e,x):c},x.low=function(e){return arguments.length?(h=e,x):h},x.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,x):t},x.width=function(e){return arguments.length?(n=e,x):n},x.height=function(e){return arguments.length?(r=e,x):r},x.xScale=function(e){return arguments.length?(s=e,x):s},x.yScale=function(e){return arguments.length?(o=e,x):o},x.xDomain=function(e){return arguments.length?(y=e,x):y},x.yDomain=function(e){return arguments.length?(b=e,x):b},x.xRange=function(e){return arguments.length?(w=e,x):w},x.yRange=function(e){return arguments.length?(E=e,x):E},x.forceX=function(e){return arguments.length?(p=e,x):p},x.forceY=function(e){return arguments.length?(d=e,x):d},x.padData=function(e){return arguments.length?(v=e,x):v},x.clipEdge=function(e){return arguments.length?(m=e,x):m},x.color=function(t){return arguments.length?(g=e.utils.getColor(t),x):g},x.id=function(e){return arguments.length?(i=e,x):i},x},e.models.pie=function(){function S(e){return e.each(function(e){function q(e){var t=(e.startAngle+e.endAngle)*90/Math.PI-90;return t>90?t-180:t}function R(e){e.endAngle=isNaN(e.endAngle)?0:e.endAngle,e.startAngle=isNaN(e.startAngle)?0:e.startAngle,m||(e.innerRadius=0);var t=d3.interpolate(this._current,e);return this._current=t(0),function(e){return A(t(e))}}function U(e){e.innerRadius=0;var t=d3.interpolate({startAngle:0,endAngle:0},e);return function(e){return A(t(e))}}var o=n-t.left-t.right,f=r-t.top-t.bottom,S=Math.min(o,f)/2,x=S-S/5,T=d3.select(this),N=T.selectAll(".nv-wrap.nv-pie").data(e),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+u),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-pie"),k.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+t.left+","+t.top+")"),L.select(".nv-pie").attr("transform","translate("+o/2+","+f/2+")"),L.select(".nv-pieLabels").attr("transform","translate("+o/2+","+f/2+")"),T.on("click",function(e,t){E.chartClick({data:e,index:t,pos:d3.event,id:u})});var A=d3.svg.arc().outerRadius(x);y&&A.startAngle(y),b&&A.endAngle(b),m&&A.innerRadius(S*w);var O=d3.layout.pie().sort(null).value(function(e){return e.disabled?0:s(e)}),M=N.select(".nv-pie").selectAll(".nv-slice").data(O),_=N.select(".nv-pieLabels").selectAll(".nv-label").data(O);M.exit().remove(),_.exit().remove();var D=M.enter().append("g").attr("class","nv-slice").on("mouseover",function(e,t){d3.select(this).classed("hover",!0),E.elementMouseover({label:i(e.data),value:s(e.data),point:e.data,pointIndex:t,pos:[d3.event.pageX,d3.event.pageY],id:u})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),E.elementMouseout({label:i(e.data),value:s(e.data),point:e.data,index:t,id:u})}).on("click",function(e,t){E.elementClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()}).on("dblclick",function(e,t){E.elementDblClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()});M.attr("fill",function(e,t){return a(e,t)}).attr("stroke",function(e,t){return a(e,t)});var P=D.append("path").each(function(e){this._current=e});M.select("path").attr("d",A);if(l){var H=d3.svg.arc().innerRadius(0);c&&(H=A),h&&(H=d3.svg.arc().outerRadius(A.outerRadius())),_.enter().append("g").classed("nv-label",!0).each(function(e,t){var n=d3.select(this);n.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}return e.outerRadius=S+10,e.innerRadius=S+15,"translate("+H.centroid(e)+")"}),n.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),n.append("text").style("text-anchor",g?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")});var B={},j=14,F=140,I=function(e){return Math.floor(e[0]/F)*F+","+Math.floor(e[1]/j)*j};_.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}e.outerRadius=S+10,e.innerRadius=S+15;var n=H.centroid(e),r=I(n);return B[r]&&(n[1]-=j),B[I(n)]=!0,"translate("+n+")"}),_.select(".nv-label text").style("text-anchor",g?(d.startAngle+d.endAngle)/2<Math.PI?"start":"end":"middle").text(function(e,t){var n=(e.endAngle-e.startAngle)/(2*Math.PI),r={key:i(e.data),value:s(e.data),percent:d3.format("%")(n)};return e.value&&n>v?r[p]:""})}}),S}var t={top:0,right:0,bottom:0,left:0},n=500,r=500,i=function(e){return e.x},s=function(e){return e.y},o=function(e){return e.description},u=Math.floor(Math.random()*1e4),a=e.utils.defaultColor(),f=d3.format(",.2f"),l=!0,c=!0,h=!1,p="key",v=.02,m=!1,g=!1,y=!1,b=!1,w=.5,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return S.dispatch=E,S.options=e.utils.optionsFunc.bind(S),S.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,S):t},S.width=function(e){return arguments.length?(n=e,S):n},S.height=function(e){return arguments.length?(r=e,S):r},S.values=function(t){return e.log("pie.values() is no longer supported."),S},S.x=function(e){return arguments.length?(i=e,S):i},S.y=function(e){return arguments.length?(s=d3.functor(e),S):s},S.description=function(e){return arguments.length?(o=e,S):o},S.showLabels=function(e){return arguments.length?(l=e,S):l},S.labelSunbeamLayout=function(e){return arguments.length?(g=e,S):g},S.donutLabelsOutside=function(e){return arguments.length?(h=e,S):h},S.pieLabelsOutside=function(e){return arguments.length?(c=e,S):c},S.labelType=function(e){return arguments.length?(p=e,p=p||"key",S):p},S.donut=function(e){return arguments.length?(m=e,S):m},S.donutRatio=function(e){return arguments.length?(w=e,S):w},S.startAngle=function(e){return arguments.length?(y=e,S):y},S.endAngle=function(e){return arguments.length?(b=e,S):b},S.id=function(e){return arguments.length?(u=e,S):u},S.color=function(t){return arguments.length?(a=e.utils.getColor(t),S):a},S.valueFormat=function(e){return arguments.length?(f=e,S):f},S.labelThreshold=function(e){return arguments.length?(v=e,S):v},S},e.models.pieChart=function(){function v(e){return e.each(function(e){var u=d3.select(this),a=this,f=(i||parseInt(u.style("width"))||960)-r.left-r.right,d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom;v.update=function(){u.call(v)},v.container=this,l.disabled=e.map(function(e){return!!e.disabled});if(!c){var m;c={};for(m in l)l[m]instanceof Array?c[m]=l[m].slice(0):c[m]=l[m]}if(!e||!e.length){var g=u.selectAll(".nv-noData").data([h]);return g.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),g.attr("x",r.left+f/2).attr("y",r.top+d/2).text(function(e){return e}),v}u.selectAll(".nv-noData").remove();var y=u.selectAll("g.nv-wrap.nv-pieChart").data([e]),b=y.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),w=y.select("g");b.append("g").attr("class","nv-pieWrap"),b.append("g").attr("class","nv-legendWrap"),o&&(n.width(f).key(t.x()),y.select(".nv-legendWrap").datum(e).call(n),r.top!=n.height()&&(r.top=n.height(),d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom),y.select(".nv-legendWrap").attr("transform","translate(0,"+ -r.top+")")),y.attr("transform","translate("+r.left+","+r.top+")"),t.width(f).height(d);var E=w.select(".nv-pieWrap").datum([e]);d3.transition(E).call(t),n.dispatch.on("stateChange",function(e){l=e,p.stateChange(l),v.update()}),t.dispatch.on("elementMouseout.tooltip",function(e){p.tooltipHide(e)}),p.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),l.disabled=t.disabled),v.update()})}),v}var t=e.models.pie(),n=e.models.legend(),r={top:30,right:20,bottom:20,left:20},i=null,s=null,o=!0,u=e.utils.defaultColor(),a=!0,f=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+t+"</p>"},l={},c=null,h="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),d=function(n,r){var i=t.description()(n.point)||t.x()(n.point),s=n.pos[0]+(r&&r.offsetLeft||0),o=n.pos[1]+(r&&r.offsetTop||0),u=t.valueFormat()(t.y()(n.point)),a=f(i,u,n,v);e.tooltip.show([s,o],a,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+r.left,e.pos[1]+r.top],p.tooltipShow(e)}),p.on("tooltipShow",function(e){a&&d(e)}),p.on("tooltipHide",function(){a&&e.tooltip.cleanup()}),v.legend=n,v.dispatch=p,v.pie=t,d3.rebind(v,t,"valueFormat","values","x","y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","labelType","donut","donutRatio","labelThreshold"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(r.top=typeof e.top!="undefined"?e.top:r.top,r.right=typeof e.right!="undefined"?e.right:r.right,r.bottom=typeof e.bottom!="undefined"?e.bottom:r.bottom,r.left=typeof e.left!="undefined"?e.left:r.left,v):r},v.width=function(e){return arguments.length?(i=e,v):i},v.height=function(e){return arguments.length?(s=e,v):s},v.color=function(r){return arguments.length?(u=e.utils.getColor(r),n.color(u),t.color(u),v):u},v.showLegend=function(e){return arguments.length?(o=e,v):o},v.tooltips=function(e){return arguments.length?(a=e,v):a},v.tooltipContent=function(e){return arguments.length?(f=e,v):f},v.state=function(e){return arguments.length?(l=e,v):l},v.defaultState=function(e){return arguments.length?(c=e,v):c},v.noData=function(e){return arguments.length?(h=e,v):h},v},e.models.scatter=function(){function I(q){return q.each(function(I){function Q(){if(!g)return!1;var e,i=d3.merge(I.map(function(e,t){return e.values.map(function(e,n){var r=f(e,n),i=l(e,n);return[o(r),u(i),t,n,e]}).filter(function(e,t){return b(e[4],t)})}));if(D===!0){if(x){var a=X.select("defs").selectAll(".nv-point-clips").data([s]).enter();a.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+s);var c=X.select("#nv-points-clip-"+s).selectAll("circle").data(i);c.enter().append("circle").attr("r",T),c.exit().remove(),c.attr("cx",function(e){return e[0]}).attr("cy",function(e){return e[1]}),X.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+s+")")}i.length&&(i.push([o.range()[0]-20,u.range()[0]-20,null,null]),i.push([o.range()[1]+20,u.range()[1]+20,null,null]),i.push([o.range()[0]-20,u.range()[0]+20,null,null]),i.push([o.range()[1]+20,u.range()[1]-20,null,null]));var h=d3.geom.polygon([[-10,-10],[-10,r+10],[n+10,r+10],[n+10,-10]]),p=1e-6;i=i.sort(function(e,t){return e[0]-t[0]||e[1]-t[1]});for(var d=0;d<i.length-1;)Math.abs(i[d][0]-i[d+1][0])<p&&Math.abs(i[d][1]-i[d+1][1])<p?i.splice(d+1,1):d++;var v=d3.geom.voronoi(i).map(function(e,t){return{data:h.clip(e),series:i[t][2],point:i[t][3]}}),m=X.select(".nv-point-paths").selectAll("path").data(v);m.enter().append("path").attr("class",function(e,t){return"nv-path-"+t}),m.exit().remove(),m.attr("d",function(e){return!e||!e.data||e.data.length===0?"M 0 0":"M"+e.data.join("L")+"Z"});var y=function(e,n){if(F)return 0;var r=I[e.series];if(typeof r=="undefined")return;var i=r.values[e.point];n({point:i,series:r,pos:[o(f(i,e.point))+t.left,u(l(i,e.point))+t.top],seriesIndex:e.series,pointIndex:e.point})};m.on("click",function(e){y(e,_.elementClick)}).on("mouseover",function(e){y(e,_.elementMouseover)}).on("mouseout",function(e,t){y(e,_.elementMouseout)})}else X.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementClick({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseover",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementMouseover({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseout",function(e,t){if(F||!I[e.series])return 0;var n=I[e.series],r=n.values[t];_.elementMouseout({point:r,series:n,seriesIndex:e.series,pointIndex:t})});F=!1}var q=n-t.left-t.right,R=r-t.top-t.bottom,U=d3.select(this);I.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var W=N&&C&&A?[]:d3.merge(I.map(function(e){return e.values.map(function(e,t){return{x:f(e,t),y:l(e,t),size:c(e,t)}})}));o.domain(N||d3.extent(W.map(function(e){return e.x}).concat(d))),w&&I[0]?o.range(k||[(q*E+q)/(2*I[0].values.length),q-q*(1+E)/(2*I[0].values.length)]):o.range(k||[0,q]),u.domain(C||d3.extent(W.map(function(e){return e.y}).concat(v))).range(L||[R,0]),a.domain(A||d3.extent(W.map(function(e){return e.size}).concat(m))).range(O||[16,256]);if(o.domain()[0]===o.domain()[1]||u.domain()[0]===u.domain()[1])M=!0;o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]-o.domain()[0]*.01,o.domain()[1]+o.domain()[1]*.01]):o.domain([-1,1])),u.domain()[0]===u.domain()[1]&&(u.domain()[0]?u.domain([u.domain()[0]-u.domain()[0]*.01,u.domain()[1]+u.domain()[1]*.01]):u.domain([-1,1])),isNaN(o.domain()[0])&&o.domain([-1,1]),isNaN(u.domain()[0])&&u.domain([-1,1]),P=P||o,H=H||u,B=B||a;var X=U.selectAll("g.nv-wrap.nv-scatter").data([I]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+s+(M?" nv-single-point":"")),$=V.append("defs"),J=V.append("g"),K=X.select("g");J.append("g").attr("class","nv-groups"),J.append("g").attr("class","nv-point-paths"),X.attr("transform","translate("+t.left+","+t.top+")"),$.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),X.select("#nv-edge-clip-"+s+" rect").attr("width",q).attr("height",R>0?R:0),K.attr("clip-path",S?"url(#nv-edge-clip-"+s+")":""),F=!0;var G=X.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});G.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),G.exit().remove(),G.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),G.style("fill",function(e,t){return i(e,t)}).style("stroke",function(e,t){return i(e,t)}).style("stroke-opacity",1).style("fill-opacity",.5);if(p){var Y=G.selectAll("circle.nv-point").data(function(e){return e.values},y);Y.enter().append("circle").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("cx",function(t,n){return e.utils.NaNtoZero(P(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(H(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)}),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)})}else{var Y=G.selectAll("path.nv-point").data(function(e){return e.values});Y.enter().append("path").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("transform",function(e,t){return"translate("+P(f(e,t))+","+H(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))})),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))}))}clearTimeout(j),j=setTimeout(Q,300),P=o.copy(),H=u.copy(),B=a.copy()}),I}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=d3.scale.linear(),u=d3.scale.linear(),a=d3.scale.linear(),f=function(e){return e.x},l=function(e){return e.y},c=function(e){return e.size||1},h=function(e){return e.shape||"circle"},p=!0,d=[],v=[],m=[],g=!0,y=null,b=function(e){return!e.notActive},w=!1,E=.1,S=!1,x=!0,T=function(){return 25},N=null,C=null,k=null,L=null,A=null,O=null,M=!1,_=d3.dispatch("elementClick","elementMouseover","elementMouseout"),D=!0,P,H,B,j,F=!1;return I.clearHighlights=function(){d3.selectAll(".nv-chart-"+s+" .nv-point.hover").classed("hover",!1)},I.highlightPoint=function(e,t,n){d3.select(".nv-chart-"+s+" .nv-series-"+e+" .nv-point-"+t).classed("hover",n)},_.on("elementMouseover.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!0)}),_.on("elementMouseout.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!1)}),I.dispatch=_,I.options=e.utils.optionsFunc.bind(I),I.x=function(e){return arguments.length?(f=d3.functor(e),I):f},I.y=function(e){return arguments.length?(l=d3.functor(e),I):l},I.size=function(e){return arguments.length?(c=d3.functor(e),I):c},I.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,I):t},I.width=function(e){return arguments.length?(n=e,I):n},I.height=function(e){return arguments.length?(r=e,I):r},I.xScale=function(e){return arguments.length?(o=e,I):o},I.yScale=function(e){return arguments.length?(u=e,I):u},I.zScale=function(e){return arguments.length?(a=e,I):a},I.xDomain=function(e){return arguments.length?(N=e,I):N},I.yDomain=function(e){return arguments.length?(C=e,I):C},I.sizeDomain=function(e){return arguments.length?(A=e,I):A},I.xRange=function(e){return arguments.length?(k=e,I):k},I.yRange=function(e){return arguments.length?(L=e,I):L},I.sizeRange=function(e){return arguments.length?(O=e,I):O},I.forceX=function(e){return arguments.length?(d=e,I):d},I.forceY=function(e){return arguments.length?(v=e,I):v},I.forceSize=function(e){return arguments.length?(m=e,I):m},I.interactive=function(e){return arguments.length?(g=e,I):g},I.pointKey=function(e){return arguments.length?(y=e,I):y},I.pointActive=function(e){return arguments.length?(b=e,I):b},I.padData=function(e){return arguments.length?(w=e,I):w},I.padDataOuter=function(e){return arguments.length?(E=e,I):E},I.clipEdge=function(e){return arguments.length?(S=e,I):S},I.clipVoronoi=function(e){return arguments.length?(x=e,I):x},I.useVoronoi=function(e){return arguments.length?(D=e,D===!1&&(x=!1),I):D},I.clipRadius=function(e){return arguments.length?(T=e,I):T},I.color=function(t){return arguments.length?(i=e.utils.getColor(t),I):i},I.shape=function(e){return arguments.length?(h=e,I):h},I.onlyCircles=function(e){return arguments.length?(p=e,I):p},I.id=function(e){return arguments.length?(s=e,I):s},I.singlePoint=function(e){return arguments.length?(M=e,I):M},I},e.models.scatterChart=function(){function F(e){return e.each(function(e){function J(){if(T)return W.select(".nv-point-paths").style("pointer-events","all"),!1;W.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(x).focus(i[0]),p.distortion(x).focus(i[1]),W.select(".nv-scatterWrap").call(t),b&&W.select(".nv-x.nv-axis").call(n),w&&W.select(".nv-y.nv-axis").call(r),W.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),W.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var C=d3.select(this),k=this,L=(f||parseInt(C.style("width"))||960)-a.left-a.right,D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom;F.update=function(){C.call(F)},F.container=this,A.disabled=e.map(function(e){return!!e.disabled});if(!O){var I;O={};for(I in A)A[I]instanceof Array?O[I]=A[I].slice(0):O[I]=A[I]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=C.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",a.left+L/2).attr("y",a.top+D/2).text(function(e){return e}),F}C.selectAll(".nv-noData").remove(),P=P||h,H=H||p;var R=C.selectAll("g.nv-wrap.nv-scatterChart").data([e]),U=R.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),z=U.append("g"),W=R.select("g");z.append("rect").attr("class","nvd3 nv-background"),z.append("g").attr("class","nv-x nv-axis"),z.append("g").attr("class","nv-y nv-axis"),z.append("g").attr("class","nv-scatterWrap"),z.append("g").attr("class","nv-distWrap"),z.append("g").attr("class","nv-legendWrap"),z.append("g").attr("class","nv-controlsWrap");if(y){var X=S?L/2:L;i.width(X),R.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom),R.select(".nv-legendWrap").attr("transform","translate("+(L-X)+","+ -a.top+")")}S&&(s.width(180).color(["#444"]),W.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -a.top+")").call(s)),R.attr("transform","translate("+a.left+","+a.top+")"),E&&W.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),t.width(L).height(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),d!==0&&t.xDomain(null),v!==0&&t.yDomain(null),R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t);if(d!==0){var V=h.domain()[1]-h.domain()[0];t.xDomain([h.domain()[0]-d*V,h.domain()[1]+d*V])}if(v!==0){var $=p.domain()[1]-p.domain()[0];t.yDomain([p.domain()[0]-v*$,p.domain()[1]+v*$])}(v!==0||d!==0)&&R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),b&&(n.scale(h).ticks(n.ticks()&&n.ticks().length?n.ticks():L/100).tickSize(-D,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),w&&(r.scale(p).ticks(r.ticks()&&r.ticks().length?r.ticks():D/36).tickSize(-L,0),W.select(".nv-y.nv-axis").call(r)),m&&(o.getData(t.x()).scale(h).width(L).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),W.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),g&&(u.getData(t.y()).scale(p).width(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),W.select(".nv-distributionY").attr("transform","translate("+(E?L:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(W.select(".nv-background").attr("width",L).attr("height",D),W.select(".nv-background").on("mousemove",J),W.select(".nv-background").on("click",function(){T=!T}),t.dispatch.on("elementClick.freezeFisheye",function(){T=!T})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,x=e.disabled?0:2.5,W.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),W.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(x).focus(0),p.distortion(x).focus(0),W.select(".nv-scatterWrap").call(t),W.select(".nv-x.nv-axis").call(n),W.select(".nv-y.nv-axis").call(r)):T=!1,F.update()}),i.dispatch.on("stateChange",function(e){A.disabled=e.disabled,M.stateChange(A),F.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",function(t,n){return e.pos[1]-D}),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],M.tooltipShow(e)}),M.on("tooltipShow",function(e){N&&B(e,k.parentNode)}),M.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),A.disabled=t.disabled),F.update()}),P=h.copy(),H=p.copy()}),F}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=0,v=0,m=!1,g=!1,y=!0,b=!0,w=!0,E=!1,S=!!d3.fisheye,x=0,T=!1,N=!0,C=function(e,t,n){return"<strong>"+t+"</strong>"},k=function(e,t,n){return"<strong>"+n+"</strong>"},L=null,A={},O=null,M=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),_="No Data Available.",D=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(E?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var P,H,B=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));C!=null&&e.tooltip.show([f,l],C(i.series.key,v,m,i,F),"n",1,s,"x-nvtooltip"),k!=null&&e.tooltip.show([c,d],k(i.series.key,v,m,i,F),"e",1,s,"y-nvtooltip"),L!=null&&e.tooltip.show([o,u],L(i.series.key,v,m,i,F),i.value<0?"n":"s",null,s)},j=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){M.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),M.on("tooltipHide",function(){N&&e.tooltip.cleanup()}),F.dispatch=M,F.scatter=t,F.legend=i,F.controls=s,F.xAxis=n,F.yAxis=r,F.distX=o,F.distY=u,d3.rebind(F,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),F.options=e.utils.optionsFunc.bind(F),F.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,F):a},F.width=function(e){return arguments.length?(f=e,F):f},F.height=function(e){return arguments.length?(l=e,F):l},F.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),F):c},F.showDistX=function(e){return arguments.length?(m=e,F):m},F.showDistY=function(e){return arguments.length?(g=e,F):g},F.showControls=function(e){return arguments.length?(S=e,F):S},F.showLegend=function(e){return arguments.length?(y=e,F):y},F.showXAxis=function(e){return arguments.length?(b=e,F):b},F.showYAxis=function(e){return arguments.length?(w=e,F):w},F.rightAlignYAxis=function(e){return arguments.length?(E=e,r.orient(e?"right":"left"),F):E},F.fisheye=function(e){return arguments.length?(x=e,F):x},F.xPadding=function(e){return arguments.length?(d=e,F):d},F.yPadding=function(e){return arguments.length?(v=e,F):v},F.tooltips=function(e){return arguments.length?(N=e,F):N},F.tooltipContent=function(e){return arguments.length?(L=e,F):L},F.tooltipXContent=function(e){return arguments.length?(C=e,F):C},F.tooltipYContent=function(e){return arguments.length?(k=e,F):k},F.state=function(e){return arguments.length?(A=e,F):A},F.defaultState=function(e){return arguments.length?(O=e,F):O},F.noData=function(e){return arguments.length?(_=e,F):_},F.transitionDuration=function(e){return arguments.length?(D=e,F):D},F},e.models.scatterPlusLineChart=function(){function B(e){return e.each(function(e){function V(){if(S)return U.select(".nv-point-paths").style("pointer-events","all"),!1;U.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(E).focus(i[0]),p.distortion(E).focus(i[1]),U.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),g&&U.select(".nv-x.nv-axis").call(n),y&&U.select(".nv-y.nv-axis").call(r),U.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),U.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var T=d3.select(this),N=this,C=(f||parseInt(T.style("width"))||960)-a.left-a.right,M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom;B.update=function(){T.call(B)},B.container=this,k.disabled=e.map(function(e){return!!e.disabled});if(!L){var j;L={};for(j in k)k[j]instanceof Array?L[j]=k[j].slice(0):L[j]=k[j]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var F=T.selectAll(".nv-noData").data([O]);return F.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),F.attr("x",a.left+C/2).attr("y",a.top+M/2).text(function(e){return e}),B}T.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale(),_=_||h,D=D||p;var I=T.selectAll("g.nv-wrap.nv-scatterChart").data([e]),q=I.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),R=q.append("g"),U=I.select("g");R.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-scatterWrap"),R.append("g").attr("class","nv-regressionLinesWrap"),R.append("g").attr("class","nv-distWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),I.attr("transform","translate("+a.left+","+a.top+")"),b&&U.select(".nv-y.nv-axis").attr("transform","translate("+C+",0)"),m&&(i.width(C/2),I.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom),I.select(".nv-legendWrap").attr("transform","translate("+C/2+","+ -a.top+")")),w&&(s.width(180).color(["#444"]),U.select(".nv-controlsWrap").datum(H).attr("transform","translate(0,"+ -a.top+")").call(s)),t.width(C).height(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),I.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),I.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+t.id()+")");var z=I.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(e){return e});z.enter().append("g").attr("class","nv-regLines");var W=z.selectAll(".nv-regLine").data(function(e){return[e]}),X=W.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0);W.attr("x1",h.range()[0]).attr("x2",h.range()[1]).attr("y1",function(e,t){return p(h.domain()[0]*e.slope+e.intercept)}).attr("y2",function(e,t){return p(h.domain()[1]*e.slope+e.intercept)}).style("stroke",function(e,t,n){return c(e,n)}).style("stroke-opacity",function(e,t){return e.disabled||typeof e.slope=="undefined"||typeof e.intercept=="undefined"?0:1}),g&&(n.scale(h).ticks(n.ticks()?n.ticks():C/100).tickSize(-M,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),y&&(r.scale(p).ticks(r.ticks()?r.ticks():M/36).tickSize(-C,0),U.select(".nv-y.nv-axis").call(r)),d&&(o.getData(t.x()).scale(h).width(C).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),U.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),v&&(u.getData(t.y()).scale(p).width(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),U.select(".nv-distributionY").attr("transform","translate("+(b?C:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(U.select(".nv-background").attr("width",C).attr("height",M),U.select(".nv-background").on("mousemove",V),U.select(".nv-background").on("click",function(){S=!S}),t.dispatch.on("elementClick.freezeFisheye",function(){S=!S})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,E=e.disabled?0:2.5,U.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),U.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(E).focus(0),p.distortion(E).focus(0),U.select(".nv-scatterWrap").call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r)):S=!1,B.update()}),i.dispatch.on("stateChange",function(e){k=e,A.stateChange(k),B.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-M),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],A.tooltipShow(e)}),A.on("tooltipShow",function(e){x&&P(e,N.parentNode)}),A.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),k.disabled=t.disabled),B.update()}),_=h.copy(),D=p.copy()}),B}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=!1,v=!1,m=!0,g=!0,y=!0,b=!1,w=!!d3.fisheye,E=0,S=!1,x=!0,T=function(e,t,n){return"<strong>"+t+"</strong>"},N=function(e,t,n){return"<strong>"+n+"</strong>"},C=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+r+"</p>"},k={},L=null,A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),O="No Data Available.",M=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(b?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var _,D,P=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));T!=null&&e.tooltip.show([f,l],T(i.series.key,v,m,i,B),"n",1,s,"x-nvtooltip"),N!=null&&e.tooltip.show([c,d],N(i.series.key,v,m,i,B),"e",1,s,"y-nvtooltip"),C!=null&&e.tooltip.show([o,u],C(i.series.key,v,m,i.point.tooltip,i,B),i.value<0?"n":"s",null,s)},H=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){A.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),A.on("tooltipHide",function(){x&&e.tooltip.cleanup()}),B.dispatch=A,B.scatter=t,B.legend=i,B.controls=s,B.xAxis=n,B.yAxis=r,B.distX=o,B.distY=u,d3.rebind(B,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),B.options=e.utils.optionsFunc.bind(B),B.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,B):a},B.width=function(e){return arguments.length?(f=e,B):f},B.height=function(e){return arguments.length?(l=e,B):l},B.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),B):c},B.showDistX=function(e){return arguments.length?(d=e,B):d},B.showDistY=function(e){return arguments.length?(v=e,B):v},B.showControls=function(e){return arguments.length?(w=e,B):w},B.showLegend=function(e){return arguments.length?(m=e,B):m},B.showXAxis=function(e){return arguments.length?(g=e,B):g},B.showYAxis=function(e){return arguments.length?(y=e,B):y},B.rightAlignYAxis=function(e){return arguments.length?(b=e,r.orient(e?"right":"left"),B):b},B.fisheye=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(x=e,B):x},B.tooltipContent=function(e){return arguments.length?(C=e,B):C},B.tooltipXContent=function(e){return arguments.length?(T=e,B):T},B.tooltipYContent=function(e){return arguments.length?(N=e,B):N},B.state=function(e){return arguments.length?(k=e,B):k},B.defaultState=function(e){return arguments.length?(L=e,B):L},B.noData=function(e){return arguments.length?(O=e,B):O},B.transitionDuration=function(e){return arguments.length?(M=e,B):M},B},e.models.sparkline=function(){function d(e){return e.each(function(e){var i=n-t.left-t.right,d=r-t.top-t.bottom,v=d3.select(this);s.domain(l||d3.extent(e,u)).range(h||[0,i]),o.domain(c||d3.extent(e,a)).range(p||[d,0]);var m=v.selectAll("g.nv-wrap.nv-sparkline").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline"),b=g.append("g"),w=m.select("g");m.attr("transform","translate("+t.left+","+t.top+")");var E=m.selectAll("path").data(function(e){return[e]});E.enter().append("path"),E.exit().remove(),E.style("stroke",function(e,t){return e.color||f(e,t)}).attr("d",d3.svg.line().x(function(e,t){return s(u(e,t))}).y(function(e,t){return o(a(e,t))}));var S=m.selectAll("circle.nv-point").data(function(e){function n(t){if(t!=-1){var n=e[t];return n.pointIndex=t,n}return null}var t=e.map(function(e,t){return a(e,t)}),r=n(t.lastIndexOf(o.domain()[1])),i=n(t.indexOf(o.domain()[0])),s=n(t.length-1);return[i,r,s].filter(function(e){return e!=null})});S.enter().append("circle"),S.exit().remove(),S.attr("cx",function(e,t){return s(u(e,e.pointIndex))}).attr("cy",function(e,t){return o(a(e,e.pointIndex))}).attr("r",2).attr("class",function(e,t){return u(e,e.pointIndex)==s.domain()[1]?"nv-point nv-currentValue":a(e,e.pointIndex)==o.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),d}var t={top:2,right:0,bottom:2,left:0},n=400,r=32,i=!0,s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=e.utils.getColor(["#000"]),l,c,h,p;return d.options=e.utils.optionsFunc.bind(d),d.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,d):t},d.width=function(e){return arguments.length?(n=e,d):n},d.height=function(e){return arguments.length?(r=e,d):r},d.x=function(e){return arguments.length?(u=d3.functor(e),d):u},d.y=function(e){return arguments.length?(a=d3.functor(e),d):a},d.xScale=function(e){return arguments.length?(s=e,d):s},d.yScale=function(e){return arguments.length?(o=e,d):o},d.xDomain=function(e){return arguments.length?(l=e,d):l},d.yDomain=function(e){return arguments.length?(c=e,d):c},d.xRange=function(e){return arguments.length?(h=e,d):h},d.yRange=function(e){return arguments.length?(p=e,d):p},d.animate=function(e){return arguments.length?(i=e,d):i},d.color=function(t){return arguments.length?(f=e.utils.getColor(t),d):f},d},e.models.sparklinePlus=function(){function v(e){return e.each(function(c){function O(){if(a)return;var e=C.selectAll(".nv-hoverValue").data(u),r=e.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);e.exit().style("stroke-opacity",0).style("fill-opacity",0).remove(),e.attr("transform",function(e){return"translate("+s(t.x()(c[e],e))+",0)"}).style("stroke-opacity",1).style("fill-opacity",1);if(!u.length)return;r.append("line").attr("x1",0).attr("y1",-n.top).attr("x2",0).attr("y2",b),r.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-n.top).attr("text-anchor","end").attr("dy",".9em"),C.select(".nv-hoverValue .nv-xValue").text(f(t.x()(c[u[0]],u[0]))),r.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-n.top).attr("text-anchor","start").attr("dy",".9em"),C.select(".nv-hoverValue .nv-yValue").text(l(t.y()(c[u[0]],u[0])))}function M(){function r(e,n){var r=Math.abs(t.x()(e[0],0)-n),i=0;for(var s=0;s<e.length;s++)Math.abs(t.x()(e[s],s)-n)<r&&(r=Math.abs(t.x()(e[s],s)-n),i=s);return i}if(a)return;var e=d3.mouse(this)[0]-n.left;u=[r(c,Math.round(s.invert(e)))],O()}var m=d3.select(this),g=(r||parseInt(m.style("width"))||960)-n.left-n.right,b=(i||parseInt(m.style("height"))||400)-n.top-n.bottom;v.update=function(){v(e)},v.container=this;if(!c||!c.length){var w=m.selectAll(".nv-noData").data([d]);return w.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),w.attr("x",n.left+g/2).attr("y",n.top+b/2).text(function(e){return e}),v}m.selectAll(".nv-noData").remove();var E=t.y()(c[c.length-1],c.length-1);s=t.xScale(),o=t.yScale();var S=m.selectAll("g.nv-wrap.nv-sparklineplus").data([c]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-sparklineWrap"),N.append("g").attr("class","nv-valueWrap"),N.append("g").attr("class","nv-hoverArea"),S.attr("transform","translate("+n.left+","+n.top+")");var k=C.select(".nv-sparklineWrap");t.width(g).height(b),k.call(t);var L=C.select(".nv-valueWrap"),A=L.selectAll(".nv-currentValue").data([E]);A.enter().append("text").attr("class","nv-currentValue").attr("dx",p?-8:8).attr("dy",".9em").style("text-anchor",p?"end":"start"),A.attr("x",g+(p?n.right:0)).attr("y",h?function(e){return o(e)}:0).style("fill",t.color()(c[c.length-1],c.length-1)).text(l(E)),N.select(".nv-hoverArea").append("rect").on("mousemove",M).on("click",function(){a=!a}).on("mouseout",function(){u=[],O()}),C.select(".nv-hoverArea rect").attr("transform",function(e){return"translate("+ -n.left+","+ -n.top+")"}).attr("width",g+n.left+n.right).attr("height",b+n.top)}),v}var t=e.models.sparkline(),n={top:15,right:100,bottom:10,left:50},r=null,i=null,s,o,u=[],a=!1,f=d3.format(",r"),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d="No Data Available.";return v.sparkline=t,d3.rebind(v,t,"x","y","xScale","yScale","color"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,v):n},v.width=function(e){return arguments.length?(r=e,v):r},v.height=function(e){return arguments.length?(i=e,v):i},v.xTickFormat=function(e){return arguments.length?(f=e,v):f},v.yTickFormat=function(e){return arguments.length?(l=e,v):l},v.showValue=function(e){return arguments.length?(c=e,v):c},v.alignValue=function(e){return arguments.length?(h=e,v):h},v.rightAlignValue=function(e){return arguments.length?(p=e,v):p},v.noData=function(e){return arguments.length?(d=e,v):d},v},e.models.stackedArea=function(){function g(e){return e.each(function(e){var a=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);p=v.xScale(),d=v.yScale();var E=e;e.forEach(function(e,t){e.seriesIndex=t,e.values=e.values.map(function(e,n){return e.index=n,e.seriesIndex=t,e})});var S=e.filter(function(e){return!e.disabled});e=d3.layout.stack().order(l).offset(f).values(function(e){return e.values}).x(o).y(u).out(function(e,t,n){var r=u(e)===0?0:n;e.display={y:r,y0:t}})(S);var T=w.selectAll("g.nv-wrap.nv-stackedarea").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),C=N.append("defs"),k=N.append("g"),L=T.select("g");k.append("g").attr("class","nv-areaWrap"),k.append("g").attr("class","nv-scatterWrap"),T.attr("transform","translate("+t.left+","+t.top+")"),v.width(a).height(b).x(o).y(function(e){return e.display.y+e.display.y0}).forceY([0]).color(e.map(function(e,t){return e.color||i(e,e.seriesIndex)}));var A=L.select(".nv-scatterWrap").datum(e);A.call(v),C.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),T.select("#nv-edge-clip-"+s+" rect").attr("width",a).attr("height",b),L.attr("clip-path",h?"url(#nv-edge-clip-"+s+")":"");var O=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y+e.display.y0)}).interpolate(c),M=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y0)}),_=L.select(".nv-areaWrap").selectAll("path.nv-area").data(function(e){return e});_.enter().append("path").attr("class",function(e,t){return"nv-area nv-area-"+t}).attr("d",function(e,t){return M(e.values,e.seriesIndex)}).on("mouseover",function(e,t){d3.select(this).classed("hover",!0),m.areaMouseover({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),m.areaMouseout({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("click",function(e,t){d3.select(this).classed("hover",!1),m.areaClick({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}),_.exit().remove(),_.style("fill",function(e,t){return e.color||i(e,e.seriesIndex)}).style("stroke",function(e,t){return e.color||i(e,e.seriesIndex)}),_.attr("d",function(e,t){return O(e.values,t)}),v.dispatch.on("elementMouseover.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!0)}),v.dispatch.on("elementMouseout.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!1)}),g.d3_stackedOffset_stackPercent=function(e){var t=e.length,n=e[0].length,r=1/t,i,s,o,a=[];for(s=0;s<n;++s){for(i=0,o=0;i<E.length;i++)o+=u(E[i].values[s]);if(o)for(i=0;i<t;i++)e[i][s][1]/=o;else for(i=0;i<t;i++)e[i][s][1]=r}for(s=0;s<n;++s)a[s]=0;return a}}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=function(e){return e.x},u=function(e){return e.y},a="stack",f="zero",l="default",c="linear",h=!1,p,d,v=e.models.scatter(),m=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout");return v.size(2.2).sizeDomain([2.2,2.2]),v.dispatch.on("elementClick.area",function(e){m.areaClick(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],m.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){m.tooltipHide(e)}),g.dispatch=m,g.scatter=v,d3.rebind(g,v,"interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","highlightPoint","clearHighlights"),g.options=e.utils.optionsFunc.bind(g),g.x=function(e){return arguments.length?(o=d3.functor(e),g):o},g.y=function(e){return arguments.length?(u=d3.functor(e),g):u},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.clipEdge=function(e){return arguments.length?(h=e,g):h},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),g):i},g.offset=function(e){return arguments.length?(f=e,g):f},g.order=function(e){return arguments.length?(l=e,g):l},g.style=function(e){if(!arguments.length)return a;a=e;switch(a){case"stack":g.offset("zero"),g.order("default");break;case"stream":g.offset("wiggle"),g.order("inside-out");break;case"stream-center":g.offset("silhouette"),g.order("inside-out");break;case"expand":g.offset("expand"),g.order("default");break;case"stack_percent":g.offset(g.d3_stackedOffset_stackPercent),g.order("default")}return g},g.interpolate=function(e){return arguments.length?(c=e,g):c},g},e.models.stackedAreaChart=function(){function M(y){return y.each(function(y){var A=d3.select(this),_=this,D=(a||parseInt(A.style("width"))||960)-u.left-u.right,P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom;M.update=function(){A.call(M)},M.container=this,S.disabled=y.map(function(e){return!!e.disabled});if(!x){var H;x={};for(H in S)S[H]instanceof Array?x[H]=S[H].slice(0):x[H]=S[H]}if(!y||!y.length||!y.filter(function(e){return e.values.length}).length){var B=A.selectAll(".nv-noData").data([T]);return B.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),B.attr("x",u.left+D/2).attr("y",u.top+P/2).text(function(e){return e}),M}A.selectAll(".nv-noData").remove(),b=t.xScale(),w=t.yScale();var j=A.selectAll("g.nv-wrap.nv-stackedAreaChart").data([y]),F=j.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),I=j.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-stackedWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-controlsWrap"),F.append("g").attr("class","nv-interactive"),I.select("rect").attr("width",D).attr("height",P);if(h){var q=c?D-C:D;i.width(q),I.select(".nv-legendWrap").datum(y).call(i),u.top!=i.height()&&(u.top=i.height(),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-legendWrap").attr("transform","translate("+(D-q)+","+ -u.top+")")}if(c){var R=[{key:L.stacked||"Stacked",metaKey:"Stacked",disabled:t.style()!="stack",style:"stack"},{key:L.stream||"Stream",metaKey:"Stream",disabled:t.style()!="stream",style:"stream"},{key:L.expanded||"Expanded",metaKey:"Expanded",disabled:t.style()!="expand",style:"expand"},{key:L.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:t.style()!="stack_percent",style:"stack_percent"}];C=k.length/3*260,R=R.filter(function(e){return k.indexOf(e.metaKey)!==-1}),s.width(C).color(["#444","#444","#444"]),I.select(".nv-controlsWrap").datum(R).call(s),u.top!=Math.max(s.height(),i.height())&&(u.top=Math.max(s.height(),i.height()),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-controlsWrap").attr("transform","translate(0,"+ -u.top+")")}j.attr("transform","translate("+u.left+","+u.top+")"),v&&I.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),m&&(o.width(D).height(P).margin({left:u.left,top:u.top}).svgContainer(A).xScale(b),j.select(".nv-interactive").call(o)),t.width(D).height(P);var U=I.select(".nv-stackedWrap").datum(y);U.call(t),p&&(n.scale(b).ticks(D/100).tickSize(-P,0),I.select(".nv-x.nv-axis").attr("transform","translate(0,"+P+")"),I.select(".nv-x.nv-axis").call(n)),d&&(r.scale(w).ticks(t.offset()=="wiggle"?0:P/36).tickSize(-D,0).setTickFormat(t.style()=="expand"||t.style()=="stack_percent"?d3.format("%"):E),I.select(".nv-y.nv-axis").call(r)),t.dispatch.on("areaClick.toggle",function(e){y.filter(function(e){return!e.disabled}).length===1?y.forEach(function(e){e.disabled=!1}):y.forEach(function(t,n){t.disabled=n!=e.seriesIndex}),S.disabled=y.map(function(e){return!!e.disabled}),N.stateChange(S),M.update()}),i.dispatch.on("stateChange",function(e){S.disabled=e.disabled,N.stateChange(S),M.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;R=R.map(function(e){return e.disabled=!0,e}),e.disabled=!1,t.style(e.style),S.style=t.style(),N.stateChange(S),M.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,a,f,c=[];y.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){a=e.interactiveBisect(n.values,i.pointXValue,M.x()),t.highlightPoint(r,a,!0);var o=n.values[a];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof f=="undefined"&&(f=M.xScale()(M.x()(o,a)));var u=t.style()=="expand"?o.display.y:M.y()(o,a);c.push({key:n.key,value:u,color:l(n,n.seriesIndex),stackedValue:o.display})}),c.reverse();if(c.length>2){var h=M.yScale().invert(i.mouseY),p=Infinity,d=null;c.forEach(function(e,t){h=Math.abs(h);var n=Math.abs(e.stackedValue.y0),r=Math.abs(e.stackedValue.y);if(h>=n&&h<=r+n){d=t;return}}),d!=null&&(c[d].highlight=!0)}var v=n.tickFormat()(M.x()(s,a)),m=t.style()=="expand"?function(e,t){return d3.format(".1%")(e)}:function(e,t){return r.tickFormat()(e)};o.tooltip.position({left:f+u.left,top:i.mouseY+u.top}).chartContainer(_.parentNode).enabled(g).valueFormatter(m).data({value:v,series:c})(),o.renderGuideLine(f)}),o.dispatch.on("elementMouseout",function(e){N.tooltipHide(),t.clearHighlights()}),N.on("tooltipShow",function(e){g&&O(e,_.parentNode)}),N.on("changeState",function(e){typeof e.disabled!="undefined"&&y.length===e.disabled.length&&(y.forEach(function(t,n){t.disabled=e.disabled[n]}),S.disabled=e.disabled),typeof e.style!="undefined"&&t.style(e.style),M.update()})}),M}var t=e.models.stackedArea(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:25,bottom:50,left:60},a=null,f=null,l=e.utils.defaultColor(),c=!0,h=!0,p=!0,d=!0,v=!1,m=!1,g=!0,y=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},b,w,E=d3.format(",.2f"),S={style:t.style()},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=250,k=["Stacked","Stream","Expanded"],L={},A=0;n.orient("bottom").tickPadding(7),r.orient(v?"right":"left"),s.updateState(!1);var O=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=y(i.series.key,a,f,i,M);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("tooltipShow",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],N.tooltipShow(e)}),t.dispatch.on("tooltipHide",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){g&&e.tooltip.cleanup()}),M.dispatch=N,M.stacked=t,M.legend=i,M.controls=s,M.xAxis=n,M.yAxis=r,M.interactiveLayer=o,d3.rebind(M,t,"x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","sizeDomain","interactive","useVoronoi","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),M.options=e.utils.optionsFunc.bind(M),M.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,M):u},M.width=function(e){return arguments.length?(a=e,M):a},M.height=function(e){return arguments.length?(f=e,M):f},M.color=function(n){return arguments.length?(l=e.utils.getColor(n),i.color(l),t.color(l),M):l},M.showControls=function(e){return arguments.length?(c=e,M):c},M.showLegend=function(e){return arguments.length?(h=e,M):h},M.showXAxis=function(e){return arguments.length?(p=e,M):p},M.showYAxis=function(e){return arguments.length?(d=e,M):d},M.rightAlignYAxis=function(e){return arguments.length?(v=e,r.orient(e?"right":"left"),M):v},M.useInteractiveGuideline=function(e){return arguments.length?(m=e,e===!0&&(M.interactive(!1),M.useVoronoi(!1)),M):m},M.tooltip=function(e){return arguments.length?(y=e,M):y},M.tooltips=function(e){return arguments.length?(g=e,M):g},M.tooltipContent=function(e){return arguments.length?(y=e,M):y},M.state=function(e){return arguments.length?(S=e,M):S},M.defaultState=function(e){return arguments.length?(x=e,M):x},M.noData=function(e){return arguments.length?(T=e,M):T},M.transitionDuration=function(e){return arguments.length?(A=e,M):A},M.controlsData=function(e){return arguments.length?(k=e,M):k},M.controlLabels=function(e){return arguments.length?typeof e!="object"?L:(L=e,M):L},r.setTickFormat=r.tickFormat,r.tickFormat=function(e){return arguments.length?(E=e,r):E},M}}(),define("plugin/plugins/nvd3/nv.d3",function(){}),define("plugin/charts/nvd3/common/config",["plugin/charts/forms/default","plugin/plugins/nvd3/nv.d3"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"NVD3",tag:"svg",keywords:"small"})}),define("plugin/charts/nvd3/bar/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/line_focus/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus",category:"Others",zoomable:"native",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/pie/config",["plugin/plugins/nvd3/nv.d3"],function(){return $.extend(!0,{},{title:"Pie chart",category:"Area charts",library:"NVD3",tag:"svg",keywords:"small",columns:{label:{title:"Labels",is_label:!0,is_auto:!0},y:{title:"Values",is_numeric:!0}},settings:{main_separator:{type:"separator",title:"Pie chart settings"},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{init:"true",hide:!0}}})}),define("plugin/charts/nvd3/stackedarea_full/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Expanded",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea_stream/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stream",category:"Area charts",zoomable:!0,keywords:"default small",showmaxmin:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/histogram/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogram",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{x_axis_label:{init:"Values"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_precision:{init:".2"}}})}),define("plugin/charts/nvd3/line/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/scatter/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/common/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"jqPlot",tag:"div",zoomable:!0,keywords:"medium",settings:{separator_grid:{title:"Grids",type:"separator"},x_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the X axis?",type:"radiobutton",init:"false",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]},y_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the Y axis?",type:"radiobutton",init:"true",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]}}})}),define("plugin/charts/jqplot/bar/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/line/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/scatter/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}},settings:{x_axis_grid:{init:"true"}}})}),define("plugin/charts/jqplot/boxplot/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Box plot",category:"Data processing (requires 'charts' tool from Toolshed)",library:"jqPlot",tag:"div",execute:"boxplot",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{show_legend:{init:"false"}}})}),define("plugin/charts/jqplot/histogram_discrete/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Discrete Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogramdiscrete",keywords:"small medium large",columns:{x:{title:"Observations",is_label:!0}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"}}})}),define("plugin/charts/others/heatmap/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"Heatmap",category:"Others",library:"Custom",tag:"svg",keywords:"small",zoomable:!0,columns:{x:{title:"Column labels",is_label:!0,is_numeric:!0,is_unique:!0},y:{title:"Row labels",is_label:!0,is_numeric:!0,is_unique:!0},z:{title:"Observation",is_numeric:!0}},settings:{use_panels:{init:"true",hide:!0},color_set:{title:"Color scheme",info:"Select a color scheme for your heatmap",type:"select",init:"jet",data:[{label:"Cold-to-Hot",value:"hot"},{label:"Cool",value:"cool"},{label:"Copper",value:"copper"},{label:"Gray scale",value:"gray"},{label:"Jet",value:"jet"},{label:"No-Green",value:"no_green"},{label:"Ocean",value:"ocean"},{label:"Polar",value:"polar"},{label:"Red-to-Green",value:"redgreen"},{label:"Red-to-green (saturated)",value:"red2green"},{label:"Relief",value:"relief"},{label:"Seismograph",value:"seis"},{label:"Sealand",value:"sealand"},{label:"Split",value:"split"},{label:"Wysiwyg",value:"wysiwyg"}]},url_template:{title:"Url template",info:"Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.",type:"text",init:"",placeholder:"http://someurl.com?id=__LABEL__"}}})}),define("plugin/charts/others/heatmap_cluster/config",["plugin/charts/others/heatmap/config"],function(e){return $.extend(!0,{},e,{title:"Clustered Heatmap",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"heatmap",keywords:"small medium large"})}),define("plugin/charts/types",["plugin/charts/nvd3/bar/config","plugin/charts/nvd3/bar_stacked/config","plugin/charts/nvd3/bar_horizontal/config","plugin/charts/nvd3/bar_horizontal_stacked/config","plugin/charts/nvd3/line_focus/config","plugin/charts/nvd3/pie/config","plugin/charts/nvd3/stackedarea_full/config","plugin/charts/nvd3/stackedarea_stream/config","plugin/charts/nvd3/histogram/config","plugin/charts/nvd3/line/config","plugin/charts/nvd3/scatter/config","plugin/charts/nvd3/stackedarea/config","plugin/charts/jqplot/bar/config","plugin/charts/jqplot/line/config","plugin/charts/jqplot/scatter/config","plugin/charts/jqplot/boxplot/config","plugin/charts/jqplot/histogram_discrete/config","plugin/charts/others/heatmap/config","plugin/charts/others/heatmap_cluster/config"],function(e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y){return Backbone.Model.extend({defaults:{nvd3_bar:e,nvd3_bar_stacked:t,nvd3_bar_horizontal:n,nvd3_bar_horizontal_stacked:r,nvd3_line_focus:i,nvd3_stackedarea:c,nvd3_stackedarea_full:o,nvd3_stackedarea_stream:u,nvd3_pie:s,nvd3_line:f,nvd3_scatter:l,nvd3_histogram:a,jqplot_bar:h,jqplot_histogram_discrete:m,jqplot_line:p,jqplot_scatter:d,jqplot_boxplot:v,others_heatmap:g,others_heatmap_cluster:y}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","utils/deferred","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c,h){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new l,this.types=new h,this.chart=new c,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.deferred=new u,this.viewer_view=new a(this),this.editor_view=new f(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el);if(!this.storage.load())this.go("editor");else{this.go("viewer");var n=this;this.deferred.execute(function(){n.chart.trigger("redraw")})}},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},chartPath:function(e){var t=e.split(/_(.+)/);return t.length>=2?t[0]+"/"+t[1]:(console.debug("FAILED App:chartPath() - Invalid format: "+e),undefined)}})});
\ No newline at end of file
+define("mvc/ui/ui-modal",[],function(){var e=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast"),this.options.closing_callback&&this.options.closing_callback()},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="ui-modal modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:e}}),function(){var e=this,t=e._,n=Array.prototype,r=Object.prototype,i=Function.prototype,s=n.push,o=n.slice,u=n.concat,a=r.toString,f=r.hasOwnProperty,l=Array.isArray,c=Object.keys,h=i.bind,p=function(e){if(e instanceof p)return e;if(!(this instanceof p))return new p(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=p),exports._=p):e._=p,p.VERSION="1.7.0";var d=function(e,t,n){if(t===void 0)return e;switch(n==null?3:n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)};case 4:return function(n,r,i,s){return e.call(t,n,r,i,s)}}return function(){return e.apply(t,arguments)}};p.iteratee=function(e,t,n){return e==null?p.identity:p.isFunction(e)?d(e,t,n):p.isObject(e)?p.matches(e):p.property(e)},p.each=p.forEach=function(e,t,n){if(e==null)return e;t=d(t,n);var r,i=e.length;if(i===+i)for(r=0;r<i;r++)t(e[r],r,e);else{var s=p.keys(e);for(r=0,i=s.length;r<i;r++)t(e[s[r]],s[r],e)}return e},p.map=p.collect=function(e,t,n){if(e==null)return[];t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s=Array(i),o;for(var u=0;u<i;u++)o=r?r[u]:u,s[u]=t(e[o],o,e);return s};var v="Reduce of empty array with no initial value";p.reduce=p.foldl=p.inject=function(e,t,n,r){e==null&&(e=[]),t=d(t,r,4);var i=e.length!==+e.length&&p.keys(e),s=(i||e).length,o=0,u;if(arguments.length<3){if(!s)throw new TypeError(v);n=e[i?i[o++]:o++]}for(;o<s;o++)u=i?i[o]:o,n=t(n,e[u],u,e);return n},p.reduceRight=p.foldr=function(e,t,n,r){e==null&&(e=[]),t=d(t,r,4);var i=e.length!==+e.length&&p.keys(e),s=(i||e).length,o;if(arguments.length<3){if(!s)throw new TypeError(v);n=e[i?i[--s]:--s]}while(s--)o=i?i[s]:s,n=t(n,e[o],o,e);return n},p.find=p.detect=function(e,t,n){var r;return t=p.iteratee(t,n),p.some(e,function(e,n,i){if(t(e,n,i))return r=e,!0}),r},p.filter=p.select=function(e,t,n){var r=[];return e==null?r:(t=p.iteratee(t,n),p.each(e,function(e,n,i){t(e,n,i)&&r.push(e)}),r)},p.reject=function(e,t,n){return p.filter(e,p.negate(p.iteratee(t)),n)},p.every=p.all=function(e,t,n){if(e==null)return!0;t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s,o;for(s=0;s<i;s++){o=r?r[s]:s;if(!t(e[o],o,e))return!1}return!0},p.some=p.any=function(e,t,n){if(e==null)return!1;t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s,o;for(s=0;s<i;s++){o=r?r[s]:s;if(t(e[o],o,e))return!0}return!1},p.contains=p.include=function(e,t){return e==null?!1:(e.length!==+e.length&&(e=p.values(e)),p.indexOf(e,t)>=0)},p.invoke=function(e,t){var n=o.call(arguments,2),r=p.isFunction(t);return p.map(e,function(e){return(r?t:e[t]).apply(e,n)})},p.pluck=function(e,t){return p.map(e,p.property(t))},p.where=function(e,t){return p.filter(e,p.matches(t))},p.findWhere=function(e,t){return p.find(e,p.matches(t))},p.max=function(e,t,n){var r=-Infinity,i=-Infinity,s,o;if(t==null&&e!=null){e=e.length===+e.length?e:p.values(e);for(var u=0,a=e.length;u<a;u++)s=e[u],s>r&&(r=s)}else t=p.iteratee(t,n),p.each(e,function(e,n,s){o=t(e,n,s);if(o>i||o===-Infinity&&r===-Infinity)r=e,i=o});return r},p.min=function(e,t,n){var r=Infinity,i=Infinity,s,o;if(t==null&&e!=null){e=e.length===+e.length?e:p.values(e);for(var u=0,a=e.length;u<a;u++)s=e[u],s<r&&(r=s)}else t=p.iteratee(t,n),p.each(e,function(e,n,s){o=t(e,n,s);if(o<i||o===Infinity&&r===Infinity)r=e,i=o});return r},p.shuffle=function(e){var t=e&&e.length===+e.length?e:p.values(e),n=t.length,r=Array(n);for(var i=0,s;i<n;i++)s=p.random(0,i),s!==i&&(r[i]=r[s]),r[s]=t[i];return r},p.sample=function(e,t,n){return t==null||n?(e.length!==+e.length&&(e=p.values(e)),e[p.random(e.length-1)]):p.shuffle(e).slice(0,Math.max(0,t))},p.sortBy=function(e,t,n){return t=p.iteratee(t,n),p.pluck(p.map(e,function(e,n,r){return{value:e,index:n,criteria:t(e,n,r)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index-t.index}),"value")};var m=function(e){return function(t,n,r){var i={};return n=p.iteratee(n,r),p.each(t,function(r,s){var o=n(r,s,t);e(i,r,o)}),i}};p.groupBy=m(function(e,t,n){p.has(e,n)?e[n].push(t):e[n]=[t]}),p.indexBy=m(function(e,t,n){e[n]=t}),p.countBy=m(function(e,t,n){p.has(e,n)?e[n]++:e[n]=1}),p.sortedIndex=function(e,t,n,r){n=p.iteratee(n,r,1);var i=n(t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n(e[u])<i?s=u+1:o=u}return s},p.toArray=function(e){return e?p.isArray(e)?o.call(e):e.length===+e.length?p.map(e,p.identity):p.values(e):[]},p.size=function(e){return e==null?0:e.length===+e.length?e.length:p.keys(e).length},p.partition=function(e,t,n){t=p.iteratee(t,n);var r=[],i=[];return p.each(e,function(e,n,s){(t(e,n,s)?r:i).push(e)}),[r,i]},p.first=p.head=p.take=function(e,t,n){return e==null?void 0:t==null||n?e[0]:t<0?[]:o.call(e,0,t)},p.initial=function(e,t,n){return o.call(e,0,Math.max(0,e.length-(t==null||n?1:t)))},p.last=function(e,t,n){return e==null?void 0:t==null||n?e[e.length-1]:o.call(e,Math.max(e.length-t,0))},p.rest=p.tail=p.drop=function(e,t,n){return o.call(e,t==null||n?1:t)},p.compact=function(e){return p.filter(e,p.identity)};var g=function(e,t,n,r){if(t&&p.every(e,p.isArray))return u.apply(r,e);for(var i=0,o=e.length;i<o;i++){var a=e[i];!p.isArray(a)&&!p.isArguments(a)?n||r.push(a):t?s.apply(r,a):g(a,t,n,r)}return r};p.flatten=function(e,t){return g(e,t,!1,[])},p.without=function(e){return p.difference(e,o.call(arguments,1))},p.uniq=p.unique=function(e,t,n,r){if(e==null)return[];p.isBoolean(t)||(r=n,n=t,t=!1),n!=null&&(n=p.iteratee(n,r));var i=[],s=[];for(var o=0,u=e.length;o<u;o++){var a=e[o];if(t)(!o||s!==a)&&i.push(a),s=a;else if(n){var f=n(a,o,e);p.indexOf(s,f)<0&&(s.push(f),i.push(a))}else p.indexOf(i,a)<0&&i.push(a)}return i},p.union=function(){return p.uniq(g(arguments,!0,!0,[]))},p.intersection=function(e){if(e==null)return[];var t=[],n=arguments.length;for(var r=0,i=e.length;r<i;r++){var s=e[r];if(p.contains(t,s))continue;for(var o=1;o<n;o++)if(!p.contains(arguments[o],s))break;o===n&&t.push(s)}return t},p.difference=function(e){var t=g(o.call(arguments,1),!0,!0,[]);return p.filter(e,function(e){return!p.contains(t,e)})},p.zip=function(e){if(e==null)return[];var t=p.max(arguments,"length").length,n=Array(t);for(var r=0;r<t;r++)n[r]=p.pluck(arguments,r);return n},p.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},p.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=p.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}for(;r<i;r++)if(e[r]===t)return r;return-1},p.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=e.length;typeof n=="number"&&(r=n<0?r+n+1:Math.min(r,n+1));while(--r>=0)if(e[r]===t)return r;return-1},p.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=n||1;var r=Math.max(Math.ceil((t-e)/n),0),i=Array(r);for(var s=0;s<r;s++,e+=n)i[s]=e;return i};var y=function(){};p.bind=function(e,t){var n,r;if(h&&e.bind===h)return h.apply(e,o.call(arguments,1));if(!p.isFunction(e))throw new TypeError("Bind must be called on a function");return n=o.call(arguments,2),r=function(){if(this instanceof r){y.prototype=e.prototype;var i=new y;y.prototype=null;var s=e.apply(i,n.concat(o.call(arguments)));return p.isObject(s)?s:i}return e.apply(t,n.concat(o.call(arguments)))},r},p.partial=function(e){var t=o.call(arguments,1);return function(){var n=0,r=t.slice();for(var i=0,s=r.length;i<s;i++)r[i]===p&&(r[i]=arguments[n++]);while(n<arguments.length)r.push(arguments[n++]);return e.apply(this,r)}},p.bindAll=function(e){var t,n=arguments.length,r;if(n<=1)throw new Error("bindAll must be passed function names");for(t=1;t<n;t++)r=arguments[t],e[r]=p.bind(e[r],e);return e},p.memoize=function(e,t){var n=function(r){var i=n.cache,s=t?t.apply(this,arguments):r;return p.has(i,s)||(i[s]=e.apply(this,arguments)),i[s]};return n.cache={},n},p.delay=function(e,t){var n=o.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},p.defer=function(e){return p.delay.apply(p,[e,1].concat(o.call(arguments,1)))},p.throttle=function(e,t,n){var r,i,s,o=null,u=0;n||(n={});var a=function(){u=n.leading===!1?0:p.now(),o=null,s=e.apply(r,i),o||(r=i=null)};return function(){var f=p.now();!u&&n.leading===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0||l>t?(clearTimeout(o),o=null,u=f,s=e.apply(r,i),o||(r=i=null)):!o&&n.trailing!==!1&&(o=setTimeout(a,l)),s}},p.debounce=function(e,t,n){var r,i,s,o,u,a=function(){var f=p.now()-o;f<t&&f>0?r=setTimeout(a,t-f):(r=null,n||(u=e.apply(s,i),r||(s=i=null)))};return function(){s=this,i=arguments,o=p.now();var f=n&&!r;return r||(r=setTimeout(a,t)),f&&(u=e.apply(s,i),s=i=null),u}},p.wrap=function(e,t){return p.partial(t,e)},p.negate=function(e){return function(){return!e.apply(this,arguments)}},p.compose=function(){var e=arguments,t=e.length-1;return function(){var n=t,r=e[t].apply(this,arguments);while(n--)r=e[n].call(this,r);return r}},p.after=function(e,t){return function(){if(--e<1)return t.apply(this,arguments)}},p.before=function(e,t){var n;return function(){return--e>0?n=t.apply(this,arguments):t=null,n}},p.once=p.partial(p.before,2),p.keys=function(e){if(!p.isObject(e))return[];if(c)return c(e);var t=[];for(var n in e)p.has(e,n)&&t.push(n);return t},p.values=function(e){var t=p.keys(e),n=t.length,r=Array(n);for(var i=0;i<n;i++)r[i]=e[t[i]];return r},p.pairs=function(e){var t=p.keys(e),n=t.length,r=Array(n);for(var i=0;i<n;i++)r[i]=[t[i],e[t[i]]];return r},p.invert=function(e){var t={},n=p.keys(e);for(var r=0,i=n.length;r<i;r++)t[e[n[r]]]=n[r];return t},p.functions=p.methods=function(e){var t=[];for(var n in e)p.isFunction(e[n])&&t.push(n);return t.sort()},p.extend=function(e){if(!p.isObject(e))return e;var t,n;for(var r=1,i=arguments.length;r<i;r++){t=arguments[r];for(n in t)f.call(t,n)&&(e[n]=t[n])}return e},p.pick=function(e,t,n){var r={},i;if(e==null)return r;if(p.isFunction(t)){t=d(t,n);for(i in e){var s=e[i];t(s,i,e)&&(r[i]=s)}}else{var a=u.apply([],o.call(arguments,1));e=new Object(e);for(var f=0,l=a.length;f<l;f++)i=a[f],i in e&&(r[i]=e[i])}return r},p.omit=function(e,t,n){if(p.isFunction(t))t=p.negate(t);else{var r=p.map(u.apply([],o.call(arguments,1)),String);t=function(e,t){return!p.contains(r,t)}}return p.pick(e,t,n)},p.defaults=function(e){if(!p.isObject(e))return e;for(var t=1,n=arguments.length;t<n;t++){var r=arguments[t];for(var i in r)e[i]===void 0&&(e[i]=r[i])}return e},p.clone=function(e){return p.isObject(e)?p.isArray(e)?e.slice():p.extend({},e):e},p.tap=function(e,t){return t(e),e};var b=function(e,t,n,r){if(e===t)return e!==0||1/e===1/t;if(e==null||t==null)return e===t;e instanceof p&&(e=e._wrapped),t instanceof p&&(t=t._wrapped);var i=a.call(e);if(i!==a.call(t))return!1;switch(i){case"[object RegExp]":case"[object String]":return""+e==""+t;case"[object Number]":if(+e!==+e)return+t!==+t;return+e===0?1/+e===1/t:+e===+t;case"[object Date]":case"[object Boolean]":return+e===+t}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]===e)return r[s]===t;var o=e.constructor,u=t.constructor;if(o!==u&&"constructor"in e&&"constructor"in t&&!(p.isFunction(o)&&o instanceof o&&p.isFunction(u)&&u instanceof u))return!1;n.push(e),r.push(t);var f,l;if(i==="[object Array]"){f=e.length,l=f===t.length;if(l)while(f--)if(!(l=b(e[f],t[f],n,r)))break}else{var c=p.keys(e),h;f=c.length,l=p.keys(t).length===f;if(l)while(f--){h=c[f];if(!(l=p.has(t,h)&&b(e[h],t[h],n,r)))break}}return n.pop(),r.pop(),l};p.isEqual=function(e,t){return b(e,t,[],[])},p.isEmpty=function(e){if(e==null)return!0;if(p.isArray(e)||p.isString(e)||p.isArguments(e))return e.length===0;for(var t in e)if(p.has(e,t))return!1;return!0},p.isElement=function(e){return!!e&&e.nodeType===1},p.isArray=l||function(e){return a.call(e)==="[object Array]"},p.isObject=function(e){var t=typeof e;return t==="function"||t==="object"&&!!e},p.each(["Arguments","Function","String","Number","Date","RegExp"],function(e){p["is"+e]=function(t){return a.call(t)==="[object "+e+"]"}}),p.isArguments(arguments)||(p.isArguments=function(e){return p.has(e,"callee")}),typeof /./!="function"&&(p.isFunction=function(e){return typeof e=="function"||!1}),p.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},p.isNaN=function(e){return p.isNumber(e)&&e!==+e},p.isBoolean=function(e){return e===!0||e===!1||a.call(e)==="[object Boolean]"},p.isNull=function(e){return e===null},p.isUndefined=function(e){return e===void 0},p.has=function(e,t){return e!=null&&f.call(e,t)},p.noConflict=function(){return e._=t,this},p.identity=function(e){return e},p.constant=function(e){return function(){return e}},p.noop=function(){},p.property=function(e){return function(t){return t[e]}},p.matches=function(e){var t=p.pairs(e),n=t.length;return function(e){if(e==null)return!n;e=new Object(e);for(var r=0;r<n;r++){var i=t[r],s=i[0];if(i[1]!==e[s]||!(s in e))return!1}return!0}},p.times=function(e,t,n){var r=Array(Math.max(0,e));t=d(t,n,1);for(var i=0;i<e;i++)r[i]=t(i);return r},p.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))},p.now=Date.now||function(){return(new Date).getTime()};var w={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},E=p.invert(w),S=function(e){var t=function(t){return e[t]},n="(?:"+p.keys(e).join("|")+")",r=RegExp(n),i=RegExp(n,"g");return function(e){return e=e==null?"":""+e,r.test(e)?e.replace(i,t):e}};p.escape=S(w),p.unescape=S(E),p.result=function(e,t){if(e==null)return void 0;var n=e[t];return p.isFunction(n)?e[t]():n};var x=0;p.uniqueId=function(e){var t=++x+"";return e?e+t:t},p.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,N={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},C=/\\|'|\r|\n|\u2028|\u2029/g,k=function(e){return"\\"+N[e]};p.template=function(e,t,n){!t&&n&&(t=n),t=p.defaults({},t,p.templateSettings);var r=RegExp([(t.escape||T).source,(t.interpolate||T).source,(t.evaluate||T).source].join("|")+"|$","g"),i=0,s="__p+='";e.replace(r,function(t,n,r,o,u){return s+=e.slice(i,u).replace(C,k),i=u+t.length,n?s+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?s+="'+\n((__t=("+r+"))==null?'':__t)+\n'":o&&(s+="';\n"+o+"\n__p+='"),t}),s+="';\n",t.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n";try{var o=new Function(t.variable||"obj","_",s)}catch(u){throw u.source=s,u}var a=function(e){return o.call(this,e,p)},f=t.variable||"obj";return a.source="function("+f+"){\n"+s+"}",a},p.chain=function(e){var t=p(e);return t._chain=!0,t};var L=function(e){return this._chain?p(e).chain():e};p.mixin=function(e){p.each(p.functions(e),function(t){var n=p[t]=e[t];p.prototype[t]=function(){var e=[this._wrapped];return s.apply(e,arguments),L.call(this,n.apply(p,e))}})},p.mixin(p),p.each(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=n[e];p.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e==="shift"||e==="splice")&&n.length===0&&delete n[0],L.call(this,n)}}),p.each(["concat","join","slice"],function(e){var t=n[e];p.prototype[e]=function(){return L.call(this,t.apply(this._wrapped,arguments))}}),p.prototype.value=function(){return this._wrapped},typeof define=="function"&&define.amd&&define("underscore",[],function(){return p})}.call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e,n){for(var r in e){var i=e[r];i&&typeof i=="object"&&(n(i),t(i,n))}}function n(e){return $("<div/>").text(e).html()}function r(e){e instanceof Array||(e=[e]);for(var t in e)if(["None",null,"null",undefined,"undefined"].indexOf(e[t])>-1)return!1;return!0}function i(e){var e=e.toString();if(e){e=e.replace(/,/g,", ");var t=e.lastIndexOf(", ");return t!=-1&&(e=e.substr(0,t)+" or "+e.substr(t+1)),e}return""}function s(e){top.__utils__get__=top.__utils__get__||{},e.cache&&top.__utils__get__[e.url]?(e.success&&e.success(top.__utils__get__[e.url]),console.debug("utils.js::get() - Fetching from cache ["+e.url+"].")):o({url:e.url,data:e.data,success:function(t){top.__utils__get__[e.url]=t,e.success&&e.success(t)},error:function(t){e.error&&e.error(t)}})}function o(e){var t={contentType:"application/json",type:e.type||"GET",data:e.data||{},url:e.url};t.type=="GET"||t.type=="DELETE"?(t.url.indexOf("?")==-1?t.url+="?":t.url+="&",t.url=t.url+$.param(t.data),t.data=null):(t.dataType="json",t.url=t.url,t.data=JSON.stringify(t.data)),$.ajax(t).done(function(t){if(typeof t=="string")try{t=t.replace("Infinity,",'"Infinity",'),t=jQuery.parseJSON(t)}catch(n){console.debug(n)}e.success&&e.success(t)}).fail(function(t){var n=null;try{n=jQuery.parseJSON(t.responseText)}catch(r){n=t.responseText}e.error&&e.error(n,t)})}function u(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function a(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function f(t,n){return t?e.defaults(t,n):n}function l(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function c(){return"x"+Math.random().toString(36).substring(2,9)}function h(e){var t=$("<p></p>");return t.append(e),t}function p(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:a,cssGetAttribute:u,get:s,merge:f,bytesToString:l,uuid:c,time:p,wrap:h,request:o,sanitize:n,textify:i,validate:r,deepeach:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,scrollable:!0,nopadding:!1,operations:null,placement:"bottom",cls:"ui-portlet",operations_flt:"right"},$title:null,$content:null,$buttons:null,$operations:null,$header:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find(".content"),this.$title=this.$el.find(".portlet-title-text"),this.$header=this.$el.find(".portlet-header");var n=this.$el.find(".portlet-content");this.options.scrollable?n.addClass("scroll"):this.options.title?n.addClass("no-scroll"):n.addClass("no-scroll-no-title"),this.options.nopadding&&(n.css("padding","0px"),this.$content.css("padding","0px")),this.$buttons=$(this.el).find(".buttons");if(this.options.buttons){var r=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),r.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find(".operations");if(this.options.operations){var r=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t,n){n?this.$content.append(t):this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div id="'+e.id+'" class="'+e.cls+'">';return e.title&&(t+='<div class="portlet-header"><div class="operations" style="float: '+e.operations_flt+';"></div>'+'<div class="portlet-title">',e.icon&&(t+='<i class="icon fa '+e.icon+'"> </i>'),t+='<span class="portlet-title-text">'+e.title+"</span>"+"</div>"+"</div>"),t+='<div class="portlet-content">',e.placement=="top"&&(t+='<div class="buttons"></div>'),t+='<div class="content"></div>',e.placement=="bottom"&&(t+='<div class="buttons"></div>'),t+="</div></div>",t}});return{View:t}}),define("mvc/ui/ui-select-default",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",error_text:"No data available",visible:!0,wait:!1,multiple:!1,searchable:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find(".select"),this.$icon=this.$el.find(".icon"),this.$button=this.$el.find(".button"),this.options.multiple?(this.$select.prop("multiple",!0),this.$select.addClass("ui-select-multiple"),this.$icon.remove()):this.$el.addClass("ui-select"),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value),this.options.visible||this.hide(),this.options.wait?this.wait():this.show();var n=this;this.$select.on("change",function(){n._change()}),this.on("change",function(){n._change()})},value:function(e){return e!==undefined&&(this.$select.val(e),this.$select.select2&&this.$select.select2("val",e)),this.$select.val()},first:function(){var e=this.$select.find("option");return e.length>0?e.val():undefined},validate:function(){return e.validate(this.value())},text:function(){return this.$select.find("option:selected").text()},show:function(){this.unwait(),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin")},unwait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down")},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){var t=this.$select.val();this.$select.find("option").remove();for(var n in e)this.$select.append(this._templateOption(e[n]));this._refresh(),this.$select.val(t),this.$select.val()||this.$select.val(this.first()),this.options.searchable&&(this.$button.hide(),this.$select.select2("destroy"),this.$select.select2())},setOnChange:function(e){this.options.onchange=e},exists:function(e){return this.$select.find('option[value="'+e+'"]').length>0},_change:function(){this.options.onchange&&this.options.onchange(this.$select.val())},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.disable(),this.$select.append(this._templateOption({value:"null",label:this.options.error_text}))):this.enable()},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){return'<div id="'+e.id+'">'+'<select id="select" class="select '+e.cls+" "+e.id+'"></select>'+'<div class="button">'+'<i class="icon"/>'+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-slider",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{min:null,max:null,step:null,precise:!1,split:1e4},initialize:function(t){var n=this;this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.useslider=this.options.max!==null&&this.options.min!==null&&this.options.max>this.options.min,this.options.step===null&&(this.options.step=1,this.options.precise&&this.useslider&&(this.options.step=(this.options.max-this.options.min)/this.options.split)),this.useslider?(this.$slider=this.$el.find("#slider"),this.$slider.slider(this.options),this.$slider.on("slide",function(e,t){n.value(t.value)})):this.$el.find(".ui-form-slider-text").css("width","100%"),this.$text=this.$el.find("#text"),this.options.value!==undefined&&this.value(this.options.value),this.$text.on("change",function(){n.value($(this).val())});var r=[];this.$text.on("keyup",function(e){r[e.which]=!1}),this.$text.on("keydown",function(e){var t=e.which;r[t]=!0,t==8||t==9||t==13||t==37||t==39||t>=48&&t<=57||t==190&&$(this).val().indexOf(".")==-1&&n.options.precise||t==189&&$(this).val().indexOf("-")==-1||r[91]||r[17]||event.preventDefault()})},value:function(e){return e!==undefined&&(isNaN(e)&&(e=0),this.options.max!==null&&(e=Math.min(e,this.options.max)),this.options.min!==null&&(e=Math.max(e,this.options.min)),this.options.onchange&&this.options.onchange(e),this.$slider&&this.$slider.slider("value",e),this.$text.val(e)),this.$text.val()},_template:function(e){return'<div id="'+e.id+'" class="ui-form-slider">'+'<input id="text" type="text" class="ui-form-slider-text"/>'+'<div id="slider" class="ui-form-slider-element"/>'+"</div>"}});return{View:t}}),define("mvc/ui/ui-options",["utils/utils"],function(e){var t=Backbone.View.extend({initialize:function(t){this.optionsDefault={visible:!0,data:[],id:e.uuid(),error_text:"No data available.",wait_text:"Please wait..."},this.options=e.merge(t,this.optionsDefault),this.setElement("<div/>"),this.$message=$("<div/>"),this.$options=$(this._template(t)),this.$el.append(this.$message),this.$el.append(this.$options),this.options.visible||this.$el.hide(),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value);var n=this;this.on("change",function(){n._change()})},update:function(e){var t=this._getValue();this.$options.empty();if(this._templateOptions)this.$options.append(this._templateOptions(e));else for(var n in e){var r=$(this._templateOption(e[n]));r.addClass("ui-option"),this.$options.append(r)}var i=this;this.$el.find("input").on("change",function(){i.value(i._getValue()),i._change()}),this._refresh(),this.value(t)},value:function(e){if(e!==undefined){e instanceof Array||(e=[e]),this.$el.find("input").prop("checked",!1);for(var t in e)this.$el.find('input[value="'+e[t]+'"]').first().prop("checked",!0)}return this._getValue()},exists:function(e){if(e!==undefined){e instanceof Array||(e=[e]);for(var t in e)if(this.$el.find('input[value="'+e[t]+'"]').length>0)return!0}return!1},first:function(){var e=this.$el.find("input");return e.length>0?e.val():undefined},validate:function(){return e.validate(this.value())},wait:function(){this._size()==0&&(this._messageShow(this.options.wait_text,"info"),this.$options.hide())},unwait:function(){this._messageHide(),this._refresh()},_change:function(){this.options.onchange&&this.options.onchange(this._getValue())},_refresh:function(){this._size()==0?(this._messageShow(this.options.error_text,"danger"),this.$options.hide()):(this._messageHide(),this.$options.css("display","inline-block"))},_getValue:function(){var e=this.$el.find(":checked");if(e.length==0)return"null";if(this.options.multiple){var t=[];return e.each(function(){t.push($(this).val())}),t}return e.val()},_size:function(){return this.$el.find(".ui-option").length},_messageShow:function(e,t){this.$message.show(),this.$message.removeClass(),this.$message.addClass("ui-message alert alert-"+t),this.$message.html(e)},_messageHide:function(){this.$message.hide()},_template:function(){return'<div class="ui-options"/>'}}),n={};n.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="radio" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var r={};r.View=t.extend({initialize:function(e){e.multiple=!0,t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="checkbox" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var i={};return i.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},value:function(e){return e!==undefined&&(this.$el.find("input").prop("checked",!1),this.$el.find("label").removeClass("active"),this.$el.find('[value="'+e+'"]').prop("checked",!0).closest("label").addClass("active")),this._getValue()},_templateOption:function(e){var t='<label class="btn btn-default">';return e.icon&&(t+='<i class="fa '+e.icon+'"/>'),t+='<input type="radio" name="'+this.options.id+'" value="'+e.value+'">'+e.label+"</label>",t},_template:function(){return'<div class="btn-group ui-radiobutton" data-toggle="buttons"/>'}}),{Base:t,Radio:n,RadioButton:i,Checkbox:r}}),define("mvc/ui/ui-drilldown",["utils/utils","mvc/ui/ui-options"],function(e,t){var n=t.Base.extend({initialize:function(e){this.display=e.display||"checkbox",e.multiple=this.display=="checkbox",t.Base.prototype.initialize.call(this,e)},_templateOption:function(e,t,n){return'<div><input name="'+this.options.id+'" class="ui-option" type="'+this.display+'" value="'+t+'">'+e+"<div/>"},_templateOptions:function(e){function n(e,t){function n(n){n?(t.fadeIn("fast"),e.removeClass("toggle-expand"),e.addClass("toggle"),e.is_expanded=!0):(t.hide(),e.removeClass("toggle"),e.addClass("toggle-expand"),e.is_expanded=!1)}e.on("click",function(){n(!e.is_expanded)})}function r(e,s){for(i in s){var o=s[i],u=o.options.length>0,a=$("<div/>");if(u){var f=$('<span class="ui-drilldown-button form-toggle icon-button toggle-expand" style="position: relative; top: 2px;"/>'),l=$("<div/>");l.append(f),l.append(t._templateOption(o.name,o.value)),a.append(l);var c=$('<div style="display: none; margin-left: 25px;"/>');r(c,o.options),a.append(c),n(f,c)}else a.append(t._templateOption(o.name,o.value));e.append(a)}}var t=this,s=$("<div/>");return r(s,e),s},_template:function(e){return'<div class="ui-options drilldown-container" id="'+e.id+'"/>'}});return{View:n}}),define("mvc/ui/ui-button-menu",["utils/utils"],function(e){return Backbone.View.extend({optionsDefault:{id:"",title:"",floating:"right",icon:null,onclick:null,cls:"ui-button-icon ui-button-menu",tooltip:"",target:"",href:"",onunload:null,visible:!0,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){$(".tooltip").hide(),e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide(),n.tooltip({title:t.tooltip,placement:"bottom"})},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null,cls:"button-menu btn-group"};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a class="dropdown-item" href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t="",n="";e.title?t="width: auto;":n="margin: 0px;";var r='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="dropdown '+e.cls+'">'+'<div class="root button dropdown-toggle" data-toggle="dropdown" style="'+n+'">'+'<i class="icon fa '+e.icon+'"/>';return e.title&&(r+=' <span class="title">'+e.title+"</span>"),r+="</div></div>",r}})}),define("mvc/ui/ui-misc",["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(e,t,n,r,i,s,o){var u=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},_template:function(e){return'<img class="ui-image '+e.cls+'" src="'+e.url+'"/>'}}),a=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<label class="ui-label '+e.cls+'">'+e.title+"</label>"},value:function(){return options.title}}),f=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" class="ui-icon"/> '+e.title+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="float: '+e.floating+';" type="button" class="'+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),c=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$button=this.$el.find(".button");var n=this;$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&!n.disabled&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled"),this.disabled=!0},enable:function(){this.$button.removeClass("disabled"),this.disabled=!1},setIcon:function(e){this.$("i").removeClass(this.options.icon).addClass(e),this.options.icon=e},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div class="button"><i class="icon fa '+e.icon+'"/> '+'<span class="title">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),h=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)" class="ui-anchor '+e.cls+'">'+e.title+"</a></div>"}}),p=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>"),this.options.message&&this.update(this.options)},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.find(".alert").append(t.message),this.$el.fadeIn(),this.timeout&&window.clearTimeout(this.timeout);if(!t.persistent){var n=this;this.timeout=window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="ui-message alert alert-'+e.status+'"/>'}}),d=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),v=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:!1,visible:!0,cls:"",area:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.$el.on("input",function(){n.options.onchange&&n.options.onchange(n.$el.val())})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return e.area?'<textarea id="'+e.id+'" class="ui-textarea '+e.cls+'"></textarea>':'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="ui-input '+e.cls+'">'}}),m=Backbone.View.extend({initialize:function(e){this.options=e,this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value)},value:function(e){return e!==undefined&&this.$("hidden").val(e),this.$("hidden").val()},_template:function(e){var t='<div id="'+e.id+'" >';return e.info&&(t+="<label>"+e.info+"</label>"),t+='<hidden value="'+e.value+'"/>'+"</div>",t}});return{Anchor:h,Button:l,ButtonIcon:c,ButtonMenu:s,Icon:f,Image:u,Input:v,Label:a,Message:p,Modal:o,RadioButton:r.RadioButton,Checkbox:r.Checkbox,Radio:r.Radio,Searchbox:d,Select:t,Hidden:m,Slider:n,Drilldown:i}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e,t,n,r,i){var s=this;e.state("wait","Requesting job results...");var o=e.get("dataset_id_job");o!=""?s._wait(e,r,i):s._submit(e,t,n,r,i)},cleanup:function(t){var n=this,r=t.get("dataset_id_job");r!=""&&(e.request({type:"PUT",url:config.root+"api/histories/none/contents/"+r,data:{deleted:!0},success:function(){n._refreshHdas()}}),t.set("dataset_id_job",""))},_submit:function(t,n,r,i,s){var o=this,u=t.id,a=t.get("type"),f=t.definition;data={tool_id:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,columns:r,settings:n}},t.state("wait","Sending job request..."),e.request({type:"POST",url:config.root+"api/tools",data:data,success:function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response."),s&&s();else{o._refreshHdas();var n=e.outputs[0];t.state("wait","Your job has been queued. You may close the browser window. The job will run in the background."),t.set("dataset_id_job",n.id),o.app.storage.save(),o._wait(t,i,s)}},error:function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the 'charts' tool. Please make sure it is installed. "+n),s&&s()}})},_wait:function(t,n,r){var i=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.get("dataset_id_job"),data:{},success:function(e){var s=!1;switch(e.state){case"ok":t.state("wait","Job completed successfully..."),n&&n(e),s=!0;break;case"error":t.state("failed","Job has failed. Please check the history for details."),r&&r(e),s=!0;break;case"running":t.state("wait","Your job is running. You may close the browser window. The job will continue in the background.")}s||setTimeout(function(){i._wait(t,n,r)},i.app.config.get("query_timeout"))}})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshContents()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e){e.groups?this._get_blocks(e):this._get_dataset(e.id,e.success,e.error)},_get_blocks:function(e){function c(i){l._get(i,function(){var s=!1;for(var o in e.groups){destination_group=e.groups[o],source_group=i.groups[o],destination_group.values||(destination_group.values=[]),destination_group.values=destination_group.values.concat(source_group.values);if(source_group.values.length==0){s=!0;break}}if(++f<u&&!s){n&&n(parseInt(f/u*100));var l=i.start+r;i=$.extend(!0,a,{start:l}),c(i)}else t()})}var t=e.success,n=e.progress,r=this.app.config.get("query_limit"),i=e.start||0,s=i+e.query_limit||i+this.app.config.get("query_limit"),o=Math.abs(s-i);if(o<=0){console.debug("FAILED - Datasets::request() - Invalid query range.");return}var u=Math.ceil(o/r)||1,a=$.extend(!0,{},e),f=0,l=this,h=$.extend(!0,a,{start:i});this._get_dataset(e.id,function(){c(h)})},_get_dataset:function(t,n,r){var i=this.list[t];if(i){n(i);return}var s=this;e.request({type:"GET",url:config.root+"api/datasets/"+t,success:function(e){switch(e.state){case"error":r&&r(e);break;default:s.list[t]=e,n(e)}}})},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.start+this.app.config.get("query_limit")+"_"+t},_get:function(e,t){e.start=e.start||0;var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f]||a==="auto"||a==="zero")continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){var t=e.start;console.debug("Datasets::_fill_from_cache() - Filling request from cache at "+t+".");var n=0;for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s],u=this._block_id(e,o.index),a=this.cache[u];a&&(n=Math.max(n,a.length))}}n==0&&console.debug("Datasets::_fill_from_cache() - Reached data range limit.");for(var r in e.groups){var i=e.groups[r];i.values=[];for(var f=0;f<n;f++)i.values[f]={x:parseInt(f)+t}}for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s];switch(o.index){case"auto":for(var f=0;f<n;f++){var l=i.values[f];l[s]=parseInt(f)+t}break;case"zero":for(var f=0;f<n;f++){var l=i.values[f];l[s]=0}break;default:var u=this._block_id(e,o.index),a=this.cache[u];for(var f=0;f<n;f++){var l=i.values[f],c=a[f];isNaN(c)&&!o.is_label&&(c=0),l[s]=c}}}}},_fetch:function(t,n){var r=t.start?t.start:0,i=this.app.config.get("query_limit"),s=0;t.columns&&(s=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+s+" column(s) at "+r+".")),s==0&&console.debug("Datasets::_fetch() - No columns requested");var o="";for(var u in t.columns)o+=t.columns[u]+",";o=o.substring(0,o.length-1);var a=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.dataset_id,data:{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},success:function(e){var t=new Array(s);for(var r=0;r<s;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var o in i){var u=i[o];u!==undefined&&u!=2147483647&&t[o].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)}})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})}),define("plugin/models/chart",["plugin/models/groups"],function(e){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(t){this.groups=new e,this.settings=new Backbone.Model},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state",e),this.set("state_info",t),this.trigger("set:state"),console.debug("Chart:state() - "+t+" ("+e+")")}})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group","mvc/visualization/visualization-model"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;var t=e.attributes.type;if(!t)return console.debug("Storage::load() - Chart type not provided. Invalid format."),!1;var r=this.app.types.get(t);if(!r)return console.debug("Storage::load() - Chart type not supported. Please re-configure the chart. Resetting chart."),!1;console.debug("Storage::load() - Loading chart type "+t+"."),this.chart.definition=r,this.chart.set(e.attributes),this.chart.state("ok","Loading saved visualization..."),this.chart.settings.set(e.settings);for(var i in e.groups)this.chart.groups.add(new n(e.groups[i]));return this.chart.set("modified",!1),!0}})}),define("utils/deferred",["utils/utils"],function(e){return Backbone.Model.extend({queue:[],process:{},counter:0,initialize:function(){this.on("refresh",function(){if(this.queue.length>0&&this.ready()){var e=this.queue[0];this.queue.splice(0,1),e&&e()}})},execute:function(e){this.queue.push(e),this.trigger("refresh")},register:function(){var t=e.uuid();return this.process[t]=!0,this.counter++,console.debug("Deferred:register() - Registering "+t),t},done:function(e){this.process[e]&&(delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh"))},reset:function(){this.queue=[]},ready:function(){return this.counter==0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({container_list:[],canvas_list:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,100),this._createContainer("div");var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("set:state",function(){var e=r.$el.find("#info"),t=r.$el.find(".charts-viewport-container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var i=r.chart.get("state");switch(i){case"ok":e.hide(),t.show();break;case"failed":n.addClass("icon fa fa-warning"),t.hide();break;default:n.addClass("icon fa fa-spinner fa-spin"),t.show()}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_createContainer:function(e,t){t=t||1;for(var n in this.container_list)this.container_list[n].remove();this.container_list=[],this.canvas_list=[];for(var n=0;n<t;n++){var r=$(this._templateContainer(e,parseInt(100/t)));this.$el.append(r),this.container_list[n]=r,this.canvas_list[n]=r.find(".charts-viewport-canvas").attr("id")}},_draw:function(e){var t=this,n=this.app.deferred.register(),r=e.get("type");this.chart_definition=e.definition;var i=1;e.settings.get("use_panels")==="true"&&(i=e.groups.length),this._createContainer(this.chart_definition.tag,i),e.state("wait","Please wait...");if(!this.chart_definition.execute||this.chart_definition.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+this.app.chartPath(r)+"/wrapper"],function(r){if(t.chart_definition.execute)t.app.jobs.request(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})},function(){this.app.deferred.done(n)});else var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){n++;for(var i in r.chart_definition.columns)t+=i+"_"+n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t={groups:[]};this.chart_definition.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var r=0,i=this;return e.groups.each(function(e){var s={};for(var o in i.chart_definition.columns){var u=i.chart_definition.columns[o];s[o]=n.merge({index:e.get(o)},u)}t.groups.push({key:++r+":"+e.get("key"),columns:s})}),t},_template:function(){return'<div class="charts-viewport"><div id="info" class="info"><span id="icon" class="icon"/><span id="text" class="text" /></div></div>'},_templateContainer:function(e,t){return'<div class="charts-viewport-container" style="width:'+t+'%;">'+'<div id="menu"/>'+"<"+e+' id="'+n.uuid()+'" class="charts-viewport-canvas">'+"</div>"}})}),define("plugin/library/screenshot",["libs/underscore"],function(e){function t(e){e.$el.find("svg").length>0?r(e):n(e)}function n(e){try{var t=e.$el.find(".jqplot-target"),n=t.jqplotToImageStr({});n&&(window.location.href=n.replace("image/png","image/octet-stream"))}catch(r){console.debug("FAILED - Screenshot::_fromCanvas() - "+r),e.error&&e.error("Please reduce your chart to a single panel and try again.")}}function r(e){var t=e.$el,n=e.url,r=e.name,s=new XMLSerializer,o=document.createElement("canvas"),u=$(o),a=t.find("svg").length,f=t.find("svg").first(),l=parseInt(f.css("height")),c=parseInt(f.css("width"));u.attr("width",c*a),u.attr("height",l),(!o.getContext||!o.getContext("2d"))&&alert("Your browser doesn't support this feature, please use a modern browser");var h=o.getContext("2d"),p=0;t.find("svg").each(function(){var e=$(this);e.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:c,height:l});var t=s.serializeToString(this);h.drawSvg(t,p,0,c,l),p+=c}),window.location.href=i(o,o.getContext("2d"),"white").replace("image/png","image/octet-stream")}function i(e,t,n){var r=e.width,i=e.height,s;if(n){s=t.getImageData(0,0,r,i);var o=t.globalCompositeOperation;t.globalCompositeOperation="destination-over",t.fillStyle=n,t.fillRect(0,0,r,i)}var u=e.toDataURL("image/png");return n&&(t.clearRect(0,0,r,i),t.putImageData(s,0,0),t.globalCompositeOperation=o),u}function s(e){window.location.href="data:none/none;base64,"+btoa(a(e).string)}function o(e){for(var t in document.styleSheets){var n=document.styleSheets[t],r=n.cssRules;if(r)for(var i=0,s=r.length;i<s;i++)try{e.find(r[i].selectorText).each(function(e,t){t.style.cssText+=r[i].style.cssText})}catch(o){}}}function u(e){var t=a(e),n={filename:name||"chart",type:"application/pdf",height:t.height,width:t.width,scale:2,svg:t.string},r=$("body"),i=r.find("#viewport-form");i.length===0&&(i=$("<form>",{id:"viewport-form",method:"post",action:"http://export.highcharts.com/",display:"none"}),r.append(i)),i.empty();for(name in n){var s=$("<input/>",{type:"hidden",name:name,value:n[name]});i.append(s)}try{i.submit()}catch(o){console.log(o)}}function a(e){if(e.$el.find("svg").length==0&&e.error){e.error("No SVG found. This chart type does not support SVG/PDF export.");return}var t=e.$el,n=t.find("svg").length,r=parseInt(t.find("svg").first().css("height")),i=parseInt(t.find("svg").first().css("width")),s=new XMLSerializer,u=$("<svg/>");u.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:i*n,height:r});var a="",f=0;return t.find("svg").each(function(){var e=$(this).clone();o(e);var t=$('<g transform="translate('+f+', 0)">');t.append(e.find("g").first()),u.append(t),f+=i}),{string:s.serializeToString(u[0]),height:r,width:i}}return{createPNG:t,createSVG:s,createPDF:u}}),define("plugin/views/viewer",["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-portlet","plugin/views/viewport","plugin/library/screenshot"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,s){this.app=e,this.chart=this.app.chart,this.viewport_view=new r(e);var o=this;this.message=new t.Message;var u=new t.ButtonMenu({icon:"fa-camera",title:"Screenshot",tooltip:"Download as PNG, SVG or PDF file"});u.addMenu({id:"button-png",title:"Save as PNG",icon:"fa-file",onclick:function(){o._wait(o.chart,function(){i.createPNG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-svg",title:"Save as SVG",icon:"fa-file-text-o",onclick:function(){o._wait(o.chart,function(){i.createSVG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-png",title:"Save as PDF",icon:"fa-file-o",onclick:function(){o.app.modal.show({title:"Send chart data for PDF creation",body:"Galaxy does not provide integrated PDF export scripts. You may click 'Continue' to create the PDF by using a 3rd party service (https://export.highcharts.com)",buttons:{Cancel:function(){o.app.modal.hide()},Continue:function(){o.app.modal.hide(),o._wait(o.chart,function(){i.createPDF({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}})}}),this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",scrollable:!1,operations:{edit_button:new t.ButtonIcon({icon:"fa-edit",tooltip:"Customize this chart",title:"Editor",onclick:function(){o._wait(o.chart,function(){o.app.go("editor")})}}),picture_button_menu:u}}),this.portlet.append(this.message.$el),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var o=this;this.chart.on("change:title",function(){o._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){this.app.deferred.ready()?t():this.message.update({message:"Your chart is currently being processed. Please wait and try again."})}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{title_new:"",operations:null,onnew:null,max:null,onchange:null},initialize:function(t){this.visible=!1,this.$nav=null,this.$content=null,this.first_tab=null,this.current_id=null,this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},size:function(){return _.size(this.list)},current:function(){return this.$el.find(".tab-pane.active").attr("id")},add:function(e){var t=this,n=e.id,r=$(this._template_tab(e)),i=$(this._template_tab_content(e));this.list[n]=e.ondel?!0:!1,this.options.onnew?this.$nav.find("#new-tab").before(r):this.$nav.append(r),i.append(e.$el),this.$content.append(i),this.size()==1&&(r.addClass("active"),i.addClass("active"),this.first_tab=n),this.options.max&&this.size()>=this.options.max&&this.$el.find("#new-tab").hide();if(e.ondel){var s=r.find("#delete");s.tooltip({title:"Delete this tab",placement:"bottom",container:t.$el}),s.on("click",function(){return s.tooltip("destroy"),t.$el.find(".tooltip").remove(),e.ondel(),!1})}r.on("click",function(r){r.preventDefault(),e.onclick?e.onclick():t.show(n)}),this.current_id||(this.current_id=n)},del:function(e){this.$el.find("#tab-"+e).remove(),this.$el.find("#"+e).remove(),this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab),this.list[e]&&delete this.list[e],this.size()<this.options.max&&this.$el.find("#new-tab").show()},delRemovable:function(){for(var e in this.list)this.del(e)},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&(this.$el.find("#tab-"+this.current_id).removeClass("active"),this.$el.find("#"+this.current_id).removeClass("active"),this.$el.find("#tab-"+e).addClass("active"),this.$el.find("#"+e).addClass("active"),this.current_id=e),this.options.onchange&&this.options.onchange(e)},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.$el.find("#tab-title-text-"+e);return t&&n.html(t),n.html()},retitle:function(e){var t=0;for(var n in this.list)this.title(n,++t+": "+e)},_template:function(e){return'<div class="ui-tabs tabbable tabs-left"><ul id="tab-navigation" class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div id="tab-content" class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i class="ui-tabs-add fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="tab-'+e.id+'" class="tab-element">'+'<a id="tab-title-link-'+e.id+'" title="" href="#'+e.id+'" data-original-title="">'+'<span id="tab-title-text-'+e.id+'" class="tab-title-text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" class="ui-tabs-delete fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("mvc/ui/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null,cls:"ui-table",cls_tr:""},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=this._row()},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},append:function(e,t){this._commit(e,t,!1)},prepend:function(e,t){this._commit(e,t,!0)},get:function(e){return this.$el.find("#"+e)},del:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},delAll:function(){this.$tbody.empty(),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t,n){this.del(e),this.row.attr("id",e),n?this.$tbody.prepend(this.row):this.$tbody.append(this.row),t&&(this.row.hide(),this.row.fadeIn()),this.row=this._row(),this.row_count++,this._refresh()},_row:function(){return $('<tr class="'+this.options.cls_tr+'"></tr>')},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n!=""&&n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="'+e.cls+'">'+"<thead></thead>"+"<tbody></tbody>"+"</table>"+"<tmessage>"+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(e){s.group.set("key",e)}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.chart.definition;this.table.delAll();var s={};for(var o in i.columns){var u=i.columns[o];if(!u){console.debug("Group::_refreshTable() - Skipping column definition.");continue}var a=new t.Select.View({id:"select_"+o,wait:!0}),f=u.title;u.is_unique&&(f+=" (all data labels)"),this.table.add(f,"25%"),this.table.add(a.$el),this.table.append(o),s[o]=a}this.chart.state("wait","Loading metadata...");var l=this.app.deferred.register(),c={id:e,success:function(e){for(var t in s)r._addRow(t,e,s,i.columns[t]);r.chart.state("ok","Metadata initialized..."),r.app.deferred.done(l)}};this.app.datasets.request(c)},_addRow:function(e,t,n,r){var i=this,s=r.is_label,o=r.is_auto,u=r.is_numeric,a=r.is_unique,f=r.is_zero,l=[],c=n[e];o&&l.push({label:"Column: Row Number",value:"auto"}),f&&l.push({label:"Column: None",value:"zero"});var h=t.metadata_column_types;for(var p in h){var d=!1;h[p]=="int"||h[p]=="float"?d=u:d=s,d&&l.push({label:"Column: "+(parseInt(p)+1)+" ["+h[p]+"]",value:p})}c.update(l),a&&this.chart.groups.first()&&this.group.set(e,this.chart.groups.first().get(e));if(!c.exists(this.group.get(e))){var v=c.first();console.debug('Group()::_addRow() - Switching model value from "'+this.group.get(e)+'" to "'+v+'".'),this.group.set(e,v)}c.value(this.group.get(e)),this.group.off("change:"+e),this.group.on("change:"+e,function(){c.value(i.group.get(e))}),c.setOnChange(function(t){a?i.chart.groups.each(function(n){n.set(e,t)}):i.group.set(e,t),i.chart.set("modified",!0)}),c.show()},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),e!=this.group_key.value()&&this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){var r=Backbone.View.extend({optionsDefault:{title:"",content:"",mode:""},list:[],initialize:function(r,i){this.app=r,this.options=n.merge(i,this.optionsDefault),this.table_title=new t.Label({title:this.options.title}),this.table=new e.View({content:this.options.content});var s=$('<div class="ui-table-form"/>');this.options.title&&s.append(n.wrap(this.table_title.$el)),s.append(n.wrap(this.table.$el)),this.setElement(s)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.delAll(),this.list=[];for(var n in e)this._add(e[n].id||n,e[n],t);for(var n in this.list)this.list[n].trigger("change")},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:"field-"+e,placeholder:n.placeholder,value:r.get(e),onchange:function(t){r.set(e,t)}});break;case"radiobutton":s=new t.RadioButton.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"select":s=new t.Select.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"dataset":s=new t.Select.View({id:"field-"+e,onchange:function(t){r.set(e,t)}}),i.app.datasets.on("all",function(){var t=[];i.app.datasets.each(function(e){e.get("datatype_id")==n.data&&t.push({value:e.get("id"),label:e.get("name")})}),s.update(t),r.get(e)||r.set(e,s.first()),s.value(r.get(e))}),i.app.datasets.trigger("all.datasets");break;case"textarea":s=new t.Textarea({id:"field-"+e,onchange:function(){r.set(e,s.value())}});break;case"separator":s=$("<div/>");break;default:s=new t.Input({id:"field-"+e,placeholder:n.placeholder,type:n.type,onchange:function(){r.set(e,s.value())}})}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),n.info&&u.append('<div class="ui-table-form-info">'+n.info+"</div>"),this.options.style=="bold"?(this.table.add((new t.Label({title:n.title,cls:"form-label"})).$el),this.table.add(u)):(this.table.add('<span class="ui-table-form-title">'+n.title+"</span>","25%"),this.table.add(u))}else this.table.add('<div class="ui-table-form-separator">'+n.title+":<div/>"),this.table.add($("<div/>"));this.table.append(e),n.hide&&this.table.get(e).hide()}});return{View:r}}),define("plugin/views/settings",["mvc/ui/ui-misc","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View(e,{title:"Configuration",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refresh()})},_refresh:function(){var e=this.chart.definition;if(!e)return;this.form.title(e.category+" - "+e.title+":"),this.form.update(e.settings,this.chart.settings)}})}),define("plugin/views/types",["utils/utils","mvc/ui/ui-misc"],function(e,t){return Backbone.View.extend({optionsDefault:{onchange:null,ondblclick:null},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(n,r){var i=this;this.app=n,this.options=e.merge(r,this.optionsDefault);var s=$('<div class="charts-grid"/>');s.append(e.wrap((new t.Label({title:"How many data points would you like to analyze?"})).$el)),this.library=new t.RadioButton.View({data:[{label:"Few (<500)",value:"small"},{label:"Some (<10k)",value:"medium"},{label:"Many (>10k)",value:"large"}],onchange:function(e){i._filter(e)}}),s.append(e.wrap(this.library.$el)),this.setElement(s),this._render(),this.library.value("small"),this.library.trigger("change")},value:function(e){var t=this.$el.find(".current").attr("id");e!==undefined&&(this.$el.find(".current").removeClass("current"),this.$el.find("#"+e).addClass("current"));var n=this.$el.find(".current").attr("id");return n===undefined?null:(n!=t&&this.options.onchange&&this.options.onchange(e),n)},_filter:function(e){this.$el.find(".header").hide();var t=this.app.types.attributes;for(var n in t){var r=t[n],i=this.$el.find("#"+n),s=this.$el.find("#types-header-"+this.categories_index[r.category]),o=r.keywords||"";o.indexOf(e)>=0?(i.show(),s.show()):i.hide()}},_render:function(){this.categories={},this.categories_index={};var e=0,t=this.app.types.attributes;for(var n in t){var r=t[n],i=r.category;this.categories[i]||(this.categories[i]={},this.categories_index[i]=e++),this.categories[i][n]=r}for(var i in this.categories){var s=$('<div style="clear: both;"/>');s.append(this._template_header({id:"types-header-"+this.categories_index[i],title:i}));for(var n in this.categories[i]){var r=this.categories[i][n],o=r.title+" ("+r.library+")";r.zoomable&&(o='<span class="fa fa-search-plus"/>'+o),s.append(this._template_item({id:n,title:o,url:config.app_root+"charts/"+this.app.chartPath(n)+"/logo.png"}))}this.$el.append(s)}},_onclick:function(e){var t=this.value(),n=$(e.target).closest(".item").attr("id");n!=""&&n&&t!=n&&this.value(n)},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_template_header:function(e){return'<div id="'+e.id+'" class="header">'+"• "+e.title+"<div>"},_template_item:function(e){return'<div id="'+e.id+'" class="item">'+'<img class="image" src="'+e.url+'">'+'<div class="title">'+e.title+"</div>"+"<div>"}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","mvc/ui/ui-misc","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings","plugin/views/types"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({initialize:function(i,s){var o=this;this.app=i,this.chart=this.app.chart,this.message=new t.Message,this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new t.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){o._saveChart()}}),back:new t.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Cancel",onclick:function(){o.app.go("viewer"),o.app.storage.load()}})}}),this.types=new a(i,{onchange:function(e){var t=o.app.types.get(e);t||console.debug("FAILED - Editor::onchange() - Chart type not supported."),o.chart.definition=t,o.chart.settings.clear(),o.chart.set({type:e}),o.chart.set("modified",!0),console.debug("Editor::onchange() - Switched chart type.")},ondblclick:function(e){o._saveChart()}}),this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=o._addGroupModel();o.tabs.show(e.id)}}),this.title=new t.Input({placeholder:"Chart title",onchange:function(){o.chart.set("title",o.title.value())}});var f=$("<div/>");f.append(r.wrap((new t.Label({title:"Provide a chart title:"})).$el)),f.append(r.wrap(this.title.$el)),f.append(r.wrap(this.types.$el)),this.tabs.add({id:"main",title:"Start",$el:f}),this.settings=new u(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.message.$el),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var o=this;this.chart.on("change:title",function(e){o._refreshTitle()}),this.chart.on("change:type",function(e){o.types.value(e.get("type"))}),this.chart.on("reset",function(e){o._resetChart()}),this.app.chart.on("redraw",function(e){o.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){o._addGroup(e)}),this.app.chart.groups.on("remove",function(e){o._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){o._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){o._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Data label"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new s({id:r.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new o(this.app,{group:e});this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",r.uuid()),this.chart.set("type","nvd3_bar"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.types.value(),title:this.title.value(),date:r.time()});if(this.chart.groups.length==0){this.message.update({message:"Please select data columns before drawing the chart."});var e=this._addGroupModel();this.tabs.show(e.id);return}var t=this,n=!0,i=this.chart.definition;this.chart.groups.each(function(e){if(!n)return;for(var r in i.columns)if(e.attributes[r]=="null"){t.message.update({status:"danger",message:"This chart type requires column types not found in your tabular file."}),t.tabs.show(e.id),n=!1;return}});if(!n)return;this.app.go("viewer");var t=this;this.app.deferred.execute(function(){t.app.storage.save(),t.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e4,query_timeout:100}})}),define("plugin/charts/forms/default",[],function(){return{title:"",category:"",library:"",tag:"",keywords:"",settings:{separator_x:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["x_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["x_axis_precision"]}},{label:"Float",value:"f",operations:{show:["x_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["x_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["x_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["x_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["x_axis_precision"]}}]},x_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_y:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["y_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["y_axis_precision"]}},{label:"Float",value:"f",operations:{show:["y_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["y_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["y_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["y_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["y_axis_precision"]}}]},y_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{title:"Use multi-panels",info:"Would you like to separate your data into individual panels?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),function(){function t(e,t){return(new Date(t,e+1,0)).getDate()}function n(e,t,n){return function(r,i,s){var o=e(r),u=[];o<r&&t(o);if(s>1)while(o<i){var a=new Date(+o);n(a)%s===0&&u.push(a),t(o)}else while(o<i)u.push(new Date(+o)),t(o);return u}}var e=window.nv||{};e.version="1.1.15b",e.dev=!0,window.nv=e,e.tooltip=e.tooltip||{},e.utils=e.utils||{},e.models=e.models||{},e.charts={},e.graphs=[],e.logs={},e.dispatch=d3.dispatch("render_start","render_end"),e.dev&&(e.dispatch.on("render_start",function(t){e.logs.startTime=+(new Date)}),e.dispatch.on("render_end",function(t){e.logs.endTime=+(new Date),e.logs.totalTime=e.logs.endTime-e.logs.startTime,e.log("total",e.logs.totalTime)})),e.log=function(){if(e.dev&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(e.dev&&typeof console.log=="function"&&Function.prototype.bind){var t=Function.prototype.bind.call(console.log,console);t.apply(console,arguments)}return arguments[arguments.length-1]},e.render=function(n){n=n||1,e.render.active=!0,e.dispatch.render_start(),setTimeout(function(){var t,r;for(var i=0;i<n&&(r=e.render.queue[i]);i++)t=r.generate(),typeof r.callback==typeof Function&&r.callback(t),e.graphs.push(t);e.render.queue.splice(0,i),e.render.queue.length?setTimeout(arguments.callee,0):(e.dispatch.render_end(),e.render.active=!1)},0)},e.render.active=!1,e.render.queue=[],e.addGraph=function(t){typeof arguments[0]==typeof Function&&(t={generate:arguments[0],callback:arguments[1]}),e.render.queue.push(t),e.render.active||e.render()},e.identity=function(e){return e},e.strip=function(e){return e.replace(/(\s|&)/g,"")},d3.time.monthEnd=function(e){return new Date(e.getFullYear(),e.getMonth(),0)},d3.time.monthEnds=n(d3.time.monthEnd,function(e){e.setUTCDate(e.getUTCDate()+1),e.setDate(t(e.getMonth()+1,e.getFullYear()))},function(e){return e.getMonth()}),e.interactiveGuideline=function(){function c(o){o.each(function(o){function g(){var e=d3.mouse(this),n=e[0],r=e[1],o=!0,a=!1;l&&(n=d3.event.offsetX,r=d3.event.offsetY,d3.event.target.tagName!=="svg"&&(o=!1),d3.event.target.className.baseVal.match("nv-legend")&&(a=!0)),o&&(n-=i.left,r-=i.top);if(n<0||r<0||n>p||r>d||d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined||a){if(l&&d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined&&d3.event.relatedTarget.className.match(t.nvPointerEventsClass))return;u.elementMouseout({mouseX:n,mouseY:r}),c.renderGuideLine(null);return}var f=s.invert(n);u.elementMousemove({mouseX:n,mouseY:r,pointXValue:f}),d3.event.type==="dblclick"&&u.elementDblclick({mouseX:n,mouseY:r,pointXValue:f})}var h=d3.select(this),p=n||960,d=r||400,v=h.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([o]),m=v.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");m.append("g").attr("class","nv-interactiveGuideLine");if(!f)return;f.on("mousemove",g,!0).on("mouseout",g,!0).on("dblclick",g),c.renderGuideLine=function(t){if(!a)return;var n=v.select(".nv-interactiveGuideLine").selectAll("line").data(t!=null?[e.utils.NaNtoZero(t)]:[],String);n.enter().append("line").attr("class","nv-guideline").attr("x1",function(e){return e}).attr("x2",function(e){return e}).attr("y1",d).attr("y2",0),n.exit().remove()}})}var t=e.models.tooltip(),n=null,r=null,i={left:0,top:0},s=d3.scale.linear(),o=d3.scale.linear(),u=d3.dispatch("elementMousemove","elementMouseout","elementDblclick"),a=!0,f=null,l=navigator.userAgent.indexOf("MSIE")!==-1;return c.dispatch=u,c.tooltip=t,c.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.left=typeof e.left!="undefined"?e.left:i.left,c):i},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.xScale=function(e){return arguments.length?(s=e,c):s},c.showGuideLine=function(e){return arguments.length?(a=e,c):a},c.svgContainer=function(e){return arguments.length?(f=e,c):f},c},e.interactiveBisect=function(e,t,n){if(!e instanceof Array)return null;typeof n!="function"&&(n=function(e,t){return e.x});var r=d3.bisector(n).left,i=d3.max([0,r(e,t)-1]),s=n(e[i],i);typeof s=="undefined"&&(s=i);if(s===t)return i;var o=d3.min([i+1,e.length-1]),u=n(e[o],o);return typeof u=="undefined"&&(u=o),Math.abs(u-t)>=Math.abs(s-t)?i:o},e.nearestValueIndex=function(e,t,n){var r=Infinity,i=null;return e.forEach(function(e,s){var o=Math.abs(t-e);o<=r&&o<n&&(r=o,i=s)}),i},function(){window.nv.tooltip={},window.nv.models.tooltip=function(){function y(){if(a){var e=d3.select(a);e.node().tagName!=="svg"&&(e=e.select("svg"));var t=e.node()?e.attr("viewBox"):null;if(t){t=t.split(" ");var n=parseInt(e.style("width"))/t[2];l.left=l.left*n,l.top=l.top*n}}}function b(e){var t;a?t=d3.select(a):t=d3.select("body");var n=t.select(".nvtooltip");return n.node()===null&&(n=t.append("div").attr("class","nvtooltip "+(u?u:"xy-tooltip")).attr("id",h)),n.node().innerHTML=e,n.style("top",0).style("left",0).style("opacity",0),n.selectAll("div, table, td, tr").classed(p,!0),n.classed(p,!0),n.node()}function w(){if(!c)return;if(!g(n))return;y();var t=l.left,u=o!=null?o:l.top,h=b(m(n));f=h;if(a){var p=a.getElementsByTagName("svg")[0],d=p?p.getBoundingClientRect():a.getBoundingClientRect(),v={left:0,top:0};if(p){var E=p.getBoundingClientRect(),S=a.getBoundingClientRect(),x=E.top;if(x<0){var T=a.getBoundingClientRect();x=Math.abs(x)>T.height?0:x}v.top=Math.abs(x-S.top),v.left=Math.abs(E.left-S.left)}t+=a.offsetLeft+v.left-2*a.scrollLeft,u+=a.offsetTop+v.top-2*a.scrollTop}return s&&s>0&&(u=Math.floor(u/s)*s),e.tooltip.calcTooltipPosition([t,u],r,i,h),w}var t=null,n=null,r="w",i=50,s=25,o=null,u=null,a=null,f=null,l={left:null,top:null},c=!0,h="nvtooltip-"+Math.floor(Math.random()*1e5),p="nv-pointer-events-none",d=function(e,t){return e},v=function(e){return e},m=function(e){if(t!=null)return t;if(e==null)return"";var n=d3.select(document.createElement("table")),r=n.selectAll("thead").data([e]).enter().append("thead");r.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(v(e.value));var i=n.selectAll("tbody").data([e]).enter().append("tbody"),s=i.selectAll("tr").data(function(e){return e.series}).enter().append("tr").classed("highlight",function(e){return e.highlight});s.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(e){return e.color}),s.append("td").classed("key",!0).html(function(e){return e.key}),s.append("td").classed("value",!0).html(function(e,t){return d(e.value,t)}),s.selectAll("td").each(function(e){if(e.highlight){var t=d3.scale.linear().domain([0,1]).range(["#fff",e.color]),n=.6;d3.select(this).style("border-bottom-color",t(n)).style("border-top-color",t(n))}});var o=n.node().outerHTML;return e.footer!==undefined&&(o+="<div class='footer'>"+e.footer+"</div>"),o},g=function(e){return e&&e.series&&e.series.length>0?!0:!1};return w.nvPointerEventsClass=p,w.content=function(e){return arguments.length?(t=e,w):t},w.tooltipElem=function(){return f},w.contentGenerator=function(e){return arguments.length?(typeof e=="function"&&(m=e),w):m},w.data=function(e){return arguments.length?(n=e,w):n},w.gravity=function(e){return arguments.length?(r=e,w):r},w.distance=function(e){return arguments.length?(i=e,w):i},w.snapDistance=function(e){return arguments.length?(s=e,w):s},w.classes=function(e){return arguments.length?(u=e,w):u},w.chartContainer=function(e){return arguments.length?(a=e,w):a},w.position=function(e){return arguments.length?(l.left=typeof e.left!="undefined"?e.left:l.left,l.top=typeof e.top!="undefined"?e.top:l.top,w):l},w.fixedTop=function(e){return arguments.length?(o=e,w):o},w.enabled=function(e){return arguments.length?(c=e,w):c},w.valueFormatter=function(e){return arguments.length?(typeof e=="function"&&(d=e),w):d},w.headerFormatter=function(e){return arguments.length?(typeof e=="function"&&(v=e),w):v},w.id=function(){return h},w},e.tooltip.show=function(t,n,r,i,s,o){var u=document.createElement("div");u.className="nvtooltip "+(o?o:"xy-tooltip");var a=s;if(!s||s.tagName.match(/g|svg/i))a=document.getElementsByTagName("body")[0];u.style.left=0,u.style.top=0,u.style.opacity=0,u.innerHTML=n,a.appendChild(u),s&&(t[0]=t[0]-s.scrollLeft,t[1]=t[1]-s.scrollTop),e.tooltip.calcTooltipPosition(t,r,i,u)},e.tooltip.findFirstNonSVGParent=function(e){while(e.tagName.match(/^g|svg$/i)!==null)e=e.parentNode;return e},e.tooltip.findTotalOffsetTop=function(e,t){var n=t;do isNaN(e.offsetTop)||(n+=e.offsetTop);while(e=e.offsetParent);return n},e.tooltip.findTotalOffsetLeft=function(e,t){var n=t;do isNaN(e.offsetLeft)||(n+=e.offsetLeft);while(e=e.offsetParent);return n},e.tooltip.calcTooltipPosition=function(t,n,r,i){var s=parseInt(i.offsetHeight),o=parseInt(i.offsetWidth),u=e.utils.windowSize().width,a=e.utils.windowSize().height,f=window.pageYOffset,l=window.pageXOffset,c,h;a=window.innerWidth>=document.body.scrollWidth?a:a-16,u=window.innerHeight>=document.body.scrollHeight?u:u-16,n=n||"s",r=r||20;var p=function(t){return e.tooltip.findTotalOffsetTop(t,h)},d=function(t){return e.tooltip.findTotalOffsetLeft(t,c)};switch(n){case"e":c=t[0]-o-r,h=t[1]-s/2;var v=d(i),m=p(i);v<l&&(c=t[0]+r>l?t[0]+r:l-v+c),m<f&&(h=f-m+h),m+s>f+a&&(h=f+a-m+h-s);break;case"w":c=t[0]+r,h=t[1]-s/2;var v=d(i),m=p(i);v+o>u&&(c=t[0]-o-r),m<f&&(h=f+5),m+s>f+a&&(h=f+a-m+h-s);break;case"n":c=t[0]-o/2-5,h=t[1]+r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),m+s>f+a&&(h=f+a-m+h-s);break;case"s":c=t[0]-o/2,h=t[1]-s-r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),f>m&&(h=f);break;case"none":c=t[0],h=t[1]-r;var v=d(i),m=p(i)}return i.style.left=c+"px",i.style.top=h+"px",i.style.opacity=1,i.style.position="absolute",i},e.tooltip.cleanup=function(){var e=document.getElementsByClassName("nvtooltip"),t=[];while(e.length)t.push(e[0]),e[0].style.transitionDelay="0 !important",e[0].style.opacity=0,e[0].className="nvtooltip-pending-removal";setTimeout(function(){while(t.length){var e=t.pop();e.parentNode.removeChild(e)}},500)}}(),e.utils.windowSize=function(){var e={width:640,height:480};return document.body&&document.body.offsetWidth&&(e.width=document.body.offsetWidth,e.height=document.body.offsetHeight),document.compatMode=="CSS1Compat"&&document.documentElement&&document.documentElement.offsetWidth&&(e.width=document.documentElement.offsetWidth,e.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(e.width=window.innerWidth,e.height=window.innerHeight),e},e.utils.windowResize=function(e){if(e===undefined)return;var t=window.onresize;window.onresize=function(n){typeof t=="function"&&t(n),e(n)}},e.utils.getColor=function(t){return arguments.length?Object.prototype.toString.call(t)==="[object Array]"?function(e,n){return e.color||t[n%t.length]}:t:e.utils.defaultColor()},e.utils.defaultColor=function(){var e=d3.scale.category20().range();return function(t,n){return t.color||e[n%e.length]}},e.utils.customTheme=function(e,t,n){t=t||function(e){return e.key},n=n||d3.scale.category20().range();var r=n.length;return function(i,s){var o=t(i);return r||(r=n.length),typeof e[o]!="undefined"?typeof e[o]=="function"?e[o]():e[o]:n[--r]}},e.utils.pjax=function(t,n){function r(r){d3.html(r,function(r){var i=d3.select(n).node();i.parentNode.replaceChild(d3.select(r).select(n).node(),i),e.utils.pjax(t,n)})}d3.selectAll(t).on("click",function(){history.pushState(this.href,this.textContent,this.href),r(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&r(d3.event.state)})},e.utils.calcApproxTextWidth=function(e){if(typeof e.style=="function"&&typeof e.text=="function"){var t=parseInt(e.style("font-size").replace("px","")),n=e.text().length;return n*t*.5}return 0},e.utils.NaNtoZero=function(e){return typeof e!="number"||isNaN(e)||e===null||e===Infinity?0:e},e.utils.optionsFunc=function(e){return e&&d3.map(e).forEach(function(e,t){typeof this[e]=="function"&&this[e](t)}.bind(this)),this},e.models.axis=function(){function m(e){return e.each(function(e){var i=d3.select(this),m=i.selectAll("g.nv-wrap.nv-axis").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),y=g.append("g"),b=m.select("g");p!==null?t.ticks(p):(t.orient()=="top"||t.orient()=="bottom")&&t.ticks(Math.abs(s.range()[1]-s.range()[0])/100),b.call(t),v=v||t.scale();var w=t.tickFormat();w==null&&(w=v.tickFormat());var E=b.selectAll("text.nv-axislabel").data([o||null]);E.exit().remove();switch(t.orient()){case"top":E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",0).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+s(e)+",0)"}).select("text").attr("dy","-0.5em").attr("y",-t.tickPadding()).attr("text-anchor","middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+s.range()[t]+",0)"})}break;case"bottom":var T=36,N=30,C=b.selectAll("g").select("text");if(f%360){C.each(function(e,t){var n=this.getBBox().width;n>N&&(N=n)});var k=Math.abs(Math.sin(f*Math.PI/180)),T=(k?k*N:N)+30;C.attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f%360>0?"start":"end")}E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",T).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data([s.domain()[0],s.domain()[s.domain().length-1]]);x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",t.tickPadding()).attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f?f%360>0?"start":"end":"middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"})}c&&C.attr("transform",function(e,t){return"translate(0,"+(t%2==0?"0":"12")+")"});break;case"right":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"begin").attr("transform",l?"rotate(90)":"").attr("y",l?-Math.max(n.right,r)+12:-10).attr("x",l?s.range()[0]/2:t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+s(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",t.tickPadding()).style("text-anchor","start").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}break;case"left":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"end").attr("transform",l?"rotate(-90)":"").attr("y",l?-Math.max(n.left,r)+d:-10).attr("x",l?-s.range()[0]/2:-t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+v(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-t.tickPadding()).attr("text-anchor","end").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}}E.text(function(e){return e}),u&&(t.orient()==="left"||t.orient()==="right")&&(b.selectAll("g").each(function(e,t){d3.select(this).select("text").attr("opacity",1);if(s(e)<s.range()[1]+10||s(e)>s.range()[0]-10)(e>1e-10||e<-1e-10)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0)}),s.domain()[0]==s.domain()[1]&&s.domain()[0]==0&&m.selectAll("g.nv-axisMaxMin").style("opacity",function(e,t){return t?0:1}));if(u&&(t.orient()==="top"||t.orient()==="bottom")){var L=[];m.selectAll("g.nv-axisMaxMin").each(function(e,t){try{t?L.push(s(e)-this.getBBox().width-4):L.push(s(e)+this.getBBox().width+4)}catch(n){t?L.push(s(e)-4):L.push(s(e)+4)}}),b.selectAll("g").each(function(e,t){if(s(e)<L[0]||s(e)>L[1])e>1e-10||e<-1e-10?d3.select(this).remove():d3.select(this).select("text").remove()})}a&&b.selectAll(".tick").filter(function(e){return!parseFloat(Math.round(e.__data__*1e5)/1e6)&&e.__data__!==undefined}).classed("zero",!0),v=s.copy()}),m}var t=d3.svg.axis(),n={top:0,right:0,bottom:0,left:0},r=75,i=60,s=d3.scale.linear(),o=null,u=!0,a=!0,f=0,l=!0,c=!1,h=!1,p=null,d=12;t.scale(s).orient("bottom").tickFormat(function(e){return e});var v;return m.axis=t,d3.rebind(m,t,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.ticks=function(e){return arguments.length?(p=e,m):p},m.height=function(e){return arguments.length?(i=e,m):i},m.axisLabel=function(e){return arguments.length?(o=e,m):o},m.showMaxMin=function(e){return arguments.length?(u=e,m):u},m.highlightZero=function(e){return arguments.length?(a=e,m):a},m.scale=function(e){return arguments.length?(s=e,t.scale(s),h=typeof s.rangeBands=="function",d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m):s},m.rotateYLabel=function(e){return arguments.length?(l=e,m):l},m.rotateLabels=function(e){return arguments.length?(f=e,m):f},m.staggerLabels=function(e){return arguments.length?(c=e,m):c},m.axisLabelDistance=function(e){return arguments.length?(d=e,m):d},m},e.models.historicalBar=function(){function w(E){return E.each(function(w){var E=n-t.left-t.right,S=r-t.top-t.bottom,T=d3.select(this);s.domain(d||d3.extent(w[0].values.map(u).concat(f))),c?s.range(m||[E*.5/w[0].values.length,E*(w[0].values.length-.5)/w[0].values.length]):s.range(m||[0,E]),o.domain(v||d3.extent(w[0].values.map(a).concat(l))).range(g||[S,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=T.selectAll("g.nv-wrap.nv-historicalBar-"+i).data([w[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+i),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-bars"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){y.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",E).attr("height",S),A.attr("clip-path",h?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-bars").selectAll(".nv-bar").data(function(e){return e},function(e,t){return u(e,t)});O.exit().remove();var M=O.enter().append("rect").attr("x",0).attr("y",function(t,n){return e.utils.NaNtoZero(o(Math.max(0,a(t,n))))}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.abs(o(a(t,n))-o(0)))}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).on("mouseover",function(e,t){if(!b)return;d3.select(this).classed("hover",!0),y.elementMouseover({point:e,series:w[0],pos:[s(u(e,t)),o(a(e,t))],pointIndex:t,seriesIndex:0,e:d3.event})}).on("mouseout",function(e,t){if(!b)return;d3.select(this).classed("hover",!1),y.elementMouseout({point:e,series:w[0],pointIndex:t,seriesIndex:0,e:d3.event})}).on("click",function(e,t){if(!b)return;y.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){if(!b)return;y.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("fill",function(e,t){return p(e,t)}).attr("class",function(e,t,n){return(a(e,t)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+n+"-"+t}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).attr("width",E/w[0].values.length*.9),O.attr("y",function(t,n){var r=a(t,n)<0?o(0):o(0)-o(a(t,n))<1?o(0)-1:o(a(t,n));return e.utils.NaNtoZero(r)}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.max(Math.abs(o(a(t,n))-o(0)),1))})}),w}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[],l=[0],c=!1,h=!0,p=e.utils.defaultColor(),d,v,m,g,y=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),b=!0;return w.highlightPoint=function(e,t){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar-0-"+e).classed("hover",t)},w.clearHighlights=function(){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar.hover").classed("hover",!1)},w.dispatch=y,w.options=e.utils.optionsFunc.bind(w),w.x=function(e){return arguments.length?(u=e,w):u},w.y=function(e){return arguments.length?(a=e,w):a},w.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,w):t},w.width=function(e){return arguments.length?(n=e,w):n},w.height=function(e){return arguments.length?(r=e,w):r},w.xScale=function(e){return arguments.length?(s=e,w):s},w.yScale=function(e){return arguments.length?(o=e,w):o},w.xDomain=function(e){return arguments.length?(d=e,w):d},w.yDomain=function(e){return arguments.length?(v=e,w):v},w.xRange=function(e){return arguments.length?(m=e,w):m},w.yRange=function(e){return arguments.length?(g=e,w):g},w.forceX=function(e){return arguments.length?(f=e,w):f},w.forceY=function(e){return arguments.length?(l=e,w):l},w.padData=function(e){return arguments.length?(c=e,w):c},w.clipEdge=function(e){return arguments.length?(h=e,w):h},w.color=function(t){return arguments.length?(p=e.utils.getColor(t),w):p},w.id=function(e){return arguments.length?(i=e,w):i},w.interactive=function(e){return arguments.length?(b=!1,w):b},w},e.models.bullet=function(){function m(e){return e.each(function(e,n){var p=c-t.left-t.right,m=h-t.top-t.bottom,g=d3.select(this),y=i.call(this,e,n).slice().sort(d3.descending),b=s.call(this,e,n).slice().sort(d3.descending),w=o.call(this,e,n).slice().sort(d3.descending),E=u.call(this,e,n).slice(),S=a.call(this,e,n).slice(),x=f.call(this,e,n).slice(),T=d3.scale.linear().domain(d3.extent(d3.merge([l,y]))).range(r?[p,0]:[0,p]),N=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(T.range());this.__chart__=T;var C=d3.min(y),k=d3.max(y),L=y[1],A=g.selectAll("g.nv-wrap.nv-bullet").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),M=O.append("g"),_=A.select("g");M.append("rect").attr("class","nv-range nv-rangeMax"),M.append("rect").attr("class","nv-range nv-rangeAvg"),M.append("rect").attr("class","nv-range nv-rangeMin"),M.append("rect").attr("class","nv-measure"),M.append("path").attr("class","nv-markerTriangle"),A.attr("transform","translate("+t.left+","+t.top+")");var D=function(e){return Math.abs(N(e)-N(0))},P=function(e){return Math.abs(T(e)-T(0))},H=function(e){return e<0?N(e):N(0)},B=function(e){return e<0?T(e):T(0)};_.select("rect.nv-rangeMax").attr("height",m).attr("width",P(k>0?k:C)).attr("x",B(k>0?k:C)).datum(k>0?k:C),_.select("rect.nv-rangeAvg").attr("height",m).attr("width",P(L)).attr("x",B(L)).datum(L),_.select("rect.nv-rangeMin").attr("height",m).attr("width",P(k)).attr("x",B(k)).attr("width",P(k>0?C:k)).attr("x",B(k>0?C:k)).datum(k>0?C:k),_.select("rect.nv-measure").style("fill",d).attr("height",m/3).attr("y",m/3).attr("width",w<0?T(0)-T(w[0]):T(w[0])-T(0)).attr("x",B(w)).on("mouseover",function(){v.elementMouseover({value:w[0],label:x[0]||"Current",pos:[T(w[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:w[0],label:x[0]||"Current"})});var j=m/6;b[0]?_.selectAll("path.nv-markerTriangle").attr("transform",function(e){return"translate("+T(b[0])+","+m/2+")"}).attr("d","M0,"+j+"L"+j+","+ -j+" "+ -j+","+ -j+"Z").on("mouseover",function(){v.elementMouseover({value:b[0],label:S[0]||"Previous",pos:[T(b[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:b[0],label:S[0]||"Previous"})}):_.selectAll("path.nv-markerTriangle").remove(),A.selectAll(".nv-range").on("mouseover",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseover({value:e,label:n,pos:[T(e),m/2]})}).on("mouseout",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseout({value:e,label:n})})}),m}var t={top:0,right:0,bottom:0,left:0},n="left",r=!1,i=function(e){return e.ranges},s=function(e){return e.markers},o=function(e){return e.measures},u=function(e){return e.rangeLabels?e.rangeLabels:[]},a=function(e){return e.markerLabels?e.markerLabels:[]},f=function(e){return e.measureLabels?e.measureLabels:[]},l=[0],c=380,h=30,p=null,d=e.utils.getColor(["#1f77b4"]),v=d3.dispatch("elementMouseover","elementMouseout");return m.dispatch=v,m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(i=e,m):i},m.markers=function(e){return arguments.length?(s=e,m):s},m.measures=function(e){return arguments.length?(o=e,m):o},m.forceX=function(e){return arguments.length?(l=e,m):l},m.width=function(e){return arguments.length?(c=e,m):c},m.height=function(e){return arguments.length?(h=e,m):h},m.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,m):t},m.tickFormat=function(e){return arguments.length?(p=e,m):p},m.color=function(t){return arguments.length?(d=e.utils.getColor(t),m):d},m},e.models.bulletChart=function(){function m(e){return e.each(function(n,h){var g=d3.select(this),y=(a||parseInt(g.style("width"))||960)-i.left-i.right,b=f-i.top-i.bottom,w=this;m.update=function(){m(e)},m.container=this;if(!n||!s.call(this,n,h)){var E=g.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+y/2).attr("y",18+i.top+b/2).text(function(e){return e}),m}g.selectAll(".nv-noData").remove();var S=s.call(this,n,h).slice().sort(d3.descending),x=o.call(this,n,h).slice().sort(d3.descending),T=u.call(this,n,h).slice().sort(d3.descending),N=g.selectAll("g.nv-wrap.nv-bulletChart").data([n]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-bulletWrap"),k.append("g").attr("class","nv-titles"),N.attr("transform","translate("+i.left+","+i.top+")");var A=d3.scale.linear().domain([0,Math.max(S[0],x[0],T[0])]).range(r?[y,0]:[0,y]),O=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(A.range());this.__chart__=A;var M=function(e){return Math.abs(O(e)-O(0))},_=function(e){return Math.abs(A(e)-A(0))},D=k.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(f-i.top-i.bottom)/2+")");D.append("text").attr("class","nv-title").text(function(e){return e.title}),D.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(e){return e.subtitle}),t.width(y).height(b);var P=L.select(".nv-bulletWrap");d3.transition(P).call(t);var H=l||A.tickFormat(y/100),B=L.selectAll("g.nv-tick").data(A.ticks(y/50),function(e){return this.textContent||H(e)}),j=B.enter().append("g").attr("class","nv-tick").attr("transform",function(e){return"translate("+O(e)+",0)"}).style("opacity",1e-6);j.append("line").attr("y1",b).attr("y2",b*7/6),j.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",b*7/6).text(H);var F=d3.transition(B).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1);F.select("line").attr("y1",b).attr("y2",b*7/6),F.select("text").attr("y",b*7/6),d3.transition(B.exit()).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1e-6).remove(),d.on("tooltipShow",function(e){e.key=n.title,c&&v(e,w.parentNode)})}),d3.timer.flush(),m}var t=e.models.bullet(),n="left",r=!1,i={top:5,right:40,bottom:20,left:120},s=function(e){return e.ranges},o=function(e){return e.markers},u=function(e){return e.measures},a=null,f=55,l=null,c=!0,h=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide"),v=function(t,n){var r=t.pos[0]+(n.offsetLeft||0)+i.left,s=t.pos[1]+(n.offsetTop||0)+i.top,o=h(t.key,t.label,t.value,t,m);e.tooltip.show([r,s],o,t.value<0?"e":"w",null,n)};return t.dispatch.on("elementMouseover.tooltip",function(e){d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),m.dispatch=d,m.bullet=t,d3.rebind(m,t,"color"),m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(s=e,m):s},m.markers=function(e){return arguments.length?(o=e,m):o},m.measures=function(e){return arguments.length?(u=e,m):u},m.width=function(e){return arguments.length?(a=e,m):a},m.height=function(e){return arguments.length?(f=e,m):f},m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.tickFormat=function(e){return arguments.length?(l=e,m):l},m.tooltips=function(e){return arguments.length?(c=e,m):c},m.tooltipContent=function(e){return arguments.length?(h=e,m):h},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.cumulativeLineChart=function(){function D(b){return b.each(function(b){function I(e,t){d3.select(D.container).style("cursor","ew-resize")}function q(e,t){M.x=d3.event.x,M.i=Math.round(O.invert(M.x)),nt()}function R(e,t){d3.select(D.container).style("cursor","auto"),x.index=M.i,k.stateChange(x)}function nt(){tt.data([M]);var e=D.transitionDuration();D.transitionDuration(0),D.update(),D.transitionDuration(e)}var L=d3.select(this).classed("nv-chart-"+S,!0),A=this,H=(f||parseInt(L.style("width"))||960)-u.left-u.right,B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom;D.update=function(){L.call(D)},D.container=this,x.disabled=b.map(function(e){return!!e.disabled});if(!T){var j;T={};for(j in x)x[j]instanceof Array?T[j]=x[j].slice(0):T[j]=x[j]}var F=d3.behavior.drag().on("dragstart",I).on("drag",q).on("dragend",R);if(!b||!b.length||!b.filter(function(e){return e.values.length}).length){var U=L.selectAll(".nv-noData").data([N]);return U.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),U.attr("x",u.left+H/2).attr("y",u.top+B/2).text(function(e){return e}),D}L.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();if(!y){var z=b.filter(function(e){return!e.disabled}).map(function(e,n){var r=d3.extent(e.values,t.y());return r[0]<-0.95&&(r[0]=-0.95),[(r[0]-r[1])/(1+r[1]),(r[1]-r[0])/(1+r[0])]}),W=[d3.min(z,function(e){return e[0]}),d3.max(z,function(e){return e[1]})];t.yDomain(W)}else t.yDomain(null);O.domain([0,b[0].values.length-1]).range([0,H]).clamp(!0);var b=P(M.i,b),X=g?"none":"all",V=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([b]),$=V.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),J=V.select("g");$.append("g").attr("class","nv-interactive"),$.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),$.append("g").attr("class","nv-y nv-axis"),$.append("g").attr("class","nv-background"),$.append("g").attr("class","nv-linesWrap").style("pointer-events",X),$.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),$.append("g").attr("class","nv-legendWrap"),$.append("g").attr("class","nv-controlsWrap"),c&&(i.width(H),J.select(".nv-legendWrap").datum(b).call(i),u.top!=i.height()&&(u.top=i.height(),B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom),J.select(".nv-legendWrap").attr("transform","translate(0,"+ -u.top+")"));if(m){var K=[{key:"Re-scale y-axis",disabled:!y}];s.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),J.select(".nv-controlsWrap").datum(K).attr("transform","translate(0,"+ -u.top+")").call(s)}V.attr("transform","translate("+u.left+","+u.top+")"),d&&J.select(".nv-y.nv-axis").attr("transform","translate("+H+",0)");var Q=b.filter(function(e){return e.tempDisabled});V.select(".tempDisabled").remove(),Q.length&&V.append("text").attr("class","tempDisabled").attr("x",H/2).attr("y","-.71em").style("text-anchor","end").text(Q.map(function(e){return e.key}).join(", ")+" values cannot be calculated for this time period."),g&&(o.width(H).height(B).margin({left:u.left,top:u.top}).svgContainer(L).xScale(w),V.select(".nv-interactive").call(o)),$.select(".nv-background").append("rect"),J.select(".nv-background rect").attr("width",H).attr("height",B),t.y(function(e){return e.display.y}).width(H).height(B).color(b.map(function(e,t){return e.color||a(e,t)}).filter(function(e,t){return!b[t].disabled&&!b[t].tempDisabled}));var G=J.select(".nv-linesWrap").datum(b.filter(function(e){return!e.disabled&&!e.tempDisabled}));G.call(t),b.forEach(function(e,t){e.seriesIndex=t});var Y=b.filter(function(e){return!e.disabled&&!!C(e)}),Z=J.select(".nv-avgLinesWrap").selectAll("line").data(Y,function(e){return e.key}),et=function(e){var t=E(C(e));return t<0?0:t>B?B:t};Z.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(e,n){return t.color()(e,e.seriesIndex)}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.style("stroke-opacity",function(e){var t=E(C(e));return t<0||t>B?0:1}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.exit().remove();var tt=G.selectAll(".nv-indexLine").data([M]);tt.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(F),tt.attr("transform",function(e){return"translate("+O(e.i)+",0)"}).attr("height",B),h&&(n.scale(w).ticks(Math.min(b[0].values.length,H/70)).tickSize(-B,0),J.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),d3.transition(J.select(".nv-x.nv-axis")).call(n)),p&&(r.scale(E).ticks(B/36).tickSize(-H,0),d3.transition(J.select(".nv-y.nv-axis")).call(r)),J.select(".nv-background rect").on("click",function(){M.x=d3.mouse(this)[0],M.i=Math.round(O.invert(M.x)),x.index=M.i,k.stateChange(x),nt()}),t.dispatch.on("elementClick",function(e){M.i=e.pointIndex,M.x=O(M.i),x.index=M.i,k.stateChange(x),nt()}),s.dispatch.on("legendClick",function(e,t){e.disabled=!e.disabled,y=!e.disabled,x.rescaleY=y,k.stateChange(x),D.update()}),i.dispatch.on("stateChange",function(e){x.disabled=e.disabled,k.stateChange(x),D.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,f,l,c=[];b.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,D.x()),t.highlightPoint(r,f,!0);var o=n.values[f];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof l=="undefined"&&(l=D.xScale()(D.x()(o,f))),c.push({key:n.key,value:D.y()(o,f),color:a(n,n.seriesIndex)})});if(c.length>2){var h=D.yScale().invert(i.mouseY),p=Math.abs(D.yScale().domain()[0]-D.yScale().domain()[1]),d=.03*p,m=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);m!==null&&(c[m].highlight=!0)}var g=n.tickFormat()(D.x()(s,f),f);o.tooltip.position({left:l+u.left,top:i.mouseY+u.top}).chartContainer(A.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:g,series:c})(),o.renderGuideLine(l)}),o.dispatch.on("elementMouseout",function(e){k.tooltipHide(),t.clearHighlights()}),k.on("tooltipShow",function(e){v&&_(e,A.parentNode)}),k.on("changeState",function(e){typeof e.disabled!="undefined"&&(b.forEach(function(t,n){t.disabled=e.disabled[n]}),x.disabled=e.disabled),typeof e.index!="undefined"&&(M.i=e.index,M.x=O(M.i),x.index=e.index,tt.data([M])),typeof e.rescaleY!="undefined"&&(y=e.rescaleY),D.update()})}),D}function P(e,n){return n.map(function(n,r){if(!n.values)return n;var i=n.values[e];if(i==null)return n;var s=t.y()(i,e);return s<-0.95&&!A?(n.tempDisabled=!0,n):(n.tempDisabled=!1,n.values=n.values.map(function(e,n){return e.display={y:(t.y()(e,n)-s)/(1+s)},e}),n)})}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:30,bottom:50,left:60},a=e.utils.defaultColor(),f=null,l=null,c=!0,h=!0,p=!0,d=!1,v=!0,m=!0,g=!1,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},w,E,S=t.id(),x={index:0,rescaleY:y},T=null,N="No Data Available.",C=function(e){return e.average},k=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),L=0,A=!1;n.orient("bottom").tickPadding(7),r.orient(d?"right":"left"),s.updateState(!1);var O=d3.scale.linear(),M={i:0,x:0},_=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,D);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],k.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){k.tooltipHide(e)}),k.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),D.dispatch=k,D.lines=t,D.legend=i,D.xAxis=n,D.yAxis=r,D.interactiveLayer=o,d3.rebind(D,t,"defined","isArea","x","y","xScale","yScale","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id"),D.options=e.utils.optionsFunc.bind(D),D.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,D):u},D.width=function(e){return arguments.length?(f=e,D):f},D.height=function(e){return arguments.length?(l=e,D):l},D.color=function(t){return arguments.length?(a=e.utils.getColor(t),i.color(a),D):a},D.rescaleY=function(e){return arguments.length?(y=e,D):y},D.showControls=function(e){return arguments.length?(m=e,D):m},D.useInteractiveGuideline=function(e){return arguments.length?(g=e,e===!0&&(D.interactive(!1),D.useVoronoi(!1)),D):g},D.showLegend=function(e){return arguments.length?(c=e,D):c},D.showXAxis=function(e){return arguments.length?(h=e,D):h},D.showYAxis=function(e){return arguments.length?(p=e,D):p},D.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),D):d},D.tooltips=function(e){return arguments.length?(v=e,D):v},D.tooltipContent=function(e){return arguments.length?(b=e,D):b},D.state=function(e){return arguments.length?(x=e,D):x},D.defaultState=function(e){return arguments.length?(T=e,D):T},D.noData=function(e){return arguments.length?(N=e,D):N},D.average=function(e){return arguments.length?(C=e,D):C},D.transitionDuration=function(e){return arguments.length?(L=e,D):L},D.noErrorCheck=function(e){return arguments.length?(A=e,D):A},D},e.models.discreteBar=function(){function E(e){return e.each(function(e){var i=n-t.left-t.right,E=r-t.top-t.bottom,S=d3.select(this);e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var T=p&&d?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0}})});s.domain(p||d3.merge(T).map(function(e){return e.x})).rangeBands(v||[0,i],.1),o.domain(d||d3.extent(d3.merge(T).map(function(e){return e.y}).concat(f))),c?o.range(m||[E-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(m||[E,0]),b=b||s,w=w||o.copy().range([o(0),o(0)]);var N=S.selectAll("g.nv-wrap.nv-discretebar").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-groups"),N.attr("transform","translate("+t.left+","+t.top+")");var A=N.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),A.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),A.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),A.style("stroke-opacity",1).style("fill-opacity",.75);var O=A.selectAll("g.nv-bar").data(function(e){return e.values});O.exit().remove();var M=O.enter().append("g").attr("transform",function(e,t,n){return"translate("+(s(u(e,t))+s.rangeBand()*.05)+", "+o(0)+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),g.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),g.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){g.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){g.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()});M.append("rect").attr("height",0).attr("width",s.rangeBand()*.9/e.length),c?(M.append("text").attr("text-anchor","middle"),O.select("text").text(function(e,t){return h(a(e,t))}).attr("x",s.rangeBand()*.9/2).attr("y",function(e,t){return a(e,t)<0?o(a(e,t))-o(0)+12:-4})):O.selectAll("text").remove(),O.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(e,t){return e.color||l(e,t)}).style("stroke",function(e,t){return e.color||l(e,t)}).select("rect").attr("class",y).attr("width",s.rangeBand()*.9/e.length),O.attr("transform",function(e,t){var n=s(u(e,t))+s.rangeBand()*.05,r=a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t));return"translate("+n+", "+r+")"}).select("rect").attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(d&&d[0]||0))||1)}),b=s.copy(),w=o.copy()}),E}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=!1,h=d3.format(",.2f"),p,d,v,m,g=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),y="discreteBar",b,w;return E.dispatch=g,E.options=e.utils.optionsFunc.bind(E),E.x=function(e){return arguments.length?(u=e,E):u},E.y=function(e){return arguments.length?(a=e,E):a},E.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.xScale=function(e){return arguments.length?(s=e,E):s},E.yScale=function(e){return arguments.length?(o=e,E):o},E.xDomain=function(e){return arguments.length?(p=e,E):p},E.yDomain=function(e){return arguments.length?(d=e,E):d},E.xRange=function(e){return arguments.length?(v=e,E):v},E.yRange=function(e){return arguments.length?(m=e,E):m},E.forceY=function(e){return arguments.length?(f=e,E):f},E.color=function(t){return arguments.length?(l=e.utils.getColor(t),E):l},E.id=function(e){return arguments.length?(i=e,E):i},E.showValues=function(e){return arguments.length?(c=e,E):c},E.valueFormat=function(e){return arguments.length?(h=e,E):h},E.rectClass=function(e){return arguments.length?(y=e,E):y},E},e.models.discreteBarChart=function(){function w(e){return e.each(function(e){var u=d3.select(this),p=this,y=(s||parseInt(u.style("width"))||960)-i.left-i.right,E=(o||parseInt(u.style("height"))||400)-i.top-i.bottom;w.update=function(){g.beforeUpdate(),u.call(w)},w.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var S=u.selectAll(".nv-noData").data([m]);return S.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),S.attr("x",i.left+y/2).attr("y",i.top+E/2).text(function(e){return e}),w}u.selectAll(".nv-noData").remove(),d=t.xScale(),v=t.yScale().clamp(!0);var T=u.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),C=N.append("defs"),k=T.select("g");N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),N.append("g").attr("class","nv-barsWrap"),k.attr("transform","translate("+i.left+","+i.top+")"),l&&k.select(".nv-y.nv-axis").attr("transform","translate("+y+",0)"),t.width(y).height(E);var L=k.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));L.call(t),C.append("clipPath").attr("id","nv-x-label-clip-"+t.id()).append("rect"),k.select("#nv-x-label-clip-"+t.id()+" rect").attr("width",d.rangeBand()*(c?2:1)).attr("height",16).attr("x",-d.rangeBand()/(c?1:2));if(a){n.scale(d).ticks(y/100).tickSize(-E,0),k.select(".nv-x.nv-axis").attr("transform","translate(0,"+(v.range()[0]+(t.showValues()&&v.domain()[0]<0?16:0))+")"),k.select(".nv-x.nv-axis").call(n);var A=k.select(".nv-x.nv-axis").selectAll("g");c&&A.selectAll("text").attr("transform",function(e,t,n){return"translate(0,"+(n%2==0?"5":"17")+")"})}f&&(r.scale(v).ticks(E/36).tickSize(-y,0),k.select(".nv-y.nv-axis").call(r)),k.select(".nv-zeroLine line").attr("x1",0).attr("x2",y).attr("y1",v(0)).attr("y2",v(0)),g.on("tooltipShow",function(e){h&&b(e,p.parentNode)})}),w}var t=e.models.discreteBar(),n=e.models.axis(),r=e.models.axis(),i={top:15,right:10,bottom:50,left:60},s=null,o=null,u=e.utils.getColor(),a=!0,f=!0,l=!1,c=!1,h=!0,p=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},d,v,m="No Data Available.",g=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate"),y=0;n.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(l?"right":"left").tickFormat(d3.format(",.1f"));var b=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=p(i.series.key,a,f,i,w);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+i.left,e.pos[1]+i.top],g.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){g.tooltipHide(e)}),g.on("tooltipHide",function(){h&&e.tooltip.cleanup()}),w.dispatch=g,w.discretebar=t,w.xAxis=n,w.yAxis=r,d3.rebind(w,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","id","showValues","valueFormat"),w.options=e.utils.optionsFunc.bind(w),w.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,w):i},w.width=function(e){return arguments.length?(s=e,w):s},w.height=function(e){return arguments.length?(o=e,w):o},w.color=function(n){return arguments.length?(u=e.utils.getColor(n),t.color(u),w):u},w.showXAxis=function(e){return arguments.length?(a=e,w):a},w.showYAxis=function(e){return arguments.length?(f=e,w):f},w.rightAlignYAxis=function(e){return arguments.length?(l=e,r.orient(e?"right":"left"),w):l},w.staggerLabels=function(e){return arguments.length?(c=e,w):c},w.tooltips=function(e){return arguments.length?(h=e,w):h},w.tooltipContent=function(e){return arguments.length?(p=e,w):p},w.noData=function(e){return arguments.length?(m=e,w):m},w.transitionDuration=function(e){return arguments.length?(y=e,w):y},w},e.models.distribution=function(){function l(e){return e.each(function(e){var a=n-(i==="x"?t.left+t.right:t.top+t.bottom),l=i=="x"?"y":"x",c=d3.select(this);f=f||u;var h=c.selectAll("g.nv-distribution").data([e]),p=h.enter().append("g").attr("class","nvd3 nv-distribution"),d=p.append("g"),v=h.select("g");h.attr("transform","translate("+t.left+","+t.top+")");var m=v.selectAll("g.nv-dist").data(function(e){return e},function(e){return e.key});m.enter().append("g"),m.attr("class",function(e,t){return"nv-dist nv-series-"+t}).style("stroke",function(e,t){return o(e,t)});var g=m.selectAll("line.nv-dist"+i).data(function(e){return e.values});g.enter().append("line").attr(i+"1",function(e,t){return f(s(e,t))}).attr(i+"2",function(e,t){return f(s(e,t))}),m.exit().selectAll("line.nv-dist"+i).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}).style("stroke-opacity",0).remove(),g.attr("class",function(e,t){return"nv-dist"+i+" nv-dist"+i+"-"+t}).attr(l+"1",0).attr(l+"2",r),g.attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}),f=u.copy()}),l}var t={top:0,right:0,bottom:0,left:0},n=400,r=8,i="x",s=function(e){return e[i]},o=e.utils.defaultColor(),u=d3.scale.linear(),a,f;return l.options=e.utils.optionsFunc.bind(l),l.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,l):t},l.width=function(e){return arguments.length?(n=e,l):n},l.axis=function(e){return arguments.length?(i=e,l):i},l.size=function(e){return arguments.length?(r=e,l):r},l.getData=function(e){return arguments.length?(s=d3.functor(e),l):s},l.scale=function(e){return arguments.length?(u=e,l):u},l.color=function(t){return arguments.length?(o=e.utils.getColor(t),l):o},l},e.models.historicalBarChart=function(){function x(e){return e.each(function(d){var E=d3.select(this),T=this,N=(u||parseInt(E.style("width"))||960)-s.left-s.right,C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom;x.update=function(){E.call(x)},x.container=this,g.disabled=d.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!d||!d.length||!d.filter(function(e){return e.values.length}).length){var L=E.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",s.left+N/2).attr("y",s.top+C/2).text(function(e){return e}),x}E.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();var A=E.selectAll("g.nv-wrap.nv-historicalBarChart").data([d]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),M=A.select("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-barsWrap"),O.append("g").attr("class","nv-legendWrap"),f&&(i.width(N),M.select(".nv-legendWrap").datum(d).call(i),s.top!=i.height()&&(s.top=i.height(),C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom),A.select(".nv-legendWrap").attr("transform","translate(0,"+ -s.top+")")),A.attr("transform","translate("+s.left+","+s.top+")"),h&&M.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)"),t.width(N).height(C).color(d.map(function(e,t){return e.color||o(e,t)}).filter(function(e,t){return!d[t].disabled}));var _=M.select(".nv-barsWrap").datum(d.filter(function(e){return!e.disabled}));_.call(t),l&&(n.scale(v).tickSize(-C,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+m.range()[0]+")"),M.select(".nv-x.nv-axis").call(n)),c&&(r.scale(m).ticks(C/36).tickSize(-N,0),M.select(".nv-y.nv-axis").call(r)),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,d.filter(function(e){return!e.disabled}).length||d.map(function(e){return e.disabled=!1,A.selectAll(".nv-series").classed("disabled",!1),e}),g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),e.call(x)}),i.dispatch.on("legendDblclick",function(e){d.forEach(function(e){e.disabled=!0}),e.disabled=!1,g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),x.update()}),w.on("tooltipShow",function(e){p&&S(e,T.parentNode)}),w.on("changeState",function(e){typeof e.disabled!="undefined"&&(d.forEach(function(t,n){t.disabled=e.disabled[n]}),g.disabled=e.disabled),x.update()})}),x}var t=e.models.historicalBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s={top:30,right:90,bottom:50,left:90},o=e.utils.defaultColor(),u=null,a=null,f=!1,l=!0,c=!0,h=!1,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},v,m,g={},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=0;n.orient("bottom").tickPadding(7),r.orient(h?"right":"left");var S=function(i,s){if(s){var o=d3.select(s).select("svg"),u=o.node()?o.attr("viewBox"):null;if(u){u=u.split(" ");var a=parseInt(o.style("width"))/u[2];i.pos[0]=i.pos[0]*a,i.pos[1]=i.pos[1]*a}}var f=i.pos[0]+(s.offsetLeft||0),l=i.pos[1]+(s.offsetTop||0),c=n.tickFormat()(t.x()(i.point,i.pointIndex)),h=r.tickFormat()(t.y()(i.point,i.pointIndex)),p=d(i.series.key,c,h,i,x);e.tooltip.show([f,l],p,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+s.left,e.pos[1]+s.top],w.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){p&&e.tooltip.cleanup()}),x.dispatch=w,x.bars=t,x.legend=i,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate","highlightPoint","clearHighlights","interactive"),x.options=e.utils.optionsFunc.bind(x),x.margin=function(e){return arguments.length?(s.top=typeof e.top!="undefined"?e.top:s.top,s.right=typeof e.right!="undefined"?e.right:s.right,s.bottom=typeof e.bottom!="undefined"?e.bottom:s.bottom,s.left=typeof e.left!="undefined"?e.left:s.left,x):s},x.width=function(e){return arguments.length?(u=e,x):u},x.height=function(e){return arguments.length?(a=e,x):a},x.color=function(t){return arguments.length?(o=e.utils.getColor(t),i.color(o),x):o},x.showLegend=function(e){return arguments.length?(f=e,x):f},x.showXAxis=function(e){return arguments.length?(l=e,x):l},x.showYAxis=function(e){return arguments.length?(c=e,x):c},x.rightAlignYAxis=function(e){return arguments.length?(h=e,r.orient(e?"right":"left"),x):h},x.tooltips=function(e){return arguments.length?(p=e,x):p},x.tooltipContent=function(e){return arguments.length?(d=e,x):d},x.state=function(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments.length?(b=e,x):b},x.transitionDuration=function(e){return arguments.length?(E=e,x):E},x},e.models.indentedTree=function(){function g(e){return e.each(function(e){function k(e,t,n){d3.event.stopPropagation();if(d3.event.shiftKey&&!n)return d3.event.shiftKey=!1,e.values&&e.values.forEach(function(e){(e.values||e._values)&&k(e,0,!0)}),!0;if(!O(e))return!0;e.values?(e._values=e.values,e.values=null):(e.values=e._values,e._values=null),g.update()}function L(e){return e._values&&e._values.length?h:e.values&&e.values.length?p:""}function A(e){return e._values&&e._values.length}function O(e){var t=e.values||e._values;return t&&t.length}var t=1,n=d3.select(this),i=d3.layout.tree().children(function(e){return e.values}).size([r,f]);g.update=function(){n.call(g)},e[0]||(e[0]={key:a});var s=i.nodes(e[0]),y=d3.select(this).selectAll("div").data([[s]]),b=y.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),w=b.append("table"),E=y.select("table").attr("width","100%").attr("class",c);if(o){var S=w.append("thead"),x=S.append("tr");l.forEach(function(e){x.append("th").attr("width",e.width?e.width:"10%").style("text-align",e.type=="numeric"?"right":"left").append("span").text(e.label)})}var T=E.selectAll("tbody").data(function(e){return e});T.enter().append("tbody"),t=d3.max(s,function(e){return e.depth}),i.size([r,t*f]);var N=T.selectAll("tr").data(function(e){return e.filter(function(e){return u&&!e.children?u(e):!0})},function(e,t){return e.id||e.id||++m});N.exit().remove(),N.select("img.nv-treeicon").attr("src",L).classed("folded",A);var C=N.enter().append("tr");l.forEach(function(e,t){var n=C.append("td").style("padding-left",function(e){return(t?0:e.depth*f+12+(L(e)?0:16))+"px"},"important").style("text-align",e.type=="numeric"?"right":"left");t==0&&n.append("img").classed("nv-treeicon",!0).classed("nv-folded",A).attr("src",L).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(e){return L(e)?"inline-block":"none"}).on("click",k),n.each(function(n){!t&&v(n)?d3.select(this).append("a").attr("href",v).attr("class",d3.functor(e.classes)).append("span"):d3.select(this).append("span"),d3.select(this).select("span").attr("class",d3.functor(e.classes)).text(function(t){return e.format?t[e.key]?e.format(t[e.key]):"-":t[e.key]||"-"})}),e.showCount&&(n.append("span").attr("class","nv-childrenCount"),N.selectAll("span.nv-childrenCount").text(function(e){return e.values&&e.values.length||e._values&&e._values.length?"("+(e.values&&e.values.filter(function(e){return u?u(e):!0}).length||e._values&&e._values.filter(function(e){return u?u(e):!0}).length||0)+")":""}))}),N.order().on("click",function(e){d.elementClick({row:this,data:e,pos:[e.x,e.y]})}).on("dblclick",function(e){d.elementDblclick({row:this,data:e,pos:[e.x,e.y]})}).on("mouseover",function(e){d.elementMouseover({row:this,data:e,pos:[e.x,e.y]})}).on("mouseout",function(e){d.elementMouseout({row:this,data:e,pos:[e.x,e.y]})})}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e4),o=!0,u=!1,a="No Data Available.",f=20,l=[{key:"key",label:"Name",type:"text"}],c=null,h="images/grey-plus.png",p="images/grey-minus.png",d=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),v=function(e){return e.url},m=0;return g.options=e.utils.optionsFunc.bind(g),g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),scatter.color(i),g):i},g.id=function(e){return arguments.length?(s=e,g):s},g.header=function(e){return arguments.length?(o=e,g):o},g.noData=function(e){return arguments.length?(a=e,g):a},g.filterZero=function(e){return arguments.length?(u=e,g):u},g.columns=function(e){return arguments.length?(l=e,g):l},g.tableClass=function(e){return arguments.length?(c=e,g):c},g.iconOpen=function(e){return arguments.length?(h=e,g):h},g.iconClose=function(e){return arguments.length?(p=e,g):p},g.getUrl=function(e){return arguments.length?(v=e,g):v},g},e.models.legend=function(){function c(h){return h.each(function(c){var h=n-t.left-t.right,p=d3.select(this),d=p.selectAll("g.nv-legend").data([c]),v=d.enter().append("g").attr("class","nvd3 nv-legend").append("g"),m=d.select("g");d.attr("transform","translate("+t.left+","+t.top+")");var g=m.selectAll(".nv-series").data(function(e){return e}),y=g.enter().append("g").attr("class","nv-series").on("mouseover",function(e,t){l.legendMouseover(e,t)}).on("mouseout",function(e,t){l.legendMouseout(e,t)}).on("click",function(e,t){l.legendClick(e,t),a&&(f?(c.forEach(function(e){e.disabled=!0}),e.disabled=!1):(e.disabled=!e.disabled,c.every(function(e){return e.disabled})&&c.forEach(function(e){e.disabled=!1})),l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))}).on("dblclick",function(e,t){l.legendDblclick(e,t),a&&(c.forEach(function(e){e.disabled=!0}),e.disabled=!1,l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))});y.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),y.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8"),g.classed("disabled",function(e){return e.disabled}),g.exit().remove(),g.select("circle").style("fill",function(e,t){return e.color||s(e,t)}).style("stroke",function(e,t){return e.color||s(e,t)}),g.select("text").text(i);if(o){var b=[];g.each(function(t,n){var r=d3.select(this).select("text"),i;try{i=r.getComputedTextLength();if(i<=0)throw Error()}catch(s){i=e.utils.calcApproxTextWidth(r)}b.push(i+28)});var w=0,E=0,S=[];while(E<h&&w<b.length)S[w]=b[w],E+=b[w++];w===0&&(w=1);while(E>h&&w>1){S=[],w--;for(var x=0;x<b.length;x++)b[x]>(S[x%w]||0)&&(S[x%w]=b[x]);E=S.reduce(function(e,t,n,r){return e+t})}var T=[];for(var N=0,C=0;N<w;N++)T[N]=C,C+=S[N];g.attr("transform",function(e,t){return"translate("+T[t%w]+","+(5+Math.floor(t/w)*20)+")"}),u?m.attr("transform","translate("+(n-t.right-E)+","+t.top+")"):m.attr("transform","translate(0,"+t.top+")"),r=t.top+t.bottom+Math.ceil(b.length/w)*20}else{var k=5,L=5,A=0,O;g.attr("transform",function(e,r){var i=d3.select(this).select("text").node().getComputedTextLength()+28;return O=L,n<t.left+t.right+O+i&&(L=O=5,k+=20),L+=i,L>A&&(A=L),"translate("+O+","+k+")"}),m.attr("transform","translate("+(n-t.right-A)+","+t.top+")"),r=t.top+t.bottom+k+15}}),c}var t={top:5,right:0,bottom:5,left:0},n=400,r=20,i=function(e){return e.key},s=e.utils.defaultColor(),o=!0,u=!0,a=!0,f=!1,l=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange");return c.dispatch=l,c.options=e.utils.optionsFunc.bind(c),c.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,c):t},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.key=function(e){return arguments.length?(i=e,c):i},c.color=function(t){return arguments.length?(s=e.utils.getColor(t),c):s},c.align=function(e){return arguments.length?(o=e,c):o},c.rightAlign=function(e){return arguments.length?(u=e,c):u},c.updateState=function(e){return arguments.length?(a=e,c):a},c.radioButtonMode=function(e){return arguments.length?(f=e,c):f},c},e.models.line=function(){function m(g){return g.each(function(m){var g=r-n.left-n.right,b=i-n.top-n.bottom,w=d3.select(this);c=t.xScale(),h=t.yScale(),d=d||c,v=v||h;var E=w.selectAll("g.nv-wrap.nv-line").data([m]),S=E.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),T=S.append("defs"),N=S.append("g"),C=E.select("g");N.append("g").attr("class","nv-groups"),N.append("g").attr("class","nv-scatterWrap"),E.attr("transform","translate("+n.left+","+n.top+")"),t.width(g).height(b);var k=E.select(".nv-scatterWrap");k.call(t),T.append("clipPath").attr("id","nv-edge-clip-"+t.id()).append("rect"),E.select("#nv-edge-clip-"+t.id()+" rect").attr("width",g).attr("height",b>0?b:0),C.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":""),k.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":"");var L=E.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});L.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),L.exit().remove(),L.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return s(e,t)}).style("stroke",function(e,t){return s(e,t)}),L.style("stroke-opacity",1).style("fill-opacity",.5);var A=L.selectAll("path.nv-area").data(function(e){return f(e)?[e]:[]});A.enter().append("path").attr("class","nv-area").attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])}),L.exit().selectAll("path.nv-area").remove(),A.attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))}).y1(function(e,t){return h(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])});var O=L.selectAll("path.nv-line").data(function(e){return[e.values]});O.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))})),O.attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))})),d=c.copy(),v=h.copy()}),m}var t=e.models.scatter(),n={top:0,right:0,bottom:0,left:0},r=960,i=500,s=e.utils.defaultColor(),o=function(e){return e.x},u=function(e){return e.y},a=function(e,t){return!isNaN(u(e,t))&&u(e,t)!==null},f=function(e){return e.area},l=!1,c,h,p="linear";t.size(16).sizeDomain([16,256]);var d,v;return m.dispatch=t.dispatch,m.scatter=t,d3.rebind(m,t,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","padData","highlightPoint","clearHighlights"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.height=function(e){return arguments.length?(i=e,m):i},m.x=function(e){return arguments.length?(o=e,t.x(e),m):o},m.y=function(e){return arguments.length?(u=e,t.y(e),m):u},m.clipEdge=function(e){return arguments.length?(l=e,m):l},m.color=function(n){return arguments.length?(s=e.utils.getColor(n),t.color(s),m):s},m.interpolate=function(e){return arguments.length?(p=e,m):p},m.defined=function(e){return arguments.length?(a=e,m):a},m.isArea=function(e){return arguments.length?(f=d3.functor(e),m):f},m},e.models.lineChart=function(){function N(m){return m.each(function(m){var x=d3.select(this),C=this,k=(a||parseInt(x.style("width"))||960)-o.left-o.right,L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom;N.update=function(){x.call(N)},N.container=this,b.disabled=m.map(function(e){return!!e.disabled});if(!w){var A;w={};for(A in b)b[A]instanceof Array?w[A]=b[A].slice(0):w[A]=b[A]}if(!m||!m.length||!m.filter(function(e){return e.values.length}).length){var O=x.selectAll(".nv-noData").data([E]);return O.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),O.attr("x",o.left+k/2).attr("y",o.top+L/2).text(function(e){return e}),N}x.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var M=x.selectAll("g.nv-wrap.nv-lineChart").data([m]),_=M.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),D=M.select("g");_.append("rect").style("opacity",0),_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y nv-axis"),_.append("g").attr("class","nv-linesWrap"),_.append("g").attr("class","nv-legendWrap"),_.append("g").attr("class","nv-interactive"),D.select("rect").attr("width",k).attr("height",L>0?L:0),l&&(i.width(k),D.select(".nv-legendWrap").datum(m).call(i),o.top!=i.height()&&(o.top=i.height(),L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate(0,"+ -o.top+")")),M.attr("transform","translate("+o.left+","+o.top+")"),p&&D.select(".nv-y.nv-axis").attr("transform","translate("+k+",0)"),d&&(s.width(k).height(L).margin({left:o.left,top:o.top}).svgContainer(x).xScale(g),M.select(".nv-interactive").call(s)),t.width(k).height(L).color(m.map(function(e,t){return e.color||u(e,t)}).filter(function(e,t){return!m[t].disabled}));var P=D.select(".nv-linesWrap").datum(m.filter(function(e){return!e.disabled}));P.call(t),c&&(n.scale(g).ticks(k/100).tickSize(-L,0),D.select(".nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),D.select(".nv-x.nv-axis").call(n)),h&&(r.scale(y).ticks(L/36).tickSize(-k,0),D.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),N.update()}),s.dispatch.on("elementMousemove",function(i){t.clearHighlights();var a,f,l,c=[];m.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,N.x()),t.highlightPoint(r,f,!0);var s=n.values[f];if(typeof s=="undefined")return;typeof a=="undefined"&&(a=s),typeof l=="undefined"&&(l=N.xScale()(N.x()(s,f))),c.push({key:n.key,value:N.y()(s,f),color:u(n,n.seriesIndex)})});if(c.length>2){var h=N.yScale().invert(i.mouseY),p=Math.abs(N.yScale().domain()[0]-N.yScale().domain()[1]),d=.03*p,g=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);g!==null&&(c[g].highlight=!0)}var y=n.tickFormat()(N.x()(a,f));s.tooltip.position({left:l+o.left,top:i.mouseY+o.top}).chartContainer(C.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:y,series:c})(),s.renderGuideLine(l)}),s.dispatch.on("elementMouseout",function(e){S.tooltipHide(),t.clearHighlights()}),S.on("tooltipShow",function(e){v&&T(e,C.parentNode)}),S.on("changeState",function(e){typeof e.disabled!="undefined"&&m.length===e.disabled.length&&(m.forEach(function(t,n){t.disabled=e.disabled[n]}),b.disabled=e.disabled),N.update()})}),N}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.interactiveGuideline(),o={top:30,right:20,bottom:50,left:60},u=e.utils.defaultColor(),a=null,f=null,l=!0,c=!0,h=!0,p=!1,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=0;n.orient("bottom").tickPadding(7),r.orient(p?"right":"left");var T=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,N);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),N.dispatch=S,N.lines=t,N.legend=i,N.xAxis=n,N.yAxis=r,N.interactiveLayer=s,d3.rebind(N,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id","interpolate"),N.options=e.utils.optionsFunc.bind(N),N.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,N):o},N.width=function(e){return arguments.length?(a=e,N):a},N.height=function(e){return arguments.length?(f=e,N):f},N.color=function(t){return arguments.length?(u=e.utils.getColor(t),i.color(u),N):u},N.showLegend=function(e){return arguments.length?(l=e,N):l},N.showXAxis=function(e){return arguments.length?(c=e,N):c},N.showYAxis=function(e){return arguments.length?(h=e,N):h},N.rightAlignYAxis=function(e){return arguments.length?(p=e,r.orient(e?"right":"left"),N):p},N.useInteractiveGuideline=function(e){return arguments.length?(d=e,e===!0&&(N.interactive(!1),N.useVoronoi(!1)),N):d},N.tooltips=function(e){return arguments.length?(v=e,N):v},N.tooltipContent=function(e){return arguments.length?(m=e,N):m},N.state=function(e){return arguments.length?(b=e,N):b},N.defaultState=function(e){return arguments.length?(w=e,N):w},N.noData=function(e){return arguments.length?(E=e,N):E},N.transitionDuration=function(e){return arguments.length?(x=e,N):x},N},e.models.linePlusBarChart=function(){function T(e){return e.each(function(e){var l=d3.select(this),c=this,v=(a||parseInt(l.style("width"))||960)-u.left-u.right,N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom;T.update=function(){l.call(T)},b.disabled=e.map(function(e){return!!e.disabled});if(!w){var C;w={};for(C in b)b[C]instanceof Array?w[C]=b[C].slice(0):w[C]=b[C]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var k=l.selectAll(".nv-noData").data([E]);return k.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),k.attr("x",u.left+v/2).attr("y",u.top+N/2).text(function(e){return e}),T}l.selectAll(".nv-noData").remove();var L=e.filter(function(e){return!e.disabled&&e.bar}),A=e.filter(function(e){return!e.bar});m=A.filter(function(e){return!e.disabled}).length&&A.filter(function(e){return!e.disabled})[0].values.length?t.xScale():n.xScale(),g=n.yScale(),y=t.yScale();var O=d3.select(this).selectAll("g.nv-wrap.nv-linePlusBar").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y1 nv-axis"),M.append("g").attr("class","nv-y2 nv-axis"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-linesWrap"),M.append("g").attr("class","nv-legendWrap"),p&&(o.width(v/2),_.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(o),u.top!=o.height()&&(u.top=o.height(),N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom),_.select(".nv-legendWrap").attr("transform","translate("+v/2+","+ -u.top+")")),O.attr("transform","translate("+u.left+","+u.top+")"),t.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar})),n.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar}));var D=_.select(".nv-barsWrap").datum(L.length?L:[{values:[]}]),P=_.select(".nv-linesWrap").datum(A[0]&&!A[0].disabled?A:[{values:[]}]);d3.transition(D).call(n),d3.transition(P).call(t),r.scale(m).ticks(v/100).tickSize(-N,0),_.select(".nv-x.nv-axis").attr("transform","translate(0,"+g.range()[0]+")"),d3.transition(_.select(".nv-x.nv-axis")).call(r),i.scale(g).ticks(N/36).tickSize(-v,0),d3.transition(_.select(".nv-y1.nv-axis")).style("opacity",L.length?1:0).call(i),s.scale(y).ticks(N/36).tickSize(L.length?0:-v,0),_.select(".nv-y2.nv-axis").style("opacity",A.length?1:0).attr("transform","translate("+v+",0)"),d3.transition(_.select(".nv-y2.nv-axis")).call(s),o.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),T.update()}),S.on("tooltipShow",function(e){d&&x(e,c.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),b.disabled=t.disabled),T.update()})}),T}var t=e.models.line(),n=e.models.historicalBar(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.legend(),u={top:30,right:60,bottom:50,left:60},a=null,f=null,l=function(e){return e.x},c=function(e){return e.y},h=e.utils.defaultColor(),p=!0,d=!0,v=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},m,g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.padData(!0),t.clipEdge(!1).padData(!0),r.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),s.orient("right");var x=function(n,o){var u=n.pos[0]+(o.offsetLeft||0),a=n.pos[1]+(o.offsetTop||0),f=r.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?i:s).tickFormat()(t.y()(n.point,n.pointIndex)),c=v(n.series.key,f,l,n,T);e.tooltip.show([u,a],c,n.value<0?"n":"s",null,o)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),n.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),n.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){d&&e.tooltip.cleanup()}),T.dispatch=S,T.legend=o,T.lines=t,T.bars=n,T.xAxis=r,T.y1Axis=i,T.y2Axis=s,d3.rebind(T,t,"defined","size","clipVoronoi","interpolate"),T.options=e.utils.optionsFunc.bind(T),T.x=function(e){return arguments.length?(l=e,t.x(e),n.x(e),T):l},T.y=function(e){return arguments.length?(c=e,t.y(e),n.y(e),T):c},T.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,T):u},T.width=function(e){return arguments.length?(a=e,T):a},T.height=function(e){return arguments.length?(f=e,T):f},T.color=function(t){return arguments.length?(h=e.utils.getColor(t),o.color(h),T):h},T.showLegend=function(e){return arguments.length?(p=e,T):p},T.tooltips=function(e){return arguments.length?(d=e,T):d},T.tooltipContent=function(e){return arguments.length?(v=e,T):v},T.state=function(e){return arguments.length?(b=e,T):b},T.defaultState=function(e){return arguments.length?(w=e,T):w},T.noData=function(e){return arguments.length?(E=e,T):E},T},e.models.lineWithFocusChart=function(){function k(e){return e.each(function(e){function R(e){var t=+(e=="e"),n=t?1:-1,r=O/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function U(){a.empty()||a.extent(w),F.data([a.empty()?g.domain():w]).each(function(e,t){var n=g(e[0])-v.range()[0],r=v.range()[1]-g(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",g(e[1])).attr("width",r<0?0:r)})}function z(){w=a.empty()?null:a.extent();var n=a.empty()?g.domain():a.extent();if(Math.abs(n[0]-n[1])<=1)return;T.brush({extent:n,brush:a}),U();var s=P.select(".nv-focus .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}).map(function(e,r){return{key:e.key,values:e.values.filter(function(e,r){return t.x()(e,r)>=n[0]&&t.x()(e,r)<=n[1]})}}));s.call(t),P.select(".nv-focus .nv-x.nv-axis").call(r),P.select(".nv-focus .nv-y.nv-axis").call(i)}var S=d3.select(this),N=this,L=(h||parseInt(S.style("width"))||960)-f.left-f.right,A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d,O=d-l.top-l.bottom;k.update=function(){S.call(k)},k.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var M=S.selectAll(".nv-noData").data([x]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",f.left+L/2).attr("y",f.top+A/2).text(function(e){return e}),k}S.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale(),g=n.xScale(),y=n.yScale();var _=S.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([e]),D=_.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),P=_.select("g");D.append("g").attr("class","nv-legendWrap");var H=D.append("g").attr("class","nv-focus");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-linesWrap");var B=D.append("g").attr("class","nv-context");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-linesWrap"),B.append("g").attr("class","nv-brushBackground"),B.append("g").attr("class","nv-x nv-brush"),b&&(u.width(L),P.select(".nv-legendWrap").datum(e).call(u),f.top!=u.height()&&(f.top=u.height(),A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d),P.select(".nv-legendWrap").attr("transform","translate(0,"+ -f.top+")")),_.attr("transform","translate("+f.left+","+f.top+")"),t.width(L).height(A).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),n.defined(t.defined()).width(L).height(O).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),P.select(".nv-context").attr("transform","translate(0,"+(A+f.bottom+l.top)+")");var j=P.select(".nv-context .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}));d3.transition(j).call(n),r.scale(v).ticks(L/100).tickSize(-A,0),i.scale(m).ticks(A/36).tickSize(-L,0),P.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+A+")"),a.x(g).on("brush",function(){var e=k.transitionDuration();k.transitionDuration(0),z(),k.transitionDuration(e)}),w&&a.extent(w);var F=P.select(".nv-brushBackground").selectAll("g").data([w||a.extent()]),I=F.enter().append("g");I.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",O),I.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",O);var q=P.select(".nv-x.nv-brush").call(a);q.selectAll("rect").attr("height",O),q.selectAll(".resize").append("path").attr("d",R),z(),s.scale(g).ticks(L/100).tickSize(-O,0),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.transition(P.select(".nv-context .nv-x.nv-axis")).call(s),o.scale(y).ticks(O/36).tickSize(-L,0),d3.transition(P.select(".nv-context .nv-y.nv-axis")).call(o),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),u.dispatch.on("stateChange",function(e){k.update()}),T.on("tooltipShow",function(e){E&&C(e,N.parentNode)})}),k}var t=e.models.line(),n=e.models.line(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.axis(),u=e.models.legend(),a=d3.svg.brush(),f={top:30,right:30,bottom:30,left:60},l={top:0,right:30,bottom:20,left:60},c=e.utils.defaultColor(),h=null,p=null,d=100,v,m,g,y,b=!0,w=null,E=!0,S=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},x="No Data Available.",T=d3.dispatch("tooltipShow","tooltipHide","brush"),N=0;t.clipEdge(!0),n.interactive(!1),r.orient("bottom").tickPadding(5),i.orient("left"),s.orient("bottom").tickPadding(5),o.orient("left");var C=function(n,s){var o=n.pos[0]+(s.offsetLeft||0),u=n.pos[1]+(s.offsetTop||0),a=r.tickFormat()(t.x()(n.point,n.pointIndex)),f=i.tickFormat()(t.y()(n.point,n.pointIndex)),l=S(n.series.key,a,f,n,k);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+f.left,e.pos[1]+f.top],T.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){E&&e.tooltip.cleanup()}),k.dispatch=T,k.legend=u,k.lines=t,k.lines2=n,k.xAxis=r,k.yAxis=i,k.x2Axis=s,k.y2Axis=o,d3.rebind(k,t,"defined","isArea","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),k.options=e.utils.optionsFunc.bind(k),k.x=function(e){return arguments.length?(t.x(e),n.x(e),k):t.x},k.y=function(e){return arguments.length?(t.y(e),n.y(e),k):t.y},k.margin=function(e){return arguments.length?(f.top=typeof e.top!="undefined"?e.top:f.top,f.right=typeof e.right!="undefined"?e.right:f.right,f.bottom=typeof e.bottom!="undefined"?e.bottom:f.bottom,f.left=typeof e.left!="undefined"?e.left:f.left,k):f},k.margin2=function(e){return arguments.length?(l=e,k):l},k.width=function(e){return arguments.length?(h=e,k):h},k.height=function(e){return arguments.length?(p=e,k):p},k.height2=function(e){return arguments.length?(d=e,k):d},k.color=function(t){return arguments.length?(c=e.utils.getColor(t),u.color(c),k):c},k.showLegend=function(e){return arguments.length?(b=e,k):b},k.tooltips=function(e){return arguments.length?(E=e,k):E},k.tooltipContent=function(e){return arguments.length?(S=e,k):S},k.interpolate=function(e){return arguments.length?(t.interpolate(e),n.interpolate(e),k):t.interpolate()},k.noData=function(e){return arguments.length?(x=e,k):x},k.xTickFormat=function(e){return arguments.length?(r.tickFormat(e),s.tickFormat(e),k):r.tickFormat()},k.yTickFormat=function(e){return arguments.length?(i.tickFormat(e),o.tickFormat(e),k):i.tickFormat()},k.brushExtent=function(e){return arguments.length?(w=e,k):w},k.transitionDuration=function(e){return arguments.length?(N=e,k):N},k},e.models.linePlusBarWithFocusChart=function(){function B(e){return e.each(function(e){function tt(e){var t=+(e=="e"),n=t?1:-1,r=I/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function nt(){h.empty()||h.extent(x),Y.data([h.empty()?k.domain():x]).each(function(e,t){var n=k(e[0])-k.range()[0],r=k.range()[1]-k(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",k(e[1])).attr("width",r<0?0:r)})}function rt(){x=h.empty()?null:h.extent(),S=h.empty()?k.domain():h.extent(),D.brush({extent:S,brush:h}),nt(),r.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),t.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var n=$.select(".nv-focus .nv-barsWrap").datum(R.length?R.map(function(e,t){return{key:e.key,values:e.values.filter(function(e,t){return r.x()(e,t)>=S[0]&&r.x()(e,t)<=S[1]})}}):[{values:[]}]),i=$.select(".nv-focus .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U.map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=S[0]&&t.x()(e,n)<=S[1]})}}));R.length?C=r.xScale():C=t.xScale(),s.scale(C).ticks(j/100).tickSize(-F,0),s.domain([Math.ceil(S[0]),Math.floor(S[1])]),$.select(".nv-x.nv-axis").call(s),n.call(r),i.call(t),$.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L.range()[0]+")"),u.scale(L).ticks(F/36).tickSize(-j,0),$.select(".nv-focus .nv-y1.nv-axis").style("opacity",R.length?1:0),a.scale(A).ticks(F/36).tickSize(R.length?0:-j,0),$.select(".nv-focus .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+C.range()[1]+",0)"),$.select(".nv-focus .nv-y1.nv-axis").call(u),$.select(".nv-focus .nv-y2.nv-axis").call(a)}var N=d3.select(this),P=this,j=(v||parseInt(N.style("width"))||960)-p.left-p.right,F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g,I=g-d.top-d.bottom;B.update=function(){N.call(B)},B.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=N.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",p.left+j/2).attr("y",p.top+F/2).text(function(e){return e}),B}N.selectAll(".nv-noData").remove();var R=e.filter(function(e){return!e.disabled&&e.bar}),U=e.filter(function(e){return!e.bar});C=r.xScale(),k=o.scale(),L=r.yScale(),A=t.yScale(),O=i.yScale(),M=n.yScale();var z=e.filter(function(e){return!e.disabled&&e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})}),W=e.filter(function(e){return!e.disabled&&!e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})});C.range([0,j]),k.domain(d3.extent(d3.merge(z.concat(W)),function(e){return e.x})).range([0,j]);var X=N.selectAll("g.nv-wrap.nv-linePlusBar").data([e]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),$=X.select("g");V.append("g").attr("class","nv-legendWrap");var J=V.append("g").attr("class","nv-focus");J.append("g").attr("class","nv-x nv-axis"),J.append("g").attr("class","nv-y1 nv-axis"),J.append("g").attr("class","nv-y2 nv-axis"),J.append("g").attr("class","nv-barsWrap"),J.append("g").attr("class","nv-linesWrap");var K=V.append("g").attr("class","nv-context");K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y1 nv-axis"),K.append("g").attr("class","nv-y2 nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-linesWrap"),K.append("g").attr("class","nv-brushBackground"),K.append("g").attr("class","nv-x nv-brush"),E&&(c.width(j/2),$.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(c),p.top!=c.height()&&(p.top=c.height(),F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g),$.select(".nv-legendWrap").attr("transform","translate("+j/2+","+ -p.top+")")),X.attr("transform","translate("+p.left+","+p.top+")"),i.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),n.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var Q=$.select(".nv-context .nv-barsWrap").datum(R.length?R:[{values:[]}]),G=$.select(".nv-context .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U);$.select(".nv-context").attr("transform","translate(0,"+(F+p.bottom+d.top)+")"),Q.call(i),G.call(n),h.x(k).on("brush",rt),x&&h.extent(x);var Y=$.select(".nv-brushBackground").selectAll("g").data([x||h.extent()]),Z=Y.enter().append("g");Z.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",I),Z.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",I);var et=$.select(".nv-x.nv-brush").call(h);et.selectAll("rect").attr("height",I),et.selectAll(".resize").append("path").attr("d",tt),o.ticks(j/100).tickSize(-I,0),$.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+O.range()[0]+")"),$.select(".nv-context .nv-x.nv-axis").call(o),f.scale(O).ticks(I/36).tickSize(-j,0),$.select(".nv-context .nv-y1.nv-axis").style("opacity",R.length?1:0).attr("transform","translate(0,"+k.range()[0]+")"),$.select(".nv-context .nv-y1.nv-axis").call(f),l.scale(M).ticks(I/36).tickSize(R.length?0:-j,0),$.select(".nv-context .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+k.range()[1]+",0)"),$.select(".nv-context .nv-y2.nv-axis").call(l),c.dispatch.on("stateChange",function(e){B.update()}),D.on("tooltipShow",function(e){T&&H(e,P.parentNode)}),rt()}),B}var t=e.models.line(),n=e.models.line(),r=e.models.historicalBar(),i=e.models.historicalBar(),s=e.models.axis(),o=e.models.axis(),u=e.models.axis(),a=e.models.axis(),f=e.models.axis(),l=e.models.axis(),c=e.models.legend(),h=d3.svg.brush(),p={top:30,right:30,bottom:30,left:60},d={top:0,right:30,bottom:20,left:60},v=null,m=null,g=100,y=function(e){return e.x},b=function(e){return e.y},w=e.utils.defaultColor(),E=!0,S,x=null,T=!0,N=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},C,k,L,A,O,M,_="No Data Available.",D=d3.dispatch("tooltipShow","tooltipHide","brush"),P=0;t.clipEdge(!0),n.interactive(!1),s.orient("bottom").tickPadding(5),u.orient("left"),a.orient("right"),o.orient("bottom").tickPadding(5),f.orient("left"),l.orient("right");var H=function(n,r){S&&(n.pointIndex+=Math.ceil(S[0]));var i=n.pos[0]+(r.offsetLeft||0),o=n.pos[1]+(r.offsetTop||0),f=s.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?u:a).tickFormat()(t.y()(n.point,n.pointIndex)),c=N(n.series.key,f,l,n,B);e.tooltip.show([i,o],c,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),r.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),r.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),D.on("tooltipHide",function(){T&&e.tooltip.cleanup()}),B.dispatch=D,B.legend=c,B.lines=t,B.lines2=n,B.bars=r,B.bars2=i,B.xAxis=s,B.x2Axis=o,B.y1Axis=u,B.y2Axis=a,B.y3Axis=f,B.y4Axis=l,d3.rebind(B,t,"defined","size","clipVoronoi","interpolate"),B.options=e.utils.optionsFunc.bind(B),B.x=function(e){return arguments.length?(y=e,t.x(e),r.x(e),B):y},B.y=function(e){return arguments.length?(b=e,t.y(e),r.y(e),B):b},B.margin=function(e){return arguments.length?(p.top=typeof e.top!="undefined"?e.top:p.top,p.right=typeof e.right!="undefined"?e.right:p.right,p.bottom=typeof e.bottom!="undefined"?e.bottom:p.bottom,p.left=typeof e.left!="undefined"?e.left:p.left,B):p},B.width=function(e){return arguments.length?(v=e,B):v},B.height=function(e){return arguments.length?(m=e,B):m},B.color=function(t){return arguments.length?(w=e.utils.getColor(t),c.color(w),B):w},B.showLegend=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(T=e,B):T},B.tooltipContent=function(e){return arguments.length?(N=e,B):N},B.noData=function(e){return arguments.length?(_=e,B):_},B.brushExtent=function(e){return arguments.length?(x=e,B):x},B},e.models.multiBar=function(){function C(e){return e.each(function(e){var g=n-t.left-t.right,C=r-t.top-t.bottom,k=d3.select(this);d&&e.length&&(d=[{values:e[0].values.map(function(e){return{x:e.x,y:0,series:e.series,size:.01}})}]),c&&(e=d3.layout.stack().offset(h).values(function(e){return e.values}).y(a)(!e.length&&d?d:e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),c&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i,i-=t.size):(t.y1=t.size+r,r+=t.size)})});var L=y&&b?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});i.domain(y||d3.merge(L).map(function(e){return e.x})).rangeBands(w||[0,g],S),s.domain(b||d3.extent(d3.merge(L).map(function(e){return c?e.y>0?e.y1:e.y1+e.y:e.y}).concat(f))).range(E||[C,0]),i.domain()[0]===i.domain()[1]&&(i.domain()[0]?i.domain([i.domain()[0]-i.domain()[0]*.01,i.domain()[1]+i.domain()[1]*.01]):i.domain([-1,1])),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]+s.domain()[0]*.01,s.domain()[1]-s.domain()[1]*.01]):s.domain([-1,1])),T=T||i,N=N||s;var A=k.selectAll("g.nv-wrap.nv-multibar").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),M=O.append("defs"),_=O.append("g"),D=A.select("g");_.append("g").attr("class","nv-groups"),A.attr("transform","translate("+t.left+","+t.top+")"),M.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),A.select("#nv-edge-clip-"+o+" rect").attr("width",g).attr("height",C),D.attr("clip-path",l?"url(#nv-edge-clip-"+o+")":"");var P=A.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});P.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),P.exit().selectAll("rect.nv-bar").attr("y",function(e){return c?N(e.y0):N(0)}).attr("height",0).remove(),P.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return p(e,t)}).style("stroke",function(e,t){return p(e,t)}),P.style("stroke-opacity",1).style("fill-opacity",.75);var H=P.selectAll("rect.nv-bar").data(function(t){return d&&!e.length?d.values:t.values});H.exit().remove();var B=H.enter().append("rect").attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(t,n,r){return c?0:r*i.rangeBand()/e.length}).attr("y",function(e){return N(c?e.y0:0)}).attr("height",0).attr("width",i.rangeBand()/(c?1:e.length)).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"});H.style("fill",function(e,t,n){return p(e,n,t)}).style("stroke",function(e,t,n){return p(e,n,t)}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"}),v&&(m||(m=e.map(function(){return!0})),H.style("fill",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()})),c?H.attr("y",function(e,t){return s(c?e.y1:0)}).attr("height",function(e,t){return Math.max(Math.abs(s(e.y+(c?e.y0:0))-s(c?e.y0:0)),1)}).attr("x",function(t,n){return c?0:t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/(c?1:e.length)):H.attr("x",function(t,n){return t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/e.length).attr("y",function(e,t){return a(e,t)<0?s(0):s(0)-s(a(e,t))<1?s(0)-1:s(a(e,t))||0}).attr("height",function(e,t){return Math.max(Math.abs(s(a(e,t))-s(0)),1)||0}),T=i.copy(),N=s.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=d3.scale.ordinal(),s=d3.scale.linear(),o=Math.floor(Math.random()*1e4),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=!0,c=!1,h="zero",p=e.utils.defaultColor(),d=!1,v=null,m,g=1200,y,b,w,E,S=.1,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(i=e,C):i},C.yScale=function(e){return arguments.length?(s=e,C):s},C.xDomain=function(e){return arguments.length?(y=e,C):y},C.yDomain=function(e){return arguments.length?(b=e,C):b},C.xRange=function(e){return arguments.length?(w=e,C):w},C.yRange=function(e){return arguments.length?(E=e,C):E},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(c=e,C):c},C.stackOffset=function(e){return arguments.length?(h=e,C):h},C.clipEdge=function(e){return arguments.length?(l=e,C):l},C.color=function(t){return arguments.length?(p=e.utils.getColor(t),C):p},C.barColor=function(t){return arguments.length?(v=e.utils.getColor(t),C):v},C.disabled=function(e){return arguments.length?(m=e,C):m},C.id=function(e){return arguments.length?(o=e,C):o},C.hideable=function(e){return arguments.length?(d=e,C):d},C.delay=function(e){return arguments.length?(g=e,C):g},C.groupSpacing=function(e){return arguments.length?(S=e,C):S},C},e.models.multiBarChart=function(){function A(e){return e.each(function(e){var b=d3.select(this),k=this,O=(u||parseInt(b.style("width"))||960)-o.left-o.right,M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom;A.update=function(){b.call(A)},A.container=this,S.disabled=e.map(function(e){return!!e.disabled});if(!x){var _;x={};for(_ in S)S[_]instanceof Array?x[_]=S[_].slice(0):x[_]=S[_]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var D=b.selectAll(".nv-noData").data([T]);return D.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),D.attr("x",o.left+O/2).attr("y",o.top+M/2).text(function(e){return e}),A}b.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();var P=b.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([e]),H=P.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),B=P.select("g");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-barsWrap"),H.append("g").attr("class","nv-legendWrap"),H.append("g").attr("class","nv-controlsWrap"),c&&(i.width(O-C()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),B.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom),B.select(".nv-legendWrap").attr("transform","translate("+C()+","+ -o.top+")"));if(l){var j=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(C()).color(["#444","#444","#444"]),B.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -o.top+")").call(s)}P.attr("transform","translate("+o.left+","+o.top+")"),d&&B.select(".nv-y.nv-axis").attr("transform","translate("+O+",0)"),t.disabled(e.map(function(e){return e.disabled})).width(O).height(M).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var F=B.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));F.call(t);if(h){n.scale(w).ticks(O/100).tickSize(-M,0),B.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),B.select(".nv-x.nv-axis").call(n);var I=B.select(".nv-x.nv-axis > g").selectAll("g");I.selectAll("line, text").style("opacity",1);if(m){var q=function(e,t){return"translate("+e+","+t+")"},R=5,U=17;I.selectAll("text").attr("transform",function(e,t,n){return q(0,n%2==0?R:U)});var z=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;B.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(e,t){return q(0,t===0||z%2!==0?U:R)})}v&&I.filter(function(t,n){return n%Math.ceil(e[0].values.length/(O/100))!==0}).selectAll("text, line").style("opacity",0),g&&I.selectAll(".tick text").attr("transform","rotate("+g+" 0,0)").style("text-anchor",g>0?"start":"end"),B.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}p&&(r.scale(E).ticks(M/36).tickSize(-O,0),B.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){S=e,N.stateChange(S),A.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;j=j.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}S.stacked=t.stacked(),N.stateChange(S),A.update()}),N.on("tooltipShow",function(e){y&&L(e,k.parentNode)}),N.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),S.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),S.stacked=n.stacked),A.update()})}),A}var t=e.models.multiBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=!1,g=0,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},w,E,S={stacked:!1},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=function(){return l?180:0},k=0;t.stacked(!1),n.orient("bottom").tickPadding(7).highlightZero(!0).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(d?"right":"left").tickFormat(d3.format(",.1f")),s.updateState(!1);var L=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,A);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],N.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){y&&e.tooltip.cleanup()}),A.dispatch=N,A.multibar=t,A.legend=i,A.xAxis=n,A.yAxis=r,d3.rebind(A,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","stacked","stackOffset","delay","barColor","groupSpacing"),A.options=e.utils.optionsFunc.bind(A),A.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,A):o},A.width=function(e){return arguments.length?(u=e,A):u},A.height=function(e){return arguments.length?(a=e,A):a},A.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),A):f},A.showControls=function(e){return arguments.length?(l=e,A):l},A.showLegend=function(e){return arguments.length?(c=e,A):c},A.showXAxis=function(e){return arguments.length?(h=e,A):h},A.showYAxis=function(e){return arguments.length?(p=e,A):p},A.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),A):d},A.reduceXTicks=function(e){return arguments.length?(v=e,A):v},A.rotateLabels=function(e){return arguments.length?(g=e,A):g},A.staggerLabels=function(e){return arguments.length?(m=e,A):m},A.tooltip=function(e){return arguments.length?(b=e,A):b},A.tooltips=function(e){return arguments.length?(y=e,A):y},A.tooltipContent=function(e){return arguments.length?(b=e,A):b},A.state=function(e){return arguments.length?(S=e,A):S},A.defaultState=function(e){return arguments.length?(x=e,A):x},A.noData=function(e){return arguments.length?(T=e,A):T},A.transitionDuration=function(e){return arguments.length?(k=e,A):k},A},e.models.multiBarHorizontal=function(){function C(e){return e.each(function(e){var i=n-t.left-t.right,y=r-t.top-t.bottom,C=d3.select(this);p&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),p&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i-t.size,i-=t.size):(t.y1=r,r+=t.size)})});var k=b&&w?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});s.domain(b||d3.merge(k).map(function(e){return e.x})).rangeBands(E||[0,y],.1),o.domain(w||d3.extent(d3.merge(k).map(function(e){return p?e.y>0?e.y1+e.y:e.y1:e.y}).concat(f))),d&&!p?o.range(S||[o.domain()[0]<0?m:0,i-(o.domain()[1]>0?m:0)]):o.range(S||[0,i]),T=T||s,N=N||d3.scale.linear().domain(o.domain()).range([o(0),o(0)]);var L=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([e]),A=L.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),O=A.append("defs"),M=A.append("g"),_=L.select("g");M.append("g").attr("class","nv-groups"),L.attr("transform","translate("+t.left+","+t.top+")");var D=L.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return l(e,t)}).style("stroke",function(e,t){return l(e,t)}),D.style("stroke-opacity",1).style("fill-opacity",.75);var P=D.selectAll("g.nv-bar").data(function(e){return e.values});P.exit().remove();var H=P.enter().append("g").attr("transform",function(t,n,r){return"translate("+N(p?t.y0:0)+","+(p?0:r*s.rangeBand()/e.length+s(u(t,n)))+")"});H.append("rect").attr("width",0).attr("height",s.rangeBand()/(p?1:e.length)),P.on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[o(a(t,n)+(p?t.y0:0)),s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.append("text"),d&&!p?(P.select("text").attr("text-anchor",function(e,t){return a(e,t)<0?"end":"start"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return g(a(e,t))}),P.select("text").attr("x",function(e,t){return a(e,t)<0?-4:o(a(e,t))-o(0)+4})):P.selectAll("text").text(""),v&&!p?(H.append("text").classed("nv-bar-label",!0),P.select("text.nv-bar-label").attr("text-anchor",function(e,t){return a(e,t)<0?"start":"end"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return u(e,t)}),P.select("text.nv-bar-label").attr("x",function(e,t){return a(e,t)<0?o(0)-o(a(e,t))+4:-4})):P.selectAll("text.nv-bar-label").text(""),P.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}),c&&(h||(h=e.map(function(){return!0})),P.style("fill",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()})),p?P.attr("transform",function(e,t){return"translate("+o(e.y1)+","+s(u(e,t))+")"}).select("rect").attr("width",function(e,t){return Math.abs(o(a(e,t)+e.y0)-o(e.y0))}).attr("height",s.rangeBand()):P.attr("transform",function(t,n){return"translate("+(a(t,n)<0?o(a(t,n)):o(0))+","+(t.series*s.rangeBand()/e.length+s(u(t,n)))+")"}).select("rect").attr("height",s.rangeBand()/e.length).attr("width",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)}),T=s.copy(),N=o.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=null,h,p=!1,d=!1,v=!1,m=60,g=d3.format(",.2f"),y=1200,b,w,E,S,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(s=e,C):s},C.yScale=function(e){return arguments.length?(o=e,C):o},C.xDomain=function(e){return arguments.length?(b=e,C):b},C.yDomain=function(e){return arguments.length?(w=e,C):w},C.xRange=function(e){return arguments.length?(E=e,C):E},C.yRange=function(e){return arguments.length?(S=e,C):S},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(p=e,C):p},C.color=function(t){return arguments.length?(l=e.utils.getColor(t),C):l},C.barColor=function(t){return arguments.length?(c=e.utils.getColor(t),C):c},C.disabled=function(e){return arguments.length?(h=e,C):h},C.id=function(e){return arguments.length?(i=e,C):i},C.delay=function(e){return arguments.length?(y=e,C):y},C.showValues=function(e){return arguments.length?(d=e,C):d},C.showBarLabels=function(e){return arguments.length?(v=e,C):v},C.valueFormat=function(e){return arguments.length?(g=e,C):g},C.valuePadding=function(e){return arguments.length?(m=e,C):m},C},e.models.multiBarHorizontalChart=function(){function C(e){return e.each(function(e){var d=d3.select(this),m=this,T=(u||parseInt(d.style("width"))||960)-o.left-o.right,k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom;C.update=function(){d.call(C)},C.container=this,b.disabled=e.map(function(e){return!!e.disabled});if(!w){var L;w={};for(L in b)b[L]instanceof Array?w[L]=b[L].slice(0):w[L]=b[L]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var A=d.selectAll(".nv-noData").data([E]);return A.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),A.attr("x",o.left+T/2).attr("y",o.top+k/2).text(function(e){return e}),C}d.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var O=d.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-legendWrap"),M.append("g").attr("class","nv-controlsWrap"),c&&(i.width(T-x()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),_.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom),_.select(".nv-legendWrap").attr("transform","translate("+x()+","+ -o.top+")"));if(l){var D=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(x()).color(["#444","#444","#444"]),_.select(".nv-controlsWrap").datum(D).attr("transform","translate(0,"+ -o.top+")").call(s)}O.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(e.map(function(e){return e.disabled})).width(T).height(k).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var P=_.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));P.call(t);if(h){n.scale(g).ticks(k/24).tickSize(-T,0),_.select(".nv-x.nv-axis").call(n);var H=_.select(".nv-x.nv-axis").selectAll("g");H.selectAll("line, text")}p&&(r.scale(y).ticks(T/100).tickSize(-k,0),_.select(".nv-y.nv-axis").attr("transform","translate(0,"+k+")"),_.select(".nv-y.nv-axis").call(r)),_.select(".nv-zeroLine line").attr("x1",y(0)).attr("x2",y(0)).attr("y1",0).attr("y2",-k),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),C.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;D=D.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}b.stacked=t.stacked(),S.stateChange(b),C.update()}),S.on("tooltipShow",function(e){v&&N(e,m.parentNode)}),S.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),b.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),b.stacked=n.stacked),C.update()})}),C}var t=e.models.multiBarHorizontal(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend().height(30),s=e.models.legend().height(30),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+" - "+t+"</h3>"+"<p>"+n+"</p>"},g,y,b={stacked:d},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=function(){return l?180:0},T=0;t.stacked(d),n.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("bottom").tickFormat(d3.format(",.1f")),s.updateState(!1);var N=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,C);e.tooltip.show([o,u],l,i.value<0?"e":"w",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),C.dispatch=S,C.multibar=t,C.legend=i,C.xAxis=n,C.yAxis=r,d3.rebind(C,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","delay","showValues","showBarLabels","valueFormat","stacked","barColor"),C.options=e.utils.optionsFunc.bind(C),C.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,C):o},C.width=function(e){return arguments.length?(u=e,C):u},C.height=function(e){return arguments.length?(a=e,C):a},C.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),C):f},C.showControls=function(e){return arguments.length?(l=e,C):l},C.showLegend=function(e){return arguments.length?(c=e,C):c},C.showXAxis=function(e){return arguments.length?(h=e,C):h},C.showYAxis=function(e){return arguments.length?(p=e,C):p},C.tooltip=function(e){return arguments.length?(m=e,C):m},C.tooltips=function(e){return arguments.length?(v=e,C):v},C.tooltipContent=function(e){return arguments.length?(m=e,C):m},C.state=function(e){return arguments.length?(b=e,C):b},C.defaultState=function(e){return arguments.length?(w=e,C):w},C.noData=function(e){return arguments.length?(E=e,C):E},C.transitionDuration=function(e){return arguments.length?(T=e,C):T},C},e.models.multiChart=function(){function C(e){return e.each(function(e){var u=d3.select(this),f=this;C.update=function(){u.call(C)},C.container=this;var k=(r||parseInt(u.style("width"))||960)-t.left-t.right,L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom,A=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==1}),O=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==2}),M=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==1}),_=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==2}),D=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==1}),P=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==2}),H=e.filter(function(e){return!e.disabled&&e.yAxis==1}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})}),B=e.filter(function(e){return!e.disabled&&e.yAxis==2}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})});a.domain(d3.extent(d3.merge(H.concat(B)),function(e){return e.x})).range([0,k]);var j=u.selectAll("g.wrap.multiChart").data([e]),F=j.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");F.append("g").attr("class","x axis"),F.append("g").attr("class","y1 axis"),F.append("g").attr("class","y2 axis"),F.append("g").attr("class","lines1Wrap"),F.append("g").attr("class","lines2Wrap"),F.append("g").attr("class","bars1Wrap"),F.append("g").attr("class","bars2Wrap"),F.append("g").attr("class","stack1Wrap"),F.append("g").attr("class","stack2Wrap"),F.append("g").attr("class","legendWrap");var I=j.select("g");s&&(x.width(k/2),I.select(".legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.yAxis==1?"":" (right axis)"),e})).call(x),t.top!=x.height()&&(t.top=x.height(),L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom),I.select(".legendWrap").attr("transform","translate("+k/2+","+ -t.top+")")),d.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="line"})),v.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="line"})),m.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="bar"})),g.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="bar"})),y.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="area"})),b.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="area"})),I.attr("transform","translate("+t.left+","+t.top+")");var q=I.select(".lines1Wrap").datum(A),R=I.select(".bars1Wrap").datum(M),U=I.select(".stack1Wrap").datum(D),z=I.select(".lines2Wrap").datum(O),W=I.select(".bars2Wrap").datum(_),X=I.select(".stack2Wrap").datum(P),V=D.length?D.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[],$=P.length?P.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[];h.domain(l||d3.extent(d3.merge(H).concat(V),function(e){return e.y})).range([0,L]),p.domain(c||d3.extent(d3.merge(B).concat($),function(e){return e.y})).range([0,L]),d.yDomain(h.domain()),m.yDomain(h.domain()),y.yDomain(h.domain()),v.yDomain(p.domain()),g.yDomain(p.domain()),b.yDomain(p.domain()),D.length&&d3.transition(U).call(y),P.length&&d3.transition(X).call(b),M.length&&d3.transition(R).call(m),_.length&&d3.transition(W).call(g),A.length&&d3.transition(q).call(d),O.length&&d3.transition(z).call(v),w.ticks(k/100).tickSize(-L,0),I.select(".x.axis").attr("transform","translate(0,"+L+")"),d3.transition(I.select(".x.axis")).call(w),E.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y1.axis")).call(E),S.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y2.axis")).call(S),I.select(".y2.axis").style("opacity",B.length?1:0).attr("transform","translate("+a.range()[1]+",0)"),x.dispatch.on("stateChange",function(e){C.update()}),T.on("tooltipShow",function(e){o&&N(e,f.parentNode)})}),C}var t={top:30,right:20,bottom:50,left:60},n=d3.scale.category20().range(),r=null,i=null,s=!0,o=!0,u=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},a,f,l,c,a=d3.scale.linear(),h=d3.scale.linear(),p=d3.scale.linear(),d=e.models.line().yScale(h),v=e.models.line().yScale(p),m=e.models.multiBar().stacked(!1).yScale(h),g=e.models.multiBar().stacked(!1).yScale(p),y=e.models.stackedArea().yScale(h),b=e.models.stackedArea().yScale(p),w=e.models.axis().scale(a).orient("bottom").tickPadding(5),E=e.models.axis().scale(h).orient("left"),S=e.models.axis().scale(p).orient("right"),x=e.models.legend().height(30),T=d3.dispatch("tooltipShow","tooltipHide"),N=function(t,n){var r=t.pos[0]+(n.offsetLeft||0),i=t.pos[1]+(n.offsetTop||0),s=w.tickFormat()(d.x()(t.point,t.pointIndex)),o=(t.series.yAxis==2?S:E).tickFormat()(d.y()(t.point,t.pointIndex)),a=u(t.series.key,s,o,t,C);e.tooltip.show([r,i],a,undefined,undefined,n.offsetParent)};return d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),m.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),m.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),g.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),g.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),y.dispatch.on("tooltipShow",function(e){if(!Math.round(y.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),y.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),b.dispatch.on("tooltipShow",function(e){if(!Math.round(b.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),b.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){o&&e.tooltip.cleanup()}),C.dispatch=T,C.lines1=d,C.lines2=v,C.bars1=m,C.bars2=g,C.stack1=y,C.stack2=b,C.xAxis=w,C.yAxis1=E,C.yAxis2=S,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(getX=e,d.x(e),m.x(e),C):getX},C.y=function(e){return arguments.length?(getY=e,d.y(e),m.y(e),C):getY},C.yDomain1=function(e){return arguments.length?(l=e,C):l},C.yDomain2=function(e){return arguments.length?(c=e,C):c},C.margin=function(e){return arguments.length?(t=e,C):t},C.width=function(e){return arguments.length?(r=e,C):r},C.height=function(e){return arguments.length?(i=e,C):i},C.color=function(e){return arguments.length?(n=e,x.color(e),C):n},C.showLegend=function(e){return arguments.length?(s=e,C):s},C.tooltips=function(e){return arguments.length?(o=e,C):o},C.tooltipContent=function(e){return arguments.length?(u=e,C):u},C},e.models.ohlcBar=function(){function x(e){return e.each(function(e){var g=n-t.left-t.right,x=r-t.top-t.bottom,T=d3.select(this);s.domain(y||d3.extent(e[0].values.map(u).concat(p))),v?s.range(w||[g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range(w||[0,g]),o.domain(b||[d3.min(e[0].values.map(h).concat(d)),d3.max(e[0].values.map(c).concat(d))]).range(E||[x,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([e[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-ticks"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){S.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",x),A.attr("clip-path",m?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-ticks").selectAll(".nv-tick").data(function(e){return e});O.exit().remove();var M=O.enter().append("path").attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"}).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),S.elementMouseover({point:t,series:e[0],pos:[s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),S.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){S.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){S.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}),d3.transition(O).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"})}),x}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=function(e){return e.open},l=function(e){return e.close},c=function(e){return e.high},h=function(e){return e.low},p=[],d=[],v=!1,m=!0,g=e.utils.defaultColor(),y,b,w,E,S=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return x.dispatch=S,x.options=e.utils.optionsFunc.bind(x),x.x=function(e){return arguments.length?(u=e,x):u},x.y=function(e){return arguments.length?(a=e,x):a},x.open=function(e){return arguments.length?(f=e,x):f},x.close=function(e){return arguments.length?(l=e,x):l},x.high=function(e){return arguments.length?(c=e,x):c},x.low=function(e){return arguments.length?(h=e,x):h},x.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,x):t},x.width=function(e){return arguments.length?(n=e,x):n},x.height=function(e){return arguments.length?(r=e,x):r},x.xScale=function(e){return arguments.length?(s=e,x):s},x.yScale=function(e){return arguments.length?(o=e,x):o},x.xDomain=function(e){return arguments.length?(y=e,x):y},x.yDomain=function(e){return arguments.length?(b=e,x):b},x.xRange=function(e){return arguments.length?(w=e,x):w},x.yRange=function(e){return arguments.length?(E=e,x):E},x.forceX=function(e){return arguments.length?(p=e,x):p},x.forceY=function(e){return arguments.length?(d=e,x):d},x.padData=function(e){return arguments.length?(v=e,x):v},x.clipEdge=function(e){return arguments.length?(m=e,x):m},x.color=function(t){return arguments.length?(g=e.utils.getColor(t),x):g},x.id=function(e){return arguments.length?(i=e,x):i},x},e.models.pie=function(){function S(e){return e.each(function(e){function q(e){var t=(e.startAngle+e.endAngle)*90/Math.PI-90;return t>90?t-180:t}function R(e){e.endAngle=isNaN(e.endAngle)?0:e.endAngle,e.startAngle=isNaN(e.startAngle)?0:e.startAngle,m||(e.innerRadius=0);var t=d3.interpolate(this._current,e);return this._current=t(0),function(e){return A(t(e))}}function U(e){e.innerRadius=0;var t=d3.interpolate({startAngle:0,endAngle:0},e);return function(e){return A(t(e))}}var o=n-t.left-t.right,f=r-t.top-t.bottom,S=Math.min(o,f)/2,x=S-S/5,T=d3.select(this),N=T.selectAll(".nv-wrap.nv-pie").data(e),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+u),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-pie"),k.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+t.left+","+t.top+")"),L.select(".nv-pie").attr("transform","translate("+o/2+","+f/2+")"),L.select(".nv-pieLabels").attr("transform","translate("+o/2+","+f/2+")"),T.on("click",function(e,t){E.chartClick({data:e,index:t,pos:d3.event,id:u})});var A=d3.svg.arc().outerRadius(x);y&&A.startAngle(y),b&&A.endAngle(b),m&&A.innerRadius(S*w);var O=d3.layout.pie().sort(null).value(function(e){return e.disabled?0:s(e)}),M=N.select(".nv-pie").selectAll(".nv-slice").data(O),_=N.select(".nv-pieLabels").selectAll(".nv-label").data(O);M.exit().remove(),_.exit().remove();var D=M.enter().append("g").attr("class","nv-slice").on("mouseover",function(e,t){d3.select(this).classed("hover",!0),E.elementMouseover({label:i(e.data),value:s(e.data),point:e.data,pointIndex:t,pos:[d3.event.pageX,d3.event.pageY],id:u})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),E.elementMouseout({label:i(e.data),value:s(e.data),point:e.data,index:t,id:u})}).on("click",function(e,t){E.elementClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()}).on("dblclick",function(e,t){E.elementDblClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()});M.attr("fill",function(e,t){return a(e,t)}).attr("stroke",function(e,t){return a(e,t)});var P=D.append("path").each(function(e){this._current=e});M.select("path").attr("d",A);if(l){var H=d3.svg.arc().innerRadius(0);c&&(H=A),h&&(H=d3.svg.arc().outerRadius(A.outerRadius())),_.enter().append("g").classed("nv-label",!0).each(function(e,t){var n=d3.select(this);n.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}return e.outerRadius=S+10,e.innerRadius=S+15,"translate("+H.centroid(e)+")"}),n.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),n.append("text").style("text-anchor",g?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")});var B={},j=14,F=140,I=function(e){return Math.floor(e[0]/F)*F+","+Math.floor(e[1]/j)*j};_.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}e.outerRadius=S+10,e.innerRadius=S+15;var n=H.centroid(e),r=I(n);return B[r]&&(n[1]-=j),B[I(n)]=!0,"translate("+n+")"}),_.select(".nv-label text").style("text-anchor",g?(d.startAngle+d.endAngle)/2<Math.PI?"start":"end":"middle").text(function(e,t){var n=(e.endAngle-e.startAngle)/(2*Math.PI),r={key:i(e.data),value:s(e.data),percent:d3.format("%")(n)};return e.value&&n>v?r[p]:""})}}),S}var t={top:0,right:0,bottom:0,left:0},n=500,r=500,i=function(e){return e.x},s=function(e){return e.y},o=function(e){return e.description},u=Math.floor(Math.random()*1e4),a=e.utils.defaultColor(),f=d3.format(",.2f"),l=!0,c=!0,h=!1,p="key",v=.02,m=!1,g=!1,y=!1,b=!1,w=.5,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return S.dispatch=E,S.options=e.utils.optionsFunc.bind(S),S.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,S):t},S.width=function(e){return arguments.length?(n=e,S):n},S.height=function(e){return arguments.length?(r=e,S):r},S.values=function(t){return e.log("pie.values() is no longer supported."),S},S.x=function(e){return arguments.length?(i=e,S):i},S.y=function(e){return arguments.length?(s=d3.functor(e),S):s},S.description=function(e){return arguments.length?(o=e,S):o},S.showLabels=function(e){return arguments.length?(l=e,S):l},S.labelSunbeamLayout=function(e){return arguments.length?(g=e,S):g},S.donutLabelsOutside=function(e){return arguments.length?(h=e,S):h},S.pieLabelsOutside=function(e){return arguments.length?(c=e,S):c},S.labelType=function(e){return arguments.length?(p=e,p=p||"key",S):p},S.donut=function(e){return arguments.length?(m=e,S):m},S.donutRatio=function(e){return arguments.length?(w=e,S):w},S.startAngle=function(e){return arguments.length?(y=e,S):y},S.endAngle=function(e){return arguments.length?(b=e,S):b},S.id=function(e){return arguments.length?(u=e,S):u},S.color=function(t){return arguments.length?(a=e.utils.getColor(t),S):a},S.valueFormat=function(e){return arguments.length?(f=e,S):f},S.labelThreshold=function(e){return arguments.length?(v=e,S):v},S},e.models.pieChart=function(){function v(e){return e.each(function(e){var u=d3.select(this),a=this,f=(i||parseInt(u.style("width"))||960)-r.left-r.right,d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom;v.update=function(){u.call(v)},v.container=this,l.disabled=e.map(function(e){return!!e.disabled});if(!c){var m;c={};for(m in l)l[m]instanceof Array?c[m]=l[m].slice(0):c[m]=l[m]}if(!e||!e.length){var g=u.selectAll(".nv-noData").data([h]);return g.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),g.attr("x",r.left+f/2).attr("y",r.top+d/2).text(function(e){return e}),v}u.selectAll(".nv-noData").remove();var y=u.selectAll("g.nv-wrap.nv-pieChart").data([e]),b=y.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),w=y.select("g");b.append("g").attr("class","nv-pieWrap"),b.append("g").attr("class","nv-legendWrap"),o&&(n.width(f).key(t.x()),y.select(".nv-legendWrap").datum(e).call(n),r.top!=n.height()&&(r.top=n.height(),d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom),y.select(".nv-legendWrap").attr("transform","translate(0,"+ -r.top+")")),y.attr("transform","translate("+r.left+","+r.top+")"),t.width(f).height(d);var E=w.select(".nv-pieWrap").datum([e]);d3.transition(E).call(t),n.dispatch.on("stateChange",function(e){l=e,p.stateChange(l),v.update()}),t.dispatch.on("elementMouseout.tooltip",function(e){p.tooltipHide(e)}),p.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),l.disabled=t.disabled),v.update()})}),v}var t=e.models.pie(),n=e.models.legend(),r={top:30,right:20,bottom:20,left:20},i=null,s=null,o=!0,u=e.utils.defaultColor(),a=!0,f=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+t+"</p>"},l={},c=null,h="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),d=function(n,r){var i=t.description()(n.point)||t.x()(n.point),s=n.pos[0]+(r&&r.offsetLeft||0),o=n.pos[1]+(r&&r.offsetTop||0),u=t.valueFormat()(t.y()(n.point)),a=f(i,u,n,v);e.tooltip.show([s,o],a,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+r.left,e.pos[1]+r.top],p.tooltipShow(e)}),p.on("tooltipShow",function(e){a&&d(e)}),p.on("tooltipHide",function(){a&&e.tooltip.cleanup()}),v.legend=n,v.dispatch=p,v.pie=t,d3.rebind(v,t,"valueFormat","values","x","y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","labelType","donut","donutRatio","labelThreshold"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(r.top=typeof e.top!="undefined"?e.top:r.top,r.right=typeof e.right!="undefined"?e.right:r.right,r.bottom=typeof e.bottom!="undefined"?e.bottom:r.bottom,r.left=typeof e.left!="undefined"?e.left:r.left,v):r},v.width=function(e){return arguments.length?(i=e,v):i},v.height=function(e){return arguments.length?(s=e,v):s},v.color=function(r){return arguments.length?(u=e.utils.getColor(r),n.color(u),t.color(u),v):u},v.showLegend=function(e){return arguments.length?(o=e,v):o},v.tooltips=function(e){return arguments.length?(a=e,v):a},v.tooltipContent=function(e){return arguments.length?(f=e,v):f},v.state=function(e){return arguments.length?(l=e,v):l},v.defaultState=function(e){return arguments.length?(c=e,v):c},v.noData=function(e){return arguments.length?(h=e,v):h},v},e.models.scatter=function(){function I(q){return q.each(function(I){function Q(){if(!g)return!1;var e,i=d3.merge(I.map(function(e,t){return e.values.map(function(e,n){var r=f(e,n),i=l(e,n);return[o(r),u(i),t,n,e]}).filter(function(e,t){return b(e[4],t)})}));if(D===!0){if(x){var a=X.select("defs").selectAll(".nv-point-clips").data([s]).enter();a.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+s);var c=X.select("#nv-points-clip-"+s).selectAll("circle").data(i);c.enter().append("circle").attr("r",T),c.exit().remove(),c.attr("cx",function(e){return e[0]}).attr("cy",function(e){return e[1]}),X.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+s+")")}i.length&&(i.push([o.range()[0]-20,u.range()[0]-20,null,null]),i.push([o.range()[1]+20,u.range()[1]+20,null,null]),i.push([o.range()[0]-20,u.range()[0]+20,null,null]),i.push([o.range()[1]+20,u.range()[1]-20,null,null]));var h=d3.geom.polygon([[-10,-10],[-10,r+10],[n+10,r+10],[n+10,-10]]),p=1e-6;i=i.sort(function(e,t){return e[0]-t[0]||e[1]-t[1]});for(var d=0;d<i.length-1;)Math.abs(i[d][0]-i[d+1][0])<p&&Math.abs(i[d][1]-i[d+1][1])<p?i.splice(d+1,1):d++;var v=d3.geom.voronoi(i).map(function(e,t){return{data:h.clip(e),series:i[t][2],point:i[t][3]}}),m=X.select(".nv-point-paths").selectAll("path").data(v);m.enter().append("path").attr("class",function(e,t){return"nv-path-"+t}),m.exit().remove(),m.attr("d",function(e){return!e||!e.data||e.data.length===0?"M 0 0":"M"+e.data.join("L")+"Z"});var y=function(e,n){if(F)return 0;var r=I[e.series];if(typeof r=="undefined")return;var i=r.values[e.point];n({point:i,series:r,pos:[o(f(i,e.point))+t.left,u(l(i,e.point))+t.top],seriesIndex:e.series,pointIndex:e.point})};m.on("click",function(e){y(e,_.elementClick)}).on("mouseover",function(e){y(e,_.elementMouseover)}).on("mouseout",function(e,t){y(e,_.elementMouseout)})}else X.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementClick({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseover",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementMouseover({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseout",function(e,t){if(F||!I[e.series])return 0;var n=I[e.series],r=n.values[t];_.elementMouseout({point:r,series:n,seriesIndex:e.series,pointIndex:t})});F=!1}var q=n-t.left-t.right,R=r-t.top-t.bottom,U=d3.select(this);I.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var W=N&&C&&A?[]:d3.merge(I.map(function(e){return e.values.map(function(e,t){return{x:f(e,t),y:l(e,t),size:c(e,t)}})}));o.domain(N||d3.extent(W.map(function(e){return e.x}).concat(d))),w&&I[0]?o.range(k||[(q*E+q)/(2*I[0].values.length),q-q*(1+E)/(2*I[0].values.length)]):o.range(k||[0,q]),u.domain(C||d3.extent(W.map(function(e){return e.y}).concat(v))).range(L||[R,0]),a.domain(A||d3.extent(W.map(function(e){return e.size}).concat(m))).range(O||[16,256]);if(o.domain()[0]===o.domain()[1]||u.domain()[0]===u.domain()[1])M=!0;o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]-o.domain()[0]*.01,o.domain()[1]+o.domain()[1]*.01]):o.domain([-1,1])),u.domain()[0]===u.domain()[1]&&(u.domain()[0]?u.domain([u.domain()[0]-u.domain()[0]*.01,u.domain()[1]+u.domain()[1]*.01]):u.domain([-1,1])),isNaN(o.domain()[0])&&o.domain([-1,1]),isNaN(u.domain()[0])&&u.domain([-1,1]),P=P||o,H=H||u,B=B||a;var X=U.selectAll("g.nv-wrap.nv-scatter").data([I]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+s+(M?" nv-single-point":"")),$=V.append("defs"),J=V.append("g"),K=X.select("g");J.append("g").attr("class","nv-groups"),J.append("g").attr("class","nv-point-paths"),X.attr("transform","translate("+t.left+","+t.top+")"),$.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),X.select("#nv-edge-clip-"+s+" rect").attr("width",q).attr("height",R>0?R:0),K.attr("clip-path",S?"url(#nv-edge-clip-"+s+")":""),F=!0;var G=X.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});G.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),G.exit().remove(),G.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),G.style("fill",function(e,t){return i(e,t)}).style("stroke",function(e,t){return i(e,t)}).style("stroke-opacity",1).style("fill-opacity",.5);if(p){var Y=G.selectAll("circle.nv-point").data(function(e){return e.values},y);Y.enter().append("circle").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("cx",function(t,n){return e.utils.NaNtoZero(P(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(H(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)}),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)})}else{var Y=G.selectAll("path.nv-point").data(function(e){return e.values});Y.enter().append("path").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("transform",function(e,t){return"translate("+P(f(e,t))+","+H(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))})),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))}))}clearTimeout(j),j=setTimeout(Q,300),P=o.copy(),H=u.copy(),B=a.copy()}),I}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=d3.scale.linear(),u=d3.scale.linear(),a=d3.scale.linear(),f=function(e){return e.x},l=function(e){return e.y},c=function(e){return e.size||1},h=function(e){return e.shape||"circle"},p=!0,d=[],v=[],m=[],g=!0,y=null,b=function(e){return!e.notActive},w=!1,E=.1,S=!1,x=!0,T=function(){return 25},N=null,C=null,k=null,L=null,A=null,O=null,M=!1,_=d3.dispatch("elementClick","elementMouseover","elementMouseout"),D=!0,P,H,B,j,F=!1;return I.clearHighlights=function(){d3.selectAll(".nv-chart-"+s+" .nv-point.hover").classed("hover",!1)},I.highlightPoint=function(e,t,n){d3.select(".nv-chart-"+s+" .nv-series-"+e+" .nv-point-"+t).classed("hover",n)},_.on("elementMouseover.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!0)}),_.on("elementMouseout.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!1)}),I.dispatch=_,I.options=e.utils.optionsFunc.bind(I),I.x=function(e){return arguments.length?(f=d3.functor(e),I):f},I.y=function(e){return arguments.length?(l=d3.functor(e),I):l},I.size=function(e){return arguments.length?(c=d3.functor(e),I):c},I.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,I):t},I.width=function(e){return arguments.length?(n=e,I):n},I.height=function(e){return arguments.length?(r=e,I):r},I.xScale=function(e){return arguments.length?(o=e,I):o},I.yScale=function(e){return arguments.length?(u=e,I):u},I.zScale=function(e){return arguments.length?(a=e,I):a},I.xDomain=function(e){return arguments.length?(N=e,I):N},I.yDomain=function(e){return arguments.length?(C=e,I):C},I.sizeDomain=function(e){return arguments.length?(A=e,I):A},I.xRange=function(e){return arguments.length?(k=e,I):k},I.yRange=function(e){return arguments.length?(L=e,I):L},I.sizeRange=function(e){return arguments.length?(O=e,I):O},I.forceX=function(e){return arguments.length?(d=e,I):d},I.forceY=function(e){return arguments.length?(v=e,I):v},I.forceSize=function(e){return arguments.length?(m=e,I):m},I.interactive=function(e){return arguments.length?(g=e,I):g},I.pointKey=function(e){return arguments.length?(y=e,I):y},I.pointActive=function(e){return arguments.length?(b=e,I):b},I.padData=function(e){return arguments.length?(w=e,I):w},I.padDataOuter=function(e){return arguments.length?(E=e,I):E},I.clipEdge=function(e){return arguments.length?(S=e,I):S},I.clipVoronoi=function(e){return arguments.length?(x=e,I):x},I.useVoronoi=function(e){return arguments.length?(D=e,D===!1&&(x=!1),I):D},I.clipRadius=function(e){return arguments.length?(T=e,I):T},I.color=function(t){return arguments.length?(i=e.utils.getColor(t),I):i},I.shape=function(e){return arguments.length?(h=e,I):h},I.onlyCircles=function(e){return arguments.length?(p=e,I):p},I.id=function(e){return arguments.length?(s=e,I):s},I.singlePoint=function(e){return arguments.length?(M=e,I):M},I},e.models.scatterChart=function(){function F(e){return e.each(function(e){function J(){if(T)return W.select(".nv-point-paths").style("pointer-events","all"),!1;W.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(x).focus(i[0]),p.distortion(x).focus(i[1]),W.select(".nv-scatterWrap").call(t),b&&W.select(".nv-x.nv-axis").call(n),w&&W.select(".nv-y.nv-axis").call(r),W.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),W.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var C=d3.select(this),k=this,L=(f||parseInt(C.style("width"))||960)-a.left-a.right,D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom;F.update=function(){C.call(F)},F.container=this,A.disabled=e.map(function(e){return!!e.disabled});if(!O){var I;O={};for(I in A)A[I]instanceof Array?O[I]=A[I].slice(0):O[I]=A[I]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=C.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",a.left+L/2).attr("y",a.top+D/2).text(function(e){return e}),F}C.selectAll(".nv-noData").remove(),P=P||h,H=H||p;var R=C.selectAll("g.nv-wrap.nv-scatterChart").data([e]),U=R.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),z=U.append("g"),W=R.select("g");z.append("rect").attr("class","nvd3 nv-background"),z.append("g").attr("class","nv-x nv-axis"),z.append("g").attr("class","nv-y nv-axis"),z.append("g").attr("class","nv-scatterWrap"),z.append("g").attr("class","nv-distWrap"),z.append("g").attr("class","nv-legendWrap"),z.append("g").attr("class","nv-controlsWrap");if(y){var X=S?L/2:L;i.width(X),R.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom),R.select(".nv-legendWrap").attr("transform","translate("+(L-X)+","+ -a.top+")")}S&&(s.width(180).color(["#444"]),W.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -a.top+")").call(s)),R.attr("transform","translate("+a.left+","+a.top+")"),E&&W.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),t.width(L).height(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),d!==0&&t.xDomain(null),v!==0&&t.yDomain(null),R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t);if(d!==0){var V=h.domain()[1]-h.domain()[0];t.xDomain([h.domain()[0]-d*V,h.domain()[1]+d*V])}if(v!==0){var $=p.domain()[1]-p.domain()[0];t.yDomain([p.domain()[0]-v*$,p.domain()[1]+v*$])}(v!==0||d!==0)&&R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),b&&(n.scale(h).ticks(n.ticks()&&n.ticks().length?n.ticks():L/100).tickSize(-D,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),w&&(r.scale(p).ticks(r.ticks()&&r.ticks().length?r.ticks():D/36).tickSize(-L,0),W.select(".nv-y.nv-axis").call(r)),m&&(o.getData(t.x()).scale(h).width(L).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),W.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),g&&(u.getData(t.y()).scale(p).width(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),W.select(".nv-distributionY").attr("transform","translate("+(E?L:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(W.select(".nv-background").attr("width",L).attr("height",D),W.select(".nv-background").on("mousemove",J),W.select(".nv-background").on("click",function(){T=!T}),t.dispatch.on("elementClick.freezeFisheye",function(){T=!T})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,x=e.disabled?0:2.5,W.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),W.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(x).focus(0),p.distortion(x).focus(0),W.select(".nv-scatterWrap").call(t),W.select(".nv-x.nv-axis").call(n),W.select(".nv-y.nv-axis").call(r)):T=!1,F.update()}),i.dispatch.on("stateChange",function(e){A.disabled=e.disabled,M.stateChange(A),F.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",function(t,n){return e.pos[1]-D}),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],M.tooltipShow(e)}),M.on("tooltipShow",function(e){N&&B(e,k.parentNode)}),M.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),A.disabled=t.disabled),F.update()}),P=h.copy(),H=p.copy()}),F}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=0,v=0,m=!1,g=!1,y=!0,b=!0,w=!0,E=!1,S=!!d3.fisheye,x=0,T=!1,N=!0,C=function(e,t,n){return"<strong>"+t+"</strong>"},k=function(e,t,n){return"<strong>"+n+"</strong>"},L=null,A={},O=null,M=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),_="No Data Available.",D=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(E?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var P,H,B=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));C!=null&&e.tooltip.show([f,l],C(i.series.key,v,m,i,F),"n",1,s,"x-nvtooltip"),k!=null&&e.tooltip.show([c,d],k(i.series.key,v,m,i,F),"e",1,s,"y-nvtooltip"),L!=null&&e.tooltip.show([o,u],L(i.series.key,v,m,i,F),i.value<0?"n":"s",null,s)},j=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){M.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),M.on("tooltipHide",function(){N&&e.tooltip.cleanup()}),F.dispatch=M,F.scatter=t,F.legend=i,F.controls=s,F.xAxis=n,F.yAxis=r,F.distX=o,F.distY=u,d3.rebind(F,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),F.options=e.utils.optionsFunc.bind(F),F.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,F):a},F.width=function(e){return arguments.length?(f=e,F):f},F.height=function(e){return arguments.length?(l=e,F):l},F.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),F):c},F.showDistX=function(e){return arguments.length?(m=e,F):m},F.showDistY=function(e){return arguments.length?(g=e,F):g},F.showControls=function(e){return arguments.length?(S=e,F):S},F.showLegend=function(e){return arguments.length?(y=e,F):y},F.showXAxis=function(e){return arguments.length?(b=e,F):b},F.showYAxis=function(e){return arguments.length?(w=e,F):w},F.rightAlignYAxis=function(e){return arguments.length?(E=e,r.orient(e?"right":"left"),F):E},F.fisheye=function(e){return arguments.length?(x=e,F):x},F.xPadding=function(e){return arguments.length?(d=e,F):d},F.yPadding=function(e){return arguments.length?(v=e,F):v},F.tooltips=function(e){return arguments.length?(N=e,F):N},F.tooltipContent=function(e){return arguments.length?(L=e,F):L},F.tooltipXContent=function(e){return arguments.length?(C=e,F):C},F.tooltipYContent=function(e){return arguments.length?(k=e,F):k},F.state=function(e){return arguments.length?(A=e,F):A},F.defaultState=function(e){return arguments.length?(O=e,F):O},F.noData=function(e){return arguments.length?(_=e,F):_},F.transitionDuration=function(e){return arguments.length?(D=e,F):D},F},e.models.scatterPlusLineChart=function(){function B(e){return e.each(function(e){function V(){if(S)return U.select(".nv-point-paths").style("pointer-events","all"),!1;U.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(E).focus(i[0]),p.distortion(E).focus(i[1]),U.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),g&&U.select(".nv-x.nv-axis").call(n),y&&U.select(".nv-y.nv-axis").call(r),U.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),U.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var T=d3.select(this),N=this,C=(f||parseInt(T.style("width"))||960)-a.left-a.right,M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom;B.update=function(){T.call(B)},B.container=this,k.disabled=e.map(function(e){return!!e.disabled});if(!L){var j;L={};for(j in k)k[j]instanceof Array?L[j]=k[j].slice(0):L[j]=k[j]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var F=T.selectAll(".nv-noData").data([O]);return F.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),F.attr("x",a.left+C/2).attr("y",a.top+M/2).text(function(e){return e}),B}T.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale(),_=_||h,D=D||p;var I=T.selectAll("g.nv-wrap.nv-scatterChart").data([e]),q=I.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),R=q.append("g"),U=I.select("g");R.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-scatterWrap"),R.append("g").attr("class","nv-regressionLinesWrap"),R.append("g").attr("class","nv-distWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),I.attr("transform","translate("+a.left+","+a.top+")"),b&&U.select(".nv-y.nv-axis").attr("transform","translate("+C+",0)"),m&&(i.width(C/2),I.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom),I.select(".nv-legendWrap").attr("transform","translate("+C/2+","+ -a.top+")")),w&&(s.width(180).color(["#444"]),U.select(".nv-controlsWrap").datum(H).attr("transform","translate(0,"+ -a.top+")").call(s)),t.width(C).height(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),I.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),I.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+t.id()+")");var z=I.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(e){return e});z.enter().append("g").attr("class","nv-regLines");var W=z.selectAll(".nv-regLine").data(function(e){return[e]}),X=W.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0);W.attr("x1",h.range()[0]).attr("x2",h.range()[1]).attr("y1",function(e,t){return p(h.domain()[0]*e.slope+e.intercept)}).attr("y2",function(e,t){return p(h.domain()[1]*e.slope+e.intercept)}).style("stroke",function(e,t,n){return c(e,n)}).style("stroke-opacity",function(e,t){return e.disabled||typeof e.slope=="undefined"||typeof e.intercept=="undefined"?0:1}),g&&(n.scale(h).ticks(n.ticks()?n.ticks():C/100).tickSize(-M,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),y&&(r.scale(p).ticks(r.ticks()?r.ticks():M/36).tickSize(-C,0),U.select(".nv-y.nv-axis").call(r)),d&&(o.getData(t.x()).scale(h).width(C).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),U.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),v&&(u.getData(t.y()).scale(p).width(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),U.select(".nv-distributionY").attr("transform","translate("+(b?C:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(U.select(".nv-background").attr("width",C).attr("height",M),U.select(".nv-background").on("mousemove",V),U.select(".nv-background").on("click",function(){S=!S}),t.dispatch.on("elementClick.freezeFisheye",function(){S=!S})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,E=e.disabled?0:2.5,U.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),U.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(E).focus(0),p.distortion(E).focus(0),U.select(".nv-scatterWrap").call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r)):S=!1,B.update()}),i.dispatch.on("stateChange",function(e){k=e,A.stateChange(k),B.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-M),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],A.tooltipShow(e)}),A.on("tooltipShow",function(e){x&&P(e,N.parentNode)}),A.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),k.disabled=t.disabled),B.update()}),_=h.copy(),D=p.copy()}),B}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=!1,v=!1,m=!0,g=!0,y=!0,b=!1,w=!!d3.fisheye,E=0,S=!1,x=!0,T=function(e,t,n){return"<strong>"+t+"</strong>"},N=function(e,t,n){return"<strong>"+n+"</strong>"},C=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+r+"</p>"},k={},L=null,A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),O="No Data Available.",M=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(b?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var _,D,P=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));T!=null&&e.tooltip.show([f,l],T(i.series.key,v,m,i,B),"n",1,s,"x-nvtooltip"),N!=null&&e.tooltip.show([c,d],N(i.series.key,v,m,i,B),"e",1,s,"y-nvtooltip"),C!=null&&e.tooltip.show([o,u],C(i.series.key,v,m,i.point.tooltip,i,B),i.value<0?"n":"s",null,s)},H=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){A.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),A.on("tooltipHide",function(){x&&e.tooltip.cleanup()}),B.dispatch=A,B.scatter=t,B.legend=i,B.controls=s,B.xAxis=n,B.yAxis=r,B.distX=o,B.distY=u,d3.rebind(B,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),B.options=e.utils.optionsFunc.bind(B),B.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,B):a},B.width=function(e){return arguments.length?(f=e,B):f},B.height=function(e){return arguments.length?(l=e,B):l},B.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),B):c},B.showDistX=function(e){return arguments.length?(d=e,B):d},B.showDistY=function(e){return arguments.length?(v=e,B):v},B.showControls=function(e){return arguments.length?(w=e,B):w},B.showLegend=function(e){return arguments.length?(m=e,B):m},B.showXAxis=function(e){return arguments.length?(g=e,B):g},B.showYAxis=function(e){return arguments.length?(y=e,B):y},B.rightAlignYAxis=function(e){return arguments.length?(b=e,r.orient(e?"right":"left"),B):b},B.fisheye=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(x=e,B):x},B.tooltipContent=function(e){return arguments.length?(C=e,B):C},B.tooltipXContent=function(e){return arguments.length?(T=e,B):T},B.tooltipYContent=function(e){return arguments.length?(N=e,B):N},B.state=function(e){return arguments.length?(k=e,B):k},B.defaultState=function(e){return arguments.length?(L=e,B):L},B.noData=function(e){return arguments.length?(O=e,B):O},B.transitionDuration=function(e){return arguments.length?(M=e,B):M},B},e.models.sparkline=function(){function d(e){return e.each(function(e){var i=n-t.left-t.right,d=r-t.top-t.bottom,v=d3.select(this);s.domain(l||d3.extent(e,u)).range(h||[0,i]),o.domain(c||d3.extent(e,a)).range(p||[d,0]);var m=v.selectAll("g.nv-wrap.nv-sparkline").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline"),b=g.append("g"),w=m.select("g");m.attr("transform","translate("+t.left+","+t.top+")");var E=m.selectAll("path").data(function(e){return[e]});E.enter().append("path"),E.exit().remove(),E.style("stroke",function(e,t){return e.color||f(e,t)}).attr("d",d3.svg.line().x(function(e,t){return s(u(e,t))}).y(function(e,t){return o(a(e,t))}));var S=m.selectAll("circle.nv-point").data(function(e){function n(t){if(t!=-1){var n=e[t];return n.pointIndex=t,n}return null}var t=e.map(function(e,t){return a(e,t)}),r=n(t.lastIndexOf(o.domain()[1])),i=n(t.indexOf(o.domain()[0])),s=n(t.length-1);return[i,r,s].filter(function(e){return e!=null})});S.enter().append("circle"),S.exit().remove(),S.attr("cx",function(e,t){return s(u(e,e.pointIndex))}).attr("cy",function(e,t){return o(a(e,e.pointIndex))}).attr("r",2).attr("class",function(e,t){return u(e,e.pointIndex)==s.domain()[1]?"nv-point nv-currentValue":a(e,e.pointIndex)==o.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),d}var t={top:2,right:0,bottom:2,left:0},n=400,r=32,i=!0,s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=e.utils.getColor(["#000"]),l,c,h,p;return d.options=e.utils.optionsFunc.bind(d),d.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,d):t},d.width=function(e){return arguments.length?(n=e,d):n},d.height=function(e){return arguments.length?(r=e,d):r},d.x=function(e){return arguments.length?(u=d3.functor(e),d):u},d.y=function(e){return arguments.length?(a=d3.functor(e),d):a},d.xScale=function(e){return arguments.length?(s=e,d):s},d.yScale=function(e){return arguments.length?(o=e,d):o},d.xDomain=function(e){return arguments.length?(l=e,d):l},d.yDomain=function(e){return arguments.length?(c=e,d):c},d.xRange=function(e){return arguments.length?(h=e,d):h},d.yRange=function(e){return arguments.length?(p=e,d):p},d.animate=function(e){return arguments.length?(i=e,d):i},d.color=function(t){return arguments.length?(f=e.utils.getColor(t),d):f},d},e.models.sparklinePlus=function(){function v(e){return e.each(function(c){function O(){if(a)return;var e=C.selectAll(".nv-hoverValue").data(u),r=e.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);e.exit().style("stroke-opacity",0).style("fill-opacity",0).remove(),e.attr("transform",function(e){return"translate("+s(t.x()(c[e],e))+",0)"}).style("stroke-opacity",1).style("fill-opacity",1);if(!u.length)return;r.append("line").attr("x1",0).attr("y1",-n.top).attr("x2",0).attr("y2",b),r.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-n.top).attr("text-anchor","end").attr("dy",".9em"),C.select(".nv-hoverValue .nv-xValue").text(f(t.x()(c[u[0]],u[0]))),r.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-n.top).attr("text-anchor","start").attr("dy",".9em"),C.select(".nv-hoverValue .nv-yValue").text(l(t.y()(c[u[0]],u[0])))}function M(){function r(e,n){var r=Math.abs(t.x()(e[0],0)-n),i=0;for(var s=0;s<e.length;s++)Math.abs(t.x()(e[s],s)-n)<r&&(r=Math.abs(t.x()(e[s],s)-n),i=s);return i}if(a)return;var e=d3.mouse(this)[0]-n.left;u=[r(c,Math.round(s.invert(e)))],O()}var m=d3.select(this),g=(r||parseInt(m.style("width"))||960)-n.left-n.right,b=(i||parseInt(m.style("height"))||400)-n.top-n.bottom;v.update=function(){v(e)},v.container=this;if(!c||!c.length){var w=m.selectAll(".nv-noData").data([d]);return w.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),w.attr("x",n.left+g/2).attr("y",n.top+b/2).text(function(e){return e}),v}m.selectAll(".nv-noData").remove();var E=t.y()(c[c.length-1],c.length-1);s=t.xScale(),o=t.yScale();var S=m.selectAll("g.nv-wrap.nv-sparklineplus").data([c]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-sparklineWrap"),N.append("g").attr("class","nv-valueWrap"),N.append("g").attr("class","nv-hoverArea"),S.attr("transform","translate("+n.left+","+n.top+")");var k=C.select(".nv-sparklineWrap");t.width(g).height(b),k.call(t);var L=C.select(".nv-valueWrap"),A=L.selectAll(".nv-currentValue").data([E]);A.enter().append("text").attr("class","nv-currentValue").attr("dx",p?-8:8).attr("dy",".9em").style("text-anchor",p?"end":"start"),A.attr("x",g+(p?n.right:0)).attr("y",h?function(e){return o(e)}:0).style("fill",t.color()(c[c.length-1],c.length-1)).text(l(E)),N.select(".nv-hoverArea").append("rect").on("mousemove",M).on("click",function(){a=!a}).on("mouseout",function(){u=[],O()}),C.select(".nv-hoverArea rect").attr("transform",function(e){return"translate("+ -n.left+","+ -n.top+")"}).attr("width",g+n.left+n.right).attr("height",b+n.top)}),v}var t=e.models.sparkline(),n={top:15,right:100,bottom:10,left:50},r=null,i=null,s,o,u=[],a=!1,f=d3.format(",r"),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d="No Data Available.";return v.sparkline=t,d3.rebind(v,t,"x","y","xScale","yScale","color"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,v):n},v.width=function(e){return arguments.length?(r=e,v):r},v.height=function(e){return arguments.length?(i=e,v):i},v.xTickFormat=function(e){return arguments.length?(f=e,v):f},v.yTickFormat=function(e){return arguments.length?(l=e,v):l},v.showValue=function(e){return arguments.length?(c=e,v):c},v.alignValue=function(e){return arguments.length?(h=e,v):h},v.rightAlignValue=function(e){return arguments.length?(p=e,v):p},v.noData=function(e){return arguments.length?(d=e,v):d},v},e.models.stackedArea=function(){function g(e){return e.each(function(e){var a=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);p=v.xScale(),d=v.yScale();var E=e;e.forEach(function(e,t){e.seriesIndex=t,e.values=e.values.map(function(e,n){return e.index=n,e.seriesIndex=t,e})});var S=e.filter(function(e){return!e.disabled});e=d3.layout.stack().order(l).offset(f).values(function(e){return e.values}).x(o).y(u).out(function(e,t,n){var r=u(e)===0?0:n;e.display={y:r,y0:t}})(S);var T=w.selectAll("g.nv-wrap.nv-stackedarea").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),C=N.append("defs"),k=N.append("g"),L=T.select("g");k.append("g").attr("class","nv-areaWrap"),k.append("g").attr("class","nv-scatterWrap"),T.attr("transform","translate("+t.left+","+t.top+")"),v.width(a).height(b).x(o).y(function(e){return e.display.y+e.display.y0}).forceY([0]).color(e.map(function(e,t){return e.color||i(e,e.seriesIndex)}));var A=L.select(".nv-scatterWrap").datum(e);A.call(v),C.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),T.select("#nv-edge-clip-"+s+" rect").attr("width",a).attr("height",b),L.attr("clip-path",h?"url(#nv-edge-clip-"+s+")":"");var O=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y+e.display.y0)}).interpolate(c),M=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y0)}),_=L.select(".nv-areaWrap").selectAll("path.nv-area").data(function(e){return e});_.enter().append("path").attr("class",function(e,t){return"nv-area nv-area-"+t}).attr("d",function(e,t){return M(e.values,e.seriesIndex)}).on("mouseover",function(e,t){d3.select(this).classed("hover",!0),m.areaMouseover({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),m.areaMouseout({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("click",function(e,t){d3.select(this).classed("hover",!1),m.areaClick({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}),_.exit().remove(),_.style("fill",function(e,t){return e.color||i(e,e.seriesIndex)}).style("stroke",function(e,t){return e.color||i(e,e.seriesIndex)}),_.attr("d",function(e,t){return O(e.values,t)}),v.dispatch.on("elementMouseover.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!0)}),v.dispatch.on("elementMouseout.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!1)}),g.d3_stackedOffset_stackPercent=function(e){var t=e.length,n=e[0].length,r=1/t,i,s,o,a=[];for(s=0;s<n;++s){for(i=0,o=0;i<E.length;i++)o+=u(E[i].values[s]);if(o)for(i=0;i<t;i++)e[i][s][1]/=o;else for(i=0;i<t;i++)e[i][s][1]=r}for(s=0;s<n;++s)a[s]=0;return a}}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=function(e){return e.x},u=function(e){return e.y},a="stack",f="zero",l="default",c="linear",h=!1,p,d,v=e.models.scatter(),m=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout");return v.size(2.2).sizeDomain([2.2,2.2]),v.dispatch.on("elementClick.area",function(e){m.areaClick(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],m.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){m.tooltipHide(e)}),g.dispatch=m,g.scatter=v,d3.rebind(g,v,"interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","highlightPoint","clearHighlights"),g.options=e.utils.optionsFunc.bind(g),g.x=function(e){return arguments.length?(o=d3.functor(e),g):o},g.y=function(e){return arguments.length?(u=d3.functor(e),g):u},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.clipEdge=function(e){return arguments.length?(h=e,g):h},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),g):i},g.offset=function(e){return arguments.length?(f=e,g):f},g.order=function(e){return arguments.length?(l=e,g):l},g.style=function(e){if(!arguments.length)return a;a=e;switch(a){case"stack":g.offset("zero"),g.order("default");break;case"stream":g.offset("wiggle"),g.order("inside-out");break;case"stream-center":g.offset("silhouette"),g.order("inside-out");break;case"expand":g.offset("expand"),g.order("default");break;case"stack_percent":g.offset(g.d3_stackedOffset_stackPercent),g.order("default")}return g},g.interpolate=function(e){return arguments.length?(c=e,g):c},g},e.models.stackedAreaChart=function(){function M(y){return y.each(function(y){var A=d3.select(this),_=this,D=(a||parseInt(A.style("width"))||960)-u.left-u.right,P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom;M.update=function(){A.call(M)},M.container=this,S.disabled=y.map(function(e){return!!e.disabled});if(!x){var H;x={};for(H in S)S[H]instanceof Array?x[H]=S[H].slice(0):x[H]=S[H]}if(!y||!y.length||!y.filter(function(e){return e.values.length}).length){var B=A.selectAll(".nv-noData").data([T]);return B.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),B.attr("x",u.left+D/2).attr("y",u.top+P/2).text(function(e){return e}),M}A.selectAll(".nv-noData").remove(),b=t.xScale(),w=t.yScale();var j=A.selectAll("g.nv-wrap.nv-stackedAreaChart").data([y]),F=j.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),I=j.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-stackedWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-controlsWrap"),F.append("g").attr("class","nv-interactive"),I.select("rect").attr("width",D).attr("height",P);if(h){var q=c?D-C:D;i.width(q),I.select(".nv-legendWrap").datum(y).call(i),u.top!=i.height()&&(u.top=i.height(),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-legendWrap").attr("transform","translate("+(D-q)+","+ -u.top+")")}if(c){var R=[{key:L.stacked||"Stacked",metaKey:"Stacked",disabled:t.style()!="stack",style:"stack"},{key:L.stream||"Stream",metaKey:"Stream",disabled:t.style()!="stream",style:"stream"},{key:L.expanded||"Expanded",metaKey:"Expanded",disabled:t.style()!="expand",style:"expand"},{key:L.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:t.style()!="stack_percent",style:"stack_percent"}];C=k.length/3*260,R=R.filter(function(e){return k.indexOf(e.metaKey)!==-1}),s.width(C).color(["#444","#444","#444"]),I.select(".nv-controlsWrap").datum(R).call(s),u.top!=Math.max(s.height(),i.height())&&(u.top=Math.max(s.height(),i.height()),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-controlsWrap").attr("transform","translate(0,"+ -u.top+")")}j.attr("transform","translate("+u.left+","+u.top+")"),v&&I.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),m&&(o.width(D).height(P).margin({left:u.left,top:u.top}).svgContainer(A).xScale(b),j.select(".nv-interactive").call(o)),t.width(D).height(P);var U=I.select(".nv-stackedWrap").datum(y);U.call(t),p&&(n.scale(b).ticks(D/100).tickSize(-P,0),I.select(".nv-x.nv-axis").attr("transform","translate(0,"+P+")"),I.select(".nv-x.nv-axis").call(n)),d&&(r.scale(w).ticks(t.offset()=="wiggle"?0:P/36).tickSize(-D,0).setTickFormat(t.style()=="expand"||t.style()=="stack_percent"?d3.format("%"):E),I.select(".nv-y.nv-axis").call(r)),t.dispatch.on("areaClick.toggle",function(e){y.filter(function(e){return!e.disabled}).length===1?y.forEach(function(e){e.disabled=!1}):y.forEach(function(t,n){t.disabled=n!=e.seriesIndex}),S.disabled=y.map(function(e){return!!e.disabled}),N.stateChange(S),M.update()}),i.dispatch.on("stateChange",function(e){S.disabled=e.disabled,N.stateChange(S),M.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;R=R.map(function(e){return e.disabled=!0,e}),e.disabled=!1,t.style(e.style),S.style=t.style(),N.stateChange(S),M.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,a,f,c=[];y.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){a=e.interactiveBisect(n.values,i.pointXValue,M.x()),t.highlightPoint(r,a,!0);var o=n.values[a];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof f=="undefined"&&(f=M.xScale()(M.x()(o,a)));var u=t.style()=="expand"?o.display.y:M.y()(o,a);c.push({key:n.key,value:u,color:l(n,n.seriesIndex),stackedValue:o.display})}),c.reverse();if(c.length>2){var h=M.yScale().invert(i.mouseY),p=Infinity,d=null;c.forEach(function(e,t){h=Math.abs(h);var n=Math.abs(e.stackedValue.y0),r=Math.abs(e.stackedValue.y);if(h>=n&&h<=r+n){d=t;return}}),d!=null&&(c[d].highlight=!0)}var v=n.tickFormat()(M.x()(s,a)),m=t.style()=="expand"?function(e,t){return d3.format(".1%")(e)}:function(e,t){return r.tickFormat()(e)};o.tooltip.position({left:f+u.left,top:i.mouseY+u.top}).chartContainer(_.parentNode).enabled(g).valueFormatter(m).data({value:v,series:c})(),o.renderGuideLine(f)}),o.dispatch.on("elementMouseout",function(e){N.tooltipHide(),t.clearHighlights()}),N.on("tooltipShow",function(e){g&&O(e,_.parentNode)}),N.on("changeState",function(e){typeof e.disabled!="undefined"&&y.length===e.disabled.length&&(y.forEach(function(t,n){t.disabled=e.disabled[n]}),S.disabled=e.disabled),typeof e.style!="undefined"&&t.style(e.style),M.update()})}),M}var t=e.models.stackedArea(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:25,bottom:50,left:60},a=null,f=null,l=e.utils.defaultColor(),c=!0,h=!0,p=!0,d=!0,v=!1,m=!1,g=!0,y=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},b,w,E=d3.format(",.2f"),S={style:t.style()},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=250,k=["Stacked","Stream","Expanded"],L={},A=0;n.orient("bottom").tickPadding(7),r.orient(v?"right":"left"),s.updateState(!1);var O=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=y(i.series.key,a,f,i,M);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("tooltipShow",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],N.tooltipShow(e)}),t.dispatch.on("tooltipHide",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){g&&e.tooltip.cleanup()}),M.dispatch=N,M.stacked=t,M.legend=i,M.controls=s,M.xAxis=n,M.yAxis=r,M.interactiveLayer=o,d3.rebind(M,t,"x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","sizeDomain","interactive","useVoronoi","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),M.options=e.utils.optionsFunc.bind(M),M.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,M):u},M.width=function(e){return arguments.length?(a=e,M):a},M.height=function(e){return arguments.length?(f=e,M):f},M.color=function(n){return arguments.length?(l=e.utils.getColor(n),i.color(l),t.color(l),M):l},M.showControls=function(e){return arguments.length?(c=e,M):c},M.showLegend=function(e){return arguments.length?(h=e,M):h},M.showXAxis=function(e){return arguments.length?(p=e,M):p},M.showYAxis=function(e){return arguments.length?(d=e,M):d},M.rightAlignYAxis=function(e){return arguments.length?(v=e,r.orient(e?"right":"left"),M):v},M.useInteractiveGuideline=function(e){return arguments.length?(m=e,e===!0&&(M.interactive(!1),M.useVoronoi(!1)),M):m},M.tooltip=function(e){return arguments.length?(y=e,M):y},M.tooltips=function(e){return arguments.length?(g=e,M):g},M.tooltipContent=function(e){return arguments.length?(y=e,M):y},M.state=function(e){return arguments.length?(S=e,M):S},M.defaultState=function(e){return arguments.length?(x=e,M):x},M.noData=function(e){return arguments.length?(T=e,M):T},M.transitionDuration=function(e){return arguments.length?(A=e,M):A},M.controlsData=function(e){return arguments.length?(k=e,M):k},M.controlLabels=function(e){return arguments.length?typeof e!="object"?L:(L=e,M):L},r.setTickFormat=r.tickFormat,r.tickFormat=function(e){return arguments.length?(E=e,r):E},M}}(),define("plugin/plugins/nvd3/nv.d3",function(){}),define("plugin/charts/nvd3/common/config",["plugin/charts/forms/default","plugin/plugins/nvd3/nv.d3"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"NVD3",tag:"svg",keywords:"small"})}),define("plugin/charts/nvd3/bar/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/line_focus/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus",category:"Others",zoomable:"native",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/pie/config",["plugin/plugins/nvd3/nv.d3"],function(){return $.extend(!0,{},{title:"Pie chart",category:"Area charts",library:"NVD3",tag:"svg",keywords:"small",columns:{label:{title:"Labels",is_label:!0,is_auto:!0},y:{title:"Values",is_numeric:!0}},settings:{main_separator:{type:"separator",title:"Pie chart settings"},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{init:"true",hide:!0}}})}),define("plugin/charts/nvd3/stackedarea_full/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Expanded",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea_stream/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stream",category:"Area charts",zoomable:!0,keywords:"default small",showmaxmin:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/histogram/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogram",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{x_axis_label:{init:"Values"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_precision:{init:".2"}}})}),define("plugin/charts/nvd3/line/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/scatter/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/common/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"jqPlot",tag:"div",zoomable:!0,keywords:"medium",settings:{separator_grid:{title:"Grids",type:"separator"},x_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the X axis?",type:"radiobutton",init:"false",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]},y_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the Y axis?",type:"radiobutton",init:"true",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]}}})}),define("plugin/charts/jqplot/bar/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/line/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/scatter/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}},settings:{x_axis_grid:{init:"true"}}})}),define("plugin/charts/jqplot/boxplot/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Box plot",category:"Data processing (requires 'charts' tool from Toolshed)",library:"jqPlot",tag:"div",execute:"boxplot",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{show_legend:{init:"false"}}})}),define("plugin/charts/jqplot/histogram_discrete/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Discrete Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogramdiscrete",keywords:"small medium large",columns:{x:{title:"Observations",is_label:!0}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"}}})}),define("plugin/charts/others/heatmap/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"Heatmap",category:"Others",library:"Custom",tag:"svg",keywords:"small",zoomable:!0,columns:{x:{title:"Column labels",is_label:!0,is_numeric:!0,is_unique:!0},y:{title:"Row labels",is_label:!0,is_numeric:!0,is_unique:!0},z:{title:"Observation",is_numeric:!0}},settings:{use_panels:{init:"true",hide:!0},color_set:{title:"Color scheme",info:"Select a color scheme for your heatmap",type:"select",init:"jet",data:[{label:"Cold-to-Hot",value:"hot"},{label:"Cool",value:"cool"},{label:"Copper",value:"copper"},{label:"Gray scale",value:"gray"},{label:"Jet",value:"jet"},{label:"No-Green",value:"no_green"},{label:"Ocean",value:"ocean"},{label:"Polar",value:"polar"},{label:"Red-to-Green",value:"redgreen"},{label:"Red-to-green (saturated)",value:"red2green"},{label:"Relief",value:"relief"},{label:"Seismograph",value:"seis"},{label:"Sealand",value:"sealand"},{label:"Split",value:"split"},{label:"Wysiwyg",value:"wysiwyg"}]},url_template:{title:"Url template",info:"Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.",type:"text",init:"",placeholder:"http://someurl.com?id=__LABEL__"}}})}),define("plugin/charts/others/heatmap_cluster/config",["plugin/charts/others/heatmap/config"],function(e){return $.extend(!0,{},e,{title:"Clustered Heatmap",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"heatmap",keywords:"small medium large"})}),define("plugin/charts/types",["plugin/charts/nvd3/bar/config","plugin/charts/nvd3/bar_stacked/config","plugin/charts/nvd3/bar_horizontal/config","plugin/charts/nvd3/bar_horizontal_stacked/config","plugin/charts/nvd3/line_focus/config","plugin/charts/nvd3/pie/config","plugin/charts/nvd3/stackedarea_full/config","plugin/charts/nvd3/stackedarea_stream/config","plugin/charts/nvd3/histogram/config","plugin/charts/nvd3/line/config","plugin/charts/nvd3/scatter/config","plugin/charts/nvd3/stackedarea/config","plugin/charts/jqplot/bar/config","plugin/charts/jqplot/line/config","plugin/charts/jqplot/scatter/config","plugin/charts/jqplot/boxplot/config","plugin/charts/jqplot/histogram_discrete/config","plugin/charts/others/heatmap/config","plugin/charts/others/heatmap_cluster/config"],function(e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y){return Backbone.Model.extend({defaults:{nvd3_bar:e,nvd3_bar_stacked:t,nvd3_bar_horizontal:n,nvd3_bar_horizontal_stacked:r,nvd3_line_focus:i,nvd3_stackedarea:c,nvd3_stackedarea_full:o,nvd3_stackedarea_stream:u,nvd3_pie:s,nvd3_line:f,nvd3_scatter:l,nvd3_histogram:a,jqplot_bar:h,jqplot_histogram_discrete:m,jqplot_line:p,jqplot_scatter:d,jqplot_boxplot:v,others_heatmap:g,others_heatmap_cluster:y}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","utils/deferred","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c,h){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new l,this.types=new h,this.chart=new c,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.deferred=new u,this.viewer_view=new a(this),this.editor_view=new f(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el);if(!this.storage.load())this.go("editor");else{this.go("viewer");var n=this;this.deferred.execute(function(){n.chart.trigger("redraw")})}},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},chartPath:function(e){var t=e.split(/_(.+)/);return t.length>=2?t[0]+"/"+t[1]:(console.debug("FAILED App:chartPath() - Invalid format: "+e),undefined)}})});
\ No newline at end of file
diff -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 -r aea916e9d68d4953003d9b913bea3ddd80749cc9 config/plugins/visualizations/charts/static/views/group.js
--- a/config/plugins/visualizations/charts/static/views/group.js
+++ b/config/plugins/visualizations/charts/static/views/group.js
@@ -254,7 +254,9 @@
if (key_text === undefined) {
key_text = '';
}
- this.group_key.value(key_text);
+ if (key_text != this.group_key.value()) {
+ this.group_key.value(key_text);
+ }
}
});
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/6485ce612ca8/
Changeset: 6485ce612ca8
User: dannon
Date: 2015-01-13 22:09:52+00:00
Summary: Remove echo of exception from message. It is still logged. The message as-is tells the user to contact an admin if they don't get an email.
Affected #: 1 file
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 6485ce612ca842464d6290e6cae33bb16265e6e8 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1167,8 +1167,6 @@
trans.sa_session.flush()
trans.log_event( "User reset password: %s" % email )
except Exception, e:
- status = 'error'
- message = 'Failed to reset password: %s' % str( e )
log.exception( 'Unable to reset password.' )
return trans.fill_template( '/user/reset_password.mako',
message=message,
https://bitbucket.org/galaxy/galaxy-central/commits/f73ddd949744/
Changeset: f73ddd949744
User: dannon
Date: 2015-01-14 14:44:33+00:00
Summary: Admins should have to re-authenticate to change password via this mechanism as well.
Affected #: 1 file
diff -r 6485ce612ca842464d6290e6cae33bb16265e6e8 -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 templates/user/change_password.mako
--- a/templates/user/change_password.mako
+++ b/templates/user/change_password.mako
@@ -10,7 +10,7 @@
<div class="toolFormTitle">Change Password</div>
%if token:
<input type="hidden" name="token" value="${token|h}"/>
- %elif not is_admin:
+ %else:
<div class="form-row"><label>Current password:</label><input type="password" name="current" value="" size="40"/>
https://bitbucket.org/galaxy/galaxy-central/commits/292aa159ad5b/
Changeset: 292aa159ad5b
User: dannon
Date: 2015-01-14 14:44:56+00:00
Summary: Merge.
Affected #: 34 files
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -8,16 +8,18 @@
5e605ed6069fe4c5ca9875e95e91b2713499e8ca release_2014.02.10
9e53251b0b7e93b9563008a2b112f2e815a04bbc release_2014.04.14
7e257c7b10badb65772b1528cb61d58175a42e47 release_2014.06.02
-7a4d321c0e38fa263ea83d29a35a608c3181fcba latest_2014.06.02
-9661b9d5d5b330483ae3ad2236410e0efaa7c500 latest_2014.04.14
-6b0bd93038a843b1585155f0d63f0eea2459c70b latest_2013.01.13
-3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 latest_2013.02.08
-425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 latest_2013.04.01
-9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 latest_2013.06.03
-9ed84cd208e07e8985ec917cb025fcbbb09edcfb latest_2013.08.12
-81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
-2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
+4145417a6e1c13f82a3de365aadef0fb3ed7ab14 latest_2014.06.02
+8f9dcac033694e4cabcf5daae5cca1cfefbe967f latest_2014.04.14
+9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
+b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
+dec9431d66b837a208e2f060d90afd913c721227 latest_2013.04.01
+19e56e66b0b344c6e2afa4541f6988e4fdb9af29 latest_2013.06.03
+cee903b8b3eee9145627ee89742555dac581791e latest_2013.08.12
+7d5aa19a166cba9039e15f338a1e3fc924c43d3a latest_2013.11.04
+0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
-548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
+8150024c0e6fc5aef3033cf8aaa574896f6b5d0d latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-5834b1066462dd219f67c1c3cbd77c78e7cf3a6c latest_2014.10.06
+c437b28348a9345db8433e5b4f0e05ec8fb6c38a latest_2014.10.06
+2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee release_2015.01.13
+2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee latest_2015.01.13
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 client/galaxy/scripts/mvc/tools/tools-form-base.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-base.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -111,7 +111,7 @@
this.tree.finalize();
// show errors
- if (!this.workflow && options.errors) {
+ if (options.errors) {
var error_messages = this.tree.matchResponse(options.errors);
for (var input_id in error_messages) {
this.highlight(input_id, error_messages[input_id], true);
@@ -131,6 +131,9 @@
this.element_list[i].reset();
}
});
+
+ // refresh
+ this.trigger('refresh');
},
/** Renders the UI elements required for the form
@@ -145,7 +148,7 @@
// button for version selection
var requirements_button = new Ui.ButtonIcon({
icon : 'fa-info-circle',
- title : 'Requirements',
+ title : (!this.workflow && 'Requirements') || null,
tooltip : 'Display tool requirements',
onclick : function() {
if (!this.visible) {
@@ -170,7 +173,7 @@
// button for version selection
var versions_button = new Ui.ButtonMenu({
icon : 'fa-cubes',
- title : 'Versions',
+ title : (!this.workflow && 'Versions') || null,
tooltip : 'Select another tool version'
});
if (options.versions && options.versions.length > 1) {
@@ -200,7 +203,7 @@
// button menu
var menu_button = new Ui.ButtonMenu({
icon : 'fa-caret-down',
- title : 'Options',
+ title : (!this.workflow && 'Options') || null,
tooltip : 'View available options'
});
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 client/galaxy/scripts/mvc/tools/tools-form-workflow.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
@@ -9,6 +9,7 @@
initialize: function(options) {
// link with node representation in workflow module
this.node = workflow.active_node;
+
if (!this.node) {
console.debug('FAILED - tools-form-workflow:initialize() - Node not found in workflow.');
return;
@@ -18,6 +19,22 @@
this.workflow = true;
this.options = options;
+ // declare fields as optional
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type) {
+ item.optional = (['data', 'data_hidden', 'hidden', 'drill_down']).indexOf(item.type) == -1;
+ }
+ });
+
+ // declare conditional fields as not optional
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type) {
+ if (item.type == 'conditional') {
+ item.test_param.optional = false;
+ }
+ }
+ });
+
// load extension
var self = this;
Utils.get({
@@ -38,6 +55,7 @@
inputs[Utils.uuid()] = {
label : 'Edit Step Attributes',
type : 'section',
+ expand : this.node.annotation,
inputs : [{
label : 'Annotation / Notes',
name : 'annotation',
@@ -160,7 +178,10 @@
type : 'boolean',
value : 'false',
ignore : 'false',
- help : 'This action will send an email notifying you when the job is done.'
+ help : 'This action will send an email notifying you when the job is done.',
+ payload : {
+ 'host' : window.location.host
+ }
},{
action : 'DeleteIntermediatesAction',
label : 'Delete non-outputs',
@@ -173,31 +194,51 @@
// visit input nodes and enrich by name/value pairs from server data
var self = this;
- function visit (inputs) {
- for (var i in inputs) {
- var input = inputs[i];
+ function visit (head, head_list) {
+ head_list = head_list || [];
+ head_list.push(head);
+ for (var i in head.inputs) {
+ var input = head.inputs[i];
if (input.action) {
+ // construct identifier as expected by backend
input.name = 'pja__' + output_id + '__' + input.action;
if (input.argument) {
input.name += '__' + input.argument;
}
+
+ // modify names of payload arguments
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ var p = input.payload[p_id];
+ input.payload[input.name + '__' + p_id] = p;
+ delete p;
+ }
+ }
+
+ // access/verify existence of value
var d = self.post_job_actions[input.action + output_id];
if (d) {
+ // mark as expanded
+ for (var j in head_list) {
+ head_list[j].expand = true;
+ }
+
+ // update input field value
if (input.argument) {
input.value = d.action_arguments && d.action_arguments[input.argument] || input.value;
} else {
input.value = 'true';
}
}
- } else {
- if (input.inputs) {
- visit(input.inputs);
- }
+ }
+ // continue with sub section
+ if (input.inputs) {
+ visit(input, head_list.slice(0));
}
}
}
- visit(input_config.inputs);
-
+ visit(input_config);
+
// return final configuration
return input_config;
},
@@ -205,6 +246,15 @@
/** Builds a new model through api call and recreates the entire form
*/
_buildModel: function() {
+ Galaxy.modal.show({
+ title : 'Coming soon...',
+ body : 'This feature has not been implemented yet.',
+ buttons : {
+ 'Close' : function() {
+ Galaxy.modal.hide();
+ }
+ }
+ });
},
/** Request a new model for an already created tool form and updates the form inputs
@@ -231,7 +281,7 @@
data : current_state,
success : function(data) {
// update node in workflow module
- self.node.update_field_data(data, true);
+ self.node.update_field_data(data);
// process completed
self.deferred.done(process_id);
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 client/galaxy/scripts/mvc/tools/tools-input.js
--- a/client/galaxy/scripts/mvc/tools/tools-input.js
+++ b/client/galaxy/scripts/mvc/tools/tools-input.js
@@ -12,6 +12,7 @@
// link field
this.field = options.field;
+ this.defaultvalue = options.defaultvalue;
// set element
this.setElement(this._template(options));
@@ -25,8 +26,13 @@
// add field element
this.$field.prepend(this.field.$el);
- // start with enabled optional fields
+ // decide wether to expand or collapse optional fields
this.field.skip = false;
+ var v = this.field.value && this.field.value();
+ this.field.skip = Boolean(options.optional &&
+ ((this.field.validate && !this.field.validate()) || !v ||
+ (v == this.defaultvalue) || (Number(v) == Number(this.defaultvalue)) ||
+ (JSON.stringify(v) == JSON.stringify(this.defaultvalue))));
// refresh view
this._refresh();
@@ -63,11 +69,12 @@
if (!this.field.skip) {
this.$field.fadeIn('fast');
this.$title_optional.html('Disable');
- this.app.trigger('refresh');
} else {
this.$field.hide();
this.$title_optional.html('Enable');
+ this.field.value && this.field.value(this.defaultvalue);
}
+ this.app.trigger('refresh');
},
/** Main Template
@@ -82,7 +89,7 @@
// is optional
if (options.optional) {
- tmp += 'Optional: ' + options.label +
+ tmp += options.label +
'<span> [<span class="ui-table-form-title-optional"/>]</span>';
} else {
tmp += options.label;
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -232,9 +232,9 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.title,
- help : input_def.help,
- field : repeat
+ label : input_def.title,
+ help : input_def.help,
+ field : repeat
});
// displays as grouped subsection
@@ -292,6 +292,11 @@
}
});
+ // show sub section if requested
+ if (input_def.expand) {
+ portlet.$header.trigger('click');
+ }
+
// create table row
this.table.add(portlet.$el);
@@ -313,10 +318,11 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.label,
- optional : input_def.optional,
- help : input_def.help,
- field : field
+ label : input_def.label,
+ defaultvalue : input_def.defaultvalue,
+ optional : input_def.optional,
+ help : input_def.help,
+ field : field
});
// add to element list
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 client/galaxy/scripts/mvc/tools/tools-template.js
--- a/client/galaxy/scripts/mvc/tools/tools-template.js
+++ b/client/galaxy/scripts/mvc/tools/tools-template.js
@@ -4,7 +4,7 @@
// tool form templates
return {
help: function(content) {
- return '<div class="toolHelp">' +
+ return '<div class="toolHelp" style="overflow: auto;">' +
'<div class="toolHelpBody">' +
content +
'</div>' +
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 client/galaxy/scripts/mvc/tools/tools-tree.js
--- a/client/galaxy/scripts/mvc/tools/tools-tree.js
+++ b/client/galaxy/scripts/mvc/tools/tools-tree.js
@@ -122,13 +122,21 @@
value = patch[input.type](value);
}
- // handle default value
- if (!field.skip) {
- if (field.validate && !field.validate(value)) {
+ // handle simple value
+ if (!field.skip || self.app.workflow) {
+ if (field.validate && !field.validate()) {
value = null;
}
- if (input.ignore === undefined || (value && input.ignore != value)) {
+ if (input.ignore === undefined || (value !== null && input.ignore != value)) {
+ // add value to submission
add (job_input_id, input.id, value);
+
+ // add payload to submission
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ add (p_id, input.id, input.payload[p_id]);
+ }
+ }
}
}
}
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 client/galaxy/scripts/utils/utils.js
--- a/client/galaxy/scripts/utils/utils.js
+++ b/client/galaxy/scripts/utils/utils.js
@@ -6,6 +6,18 @@
// dependencies
define(["libs/underscore"], function(_) {
+/** Traverse through json
+*/
+function deepeach(dict, callback) {
+ for (var i in dict) {
+ var d = dict[i];
+ if (d && typeof(d) == "object") {
+ callback(d);
+ deepeach(d, callback);
+ }
+ }
+}
+
/**
* Sanitize/escape a string
* @param{String} content - Content to be sanitized
@@ -248,7 +260,8 @@
request: request,
sanitize: sanitize,
textify: textify,
- validate: validate
+ validate: validate,
+ deepeach: deepeach
};
});
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util import stringify_dictionary_keys
from galaxy.util import string_as_bool
from galaxy.util import in_directory
@@ -232,6 +233,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -480,6 +484,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.safe_dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -510,6 +518,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -12,8 +12,10 @@
import threading
import types
import urllib
+import copy
-from galaxy import eggs
+from galaxy import eggs, util
+
eggs.require( "MarkupSafe" ) # MarkupSafe must load before mako
eggs.require( "Mako" )
eggs.require( "elementtree" )
@@ -2150,9 +2152,9 @@
return None
# ensures that input dictionary is jsonifiable
- def sanitize(dict):
+ def sanitize(dict, key='value'):
# get current value
- value = dict['value'] if 'value' in dict else None
+ value = dict[key] if key in dict else None
# jsonify by type
if dict['type'] in ['data']:
@@ -2167,15 +2169,8 @@
value = jsonify(value)
# update and return
- dict['value'] = value
- return dict
+ dict[key] = value
- # initialize state using default parameters
- def initialize_state(trans, inputs, state, context=None):
- context = ExpressionContext(state, context)
- for input in inputs.itervalues():
- state[input.name] = input.get_initial_value(trans, context)
-
# check the current state of a value and update it if necessary
def check_state(trans, input, default_value, context):
value = default_value
@@ -2195,6 +2190,7 @@
def populate_state(trans, inputs, state, errors, incoming, prefix="", context=None ):
context = ExpressionContext(state, context)
for input in inputs.itervalues():
+ state[input.name] = input.get_initial_value(trans, context)
key = prefix + input.name
if input.type == 'repeat':
group_state = state[input.name]
@@ -2207,7 +2203,6 @@
if rep_index < input.max:
new_state = {}
new_state['__index__'] = rep_index
- initialize_state(trans, input.inputs, new_state, context)
group_state.append(new_state)
populate_state(trans, input.inputs, new_state, errors, incoming, prefix=rep_name + "|", context=context)
rep_index += 1
@@ -2223,7 +2218,6 @@
try:
current_case = input.get_current_case(value, trans)
group_state = state[input.name] = {}
- initialize_state(trans, input.cases[current_case].inputs, group_state, context)
populate_state( trans, input.cases[current_case].inputs, group_state, errors, incoming, prefix=group_prefix, context=context)
group_state['__current_case__'] = current_case
except Exception, e:
@@ -2272,13 +2266,17 @@
# identify name
input_name = tool_dict.get('name')
if input_name:
+ # backup default value
+ tool_dict['defaultvalue'] = input.get_initial_value(trans, other_values)
+
# update input value from tool state
if input_name in state_inputs:
tool_dict['value'] = state_inputs[input_name]
-
- # sanitize if value exists
- tool_dict = sanitize(tool_dict)
-
+
+ # sanitize values
+ sanitize(tool_dict, 'value')
+ sanitize(tool_dict, 'defaultvalue')
+
# backup final input dictionary
group_inputs[input_index] = tool_dict
@@ -2303,7 +2301,6 @@
# initialize and populate tool state
state_inputs = {}
state_errors = {}
- initialize_state(trans, self.inputs, state_inputs)
populate_state(trans, self.inputs, state_inputs, state_errors, params.__dict__)
# create basic tool model
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
DatasetCollectionWrapper,
@@ -114,6 +116,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -334,6 +339,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -2,6 +2,7 @@
from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
from galaxy.util import odict
+from galaxy.util.object_wrapper import wrap_with_safe_string
from logging import getLogger
log = getLogger( __name__ )
@@ -162,10 +163,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -190,9 +194,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.datatypes_registry = datatypes_registry
self.false_path = getattr( dataset_path, "false_path", None )
@@ -210,7 +218,7 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
@@ -230,7 +238,7 @@
# object store to find the static location of this
# directory.
try:
- return self.dataset.extra_files_path
+ return self.unsanitized.extra_files_path
except exceptions.ObjectNotFound:
# NestedObjectstore raises an error here
# instead of just returning a non-existent
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -360,46 +360,57 @@
'#': '__pd__'}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -4,6 +4,7 @@
#dbkeys read from disk using builds.txt
from galaxy.util import read_dbnames
from galaxy.util.json import loads
+from galaxy.util.object_wrapper import sanitize_lists_to_string
import os.path
@@ -84,6 +85,7 @@
# use configured server len path
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % dbkey )
+ # Since we are using an unverified dbkey, we will sanitize the dbkey before use
+ chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string( dbkey ) )
chrom_info = os.path.abspath( chrom_info )
return ( chrom_info, db_dataset )
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -80,14 +80,28 @@
message=message,
status=status,
redirect=redirect ) )
- params = galaxy.util.Params( kwd, sanitize = False ) #Sanitize parameters when substituting into command line via input wrappers
- #do param translation here, used by datasource tools
- if tool.input_translator:
- tool.input_translator.translate( params )
+
+ def _validated_params_for( kwd ):
+ params = galaxy.util.Params( kwd, sanitize=False ) # Sanitize parameters when substituting into command line via input wrappers
+ #do param translation here, used by datasource tools
+ if tool.input_translator:
+ tool.input_translator.translate( params )
+ return params
+
+ params = _validated_params_for( kwd )
# We may be visiting Galaxy for the first time ( e.g., sending data from UCSC ),
# so make sure to create a new history if we've never had one before.
history = tool.get_default_history_by_trans( trans, create=True )
- template, vars = tool.handle_input( trans, params.__dict__ )
+ try:
+ template, vars = tool.handle_input( trans, params.__dict__ )
+ except KeyError:
+ # This error indicates (or at least can indicate) there was a
+ # problem with the stored tool_state - it is incompatible with
+ # this variant of the tool - possibly because the tool changed
+ # or because the tool version changed.
+ del kwd[ "tool_state" ]
+ params = _validated_params_for( kwd )
+ template, vars = tool.handle_input( trans, params.__dict__ )
if len( params ) > 0:
trans.log_event( "Tool params: %s" % ( str( params ) ), tool_id=tool_id )
add_frame = AddFrameData()
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/mvc/tools/tools-form-base.js
--- a/static/scripts/mvc/tools/tools-form-base.js
+++ b/static/scripts/mvc/tools/tools-form-base.js
@@ -111,7 +111,7 @@
this.tree.finalize();
// show errors
- if (!this.workflow && options.errors) {
+ if (options.errors) {
var error_messages = this.tree.matchResponse(options.errors);
for (var input_id in error_messages) {
this.highlight(input_id, error_messages[input_id], true);
@@ -131,6 +131,9 @@
this.element_list[i].reset();
}
});
+
+ // refresh
+ this.trigger('refresh');
},
/** Renders the UI elements required for the form
@@ -145,7 +148,7 @@
// button for version selection
var requirements_button = new Ui.ButtonIcon({
icon : 'fa-info-circle',
- title : 'Requirements',
+ title : (!this.workflow && 'Requirements') || null,
tooltip : 'Display tool requirements',
onclick : function() {
if (!this.visible) {
@@ -170,7 +173,7 @@
// button for version selection
var versions_button = new Ui.ButtonMenu({
icon : 'fa-cubes',
- title : 'Versions',
+ title : (!this.workflow && 'Versions') || null,
tooltip : 'Select another tool version'
});
if (options.versions && options.versions.length > 1) {
@@ -200,7 +203,7 @@
// button menu
var menu_button = new Ui.ButtonMenu({
icon : 'fa-caret-down',
- title : 'Options',
+ title : (!this.workflow && 'Options') || null,
tooltip : 'View available options'
});
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/mvc/tools/tools-form-workflow.js
--- a/static/scripts/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/mvc/tools/tools-form-workflow.js
@@ -9,6 +9,7 @@
initialize: function(options) {
// link with node representation in workflow module
this.node = workflow.active_node;
+
if (!this.node) {
console.debug('FAILED - tools-form-workflow:initialize() - Node not found in workflow.');
return;
@@ -18,6 +19,22 @@
this.workflow = true;
this.options = options;
+ // declare fields as optional
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type) {
+ item.optional = (['data', 'data_hidden', 'hidden', 'drill_down']).indexOf(item.type) == -1;
+ }
+ });
+
+ // declare conditional fields as not optional
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type) {
+ if (item.type == 'conditional') {
+ item.test_param.optional = false;
+ }
+ }
+ });
+
// load extension
var self = this;
Utils.get({
@@ -38,6 +55,7 @@
inputs[Utils.uuid()] = {
label : 'Edit Step Attributes',
type : 'section',
+ expand : this.node.annotation,
inputs : [{
label : 'Annotation / Notes',
name : 'annotation',
@@ -160,7 +178,10 @@
type : 'boolean',
value : 'false',
ignore : 'false',
- help : 'This action will send an email notifying you when the job is done.'
+ help : 'This action will send an email notifying you when the job is done.',
+ payload : {
+ 'host' : window.location.host
+ }
},{
action : 'DeleteIntermediatesAction',
label : 'Delete non-outputs',
@@ -173,31 +194,51 @@
// visit input nodes and enrich by name/value pairs from server data
var self = this;
- function visit (inputs) {
- for (var i in inputs) {
- var input = inputs[i];
+ function visit (head, head_list) {
+ head_list = head_list || [];
+ head_list.push(head);
+ for (var i in head.inputs) {
+ var input = head.inputs[i];
if (input.action) {
+ // construct identifier as expected by backend
input.name = 'pja__' + output_id + '__' + input.action;
if (input.argument) {
input.name += '__' + input.argument;
}
+
+ // modify names of payload arguments
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ var p = input.payload[p_id];
+ input.payload[input.name + '__' + p_id] = p;
+ delete p;
+ }
+ }
+
+ // access/verify existence of value
var d = self.post_job_actions[input.action + output_id];
if (d) {
+ // mark as expanded
+ for (var j in head_list) {
+ head_list[j].expand = true;
+ }
+
+ // update input field value
if (input.argument) {
input.value = d.action_arguments && d.action_arguments[input.argument] || input.value;
} else {
input.value = 'true';
}
}
- } else {
- if (input.inputs) {
- visit(input.inputs);
- }
+ }
+ // continue with sub section
+ if (input.inputs) {
+ visit(input, head_list.slice(0));
}
}
}
- visit(input_config.inputs);
-
+ visit(input_config);
+
// return final configuration
return input_config;
},
@@ -205,6 +246,15 @@
/** Builds a new model through api call and recreates the entire form
*/
_buildModel: function() {
+ Galaxy.modal.show({
+ title : 'Coming soon...',
+ body : 'This feature has not been implemented yet.',
+ buttons : {
+ 'Close' : function() {
+ Galaxy.modal.hide();
+ }
+ }
+ });
},
/** Request a new model for an already created tool form and updates the form inputs
@@ -231,7 +281,7 @@
data : current_state,
success : function(data) {
// update node in workflow module
- self.node.update_field_data(data, true);
+ self.node.update_field_data(data);
// process completed
self.deferred.done(process_id);
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/mvc/tools/tools-input.js
--- a/static/scripts/mvc/tools/tools-input.js
+++ b/static/scripts/mvc/tools/tools-input.js
@@ -12,6 +12,7 @@
// link field
this.field = options.field;
+ this.defaultvalue = options.defaultvalue;
// set element
this.setElement(this._template(options));
@@ -25,8 +26,13 @@
// add field element
this.$field.prepend(this.field.$el);
- // start with enabled optional fields
+ // decide wether to expand or collapse optional fields
this.field.skip = false;
+ var v = this.field.value && this.field.value();
+ this.field.skip = Boolean(options.optional &&
+ ((this.field.validate && !this.field.validate()) || !v ||
+ (v == this.defaultvalue) || (Number(v) == Number(this.defaultvalue)) ||
+ (JSON.stringify(v) == JSON.stringify(this.defaultvalue))));
// refresh view
this._refresh();
@@ -63,11 +69,12 @@
if (!this.field.skip) {
this.$field.fadeIn('fast');
this.$title_optional.html('Disable');
- this.app.trigger('refresh');
} else {
this.$field.hide();
this.$title_optional.html('Enable');
+ this.field.value && this.field.value(this.defaultvalue);
}
+ this.app.trigger('refresh');
},
/** Main Template
@@ -82,7 +89,7 @@
// is optional
if (options.optional) {
- tmp += 'Optional: ' + options.label +
+ tmp += options.label +
'<span> [<span class="ui-table-form-title-optional"/>]</span>';
} else {
tmp += options.label;
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/mvc/tools/tools-section.js
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -232,9 +232,9 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.title,
- help : input_def.help,
- field : repeat
+ label : input_def.title,
+ help : input_def.help,
+ field : repeat
});
// displays as grouped subsection
@@ -292,6 +292,11 @@
}
});
+ // show sub section if requested
+ if (input_def.expand) {
+ portlet.$header.trigger('click');
+ }
+
// create table row
this.table.add(portlet.$el);
@@ -313,10 +318,11 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.label,
- optional : input_def.optional,
- help : input_def.help,
- field : field
+ label : input_def.label,
+ defaultvalue : input_def.defaultvalue,
+ optional : input_def.optional,
+ help : input_def.help,
+ field : field
});
// add to element list
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/mvc/tools/tools-template.js
--- a/static/scripts/mvc/tools/tools-template.js
+++ b/static/scripts/mvc/tools/tools-template.js
@@ -4,7 +4,7 @@
// tool form templates
return {
help: function(content) {
- return '<div class="toolHelp">' +
+ return '<div class="toolHelp" style="overflow: auto;">' +
'<div class="toolHelpBody">' +
content +
'</div>' +
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/mvc/tools/tools-tree.js
--- a/static/scripts/mvc/tools/tools-tree.js
+++ b/static/scripts/mvc/tools/tools-tree.js
@@ -122,13 +122,21 @@
value = patch[input.type](value);
}
- // handle default value
- if (!field.skip) {
- if (field.validate && !field.validate(value)) {
+ // handle simple value
+ if (!field.skip || self.app.workflow) {
+ if (field.validate && !field.validate()) {
value = null;
}
- if (input.ignore === undefined || (value && input.ignore != value)) {
+ if (input.ignore === undefined || (value !== null && input.ignore != value)) {
+ // add value to submission
add (job_input_id, input.id, value);
+
+ // add payload to submission
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ add (p_id, input.id, input.payload[p_id]);
+ }
+ }
}
}
}
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/packed/mvc/tools/tools-form-base.js
--- a/static/scripts/packed/mvc/tools/tools-form-base.js
+++ b/static/scripts/packed/mvc/tools/tools-form-base.js
@@ -1,1 +1,1 @@
-define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(!this.workflow&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}})},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:"Versions",tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:"Options",tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
+define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}});this.trigger("refresh")},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!this.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!this.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!this.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/packed/mvc/tools/tools-form-workflow.js
--- a/static/scripts/packed/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/packed/mvc/tools/tools-form-workflow.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:"None"});var f={label:"Edit Step Action: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done."},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(j){for(var l in j){var k=j[l];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}var m=d.post_job_actions[k.action+h];if(m){if(k.argument){k.value=m.action_arguments&&m.action_arguments[k.argument]||k.value}else{k.value="true"}}}else{if(k.inputs){e(k.inputs)}}}}e(f.inputs);return f},_buildModel:function(){},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h,true);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
+define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","drill_down"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",expand:this.node.annotation,inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:"None"});var f={label:"Edit Step Action: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done.",payload:{host:window.location.host}},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/packed/mvc/tools/tools-input.js
--- a/static/scripts/packed/mvc/tools/tools-input.js
+++ b/static/scripts/packed/mvc/tools/tools-input.js
@@ -1,1 +1,1 @@
-define([],function(){return Backbone.View.extend({initialize:function(c,b){this.app=c;this.field=b.field;this.setElement(this._template(b));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable");this.app.trigger("refresh")}else{this.$field.hide();this.$title_optional.html("Enable")}},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+="Optional: "+a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
\ No newline at end of file
+define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.field=c.field;this.defaultvalue=c.defaultvalue;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&((this.field.validate&&!this.field.validate())||!b||(b==this.defaultvalue)||(Number(b)==Number(this.defaultvalue))||(JSON.stringify(b)==JSON.stringify(this.defaultvalue))));this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable")}else{this.$field.hide();this.$title_optional.html("Enable");this.field.value&&this.field.value(this.defaultvalue)}this.app.trigger("refresh")},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+=a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
\ No newline at end of file
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/packed/mvc/tools/tools-section.js
--- a/static/scripts/packed/mvc/tools/tools-section.js
+++ b/static/scripts/packed/mvc/tools/tools-section.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(e,b,h,d,c,a,f){var g=Backbone.View.extend({initialize:function(j,i){this.app=j;this.inputs=i.inputs;i.cls_tr="section-row";this.table=new b.View(i);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var j in this.inputs){this.add(this.inputs[j])}},add:function(k){var j=this;var i=jQuery.extend(true,{},k);i.id=k.id=e.uuid();this.app.input_list[i.id]=i;var l=i.type;switch(l){case"conditional":this._addConditional(i);break;case"repeat":this._addRepeat(i);break;case"section":this._addSection(i);break;default:this._addRow(i)}},_addConditional:function(j){var k=this;j.test_param.id=j.id;var n=this._addRow(j.test_param);n.options.onchange=function(w){var v=k.app.tree.matchCase(j,w);for(var u in j.cases){var q=j.cases[u];var t=j.id+"-section-"+u;var p=k.table.get(t);var s=false;for(var r in q.inputs){if(!q.inputs[r].hidden){s=true;break}}if(u==v&&s){p.fadeIn("fast")}else{p.hide()}}k.app.trigger("refresh")};for(var m in j.cases){var l=j.id+"-section-"+m;var o=new g(this.app,{inputs:j.cases[m].inputs,cls:"ui-table-plain"});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(l)}n.trigger("change")},_addRepeat:function(p){var s=this;var q=0;function n(i,u){var t=p.id+"-section-"+(q++);var v=null;if(u){v=function(){l.del(t);l.retitle(p.title);s.app.trigger("refresh")}}var w=new g(s.app,{inputs:i,cls:"ui-table-plain"});l.add({id:t,title:p.title,$el:w.$el,ondel:v});l.retitle(p.title)}var l=new c.View({title_new:p.title,max:p.max,onnew:function(){n(p.inputs,true);s.app.trigger("refresh")}});var j=p.min;var r=_.size(p.cache);for(var m=0;m<Math.max(r,j);m++){var o=null;if(m<r){o=p.cache[m]}else{o=p.inputs}n(o,m>=j)}var k=new f(this.app,{label:p.title,help:p.help,field:l});k.$el.addClass("ui-table-form-section");this.table.add(k.$el);this.table.append(p.id)},_addSection:function(i){var j=this;var n=new g(j.app,{inputs:i.inputs,cls:"ui-table-plain"});var m=new h.ButtonIcon({icon:"fa-eye-slash",tooltip:"Show/hide section",cls:"ui-button-icon-plain"});var l=new d.View({title:i.label,cls:"ui-portlet-section",operations:{button_visible:m}});l.append(n.$el);var k=false;l.$content.hide();l.$header.css("cursor","pointer");l.$header.on("click",function(){if(k){k=false;l.$content.hide();m.setIcon("fa-eye-slash")}else{k=true;l.$content.fadeIn("fast");m.setIcon("fa-eye")}});this.table.add(l.$el);this.table.append(i.id)},_addRow:function(i){var l=i.id;var j=this._createField(i);this.app.field_list[l]=j;var k=new f(this.app,{label:i.label,optional:i.optional,help:i.help,field:j});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);if(i.hidden){this.table.get(l).hide()}return j},_createField:function(i){var j=null;switch(i.type){case"text":j=this._fieldText(i);break;case"select":j=this._fieldSelect(i);break;case"data":j=this._fieldData(i);break;case"data_collection":j=this._fieldData(i);break;case"data_column":i.error_text="Missing columns in referenced dataset.";j=this._fieldSelect(i);break;case"hidden":j=this._fieldHidden(i);break;case"hidden_data":j=this._fieldHidden(i);break;case"integer":j=this._fieldSlider(i);break;case"float":j=this._fieldSlider(i);break;case"boolean":j=this._fieldBoolean(i);break;case"genomebuild":i.searchable=true;j=this._fieldSelect(i);break;case"drill_down":j=this._fieldDrilldown(i);break;case"baseurl":j=this._fieldHidden(i);break;default:this.app.incompatible=true;if(i.options){j=this._fieldSelect(i)}else{j=this._fieldText(i)}console.debug("tools-form::_addRow() : Auto matched field type ("+i.type+").")}if(i.value!==undefined){j.value(i.value)}return j},_fieldData:function(i){if(this.app.workflow){var k=e.textify(i.extensions.toString());i.info="Data input '"+i.name+"' ("+k+")";return this._fieldHidden(i)}var j=this;return new a.View(this.app,{id:"field-"+i.id,extensions:i.extensions,multiple:i.multiple,type:i.type,data:i.options,onchange:function(){j.app.trigger("refresh")}})},_fieldSelect:function(j){if(this.app.workflow&&j.is_dynamic){if(!e.validate(j.value)){j.value=""}return this._fieldText(j)}var l=[];for(var m in j.options){var n=j.options[m];l.push({label:n[0],value:n[1]})}var o=h.Select;switch(j.display){case"checkboxes":o=h.Checkbox;break;case"radio":o=h.Radio;break}var k=this;return new o.View({id:"field-"+j.id,data:l,error_text:j.error_text||"No options available",multiple:j.multiple,searchable:j.searchable,onchange:function(){k.app.trigger("refresh")}})},_fieldDrilldown:function(i){var j=this;return new h.Drilldown.View({id:"field-"+i.id,data:i.options,display:i.display,onchange:function(){j.app.trigger("refresh")}})},_fieldText:function(i){var j=this;return new h.Input({id:"field-"+i.id,area:i.area,onchange:function(){j.app.trigger("refresh")}})},_fieldSlider:function(i){var j=this;return new h.Slider.View({id:"field-"+i.id,precise:i.type=="float",min:i.min,max:i.max,onchange:function(){j.app.trigger("refresh")}})},_fieldHidden:function(i){return new h.Hidden({id:"field-"+i.id,info:i.info})},_fieldBoolean:function(i){var j=this;return new h.RadioButton.View({id:"field-"+i.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:function(){j.app.trigger("refresh")}})}});return{View:g}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(e,b,h,d,c,a,f){var g=Backbone.View.extend({initialize:function(j,i){this.app=j;this.inputs=i.inputs;i.cls_tr="section-row";this.table=new b.View(i);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var j in this.inputs){this.add(this.inputs[j])}},add:function(k){var j=this;var i=jQuery.extend(true,{},k);i.id=k.id=e.uuid();this.app.input_list[i.id]=i;var l=i.type;switch(l){case"conditional":this._addConditional(i);break;case"repeat":this._addRepeat(i);break;case"section":this._addSection(i);break;default:this._addRow(i)}},_addConditional:function(j){var k=this;j.test_param.id=j.id;var n=this._addRow(j.test_param);n.options.onchange=function(w){var v=k.app.tree.matchCase(j,w);for(var u in j.cases){var q=j.cases[u];var t=j.id+"-section-"+u;var p=k.table.get(t);var s=false;for(var r in q.inputs){if(!q.inputs[r].hidden){s=true;break}}if(u==v&&s){p.fadeIn("fast")}else{p.hide()}}k.app.trigger("refresh")};for(var m in j.cases){var l=j.id+"-section-"+m;var o=new g(this.app,{inputs:j.cases[m].inputs,cls:"ui-table-plain"});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(l)}n.trigger("change")},_addRepeat:function(p){var s=this;var q=0;function n(i,u){var t=p.id+"-section-"+(q++);var v=null;if(u){v=function(){l.del(t);l.retitle(p.title);s.app.trigger("refresh")}}var w=new g(s.app,{inputs:i,cls:"ui-table-plain"});l.add({id:t,title:p.title,$el:w.$el,ondel:v});l.retitle(p.title)}var l=new c.View({title_new:p.title,max:p.max,onnew:function(){n(p.inputs,true);s.app.trigger("refresh")}});var j=p.min;var r=_.size(p.cache);for(var m=0;m<Math.max(r,j);m++){var o=null;if(m<r){o=p.cache[m]}else{o=p.inputs}n(o,m>=j)}var k=new f(this.app,{label:p.title,help:p.help,field:l});k.$el.addClass("ui-table-form-section");this.table.add(k.$el);this.table.append(p.id)},_addSection:function(i){var j=this;var n=new g(j.app,{inputs:i.inputs,cls:"ui-table-plain"});var m=new h.ButtonIcon({icon:"fa-eye-slash",tooltip:"Show/hide section",cls:"ui-button-icon-plain"});var l=new d.View({title:i.label,cls:"ui-portlet-section",operations:{button_visible:m}});l.append(n.$el);var k=false;l.$content.hide();l.$header.css("cursor","pointer");l.$header.on("click",function(){if(k){k=false;l.$content.hide();m.setIcon("fa-eye-slash")}else{k=true;l.$content.fadeIn("fast");m.setIcon("fa-eye")}});if(i.expand){l.$header.trigger("click")}this.table.add(l.$el);this.table.append(i.id)},_addRow:function(i){var l=i.id;var j=this._createField(i);this.app.field_list[l]=j;var k=new f(this.app,{label:i.label,defaultvalue:i.defaultvalue,optional:i.optional,help:i.help,field:j});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);if(i.hidden){this.table.get(l).hide()}return j},_createField:function(i){var j=null;switch(i.type){case"text":j=this._fieldText(i);break;case"select":j=this._fieldSelect(i);break;case"data":j=this._fieldData(i);break;case"data_collection":j=this._fieldData(i);break;case"data_column":i.error_text="Missing columns in referenced dataset.";j=this._fieldSelect(i);break;case"hidden":j=this._fieldHidden(i);break;case"hidden_data":j=this._fieldHidden(i);break;case"integer":j=this._fieldSlider(i);break;case"float":j=this._fieldSlider(i);break;case"boolean":j=this._fieldBoolean(i);break;case"genomebuild":i.searchable=true;j=this._fieldSelect(i);break;case"drill_down":j=this._fieldDrilldown(i);break;case"baseurl":j=this._fieldHidden(i);break;default:this.app.incompatible=true;if(i.options){j=this._fieldSelect(i)}else{j=this._fieldText(i)}console.debug("tools-form::_addRow() : Auto matched field type ("+i.type+").")}if(i.value!==undefined){j.value(i.value)}return j},_fieldData:function(i){if(this.app.workflow){var k=e.textify(i.extensions.toString());i.info="Data input '"+i.name+"' ("+k+")";return this._fieldHidden(i)}var j=this;return new a.View(this.app,{id:"field-"+i.id,extensions:i.extensions,multiple:i.multiple,type:i.type,data:i.options,onchange:function(){j.app.trigger("refresh")}})},_fieldSelect:function(j){if(this.app.workflow&&j.is_dynamic){if(!e.validate(j.value)){j.value=""}return this._fieldText(j)}var l=[];for(var m in j.options){var n=j.options[m];l.push({label:n[0],value:n[1]})}var o=h.Select;switch(j.display){case"checkboxes":o=h.Checkbox;break;case"radio":o=h.Radio;break}var k=this;return new o.View({id:"field-"+j.id,data:l,error_text:j.error_text||"No options available",multiple:j.multiple,searchable:j.searchable,onchange:function(){k.app.trigger("refresh")}})},_fieldDrilldown:function(i){var j=this;return new h.Drilldown.View({id:"field-"+i.id,data:i.options,display:i.display,onchange:function(){j.app.trigger("refresh")}})},_fieldText:function(i){var j=this;return new h.Input({id:"field-"+i.id,area:i.area,onchange:function(){j.app.trigger("refresh")}})},_fieldSlider:function(i){var j=this;return new h.Slider.View({id:"field-"+i.id,precise:i.type=="float",min:i.min,max:i.max,onchange:function(){j.app.trigger("refresh")}})},_fieldHidden:function(i){return new h.Hidden({id:"field-"+i.id,info:i.info})},_fieldBoolean:function(i){var j=this;return new h.RadioButton.View({id:"field-"+i.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:function(){j.app.trigger("refresh")}})}});return{View:g}});
\ No newline at end of file
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/packed/mvc/tools/tools-template.js
--- a/static/scripts/packed/mvc/tools/tools-template.js
+++ b/static/scripts/packed/mvc/tools/tools-template.js
@@ -1,1 +1,1 @@
-define([],function(){return{help:function(a){return'<div class="toolHelp"><div class="toolHelpBody">'+a+"</div></div>"},success:function(c){if(!c.jobs||!c.jobs.length){console.debug("tools-template::success() - Failed jobs.");return}var a=c.jobs.length;var d="";if(a==1){d="1 job has"}else{d=a+" jobs have"}var b='<div class="donemessagelarge"><p>'+d+" been successfully added to the queue - resulting in the following datasets:</p>";for(var e in c.outputs){b+='<p style="padding: 10px 20px;"><b>'+(parseInt(e)+1)+": "+c.outputs[e].name+"</b></p>"}b+="<p>You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.</p></div>";return b},error:function(a){return'<div><p>The server could not complete the request. Please contact the Galaxy Team if this error persists.</p><textarea class="ui-textarea" disabled style="color: black;" rows="6">'+JSON.stringify(a,undefined,4)+"</textarea></div>"},batchMode:function(){return'<div class="ui-table-form-info"><i class="fa fa-sitemap" style="font-size: 1.2em; padding: 2px 5px;"/>This is a batch mode input field. A separate job will be triggered for each dataset.</div>'},requirements:function(a){var d="This tool requires ";for(var b in a.requirements){var c=a.requirements[b];d+=c.name;if(c.version){d+=" (Version "+c.version+")"}if(b<a.requirements.length-2){d+=", "}if(b==a.requirements.length-2){d+=" and "}}return d+'. Click <a target="_blank" href="https://wiki.galaxyproject.org/Tools/Requirements">here</a> for more information.'}}});
\ No newline at end of file
+define([],function(){return{help:function(a){return'<div class="toolHelp" style="overflow: auto;"><div class="toolHelpBody">'+a+"</div></div>"},success:function(c){if(!c.jobs||!c.jobs.length){console.debug("tools-template::success() - Failed jobs.");return}var a=c.jobs.length;var d="";if(a==1){d="1 job has"}else{d=a+" jobs have"}var b='<div class="donemessagelarge"><p>'+d+" been successfully added to the queue - resulting in the following datasets:</p>";for(var e in c.outputs){b+='<p style="padding: 10px 20px;"><b>'+(parseInt(e)+1)+": "+c.outputs[e].name+"</b></p>"}b+="<p>You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.</p></div>";return b},error:function(a){return'<div><p>The server could not complete the request. Please contact the Galaxy Team if this error persists.</p><textarea class="ui-textarea" disabled style="color: black;" rows="6">'+JSON.stringify(a,undefined,4)+"</textarea></div>"},batchMode:function(){return'<div class="ui-table-form-info"><i class="fa fa-sitemap" style="font-size: 1.2em; padding: 2px 5px;"/>This is a batch mode input field. A separate job will be triggered for each dataset.</div>'},requirements:function(a){var d="This tool requires ";for(var b in a.requirements){var c=a.requirements[b];d+=c.name;if(c.version){d+=" (Version "+c.version+")"}if(b<a.requirements.length-2){d+=", "}if(b==a.requirements.length-2){d+=" and "}}return d+'. Click <a target="_blank" href="https://wiki.galaxyproject.org/Tools/Requirements">here</a> for more information.'}}});
\ No newline at end of file
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/packed/mvc/tools/tools-tree.js
--- a/static/scripts/packed/mvc/tools/tools-tree.js
+++ b/static/scripts/packed/mvc/tools/tools-tree.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(o,r){for(var m in r){var k=r[m];if(k.input){var t=k.input;var n=o;if(o!=""){n+="|"}n+=t.name;switch(t.type){case"repeat":var j="section-";var w=[];var q=null;for(var v in k){var p=v.indexOf(j);if(p!=-1){p+=j.length;w.push(parseInt(v.substr(p)));if(!q){q=v.substr(0,p)}}}w.sort(function(x,i){return x-i});var m=0;for(var l in w){c(n+"_"+m++,k[q+w[l]])}break;case"conditional":var u=b.app.field_list[t.id].value();if(g[t.test_param.type]){u=g[t.test_param.type](u)}d(n+"|"+t.test_param.name,t.id,u);var h=b.matchCase(t,u);if(h!=-1){c(n,r[t.id+"-section-"+h])}break;case"section":c("",k);break;default:var s=b.app.field_list[t.id];if(s&&s.value){var u=s.value();if(g[t.type]){u=g[t.type](u)}if(!s.skip){if(s.validate&&!s.validate(u)){u=null}if(t.ignore===undefined||(u&&t.ignore!=u)){d(n,t.id,u)}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(p,s){for(var n in s){var k=s[n];if(k.input){var u=k.input;var o=p;if(p!=""){o+="|"}o+=u.name;switch(u.type){case"repeat":var j="section-";var x=[];var r=null;for(var w in k){var q=w.indexOf(j);if(q!=-1){q+=j.length;x.push(parseInt(w.substr(q)));if(!r){r=w.substr(0,q)}}}x.sort(function(y,i){return y-i});var n=0;for(var l in x){c(o+"_"+n++,k[r+x[l]])}break;case"conditional":var v=b.app.field_list[u.id].value();if(g[u.test_param.type]){v=g[u.test_param.type](v)}d(o+"|"+u.test_param.name,u.id,v);var h=b.matchCase(u,v);if(h!=-1){c(o,s[u.id+"-section-"+h])}break;case"section":c("",k);break;default:var t=b.app.field_list[u.id];if(t&&t.value){var v=t.value();if(g[u.type]){v=g[u.type](v)}if(!t.skip||b.app.workflow){if(t.validate&&!t.validate()){v=null}if(u.ignore===undefined||(v!==null&&u.ignore!=v)){d(o,u.id,v);if(u.payload){for(var m in u.payload){d(m,u.id,u.payload[m])}}}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/packed/utils/utils.js
--- a/static/scripts/packed/utils/utils.js
+++ b/static/scripts/packed/utils/utils.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(m){function d(n){return $("<div/>").text(n).html()}function l(o){if(!(o instanceof Array)){o=[o]}for(var n in o){if(["None",null,"null",undefined,"undefined"].indexOf(o[n])>-1){return false}}return true}function h(n){var n=n.toString();if(n){n=n.replace(/,/g,", ");var o=n.lastIndexOf(", ");if(o!=-1){n=n.substr(0,o)+" or "+n.substr(o+1)}return n}return""}function e(n){top.__utils__get__=top.__utils__get__||{};if(n.cache&&top.__utils__get__[n.url]){n.success&&n.success(top.__utils__get__[n.url]);console.debug("utils.js::get() - Fetching from cache ["+n.url+"].")}else{i({url:n.url,data:n.data,success:function(o){top.__utils__get__[n.url]=o;n.success&&n.success(o)},error:function(o){n.error&&n.error(o)}})}}function i(o){var n={contentType:"application/json",type:o.type||"GET",data:o.data||{},url:o.url};if(n.type=="GET"||n.type=="DELETE"){if(n.url.indexOf("?")==-1){n.url+="?"}else{n.url+="&"}n.url=n.url+$.param(n.data);n.data=null}else{n.dataType="json";n.url=n.url;n.data=JSON.stringify(n.data)}$.ajax(n).done(function(p){if(typeof p==="string"){try{p=p.replace("Infinity,",'"Infinity",');p=jQuery.parseJSON(p)}catch(q){console.debug(q)}}o.success&&o.success(p)}).fail(function(q){var p=null;try{p=jQuery.parseJSON(q.responseText)}catch(r){p=q.responseText}o.error&&o.error(p,q)})}function j(q,n){var o=$('<div class="'+q+'"></div>');o.appendTo(":eq(0)");var p=o.css(n);o.remove();return p}function g(n){if(!$('link[href^="'+n+'"]').length){$('<link href="'+galaxy_config.root+n+'" rel="stylesheet">').appendTo("head")}}function k(n,o){if(n){return m.defaults(n,o)}else{return o}}function b(o,q){var p="";if(o>=100000000000){o=o/100000000000;p="TB"}else{if(o>=100000000){o=o/100000000;p="GB"}else{if(o>=100000){o=o/100000;p="MB"}else{if(o>=100){o=o/100;p="KB"}else{if(o>0){o=o*10;p="b"}else{return"<strong>-</strong>"}}}}}var n=(Math.round(o)/10);if(q){return n+" "+p}else{return"<strong>"+n+"</strong> "+p}}function a(){return"x"+Math.random().toString(36).substring(2,9)}function c(n){var o=$("<p></p>");o.append(n);return o}function f(){var p=new Date();var n=(p.getHours()<10?"0":"")+p.getHours();var o=(p.getMinutes()<10?"0":"")+p.getMinutes();var q=p.getDate()+"/"+(p.getMonth()+1)+"/"+p.getFullYear()+", "+n+":"+o;return q}return{cssLoadFile:g,cssGetAttribute:j,get:e,merge:k,bytesToString:b,uuid:a,time:f,wrap:c,request:i,sanitize:d,textify:h,validate:l}});
\ No newline at end of file
+define(["libs/underscore"],function(m){function n(r,q){for(var o in r){var p=r[o];if(p&&typeof(p)=="object"){q(p);n(p,q)}}}function d(o){return $("<div/>").text(o).html()}function l(p){if(!(p instanceof Array)){p=[p]}for(var o in p){if(["None",null,"null",undefined,"undefined"].indexOf(p[o])>-1){return false}}return true}function h(o){var o=o.toString();if(o){o=o.replace(/,/g,", ");var p=o.lastIndexOf(", ");if(p!=-1){o=o.substr(0,p)+" or "+o.substr(p+1)}return o}return""}function e(o){top.__utils__get__=top.__utils__get__||{};if(o.cache&&top.__utils__get__[o.url]){o.success&&o.success(top.__utils__get__[o.url]);console.debug("utils.js::get() - Fetching from cache ["+o.url+"].")}else{i({url:o.url,data:o.data,success:function(p){top.__utils__get__[o.url]=p;o.success&&o.success(p)},error:function(p){o.error&&o.error(p)}})}}function i(p){var o={contentType:"application/json",type:p.type||"GET",data:p.data||{},url:p.url};if(o.type=="GET"||o.type=="DELETE"){if(o.url.indexOf("?")==-1){o.url+="?"}else{o.url+="&"}o.url=o.url+$.param(o.data);o.data=null}else{o.dataType="json";o.url=o.url;o.data=JSON.stringify(o.data)}$.ajax(o).done(function(q){if(typeof q==="string"){try{q=q.replace("Infinity,",'"Infinity",');q=jQuery.parseJSON(q)}catch(r){console.debug(r)}}p.success&&p.success(q)}).fail(function(r){var q=null;try{q=jQuery.parseJSON(r.responseText)}catch(s){q=r.responseText}p.error&&p.error(q,r)})}function j(r,o){var p=$('<div class="'+r+'"></div>');p.appendTo(":eq(0)");var q=p.css(o);p.remove();return q}function g(o){if(!$('link[href^="'+o+'"]').length){$('<link href="'+galaxy_config.root+o+'" rel="stylesheet">').appendTo("head")}}function k(o,p){if(o){return m.defaults(o,p)}else{return p}}function b(p,r){var q="";if(p>=100000000000){p=p/100000000000;q="TB"}else{if(p>=100000000){p=p/100000000;q="GB"}else{if(p>=100000){p=p/100000;q="MB"}else{if(p>=100){p=p/100;q="KB"}else{if(p>0){p=p*10;q="b"}else{return"<strong>-</strong>"}}}}}var o=(Math.round(p)/10);if(r){return o+" "+q}else{return"<strong>"+o+"</strong> "+q}}function a(){return"x"+Math.random().toString(36).substring(2,9)}function c(o){var p=$("<p></p>");p.append(o);return p}function f(){var q=new Date();var o=(q.getHours()<10?"0":"")+q.getHours();var p=(q.getMinutes()<10?"0":"")+q.getMinutes();var r=q.getDate()+"/"+(q.getMonth()+1)+"/"+q.getFullYear()+", "+o+":"+p;return r}return{cssLoadFile:g,cssGetAttribute:j,get:e,merge:k,bytesToString:b,uuid:a,time:f,wrap:c,request:i,sanitize:d,textify:h,validate:l,deepeach:n}});
\ No newline at end of file
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/scripts/utils/utils.js
--- a/static/scripts/utils/utils.js
+++ b/static/scripts/utils/utils.js
@@ -6,6 +6,18 @@
// dependencies
define(["libs/underscore"], function(_) {
+/** Traverse through json
+*/
+function deepeach(dict, callback) {
+ for (var i in dict) {
+ var d = dict[i];
+ if (d && typeof(d) == "object") {
+ callback(d);
+ deepeach(d, callback);
+ }
+ }
+}
+
/**
* Sanitize/escape a string
* @param{String} content - Content to be sanitized
@@ -248,7 +260,8 @@
request: request,
sanitize: sanitize,
textify: textify,
- validate: validate
+ validate: validate,
+ deepeach: deepeach
};
});
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1412,7 +1412,7 @@
.ui-button-icon-plain{border:none !important;background:none !important;height:inherit !important;width:inherit !important;padding-right:3px !important}
.ui-tabs .ui-tabs-add{font-size:0.8em;margin-right:5px}
.ui-tabs .ui-tabs-delete{font-size:0.8em;margin-left:5px;cursor:pointer}
-.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;clear:both;width:auto;height:100%}.ui-portlet .portlet-header,.ui-portlet-slim .portlet-header{background:#ebd9b2;border-bottom:solid #d6b161 1px;padding:2px 8px;overflow:visible;float:right;width:100%}.ui-portlet .portlet-header .portlet-title,.ui-portlet-slim .portlet-header .portlet-title{display:inline;vertical-align:middle}.ui-portlet .portlet-header .portlet-title .portlet-title-text,.ui-portlet-slim .portlet-header .portlet-title .portlet-title-text{vertical-align:middle}
+.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;clear:both;width:auto;height:100%}.ui-portlet .portlet-header,.ui-portlet-slim .portlet-header{background:#ebd9b2;border-bottom:solid #d6b161 1px;padding:2px 8px;overflow:visible;float:right;width:100%}.ui-portlet .portlet-header .portlet-title,.ui-portlet-slim .portlet-header .portlet-title{display:inline;vertical-align:middle}.ui-portlet .portlet-header .portlet-title .portlet-title-text,.ui-portlet-slim .portlet-header .portlet-title .portlet-title-text{vertical-align:middle;line-height:20px}
.ui-portlet .portlet-header .portlet-title .icon,.ui-portlet-slim .portlet-header .portlet-title .icon{font-size:1.2em;vertical-align:middle}
.ui-portlet .portlet-buttons,.ui-portlet-slim .portlet-buttons{height:50px;padding:10px}
.ui-portlet .portlet-content,.ui-portlet-slim .portlet-content{height:inherit;padding:10px;clear:both}.ui-portlet .portlet-content .content,.ui-portlet-slim .portlet-content .content{padding:10px;height:100%;width:100%}.ui-portlet .portlet-content .content .buttons,.ui-portlet-slim .portlet-content .content .buttons{height:50px;padding:10px}
@@ -1765,7 +1765,7 @@
div.toolFormDisabled{border-color:#bfbfbf}
div.toolHelp{margin-top:15px;padding:5px}
div.toolHelpBody{width:100%}
-.toolForm.toolFormInCanvas{border:solid #d6b161 1px;background:#fff}.toolForm.toolFormInCanvas.toolForm-active{border:solid blue 3px;margin:4px}
+.toolForm.toolFormInCanvas{border:solid #d6b161 1px;background:#fff}.toolForm.toolFormInCanvas.toolForm-active{border:solid #5f6990 3px;margin:4px}
.toolForm.toolFormInCanvas .toolFormTitle{font-size:12px;line-height:1.428571429}
div.form,div.toolForm{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
div.form-title,div.toolFormTitle{padding:5px 10px;background:#ebd9b2;border-bottom:solid #d6b161 1px}
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/style/src/less/base.less
--- a/static/style/src/less/base.less
+++ b/static/style/src/less/base.less
@@ -586,7 +586,7 @@
border: solid @form-border 1px;
background: @white;
&.toolForm-active {
- border: solid blue 3px;
+ border: solid @brand-primary 3px;
margin: 4px;
}
.toolFormTitle {
diff -r f73ddd949744e9f79ca84cecfbfbee4eb923daf4 -r 292aa159ad5b429393c7bd9855bfe28d4eb39cd3 static/style/src/less/ui.less
--- a/static/style/src/less/ui.less
+++ b/static/style/src/less/ui.less
@@ -168,6 +168,7 @@
vertical-align: middle;
.portlet-title-text {
vertical-align: middle;
+ line-height: 20px;
}
.icon {
font-size: 1.2em;
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: guerler: ToolForm/Workflow: Collapse optional parameters for default values
by commits-noreply@bitbucket.org 14 Jan '15
by commits-noreply@bitbucket.org 14 Jan '15
14 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0c1a9c098774/
Changeset: 0c1a9c098774
User: guerler
Date: 2015-01-14 08:26:36+00:00
Summary: ToolForm/Workflow: Collapse optional parameters for default values
Affected #: 12 files
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 client/galaxy/scripts/mvc/tools/tools-form-base.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-base.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -148,7 +148,7 @@
// button for version selection
var requirements_button = new Ui.ButtonIcon({
icon : 'fa-info-circle',
- title : (!self.workflow && 'Requirements') || null,
+ title : (!this.workflow && 'Requirements') || null,
tooltip : 'Display tool requirements',
onclick : function() {
if (!this.visible) {
@@ -173,7 +173,7 @@
// button for version selection
var versions_button = new Ui.ButtonMenu({
icon : 'fa-cubes',
- title : (!self.workflow && 'Versions') || null,
+ title : (!this.workflow && 'Versions') || null,
tooltip : 'Select another tool version'
});
if (options.versions && options.versions.length > 1) {
@@ -203,7 +203,7 @@
// button menu
var menu_button = new Ui.ButtonMenu({
icon : 'fa-caret-down',
- title : (!self.workflow && 'Options') || null,
+ title : (!this.workflow && 'Options') || null,
tooltip : 'View available options'
});
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 client/galaxy/scripts/mvc/tools/tools-form-workflow.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
@@ -19,10 +19,19 @@
this.workflow = true;
this.options = options;
- // traverse through dictionary
+ // declare fields as optional
Utils.deepeach(options.inputs, function(item) {
- if (item.type && (['data', 'data_hidden', 'hidden']).indexOf(item.type) == -1) {
- item.optional = true;
+ if (item.type) {
+ item.optional = (['data', 'data_hidden', 'hidden', 'drill_down']).indexOf(item.type) == -1;
+ }
+ });
+
+ // declare conditional fields as not optional
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type) {
+ if (item.type == 'conditional') {
+ item.test_param.optional = false;
+ }
}
});
@@ -272,7 +281,7 @@
data : current_state,
success : function(data) {
// update node in workflow module
- self.node.update_field_data(data, true);
+ self.node.update_field_data(data);
// process completed
self.deferred.done(process_id);
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 client/galaxy/scripts/mvc/tools/tools-input.js
--- a/client/galaxy/scripts/mvc/tools/tools-input.js
+++ b/client/galaxy/scripts/mvc/tools/tools-input.js
@@ -28,15 +28,12 @@
// decide wether to expand or collapse optional fields
this.field.skip = false;
- if (options.optional) {
- if ((this.field.validate && !this.field.validate()) ||
- (this.field.value && !this.field.value()) ||
- (this.field.value && Number(this.field.value()) == Number(this.defaultvalue)) ||
- (this.field.value && JSON.stringify(this.field.value()) == JSON.stringify(this.defaultvalue))) {
- this.field.skip = true;
- }
- }
-
+ var v = this.field.value && this.field.value();
+ this.field.skip = Boolean(options.optional &&
+ ((this.field.validate && !this.field.validate()) || !v ||
+ (v == this.defaultvalue) || (Number(v) == Number(this.defaultvalue)) ||
+ (JSON.stringify(v) == JSON.stringify(this.defaultvalue))));
+
// refresh view
this._refresh();
@@ -75,7 +72,7 @@
} else {
this.$field.hide();
this.$title_optional.html('Enable');
- this.field.value(this.defaultvalue);
+ this.field.value && this.field.value(this.defaultvalue);
}
this.app.trigger('refresh');
},
@@ -92,7 +89,7 @@
// is optional
if (options.optional) {
- tmp += 'Optional: ' + options.label +
+ tmp += options.label +
'<span> [<span class="ui-table-form-title-optional"/>]</span>';
} else {
tmp += options.label;
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 client/galaxy/scripts/mvc/tools/tools-tree.js
--- a/client/galaxy/scripts/mvc/tools/tools-tree.js
+++ b/client/galaxy/scripts/mvc/tools/tools-tree.js
@@ -123,7 +123,7 @@
}
// handle simple value
- if (!field.skip) {
+ if (!field.skip || self.app.workflow) {
if (field.validate && !field.validate()) {
value = null;
}
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/mvc/tools/tools-form-base.js
--- a/static/scripts/mvc/tools/tools-form-base.js
+++ b/static/scripts/mvc/tools/tools-form-base.js
@@ -148,7 +148,7 @@
// button for version selection
var requirements_button = new Ui.ButtonIcon({
icon : 'fa-info-circle',
- title : (!self.workflow && 'Requirements') || null,
+ title : (!this.workflow && 'Requirements') || null,
tooltip : 'Display tool requirements',
onclick : function() {
if (!this.visible) {
@@ -173,7 +173,7 @@
// button for version selection
var versions_button = new Ui.ButtonMenu({
icon : 'fa-cubes',
- title : (!self.workflow && 'Versions') || null,
+ title : (!this.workflow && 'Versions') || null,
tooltip : 'Select another tool version'
});
if (options.versions && options.versions.length > 1) {
@@ -203,7 +203,7 @@
// button menu
var menu_button = new Ui.ButtonMenu({
icon : 'fa-caret-down',
- title : (!self.workflow && 'Options') || null,
+ title : (!this.workflow && 'Options') || null,
tooltip : 'View available options'
});
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/mvc/tools/tools-form-workflow.js
--- a/static/scripts/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/mvc/tools/tools-form-workflow.js
@@ -19,10 +19,19 @@
this.workflow = true;
this.options = options;
- // traverse through dictionary
+ // declare fields as optional
Utils.deepeach(options.inputs, function(item) {
- if (item.type && (['data', 'data_hidden', 'hidden']).indexOf(item.type) == -1) {
- item.optional = true;
+ if (item.type) {
+ item.optional = (['data', 'data_hidden', 'hidden', 'drill_down']).indexOf(item.type) == -1;
+ }
+ });
+
+ // declare conditional fields as not optional
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type) {
+ if (item.type == 'conditional') {
+ item.test_param.optional = false;
+ }
}
});
@@ -272,7 +281,7 @@
data : current_state,
success : function(data) {
// update node in workflow module
- self.node.update_field_data(data, true);
+ self.node.update_field_data(data);
// process completed
self.deferred.done(process_id);
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/mvc/tools/tools-input.js
--- a/static/scripts/mvc/tools/tools-input.js
+++ b/static/scripts/mvc/tools/tools-input.js
@@ -28,15 +28,12 @@
// decide wether to expand or collapse optional fields
this.field.skip = false;
- if (options.optional) {
- if ((this.field.validate && !this.field.validate()) ||
- (this.field.value && !this.field.value()) ||
- (this.field.value && Number(this.field.value()) == Number(this.defaultvalue)) ||
- (this.field.value && JSON.stringify(this.field.value()) == JSON.stringify(this.defaultvalue))) {
- this.field.skip = true;
- }
- }
-
+ var v = this.field.value && this.field.value();
+ this.field.skip = Boolean(options.optional &&
+ ((this.field.validate && !this.field.validate()) || !v ||
+ (v == this.defaultvalue) || (Number(v) == Number(this.defaultvalue)) ||
+ (JSON.stringify(v) == JSON.stringify(this.defaultvalue))));
+
// refresh view
this._refresh();
@@ -75,7 +72,7 @@
} else {
this.$field.hide();
this.$title_optional.html('Enable');
- this.field.value(this.defaultvalue);
+ this.field.value && this.field.value(this.defaultvalue);
}
this.app.trigger('refresh');
},
@@ -92,7 +89,7 @@
// is optional
if (options.optional) {
- tmp += 'Optional: ' + options.label +
+ tmp += options.label +
'<span> [<span class="ui-table-form-title-optional"/>]</span>';
} else {
tmp += options.label;
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/mvc/tools/tools-tree.js
--- a/static/scripts/mvc/tools/tools-tree.js
+++ b/static/scripts/mvc/tools/tools-tree.js
@@ -123,7 +123,7 @@
}
// handle simple value
- if (!field.skip) {
+ if (!field.skip || self.app.workflow) {
if (field.validate && !field.validate()) {
value = null;
}
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/packed/mvc/tools/tools-form-base.js
--- a/static/scripts/packed/mvc/tools/tools-form-base.js
+++ b/static/scripts/packed/mvc/tools/tools-form-base.js
@@ -1,1 +1,1 @@
-define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}});this.trigger("refresh")},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!t.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!t.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!t.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
+define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}});this.trigger("refresh")},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!this.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!this.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!this.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/packed/mvc/tools/tools-form-workflow.js
--- a/static/scripts/packed/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/packed/mvc/tools/tools-form-workflow.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;b.deepeach(e.inputs,function(f){if(f.type&&(["data","data_hidden","hidden"]).indexOf(f.type)==-1){f.optional=true}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",expand:this.node.annotation,inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:"None"});var f={label:"Edit Step Action: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done.",payload:{host:window.location.host}},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h,true);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
+define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","drill_down"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",expand:this.node.annotation,inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:"None"});var f={label:"Edit Step Action: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done.",payload:{host:window.location.host}},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/packed/mvc/tools/tools-input.js
--- a/static/scripts/packed/mvc/tools/tools-input.js
+++ b/static/scripts/packed/mvc/tools/tools-input.js
@@ -1,1 +1,1 @@
-define([],function(){return Backbone.View.extend({initialize:function(c,b){this.app=c;this.field=b.field;this.defaultvalue=b.defaultvalue;this.setElement(this._template(b));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;if(b.optional){if((this.field.validate&&!this.field.validate())||(this.field.value&&!this.field.value())||(this.field.value&&Number(this.field.value())==Number(this.defaultvalue))||(this.field.value&&JSON.stringify(this.field.value())==JSON.stringify(this.defaultvalue))){this.field.skip=true}}this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable")}else{this.$field.hide();this.$title_optional.html("Enable");this.field.value(this.defaultvalue)}this.app.trigger("refresh")},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+="Optional: "+a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
\ No newline at end of file
+define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.field=c.field;this.defaultvalue=c.defaultvalue;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&((this.field.validate&&!this.field.validate())||!b||(b==this.defaultvalue)||(Number(b)==Number(this.defaultvalue))||(JSON.stringify(b)==JSON.stringify(this.defaultvalue))));this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable")}else{this.$field.hide();this.$title_optional.html("Enable");this.field.value&&this.field.value(this.defaultvalue)}this.app.trigger("refresh")},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+=a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
\ No newline at end of file
diff -r ba17da4b23564fdff554c6f0b5d0618326147b97 -r 0c1a9c09877422dd03f83ec343b298a9f5d947f6 static/scripts/packed/mvc/tools/tools-tree.js
--- a/static/scripts/packed/mvc/tools/tools-tree.js
+++ b/static/scripts/packed/mvc/tools/tools-tree.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(p,s){for(var n in s){var k=s[n];if(k.input){var u=k.input;var o=p;if(p!=""){o+="|"}o+=u.name;switch(u.type){case"repeat":var j="section-";var x=[];var r=null;for(var w in k){var q=w.indexOf(j);if(q!=-1){q+=j.length;x.push(parseInt(w.substr(q)));if(!r){r=w.substr(0,q)}}}x.sort(function(y,i){return y-i});var n=0;for(var l in x){c(o+"_"+n++,k[r+x[l]])}break;case"conditional":var v=b.app.field_list[u.id].value();if(g[u.test_param.type]){v=g[u.test_param.type](v)}d(o+"|"+u.test_param.name,u.id,v);var h=b.matchCase(u,v);if(h!=-1){c(o,s[u.id+"-section-"+h])}break;case"section":c("",k);break;default:var t=b.app.field_list[u.id];if(t&&t.value){var v=t.value();if(g[u.type]){v=g[u.type](v)}if(!t.skip){if(t.validate&&!t.validate()){v=null}if(u.ignore===undefined||(v!==null&&u.ignore!=v)){d(o,u.id,v);if(u.payload){for(var m in u.payload){d(m,u.id,u.payload[m])}}}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(p,s){for(var n in s){var k=s[n];if(k.input){var u=k.input;var o=p;if(p!=""){o+="|"}o+=u.name;switch(u.type){case"repeat":var j="section-";var x=[];var r=null;for(var w in k){var q=w.indexOf(j);if(q!=-1){q+=j.length;x.push(parseInt(w.substr(q)));if(!r){r=w.substr(0,q)}}}x.sort(function(y,i){return y-i});var n=0;for(var l in x){c(o+"_"+n++,k[r+x[l]])}break;case"conditional":var v=b.app.field_list[u.id].value();if(g[u.test_param.type]){v=g[u.test_param.type](v)}d(o+"|"+u.test_param.name,u.id,v);var h=b.matchCase(u,v);if(h!=-1){c(o,s[u.id+"-section-"+h])}break;case"section":c("",k);break;default:var t=b.app.field_list[u.id];if(t&&t.value){var v=t.value();if(g[u.type]){v=g[u.type](v)}if(!t.skip||b.app.workflow){if(t.validate&&!t.validate()){v=null}if(u.ignore===undefined||(v!==null&&u.ignore!=v)){d(o,u.id,v);if(u.payload){for(var m in u.payload){d(m,u.id,u.payload[m])}}}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of 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
commit/galaxy-central: guerler: ToolForm: Add additional trigger for refresh event
by commits-noreply@bitbucket.org 14 Jan '15
by commits-noreply@bitbucket.org 14 Jan '15
14 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ba17da4b2356/
Changeset: ba17da4b2356
User: guerler
Date: 2015-01-14 05:52:19+00:00
Summary: ToolForm: Add additional trigger for refresh event
Affected #: 3 files
diff -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc -r ba17da4b23564fdff554c6f0b5d0618326147b97 client/galaxy/scripts/mvc/tools/tools-form-base.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-base.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -131,6 +131,9 @@
this.element_list[i].reset();
}
});
+
+ // refresh
+ this.trigger('refresh');
},
/** Renders the UI elements required for the form
diff -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc -r ba17da4b23564fdff554c6f0b5d0618326147b97 static/scripts/mvc/tools/tools-form-base.js
--- a/static/scripts/mvc/tools/tools-form-base.js
+++ b/static/scripts/mvc/tools/tools-form-base.js
@@ -131,6 +131,9 @@
this.element_list[i].reset();
}
});
+
+ // refresh
+ this.trigger('refresh');
},
/** Renders the UI elements required for the form
diff -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc -r ba17da4b23564fdff554c6f0b5d0618326147b97 static/scripts/packed/mvc/tools/tools-form-base.js
--- a/static/scripts/packed/mvc/tools/tools-form-base.js
+++ b/static/scripts/packed/mvc/tools/tools-form-base.js
@@ -1,1 +1,1 @@
-define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}})},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!t.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!t.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!t.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
+define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}});this.trigger("refresh")},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!t.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!t.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!t.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
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: guerler: ToolForm/Workflow: Add payload, use default value to collapse/expand sections, fix styles
by commits-noreply@bitbucket.org 14 Jan '15
by commits-noreply@bitbucket.org 14 Jan '15
14 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bf6b51623d29/
Changeset: bf6b51623d29
User: guerler
Date: 2015-01-14 03:39:17+00:00
Summary: ToolForm/Workflow: Add payload, use default value to collapse/expand sections, fix styles
Affected #: 25 files
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc client/galaxy/scripts/mvc/tools/tools-form-base.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-base.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -111,7 +111,7 @@
this.tree.finalize();
// show errors
- if (!this.workflow && options.errors) {
+ if (options.errors) {
var error_messages = this.tree.matchResponse(options.errors);
for (var input_id in error_messages) {
this.highlight(input_id, error_messages[input_id], true);
@@ -145,7 +145,7 @@
// button for version selection
var requirements_button = new Ui.ButtonIcon({
icon : 'fa-info-circle',
- title : 'Requirements',
+ title : (!self.workflow && 'Requirements') || null,
tooltip : 'Display tool requirements',
onclick : function() {
if (!this.visible) {
@@ -170,7 +170,7 @@
// button for version selection
var versions_button = new Ui.ButtonMenu({
icon : 'fa-cubes',
- title : 'Versions',
+ title : (!self.workflow && 'Versions') || null,
tooltip : 'Select another tool version'
});
if (options.versions && options.versions.length > 1) {
@@ -200,7 +200,7 @@
// button menu
var menu_button = new Ui.ButtonMenu({
icon : 'fa-caret-down',
- title : 'Options',
+ title : (!self.workflow && 'Options') || null,
tooltip : 'View available options'
});
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc client/galaxy/scripts/mvc/tools/tools-form-workflow.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
@@ -9,6 +9,7 @@
initialize: function(options) {
// link with node representation in workflow module
this.node = workflow.active_node;
+
if (!this.node) {
console.debug('FAILED - tools-form-workflow:initialize() - Node not found in workflow.');
return;
@@ -18,6 +19,13 @@
this.workflow = true;
this.options = options;
+ // traverse through dictionary
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type && (['data', 'data_hidden', 'hidden']).indexOf(item.type) == -1) {
+ item.optional = true;
+ }
+ });
+
// load extension
var self = this;
Utils.get({
@@ -38,6 +46,7 @@
inputs[Utils.uuid()] = {
label : 'Edit Step Attributes',
type : 'section',
+ expand : this.node.annotation,
inputs : [{
label : 'Annotation / Notes',
name : 'annotation',
@@ -160,7 +169,10 @@
type : 'boolean',
value : 'false',
ignore : 'false',
- help : 'This action will send an email notifying you when the job is done.'
+ help : 'This action will send an email notifying you when the job is done.',
+ payload : {
+ 'host' : window.location.host
+ }
},{
action : 'DeleteIntermediatesAction',
label : 'Delete non-outputs',
@@ -173,31 +185,51 @@
// visit input nodes and enrich by name/value pairs from server data
var self = this;
- function visit (inputs) {
- for (var i in inputs) {
- var input = inputs[i];
+ function visit (head, head_list) {
+ head_list = head_list || [];
+ head_list.push(head);
+ for (var i in head.inputs) {
+ var input = head.inputs[i];
if (input.action) {
+ // construct identifier as expected by backend
input.name = 'pja__' + output_id + '__' + input.action;
if (input.argument) {
input.name += '__' + input.argument;
}
+
+ // modify names of payload arguments
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ var p = input.payload[p_id];
+ input.payload[input.name + '__' + p_id] = p;
+ delete p;
+ }
+ }
+
+ // access/verify existence of value
var d = self.post_job_actions[input.action + output_id];
if (d) {
+ // mark as expanded
+ for (var j in head_list) {
+ head_list[j].expand = true;
+ }
+
+ // update input field value
if (input.argument) {
input.value = d.action_arguments && d.action_arguments[input.argument] || input.value;
} else {
input.value = 'true';
}
}
- } else {
- if (input.inputs) {
- visit(input.inputs);
- }
+ }
+ // continue with sub section
+ if (input.inputs) {
+ visit(input, head_list.slice(0));
}
}
}
- visit(input_config.inputs);
-
+ visit(input_config);
+
// return final configuration
return input_config;
},
@@ -205,6 +237,15 @@
/** Builds a new model through api call and recreates the entire form
*/
_buildModel: function() {
+ Galaxy.modal.show({
+ title : 'Coming soon...',
+ body : 'This feature has not been implemented yet.',
+ buttons : {
+ 'Close' : function() {
+ Galaxy.modal.hide();
+ }
+ }
+ });
},
/** Request a new model for an already created tool form and updates the form inputs
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc client/galaxy/scripts/mvc/tools/tools-input.js
--- a/client/galaxy/scripts/mvc/tools/tools-input.js
+++ b/client/galaxy/scripts/mvc/tools/tools-input.js
@@ -12,6 +12,7 @@
// link field
this.field = options.field;
+ this.defaultvalue = options.defaultvalue;
// set element
this.setElement(this._template(options));
@@ -25,9 +26,17 @@
// add field element
this.$field.prepend(this.field.$el);
- // start with enabled optional fields
+ // decide wether to expand or collapse optional fields
this.field.skip = false;
-
+ if (options.optional) {
+ if ((this.field.validate && !this.field.validate()) ||
+ (this.field.value && !this.field.value()) ||
+ (this.field.value && Number(this.field.value()) == Number(this.defaultvalue)) ||
+ (this.field.value && JSON.stringify(this.field.value()) == JSON.stringify(this.defaultvalue))) {
+ this.field.skip = true;
+ }
+ }
+
// refresh view
this._refresh();
@@ -63,11 +72,12 @@
if (!this.field.skip) {
this.$field.fadeIn('fast');
this.$title_optional.html('Disable');
- this.app.trigger('refresh');
} else {
this.$field.hide();
this.$title_optional.html('Enable');
+ this.field.value(this.defaultvalue);
}
+ this.app.trigger('refresh');
},
/** Main Template
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -232,9 +232,9 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.title,
- help : input_def.help,
- field : repeat
+ label : input_def.title,
+ help : input_def.help,
+ field : repeat
});
// displays as grouped subsection
@@ -292,6 +292,11 @@
}
});
+ // show sub section if requested
+ if (input_def.expand) {
+ portlet.$header.trigger('click');
+ }
+
// create table row
this.table.add(portlet.$el);
@@ -313,10 +318,11 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.label,
- optional : input_def.optional,
- help : input_def.help,
- field : field
+ label : input_def.label,
+ defaultvalue : input_def.defaultvalue,
+ optional : input_def.optional,
+ help : input_def.help,
+ field : field
});
// add to element list
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc client/galaxy/scripts/mvc/tools/tools-template.js
--- a/client/galaxy/scripts/mvc/tools/tools-template.js
+++ b/client/galaxy/scripts/mvc/tools/tools-template.js
@@ -4,7 +4,7 @@
// tool form templates
return {
help: function(content) {
- return '<div class="toolHelp">' +
+ return '<div class="toolHelp" style="overflow: auto;">' +
'<div class="toolHelpBody">' +
content +
'</div>' +
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc client/galaxy/scripts/mvc/tools/tools-tree.js
--- a/client/galaxy/scripts/mvc/tools/tools-tree.js
+++ b/client/galaxy/scripts/mvc/tools/tools-tree.js
@@ -122,13 +122,21 @@
value = patch[input.type](value);
}
- // handle default value
+ // handle simple value
if (!field.skip) {
- if (field.validate && !field.validate(value)) {
+ if (field.validate && !field.validate()) {
value = null;
}
- if (input.ignore === undefined || (value && input.ignore != value)) {
+ if (input.ignore === undefined || (value !== null && input.ignore != value)) {
+ // add value to submission
add (job_input_id, input.id, value);
+
+ // add payload to submission
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ add (p_id, input.id, input.payload[p_id]);
+ }
+ }
}
}
}
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc client/galaxy/scripts/utils/utils.js
--- a/client/galaxy/scripts/utils/utils.js
+++ b/client/galaxy/scripts/utils/utils.js
@@ -6,6 +6,18 @@
// dependencies
define(["libs/underscore"], function(_) {
+/** Traverse through json
+*/
+function deepeach(dict, callback) {
+ for (var i in dict) {
+ var d = dict[i];
+ if (d && typeof(d) == "object") {
+ callback(d);
+ deepeach(d, callback);
+ }
+ }
+}
+
/**
* Sanitize/escape a string
* @param{String} content - Content to be sanitized
@@ -248,7 +260,8 @@
request: request,
sanitize: sanitize,
textify: textify,
- validate: validate
+ validate: validate,
+ deepeach: deepeach
};
});
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -12,8 +12,10 @@
import threading
import types
import urllib
+import copy
-from galaxy import eggs
+from galaxy import eggs, util
+
eggs.require( "MarkupSafe" ) # MarkupSafe must load before mako
eggs.require( "Mako" )
eggs.require( "elementtree" )
@@ -2150,9 +2152,9 @@
return None
# ensures that input dictionary is jsonifiable
- def sanitize(dict):
+ def sanitize(dict, key='value'):
# get current value
- value = dict['value'] if 'value' in dict else None
+ value = dict[key] if key in dict else None
# jsonify by type
if dict['type'] in ['data']:
@@ -2167,15 +2169,8 @@
value = jsonify(value)
# update and return
- dict['value'] = value
- return dict
+ dict[key] = value
- # initialize state using default parameters
- def initialize_state(trans, inputs, state, context=None):
- context = ExpressionContext(state, context)
- for input in inputs.itervalues():
- state[input.name] = input.get_initial_value(trans, context)
-
# check the current state of a value and update it if necessary
def check_state(trans, input, default_value, context):
value = default_value
@@ -2195,6 +2190,7 @@
def populate_state(trans, inputs, state, errors, incoming, prefix="", context=None ):
context = ExpressionContext(state, context)
for input in inputs.itervalues():
+ state[input.name] = input.get_initial_value(trans, context)
key = prefix + input.name
if input.type == 'repeat':
group_state = state[input.name]
@@ -2207,7 +2203,6 @@
if rep_index < input.max:
new_state = {}
new_state['__index__'] = rep_index
- initialize_state(trans, input.inputs, new_state, context)
group_state.append(new_state)
populate_state(trans, input.inputs, new_state, errors, incoming, prefix=rep_name + "|", context=context)
rep_index += 1
@@ -2223,7 +2218,6 @@
try:
current_case = input.get_current_case(value, trans)
group_state = state[input.name] = {}
- initialize_state(trans, input.cases[current_case].inputs, group_state, context)
populate_state( trans, input.cases[current_case].inputs, group_state, errors, incoming, prefix=group_prefix, context=context)
group_state['__current_case__'] = current_case
except Exception, e:
@@ -2272,13 +2266,17 @@
# identify name
input_name = tool_dict.get('name')
if input_name:
+ # backup default value
+ tool_dict['defaultvalue'] = input.get_initial_value(trans, other_values)
+
# update input value from tool state
if input_name in state_inputs:
tool_dict['value'] = state_inputs[input_name]
-
- # sanitize if value exists
- tool_dict = sanitize(tool_dict)
-
+
+ # sanitize values
+ sanitize(tool_dict, 'value')
+ sanitize(tool_dict, 'defaultvalue')
+
# backup final input dictionary
group_inputs[input_index] = tool_dict
@@ -2303,7 +2301,6 @@
# initialize and populate tool state
state_inputs = {}
state_errors = {}
- initialize_state(trans, self.inputs, state_inputs)
populate_state(trans, self.inputs, state_inputs, state_errors, params.__dict__)
# create basic tool model
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/mvc/tools/tools-form-base.js
--- a/static/scripts/mvc/tools/tools-form-base.js
+++ b/static/scripts/mvc/tools/tools-form-base.js
@@ -111,7 +111,7 @@
this.tree.finalize();
// show errors
- if (!this.workflow && options.errors) {
+ if (options.errors) {
var error_messages = this.tree.matchResponse(options.errors);
for (var input_id in error_messages) {
this.highlight(input_id, error_messages[input_id], true);
@@ -145,7 +145,7 @@
// button for version selection
var requirements_button = new Ui.ButtonIcon({
icon : 'fa-info-circle',
- title : 'Requirements',
+ title : (!self.workflow && 'Requirements') || null,
tooltip : 'Display tool requirements',
onclick : function() {
if (!this.visible) {
@@ -170,7 +170,7 @@
// button for version selection
var versions_button = new Ui.ButtonMenu({
icon : 'fa-cubes',
- title : 'Versions',
+ title : (!self.workflow && 'Versions') || null,
tooltip : 'Select another tool version'
});
if (options.versions && options.versions.length > 1) {
@@ -200,7 +200,7 @@
// button menu
var menu_button = new Ui.ButtonMenu({
icon : 'fa-caret-down',
- title : 'Options',
+ title : (!self.workflow && 'Options') || null,
tooltip : 'View available options'
});
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/mvc/tools/tools-form-workflow.js
--- a/static/scripts/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/mvc/tools/tools-form-workflow.js
@@ -9,6 +9,7 @@
initialize: function(options) {
// link with node representation in workflow module
this.node = workflow.active_node;
+
if (!this.node) {
console.debug('FAILED - tools-form-workflow:initialize() - Node not found in workflow.');
return;
@@ -18,6 +19,13 @@
this.workflow = true;
this.options = options;
+ // traverse through dictionary
+ Utils.deepeach(options.inputs, function(item) {
+ if (item.type && (['data', 'data_hidden', 'hidden']).indexOf(item.type) == -1) {
+ item.optional = true;
+ }
+ });
+
// load extension
var self = this;
Utils.get({
@@ -38,6 +46,7 @@
inputs[Utils.uuid()] = {
label : 'Edit Step Attributes',
type : 'section',
+ expand : this.node.annotation,
inputs : [{
label : 'Annotation / Notes',
name : 'annotation',
@@ -160,7 +169,10 @@
type : 'boolean',
value : 'false',
ignore : 'false',
- help : 'This action will send an email notifying you when the job is done.'
+ help : 'This action will send an email notifying you when the job is done.',
+ payload : {
+ 'host' : window.location.host
+ }
},{
action : 'DeleteIntermediatesAction',
label : 'Delete non-outputs',
@@ -173,31 +185,51 @@
// visit input nodes and enrich by name/value pairs from server data
var self = this;
- function visit (inputs) {
- for (var i in inputs) {
- var input = inputs[i];
+ function visit (head, head_list) {
+ head_list = head_list || [];
+ head_list.push(head);
+ for (var i in head.inputs) {
+ var input = head.inputs[i];
if (input.action) {
+ // construct identifier as expected by backend
input.name = 'pja__' + output_id + '__' + input.action;
if (input.argument) {
input.name += '__' + input.argument;
}
+
+ // modify names of payload arguments
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ var p = input.payload[p_id];
+ input.payload[input.name + '__' + p_id] = p;
+ delete p;
+ }
+ }
+
+ // access/verify existence of value
var d = self.post_job_actions[input.action + output_id];
if (d) {
+ // mark as expanded
+ for (var j in head_list) {
+ head_list[j].expand = true;
+ }
+
+ // update input field value
if (input.argument) {
input.value = d.action_arguments && d.action_arguments[input.argument] || input.value;
} else {
input.value = 'true';
}
}
- } else {
- if (input.inputs) {
- visit(input.inputs);
- }
+ }
+ // continue with sub section
+ if (input.inputs) {
+ visit(input, head_list.slice(0));
}
}
}
- visit(input_config.inputs);
-
+ visit(input_config);
+
// return final configuration
return input_config;
},
@@ -205,6 +237,15 @@
/** Builds a new model through api call and recreates the entire form
*/
_buildModel: function() {
+ Galaxy.modal.show({
+ title : 'Coming soon...',
+ body : 'This feature has not been implemented yet.',
+ buttons : {
+ 'Close' : function() {
+ Galaxy.modal.hide();
+ }
+ }
+ });
},
/** Request a new model for an already created tool form and updates the form inputs
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/mvc/tools/tools-input.js
--- a/static/scripts/mvc/tools/tools-input.js
+++ b/static/scripts/mvc/tools/tools-input.js
@@ -12,6 +12,7 @@
// link field
this.field = options.field;
+ this.defaultvalue = options.defaultvalue;
// set element
this.setElement(this._template(options));
@@ -25,9 +26,17 @@
// add field element
this.$field.prepend(this.field.$el);
- // start with enabled optional fields
+ // decide wether to expand or collapse optional fields
this.field.skip = false;
-
+ if (options.optional) {
+ if ((this.field.validate && !this.field.validate()) ||
+ (this.field.value && !this.field.value()) ||
+ (this.field.value && Number(this.field.value()) == Number(this.defaultvalue)) ||
+ (this.field.value && JSON.stringify(this.field.value()) == JSON.stringify(this.defaultvalue))) {
+ this.field.skip = true;
+ }
+ }
+
// refresh view
this._refresh();
@@ -63,11 +72,12 @@
if (!this.field.skip) {
this.$field.fadeIn('fast');
this.$title_optional.html('Disable');
- this.app.trigger('refresh');
} else {
this.$field.hide();
this.$title_optional.html('Enable');
+ this.field.value(this.defaultvalue);
}
+ this.app.trigger('refresh');
},
/** Main Template
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/mvc/tools/tools-section.js
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -232,9 +232,9 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.title,
- help : input_def.help,
- field : repeat
+ label : input_def.title,
+ help : input_def.help,
+ field : repeat
});
// displays as grouped subsection
@@ -292,6 +292,11 @@
}
});
+ // show sub section if requested
+ if (input_def.expand) {
+ portlet.$header.trigger('click');
+ }
+
// create table row
this.table.add(portlet.$el);
@@ -313,10 +318,11 @@
// create input field wrapper
var input_element = new InputElement(this.app, {
- label : input_def.label,
- optional : input_def.optional,
- help : input_def.help,
- field : field
+ label : input_def.label,
+ defaultvalue : input_def.defaultvalue,
+ optional : input_def.optional,
+ help : input_def.help,
+ field : field
});
// add to element list
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/mvc/tools/tools-template.js
--- a/static/scripts/mvc/tools/tools-template.js
+++ b/static/scripts/mvc/tools/tools-template.js
@@ -4,7 +4,7 @@
// tool form templates
return {
help: function(content) {
- return '<div class="toolHelp">' +
+ return '<div class="toolHelp" style="overflow: auto;">' +
'<div class="toolHelpBody">' +
content +
'</div>' +
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/mvc/tools/tools-tree.js
--- a/static/scripts/mvc/tools/tools-tree.js
+++ b/static/scripts/mvc/tools/tools-tree.js
@@ -122,13 +122,21 @@
value = patch[input.type](value);
}
- // handle default value
+ // handle simple value
if (!field.skip) {
- if (field.validate && !field.validate(value)) {
+ if (field.validate && !field.validate()) {
value = null;
}
- if (input.ignore === undefined || (value && input.ignore != value)) {
+ if (input.ignore === undefined || (value !== null && input.ignore != value)) {
+ // add value to submission
add (job_input_id, input.id, value);
+
+ // add payload to submission
+ if (input.payload) {
+ for (var p_id in input.payload) {
+ add (p_id, input.id, input.payload[p_id]);
+ }
+ }
}
}
}
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/packed/mvc/tools/tools-form-base.js
--- a/static/scripts/packed/mvc/tools/tools-form-base.js
+++ b/static/scripts/packed/mvc/tools/tools-form-base.js
@@ -1,1 +1,1 @@
-define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(!this.workflow&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}})},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:"Versions",tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:"Options",tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
+define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}})},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:(!t.workflow&&"Requirements")||null,tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:(!t.workflow&&"Versions")||null,tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!t.workflow&&"Options")||null,tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/packed/mvc/tools/tools-form-workflow.js
--- a/static/scripts/packed/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/packed/mvc/tools/tools-form-workflow.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:"None"});var f={label:"Edit Step Action: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done."},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(j){for(var l in j){var k=j[l];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}var m=d.post_job_actions[k.action+h];if(m){if(k.argument){k.value=m.action_arguments&&m.action_arguments[k.argument]||k.value}else{k.value="true"}}}else{if(k.inputs){e(k.inputs)}}}}e(f.inputs);return f},_buildModel:function(){},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h,true);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
+define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;b.deepeach(e.inputs,function(f){if(f.type&&(["data","data_hidden","hidden"]).indexOf(f.type)==-1){f.optional=true}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",expand:this.node.annotation,inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:"None"});var f={label:"Edit Step Action: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done.",payload:{host:window.location.host}},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h,true);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/packed/mvc/tools/tools-input.js
--- a/static/scripts/packed/mvc/tools/tools-input.js
+++ b/static/scripts/packed/mvc/tools/tools-input.js
@@ -1,1 +1,1 @@
-define([],function(){return Backbone.View.extend({initialize:function(c,b){this.app=c;this.field=b.field;this.setElement(this._template(b));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable");this.app.trigger("refresh")}else{this.$field.hide();this.$title_optional.html("Enable")}},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+="Optional: "+a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
\ No newline at end of file
+define([],function(){return Backbone.View.extend({initialize:function(c,b){this.app=c;this.field=b.field;this.defaultvalue=b.defaultvalue;this.setElement(this._template(b));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;if(b.optional){if((this.field.validate&&!this.field.validate())||(this.field.value&&!this.field.value())||(this.field.value&&Number(this.field.value())==Number(this.defaultvalue))||(this.field.value&&JSON.stringify(this.field.value())==JSON.stringify(this.defaultvalue))){this.field.skip=true}}this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html("Disable")}else{this.$field.hide();this.$title_optional.html("Enable");this.field.value(this.defaultvalue)}this.app.trigger("refresh")},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+="Optional: "+a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
\ No newline at end of file
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/packed/mvc/tools/tools-section.js
--- a/static/scripts/packed/mvc/tools/tools-section.js
+++ b/static/scripts/packed/mvc/tools/tools-section.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(e,b,h,d,c,a,f){var g=Backbone.View.extend({initialize:function(j,i){this.app=j;this.inputs=i.inputs;i.cls_tr="section-row";this.table=new b.View(i);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var j in this.inputs){this.add(this.inputs[j])}},add:function(k){var j=this;var i=jQuery.extend(true,{},k);i.id=k.id=e.uuid();this.app.input_list[i.id]=i;var l=i.type;switch(l){case"conditional":this._addConditional(i);break;case"repeat":this._addRepeat(i);break;case"section":this._addSection(i);break;default:this._addRow(i)}},_addConditional:function(j){var k=this;j.test_param.id=j.id;var n=this._addRow(j.test_param);n.options.onchange=function(w){var v=k.app.tree.matchCase(j,w);for(var u in j.cases){var q=j.cases[u];var t=j.id+"-section-"+u;var p=k.table.get(t);var s=false;for(var r in q.inputs){if(!q.inputs[r].hidden){s=true;break}}if(u==v&&s){p.fadeIn("fast")}else{p.hide()}}k.app.trigger("refresh")};for(var m in j.cases){var l=j.id+"-section-"+m;var o=new g(this.app,{inputs:j.cases[m].inputs,cls:"ui-table-plain"});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(l)}n.trigger("change")},_addRepeat:function(p){var s=this;var q=0;function n(i,u){var t=p.id+"-section-"+(q++);var v=null;if(u){v=function(){l.del(t);l.retitle(p.title);s.app.trigger("refresh")}}var w=new g(s.app,{inputs:i,cls:"ui-table-plain"});l.add({id:t,title:p.title,$el:w.$el,ondel:v});l.retitle(p.title)}var l=new c.View({title_new:p.title,max:p.max,onnew:function(){n(p.inputs,true);s.app.trigger("refresh")}});var j=p.min;var r=_.size(p.cache);for(var m=0;m<Math.max(r,j);m++){var o=null;if(m<r){o=p.cache[m]}else{o=p.inputs}n(o,m>=j)}var k=new f(this.app,{label:p.title,help:p.help,field:l});k.$el.addClass("ui-table-form-section");this.table.add(k.$el);this.table.append(p.id)},_addSection:function(i){var j=this;var n=new g(j.app,{inputs:i.inputs,cls:"ui-table-plain"});var m=new h.ButtonIcon({icon:"fa-eye-slash",tooltip:"Show/hide section",cls:"ui-button-icon-plain"});var l=new d.View({title:i.label,cls:"ui-portlet-section",operations:{button_visible:m}});l.append(n.$el);var k=false;l.$content.hide();l.$header.css("cursor","pointer");l.$header.on("click",function(){if(k){k=false;l.$content.hide();m.setIcon("fa-eye-slash")}else{k=true;l.$content.fadeIn("fast");m.setIcon("fa-eye")}});this.table.add(l.$el);this.table.append(i.id)},_addRow:function(i){var l=i.id;var j=this._createField(i);this.app.field_list[l]=j;var k=new f(this.app,{label:i.label,optional:i.optional,help:i.help,field:j});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);if(i.hidden){this.table.get(l).hide()}return j},_createField:function(i){var j=null;switch(i.type){case"text":j=this._fieldText(i);break;case"select":j=this._fieldSelect(i);break;case"data":j=this._fieldData(i);break;case"data_collection":j=this._fieldData(i);break;case"data_column":i.error_text="Missing columns in referenced dataset.";j=this._fieldSelect(i);break;case"hidden":j=this._fieldHidden(i);break;case"hidden_data":j=this._fieldHidden(i);break;case"integer":j=this._fieldSlider(i);break;case"float":j=this._fieldSlider(i);break;case"boolean":j=this._fieldBoolean(i);break;case"genomebuild":i.searchable=true;j=this._fieldSelect(i);break;case"drill_down":j=this._fieldDrilldown(i);break;case"baseurl":j=this._fieldHidden(i);break;default:this.app.incompatible=true;if(i.options){j=this._fieldSelect(i)}else{j=this._fieldText(i)}console.debug("tools-form::_addRow() : Auto matched field type ("+i.type+").")}if(i.value!==undefined){j.value(i.value)}return j},_fieldData:function(i){if(this.app.workflow){var k=e.textify(i.extensions.toString());i.info="Data input '"+i.name+"' ("+k+")";return this._fieldHidden(i)}var j=this;return new a.View(this.app,{id:"field-"+i.id,extensions:i.extensions,multiple:i.multiple,type:i.type,data:i.options,onchange:function(){j.app.trigger("refresh")}})},_fieldSelect:function(j){if(this.app.workflow&&j.is_dynamic){if(!e.validate(j.value)){j.value=""}return this._fieldText(j)}var l=[];for(var m in j.options){var n=j.options[m];l.push({label:n[0],value:n[1]})}var o=h.Select;switch(j.display){case"checkboxes":o=h.Checkbox;break;case"radio":o=h.Radio;break}var k=this;return new o.View({id:"field-"+j.id,data:l,error_text:j.error_text||"No options available",multiple:j.multiple,searchable:j.searchable,onchange:function(){k.app.trigger("refresh")}})},_fieldDrilldown:function(i){var j=this;return new h.Drilldown.View({id:"field-"+i.id,data:i.options,display:i.display,onchange:function(){j.app.trigger("refresh")}})},_fieldText:function(i){var j=this;return new h.Input({id:"field-"+i.id,area:i.area,onchange:function(){j.app.trigger("refresh")}})},_fieldSlider:function(i){var j=this;return new h.Slider.View({id:"field-"+i.id,precise:i.type=="float",min:i.min,max:i.max,onchange:function(){j.app.trigger("refresh")}})},_fieldHidden:function(i){return new h.Hidden({id:"field-"+i.id,info:i.info})},_fieldBoolean:function(i){var j=this;return new h.RadioButton.View({id:"field-"+i.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:function(){j.app.trigger("refresh")}})}});return{View:g}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(e,b,h,d,c,a,f){var g=Backbone.View.extend({initialize:function(j,i){this.app=j;this.inputs=i.inputs;i.cls_tr="section-row";this.table=new b.View(i);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var j in this.inputs){this.add(this.inputs[j])}},add:function(k){var j=this;var i=jQuery.extend(true,{},k);i.id=k.id=e.uuid();this.app.input_list[i.id]=i;var l=i.type;switch(l){case"conditional":this._addConditional(i);break;case"repeat":this._addRepeat(i);break;case"section":this._addSection(i);break;default:this._addRow(i)}},_addConditional:function(j){var k=this;j.test_param.id=j.id;var n=this._addRow(j.test_param);n.options.onchange=function(w){var v=k.app.tree.matchCase(j,w);for(var u in j.cases){var q=j.cases[u];var t=j.id+"-section-"+u;var p=k.table.get(t);var s=false;for(var r in q.inputs){if(!q.inputs[r].hidden){s=true;break}}if(u==v&&s){p.fadeIn("fast")}else{p.hide()}}k.app.trigger("refresh")};for(var m in j.cases){var l=j.id+"-section-"+m;var o=new g(this.app,{inputs:j.cases[m].inputs,cls:"ui-table-plain"});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(l)}n.trigger("change")},_addRepeat:function(p){var s=this;var q=0;function n(i,u){var t=p.id+"-section-"+(q++);var v=null;if(u){v=function(){l.del(t);l.retitle(p.title);s.app.trigger("refresh")}}var w=new g(s.app,{inputs:i,cls:"ui-table-plain"});l.add({id:t,title:p.title,$el:w.$el,ondel:v});l.retitle(p.title)}var l=new c.View({title_new:p.title,max:p.max,onnew:function(){n(p.inputs,true);s.app.trigger("refresh")}});var j=p.min;var r=_.size(p.cache);for(var m=0;m<Math.max(r,j);m++){var o=null;if(m<r){o=p.cache[m]}else{o=p.inputs}n(o,m>=j)}var k=new f(this.app,{label:p.title,help:p.help,field:l});k.$el.addClass("ui-table-form-section");this.table.add(k.$el);this.table.append(p.id)},_addSection:function(i){var j=this;var n=new g(j.app,{inputs:i.inputs,cls:"ui-table-plain"});var m=new h.ButtonIcon({icon:"fa-eye-slash",tooltip:"Show/hide section",cls:"ui-button-icon-plain"});var l=new d.View({title:i.label,cls:"ui-portlet-section",operations:{button_visible:m}});l.append(n.$el);var k=false;l.$content.hide();l.$header.css("cursor","pointer");l.$header.on("click",function(){if(k){k=false;l.$content.hide();m.setIcon("fa-eye-slash")}else{k=true;l.$content.fadeIn("fast");m.setIcon("fa-eye")}});if(i.expand){l.$header.trigger("click")}this.table.add(l.$el);this.table.append(i.id)},_addRow:function(i){var l=i.id;var j=this._createField(i);this.app.field_list[l]=j;var k=new f(this.app,{label:i.label,defaultvalue:i.defaultvalue,optional:i.optional,help:i.help,field:j});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);if(i.hidden){this.table.get(l).hide()}return j},_createField:function(i){var j=null;switch(i.type){case"text":j=this._fieldText(i);break;case"select":j=this._fieldSelect(i);break;case"data":j=this._fieldData(i);break;case"data_collection":j=this._fieldData(i);break;case"data_column":i.error_text="Missing columns in referenced dataset.";j=this._fieldSelect(i);break;case"hidden":j=this._fieldHidden(i);break;case"hidden_data":j=this._fieldHidden(i);break;case"integer":j=this._fieldSlider(i);break;case"float":j=this._fieldSlider(i);break;case"boolean":j=this._fieldBoolean(i);break;case"genomebuild":i.searchable=true;j=this._fieldSelect(i);break;case"drill_down":j=this._fieldDrilldown(i);break;case"baseurl":j=this._fieldHidden(i);break;default:this.app.incompatible=true;if(i.options){j=this._fieldSelect(i)}else{j=this._fieldText(i)}console.debug("tools-form::_addRow() : Auto matched field type ("+i.type+").")}if(i.value!==undefined){j.value(i.value)}return j},_fieldData:function(i){if(this.app.workflow){var k=e.textify(i.extensions.toString());i.info="Data input '"+i.name+"' ("+k+")";return this._fieldHidden(i)}var j=this;return new a.View(this.app,{id:"field-"+i.id,extensions:i.extensions,multiple:i.multiple,type:i.type,data:i.options,onchange:function(){j.app.trigger("refresh")}})},_fieldSelect:function(j){if(this.app.workflow&&j.is_dynamic){if(!e.validate(j.value)){j.value=""}return this._fieldText(j)}var l=[];for(var m in j.options){var n=j.options[m];l.push({label:n[0],value:n[1]})}var o=h.Select;switch(j.display){case"checkboxes":o=h.Checkbox;break;case"radio":o=h.Radio;break}var k=this;return new o.View({id:"field-"+j.id,data:l,error_text:j.error_text||"No options available",multiple:j.multiple,searchable:j.searchable,onchange:function(){k.app.trigger("refresh")}})},_fieldDrilldown:function(i){var j=this;return new h.Drilldown.View({id:"field-"+i.id,data:i.options,display:i.display,onchange:function(){j.app.trigger("refresh")}})},_fieldText:function(i){var j=this;return new h.Input({id:"field-"+i.id,area:i.area,onchange:function(){j.app.trigger("refresh")}})},_fieldSlider:function(i){var j=this;return new h.Slider.View({id:"field-"+i.id,precise:i.type=="float",min:i.min,max:i.max,onchange:function(){j.app.trigger("refresh")}})},_fieldHidden:function(i){return new h.Hidden({id:"field-"+i.id,info:i.info})},_fieldBoolean:function(i){var j=this;return new h.RadioButton.View({id:"field-"+i.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:function(){j.app.trigger("refresh")}})}});return{View:g}});
\ No newline at end of file
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/packed/mvc/tools/tools-template.js
--- a/static/scripts/packed/mvc/tools/tools-template.js
+++ b/static/scripts/packed/mvc/tools/tools-template.js
@@ -1,1 +1,1 @@
-define([],function(){return{help:function(a){return'<div class="toolHelp"><div class="toolHelpBody">'+a+"</div></div>"},success:function(c){if(!c.jobs||!c.jobs.length){console.debug("tools-template::success() - Failed jobs.");return}var a=c.jobs.length;var d="";if(a==1){d="1 job has"}else{d=a+" jobs have"}var b='<div class="donemessagelarge"><p>'+d+" been successfully added to the queue - resulting in the following datasets:</p>";for(var e in c.outputs){b+='<p style="padding: 10px 20px;"><b>'+(parseInt(e)+1)+": "+c.outputs[e].name+"</b></p>"}b+="<p>You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.</p></div>";return b},error:function(a){return'<div><p>The server could not complete the request. Please contact the Galaxy Team if this error persists.</p><textarea class="ui-textarea" disabled style="color: black;" rows="6">'+JSON.stringify(a,undefined,4)+"</textarea></div>"},batchMode:function(){return'<div class="ui-table-form-info"><i class="fa fa-sitemap" style="font-size: 1.2em; padding: 2px 5px;"/>This is a batch mode input field. A separate job will be triggered for each dataset.</div>'},requirements:function(a){var d="This tool requires ";for(var b in a.requirements){var c=a.requirements[b];d+=c.name;if(c.version){d+=" (Version "+c.version+")"}if(b<a.requirements.length-2){d+=", "}if(b==a.requirements.length-2){d+=" and "}}return d+'. Click <a target="_blank" href="https://wiki.galaxyproject.org/Tools/Requirements">here</a> for more information.'}}});
\ No newline at end of file
+define([],function(){return{help:function(a){return'<div class="toolHelp" style="overflow: auto;"><div class="toolHelpBody">'+a+"</div></div>"},success:function(c){if(!c.jobs||!c.jobs.length){console.debug("tools-template::success() - Failed jobs.");return}var a=c.jobs.length;var d="";if(a==1){d="1 job has"}else{d=a+" jobs have"}var b='<div class="donemessagelarge"><p>'+d+" been successfully added to the queue - resulting in the following datasets:</p>";for(var e in c.outputs){b+='<p style="padding: 10px 20px;"><b>'+(parseInt(e)+1)+": "+c.outputs[e].name+"</b></p>"}b+="<p>You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.</p></div>";return b},error:function(a){return'<div><p>The server could not complete the request. Please contact the Galaxy Team if this error persists.</p><textarea class="ui-textarea" disabled style="color: black;" rows="6">'+JSON.stringify(a,undefined,4)+"</textarea></div>"},batchMode:function(){return'<div class="ui-table-form-info"><i class="fa fa-sitemap" style="font-size: 1.2em; padding: 2px 5px;"/>This is a batch mode input field. A separate job will be triggered for each dataset.</div>'},requirements:function(a){var d="This tool requires ";for(var b in a.requirements){var c=a.requirements[b];d+=c.name;if(c.version){d+=" (Version "+c.version+")"}if(b<a.requirements.length-2){d+=", "}if(b==a.requirements.length-2){d+=" and "}}return d+'. Click <a target="_blank" href="https://wiki.galaxyproject.org/Tools/Requirements">here</a> for more information.'}}});
\ No newline at end of file
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/packed/mvc/tools/tools-tree.js
--- a/static/scripts/packed/mvc/tools/tools-tree.js
+++ b/static/scripts/packed/mvc/tools/tools-tree.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(o,r){for(var m in r){var k=r[m];if(k.input){var t=k.input;var n=o;if(o!=""){n+="|"}n+=t.name;switch(t.type){case"repeat":var j="section-";var w=[];var q=null;for(var v in k){var p=v.indexOf(j);if(p!=-1){p+=j.length;w.push(parseInt(v.substr(p)));if(!q){q=v.substr(0,p)}}}w.sort(function(x,i){return x-i});var m=0;for(var l in w){c(n+"_"+m++,k[q+w[l]])}break;case"conditional":var u=b.app.field_list[t.id].value();if(g[t.test_param.type]){u=g[t.test_param.type](u)}d(n+"|"+t.test_param.name,t.id,u);var h=b.matchCase(t,u);if(h!=-1){c(n,r[t.id+"-section-"+h])}break;case"section":c("",k);break;default:var s=b.app.field_list[t.id];if(s&&s.value){var u=s.value();if(g[t.type]){u=g[t.type](u)}if(!s.skip){if(s.validate&&!s.validate(u)){u=null}if(t.ignore===undefined||(u&&t.ignore!=u)){d(n,t.id,u)}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(p,s){for(var n in s){var k=s[n];if(k.input){var u=k.input;var o=p;if(p!=""){o+="|"}o+=u.name;switch(u.type){case"repeat":var j="section-";var x=[];var r=null;for(var w in k){var q=w.indexOf(j);if(q!=-1){q+=j.length;x.push(parseInt(w.substr(q)));if(!r){r=w.substr(0,q)}}}x.sort(function(y,i){return y-i});var n=0;for(var l in x){c(o+"_"+n++,k[r+x[l]])}break;case"conditional":var v=b.app.field_list[u.id].value();if(g[u.test_param.type]){v=g[u.test_param.type](v)}d(o+"|"+u.test_param.name,u.id,v);var h=b.matchCase(u,v);if(h!=-1){c(o,s[u.id+"-section-"+h])}break;case"section":c("",k);break;default:var t=b.app.field_list[u.id];if(t&&t.value){var v=t.value();if(g[u.type]){v=g[u.type](v)}if(!t.skip){if(t.validate&&!t.validate()){v=null}if(u.ignore===undefined||(v!==null&&u.ignore!=v)){d(o,u.id,v);if(u.payload){for(var m in u.payload){d(m,u.id,u.payload[m])}}}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/packed/utils/utils.js
--- a/static/scripts/packed/utils/utils.js
+++ b/static/scripts/packed/utils/utils.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(m){function d(n){return $("<div/>").text(n).html()}function l(o){if(!(o instanceof Array)){o=[o]}for(var n in o){if(["None",null,"null",undefined,"undefined"].indexOf(o[n])>-1){return false}}return true}function h(n){var n=n.toString();if(n){n=n.replace(/,/g,", ");var o=n.lastIndexOf(", ");if(o!=-1){n=n.substr(0,o)+" or "+n.substr(o+1)}return n}return""}function e(n){top.__utils__get__=top.__utils__get__||{};if(n.cache&&top.__utils__get__[n.url]){n.success&&n.success(top.__utils__get__[n.url]);console.debug("utils.js::get() - Fetching from cache ["+n.url+"].")}else{i({url:n.url,data:n.data,success:function(o){top.__utils__get__[n.url]=o;n.success&&n.success(o)},error:function(o){n.error&&n.error(o)}})}}function i(o){var n={contentType:"application/json",type:o.type||"GET",data:o.data||{},url:o.url};if(n.type=="GET"||n.type=="DELETE"){if(n.url.indexOf("?")==-1){n.url+="?"}else{n.url+="&"}n.url=n.url+$.param(n.data);n.data=null}else{n.dataType="json";n.url=n.url;n.data=JSON.stringify(n.data)}$.ajax(n).done(function(p){if(typeof p==="string"){try{p=p.replace("Infinity,",'"Infinity",');p=jQuery.parseJSON(p)}catch(q){console.debug(q)}}o.success&&o.success(p)}).fail(function(q){var p=null;try{p=jQuery.parseJSON(q.responseText)}catch(r){p=q.responseText}o.error&&o.error(p,q)})}function j(q,n){var o=$('<div class="'+q+'"></div>');o.appendTo(":eq(0)");var p=o.css(n);o.remove();return p}function g(n){if(!$('link[href^="'+n+'"]').length){$('<link href="'+galaxy_config.root+n+'" rel="stylesheet">').appendTo("head")}}function k(n,o){if(n){return m.defaults(n,o)}else{return o}}function b(o,q){var p="";if(o>=100000000000){o=o/100000000000;p="TB"}else{if(o>=100000000){o=o/100000000;p="GB"}else{if(o>=100000){o=o/100000;p="MB"}else{if(o>=100){o=o/100;p="KB"}else{if(o>0){o=o*10;p="b"}else{return"<strong>-</strong>"}}}}}var n=(Math.round(o)/10);if(q){return n+" "+p}else{return"<strong>"+n+"</strong> "+p}}function a(){return"x"+Math.random().toString(36).substring(2,9)}function c(n){var o=$("<p></p>");o.append(n);return o}function f(){var p=new Date();var n=(p.getHours()<10?"0":"")+p.getHours();var o=(p.getMinutes()<10?"0":"")+p.getMinutes();var q=p.getDate()+"/"+(p.getMonth()+1)+"/"+p.getFullYear()+", "+n+":"+o;return q}return{cssLoadFile:g,cssGetAttribute:j,get:e,merge:k,bytesToString:b,uuid:a,time:f,wrap:c,request:i,sanitize:d,textify:h,validate:l}});
\ No newline at end of file
+define(["libs/underscore"],function(m){function n(r,q){for(var o in r){var p=r[o];if(p&&typeof(p)=="object"){q(p);n(p,q)}}}function d(o){return $("<div/>").text(o).html()}function l(p){if(!(p instanceof Array)){p=[p]}for(var o in p){if(["None",null,"null",undefined,"undefined"].indexOf(p[o])>-1){return false}}return true}function h(o){var o=o.toString();if(o){o=o.replace(/,/g,", ");var p=o.lastIndexOf(", ");if(p!=-1){o=o.substr(0,p)+" or "+o.substr(p+1)}return o}return""}function e(o){top.__utils__get__=top.__utils__get__||{};if(o.cache&&top.__utils__get__[o.url]){o.success&&o.success(top.__utils__get__[o.url]);console.debug("utils.js::get() - Fetching from cache ["+o.url+"].")}else{i({url:o.url,data:o.data,success:function(p){top.__utils__get__[o.url]=p;o.success&&o.success(p)},error:function(p){o.error&&o.error(p)}})}}function i(p){var o={contentType:"application/json",type:p.type||"GET",data:p.data||{},url:p.url};if(o.type=="GET"||o.type=="DELETE"){if(o.url.indexOf("?")==-1){o.url+="?"}else{o.url+="&"}o.url=o.url+$.param(o.data);o.data=null}else{o.dataType="json";o.url=o.url;o.data=JSON.stringify(o.data)}$.ajax(o).done(function(q){if(typeof q==="string"){try{q=q.replace("Infinity,",'"Infinity",');q=jQuery.parseJSON(q)}catch(r){console.debug(r)}}p.success&&p.success(q)}).fail(function(r){var q=null;try{q=jQuery.parseJSON(r.responseText)}catch(s){q=r.responseText}p.error&&p.error(q,r)})}function j(r,o){var p=$('<div class="'+r+'"></div>');p.appendTo(":eq(0)");var q=p.css(o);p.remove();return q}function g(o){if(!$('link[href^="'+o+'"]').length){$('<link href="'+galaxy_config.root+o+'" rel="stylesheet">').appendTo("head")}}function k(o,p){if(o){return m.defaults(o,p)}else{return p}}function b(p,r){var q="";if(p>=100000000000){p=p/100000000000;q="TB"}else{if(p>=100000000){p=p/100000000;q="GB"}else{if(p>=100000){p=p/100000;q="MB"}else{if(p>=100){p=p/100;q="KB"}else{if(p>0){p=p*10;q="b"}else{return"<strong>-</strong>"}}}}}var o=(Math.round(p)/10);if(r){return o+" "+q}else{return"<strong>"+o+"</strong> "+q}}function a(){return"x"+Math.random().toString(36).substring(2,9)}function c(o){var p=$("<p></p>");p.append(o);return p}function f(){var q=new Date();var o=(q.getHours()<10?"0":"")+q.getHours();var p=(q.getMinutes()<10?"0":"")+q.getMinutes();var r=q.getDate()+"/"+(q.getMonth()+1)+"/"+q.getFullYear()+", "+o+":"+p;return r}return{cssLoadFile:g,cssGetAttribute:j,get:e,merge:k,bytesToString:b,uuid:a,time:f,wrap:c,request:i,sanitize:d,textify:h,validate:l,deepeach:n}});
\ No newline at end of file
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/scripts/utils/utils.js
--- a/static/scripts/utils/utils.js
+++ b/static/scripts/utils/utils.js
@@ -6,6 +6,18 @@
// dependencies
define(["libs/underscore"], function(_) {
+/** Traverse through json
+*/
+function deepeach(dict, callback) {
+ for (var i in dict) {
+ var d = dict[i];
+ if (d && typeof(d) == "object") {
+ callback(d);
+ deepeach(d, callback);
+ }
+ }
+}
+
/**
* Sanitize/escape a string
* @param{String} content - Content to be sanitized
@@ -248,7 +260,8 @@
request: request,
sanitize: sanitize,
textify: textify,
- validate: validate
+ validate: validate,
+ deepeach: deepeach
};
});
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1412,7 +1412,7 @@
.ui-button-icon-plain{border:none !important;background:none !important;height:inherit !important;width:inherit !important;padding-right:3px !important}
.ui-tabs .ui-tabs-add{font-size:0.8em;margin-right:5px}
.ui-tabs .ui-tabs-delete{font-size:0.8em;margin-left:5px;cursor:pointer}
-.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;clear:both;width:auto;height:100%}.ui-portlet .portlet-header,.ui-portlet-slim .portlet-header{background:#ebd9b2;border-bottom:solid #d6b161 1px;padding:2px 8px;overflow:visible;float:right;width:100%}.ui-portlet .portlet-header .portlet-title,.ui-portlet-slim .portlet-header .portlet-title{display:inline;vertical-align:middle}.ui-portlet .portlet-header .portlet-title .portlet-title-text,.ui-portlet-slim .portlet-header .portlet-title .portlet-title-text{vertical-align:middle}
+.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;clear:both;width:auto;height:100%}.ui-portlet .portlet-header,.ui-portlet-slim .portlet-header{background:#ebd9b2;border-bottom:solid #d6b161 1px;padding:2px 8px;overflow:visible;float:right;width:100%}.ui-portlet .portlet-header .portlet-title,.ui-portlet-slim .portlet-header .portlet-title{display:inline;vertical-align:middle}.ui-portlet .portlet-header .portlet-title .portlet-title-text,.ui-portlet-slim .portlet-header .portlet-title .portlet-title-text{vertical-align:middle;line-height:20px}
.ui-portlet .portlet-header .portlet-title .icon,.ui-portlet-slim .portlet-header .portlet-title .icon{font-size:1.2em;vertical-align:middle}
.ui-portlet .portlet-buttons,.ui-portlet-slim .portlet-buttons{height:50px;padding:10px}
.ui-portlet .portlet-content,.ui-portlet-slim .portlet-content{height:inherit;padding:10px;clear:both}.ui-portlet .portlet-content .content,.ui-portlet-slim .portlet-content .content{padding:10px;height:100%;width:100%}.ui-portlet .portlet-content .content .buttons,.ui-portlet-slim .portlet-content .content .buttons{height:50px;padding:10px}
@@ -1765,7 +1765,7 @@
div.toolFormDisabled{border-color:#bfbfbf}
div.toolHelp{margin-top:15px;padding:5px}
div.toolHelpBody{width:100%}
-.toolForm.toolFormInCanvas{border:solid #d6b161 1px;background:#fff}.toolForm.toolFormInCanvas.toolForm-active{border:solid blue 3px;margin:4px}
+.toolForm.toolFormInCanvas{border:solid #d6b161 1px;background:#fff}.toolForm.toolFormInCanvas.toolForm-active{border:solid #5f6990 3px;margin:4px}
.toolForm.toolFormInCanvas .toolFormTitle{font-size:12px;line-height:1.428571429}
div.form,div.toolForm{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
div.form-title,div.toolFormTitle{padding:5px 10px;background:#ebd9b2;border-bottom:solid #d6b161 1px}
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/style/src/less/base.less
--- a/static/style/src/less/base.less
+++ b/static/style/src/less/base.less
@@ -586,7 +586,7 @@
border: solid @form-border 1px;
background: @white;
&.toolForm-active {
- border: solid blue 3px;
+ border: solid @brand-primary 3px;
margin: 4px;
}
.toolFormTitle {
diff -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 -r bf6b51623d29b68ba216d97d99bb1ea200a3e4fc static/style/src/less/ui.less
--- a/static/style/src/less/ui.less
+++ b/static/style/src/less/ui.less
@@ -168,6 +168,7 @@
vertical-align: middle;
.portlet-title-text {
vertical-align: middle;
+ line-height: 20px;
}
.icon {
font-size: 1.2em;
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
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: f005c354d24102dfe13c1337485b4c7cf4f46ecd
https://github.com/galaxyproject/usegalaxy-playbook/commit/f005c354d24102df…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2015-01-13 (Tue, 13 Jan 2015)
Changed paths:
M files/galaxy/test.galaxyproject.org/var/integrated_tool_panel.xml
M stage/group_vars/all.yml
Log Message:
-----------
Update Test
1
0
14 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/659fc6822f0a/
Changeset: 659fc6822f0a
User: natefoo
Date: 2015-01-14 03:34:26+00:00
Summary: Merge stable to default
Affected #: 10 files
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -8,16 +8,18 @@
5e605ed6069fe4c5ca9875e95e91b2713499e8ca release_2014.02.10
9e53251b0b7e93b9563008a2b112f2e815a04bbc release_2014.04.14
7e257c7b10badb65772b1528cb61d58175a42e47 release_2014.06.02
-7a4d321c0e38fa263ea83d29a35a608c3181fcba latest_2014.06.02
-9661b9d5d5b330483ae3ad2236410e0efaa7c500 latest_2014.04.14
-6b0bd93038a843b1585155f0d63f0eea2459c70b latest_2013.01.13
-3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 latest_2013.02.08
-425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 latest_2013.04.01
-9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 latest_2013.06.03
-9ed84cd208e07e8985ec917cb025fcbbb09edcfb latest_2013.08.12
-81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
-2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
+4145417a6e1c13f82a3de365aadef0fb3ed7ab14 latest_2014.06.02
+8f9dcac033694e4cabcf5daae5cca1cfefbe967f latest_2014.04.14
+9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
+b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
+dec9431d66b837a208e2f060d90afd913c721227 latest_2013.04.01
+19e56e66b0b344c6e2afa4541f6988e4fdb9af29 latest_2013.06.03
+cee903b8b3eee9145627ee89742555dac581791e latest_2013.08.12
+7d5aa19a166cba9039e15f338a1e3fc924c43d3a latest_2013.11.04
+0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
-548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
+8150024c0e6fc5aef3033cf8aaa574896f6b5d0d latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-5834b1066462dd219f67c1c3cbd77c78e7cf3a6c latest_2014.10.06
+c437b28348a9345db8433e5b4f0e05ec8fb6c38a latest_2014.10.06
+2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee release_2015.01.13
+2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee latest_2015.01.13
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util import stringify_dictionary_keys
from galaxy.util import string_as_bool
from galaxy.util import in_directory
@@ -232,6 +233,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -480,6 +484,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.safe_dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -510,6 +518,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
DatasetCollectionWrapper,
@@ -114,6 +116,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -334,6 +339,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -2,6 +2,7 @@
from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
from galaxy.util import odict
+from galaxy.util.object_wrapper import wrap_with_safe_string
from logging import getLogger
log = getLogger( __name__ )
@@ -162,10 +163,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -190,9 +194,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.datatypes_registry = datatypes_registry
self.false_path = getattr( dataset_path, "false_path", None )
@@ -210,7 +218,7 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
@@ -230,7 +238,7 @@
# object store to find the static location of this
# directory.
try:
- return self.dataset.extra_files_path
+ return self.unsanitized.extra_files_path
except exceptions.ObjectNotFound:
# NestedObjectstore raises an error here
# instead of just returning a non-existent
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -360,46 +360,57 @@
'#': '__pd__'}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -4,6 +4,7 @@
#dbkeys read from disk using builds.txt
from galaxy.util import read_dbnames
from galaxy.util.json import loads
+from galaxy.util.object_wrapper import sanitize_lists_to_string
import os.path
@@ -84,6 +85,7 @@
# use configured server len path
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % dbkey )
+ # Since we are using an unverified dbkey, we will sanitize the dbkey before use
+ chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string( dbkey ) )
chrom_info = os.path.abspath( chrom_info )
return ( chrom_info, db_dataset )
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
diff -r a74b0112995cd2ae396d0916a6e845b7709f9002 -r 659fc6822f0afcdf77ba5f8857ba58700ce06b16 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -80,14 +80,28 @@
message=message,
status=status,
redirect=redirect ) )
- params = galaxy.util.Params( kwd, sanitize = False ) #Sanitize parameters when substituting into command line via input wrappers
- #do param translation here, used by datasource tools
- if tool.input_translator:
- tool.input_translator.translate( params )
+
+ def _validated_params_for( kwd ):
+ params = galaxy.util.Params( kwd, sanitize=False ) # Sanitize parameters when substituting into command line via input wrappers
+ #do param translation here, used by datasource tools
+ if tool.input_translator:
+ tool.input_translator.translate( params )
+ return params
+
+ params = _validated_params_for( kwd )
# We may be visiting Galaxy for the first time ( e.g., sending data from UCSC ),
# so make sure to create a new history if we've never had one before.
history = tool.get_default_history_by_trans( trans, create=True )
- template, vars = tool.handle_input( trans, params.__dict__ )
+ try:
+ template, vars = tool.handle_input( trans, params.__dict__ )
+ except KeyError:
+ # This error indicates (or at least can indicate) there was a
+ # problem with the stored tool_state - it is incompatible with
+ # this variant of the tool - possibly because the tool changed
+ # or because the tool version changed.
+ del kwd[ "tool_state" ]
+ params = _validated_params_for( kwd )
+ template, vars = tool.handle_input( trans, params.__dict__ )
if len( params ) > 0:
trans.log_event( "Tool params: %s" % ( str( params ) ), tool_id=tool_id )
add_frame = AddFrameData()
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
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: b1ae131ed466098f65a7b8a9346ce16d1d9faa69
https://github.com/galaxyproject/usegalaxy-playbook/commit/b1ae131ed466098f…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2015-01-13 (Tue, 13 Jan 2015)
Changed paths:
M production/group_vars/all.yml
Log Message:
-----------
Update Main
1
0
[galaxyproject/usegalaxy-playbook] ca6319: Update Test, commit mutable configs.
by GitHub 14 Jan '15
by GitHub 14 Jan '15
14 Jan '15
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: ca6319537b9bb471315ece8b2a4cd0ad07701e9d
https://github.com/galaxyproject/usegalaxy-playbook/commit/ca6319537b9bb471…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2015-01-13 (Tue, 13 Jan 2015)
Changed paths:
M files/galaxy/test.galaxyproject.org/var/integrated_tool_panel.xml
M files/galaxy/test.galaxyproject.org/var/migrated_tools_conf.xml
M files/galaxy/test.galaxyproject.org/var/shed_data_manager_conf.xml
M files/galaxy/test.galaxyproject.org/var/shed_tool_conf.xml
M files/galaxy/test.galaxyproject.org/var/shed_tool_data_table_conf.xml
M stage/group_vars/all.yml
Log Message:
-----------
Update Test, commit mutable configs.
1
0
37 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9c323aad4ffd/
Changeset: 9c323aad4ffd
Branch: stable
User: dan
Date: 2015-01-13 15:25:57+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 5 files
diff -r 6b0bd93038a843b1585155f0d63f0eea2459c70b -r 9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -2,6 +2,7 @@
from os.path import abspath
from galaxy.util import string_as_bool, stringify_dictionary_keys, listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.web import form_builder
import galaxy.model
@@ -176,7 +177,10 @@
def to_string( self, value ):
return str( value )
-
+
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -394,6 +398,10 @@
def to_string( self, value ):
return simplejson.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return simplejson.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
def to_string( self, value ):
@@ -417,7 +425,11 @@
if not value:
return str( self.spec.no_value )
return value.file_name
-
+
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context={}, other_values={}, **kwd ):
return form_builder.TextField( self.spec.name, value=str( value.id ) )
diff -r 6b0bd93038a843b1585155f0d63f0eea2459c70b -r 9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -34,6 +34,8 @@
from galaxy.util import listify
import galaxy.util.shed_util_common
from galaxy.web import url_for
+from galaxy.util.object_wrapper import wrap_with_safe_string
+from galaxy import exceptions
from galaxy.visualization.genome.visual_analytics import TracksterConfig
@@ -2382,6 +2384,9 @@
# failed to pass; for tool writing convienence, provide a
# NoneDataset
param_dict[ out_name ] = NoneDataset( datatypes_registry = self.app.datatypes_registry, ext = output.format )
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
# We add access to app here, this allows access to app.config, etc
param_dict['__app__'] = RawObjectWrapper( self.app )
# More convienent access to app.config.new_file_path; we don't need to
@@ -2399,6 +2404,23 @@
param_dict['__admin_users__'] = self.app.config.admin_users
# Return the dictionary of parameters
return param_dict
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.options or self.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
def build_param_file( self, param_dict, directory=None ):
"""
Build temporary file for file based parameter transfer if needed
@@ -3078,10 +3100,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
- setattr( self, name, rval )
+ setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
return self.metadata.__nonzero__()
@@ -3102,9 +3127,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry = datatypes_registry, ext = ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = false_path
@@ -3112,10 +3141,28 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
+ #does not implement support for false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
def __nonzero__( self ):
diff -r 6b0bd93038a843b1585155f0d63f0eea2459c70b -r 9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -6,6 +6,7 @@
from galaxy.tools.parameters.grouping import *
from galaxy.util.template import fill_template
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
from galaxy.exceptions import ObjectInvalid
import galaxy.tools
@@ -214,7 +215,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.tool_data_path, 'shared','ucsc','chrom', "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.tool_data_path, 'shared','ucsc','chrom', "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = chrom_info
inp_data.update( db_datasets )
diff -r 6b0bd93038a843b1585155f0d63f0eea2459c70b -r 9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -187,37 +187,59 @@
'#' : '__pd__'
}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
- """Restricts the characters that are allowed in a text"""
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ """
+ Restricts the characters that are allowed in text; accepts both strings
+ and lists of strings; non-string entities will be cast to strings.
+ """
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
+
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ """Restricts the characters that are allowed in a string"""
+
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- print value
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
-
-valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
invalid_filenames = [ '', '.', '..' ]
def sanitize_for_filename( text, default=None ):
"""
@@ -399,6 +421,28 @@
except:
return default
+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
+ """
+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
+
+ If strings_only is True, don't convert (some) non-string-like objects.
+
+ Adapted from an older, simpler version of django.utils.encoding.smart_str.
+ """
+ if strings_only and isinstance(s, (type(None), int)):
+ return s
+ if not isinstance(s, basestring):
+ try:
+ return str(s)
+ except UnicodeEncodeError:
+ return unicode(s).encode(encoding, errors)
+ elif isinstance(s, unicode):
+ return s.encode(encoding, errors)
+ elif s and encoding != 'utf-8':
+ return s.decode('utf-8', errors).encode(encoding, errors)
+ else:
+ return s
+
def object_to_string( obj ):
return binascii.hexlify( obj )
diff -r 6b0bd93038a843b1585155f0d63f0eea2459c70b -r 9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/f5d12a0ef90f/
Changeset: f5d12a0ef90f
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:03+00:00
Summary: Update tag latest_2013.01.13 for changeset 9c323aad4ffd
Affected #: 1 file
diff -r c25df9f3d31effd9c4abdbbffd40381f23fc6dc8 -r f5d12a0ef90f8244ade33db951e002518ed8a9fc .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -10,7 +10,7 @@
7e257c7b10badb65772b1528cb61d58175a42e47 release_2014.06.02
7a4d321c0e38fa263ea83d29a35a608c3181fcba latest_2014.06.02
9661b9d5d5b330483ae3ad2236410e0efaa7c500 latest_2014.04.14
-6b0bd93038a843b1585155f0d63f0eea2459c70b latest_2013.01.13
+9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 latest_2013.02.08
425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 latest_2013.04.01
9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 latest_2013.06.03
https://bitbucket.org/galaxy/galaxy-central/commits/cbcce50577bf/
Changeset: cbcce50577bf
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:04+00:00
Summary: Merge head created for security fix on latest_2013.01.13
Affected #: 5 files
diff -r f5d12a0ef90f8244ade33db951e002518ed8a9fc -r cbcce50577bf98aa164355caf631568e7c4b56f4 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/b986c184be88/
Changeset: b986c184be88
Branch: stable
User: dan
Date: 2015-01-13 15:26:12+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 5 files
diff -r 3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 -r b986c184be88947b5d1d90be7f36cfd2627dd938 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -2,6 +2,7 @@
from os.path import abspath
from galaxy.util import string_as_bool, stringify_dictionary_keys, listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.web import form_builder
import galaxy.model
@@ -176,7 +177,10 @@
def to_string( self, value ):
return str( value )
-
+
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -394,6 +398,10 @@
def to_string( self, value ):
return simplejson.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return simplejson.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
def to_string( self, value ):
@@ -417,7 +425,11 @@
if not value:
return str( self.spec.no_value )
return value.file_name
-
+
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context={}, other_values={}, **kwd ):
return form_builder.TextField( self.spec.name, value=str( value.id ) )
diff -r 3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 -r b986c184be88947b5d1d90be7f36cfd2627dd938 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -35,6 +35,8 @@
from galaxy.util import listify
import galaxy.util.shed_util_common
from galaxy.web import url_for
+from galaxy.util.object_wrapper import wrap_with_safe_string
+from galaxy import exceptions
from paste import httpexceptions
@@ -2384,6 +2386,9 @@
# failed to pass; for tool writing convienence, provide a
# NoneDataset
param_dict[ out_name ] = NoneDataset( datatypes_registry = self.app.datatypes_registry, ext = output.format )
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
# We add access to app here, this allows access to app.config, etc
param_dict['__app__'] = RawObjectWrapper( self.app )
# More convienent access to app.config.new_file_path; we don't need to
@@ -2401,6 +2406,23 @@
param_dict['__admin_users__'] = self.app.config.admin_users
# Return the dictionary of parameters
return param_dict
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.options or self.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
def build_param_file( self, param_dict, directory=None ):
"""
Build temporary file for file based parameter transfer if needed
@@ -3080,10 +3102,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
- setattr( self, name, rval )
+ setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
return self.metadata.__nonzero__()
@@ -3104,9 +3129,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry = datatypes_registry, ext = ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = false_path
@@ -3114,10 +3143,28 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
+ #does not implement support for false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
def __nonzero__( self ):
diff -r 3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 -r b986c184be88947b5d1d90be7f36cfd2627dd938 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -6,6 +6,7 @@
from galaxy.tools.parameters.grouping import *
from galaxy.util.template import fill_template
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
from galaxy.exceptions import ObjectInvalid
import galaxy.tools
@@ -214,7 +215,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.tool_data_path, 'shared','ucsc','chrom', "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.tool_data_path, 'shared','ucsc','chrom', "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = chrom_info
inp_data.update( db_datasets )
diff -r 3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 -r b986c184be88947b5d1d90be7f36cfd2627dd938 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -187,37 +187,59 @@
'#' : '__pd__'
}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
- """Restricts the characters that are allowed in a text"""
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ """
+ Restricts the characters that are allowed in text; accepts both strings
+ and lists of strings; non-string entities will be cast to strings.
+ """
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
+
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ """Restricts the characters that are allowed in a string"""
+
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- print value
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
-
-valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
invalid_filenames = [ '', '.', '..' ]
def sanitize_for_filename( text, default=None ):
"""
@@ -399,6 +421,28 @@
except:
return default
+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
+ """
+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
+
+ If strings_only is True, don't convert (some) non-string-like objects.
+
+ Adapted from an older, simpler version of django.utils.encoding.smart_str.
+ """
+ if strings_only and isinstance(s, (type(None), int)):
+ return s
+ if not isinstance(s, basestring):
+ try:
+ return str(s)
+ except UnicodeEncodeError:
+ return unicode(s).encode(encoding, errors)
+ elif isinstance(s, unicode):
+ return s.encode(encoding, errors)
+ elif s and encoding != 'utf-8':
+ return s.decode('utf-8', errors).encode(encoding, errors)
+ else:
+ return s
+
def object_to_string( obj ):
return binascii.hexlify( obj )
diff -r 3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 -r b986c184be88947b5d1d90be7f36cfd2627dd938 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/ccbe7f3db659/
Changeset: ccbe7f3db659
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:18+00:00
Summary: Update tag latest_2013.02.08 for changeset b986c184be88
Affected #: 1 file
diff -r cbcce50577bf98aa164355caf631568e7c4b56f4 -r ccbe7f3db659092c9d7df2845e4bab3f58a7a6b0 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -11,7 +11,7 @@
7a4d321c0e38fa263ea83d29a35a608c3181fcba latest_2014.06.02
9661b9d5d5b330483ae3ad2236410e0efaa7c500 latest_2014.04.14
9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
-3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 latest_2013.02.08
+b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 latest_2013.04.01
9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 latest_2013.06.03
9ed84cd208e07e8985ec917cb025fcbbb09edcfb latest_2013.08.12
https://bitbucket.org/galaxy/galaxy-central/commits/7c4a6bf151a2/
Changeset: 7c4a6bf151a2
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:20+00:00
Summary: Merge head created for security fix on latest_2013.02.08
Affected #: 2 files
https://bitbucket.org/galaxy/galaxy-central/commits/dec9431d66b8/
Changeset: dec9431d66b8
Branch: stable
User: dan
Date: 2015-01-13 15:26:27+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 5 files
diff -r 425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 -r dec9431d66b837a208e2f060d90afd913c721227 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -2,6 +2,7 @@
from os.path import abspath
from galaxy.util import string_as_bool, stringify_dictionary_keys, listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.web import form_builder
import galaxy.model
@@ -176,7 +177,10 @@
def to_string( self, value ):
return str( value )
-
+
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -394,6 +398,10 @@
def to_string( self, value ):
return simplejson.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return simplejson.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
def to_string( self, value ):
@@ -417,7 +425,11 @@
if not value:
return str( self.spec.no_value )
return value.file_name
-
+
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context={}, other_values={}, **kwd ):
return form_builder.TextField( self.spec.name, value=str( value.id ) )
diff -r 425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 -r dec9431d66b837a208e2f060d90afd913c721227 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -57,6 +57,8 @@
from galaxy.web import url_for
from galaxy.web.form_builder import SelectField
from tool_shed.util import shed_util_common
+from galaxy.util.object_wrapper import wrap_with_safe_string
+from galaxy import exceptions
log = logging.getLogger( __name__ )
@@ -2621,7 +2623,9 @@
return self.app.tool_data_tables[ table_name ].get_entry( query_attr, query_val, return_attr )
param_dict['__get_data_table_entry__'] = get_data_table_entry
-
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
# We add access to app here, this allows access to app.config, etc
param_dict['__app__'] = RawObjectWrapper( self.app )
# More convienent access to app.config.new_file_path; we don't need to
@@ -2639,6 +2643,23 @@
param_dict['__admin_users__'] = self.app.config.admin_users
# Return the dictionary of parameters
return param_dict
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.options or self.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
def build_param_file( self, param_dict, directory=None ):
"""
Build temporary file for file based parameter transfer if needed
@@ -3421,10 +3442,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
return self.metadata.__nonzero__()
@@ -3445,9 +3469,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry = datatypes_registry, ext = ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = false_path
@@ -3455,10 +3483,28 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
+ #does not implement support for false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
def __nonzero__( self ):
diff -r 425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 -r dec9431d66b837a208e2f060d90afd913c721227 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -6,6 +6,7 @@
from galaxy.tools.parameters.grouping import *
from galaxy.util.template import fill_template
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
from galaxy.exceptions import ObjectInvalid
import galaxy.tools
@@ -214,7 +215,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.tool_data_path, 'shared','ucsc','chrom', "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.tool_data_path, 'shared','ucsc','chrom', "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = chrom_info
inp_data.update( db_datasets )
diff -r 425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 -r dec9431d66b837a208e2f060d90afd913c721227 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -187,48 +187,60 @@
'#' : '__pd__'
}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- print value
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
-valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
invalid_filenames = [ '', '.', '..' ]
def sanitize_for_filename( text, default=None ):
"""
@@ -425,6 +437,28 @@
except:
return default
+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
+ """
+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
+
+ If strings_only is True, don't convert (some) non-string-like objects.
+
+ Adapted from an older, simpler version of django.utils.encoding.smart_str.
+ """
+ if strings_only and isinstance(s, (type(None), int)):
+ return s
+ if not isinstance(s, basestring):
+ try:
+ return str(s)
+ except UnicodeEncodeError:
+ return unicode(s).encode(encoding, errors)
+ elif isinstance(s, unicode):
+ return s.encode(encoding, errors)
+ elif s and encoding != 'utf-8':
+ return s.decode('utf-8', errors).encode(encoding, errors)
+ else:
+ return s
+
def object_to_string( obj ):
return binascii.hexlify( obj )
diff -r 425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 -r dec9431d66b837a208e2f060d90afd913c721227 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/b979070e064a/
Changeset: b979070e064a
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:32+00:00
Summary: Update tag latest_2013.04.01 for changeset dec9431d66b8
Affected #: 1 file
diff -r 7c4a6bf151a279cbc9b639e1804f0701d3b11ccf -r b979070e064ace7b70ece868977e72712f647a80 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -12,7 +12,7 @@
9661b9d5d5b330483ae3ad2236410e0efaa7c500 latest_2014.04.14
9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
-425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 latest_2013.04.01
+dec9431d66b837a208e2f060d90afd913c721227 latest_2013.04.01
9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 latest_2013.06.03
9ed84cd208e07e8985ec917cb025fcbbb09edcfb latest_2013.08.12
81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
https://bitbucket.org/galaxy/galaxy-central/commits/29a6bfeb4f46/
Changeset: 29a6bfeb4f46
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:33+00:00
Summary: Merge head created for security fix on latest_2013.04.01
Affected #: 3 files
https://bitbucket.org/galaxy/galaxy-central/commits/19e56e66b0b3/
Changeset: 19e56e66b0b3
Branch: stable
User: dan
Date: 2015-01-13 15:26:40+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 5 files
diff -r 9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 -r 19e56e66b0b344c6e2afa4541f6988e4fdb9af29 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.web import form_builder
from sqlalchemy.orm import object_session
@@ -187,7 +188,10 @@
def to_string( self, value ):
return str( value )
-
+
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -405,6 +409,10 @@
def to_string( self, value ):
return simplejson.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return simplejson.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
def to_string( self, value ):
@@ -428,7 +436,11 @@
if not value:
return str( self.spec.no_value )
return value.file_name
-
+
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context={}, other_values={}, **kwd ):
return form_builder.TextField( self.spec.name, value=str( value.id ) )
diff -r 9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 -r 19e56e66b0b344c6e2afa4541f6988e4fdb9af29 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -60,6 +60,8 @@
from galaxy.web.form_builder import SelectField
from tool_shed.util import shed_util_common
from .loader import load_tool, template_macro_params
+from galaxy.util.object_wrapper import wrap_with_safe_string
+from galaxy import exceptions
log = logging.getLogger( __name__ )
@@ -2543,7 +2545,9 @@
return self.app.tool_data_tables[ table_name ].get_entry( query_attr, query_val, return_attr )
param_dict['__get_data_table_entry__'] = get_data_table_entry
-
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
# We add access to app here, this allows access to app.config, etc
param_dict['__app__'] = RawObjectWrapper( self.app )
# More convienent access to app.config.new_file_path; we don't need to
@@ -2562,6 +2566,23 @@
param_dict['__user__'] = RawObjectWrapper( param_dict.get( '__user__', None ) )
# Return the dictionary of parameters
return param_dict
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.options or self.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
def build_param_file( self, param_dict, directory=None ):
"""
Build temporary file for file based parameter transfer if needed
@@ -3357,10 +3378,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
return self.metadata.__nonzero__()
@@ -3381,9 +3405,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry = datatypes_registry, ext = ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = false_path
@@ -3391,10 +3419,28 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
+ #does not implement support for false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
def __nonzero__( self ):
diff -r 9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 -r 19e56e66b0b344c6e2afa4541f6988e4fdb9af29 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -6,6 +6,7 @@
from galaxy.tools.parameters.grouping import *
from galaxy.util.template import fill_template
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
from galaxy.exceptions import ObjectInvalid
import galaxy.tools
@@ -214,7 +215,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = chrom_info
inp_data.update( db_datasets )
diff -r 9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 -r 19e56e66b0b344c6e2afa4541f6988e4fdb9af29 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -249,48 +249,60 @@
'#' : '__pd__'
}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- print value
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
-valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
invalid_filenames = [ '', '.', '..' ]
def sanitize_for_filename( text, default=None ):
"""
@@ -488,6 +500,28 @@
except:
return default
+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
+ """
+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
+
+ If strings_only is True, don't convert (some) non-string-like objects.
+
+ Adapted from an older, simpler version of django.utils.encoding.smart_str.
+ """
+ if strings_only and isinstance(s, (type(None), int)):
+ return s
+ if not isinstance(s, basestring):
+ try:
+ return str(s)
+ except UnicodeEncodeError:
+ return unicode(s).encode(encoding, errors)
+ elif isinstance(s, unicode):
+ return s.encode(encoding, errors)
+ elif s and encoding != 'utf-8':
+ return s.decode('utf-8', errors).encode(encoding, errors)
+ else:
+ return s
+
def object_to_string( obj ):
return binascii.hexlify( obj )
diff -r 9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 -r 19e56e66b0b344c6e2afa4541f6988e4fdb9af29 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/4b481505104e/
Changeset: 4b481505104e
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:45+00:00
Summary: Update tag latest_2013.06.03 for changeset 19e56e66b0b3
Affected #: 1 file
diff -r 29a6bfeb4f468e76c84bea8bc5d445ebf08fdfee -r 4b481505104efe8a711532ad0878e7f5cb6786c0 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -13,7 +13,7 @@
9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
dec9431d66b837a208e2f060d90afd913c721227 latest_2013.04.01
-9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 latest_2013.06.03
+19e56e66b0b344c6e2afa4541f6988e4fdb9af29 latest_2013.06.03
9ed84cd208e07e8985ec917cb025fcbbb09edcfb latest_2013.08.12
81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
https://bitbucket.org/galaxy/galaxy-central/commits/91ca514f61ec/
Changeset: 91ca514f61ec
Branch: stable
User: natefoo
Date: 2015-01-13 15:26:46+00:00
Summary: Merge head created for security fix on latest_2013.06.03
Affected #: 4 files
https://bitbucket.org/galaxy/galaxy-central/commits/cee903b8b3ee/
Changeset: cee903b8b3ee
Branch: stable
User: dan
Date: 2015-01-13 15:26:56+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 5 files
diff -r 9ed84cd208e07e8985ec917cb025fcbbb09edcfb -r cee903b8b3eee9145627ee89742555dac581791e lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.web import form_builder
from sqlalchemy.orm import object_session
@@ -187,7 +188,10 @@
def to_string( self, value ):
return str( value )
-
+
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -405,6 +409,10 @@
def to_string( self, value ):
return simplejson.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return simplejson.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
def to_string( self, value ):
@@ -428,7 +436,11 @@
if not value:
return str( self.spec.no_value )
return value.file_name
-
+
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context={}, other_values={}, **kwd ):
return form_builder.TextField( self.spec.name, value=str( value.id ) )
diff -r 9ed84cd208e07e8985ec917cb025fcbbb09edcfb -r cee903b8b3eee9145627ee89742555dac581791e lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -61,6 +61,8 @@
from galaxy.web.form_builder import SelectField
from tool_shed.util import shed_util_common
from .loader import load_tool, template_macro_params
+from galaxy.util.object_wrapper import wrap_with_safe_string
+from galaxy import exceptions
log = logging.getLogger( __name__ )
@@ -2553,7 +2555,9 @@
return self.app.tool_data_tables[ table_name ].get_entry( query_attr, query_val, return_attr )
param_dict['__get_data_table_entry__'] = get_data_table_entry
-
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
# We add access to app here, this allows access to app.config, etc
param_dict['__app__'] = RawObjectWrapper( self.app )
# More convienent access to app.config.new_file_path; we don't need to
@@ -2572,6 +2576,23 @@
param_dict['__user__'] = RawObjectWrapper( param_dict.get( '__user__', None ) )
# Return the dictionary of parameters
return param_dict
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.options or self.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
def build_param_file( self, param_dict, directory=None ):
"""
Build temporary file for file based parameter transfer if needed
@@ -3369,10 +3390,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
return self.metadata.__nonzero__()
@@ -3393,9 +3417,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry = datatypes_registry, ext = ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = false_path
@@ -3403,10 +3431,28 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
+ #does not implement support for false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
def __nonzero__( self ):
diff -r 9ed84cd208e07e8985ec917cb025fcbbb09edcfb -r cee903b8b3eee9145627ee89742555dac581791e lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -10,6 +10,7 @@
from galaxy.util.none_like import NoneDataset
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
import logging
@@ -217,7 +218,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = chrom_info
inp_data.update( db_datasets )
diff -r 9ed84cd208e07e8985ec917cb025fcbbb09edcfb -r cee903b8b3eee9145627ee89742555dac581791e lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -301,47 +301,60 @@
'#' : '__pd__'
}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
-valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
invalid_filenames = [ '', '.', '..' ]
def sanitize_for_filename( text, default=None ):
"""
@@ -539,6 +552,28 @@
except:
return default
+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
+ """
+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
+
+ If strings_only is True, don't convert (some) non-string-like objects.
+
+ Adapted from an older, simpler version of django.utils.encoding.smart_str.
+ """
+ if strings_only and isinstance(s, (type(None), int)):
+ return s
+ if not isinstance(s, basestring):
+ try:
+ return str(s)
+ except UnicodeEncodeError:
+ return unicode(s).encode(encoding, errors)
+ elif isinstance(s, unicode):
+ return s.encode(encoding, errors)
+ elif s and encoding != 'utf-8':
+ return s.decode('utf-8', errors).encode(encoding, errors)
+ else:
+ return s
+
def object_to_string( obj ):
return binascii.hexlify( obj )
diff -r 9ed84cd208e07e8985ec917cb025fcbbb09edcfb -r cee903b8b3eee9145627ee89742555dac581791e lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/f87251ad7e02/
Changeset: f87251ad7e02
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:02+00:00
Summary: Update tag latest_2013.08.12 for changeset cee903b8b3ee
Affected #: 1 file
diff -r 91ca514f61ec74cecd7ef93a1f34b4fc618e0694 -r f87251ad7e0262908cb4f6e37e235610c16eaeb9 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -14,7 +14,7 @@
b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
dec9431d66b837a208e2f060d90afd913c721227 latest_2013.04.01
19e56e66b0b344c6e2afa4541f6988e4fdb9af29 latest_2013.06.03
-9ed84cd208e07e8985ec917cb025fcbbb09edcfb latest_2013.08.12
+cee903b8b3eee9145627ee89742555dac581791e latest_2013.08.12
81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
https://bitbucket.org/galaxy/galaxy-central/commits/0face4c7b1c9/
Changeset: 0face4c7b1c9
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:03+00:00
Summary: Merge head created for security fix on latest_2013.08.12
Affected #: 3 files
https://bitbucket.org/galaxy/galaxy-central/commits/7d5aa19a166c/
Changeset: 7d5aa19a166c
Branch: stable
User: dan
Date: 2015-01-13 15:27:09+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 5 files
diff -r 81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 -r 7d5aa19a166cba9039e15f338a1e3fc924c43d3a lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.web import form_builder
from sqlalchemy.orm import object_session
@@ -188,6 +189,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -405,6 +409,10 @@
def to_string( self, value ):
return simplejson.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return simplejson.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
def to_string( self, value ):
@@ -429,6 +437,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context={}, other_values={}, **kwd ):
return form_builder.TextField( self.spec.name, value=str( value.id ) )
diff -r 81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 -r 7d5aa19a166cba9039e15f338a1e3fc924c43d3a lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -65,6 +65,8 @@
from galaxy.model.item_attrs import Dictifiable
from tool_shed.util import shed_util_common
from .loader import load_tool, template_macro_params
+from galaxy.util.object_wrapper import wrap_with_safe_string
+from galaxy import exceptions
log = logging.getLogger( __name__ )
@@ -2560,7 +2562,9 @@
return self.app.tool_data_tables[ table_name ].get_entry( query_attr, query_val, return_attr )
param_dict['__get_data_table_entry__'] = get_data_table_entry
-
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
# We add access to app here, this allows access to app.config, etc
param_dict['__app__'] = RawObjectWrapper( self.app )
# More convienent access to app.config.new_file_path; we don't need to
@@ -2579,6 +2583,23 @@
param_dict['__user__'] = RawObjectWrapper( param_dict.get( '__user__', None ) )
# Return the dictionary of parameters
return param_dict
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.options or self.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
def build_param_file( self, param_dict, directory=None ):
"""
Build temporary file for file based parameter transfer if needed
@@ -3352,10 +3373,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
return self.metadata.__nonzero__()
@@ -3376,9 +3400,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry = datatypes_registry, ext = ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = false_path
@@ -3386,10 +3414,28 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
+ #does not implement support for false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
def __nonzero__( self ):
diff -r 81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 -r 7d5aa19a166cba9039e15f338a1e3fc924c43d3a lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -10,6 +10,7 @@
from galaxy.util.none_like import NoneDataset
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
import logging
@@ -224,7 +225,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = chrom_info
inp_data.update( db_datasets )
diff -r 81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 -r 7d5aa19a166cba9039e15f338a1e3fc924c43d3a lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -309,47 +309,60 @@
'#' : '__pd__'
}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
-valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
invalid_filenames = [ '', '.', '..' ]
def sanitize_for_filename( text, default=None ):
"""
@@ -574,6 +587,28 @@
return s
+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
+ """
+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
+
+ If strings_only is True, don't convert (some) non-string-like objects.
+
+ Adapted from an older, simpler version of django.utils.encoding.smart_str.
+ """
+ if strings_only and isinstance(s, (type(None), int)):
+ return s
+ if not isinstance(s, basestring):
+ try:
+ return str(s)
+ except UnicodeEncodeError:
+ return unicode(s).encode(encoding, errors)
+ elif isinstance(s, unicode):
+ return s.encode(encoding, errors)
+ elif s and encoding != 'utf-8':
+ return s.decode('utf-8', errors).encode(encoding, errors)
+ else:
+ return s
+
def object_to_string( obj ):
return binascii.hexlify( obj )
diff -r 81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 -r 7d5aa19a166cba9039e15f338a1e3fc924c43d3a lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/48635612a356/
Changeset: 48635612a356
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:13+00:00
Summary: Update tag latest_2013.11.04 for changeset 7d5aa19a166c
Affected #: 1 file
diff -r 0face4c7b1c9c1991fb7ab93abca5e0f47eece96 -r 48635612a3561e83aa77d604e44d0cea80969c2a .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -15,7 +15,7 @@
dec9431d66b837a208e2f060d90afd913c721227 latest_2013.04.01
19e56e66b0b344c6e2afa4541f6988e4fdb9af29 latest_2013.06.03
cee903b8b3eee9145627ee89742555dac581791e latest_2013.08.12
-81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
+7d5aa19a166cba9039e15f338a1e3fc924c43d3a latest_2013.11.04
2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
https://bitbucket.org/galaxy/galaxy-central/commits/5b0c93bcc791/
Changeset: 5b0c93bcc791
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:15+00:00
Summary: Merge head created for security fix on latest_2013.11.04
Affected #: 4 files
https://bitbucket.org/galaxy/galaxy-central/commits/0c000cc2f9c0/
Changeset: 0c000cc2f9c0
Branch: stable
User: dan
Date: 2015-01-13 15:27:19+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 6 files
diff -r 2a756ca2cb1826db7796018e77d12e2dd7b67603 -r 0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -17,6 +17,7 @@
import galaxy.model
from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.util import in_directory
from galaxy.web import form_builder
@@ -209,6 +210,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -457,6 +461,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -487,6 +495,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r 2a756ca2cb1826db7796018e77d12e2dd7b67603 -r 0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -9,6 +9,7 @@
from galaxy.util.none_like import NoneDataset
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
import logging
@@ -176,7 +177,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = os.path.abspath( chrom_info )
inp_data.update( db_datasets )
diff -r 2a756ca2cb1826db7796018e77d12e2dd7b67603 -r 0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
LibraryDatasetValueWrapper,
@@ -109,6 +111,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -309,6 +314,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r 2a756ca2cb1826db7796018e77d12e2dd7b67603 -r 0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -1,5 +1,7 @@
import pipes
+from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import wrap_with_safe_string
class ToolParameterValueWrapper( object ):
@@ -145,10 +147,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -173,9 +178,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = getattr( dataset_path, "false_path", None )
self.false_extra_files_path = getattr( dataset_path, "false_extra_files_path", None )
@@ -184,13 +193,31 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
elif self.false_extra_files_path is not None and key == 'extra_files_path':
+ # Path to extra files was rewritten for this job.
return self.false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
diff -r 2a756ca2cb1826db7796018e77d12e2dd7b67603 -r 0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -328,48 +328,62 @@
'\n' : '__cn__',
'\r' : '__cr__',
'\t' : '__tc__',
- '#' : '__pd__'
- }
+ '#': '__pd__'}
-def restore_text(text):
+
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
invalid_filenames = [ '', '.', '..' ]
diff -r 2a756ca2cb1826db7796018e77d12e2dd7b67603 -r 0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/bf8b6aeb7fd7/
Changeset: bf8b6aeb7fd7
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:22+00:00
Summary: Update tag latest_2014.02.10 for changeset 0c000cc2f9c0
Affected #: 1 file
diff -r 5b0c93bcc791747b315038a66fdb785f9db4ea47 -r bf8b6aeb7fd7d6b7ae8f64b97f7d585df22817b6 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -16,7 +16,7 @@
19e56e66b0b344c6e2afa4541f6988e4fdb9af29 latest_2013.06.03
cee903b8b3eee9145627ee89742555dac581791e latest_2013.08.12
7d5aa19a166cba9039e15f338a1e3fc924c43d3a latest_2013.11.04
-2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
+0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
https://bitbucket.org/galaxy/galaxy-central/commits/50867216bdc8/
Changeset: 50867216bdc8
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:23+00:00
Summary: Merge head created for security fix on latest_2014.02.10
Affected #: 5 files
https://bitbucket.org/galaxy/galaxy-central/commits/8f9dcac03369/
Changeset: 8f9dcac03369
Branch: stable
User: dan
Date: 2015-01-13 15:27:27+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 6 files
diff -r 9661b9d5d5b330483ae3ad2236410e0efaa7c500 -r 8f9dcac033694e4cabcf5daae5cca1cfefbe967f lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -17,6 +17,7 @@
import galaxy.model
from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.util import in_directory
from galaxy.web import form_builder
@@ -209,6 +210,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -457,6 +461,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -487,6 +495,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r 9661b9d5d5b330483ae3ad2236410e0efaa7c500 -r 8f9dcac033694e4cabcf5daae5cca1cfefbe967f lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -9,6 +9,7 @@
from galaxy.util.none_like import NoneDataset
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.web import url_for
import logging
@@ -176,7 +177,7 @@
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % input_dbkey )
+ chrom_info = os.path.join( trans.app.config.len_file_path, "%s.len" % ( sanitize_lists_to_string( input_dbkey ) ) )
incoming[ "chromInfo" ] = os.path.abspath( chrom_info )
inp_data.update( db_datasets )
diff -r 9661b9d5d5b330483ae3ad2236410e0efaa7c500 -r 8f9dcac033694e4cabcf5daae5cca1cfefbe967f lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
LibraryDatasetValueWrapper,
@@ -109,6 +111,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -309,6 +314,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r 9661b9d5d5b330483ae3ad2236410e0efaa7c500 -r 8f9dcac033694e4cabcf5daae5cca1cfefbe967f lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -1,5 +1,7 @@
import pipes
+from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import wrap_with_safe_string
class ToolParameterValueWrapper( object ):
@@ -145,10 +147,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -173,9 +178,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = getattr( dataset_path, "false_path", None )
self.false_extra_files_path = getattr( dataset_path, "false_extra_files_path", None )
@@ -184,13 +193,31 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
elif self.false_extra_files_path is not None and key == 'extra_files_path':
+ # Path to extra files was rewritten for this job.
return self.false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
diff -r 9661b9d5d5b330483ae3ad2236410e0efaa7c500 -r 8f9dcac033694e4cabcf5daae5cca1cfefbe967f lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -330,48 +330,62 @@
'\n' : '__cn__',
'\r' : '__cr__',
'\t' : '__tc__',
- '#' : '__pd__'
- }
+ '#': '__pd__'}
-def restore_text(text):
+
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
invalid_filenames = [ '', '.', '..' ]
diff -r 9661b9d5d5b330483ae3ad2236410e0efaa7c500 -r 8f9dcac033694e4cabcf5daae5cca1cfefbe967f lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/1cc98e8f6782/
Changeset: 1cc98e8f6782
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:31+00:00
Summary: Update tag latest_2014.04.14 for changeset 8f9dcac03369
Affected #: 1 file
diff -r 50867216bdc89348afbce913b8371eb3463ce576 -r 1cc98e8f678283d05dbd5693bc0f48ce49c340bf .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -9,7 +9,7 @@
9e53251b0b7e93b9563008a2b112f2e815a04bbc release_2014.04.14
7e257c7b10badb65772b1528cb61d58175a42e47 release_2014.06.02
7a4d321c0e38fa263ea83d29a35a608c3181fcba latest_2014.06.02
-9661b9d5d5b330483ae3ad2236410e0efaa7c500 latest_2014.04.14
+8f9dcac033694e4cabcf5daae5cca1cfefbe967f latest_2014.04.14
9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
dec9431d66b837a208e2f060d90afd913c721227 latest_2013.04.01
https://bitbucket.org/galaxy/galaxy-central/commits/c46ef9a4aa9c/
Changeset: c46ef9a4aa9c
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:32+00:00
Summary: Merge head created for security fix on latest_2014.04.14
Affected #: 1 file
https://bitbucket.org/galaxy/galaxy-central/commits/4145417a6e1c/
Changeset: 4145417a6e1c
Branch: stable
User: dan
Date: 2015-01-13 15:27:36+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 6 files
diff -r 7a4d321c0e38fa263ea83d29a35a608c3181fcba -r 4145417a6e1c13f82a3de365aadef0fb3ed7ab14 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -17,6 +17,7 @@
import galaxy.model
from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.util import in_directory
from galaxy.web import form_builder
@@ -209,6 +210,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -457,6 +461,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -487,6 +495,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r 7a4d321c0e38fa263ea83d29a35a608c3181fcba -r 4145417a6e1c13f82a3de365aadef0fb3ed7ab14 lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
DatasetCollectionWrapper,
@@ -114,6 +116,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -334,6 +339,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r 7a4d321c0e38fa263ea83d29a35a608c3181fcba -r 4145417a6e1c13f82a3de365aadef0fb3ed7ab14 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -1,5 +1,7 @@
import pipes
+from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util import odict
from logging import getLogger
@@ -149,10 +151,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -177,9 +182,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = getattr( dataset_path, "false_path", None )
self.false_extra_files_path = getattr( dataset_path, "false_extra_files_path", None )
@@ -192,13 +201,31 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
return self.false_path
elif self.false_extra_files_path is not None and key == 'extra_files_path':
+ # Path to extra files was rewritten for this job.
return self.false_extra_files_path
+ elif key == 'extra_files_path':
+ try:
+ # Assume it is an output and that this wrapper
+ # will be set with correct "files_path" for this
+ # job.
+ return self.files_path
+ except AttributeError:
+ # Otherwise, we have an input - delegate to model and
+ # object store to find the static location of this
+ # directory.
+ try:
+ return self.unsanitized.extra_files_path
+ except exceptions.ObjectNotFound:
+ # NestedObjectstore raises an error here
+ # instead of just returning a non-existent
+ # path like DiskObjectStore.
+ raise
else:
return getattr( self.dataset, key )
diff -r 7a4d321c0e38fa263ea83d29a35a608c3181fcba -r 4145417a6e1c13f82a3de365aadef0fb3ed7ab14 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -330,48 +330,62 @@
'\n' : '__cn__',
'\r' : '__cr__',
'\t' : '__tc__',
- '#' : '__pd__'
- }
+ '#': '__pd__'}
-def restore_text(text):
+
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
- raise Exception, 'Unknown parameter type (%s)' % ( type( value ) )
+ raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
valid_filename_chars = set( string.ascii_letters + string.digits + '_.' )
invalid_filenames = [ '', '.', '..' ]
diff -r 7a4d321c0e38fa263ea83d29a35a608c3181fcba -r 4145417a6e1c13f82a3de365aadef0fb3ed7ab14 lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -4,6 +4,7 @@
#dbkeys read from disk using builds.txt
from galaxy.util import dbnames
from galaxy.util.json import from_json_string
+from galaxy.util.object_wrapper import sanitize_lists_to_string
import os.path
@@ -84,6 +85,7 @@
# use configured server len path
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % dbkey )
+ # Since we are using an unverified dbkey, we will sanitize the dbkey before use
+ chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string( dbkey ) )
chrom_info = os.path.abspath( chrom_info )
return ( chrom_info, db_dataset )
diff -r 7a4d321c0e38fa263ea83d29a35a608c3181fcba -r 4145417a6e1c13f82a3de365aadef0fb3ed7ab14 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/5d390ca2627a/
Changeset: 5d390ca2627a
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:39+00:00
Summary: Update tag latest_2014.06.02 for changeset 4145417a6e1c
Affected #: 1 file
diff -r c46ef9a4aa9cb7eca5951d82bf9aeba408a48496 -r 5d390ca2627a4e9b7ab004da072f21b15dc25501 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -8,7 +8,7 @@
5e605ed6069fe4c5ca9875e95e91b2713499e8ca release_2014.02.10
9e53251b0b7e93b9563008a2b112f2e815a04bbc release_2014.04.14
7e257c7b10badb65772b1528cb61d58175a42e47 release_2014.06.02
-7a4d321c0e38fa263ea83d29a35a608c3181fcba latest_2014.06.02
+4145417a6e1c13f82a3de365aadef0fb3ed7ab14 latest_2014.06.02
8f9dcac033694e4cabcf5daae5cca1cfefbe967f latest_2014.04.14
9c323aad4ffdd65a3deb06a4a36f6b2c5115a60f latest_2013.01.13
b986c184be88947b5d1d90be7f36cfd2627dd938 latest_2013.02.08
https://bitbucket.org/galaxy/galaxy-central/commits/ffacc6553f1a/
Changeset: ffacc6553f1a
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:40+00:00
Summary: Merge head created for security fix on latest_2014.06.02
Affected #: 4 files
https://bitbucket.org/galaxy/galaxy-central/commits/8150024c0e6f/
Changeset: 8150024c0e6f
Branch: stable
User: dan
Date: 2015-01-13 15:27:43+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 6 files
diff -r 548ab24667d6206780237bd807f7d857a484c461 -r 8150024c0e6fc5aef3033cf8aaa574896f6b5d0d lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -17,6 +17,7 @@
import galaxy.model
from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util.odict import odict
from galaxy.util import in_directory
from galaxy.web import form_builder
@@ -227,6 +228,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -475,6 +479,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -505,6 +513,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r 548ab24667d6206780237bd807f7d857a484c461 -r 8150024c0e6fc5aef3033cf8aaa574896f6b5d0d lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
DatasetCollectionWrapper,
@@ -114,6 +116,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -334,6 +339,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r 548ab24667d6206780237bd807f7d857a484c461 -r 8150024c0e6fc5aef3033cf8aaa574896f6b5d0d lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -1,6 +1,7 @@
import pipes
from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util import odict
from logging import getLogger
@@ -162,10 +163,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -190,9 +194,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = getattr( dataset_path, "false_path", None )
self.false_extra_files_path = getattr( dataset_path, "false_extra_files_path", None )
@@ -205,7 +213,7 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
@@ -225,7 +233,7 @@
# object store to find the static location of this
# directory.
try:
- return self.dataset.extra_files_path
+ return self.unsanitized.extra_files_path
except exceptions.ObjectNotFound:
# NestedObjectstore raises an error here
# instead of just returning a non-existent
diff -r 548ab24667d6206780237bd807f7d857a484c461 -r 8150024c0e6fc5aef3033cf8aaa574896f6b5d0d lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -345,46 +345,57 @@
'#': '__pd__'}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
diff -r 548ab24667d6206780237bd807f7d857a484c461 -r 8150024c0e6fc5aef3033cf8aaa574896f6b5d0d lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -4,6 +4,7 @@
#dbkeys read from disk using builds.txt
from galaxy.util import dbnames
from galaxy.util.json import from_json_string
+from galaxy.util.object_wrapper import sanitize_lists_to_string
import os.path
@@ -84,6 +85,7 @@
# use configured server len path
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % dbkey )
+ # Since we are using an unverified dbkey, we will sanitize the dbkey before use
+ chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string( dbkey ) )
chrom_info = os.path.abspath( chrom_info )
return ( chrom_info, db_dataset )
diff -r 548ab24667d6206780237bd807f7d857a484c461 -r 8150024c0e6fc5aef3033cf8aaa574896f6b5d0d lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/c776fba69528/
Changeset: c776fba69528
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:46+00:00
Summary: Update tag latest_2014.08.11 for changeset 8150024c0e6f
Affected #: 1 file
diff -r ffacc6553f1ad02470d92e058c15848251e12453 -r c776fba69528715271b416a97928246888180d80 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -18,6 +18,6 @@
7d5aa19a166cba9039e15f338a1e3fc924c43d3a latest_2013.11.04
0c000cc2f9c05bf4c1c2bc3a10215014fd64e696 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
-548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
+8150024c0e6fc5aef3033cf8aaa574896f6b5d0d latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
ff6e36d7a2388214fe7636c43d30838c07246907 latest_2014.10.06
https://bitbucket.org/galaxy/galaxy-central/commits/37201f6fe299/
Changeset: 37201f6fe299
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:47+00:00
Summary: Merge head created for security fix on latest_2014.08.11
Affected #: 3 files
https://bitbucket.org/galaxy/galaxy-central/commits/c437b28348a9/
Changeset: c437b28348a9
Branch: stable
User: dan
Date: 2015-01-13 15:27:49+00:00
Summary: Fix a critical security vulnerability where unsanitized user-modifiable values could be included in a command line template.
Affected #: 6 files
diff -r ff6e36d7a2388214fe7636c43d30838c07246907 -r c437b28348a9345db8433e5b4f0e05ec8fb6c38a lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util import stringify_dictionary_keys
from galaxy.util import string_as_bool
from galaxy.util import in_directory
@@ -232,6 +233,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -480,6 +484,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.safe_dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -510,6 +518,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r ff6e36d7a2388214fe7636c43d30838c07246907 -r c437b28348a9345db8433e5b4f0e05ec8fb6c38a lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
DatasetCollectionWrapper,
@@ -114,6 +116,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -334,6 +339,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r ff6e36d7a2388214fe7636c43d30838c07246907 -r c437b28348a9345db8433e5b4f0e05ec8fb6c38a lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -2,6 +2,7 @@
from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
from galaxy.util import odict
+from galaxy.util.object_wrapper import wrap_with_safe_string
from logging import getLogger
log = getLogger( __name__ )
@@ -162,10 +163,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -190,9 +194,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.datatypes_registry = datatypes_registry
self.false_path = getattr( dataset_path, "false_path", None )
@@ -210,7 +218,7 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
@@ -230,7 +238,7 @@
# object store to find the static location of this
# directory.
try:
- return self.dataset.extra_files_path
+ return self.unsanitized.extra_files_path
except exceptions.ObjectNotFound:
# NestedObjectstore raises an error here
# instead of just returning a non-existent
diff -r ff6e36d7a2388214fe7636c43d30838c07246907 -r c437b28348a9345db8433e5b4f0e05ec8fb6c38a lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -360,46 +360,57 @@
'#': '__pd__'}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
diff -r ff6e36d7a2388214fe7636c43d30838c07246907 -r c437b28348a9345db8433e5b4f0e05ec8fb6c38a lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -4,6 +4,7 @@
#dbkeys read from disk using builds.txt
from galaxy.util import read_dbnames
from galaxy.util.json import loads
+from galaxy.util.object_wrapper import sanitize_lists_to_string
import os.path
@@ -84,6 +85,7 @@
# use configured server len path
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % dbkey )
+ # Since we are using an unverified dbkey, we will sanitize the dbkey before use
+ chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string( dbkey ) )
chrom_info = os.path.abspath( chrom_info )
return ( chrom_info, db_dataset )
diff -r ff6e36d7a2388214fe7636c43d30838c07246907 -r c437b28348a9345db8433e5b4f0e05ec8fb6c38a lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/593bd69b3d5b/
Changeset: 593bd69b3d5b
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:50+00:00
Summary: Update tag latest_2014.10.06 for changeset c437b28348a9
Affected #: 1 file
diff -r 37201f6fe299a099fad0b5f54ff0ba72a02185cb -r 593bd69b3d5b937c2eb0ae5133a8f989b3131504 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,4 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
8150024c0e6fc5aef3033cf8aaa574896f6b5d0d latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-ff6e36d7a2388214fe7636c43d30838c07246907 latest_2014.10.06
+c437b28348a9345db8433e5b4f0e05ec8fb6c38a latest_2014.10.06
https://bitbucket.org/galaxy/galaxy-central/commits/605de23ca239/
Changeset: 605de23ca239
Branch: stable
User: natefoo
Date: 2015-01-13 15:27:51+00:00
Summary: Merge head created for security fix on latest_2014.10.06
Affected #: 5 files
diff -r 593bd69b3d5b937c2eb0ae5133a8f989b3131504 -r 605de23ca239879a34426885feddd2d3a459ca26 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util import stringify_dictionary_keys
from galaxy.util import string_as_bool
from galaxy.util import in_directory
@@ -232,6 +233,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -480,6 +484,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.safe_dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -510,6 +518,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r 593bd69b3d5b937c2eb0ae5133a8f989b3131504 -r 605de23ca239879a34426885feddd2d3a459ca26 lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
DatasetCollectionWrapper,
@@ -114,6 +116,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -334,6 +339,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r 593bd69b3d5b937c2eb0ae5133a8f989b3131504 -r 605de23ca239879a34426885feddd2d3a459ca26 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -2,6 +2,7 @@
from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
from galaxy.util import odict
+from galaxy.util.object_wrapper import wrap_with_safe_string
from logging import getLogger
log = getLogger( __name__ )
@@ -162,10 +163,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -190,9 +194,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.datatypes_registry = datatypes_registry
self.false_path = getattr( dataset_path, "false_path", None )
@@ -210,7 +218,7 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
@@ -230,7 +238,7 @@
# object store to find the static location of this
# directory.
try:
- return self.dataset.extra_files_path
+ return self.unsanitized.extra_files_path
except exceptions.ObjectNotFound:
# NestedObjectstore raises an error here
# instead of just returning a non-existent
diff -r 593bd69b3d5b937c2eb0ae5133a8f989b3131504 -r 605de23ca239879a34426885feddd2d3a459ca26 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -360,46 +360,57 @@
'#': '__pd__'}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
diff -r 593bd69b3d5b937c2eb0ae5133a8f989b3131504 -r 605de23ca239879a34426885feddd2d3a459ca26 lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -4,6 +4,7 @@
#dbkeys read from disk using builds.txt
from galaxy.util import read_dbnames
from galaxy.util.json import loads
+from galaxy.util.object_wrapper import sanitize_lists_to_string
import os.path
@@ -84,6 +85,7 @@
# use configured server len path
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % dbkey )
+ # Since we are using an unverified dbkey, we will sanitize the dbkey before use
+ chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string( dbkey ) )
chrom_info = os.path.abspath( chrom_info )
return ( chrom_info, db_dataset )
https://bitbucket.org/galaxy/galaxy-central/commits/8da5fd3df6e7/
Changeset: 8da5fd3df6e7
Branch: next-stable
User: natefoo
Date: 2015-01-13 15:33:41+00:00
Summary: Close next-stable branch for release_2015.01.13
Affected #: 6 files
diff -r 7fe5cbb6b66e0debec7775a88a8c553384784a00 -r 8da5fd3df6e7e710bd9c9e5acc3baa98a665e247 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -20,6 +20,7 @@
import galaxy.model
from galaxy.util import listify
+from galaxy.util.object_wrapper import sanitize_lists_to_string
from galaxy.util import stringify_dictionary_keys
from galaxy.util import string_as_bool
from galaxy.util import in_directory
@@ -232,6 +233,9 @@
def to_string( self, value ):
return str( value )
+ def to_safe_string( self, value ):
+ return sanitize_lists_to_string( self.to_string( value ) )
+
def make_copy( self, value, target_context = None, source_context = None ):
return copy.deepcopy( value )
@@ -480,6 +484,10 @@
def to_string( self, value ):
return json.dumps( value )
+ def to_safe_string( self, value ):
+ # We do not sanitize json dicts
+ return json.safe_dumps( value )
+
class PythonObjectParameter( MetadataParameter ):
@@ -510,6 +518,10 @@
return str( self.spec.no_value )
return value.file_name
+ def to_safe_string( self, value ):
+ # We do not sanitize file names
+ return self.to_string( value )
+
def get_html_field( self, value=None, context=None, other_values=None, **kwd ):
context = context or {}
other_values = other_values or {}
diff -r 7fe5cbb6b66e0debec7775a88a8c553384784a00 -r 8da5fd3df6e7e710bd9c9e5acc3baa98a665e247 lib/galaxy/tools/evaluation.py
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -2,10 +2,12 @@
import tempfile
from galaxy import model
+from galaxy.util.object_wrapper import wrap_with_safe_string
from galaxy.util.bunch import Bunch
from galaxy.util.none_like import NoneDataset
from galaxy.util.template import fill_template
from galaxy.tools.wrappers import (
+ ToolParameterValueWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
DatasetCollectionWrapper,
@@ -114,6 +116,9 @@
self.__populate_input_dataset_wrappers(param_dict, input_datasets, input_dataset_paths)
self.__populate_output_dataset_wrappers(param_dict, output_datasets, output_paths, job_working_directory)
self.__populate_unstructured_path_rewrites(param_dict)
+ # Call param dict sanitizer, before non-job params are added, as we don't want to sanitize filenames.
+ self.__sanitize_param_dict( param_dict )
+ # Parameters added after this line are not sanitized
self.__populate_non_job_params(param_dict)
# Return the dictionary of parameters
@@ -334,6 +339,24 @@
#the paths rewritten.
self.__walk_inputs( self.tool.inputs, param_dict, rewrite_unstructured_paths )
+ def __sanitize_param_dict( self, param_dict ):
+ """
+ Sanitize all values that will be substituted on the command line, with the exception of ToolParameterValueWrappers,
+ which already have their own specific sanitization rules and also exclude special-cased named values.
+ We will only examine the first level for values to skip; the wrapping function will recurse as necessary.
+
+ Note: this method follows the style of the similar populate calls, in that param_dict is modified in-place.
+ """
+ # chromInfo is a filename, do not sanitize it.
+ skip = [ 'chromInfo' ]
+ if not self.tool or not self.tool.options or self.tool.options.sanitize:
+ for key, value in param_dict.items():
+ if key not in skip:
+ # Remove key so that new wrapped object will occupy key slot
+ del param_dict[key]
+ # And replace with new wrapped key
+ param_dict[ wrap_with_safe_string( key, no_wrap_classes=ToolParameterValueWrapper ) ] = wrap_with_safe_string( value, no_wrap_classes=ToolParameterValueWrapper )
+
def build( self ):
"""
Build runtime description of job to execute, evaluate command and
diff -r 7fe5cbb6b66e0debec7775a88a8c553384784a00 -r 8da5fd3df6e7e710bd9c9e5acc3baa98a665e247 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -2,6 +2,7 @@
from galaxy import exceptions
from galaxy.util.none_like import NoneDataset
from galaxy.util import odict
+from galaxy.util.object_wrapper import wrap_with_safe_string
from logging import getLogger
log = getLogger( __name__ )
@@ -162,10 +163,13 @@
if name in self.metadata.spec:
if rval is None:
rval = self.metadata.spec[name].no_value
- rval = self.metadata.spec[name].param.to_string( rval )
+ rval = self.metadata.spec[ name ].param.to_safe_string( rval )
# Store this value, so we don't need to recalculate if needed
# again
setattr( self, name, rval )
+ else:
+ #escape string value of non-defined metadata value
+ rval = wrap_with_safe_string( rval )
return rval
def __nonzero__( self ):
@@ -190,9 +194,13 @@
ext = tool.inputs[name].extensions[0]
except:
ext = 'data'
- self.dataset = NoneDataset( datatypes_registry=datatypes_registry, ext=ext )
+ self.dataset = wrap_with_safe_string( NoneDataset( datatypes_registry=datatypes_registry, ext=ext ), no_wrap_classes=ToolParameterValueWrapper )
else:
- self.dataset = dataset
+ # Tool wrappers should not normally be accessing .dataset directly,
+ # so we will wrap it and keep the original around for file paths
+ # Should we name this .value to maintain consistency with most other ToolParameterValueWrapper?
+ self.unsanitized = dataset
+ self.dataset = wrap_with_safe_string( dataset, no_wrap_classes=ToolParameterValueWrapper )
self.metadata = self.MetadataWrapper( dataset.metadata )
self.datatypes_registry = datatypes_registry
self.false_path = getattr( dataset_path, "false_path", None )
@@ -210,7 +218,7 @@
if self.false_path is not None:
return self.false_path
else:
- return self.dataset.file_name
+ return self.unsanitized.file_name
def __getattr__( self, key ):
if self.false_path is not None and key == 'file_name':
@@ -230,7 +238,7 @@
# object store to find the static location of this
# directory.
try:
- return self.dataset.extra_files_path
+ return self.unsanitized.extra_files_path
except exceptions.ObjectNotFound:
# NestedObjectstore raises an error here
# instead of just returning a non-existent
diff -r 7fe5cbb6b66e0debec7775a88a8c553384784a00 -r 8da5fd3df6e7e710bd9c9e5acc3baa98a665e247 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -360,46 +360,57 @@
'#': '__pd__'}
-def restore_text(text):
+def restore_text( text, character_map=mapped_chars ):
"""Restores sanitized text"""
if not text:
return text
- for key, value in mapped_chars.items():
+ for key, value in character_map.items():
text = text.replace(value, key)
return text
-def sanitize_text(text):
+def sanitize_text( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""
Restricts the characters that are allowed in text; accepts both strings
- and lists of strings.
+ and lists of strings; non-string entities will be cast to strings.
"""
- if isinstance( text, basestring ):
- return _sanitize_text_helper(text)
- elif isinstance( text, list ):
- return [ _sanitize_text_helper(t) for t in text ]
+ if isinstance( text, list ):
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), text )
+ if not isinstance( text, basestring ):
+ text = smart_str( text )
+ return _sanitize_text_helper( text, valid_characters=valid_characters, character_map=character_map )
-
-def _sanitize_text_helper(text):
+def _sanitize_text_helper( text, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Restricts the characters that are allowed in a string"""
out = []
for c in text:
- if c in valid_chars:
+ if c in valid_characters:
out.append(c)
- elif c in mapped_chars:
- out.append(mapped_chars[c])
+ elif c in character_map:
+ out.append( character_map[c] )
else:
- out.append('X') # makes debugging easier
+ out.append( invalid_character ) # makes debugging easier
return ''.join(out)
-def sanitize_param(value):
+def sanitize_lists_to_string( values, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
+ if isinstance( values, list ):
+ rval = []
+ for value in values:
+ rval.append( sanitize_lists_to_string( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ) )
+ values = ",".join( rval )
+ else:
+ values = sanitize_text( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+ return values
+
+
+def sanitize_param( value, valid_characters=valid_chars, character_map=mapped_chars, invalid_character='X' ):
"""Clean incoming parameters (strings or lists)"""
if isinstance( value, basestring ):
- return sanitize_text(value)
+ return sanitize_text( value, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
elif isinstance( value, list ):
- return map(sanitize_text, value)
+ return map( lambda x: sanitize_text( x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character ), value )
else:
raise Exception('Unknown parameter type (%s)' % ( type( value ) ))
diff -r 7fe5cbb6b66e0debec7775a88a8c553384784a00 -r 8da5fd3df6e7e710bd9c9e5acc3baa98a665e247 lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -4,6 +4,7 @@
#dbkeys read from disk using builds.txt
from galaxy.util import read_dbnames
from galaxy.util.json import loads
+from galaxy.util.object_wrapper import sanitize_lists_to_string
import os.path
@@ -84,6 +85,7 @@
# use configured server len path
if not chrom_info:
# Default to built-in build.
- chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % dbkey )
+ # Since we are using an unverified dbkey, we will sanitize the dbkey before use
+ chrom_info = os.path.join( self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string( dbkey ) )
chrom_info = os.path.abspath( chrom_info )
return ( chrom_info, db_dataset )
diff -r 7fe5cbb6b66e0debec7775a88a8c553384784a00 -r 8da5fd3df6e7e710bd9c9e5acc3baa98a665e247 lib/galaxy/util/object_wrapper.py
--- /dev/null
+++ b/lib/galaxy/util/object_wrapper.py
@@ -0,0 +1,436 @@
+"""
+Classes for wrapping Objects and Sanitizing string output.
+"""
+
+import inspect
+import copy_reg
+import logging
+import string
+from numbers import Number
+from types import ( NoneType, NotImplementedType, EllipsisType, FunctionType, MethodType, GeneratorType, CodeType,
+ BuiltinFunctionType, BuiltinMethodType, ModuleType, XRangeType, SliceType, TracebackType, FrameType,
+ BufferType, DictProxyType, GetSetDescriptorType, MemberDescriptorType )
+from UserDict import UserDict
+
+from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string
+
+log = logging.getLogger( __name__ )
+
+# Define different behaviors for different types, see also: https://docs.python.org/2/library/types.html
+
+# Known Callable types
+__CALLABLE_TYPES__ = ( FunctionType, MethodType, GeneratorType, CodeType, BuiltinFunctionType, BuiltinMethodType, )
+
+# Always wrap these types without attempting to subclass
+__WRAP_NO_SUBCLASS__ = ( ModuleType, XRangeType, SliceType, BufferType, TracebackType, FrameType, DictProxyType,
+ GetSetDescriptorType, MemberDescriptorType ) + __CALLABLE_TYPES__
+
+# Don't wrap or sanitize.
+__DONT_SANITIZE_TYPES__ = ( Number, bool, NoneType, NotImplementedType, EllipsisType, bytearray, )
+
+# Don't wrap, but do sanitize.
+__DONT_WRAP_TYPES__ = tuple() #( basestring, ) so that we can get the unsanitized string, we will now wrap basestring instances
+
+# Wrap contents, but not the container
+__WRAP_SEQUENCES__ = ( tuple, list, )
+__WRAP_SETS__ = ( set, frozenset, )
+__WRAP_MAPPINGS__ = ( dict, UserDict, )
+
+
+# Define the set of characters that are not sanitized, and define a set of mappings for those that are.
+# characters that are valid
+VALID_CHARACTERS = set( string.letters + string.digits + " -=_.()/+*^,:?!@" )
+
+# characters that are allowed but need to be escaped
+CHARACTER_MAP = { '>': '__gt__',
+ '<': '__lt__',
+ "'": '__sq__',
+ '"': '__dq__',
+ '[': '__ob__',
+ ']': '__cb__',
+ '{': '__oc__',
+ '}': '__cc__',
+ '\n': '__cn__',
+ '\r': '__cr__',
+ '\t': '__tc__',
+ '#': '__pd__'}
+
+INVALID_CHARACTER = "X"
+
+def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+ return _sanitize_lists_to_string( values, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character )
+
+
+def wrap_with_safe_string( value, no_wrap_classes = None ):
+ """
+ Recursively wrap values that should be wrapped.
+ """
+
+ def __do_wrap( value ):
+ if isinstance( value, SafeStringWrapper ):
+ # Only ever wrap one-layer
+ return value
+ if callable( value ):
+ safe_class = CallableSafeStringWrapper
+ else:
+ safe_class = SafeStringWrapper
+ if isinstance( value, no_wrap_classes ):
+ return value
+ if isinstance( value, __DONT_WRAP_TYPES__ ):
+ return sanitize_lists_to_string( value, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+ if isinstance( value, __WRAP_NO_SUBCLASS__ ):
+ return safe_class( value, safe_string_wrapper_function = __do_wrap )
+ for this_type in __WRAP_SEQUENCES__ + __WRAP_SETS__:
+ if isinstance( value, this_type ):
+ return this_type( map( __do_wrap, value ) )
+ for this_type in __WRAP_MAPPINGS__:
+ if isinstance( value, this_type ):
+ # Wrap both key and value
+ return this_type( map( lambda x: ( __do_wrap( x[0] ), __do_wrap( x[1] ) ), value.items() ) )
+ # Create a dynamic class that joins SafeStringWrapper with the object being wrapped.
+ # This allows e.g. isinstance to continue to work.
+ try:
+ wrapped_class_name = value.__name__
+ wrapped_class = value
+ except:
+ wrapped_class_name = value.__class__.__name__
+ wrapped_class = value.__class__
+ value_mod = inspect.getmodule( value )
+ if value_mod:
+ wrapped_class_name = "%s.%s" % ( value_mod.__name__, wrapped_class_name )
+ wrapped_class_name = "SafeStringWrapper(%s:%s)" % ( wrapped_class_name, ",".join( sorted( map( str, no_wrap_classes ) ) ) )
+ do_wrap_func_name = "__do_wrap_%s" % ( wrapped_class_name )
+ do_wrap_func = __do_wrap
+ global_dict = globals()
+ if wrapped_class_name in global_dict:
+ # Check to see if we have created a wrapper for this class yet, if so, reuse
+ wrapped_class = global_dict.get( wrapped_class_name )
+ do_wrap_func = global_dict.get( do_wrap_func_name, __do_wrap )
+ else:
+ try:
+ wrapped_class = type( wrapped_class_name, ( safe_class, wrapped_class, ), {} )
+ except TypeError, e:
+ # Fail-safe for when a class cannot be dynamically subclassed.
+ log.warning( "Unable to create dynamic subclass for %s, %s: %s", type( value), value, e )
+ wrapped_class = type( wrapped_class_name, ( safe_class, ), {} )
+ if wrapped_class not in ( SafeStringWrapper, CallableSafeStringWrapper ):
+ # Save this wrapper for reuse and pickling/copying
+ global_dict[ wrapped_class_name ] = wrapped_class
+ do_wrap_func.__name__ = do_wrap_func_name
+ global_dict[ do_wrap_func_name ] = do_wrap_func
+ def pickle_safe_object( safe_object ):
+ return ( wrapped_class, ( safe_object.unsanitized, do_wrap_func, ) )
+ # Set pickle and copy properties
+ copy_reg.pickle( wrapped_class, pickle_safe_object, do_wrap_func )
+ return wrapped_class( value, safe_string_wrapper_function = do_wrap_func )
+ # Determine classes not to wrap
+ if no_wrap_classes:
+ if not isinstance( no_wrap_classes, ( tuple, list ) ):
+ no_wrap_classes = [ no_wrap_classes ]
+ no_wrap_classes = list( no_wrap_classes ) + list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ else:
+ no_wrap_classes = list( __DONT_SANITIZE_TYPES__ ) + [ SafeStringWrapper ]
+ no_wrap_classes = tuple( set( sorted( no_wrap_classes, key=str ) ) )
+ return __do_wrap( value )
+
+
+# N.B. refer to e.g. https://docs.python.org/2/reference/datamodel.html for information on Python's Data Model.
+
+
+class SafeStringWrapper( object ):
+ """
+ Class that wraps and sanitizes any provided value's attributes
+ that will attempt to be cast into a string.
+
+ Attempts to mimic behavior of original class, including operands.
+
+ To ensure proper handling of e.g. subclass checks, the *wrap_with_safe_string()*
+ method should be used.
+
+ This wrapping occurs in a recursive/parasitic fashion, as all called attributes of
+ the originally wrapped object will also be wrapped and sanitized, unless the attribute
+ is of a type found in __DONT_SANITIZE_TYPES__ + __DONT_WRAP_TYPES__, where e.g. ~(strings
+ will still be sanitized, but not wrapped), and e.g. integers will have neither.
+ """
+ __UNSANITIZED_ATTRIBUTE_NAME__ = 'unsanitized'
+ __NO_WRAP_NAMES__ = [ '__safe_string_wrapper_function__', __UNSANITIZED_ATTRIBUTE_NAME__]
+
+
+ def __new__( cls, *arg, **kwd ):
+ # We need to define a __new__ since, we are subclassing from e.g. immutable str, which internally sets data
+ # that will be used when other + this (this + other is handled by __add__)
+ safe_string_wrapper_function = kwd.get( 'safe_string_wrapper_function', None) or wrap_with_safe_string
+ try:
+ return super( SafeStringWrapper, cls ).__new__( cls, sanitize_lists_to_string( arg[0], valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+ except Exception, e:
+ log.warning( "Could not provide an argument to %s.__new__: %s; will try without arguments.", cls, e )
+ return super( SafeStringWrapper, cls ).__new__( cls )
+
+ def __init__( self, value, safe_string_wrapper_function = wrap_with_safe_string ):
+ self.unsanitized = value
+ self.__safe_string_wrapper_function__ = safe_string_wrapper_function
+
+ def __str__( self ):
+ return sanitize_lists_to_string( self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP )
+
+ def __repr__( self ):
+ return "%s object at %x on: %s" % ( sanitize_lists_to_string( self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ), id( self ), sanitize_lists_to_string( repr( self.unsanitized ), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP ) )
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __le__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized <= other
+
+ def __eq__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized == other
+
+ def __ne__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized != other
+
+ def __gt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized > other
+
+ def __ge__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized >= other
+
+ def __lt__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.unsanitized < other
+
+ def __cmp__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return cmp( self.unsanitized, other )
+
+ # Do not implement __rcmp__, python 2.2 < 2.6
+
+ def __hash__( self ):
+ return hash( self.unsanitized )
+
+ def __nonzero__( self ):
+ return bool( self.unsanitized )
+
+ # Do not implement __unicode__, we will rely on __str__
+
+ def __getattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ #FIXME: is this ever reached?
+ return object.__getattr__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( self.unsanitized, name ) )
+
+ def __setattr__( self, name, value ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__setattr__( self, name, value )
+ return setattr( self.unsanitized, name, value )
+
+ def __delattr__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__delattr__( self, name )
+ return delattr( self.unsanitized, name )
+
+ def __getattribute__( self, name ):
+ if name in SafeStringWrapper.__NO_WRAP_NAMES__:
+ return object.__getattribute__( self, name )
+ return self.__safe_string_wrapper_function__( getattr( object.__getattribute__( self, 'unsanitized' ), name ) )
+
+ # Skip Descriptors
+
+ # Skip __slots__
+
+ # Don't need __metaclass__, we'll use the helper function to handle with subclassing for e.g. isinstance()
+
+ # Revisit:
+ # __instancecheck__
+ # __subclasscheck__
+ # We are using a helper class to create dynamic subclasses to handle class checks
+
+ # We address __call__ as needed based upon unsanitized, through the use of a CallableSafeStringWrapper class
+
+ def __len__( self ):
+ original_value = self.unsanitized
+ while isinstance( original_value, SafeStringWrapper ):
+ original_value = self.unsanitized
+ return len( self.unsanitized )
+
+ def __getitem__( self, key ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ key ] )
+
+ def __setitem__( self, key, value ):
+ while isinstance( value, SafeStringWrapper ):
+ value = value.unsanitized
+ self.unsanitized[ key ] = value
+
+ def __delitem__( self, key ):
+ del self.unsanitized[ key ]
+
+ def __iter__( self ):
+ return iter( map( self.__safe_string_wrapper_function__, iter( self.unsanitized ) ) )
+
+ # Do not implement __reversed__
+
+ def __contains__( self, item ):
+ # FIXME: Do we need to consider if item is/isn't or does/doesn't contain SafeStringWrapper?
+ # When considering e.g. nested lists/dicts/etc, this gets complicated
+ while isinstance( item, SafeStringWrapper ):
+ item = item.unsanitized
+ return item in self.unsanitized
+
+ # Not sure that we need these slice methods, but will provide anyway
+ def __getslice__( self, i, j ):
+ return self.__safe_string_wrapper_function__( self.unsanitized[ i:j ] )
+
+ def __setslice__( self, i, j, value ):
+ self.unsanitized[ i:j ] = value
+
+ def __delslice__( self, i, j ):
+ del self.unsanitized[ i:j ]
+
+ def __add__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized + other )
+
+ def __sub__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized - other )
+
+ def __mul__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized * other )
+
+ def __floordiv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized // other )
+
+ def __mod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized % other )
+
+ def __divmod__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( divmod( self.unsanitized, other ) )
+
+ def __pow__( self, *other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( self.unsanitized, *other ) )
+
+ def __lshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized << other )
+
+ def __rshift__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized >> other )
+
+ def __and__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized & other )
+
+ def __xor__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized ^ other )
+
+ def __or__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized | other )
+
+ def __div__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ def __truediv__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( self.unsanitized / other )
+
+ # The only reflected operand that we will define is __rpow__, due to coercion rules complications as per docs
+ def __rpow__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return self.__safe_string_wrapper_function__( pow( other, self.unsanitized ) )
+
+ # Do not implement in-place operands
+
+ def __neg__( self ):
+ return __safe_string_wrapper_function__( -self.unsanitized )
+
+ def __pos__( self ):
+ return __safe_string_wrapper_function__( +self.unsanitized )
+
+ def __abs__( self ):
+ return __safe_string_wrapper_function__( abs( self.unsanitized ) )
+
+ def __invert__( self ):
+ return __safe_string_wrapper_function__( ~self.unsanitized )
+
+ def __complex__( self ):
+ return __safe_string_wrapper_function__( complex( self.unsanitized ) )
+
+ def __int__( self ):
+ return int( self.unsanitized )
+
+ def __float__( self ):
+ return float( self.unsanitized )
+
+ def __oct__( self ):
+ return oct( self.unsanitized )
+
+ def __hex__( self ):
+ return hex( self.unsanitized )
+
+ def __index__( self ):
+ return self.unsanitized.index()
+
+ def __coerce__( self, other ):
+ while isinstance( other, SafeStringWrapper ):
+ other = other.unsanitized
+ return coerce( self.unsanitized, other )
+
+ def __enter__( self ):
+ return self.unsanitized.__enter__()
+
+ def __exit__( self, *args ):
+ return self.unsanitized.__exit__( *args )
+
+class CallableSafeStringWrapper( SafeStringWrapper ):
+
+ def __call__( self, *args, **kwds ):
+ return self.__safe_string_wrapper_function__( self.unsanitized( *args, **kwds ) )
+
+
+# Enable pickling/deepcopy
+def pickle_SafeStringWrapper( safe_object ):
+ args = ( safe_object.unsanitized, )
+ cls = SafeStringWrapper
+ if isinstance( safe_object, CallableSafeStringWrapper ):
+ cls = CallableSafeStringWrapper
+ return ( cls, args )
+copy_reg.pickle( SafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+copy_reg.pickle( CallableSafeStringWrapper, pickle_SafeStringWrapper, wrap_with_safe_string )
+
https://bitbucket.org/galaxy/galaxy-central/commits/2e8dd2949dd3/
Changeset: 2e8dd2949dd3
Branch: stable
User: natefoo
Date: 2015-01-13 15:33:50+00:00
Summary: Merge next-stable to stable for release_2015.01.13
Affected #: 427 files
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee .hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -67,6 +67,7 @@
shed_data_manager_conf.xml
object_store_conf.xml
job_metrics_conf.xml
+workflow_schedulers_conf.xml
config/*
static/welcome.html.*
static/welcome.html
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee buildbot_setup.sh
--- a/buildbot_setup.sh
+++ b/buildbot_setup.sh
@@ -126,5 +126,3 @@
echo "Appending tool-data/shared/ucsc/builds.txt.buildbot to tool-data/shared/ucsc/builds.txt"
cat tool-data/shared/ucsc/builds.txt.buildbot >> tool-data/shared/ucsc/builds.txt
-
-python ./scripts/fetch_eggs.py all
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/galaxy.frame.js
--- a/client/galaxy/scripts/galaxy.frame.js
+++ b/client/galaxy/scripts/galaxy.frame.js
@@ -1,9 +1,8 @@
// dependencies
define(["galaxy.masthead", "mvc/ui/ui-frames"], function(mod_masthead, Frames) {
-// frame manager
-var GalaxyFrame = Backbone.View.extend(
-{
+/** Frame manager uses the ui-frames to create the scratch book masthead icon and functionality **/
+var GalaxyFrame = Backbone.View.extend({
// base element
el_main: 'body',
@@ -17,8 +16,7 @@
button_load : null,
// initialize
- initialize : function(options)
- {
+ initialize : function(options) {
// add to masthead menu
var self = this;
@@ -28,8 +26,7 @@
});
// add activate icon
- this.button_active = new mod_masthead.GalaxyMastheadIcon (
- {
+ this.button_active = new mod_masthead.GalaxyMastheadIcon({
icon : 'fa-th',
tooltip : 'Enable/Disable Scratchbook',
onclick : function() { self._activate(); },
@@ -44,8 +41,7 @@
Galaxy.masthead.append(this.button_active);
// add load icon
- this.button_load = new mod_masthead.GalaxyMastheadIcon (
- {
+ this.button_load = new mod_masthead.GalaxyMastheadIcon({
icon : 'fa-eye',
tooltip : 'Show/Hide Scratchbook',
onclick : function(e) {
@@ -122,35 +118,77 @@
});
},
+
+ /**
+ * Add a trackster visualization to the frames.
+ */
+ add_trackster_viz: function(viz_id) {
+ var self = this;
+ require(['viz/visualization', 'viz/trackster'], function(visualization, trackster) {
+ var viz = new visualization.Visualization({id: viz_id});
+ $.when( viz.fetch() ).then( function() {
+ var ui = new trackster.TracksterUI(galaxy_config.root);
+
+ // Construct frame config based on dataset's type.
+ var frame_config = {
+ title: viz.get('name'),
+ type: 'other',
+ content: function(parent_elt) {
+ // Create view config.
+ var view_config = {
+ container: parent_elt,
+ name: viz.get('title'),
+ id: viz.id,
+ // FIXME: this will not work with custom builds b/c the dbkey needed to be encoded.
+ dbkey: viz.get('dbkey'),
+ stand_alone: false
+ },
+ latest_revision = viz.get('latest_revision'),
+ drawables = latest_revision.config.view.drawables;
+
+ // Set up datasets in drawables.
+ _.each(drawables, function(d) {
+ d.dataset = {
+ hda_ldda: d.hda_ldda,
+ id: d.dataset_id
+ };
+ });
+
+ view = ui.create_visualization(view_config,
+ latest_revision.config.viewport,
+ latest_revision.config.view.drawables,
+ latest_revision.config.bookmarks,
+ false);
+ }
+ };
+
+ self.add(frame_config);
+ });
+ });
+ },
/**
* Add and display a new frame/window based on options.
*/
- add: function(options)
- {
+ add: function(options){
// open new tab
- if (options.target == '_blank')
- {
+ if (options.target == '_blank'){
window.open(options.content);
return;
}
// reload entire window
- if (options.target == '_top' || options.target == '_parent' || options.target == '_self')
- {
+ if (options.target == '_top' || options.target == '_parent' || options.target == '_self'){
window.location = options.content;
return;
}
// validate
- if (!this.active)
- {
+ if (!this.active){
// fix url if main frame is unavailable
var $galaxy_main = $(window.parent.document).find('#galaxy_main');
- if (options.target == 'galaxy_main' || options.target == 'center')
- {
- if ($galaxy_main.length === 0)
- {
+ if (options.target == 'galaxy_main' || options.target == 'center'){
+ if ($galaxy_main.length === 0){
var href = options.content;
if (href.indexOf('?') == -1)
href += '?';
@@ -173,11 +211,9 @@
},
// activate/disable panel
- _activate: function ()
- {
+ _activate: function (){
// check
- if (this.active)
- {
+ if (this.active){
// disable
this.active = false;
@@ -196,8 +232,7 @@
},
// update frame counter
- _refresh: function()
- {
+ _refresh: function(){
// update on screen counter
this.button_load.number(this.frames.length());
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/galaxy.interactive_environments.js
--- /dev/null
+++ b/client/galaxy/scripts/galaxy.interactive_environments.js
@@ -0,0 +1,59 @@
+/**
+ * Internal function to remove content from the main area and add the notebook.
+ * Not idempotent
+ */
+function append_notebook(url){
+ clear_main_area();
+ $('#main').append('<iframe frameBorder="0" seamless="seamless" style="width: 100%; height: 100%; overflow:hidden;" scrolling="no" src="'+ url +'"></iframe>'
+ );
+}
+
+function clear_main_area(){
+ $('#spinner').remove();
+ $('#main').children().remove();
+}
+
+function display_spinner(){
+ $('#main').append('<img id="spinner" src="' + galaxy_root + '/static/style/largespinner.gif" style="position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;">');
+}
+
+
+/**
+ * Test availability of a URL, and call a callback when done.
+ * http://stackoverflow.com/q/25390206/347368
+ * @param {String} url: URL to test availability of. Must return a 200 (302->200 is OK).
+ * @param {String} callback: function to call once successfully connected.
+ *
+ */
+function test_ie_availability(url, success_callback){
+ var request_count = 0;
+ display_spinner();
+ interval = setInterval(function(){
+ $.ajax({
+ url: url,
+ xhrFields: {
+ withCredentials: true
+ },
+ type: "GET",
+ timeout: 500,
+ success: function(){
+ console.log("Connected to IE, returning");
+ clearInterval(interval);
+ success_callback();
+ },
+ error: function(jqxhr, status, error){
+ request_count++;
+ console.log("Request " + request_count);
+ if(request_count > 30){
+ clearInterval(interval);
+ clear_main_area();
+ toastr.error(
+ "Could not connect to IE, contact your administrator",
+ "Error",
+ {'closeButton': true, 'timeOut': 20000, 'tapToDismiss': false}
+ );
+ }
+ }
+ });
+ }, 1000);
+}
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/galaxy.library.js
--- a/client/galaxy/scripts/galaxy.library.js
+++ b/client/galaxy/scripts/galaxy.library.js
@@ -16,19 +16,19 @@
"mvc/library/library-library-view",
"mvc/library/library-folder-view"
],
-function(mod_masthead,
- mod_utils,
- mod_toastr,
- mod_baseMVC,
- mod_library_model,
- mod_folderlist_view,
- mod_librarylist_view,
- mod_librarytoolbar_view,
- mod_foldertoolbar_view,
- mod_library_dataset_view,
- mod_library_library_view,
- mod_library_folder_view
- ) {
+ function(mod_masthead,
+ mod_utils,
+ mod_toastr,
+ mod_baseMVC,
+ mod_library_model,
+ mod_folderlist_view,
+ mod_librarylist_view,
+ mod_librarytoolbar_view,
+ mod_foldertoolbar_view,
+ mod_library_dataset_view,
+ mod_library_library_view,
+ mod_library_folder_view
+ ) {
// ============================================================================
// ROUTER
@@ -36,40 +36,44 @@
initialize: function() {
this.routesHit = 0;
//keep count of number of routes handled by the application
- Backbone.history.on('route', function() { this.routesHit++; }, this);
- },
+ Backbone.history.on( 'route', function() { this.routesHit++; }, this );
+},
- routes: {
+routes: {
"" : "libraries",
+ "page/:show_page" : "libraries_page",
"library/:library_id/permissions" : "library_permissions",
"folders/:folder_id/permissions" : "folder_permissions",
"folders/:id" : "folder_content",
+ "folders/:id/page/:show_page" : "folder_page",
"folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
"folders/:folder_id/datasets/:dataset_id/permissions" : "dataset_permissions",
"folders/:folder_id/datasets/:dataset_id/versions/:ldda_id" : "dataset_version",
"folders/:folder_id/download/:format" : "download",
"folders/:folder_id/import/:source" : "import_datasets"
- },
+},
- back: function() {
- if(this.routesHit > 1) {
+back: function() {
+ if( this.routesHit > 1 ) {
//more than one route hit -> user did not land to current page directly
window.history.back();
- } else {
+ } else {
//otherwise go to the home page. Use replaceState if available so
//the navigation doesn't create an extra history entry
- this.navigate('#', {trigger:true, replace:true});
- }
+ this.navigate( '#', { trigger:true, replace:true } );
}
+}
});
// ============================================================================
/** session storage for library preferences */
var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({
defaults : {
- with_deleted : false,
- sort_order : 'asc',
- sort_by : 'name'
+ with_deleted : false,
+ sort_order : 'asc',
+ sort_by : 'name',
+ library_page_size : 20,
+ folder_page_size : 15
}
});
@@ -88,77 +92,97 @@
initialize : function(){
Galaxy.libraries = this;
- this.preferences = new LibraryPrefs( {id: 'global-lib-prefs'} );
+ this.preferences = new LibraryPrefs( { id: 'global-lib-prefs' } );
this.library_router = new LibraryRouter();
- this.library_router.on('route:libraries', function() {
- Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
- Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView();
+ this.library_router.on( 'route:libraries', function() {
+ Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
+ Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView();
+ });
+
+ this.library_router.on('route:libraries_page', function( show_page ) {
+ if ( Galaxy.libraries.libraryToolbarView === null ){
+ Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
+ Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView( { show_page: show_page } );
+ } else {
+ Galaxy.libraries.libraryListView.render( { show_page: show_page } )
+ }
});
- this.library_router.on('route:folder_content', function(id) {
+ this.library_router.on( 'route:folder_content', function( id ) {
if (Galaxy.libraries.folderToolbarView){
- Galaxy.libraries.folderToolbarView.$el.unbind('click');
+ Galaxy.libraries.folderToolbarView.$el.unbind( 'click' );
}
- Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id});
- Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id});
+ Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView( { id: id } );
+ Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView( { id: id } );
});
- this.library_router.on('route:download', function(folder_id, format) {
- if ($('#folder_list_body').find(':checked').length === 0) {
- mod_toastr.info( 'You must select at least one dataset to download' );
- Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true});
- } else {
- Galaxy.libraries.folderToolbarView.download(folder_id, format);
- Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: false, replace: true});
- }
+ this.library_router.on( 'route:folder_page', function( id, show_page ) {
+ if ( Galaxy.libraries.folderToolbarView === null ){
+ Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView( {id: id} );
+ Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView( { id: id, show_page: show_page } );
+ } else {
+ Galaxy.libraries.folderListView.render( { id: id, show_page: parseInt( show_page ) } )
+ }
});
- this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){
- if (Galaxy.libraries.datasetView){
- Galaxy.libraries.datasetView.$el.unbind('click');
- }
- Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id});
- });
- this.library_router.on('route:dataset_version', function(folder_id, dataset_id, ldda_id){
- if (Galaxy.libraries.datasetView){
- Galaxy.libraries.datasetView.$el.unbind('click');
- }
- Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true});
- });
+ this.library_router.on( 'route:download', function( folder_id, format ) {
+ if ( $( '#folder_list_body' ).find( ':checked' ).length === 0 ) {
+ mod_toastr.info( 'You must select at least one dataset to download' );
+ Galaxy.libraries.library_router.navigate( 'folders/' + folder_id, { trigger: true, replace: true } );
+ } else {
+ Galaxy.libraries.folderToolbarView.download( folder_id, format );
+ Galaxy.libraries.library_router.navigate( 'folders/' + folder_id, { trigger: false, replace: true } );
+ }
+ });
- this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){
- if (Galaxy.libraries.datasetView){
- Galaxy.libraries.datasetView.$el.unbind('click');
- }
- Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true});
- });
+ this.library_router.on( 'route:dataset_detail', function(folder_id, dataset_id){
+ if (Galaxy.libraries.datasetView){
+ Galaxy.libraries.datasetView.$el.unbind('click');
+ }
+ Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id});
+ });
- this.library_router.on('route:library_permissions', function(library_id){
- if (Galaxy.libraries.libraryView){
- Galaxy.libraries.libraryView.$el.unbind('click');
- }
- Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true});
- });
+ this.library_router.on( 'route:dataset_version', function(folder_id, dataset_id, ldda_id){
+ if (Galaxy.libraries.datasetView){
+ Galaxy.libraries.datasetView.$el.unbind('click');
+ }
+ Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true});
+ });
- this.library_router.on('route:folder_permissions', function(folder_id){
- if (Galaxy.libraries.folderView){
- Galaxy.libraries.folderView.$el.unbind('click');
- }
- Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true});
- });
- this.library_router.on('route:import_datasets', function(folder_id, source){
- if (Galaxy.libraries.folderToolbarView && Galaxy.libraries.folderListView){
- Galaxy.libraries.folderToolbarView.showImportModal({source:source});
- } else {
- Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: folder_id});
- Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id});
- Galaxy.libraries.folderToolbarView.showImportModal({source: source});
- }
- });
+ this.library_router.on( 'route:dataset_permissions', function(folder_id, dataset_id){
+ if (Galaxy.libraries.datasetView){
+ Galaxy.libraries.datasetView.$el.unbind('click');
+ }
+ Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true});
+ });
- Backbone.history.start({pushState: false});
+ this.library_router.on( 'route:library_permissions', function(library_id){
+ if (Galaxy.libraries.libraryView){
+ Galaxy.libraries.libraryView.$el.unbind('click');
+ }
+ Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true});
+ });
+
+ this.library_router.on( 'route:folder_permissions', function(folder_id){
+ if (Galaxy.libraries.folderView){
+ Galaxy.libraries.folderView.$el.unbind('click');
+ }
+ Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true});
+ });
+
+ this.library_router.on( 'route:import_datasets', function( folder_id, source ){
+ if ( Galaxy.libraries.folderToolbarView && Galaxy.libraries.folderListView ){
+ Galaxy.libraries.folderToolbarView.showImportModal( { source:source } );
+ } else {
+ Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView( { id: folder_id } );
+ Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView( { id: folder_id } );
+ Galaxy.libraries.folderToolbarView.showImportModal( { source: source } );
+ }
+ });
+
+ Backbone.history.start({pushState: false});
}
});
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/galaxy.masthead.js
--- a/client/galaxy/scripts/galaxy.masthead.js
+++ b/client/galaxy/scripts/galaxy.masthead.js
@@ -1,9 +1,8 @@
// dependencies
define([], function() {
-// masthead
-var GalaxyMasthead = Backbone.View.extend(
-{
+/** Masthead **/
+var GalaxyMasthead = Backbone.View.extend({
// base element
el_masthead: '#everything',
@@ -17,8 +16,7 @@
list: [],
// initialize
- initialize : function(options)
- {
+ initialize : function(options) {
// update options
this.options = options;
@@ -51,27 +49,23 @@
},
// configure events
- events:
- {
+ events: {
'click' : '_click',
'mousedown' : function(e) { e.preventDefault() }
},
// adds a new item to the masthead
- append : function(item)
- {
+ append : function(item) {
return this._add(item, true);
},
// adds a new item to the masthead
- prepend : function(item)
- {
+ prepend : function(item) {
return this._add(item, false);
},
// activate
- highlight: function(id)
- {
+ highlight: function(id) {
var current = $(this.el).find('#' + id + '> li');
if (current) {
current.addClass('active');
@@ -79,11 +73,9 @@
},
// adds a new item to the masthead
- _add : function(item, append)
- {
+ _add : function(item, append) {
var $loc = $(this.el).find('#' + item.location);
- if ($loc)
- {
+ if ($loc){
// create frame for new item
var $current = $(item.el);
@@ -106,8 +98,7 @@
},
// handle click event
- _click: function(e)
- {
+ _click: function(e) {
// close all popups
var $all = $(this.el).find('.popup');
if ($all) {
@@ -129,8 +120,7 @@
*/
// fill template
- _template: function(options)
- {
+ _template: function(options) {
var brand_text = options.brand ? ("/ " + options.brand) : "" ;
return '<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse">' +
'<div style="position: relative; right: -50%; float: left;">' +
@@ -150,12 +140,10 @@
}
});
-// icon
-var GalaxyMastheadIcon = Backbone.View.extend(
-{
+/** Masthead icon **/
+var GalaxyMastheadIcon = Backbone.View.extend({
// icon options
- options:
- {
+ options:{
id : '',
icon : 'fa-cog',
tooltip : '',
@@ -169,8 +157,7 @@
location: 'iconbar',
// initialize
- initialize: function (options)
- {
+ initialize: function (options){
// read in defaults
if (options)
this.options = _.defaults(options, this.options);
@@ -189,20 +176,17 @@
},
// show
- show: function()
- {
+ show: function(){
$(this.el).css({visibility : 'visible'});
},
// show
- hide: function()
- {
+ hide: function(){
$(this.el).css({visibility : 'hidden'});
},
// switch icon
- icon: function (new_icon)
- {
+ icon: function (new_icon){
// update icon class
$(this.el).find('.icon').removeClass(this.options.icon)
.addClass(new_icon);
@@ -212,26 +196,22 @@
},
// toggle
- toggle: function()
- {
+ toggle: function(){
$(this.el).addClass('toggle');
},
// untoggle
- untoggle: function()
- {
+ untoggle: function(){
$(this.el).removeClass('toggle');
},
// set/get number
- number: function(new_number)
- {
+ number: function(new_number){
$(this.el).find('.number').text(new_number);
},
// fill template icon
- _template: function (options)
- {
+ _template: function (options){
var tmpl = '<div id="' + options.id + '" class="symbol">' +
'<div class="icon fa fa-2x ' + options.icon + '"></div>';
if (options.with_number)
@@ -243,12 +223,10 @@
}
});
-// tab
-var GalaxyMastheadTab = Backbone.View.extend(
-{
+/** Masthead tab **/
+var GalaxyMastheadTab = Backbone.View.extend({
// main options
- options:
- {
+ options:{
id : '',
title : '',
target : '_parent',
@@ -268,52 +246,50 @@
$menu: null,
// events
- events:
- {
+ events:{
'click .head' : '_head'
},
// initialize
- initialize: function (options)
- {
+ initialize: function ( options ){
// read in defaults
- if (options)
- this.options = _.defaults(options, this.options);
-
+ if ( options ){
+ this.options = _.defaults( options, this.options );
+ }
+
// update url
- if (this.options.content && this.options.content.indexOf('//') === -1)
+ if ( this.options.content !== undefined && this.options.content.indexOf( '//' ) === -1 ){
this.options.content = galaxy_config.root + this.options.content;
+ }
// add template for tab
- this.setElement($(this._template(this.options)));
+ 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');
+ if ( this.options.disabled ){
+ $( this.el ).find( '.root' ).addClass( 'disabled' );
this._attachPopover();
}
// visiblity
- if (!this.options.visible)
+ if ( !this.options.visible ){
this.hide();
+ }
},
// show
- show: function()
- {
+ show: function(){
$(this.el).css({visibility : 'visible'});
},
// show
- hide: function()
- {
+ hide: function(){
$(this.el).css({visibility : 'hidden'});
},
// add menu item
- add: function (options)
- {
+ add: function (options){
// menu option defaults
var menuOptions = {
title : 'Title',
@@ -333,8 +309,7 @@
menuOptions.content = galaxy_config.root + menuOptions.content;
// check if submenu element is available
- if (!this.$menu)
- {
+ if (!this.$menu){
// insert submenu element into root
$(this.el).find('.root').append(this._templateMenu());
@@ -353,8 +328,7 @@
// add events
var self = this;
- $item.on('click', function(e)
- {
+ $item.on('click', function(e){
// prevent default
e.preventDefault();
@@ -372,8 +346,7 @@
},
// show menu on header click
- _head: function(e)
- {
+ _head: function(e){
// prevent default
e.preventDefault();
@@ -387,12 +360,11 @@
}
},
- _attachPopover : function()
- {
+ _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.',
+ content: 'Please <a href="' + galaxy_config.root + '/user/login">log in</a> or <a href="' + galaxy_config.root + '/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() {
@@ -402,25 +374,21 @@
},
// fill template header
- _templateMenuItem: function (options)
- {
+ _templateMenuItem: function (options){
return '<li><a href="' + options.content + '" target="' + options.target + '">' + options.title + '</a></li>';
},
// fill template header
- _templateMenu: function ()
- {
+ _templateMenu: function (){
return '<ul class="popup dropdown-menu"></ul>';
},
- _templateDivider: function()
- {
+ _templateDivider: function(){
return '<li class="divider"></li>';
},
// fill template
- _template: function (options)
- {
+ _template: function (options){
// start template
var tmpl = '<ul id="' + options.id + '" class="nav navbar-nav" border="0" cellspacing="0">' +
'<li class="root dropdown" style="">' +
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/galaxy.menu.js
--- a/client/galaxy/scripts/galaxy.menu.js
+++ b/client/galaxy/scripts/galaxy.menu.js
@@ -1,13 +1,8 @@
-/*
- galaxy menu
-*/
-
// dependencies
define(["galaxy.masthead"], function(mod_masthead) {
-// frame manager
-var GalaxyMenu = Backbone.Model.extend(
-{
+/** GalaxyMenu uses the GalaxyMasthead class in order to add menu items and icons to the Masthead **/
+var GalaxyMenu = Backbone.Model.extend({
// options
options: null,
@@ -15,23 +10,21 @@
masthead: null,
// initialize
- initialize: function(options)
- {
+ initialize: function(options) {
this.options = options.config;
this.masthead = options.masthead;
this.create();
},
// default menu
- create: function()
- {
+ create: function(){
//
// Analyze data tab.
//
var tab_analysis = new mod_masthead.GalaxyMastheadTab({
id : "analysis",
title : "Analyze Data",
- content : "root/index",
+ content : "",
title_attribute : 'Analysis home view'
});
this.masthead.append(tab_analysis);
@@ -137,8 +130,7 @@
var tab_visualization = new mod_masthead.GalaxyMastheadTab(visualization_options);
- if (this.options.user.valid) //add submenu only when user is logged in
- {
+ if (this.options.user.valid){ //add submenu only when user is logged in
tab_visualization.add({
title : "New Track Browser",
content : "visualization/trackster",
@@ -155,8 +147,7 @@
//
// Cloud menu.
//
- if (this.options.enable_cloud_launch)
- {
+ if (this.options.enable_cloud_launch){
var tab_cloud = new mod_masthead.GalaxyMastheadTab({
id : "cloud",
title : "Cloud",
@@ -172,12 +163,11 @@
//
// Admin.
//
- if (this.options.is_admin_user)
- {
+ if (this.options.is_admin_user) {
var tab_admin = new mod_masthead.GalaxyMastheadTab({
id : "admin",
title : "Admin",
- content : "admin/index",
+ content : "admin",
extra_class : "admin-only",
title_attribute : 'Administer this Galaxy'
});
@@ -192,8 +182,7 @@
title : "Help",
title_attribute : 'Support, contact, and community hubs'
});
- if (this.options.biostar_url)
- {
+ if (this.options.biostar_url){
tab_help.add({
title : "Galaxy Biostar",
content : this.options.biostar_url_redirect,
@@ -235,8 +224,7 @@
content : this.options.citation_url,
target : "_blank"
});
- if (this.options.terms_url)
- {
+ if (this.options.terms_url){
tab_help.add({
title : "Terms and Conditions",
content : this.options.terms_url,
@@ -248,8 +236,7 @@
//
// User tab.
//
- if (!this.options.user.valid)
- {
+ if (!this.options.user.valid){
var tab_user = new mod_masthead.GalaxyMastheadTab({
id : "user",
title : "User",
@@ -265,8 +252,7 @@
});
// register
- if (this.options.allow_user_creation)
- {
+ if (this.options.allow_user_creation){
tab_user.add({
title : "Register",
content : "user/create",
@@ -331,8 +317,7 @@
target : "galaxy_main"
});
- if (this.options.use_remote_user)
- {
+ if (this.options.use_remote_user){
tab_user.add({
title : "Public Name",
content : "user/edit_username?cntrller=user",
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/base-mvc.js
--- a/client/galaxy/scripts/mvc/base-mvc.js
+++ b/client/galaxy/scripts/mvc/base-mvc.js
@@ -380,11 +380,6 @@
/** allow the view to be dragged, set up event handlers */
draggableOn : function(){
this.draggable = true;
- //TODO: I have no idea why this doesn't work with the events hash or jq.on()...
- //this.$el.find( '.title-bar' )
- // .attr( 'draggable', true )
- // .bind( 'dragstart', this.dragStartHandler, false )
- // .bind( 'dragend', this.dragEndHandler, false );
this.dragStartHandler = _.bind( this._dragStartHandler, this );
this.dragEndHandler = _.bind( this._dragEndHandler, this );
@@ -402,23 +397,22 @@
},
/** sets the dataTransfer data to the model's toJSON
- * @fires dragstart (bbone event) which is passed this view
+ * @fires draggable:dragstart (bbone event) which is passed the event and this view
*/
_dragStartHandler : function( event ){
- //this.debug( 'dragStartHandler:', this, event, arguments )
- this.trigger( 'dragstart', this );
event.dataTransfer.effectAllowed = 'move';
+ //ASSUMES: this.model
//TODO: all except IE: should be 'application/json', IE: must be 'text'
event.dataTransfer.setData( 'text', JSON.stringify( this.model.toJSON() ) );
+ this.trigger( 'draggable:dragstart', event, this );
return false;
},
/** handle the dragend
- * @fires dragend (bbone event) which is passed this view
+ * @fires draggable:dragend (bbone event) which is passed the event and this view
*/
_dragEndHandler : function( event ){
- this.trigger( 'dragend', this );
- //this.debug( 'dragEndHandler:', event )
+ this.trigger( 'draggable:dragend', event, this );
return false;
}
};
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/collection/collection-li.js
--- a/client/galaxy/scripts/mvc/collection/collection-li.js
+++ b/client/galaxy/scripts/mvc/collection/collection-li.js
@@ -100,8 +100,6 @@
/** add the DCE class to the list item */
className : ListItemView.prototype.className + " dataset-collection-element",
- /** jq fx speed for this view */
- fxSpeed : 'fast',
/** set up */
initialize : function( attributes ){
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/dataset/dataset-li-edit.js
--- a/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js
+++ b/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js
@@ -181,6 +181,8 @@
}
var $visualizations = $( this.templates.visualizations( visualizations, this ) );
+ //HACK: need to re-write those directed at galaxy_main with linkTarget
+ $visualizations.find( '[target="galaxy_main"]').attr( 'target', this.linkTarget );
// use addBack here to include the root $visualizations elem (for the case of 1 visualization)
this._addScratchBookFn( $visualizations.find( '.visualization-link' ).addBack( '.visualization-link' ) );
return $visualizations;
@@ -188,6 +190,7 @@
/** add scratchbook functionality to visualization links */
_addScratchBookFn : function( $links ){
+ var li = this;
$links.click( function( ev ){
if( Galaxy.frame && Galaxy.frame.active ){
Galaxy.frame.add({
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/dataset/dataset-li.js
--- a/client/galaxy/scripts/mvc/dataset/dataset-li.js
+++ b/client/galaxy/scripts/mvc/dataset/dataset-li.js
@@ -160,7 +160,7 @@
// add frame manager option onclick event
var self = this;
displayBtnData.onclick = function( ev ){
- if( Galaxy.frame && Galaxy.frame.active ){
+ if (Galaxy.frame && Galaxy.frame.active) {
// Add dataset to frames.
Galaxy.frame.add_dataset(self.model.get('id'));
ev.preventDefault();
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/dataset/dataset-model.js
--- a/client/galaxy/scripts/mvc/dataset/dataset-model.js
+++ b/client/galaxy/scripts/mvc/dataset/dataset-model.js
@@ -363,74 +363,11 @@
Backbone.Collection.prototype.set.call( this, models, options );
},
-// /** Convert this ad-hoc collection of hdas to a formal collection tracked
-// by the server.
-// **/
-// promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){
-////TODO: seems like this would be better in mvc/collections
-// options = options || {};
-// options.url = this.url();
-// options.type = "POST";
-// var full_collection_type = collection_type;
-// var element_identifiers = [],
-// name = null;
-//
-// // This mechanism is rough - no error handling, allows invalid selections, no way
-// // for user to pick/override element identifiers. This is only really meant
-// if( collection_type === "list" ) {
-// this.chain().each( function( hda ) {
-// // TODO: Handle duplicate names.
-// var name = hda.attributes.name;
-// var id = hda.get('id');
-// var content_type = hda.attributes.history_content_type;
-// if( content_type === "dataset" ) {
-// if( full_collection_type !== "list" ) {
-// this.log( "Invalid collection type" );
-// }
-// element_identifiers.push( { name: name, src: "hda", id: id } );
-// } else {
-// if( full_collection_type === "list" ) {
-// full_collection_type = "list:" + hda.attributes.collection_type;
-// } else {
-// if( full_collection_type !== "list:" + hda.attributes.collection_type ) {
-// this.log( "Invalid collection type" );
-// }
-// }
-// element_identifiers.push( { name: name, src: "hdca", id: id } );
-// }
-// });
-// name = "New Dataset List";
-// } else if( collection_type === "paired" ) {
-// var ids = this.ids();
-// if( ids.length !== 2 ){
-// // TODO: Do something...
-// }
-// element_identifiers.push( { name: "forward", src: "hda", id: ids[ 0 ] } );
-// element_identifiers.push( { name: "reverse", src: "hda", id: ids[ 1 ] } );
-// name = "New Dataset Pair";
-// }
-// options.data = {
-// type: "dataset_collection",
-// name: name,
-// collection_type: full_collection_type,
-// element_identifiers: JSON.stringify( element_identifiers )
-// };
-//
-// var xhr = jQuery.ajax( options );
-// xhr.done( function( message, status, responseObj ){
-// history.refresh( );
-// });
-// xhr.fail( function( xhr, status, message ){
-// if( xhr.responseJSON && xhr.responseJSON.error ){
-// error = xhr.responseJSON.error;
-// } else {
-// error = xhr.responseJSON;
-// }
-// xhr.responseText = error;
-// // Do something?
-// });
-// return xhr;
-// },
+ ///** Convert this ad-hoc collection of hdas to a formal collection tracked
+ // by the server.
+ //**/
+ //promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){
+ //},
/** String representation. */
toString : function(){
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/history/history-contents.js
--- a/client/galaxy/scripts/mvc/history/history-contents.js
+++ b/client/galaxy/scripts/mvc/history/history-contents.js
@@ -187,6 +187,7 @@
/** copy an existing, accessible hda into this collection */
copy : function( id ){
+//TODO: incorp collections
var collection = this,
xhr = jQuery.post( this.url(), {
source : 'hda',
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/history/history-model.js
--- a/client/galaxy/scripts/mvc/history/history-model.js
+++ b/client/galaxy/scripts/mvc/history/history-model.js
@@ -14,7 +14,7 @@
* @constructs
*/
var History = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
-/** @lends History.prototype */{
+ BASE_MVC.mixin( BASE_MVC.SearchableModelMixin, /** @lends History.prototype */{
/** logger used to record this.log messages, commonly set to console */
//logger : console,
@@ -117,7 +117,19 @@
return _.reduce( _.values( this.get( 'state_details' ) ), function( memo, num ){ return memo + num; }, 0 );
},
- // ........................................................................ ajax
+ // ........................................................................ search
+ /** What model fields to search with */
+ searchAttributes : [
+ 'name', 'annotation', 'tags'
+ ],
+
+ /** Adding title and singular tag */
+ searchAliases : {
+ title : 'name',
+ tag : 'tags'
+ },
+
+ // ........................................................................ updates
/** does the contents collection indicate they're still running and need to be updated later?
* delay + update if needed
* @param {Function} onReadyCallback function to run when all contents are in the ready state
@@ -187,6 +199,18 @@
return xhr;
},
+ // ........................................................................ ajax
+ /** save this history, _Mark_ing it as deleted (just a flag) */
+ _delete : function( options ){
+ if( this.get( 'deleted' ) ){ return jQuery.when(); }
+ return this.save( { deleted: true }, options );
+ },
+ /** save this history, _Mark_ing it as undeleted */
+ undelete : function( options ){
+ if( !this.get( 'deleted' ) ){ return jQuery.when(); }
+ return this.save( { deleted: false }, options );
+ },
+
/** Make a copy of this history on the server
* @param {Boolean} current if true, set the copy as the new current history (default: true)
* @param {String} name name of new history (default: none - server sets to: Copy of <current name>)
@@ -210,9 +234,28 @@
//TODO:?? all datasets?
var history = this,
- xhr = jQuery.post( this.urlRoot, postData );
- xhr.done( function( newData ){
- history.trigger( 'copied', history, newData );
+ copy = jQuery.post( this.urlRoot, postData );
+ // if current - queue to setAsCurrent before firing 'copied'
+ if( current ){
+ return copy.then( function( response ){
+ var newHistory = new History( response );
+ return newHistory.setAsCurrent()
+ .done( function(){
+ history.trigger( 'copied', history, response );
+ });
+ });
+ }
+ return copy.done( function( response ){
+ history.trigger( 'copied', history, response );
+ });
+ },
+
+ setAsCurrent : function(){
+ var history = this,
+ xhr = jQuery.getJSON( '/history/set_as_current?id=' + this.id );
+
+ xhr.done( function(){
+ history.trigger( 'set-as-current', history );
});
return xhr;
},
@@ -221,7 +264,7 @@
toString : function(){
return 'History(' + this.get( 'id' ) + ',' + this.get( 'name' ) + ')';
}
-});
+}));
//------------------------------------------------------------------------------ CLASS VARS
/** When the history has running hdas,
@@ -351,12 +394,15 @@
create : function create( data, hdas, historyOptions, xhrOptions ){
var collection = this,
- history = new History( data || {}, hdas || [], historyOptions || {} );
- return history.save( xhrOptions ).done( function( newData ){
+ xhr = jQuery.getJSON( galaxy_config.root + 'history/create_new_current' );
+ return xhr.done( function( newData ){
+ var history = new History( newData, [], historyOptions || {} );
// new histories go in the front
//TODO: (implicit ordering by update time...)
collection.unshift( history );
+ collection.trigger( 'new-current' );
});
+//TODO: move back to using history.save (via Deferred.then w/ set_as_current)
},
toString: function toString(){
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/history/history-panel-edit-current.js
--- a/client/galaxy/scripts/mvc/history/history-panel-edit-current.js
+++ b/client/galaxy/scripts/mvc/history/history-panel-edit-current.js
@@ -164,12 +164,13 @@
_setUpCollectionListeners : function(){
_super.prototype._setUpCollectionListeners.call( this );
+ //TODO:?? may not be needed? see history-panel-edit, 369
// if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,
// then: remove it from the collection if the panel is set to NOT show hidden datasets
this.collection.on( 'state:ready', function( model, newState, oldState ){
if( ( !model.get( 'visible' ) )
&& ( !this.storage.get( 'show_hidden' ) ) ){
- this.removeItemView( this.viewFromModel( model ) );
+ this.removeItemView( model );
}
}, this );
},
@@ -226,7 +227,7 @@
'</a>'
].join('') );
$emptyMsg.find( '.uploader-link' ).click( function( ev ){
- Galaxy.upload._eventShow( ev );
+ Galaxy.upload.show( ev );
});
$emptyMsg.find( '.get-data-link' ).click( function( ev ){
$toolMenu.parent().scrollTop( 0 );
@@ -288,51 +289,23 @@
},
// ------------------------------------------------------------------------ sub-views
- // reverse HID order
- /** Override to reverse order of views - newest contents on top
- * and add the current-content highlight class to currentContentId's view
- */
+ /** Override to add the current-content highlight class to currentContentId's view */
_attachItems : function( $whereTo ){
- var panel = this;
- this.$list( $whereTo ).append( this.views.reverse().map( function( view ){
- // add current content
- if( panel.currentContentId && view.model.id === panel.currentContentId ){
- panel.setCurrentContent( view );
- }
- return view.$el;
- }));
+ _super.prototype._attachItems.call( this, $whereTo );
+ var panel = this,
+ currentContentView;
+ if( panel.currentContentId
+ && ( currentContentView = panel.viewFromModelId( panel.currentContentId ) ) ){
+ panel.setCurrentContent( currentContentView );
+ }
return this;
},
- /** Override to add datasets at the top */
+ /** Override to remove any drill down panels */
addItemView : function( model, collection, options ){
- this.log( this + '.addItemView:', model );
- var panel = this;
- if( !panel._filterItem( model ) ){ return undefined; }
-//TODO: alternately, call collapse drilldown
- // if this panel is currently hidden, return undefined
- if( panel.panelStack.length ){ return this._collapseDrilldownPanel(); }
-
- var view = panel._createItemView( model );
- // use unshift and prepend to preserve reversed order
- panel.views.unshift( view );
-
- panel.scrollToTop();
- $({}).queue([
- function fadeOutEmptyMsg( next ){
- var $emptyMsg = panel.$emptyMessage();
- if( $emptyMsg.is( ':visible' ) ){
- $emptyMsg.fadeOut( panel.fxSpeed, next );
- } else {
- next();
- }
- },
- function createAndPrepend( next ){
- // render as hidden then slide down
- panel.$list().prepend( view.render( 0 ).$el.hide() );
- view.$el.slideDown( panel.fxSpeed );
- }
- ]);
+ var view = _super.prototype.addItemView.call( this, model, collection, options );
+ if( !view ){ return view; }
+ if( this.panelStack.length ){ return this._collapseDrilldownPanel(); }
return view;
},
@@ -423,22 +396,6 @@
if( !msg.is( ':hidden' ) ){ msg.slideUp( this.fxSpeed ); }
},
-//TODO: move show_deleted/hidden into panel from opt menu and remove this
- /** add listeners to an external options menu (templates/webapps/galaxy/root/index.mako) */
- connectToOptionsMenu : function( optionsMenu ){
- if( !optionsMenu ){
- return this;
- }
- // set a visible indication in the popupmenu for show_hidden/deleted based on the currHistoryPanel's settings
- this.on( 'new-storage', function( storage, panel ){
- if( optionsMenu && storage ){
- optionsMenu.findItemByHtml( _l( 'Include Deleted Datasets' ) ).checked = storage.get( 'show_deleted' );
- optionsMenu.findItemByHtml( _l( 'Include Hidden Datasets' ) ).checked = storage.get( 'show_hidden' );
- }
- });
- return this;
- },
-
/** Return a string rep of the history
*/
toString : function(){
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/history/history-panel-edit.js
--- a/client/galaxy/scripts/mvc/history/history-panel-edit.js
+++ b/client/galaxy/scripts/mvc/history/history-panel-edit.js
@@ -69,7 +69,18 @@
this.multiselectActions = attributes.multiselectActions || this._getActions();
},
- // ------------------------------------------------------------------------ panel rendering
+ /** Override to handle history as drag-drop target */
+ _setUpListeners : function(){
+ _super.prototype._setUpListeners.call( this );
+
+ this.on( 'drop', function( ev, data ){
+ this.dataDropped( data );
+ // remove the drop target
+ this.dropTargetOff();
+ });
+ },
+
+ // ------------------------------------------------------------------------ listeners
/** listening for collection events */
_setUpCollectionListeners : function(){
_super.prototype._setUpCollectionListeners.call( this );
@@ -104,6 +115,42 @@
return $newRender;
},
+ /** override to render counts when the items are rendered */
+ renderItems : function( $whereTo ){
+ var views = _super.prototype.renderItems.call( this, $whereTo );
+ this._renderCounts( $whereTo );
+ return views;
+ },
+
+ /** override to show counts, what's deleted/hidden, and links to toggle those */
+ _renderCounts : function( $whereTo ){
+//TODO: too complicated
+ function toggleLink( _class, text ){
+ return [ '<a class="', _class, '" href="javascript:void(0);">', text, '</a>' ].join( '' );
+ }
+ $whereTo = $whereTo || this.$el;
+ var deleted = this.collection.where({ deleted: true }),
+ hidden = this.collection.where({ visible: false }),
+ msgs = [];
+
+ if( this.views.length ){
+ msgs.push( [ this.views.length, _l( 'shown' ) ].join( ' ' ) );
+ }
+ if( deleted.length ){
+ msgs.push( ( !this.showDeleted )?
+ ([ deleted.length, toggleLink( 'toggle-deleted-link', _l( 'deleted' ) ) ].join( ' ' ))
+ :( toggleLink( 'toggle-deleted-link', _l( 'hide deleted' ) ) )
+ );
+ }
+ if( hidden.length ){
+ msgs.push( ( !this.showHidden )?
+ ([ hidden.length, toggleLink( 'toggle-hidden-link', _l( 'hidden' ) ) ].join( ' ' ))
+ :( toggleLink( 'toggle-hidden-link', _l( 'hide hidden' ) ) )
+ );
+ }
+ return $whereTo.find( '> .controls .subtitle' ).html( msgs.join( ', ' ) );
+ },
+
/** render the tags sub-view controller */
_renderTags : function( $where ){
var panel = this;
@@ -266,6 +313,24 @@
},
// ------------------------------------------------------------------------ sub-views
+ // reverse HID order
+ /** Override to reverse order of views - newest contents on top */
+ _attachItems : function( $whereTo ){
+ this.$list( $whereTo ).append( this.views.reverse().map( function( view ){
+ return view.$el;
+ }));
+ return this;
+ },
+
+ /** Override to add new contents at the top */
+ _attachView : function( view ){
+ var panel = this;
+ // override to control where the view is added, how/whether it's rendered
+ panel.views.unshift( view );
+ panel.$list().prepend( view.render( 0 ).$el.hide() );
+ view.$el.slideDown( panel.fxSpeed );
+ },
+
/** In this override, add purgeAllowed and whether tags/annotation editors should be shown */
_getItemViewOptions : function( model ){
var options = _super.prototype._getItemViewOptions.call( this, model );
@@ -278,22 +343,31 @@
return options;
},
+ ///** Override to alter data in drag based on multiselection */
+ //_setUpItemViewListeners : function( view ){
+ // var panel = this;
+ // _super.prototype._setUpItemViewListeners.call( panel, view );
+ //
+ //},
+
/** If this item is deleted and we're not showing deleted items, remove the view
* @param {Model} the item model to check
*/
_handleHdaDeletionChange : function( itemModel ){
- if( itemModel.get( 'deleted' ) && !this.storage.get( 'show_deleted' ) ){
+ if( itemModel.get( 'deleted' ) && !this.showDeleted ){
this.removeItemView( itemModel );
}
+ this._renderCounts();
},
/** If this item is hidden and we're not showing hidden items, remove the view
* @param {Model} the item model to check
*/
_handleHdaVisibleChange : function( itemModel ){
- if( itemModel.hidden() && !this.storage.get( 'show_hidden' ) ){
+ if( itemModel.hidden() && !this.storage.showHidden ){
this.removeItemView( itemModel );
}
+ this._renderCounts();
},
/** toggle the visibility of each content's tagsEditor applying all the args sent to this function */
@@ -319,7 +393,9 @@
// ------------------------------------------------------------------------ panel events
/** event map */
events : _.extend( _.clone( _super.prototype.events ), {
- 'click .show-selectors-btn' : 'toggleSelectors'
+ 'click .show-selectors-btn' : 'toggleSelectors',
+ 'click .toggle-deleted-link' : function( ev ){ this.toggleShowDeleted(); },
+ 'click .toggle-hidden-link' : function( ev ){ this.toggleShowHidden(); }
}),
/** Update the history size display (curr. upper right of panel).
@@ -328,6 +404,132 @@
this.$el.find( '.history-size' ).text( this.model.get( 'nice_size' ) );
},
+ // ------------------------------------------------------------------------ as drop target
+ /** */
+ dropTargetOn : function(){
+ if( this.dropTarget ){ return this; }
+ this.dropTarget = true;
+
+ //TODO: to init
+ var dropHandlers = {
+ 'dragenter' : _.bind( this.dragenter, this ),
+ 'dragover' : _.bind( this.dragover, this ),
+ 'dragleave' : _.bind( this.dragleave, this ),
+ 'drop' : _.bind( this.drop, this )
+ };
+//TODO: scroll to top
+ var $dropTarget = this._renderDropTarget();
+ this.$list().before([ this._renderDropTargetHelp(), $dropTarget ]);
+ for( var evName in dropHandlers ){
+ if( dropHandlers.hasOwnProperty( evName ) ){
+ //console.debug( evName, dropHandlers[ evName ] );
+ $dropTarget.on( evName, dropHandlers[ evName ] );
+ }
+ }
+ return this;
+ },
+
+ /** */
+ _renderDropTarget : function(){
+ return $( '<div/>' ).addClass( 'history-drop-target' )
+ .css({
+ 'height': '64px',
+ 'margin': '0px 10px 10px 10px',
+ 'border': '1px dashed black',
+ 'border-radius' : '3px'
+ });
+ },
+
+ /** */
+ _renderDropTargetHelp : function(){
+ return $( '<div/>' ).addClass( 'history-drop-target-help' )
+ .css({
+ 'margin' : '10px 10px 4px 10px',
+ 'color' : 'grey',
+ 'font-size' : '80%',
+ 'font-style' : 'italic'
+ })
+ .text( _l( 'Drag datasets here to copy them to the current history' ) );
+ },
+
+ /** */
+ dropTargetOff : function(){
+ if( !this.dropTarget ){ return this; }
+ //this.log( 'dropTargetOff' );
+ this.dropTarget = false;
+ //
+ //var dropTarget = this.$( '.history-drop-target' ).get(0);
+ //for( var evName in this._dropHandlers ){
+ // if( this._dropHandlers.hasOwnProperty( evName ) ){
+ // console.debug( evName, this._dropHandlers[ evName ] );
+ // dropTarget.off( evName, this._dropHandlers[ evName ] );
+ // }
+ //}
+ this.$( '.history-drop-target' ).remove();
+ this.$( '.history-drop-target-help' ).remove();
+ return this;
+ },
+ /** */
+ dropTargetToggle : function(){
+ if( this.dropTarget ){
+ this.dropTargetOff();
+ } else {
+ this.dropTargetOn();
+ }
+ return this;
+ },
+
+ /** */
+ dragenter : function( ev ){
+ //console.debug( 'dragenter:', this, ev );
+ ev.preventDefault();
+ ev.stopPropagation();
+ this.$( '.history-drop-target' ).css( 'border', '2px solid black' );
+ },
+ /** */
+ dragover : function( ev ){
+ ev.preventDefault();
+ ev.stopPropagation();
+ },
+ /** */
+ dragleave : function( ev ){
+ //console.debug( 'dragleave:', this, ev );
+ ev.preventDefault();
+ ev.stopPropagation();
+ this.$( '.history-drop-target' ).css( 'border', '1px dashed black' );
+ },
+ /** */
+ drop : function( ev ){
+ //console.warn( 'dataTransfer:', ev.dataTransfer.getData( 'text' ) );
+ //console.warn( 'dataTransfer:', ev.originalEvent.dataTransfer.getData( 'text' ) );
+ ev.preventDefault();
+ //ev.stopPropagation();
+ ev.dataTransfer.dropEffect = 'move';
+
+ //console.debug( 'ev.dataTransfer:', ev.dataTransfer );
+
+ var panel = this,
+ data = ev.dataTransfer.getData( "text" );
+ try {
+ data = JSON.parse( data );
+
+ } catch( err ){
+ this.warn( 'error parsing JSON from drop:', data );
+ }
+ this.trigger( 'droptarget:drop', ev, data, panel );
+ return false;
+ },
+
+ /** */
+ dataDropped : function( data ){
+ var panel = this;
+ // HDA: dropping will copy it to the history
+ if( _.isObject( data ) && data.model_class === 'HistoryDatasetAssociation' && data.id ){
+ return panel.model.contents.copy( data.id );
+ }
+ return jQuery.when();
+ },
+
// ........................................................................ misc
/** Return a string rep of the history */
toString : function(){
diff -r 605de23ca239879a34426885feddd2d3a459ca26 -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee client/galaxy/scripts/mvc/history/history-panel.js
--- a/client/galaxy/scripts/mvc/history/history-panel.js
+++ b/client/galaxy/scripts/mvc/history/history-panel.js
@@ -254,6 +254,10 @@
_setUpWebStorage : function( initiallyExpanded, show_deleted, show_hidden ){
//if( !this.model ){ return this; }
//this.log( '_setUpWebStorage', initiallyExpanded, show_deleted, show_hidden );
+ if( this.storage ){
+ this.stopListening( this.storage );
+ }
+
this.storage = new HistoryPrefs({
id: HistoryPrefs.historyStorageKey( this.model.get( 'id' ) )
});
@@ -276,6 +280,18 @@
this.trigger( 'new-storage', this.storage, this );
this.log( this + ' (init\'d) storage:', this.storage.get() );
+
+ this.listenTo( this.storage, {
+ 'change:show_deleted' : function( view, newVal ){
+ this.showDeleted = newVal;
+ },
+ 'change:show_hidden' : function( view, newVal ){
+ this.showHidden = newVal;
+ }
+ }, this );
+ this.showDeleted = ( show_deleted !== undefined )? show_deleted : this.storage.get( 'show_deleted' );
+ this.showHidden = ( show_hidden !== undefined )? show_hidden : this.storage.get( 'show_hidden' );
+
return this;
},
@@ -317,8 +333,8 @@
_filterItem : function( model ){
var panel = this;
return ( _super.prototype._filterItem.call( panel, model )
- && ( !model.hidden() || panel.storage.get( 'show_hidden' ) )
- && ( !model.isDeletedOrPurged() || panel.storage.get( 'show_deleted' ) ) );
+ && ( !model.hidden() || panel.showHidden )
+ && ( !model.isDeletedOrPurged() || panel.showDeleted ) );
},
/** in this override, add a linktarget, and expand if id is in web storage */
@@ -372,12 +388,17 @@
* (2) re-rendering the history
* @returns {Boolean} new show_deleted setting
*/
- toggleShowDeleted : function( show ){
- show = ( show !== undefined )?( show ):( !this.storage.get( 'show_deleted' ) );
- this.storage.set( 'show_deleted', show );
+ toggleShowDeleted : function( show, store ){
+ show = ( show !== undefined )?( show ):( !this.showDeleted );
+ store = ( store !== undefined )?( store ):( true );
+ this.showDeleted = show;
+ if( store ){
+ this.storage.set( 'show_deleted', show );
+ }
+ this.trigger( 'show-hidden', show );
//TODO:?? to events on storage('change:show_deleted')
this.renderItems();
- return this.storage.get( 'show_deleted' );
+ return this.showDeleted;
},
/** Handle the user toggling the deleted visibility by:
@@ -385,12 +406,17 @@
* (2) re-rendering the history
* @returns {Boolean} new show_hidden setting
*/
- toggleShowHidden : function( show ){
- show = ( show !== undefined )?( show ):( !this.storage.get( 'show_hidden' ) );
- this.storage.set( 'show_hidden', show );
- //TODO:?? to events on storage('change:show_hidden')
+ toggleShowHidden : function( show, store ){
+ show = ( show !== undefined )?( show ):( !this.showHidden );
+ store = ( store !== undefined )?( store ):( true );
+ this.showHidden = show;
+ if( store ){
+ this.storage.set( 'show_hidden', show );
+ }
+ this.trigger( 'show-hidden', show );
+ //TODO:?? to events on storage('change:show_deleted')
this.renderItems();
- return this.storage.get( 'show_hidden' );
+ return this.showHidden;
},
/** On the first search, if there are no details - load them, then search */
@@ -582,9 +608,7 @@
'<div class="title">',
'<div class="name"><%= history.name %></div>',
'</div>',
- '<div class="subtitle">',
- //'<%= view.collection.length %>', _l( ' items' ),
- '</div>',
+ '<div class="subtitle"></div>',
'<div class="history-size"><%= history.nice_size %></div>',
'<div class="actions"></div>',
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/055016b332aa/
Changeset: 055016b332aa
Branch: stable
User: natefoo
Date: 2015-01-13 15:36:58+00:00
Summary: Added tag release_2015.01.13 for changeset 2e8dd2949dd3
Affected #: 1 file
diff -r 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee -r 055016b332aa41d559f9ec12c638734824292b54 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -21,3 +21,4 @@
8150024c0e6fc5aef3033cf8aaa574896f6b5d0d latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
c437b28348a9345db8433e5b4f0e05ec8fb6c38a latest_2014.10.06
+2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee release_2015.01.13
https://bitbucket.org/galaxy/galaxy-central/commits/fd1946912be3/
Changeset: fd1946912be3
Branch: stable
User: natefoo
Date: 2015-01-13 15:37:28+00:00
Summary: Added tag latest_2015.01.13 for changeset 2e8dd2949dd3
Affected #: 1 file
diff -r 055016b332aa41d559f9ec12c638734824292b54 -r fd1946912be3f0454e155effc10e5a2127388559 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -22,3 +22,4 @@
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
c437b28348a9345db8433e5b4f0e05ec8fb6c38a latest_2014.10.06
2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee release_2015.01.13
+2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee latest_2015.01.13
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: dannon: Remove pointless user check preventing userA from requesting reset for userB. userA could just log out and then request a password reset for userB.
by commits-noreply@bitbucket.org 13 Jan '15
by commits-noreply@bitbucket.org 13 Jan '15
13 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a74b0112995c/
Changeset: a74b0112995c
User: dannon
Date: 2015-01-13 21:36:10+00:00
Summary: Remove pointless user check preventing userA from requesting reset for userB. userA could just log out and then request a password reset for userB.
Affected #: 1 file
diff -r 5e6da19ffd907f39afd795e5d43b306071556bad -r a74b0112995cd2ae396d0916a6e845b7709f9002 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1149,33 +1149,27 @@
reset_user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first()
user = trans.get_user()
if reset_user:
- if user and user.id != reset_user.id:
- # This doesn't make any sense because all they have to do is log
- # out and then try it again #TODO revisit why this exists.
- message = "You may only reset your own password."
+ prt = trans.app.model.PasswordResetToken( reset_user )
+ trans.sa_session.add( prt )
+ trans.sa_session.flush()
+ host = trans.request.host.split( ':' )[ 0 ]
+ if host == 'localhost':
+ host = socket.getfqdn()
+ reset_url = url_for( controller='user',
+ action="change_password",
+ token=prt.token, qualified=True)
+ body = PASSWORD_RESET_TEMPLATE % ( host, reset_url, reset_url )
+ frm = 'galaxy-no-reply@' + host
+ subject = 'Galaxy Password Reset'
+ try:
+ util.send_mail( frm, email, subject, body, trans.app.config )
+ trans.sa_session.add( reset_user )
+ trans.sa_session.flush()
+ trans.log_event( "User reset password: %s" % email )
+ except Exception, e:
status = 'error'
- else:
- prt = trans.app.model.PasswordResetToken( reset_user )
- trans.sa_session.add( prt )
- trans.sa_session.flush()
- host = trans.request.host.split( ':' )[ 0 ]
- if host == 'localhost':
- host = socket.getfqdn()
- reset_url = url_for( controller='user',
- action="change_password",
- token=prt.token, qualified=True)
- body = PASSWORD_RESET_TEMPLATE % ( host, reset_url, reset_url )
- frm = 'galaxy-no-reply@' + host
- subject = 'Galaxy Password Reset'
- try:
- util.send_mail( frm, email, subject, body, trans.app.config )
- trans.sa_session.add( reset_user )
- trans.sa_session.flush()
- trans.log_event( "User reset password: %s" % email )
- except Exception, e:
- status = 'error'
- message = 'Failed to reset password: %s' % str( e )
- log.exception( 'Unable to reset password.' )
+ message = 'Failed to reset password: %s' % str( e )
+ log.exception( 'Unable to reset password.' )
return trans.fill_template( '/user/reset_password.mako',
message=message,
status=status )
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: dannon: Make password reset via link feature work for the toolshed too.
by commits-noreply@bitbucket.org 13 Jan '15
by commits-noreply@bitbucket.org 13 Jan '15
13 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5e6da19ffd90/
Changeset: 5e6da19ffd90
User: dannon
Date: 2015-01-13 21:27:35+00:00
Summary: Make password reset via link feature work for the toolshed too.
Affected #: 5 files
diff -r d2cafc77eee48d07b1958e395f6a8cf58770cf94 -r 5e6da19ffd907f39afd795e5d43b306071556bad lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1155,7 +1155,7 @@
message = "You may only reset your own password."
status = 'error'
else:
- prt = model.PasswordResetToken( reset_user )
+ prt = trans.app.model.PasswordResetToken( reset_user )
trans.sa_session.add( prt )
trans.sa_session.flush()
host = trans.request.host.split( ':' )[ 0 ]
diff -r d2cafc77eee48d07b1958e395f6a8cf58770cf94 -r 5e6da19ffd907f39afd795e5d43b306071556bad lib/galaxy/webapps/tool_shed/model/__init__.py
--- a/lib/galaxy/webapps/tool_shed/model/__init__.py
+++ b/lib/galaxy/webapps/tool_shed/model/__init__.py
@@ -1,7 +1,9 @@
import logging
import operator
import os
+from datetime import datetime, timedelta
from galaxy import util
+from galaxy.util import unique_id
from galaxy.util.bunch import Bunch
from galaxy.util.hash_util import new_secure_hash
from galaxy.model.item_attrs import Dictifiable
@@ -61,6 +63,16 @@
self.password = new_secure_hash( text_type=cleartext )
+class PasswordResetToken( object ):
+ def __init__( self, user, token=None):
+ if token:
+ self.token = token
+ else:
+ self.token = unique_id()
+ self.user = user
+ self.expiration_time = datetime.now() + timedelta(hours=24)
+
+
class Group( object, Dictifiable ):
dict_collection_visible_keys = ( 'id', 'name' )
dict_element_visible_keys = ( 'id', 'name' )
@@ -85,7 +97,7 @@
self.description = description
self.type = type
self.deleted = deleted
-
+
@property
def is_repository_admin_role( self ):
# A repository admin role must always be associated with a repository. The mapper returns an
diff -r d2cafc77eee48d07b1958e395f6a8cf58770cf94 -r 5e6da19ffd907f39afd795e5d43b306071556bad lib/galaxy/webapps/tool_shed/model/mapping.py
--- a/lib/galaxy/webapps/tool_shed/model/mapping.py
+++ b/lib/galaxy/webapps/tool_shed/model/mapping.py
@@ -37,6 +37,11 @@
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ) )
+PasswordResetToken.table = Table("password_reset_token", metadata,
+ Column( "token", String( 32 ), primary_key=True, unique=True, index=True ),
+ Column( "expiration_time", DateTime ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ) )
+
Group.table = Table( "galaxy_group", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
@@ -204,6 +209,9 @@
galaxy_sessions=relation( GalaxySession, order_by=desc( GalaxySession.table.c.update_time ) ),
api_keys=relation( APIKeys, backref="user", order_by=desc( APIKeys.table.c.create_time ) ) ) )
+mapper( PasswordResetToken, PasswordResetToken.table,
+ properties=dict( user=relation( User, backref="reset_tokens") ) )
+
mapper( APIKeys, APIKeys.table,
properties = {} )
diff -r d2cafc77eee48d07b1958e395f6a8cf58770cf94 -r 5e6da19ffd907f39afd795e5d43b306071556bad lib/galaxy/webapps/tool_shed/model/migrate/versions/0024_password_reset.py
--- /dev/null
+++ b/lib/galaxy/webapps/tool_shed/model/migrate/versions/0024_password_reset.py
@@ -0,0 +1,43 @@
+"""
+Migration script for the password reset table
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+from galaxy.model.custom_types import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData()
+
+PasswordResetToken_table = Table("password_reset_token", metadata,
+ Column( "token", String( 32 ), primary_key=True, unique=True, index=True ),
+ Column( "expiration_time", DateTime ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ))
+
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ try:
+ PasswordResetToken_table.create()
+ except Exception as e:
+ print str(e)
+ log.exception("Creating %s table failed: %s" % (PasswordResetToken_table.name, str( e ) ) )
+
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ PasswordResetToken_table.drop()
+ except Exception as e:
+ print str(e)
+ log.exception("Dropping %s table failed: %s" % (PasswordResetToken_table.name, str( e ) ) )
diff -r d2cafc77eee48d07b1958e395f6a8cf58770cf94 -r 5e6da19ffd907f39afd795e5d43b306071556bad templates/user/index.mako
--- a/templates/user/index.mako
+++ b/templates/user/index.mako
@@ -18,6 +18,7 @@
<li><a href="${h.url_for( controller='user', action='logout', logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li>
%else:
<li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a></li>
+ <li><a href="${h.url_for( controller='user', action='change_password' )}">${_('Change your password')}</a></li><li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li><li><a href="${h.url_for( controller='repository', action='manage_email_alerts', cntrller=cntrller )}">${_('Manage your email alerts')}</a></li><li><a href="${h.url_for( controller='user', action='logout', logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li>
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
8 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/109372878f62/
Changeset: 109372878f62
User: dannon
Date: 2015-01-13 19:17:33+00:00
Summary: Initial password reset token feature.
Affected #: 9 files
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c config/galaxy.ini.sample
--- a/config/galaxy.ini.sample
+++ b/config/galaxy.ini.sample
@@ -354,10 +354,6 @@
# If no message specified the warning box will not be shown.
#registration_warning_message = Please register only one account - we provide this service free of charge and have limited computational resources. Multi-accounts are tracked and will be subjected to account termination and data deletion.
-# When users opt to reset passwords, new ones are created, this option
-# specifies the length of these passwords.
-#reset_password_length = 15
-
# -- Account activation
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -161,7 +161,6 @@
self.job_walltime_delta = timedelta( 0, s, 0, 0, m, h )
self.admin_users = kwargs.get( "admin_users", "" )
self.admin_users_list = [u.strip() for u in self.admin_users.split(',') if u]
- self.reset_password_length = int( kwargs.get('reset_password_length', '15') )
self.mailing_join_addr = kwargs.get('mailing_join_addr', 'galaxy-announce-join(a)bx.psu.edu')
self.error_email_to = kwargs.get( 'error_email_to', None )
self.activation_email = kwargs.get( 'activation_email', None )
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -18,6 +18,7 @@
import socket
import time
import numbers
+from datetime import datetime, timedelta
from uuid import UUID, uuid4
from string import Template
from itertools import ifilter
@@ -31,7 +32,7 @@
import galaxy.model.orm.now
from galaxy.security import get_permitted_actions
from galaxy.util import is_multi_byte, nice_size, Params, restore_text, send_mail
-from galaxy.util import ready_name_for_url
+from galaxy.util import ready_name_for_url, unique_id
from galaxy.util.bunch import Bunch
from galaxy.util.hash_util import new_secure_hash
from galaxy.util.directory_hash import directory_hash_id
@@ -261,6 +262,14 @@
environment = User.user_template_environment( user )
return Template( in_string ).safe_substitute( environment )
+class PasswordResetToken( object ):
+ def __init__( self, user, token=None):
+ if token:
+ self.token = token
+ else:
+ self.token = unique_id()
+ self.user = user
+ self.expiration_time = datetime.now() + timedelta(hours=24)
class BaseJobMetric( object ):
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -68,6 +68,11 @@
Column( "provider", TrimmedString( 255 ) ),
)
+model.PasswordResetToken.table = Table("password_reset_token", metadata,
+ Column( "token", String( 32 ), primary_key=True, unique=True, index=True ),
+ Column( "expiration_time", DateTime ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ) )
+
model.History.table = Table( "history", metadata,
Column( "id", Integer, primary_key=True),
Column( "create_time", DateTime, default=now ),
@@ -1564,6 +1569,10 @@
api_keys=relation( model.APIKeys, backref="user", order_by=desc( model.APIKeys.table.c.create_time ) ),
) )
+mapper( model.PasswordResetToken, model.PasswordResetToken.table,
+ properties=dict( user=relation( model.User, backref="reset_tokens") ) )
+
+
# Set up proxy so that this syntax is possible:
# <user_obj>.preferences[pref_name] = pref_value
model.User.preferences = association_proxy('_preferences', 'value', creator=model.UserPreference)
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c lib/galaxy/model/migrate/versions/0126_password_reset.py
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0126_password_reset.py
@@ -0,0 +1,43 @@
+"""
+Migration script for the password reset table
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+from galaxy.model.custom_types import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData()
+
+PasswordResetToken_table = Table("password_reset_token", metadata,
+ Column( "token", String( 32 ), primary_key=True, unique=True, index=True ),
+ Column( "expiration_time", DateTime ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ))
+
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ try:
+ PasswordResetToken_table.create()
+ except Exception as e:
+ print str(e)
+ log.exception("Creating %s table failed: %s" % (PasswordResetToken_table.name, str( e ) ) )
+
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ PasswordResetToken_table.drop()
+ except Exception as e:
+ print str(e)
+ log.exception("Dropping %s table failed: %s" % (PasswordResetToken_table.name, str( e ) ) )
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -7,7 +7,6 @@
import os
import random
import socket
-import string
import urllib
from datetime import datetime, timedelta
@@ -41,6 +40,13 @@
<p/>
"""
+PASSWORD_RESET_TEMPLATE = """
+To reset your Galaxy password for the instance at %s, use the following link:
+
+ <a href="%s">%s</a>
+
+If you did not make this request, no action is necessary on your part, though
+you may want to notify an administrator."""
class UserOpenIDGrid( grids.Grid ):
use_panels = False
@@ -1031,38 +1037,6 @@
trans.sa_session.add( user )
trans.sa_session.flush()
message = 'The login information has been updated with the changes.'
- elif user and params.get( 'change_password_button', False ):
- # Editing password. Do not sanitize passwords, so get from kwd
- # and not params (which were sanitized).
- password = kwd.get( 'password', '' )
- confirm = kwd.get( 'confirm', '' )
- ok = True
- if not is_admin:
- # If the current user is changing their own password, validate their current password
- current = kwd.get( 'current', '' )
- if not trans.user.check_password( current ):
- message = 'Invalid current password'
- status = 'error'
- ok = False
- if ok:
- # Validate the new password
- message = validate_password( trans, password, confirm )
- if message:
- status = 'error'
- else:
- # Save new password
- user.set_password_cleartext( password )
- # Invalidate all other sessions
- for other_galaxy_session in trans.sa_session.query( trans.app.model.GalaxySession ) \
- .filter( and_( trans.app.model.GalaxySession.table.c.user_id == trans.user.id,
- trans.app.model.GalaxySession.table.c.is_valid is True,
- trans.app.model.GalaxySession.table.c.id != trans.galaxy_session.id ) ):
- other_galaxy_session.is_valid = False
- trans.sa_session.add( other_galaxy_session )
- trans.sa_session.add( user )
- trans.sa_session.flush()
- trans.log_event( "User change password" )
- message = 'The password has been changed and any other existing Galaxy sessions have been logged out (but jobs in histories in those sessions will not be interrupted).'
elif user and params.get( 'edit_user_info_button', False ):
# Edit user information - webapp MUST BE 'galaxy'
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
@@ -1105,38 +1079,99 @@
**kwd ) )
@web.expose
- def reset_password( self, trans, email=None, **kwd ):
+ def change_password( self, trans, token=None, **kwd):
+ """
+ Provides a form with which one can change their password. If token is
+ provided, don't require current password.
+ """
+ status = None
+ message = None
+ user = None
+ if kwd.get( 'change_password_button', False ):
+ password = kwd.get( 'password', '' )
+ confirm = kwd.get( 'confirm', '' )
+ current = kwd.get( 'current', '' )
+ token_result = None
+ if token:
+ # If a token was supplied, validate and set user
+ token_result = trans.sa_session.query( trans.app.model.PasswordResetToken ).get(token)
+ if token_result and token_result.expiration_time > datetime.now():
+ user = token_result.user
+ else:
+ return trans.show_error_message("Invalid or expired password reset token, please request a new one.")
+ else:
+ # The user is changing their own password, validate their current password
+ if trans.user.check_password( current ):
+ user = trans.user
+ else:
+ message = 'Invalid current password'
+ status = 'error'
+ if user:
+ # Validate the new password
+ message = validate_password( trans, password, confirm )
+ if message:
+ status = 'error'
+ else:
+ # Save new password
+ user.set_password_cleartext( password )
+ # if we used a token, invalidate it and log the user in.
+ if token_result:
+ trans.handle_user_login(token_result.user)
+ token_result.expiration_time = datetime.now()
+ trans.sa_session.add(token_result)
+ # Invalidate all other sessions
+ for other_galaxy_session in trans.sa_session.query( trans.app.model.GalaxySession ) \
+ .filter( and_( trans.app.model.GalaxySession.table.c.user_id == user.id,
+ trans.app.model.GalaxySession.table.c.is_valid is True,
+ trans.app.model.GalaxySession.table.c.id != trans.galaxy_session.id ) ):
+ other_galaxy_session.is_valid = False
+ trans.sa_session.add( other_galaxy_session )
+ trans.sa_session.add( user )
+ trans.sa_session.flush()
+ trans.log_event( "User change password" )
+ return trans.show_ok_message('The password has been changed and any other existing Galaxy sessions have been logged out (but jobs in histories in those sessions will not be interrupted).')
+ return trans.fill_template( '/user/change_password.mako',
+ token=token,
+ status=status,
+ message=message )
+
+
+ @web.expose
+ def reset_password( self, trans, email=None, token=None, **kwd ):
"""Reset the user's password. Send an email with the new password."""
if trans.app.config.smtp_server is None:
- return trans.show_error_message( "Mail is not configured for this Galaxy instance. Please contact your local Galaxy administrator." )
- message = ''
- status = 'done'
+ return trans.show_error_message( "Mail is not configured for this"
+ "Galaxy instance and password reset information cannot be sent."
+ "Please contact your local Galaxy administrator." )
+ message = None
+ status = None
if kwd.get( 'reset_password_button', False ):
reset_user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first()
user = trans.get_user()
if reset_user:
if user and user.id != reset_user.id:
+ # This doesn't make any sense because all they have to do is log
+ # out and then try it again #TODO revisit why this exists.
message = "You may only reset your own password."
status = 'error'
else:
- chars = string.letters + string.digits
- new_pass = ""
+ prt = model.PasswordResetToken(reset_user)
+ trans.sa_session.add(prt)
+ trans.sa_session.flush()
reset_password_length = getattr( trans.app.config, "reset_password_length", 15 )
- for i in range( reset_password_length ):
- new_pass = new_pass + random.choice( chars )
host = trans.request.host.split( ':' )[ 0 ]
if host == 'localhost':
host = socket.getfqdn()
- body = 'Your password on %s has been reset to:\n\n %s\n' % ( host, new_pass )
+ reset_url = url_for( controller='user', action="change_password", token=prt.token, qualified=True)
+ body = PASSWORD_RESET_TEMPLATE % ( host, reset_url, reset_url )
frm = 'galaxy-no-reply@' + host
subject = 'Galaxy Password Reset'
try:
util.send_mail( frm, email, subject, body, trans.app.config )
- reset_user.set_password_cleartext( new_pass )
trans.sa_session.add( reset_user )
trans.sa_session.flush()
trans.log_event( "User reset password: %s" % email )
- message = "Password has been reset and emailed to: %s. <a href='%s'>Click here</a> to return to the login form." % ( escape( email ), web.url_for( controller='user', action='login', noredirect='true' ) )
+ message = "An email has been sent to %s. Please refer to that email for more instructions." % ( escape( email ) )
except Exception, e:
status = 'error'
message = 'Failed to reset password: %s' % str( e )
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c templates/user/change_password.mako
--- /dev/null
+++ b/templates/user/change_password.mako
@@ -0,0 +1,31 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <form name="change_password" id="change_password" action="${h.url_for( controller='user', action='change_password' )}" method="post" >
+ <div class="toolFormTitle">Change Password</div>
+ %if token:
+ <input type="hidden" name="token" value="${token|h}"/>
+ %elif not is_admin:
+ <div class="form-row">
+ <label>Current password:</label>
+ <input type="password" name="current" value="" size="40"/>
+ </div>
+ %endif
+ <div class="form-row">
+ <label>New password:</label>
+ <input type="password" name="password" value="" size="40"/>
+ </div>
+ <div class="form-row">
+ <label>Confirm:</label>
+ <input type="password" name="confirm" value="" size="40"/>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="change_password_button" value="Save"/>
+ </div>
+ </form>
+</div>
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c templates/user/index.mako
--- a/templates/user/index.mako
+++ b/templates/user/index.mako
@@ -6,7 +6,8 @@
<ul>
%if t.webapp.name == 'galaxy':
%if not trans.app.config.use_remote_user:
- <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a> (email, password, etc.)</li>
+ <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a> (email, address, etc.)</li>
+ <li><a href="${h.url_for( controller='user', action='change_password', cntrller=cntrller )}">${_('Change your password')}</a></li>
%endif
<li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li><li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li>
diff -r a2308bdc93b897af974766b190abe019ade49e9a -r 109372878f62317b74b57b47bb37d44b486ccf0c templates/user/info.mako
--- a/templates/user/info.mako
+++ b/templates/user/info.mako
@@ -127,27 +127,4 @@
</div></form></div>
- <p></p>
- <div class="toolForm">
- <form name="change_password" id="change_password" action="${h.url_for( controller='user', action='edit_info', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" >
- <div class="toolFormTitle">Change Password</div>
- %if not is_admin:
- <div class="form-row">
- <label>Current password:</label>
- <input type="password" name="current" value="" size="40"/>
- </div>
- %endif
- <div class="form-row">
- <label>New password:</label>
- <input type="password" name="password" value="" size="40"/>
- </div>
- <div class="form-row">
- <label>Confirm:</label>
- <input type="password" name="confirm" value="" size="40"/>
- </div>
- <div class="form-row">
- <input type="submit" name="change_password_button" value="Save"/>
- </div>
- </form>
- </div></%def>
https://bitbucket.org/galaxy/galaxy-central/commits/d0de709cc3e1/
Changeset: d0de709cc3e1
User: dannon
Date: 2015-01-13 19:21:08+00:00
Summary: pep8, import dedupe in user controller.
Affected #: 1 file
diff -r 109372878f62317b74b57b47bb37d44b486ccf0c -r d0de709cc3e16ca6e0b9e28ee91ea124467081a4 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -28,12 +28,10 @@
UsesFormDefinitionsMixin)
from galaxy.web.form_builder import build_select_field, CheckboxField
from galaxy.web.framework.helpers import escape, grids, time_ago
-from galaxy.web.framework.helpers import time_ago, grids
-from markupsafe import escape
log = logging.getLogger( __name__ )
-require_login_template = """
+REQUIRE_LOGIN_TEMPLATE = """
<p>
This %s has been configured such that only users who are logged in may use it.%s
</p>
@@ -48,6 +46,7 @@
If you did not make this request, no action is necessary on your part, though
you may want to notify an administrator."""
+
class UserOpenIDGrid( grids.Grid ):
use_panels = False
title = "OpenIDs linked to your account"
@@ -483,14 +482,14 @@
create_account_str = " If you don't already have an account, <a href='%s'>you may create one</a>." % \
web.url_for( controller='user', action='create', cntrller='user' )
if trans.webapp.name == 'galaxy':
- header = require_login_template % ( "Galaxy instance", create_account_str )
+ header = REQUIRE_LOGIN_TEMPLATE % ( "Galaxy instance", create_account_str )
else:
- header = require_login_template % ( "Galaxy tool shed", create_account_str )
+ header = REQUIRE_LOGIN_TEMPLATE % ( "Galaxy tool shed", create_account_str )
else:
if trans.webapp.name == 'galaxy':
- header = require_login_template % ( "Galaxy instance", "" )
+ header = REQUIRE_LOGIN_TEMPLATE % ( "Galaxy instance", "" )
else:
- header = require_login_template % ( "Galaxy tool shed", "" )
+ header = REQUIRE_LOGIN_TEMPLATE % ( "Galaxy tool shed", "" )
return trans.fill_template( '/user/login.mako',
email=email,
header=header,
@@ -1135,14 +1134,13 @@
status=status,
message=message )
-
@web.expose
def reset_password( self, trans, email=None, token=None, **kwd ):
"""Reset the user's password. Send an email with the new password."""
if trans.app.config.smtp_server is None:
- return trans.show_error_message( "Mail is not configured for this"
- "Galaxy instance and password reset information cannot be sent."
- "Please contact your local Galaxy administrator." )
+ return trans.show_error_message( "Mail is not configured for this Galaxy instance "
+ "and password reset information cannot be sent."
+ "Please contact your local Galaxy administrator." )
message = None
status = None
if kwd.get( 'reset_password_button', False ):
https://bitbucket.org/galaxy/galaxy-central/commits/9fa4eee8e77c/
Changeset: 9fa4eee8e77c
User: dannon
Date: 2015-01-13 19:22:03+00:00
Summary: Remove unused old password_reset_length for good.
Affected #: 1 file
diff -r d0de709cc3e16ca6e0b9e28ee91ea124467081a4 -r 9fa4eee8e77c2605b123ca9f686dd1970a1bfd2a lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1156,7 +1156,6 @@
prt = model.PasswordResetToken(reset_user)
trans.sa_session.add(prt)
trans.sa_session.flush()
- reset_password_length = getattr( trans.app.config, "reset_password_length", 15 )
host = trans.request.host.split( ':' )[ 0 ]
if host == 'localhost':
host = socket.getfqdn()
https://bitbucket.org/galaxy/galaxy-central/commits/80361f1c960f/
Changeset: 80361f1c960f
User: dannon
Date: 2015-01-13 19:24:15+00:00
Summary: Style tweaks in user_info.mako
Affected #: 1 file
diff -r 9fa4eee8e77c2605b123ca9f686dd1970a1bfd2a -r 80361f1c960fdbe48e83549f92c001d36d72a78d templates/user/info.mako
--- a/templates/user/info.mako
+++ b/templates/user/info.mako
@@ -7,7 +7,7 @@
<script type="text/javascript">
$(document).ready(function() {
- function validateString(test_string, type) {
+ function validateString(test_string, type) {
var mail_re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var username_re = /^[a-z0-9\-]{4,255}$/;
if (type === 'email') {
@@ -15,7 +15,7 @@
} else if (type === 'username'){
return username_re.test(test_string);
}
- }
+ }
function renderError(message) {
$(".donemessage").hide();
@@ -26,8 +26,9 @@
div.className = "errormessage";
div.innerHTML = message;
document.body.insertBefore( div, document.body.firstChild );
- }
}
+ }
+
function renderDone(message) {
$(".errormessage").hide();
if ($(".donemessage").length === 1) {
@@ -37,8 +38,8 @@
div.className = "donemessage";
div.innerHTML = message;
document.body.insertBefore( div, document.body.firstChild );
- }
}
+ }
original_email = $( '#email_input' ).val();
original_username = $( '#name_input' ).val();
@@ -55,7 +56,6 @@
var hidden_input = '<input type="hidden" id="login_info_button" name="login_info_button" value="Submit"/>';
$( '#send' ).attr( 'disabled', 'disabled' );
$( "#email_input" ).before( hidden_input );
-
if ( original_email !== email ){
if ( email.length > 255 ){ renderError( error_text_email_long ); validForm = false; }
else if ( !validateString( email, "email" ) ){ renderError( error_text_email ); validForm = false; }
@@ -66,7 +66,7 @@
if ( nothing_changed ){
renderDone( "Nothing has changed." );
}
- if ( !validForm || nothing_changed ) {
+ if ( !validForm || nothing_changed ) {
e.preventDefault();
// reactivate the button if the form wasn't submitted
$( '#send' ).removeAttr( 'disabled' );
https://bitbucket.org/galaxy/galaxy-central/commits/b64ae555ad12/
Changeset: b64ae555ad12
User: dannon
Date: 2015-01-13 19:33:56+00:00
Summary: More minor style tweaks in user controller.
Affected #: 1 file
diff -r 80361f1c960fdbe48e83549f92c001d36d72a78d -r b64ae555ad12fa3fef9a96954b33f8f23b723893 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1153,13 +1153,15 @@
message = "You may only reset your own password."
status = 'error'
else:
- prt = model.PasswordResetToken(reset_user)
- trans.sa_session.add(prt)
+ prt = model.PasswordResetToken( reset_user )
+ trans.sa_session.add( prt )
trans.sa_session.flush()
host = trans.request.host.split( ':' )[ 0 ]
if host == 'localhost':
host = socket.getfqdn()
- reset_url = url_for( controller='user', action="change_password", token=prt.token, qualified=True)
+ reset_url = url_for( controller='user',
+ action="change_password",
+ token=prt.token, qualified=True)
body = PASSWORD_RESET_TEMPLATE % ( host, reset_url, reset_url )
frm = 'galaxy-no-reply@' + host
subject = 'Galaxy Password Reset'
https://bitbucket.org/galaxy/galaxy-central/commits/27fec2663c6c/
Changeset: 27fec2663c6c
User: dannon
Date: 2015-01-13 19:58:35+00:00
Summary: Default to a response that doesn't leak user information (whether or not the user exists, when resetting password.
Affected #: 1 file
diff -r b64ae555ad12fa3fef9a96954b33f8f23b723893 -r 27fec2663c6c9305926f6bc34ba074042dd467cb lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1142,8 +1142,10 @@
"and password reset information cannot be sent."
"Please contact your local Galaxy administrator." )
message = None
- status = None
+ status = 'done'
if kwd.get( 'reset_password_button', False ):
+ # Default to a non-userinfo-leaking response message
+ message = "Your reset request for %s has been received. Please check your email account for more instructions. If you do not receive an email shortly, please contact an administrator." % ( escape( email ) )
reset_user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first()
user = trans.get_user()
if reset_user:
@@ -1170,16 +1172,10 @@
trans.sa_session.add( reset_user )
trans.sa_session.flush()
trans.log_event( "User reset password: %s" % email )
- message = "An email has been sent to %s. Please refer to that email for more instructions." % ( escape( email ) )
except Exception, e:
status = 'error'
message = 'Failed to reset password: %s' % str( e )
log.exception( 'Unable to reset password.' )
- elif email is not None:
- message = "The specified user does not exist."
- status = 'error'
- elif email is None:
- email = ""
return trans.fill_template( '/user/reset_password.mako',
message=message,
status=status )
https://bitbucket.org/galaxy/galaxy-central/commits/5222b149d9dc/
Changeset: 5222b149d9dc
User: dannon
Date: 2015-01-13 20:08:55+00:00
Summary: Change password does not need 'cntrller'.
Affected #: 1 file
diff -r 27fec2663c6c9305926f6bc34ba074042dd467cb -r 5222b149d9dcdd84fe593e64e3b48c3c7a0bc395 templates/user/index.mako
--- a/templates/user/index.mako
+++ b/templates/user/index.mako
@@ -7,7 +7,7 @@
%if t.webapp.name == 'galaxy':
%if not trans.app.config.use_remote_user:
<li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a> (email, address, etc.)</li>
- <li><a href="${h.url_for( controller='user', action='change_password', cntrller=cntrller )}">${_('Change your password')}</a></li>
+ <li><a href="${h.url_for( controller='user', action='change_password' )}">${_('Change your password')}</a></li>
%endif
<li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li><li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li>
https://bitbucket.org/galaxy/galaxy-central/commits/d2cafc77eee4/
Changeset: d2cafc77eee4
User: dannon
Date: 2015-01-13 20:31:11+00:00
Summary: Correct spacing in mail configuration message, was missing one between sentences.
Affected #: 1 file
diff -r 5222b149d9dcdd84fe593e64e3b48c3c7a0bc395 -r d2cafc77eee48d07b1958e395f6a8cf58770cf94 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1139,7 +1139,7 @@
"""Reset the user's password. Send an email with the new password."""
if trans.app.config.smtp_server is None:
return trans.show_error_message( "Mail is not configured for this Galaxy instance "
- "and password reset information cannot be sent."
+ "and password reset information cannot be sent. "
"Please contact your local Galaxy administrator." )
message = None
status = 'done'
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: davebgx: Close merged branch rna_eps_format.
by commits-noreply@bitbucket.org 13 Jan '15
by commits-noreply@bitbucket.org 13 Jan '15
13 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2fe70b684cea/
Changeset: 2fe70b684cea
Branch: rna_eps_format
User: davebgx
Date: 2015-01-13 14:09:35+00:00
Summary: Close merged branch rna_eps_format.
Affected #: 0 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: guerler: ToolForm/Workflow: Add post job action forms, enable custom tool form sections
by commits-noreply@bitbucket.org 13 Jan '15
by commits-noreply@bitbucket.org 13 Jan '15
13 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a2308bdc93b8/
Changeset: a2308bdc93b8
User: guerler
Date: 2015-01-13 06:09:03+00:00
Summary: ToolForm/Workflow: Add post job action forms, enable custom tool form sections
Affected #: 28 files
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a client/galaxy/scripts/galaxy.workflow_editor.canvas.js
--- a/client/galaxy/scripts/galaxy.workflow_editor.canvas.js
+++ b/client/galaxy/scripts/galaxy.workflow_editor.canvas.js
@@ -1089,7 +1089,11 @@
if ( this.active_node != node ) {
this.check_changes_in_active_form();
this.clear_active_node();
- parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ if (parent.__NEWTOOLFORM__) {
+ parent.show_form_for_tool( node.form_html, node );
+ } else {
+ parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ }
node.make_active();
this.active_node = node;
}
@@ -1099,7 +1103,11 @@
if ( this.active_node == node && (!parent.__NEWTOOLFORM__ || force)) {
// Reactive with new form_html
this.check_changes_in_active_form(); //Force changes to be saved even on new connection (previously dumped)
- parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ if (parent.__NEWTOOLFORM__) {
+ parent.show_form_for_tool( node.form_html, node );
+ } else {
+ parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ }
}
},
layout : function () {
@@ -1305,13 +1313,6 @@
return node;
}
-function update_node( data ) {
- var node = workflow.active_node;
- if (node) {
- node.update_field_data(data, true);
- }
-}
-
var ext_to_type = null;
var type_to_type = null;
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a client/galaxy/scripts/mvc/tools/tools-form-base.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-base.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -276,6 +276,11 @@
buttons : this.buttons
});
+ // remove padding
+ if (this.options.workflow) {
+ this.portlet.$content.css('padding', '0px');
+ }
+
// append message
this.portlet.append(this.message.$el, true);
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a client/galaxy/scripts/mvc/tools/tools-form-workflow.js
--- a/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
@@ -7,8 +7,199 @@
// create form view
var View = ToolFormBase.extend({
initialize: function(options) {
+ // link with node representation in workflow module
+ this.node = workflow.active_node;
+ if (!this.node) {
+ console.debug('FAILED - tools-form-workflow:initialize() - Node not found in workflow.');
+ return;
+ }
+
+ // initialize parameters
this.workflow = true;
- ToolFormBase.prototype.initialize.call(this, options);
+ this.options = options;
+
+ // load extension
+ var self = this;
+ Utils.get({
+ url : galaxy_config.root + 'api/datatypes',
+ cache : true,
+ success : function(datatypes) {
+ self.datatypes = datatypes;
+ self._makeSections(options.inputs);
+ ToolFormBase.prototype.initialize.call(self, options);
+ }
+ });
+ },
+
+ /** Builds all sub sections
+ */
+ _makeSections: function(inputs){
+ // for annotation
+ inputs[Utils.uuid()] = {
+ label : 'Edit Step Attributes',
+ type : 'section',
+ inputs : [{
+ label : 'Annotation / Notes',
+ name : 'annotation',
+ type : 'text',
+ area : true,
+ help : 'Add an annotation or notes to this step; annotations are available when a workflow is viewed.',
+ value : this.node.annotation
+ }]
+ }
+
+ // for actions
+ this.post_job_actions = this.node.post_job_actions;
+ for (var i in this.node.output_terminals) {
+ inputs[Utils.uuid()] = this._makeSection(i);
+ }
+ },
+
+ /** Builds sub section with step actions/annotation
+ */
+ _makeSection: function(output_id){
+ // format datatypes
+ var extensions = [];
+ for (key in this.datatypes) {
+ extensions.push({
+ 0 : this.datatypes[key],
+ 1 : this.datatypes[key]
+ });
+ }
+
+ // sort extensions
+ extensions.sort(function(a, b) {
+ return a.label > b.label ? 1 : a.label < b.label ? -1 : 0;
+ });
+
+ // add additional options
+ extensions.unshift({
+ 0 : 'Sequences',
+ 1 : 'Sequences'
+ });
+ extensions.unshift({
+ 0 : 'Roadmaps',
+ 1 : 'Roadmaps'
+ });
+ extensions.unshift({
+ 0 : 'Leave unchanged',
+ 1 : 'None'
+ });
+
+ // create custom sub section
+ var input_config = {
+ label : 'Edit Step Action: \'' + output_id + '\'',
+ type : 'section',
+ inputs : [{
+ action : 'RenameDatasetAction',
+ argument : 'newname',
+ label : 'Rename dataset',
+ type : 'text',
+ value : '',
+ ignore : '',
+ help : 'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'
+ },{
+ action : 'ChangeDatatypeAction',
+ argument : 'newtype',
+ label : 'Change datatype',
+ type : 'select',
+ ignore : 'None',
+ options : extensions,
+ help : 'This action will change the datatype of the output to the indicated value.'
+ },{
+ action : 'TagDatasetAction',
+ argument : 'tags',
+ label : 'Tags',
+ type : 'text',
+ value : '',
+ ignore : '',
+ help : 'This action will set tags for the dataset.'
+ },{
+ label : 'Assign columns',
+ type : 'section',
+ inputs : [{
+ action : 'ColumnSetAction',
+ argument : 'chromCol',
+ label : 'Chrom column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'startCol',
+ label : 'Start column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'endCol',
+ label : 'End column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'strandCol',
+ label : 'Strand column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'nameCol',
+ label : 'Name column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ }],
+ help : 'This action will set column assignments in the output dataset. Blank fields are ignored.'
+ },{
+ action : 'EmailAction',
+ label : 'Email notification',
+ type : 'boolean',
+ value : 'false',
+ ignore : 'false',
+ help : 'This action will send an email notifying you when the job is done.'
+ },{
+ action : 'DeleteIntermediatesAction',
+ label : 'Delete non-outputs',
+ type : 'boolean',
+ value : 'false',
+ ignore : 'false',
+ help : 'All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect.'
+ }]
+ };
+
+ // visit input nodes and enrich by name/value pairs from server data
+ var self = this;
+ function visit (inputs) {
+ for (var i in inputs) {
+ var input = inputs[i];
+ if (input.action) {
+ input.name = 'pja__' + output_id + '__' + input.action;
+ if (input.argument) {
+ input.name += '__' + input.argument;
+ }
+ var d = self.post_job_actions[input.action + output_id];
+ if (d) {
+ if (input.argument) {
+ input.value = d.action_arguments && d.action_arguments[input.argument] || input.value;
+ } else {
+ input.value = 'true';
+ }
+ }
+ } else {
+ if (input.inputs) {
+ visit(input.inputs);
+ }
+ }
+ }
+ }
+ visit(input_config.inputs);
+
+ // return final configuration
+ return input_config;
},
/** Builds a new model through api call and recreates the entire form
@@ -38,15 +229,16 @@
type : 'GET',
url : model_url,
data : current_state,
- success : function(node) {
- parent.update_node(node);
+ success : function(data) {
+ // update node in workflow module
+ self.node.update_field_data(data, true);
// process completed
self.deferred.done(process_id);
// log success
console.debug('tools-form::_refreshForm() - States refreshed.');
- console.debug(node);
+ console.debug(data);
},
error : function(response) {
// process completed
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -1,8 +1,8 @@
/**
This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _createField() function.
*/
-define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content', 'mvc/tools/tools-input'],
- function(Utils, Table, Ui, Repeat, SelectContent, InputElement) {
+define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content', 'mvc/tools/tools-input'],
+ function(Utils, Table, Ui, Portlet, Repeat, SelectContent, InputElement) {
// create form view
var View = Backbone.View.extend({
@@ -36,13 +36,13 @@
// load settings elements into table
for (var i in this.inputs) {
- this._add(this.inputs[i]);
+ this.add(this.inputs[i]);
}
},
/** Add a new input element
*/
- _add: function(input) {
+ add: function(input) {
// link this
var self = this;
@@ -66,6 +66,10 @@
case 'repeat':
this._addRepeat(input_def);
break;
+ // customized section
+ case 'section':
+ this._addSection(input_def);
+ break;
// default single element row
default:
this._addRow(input_def);
@@ -103,8 +107,7 @@
// check if non-hidden elements exist
var nonhidden = false;
for (var j in case_def.inputs) {
- var type = case_def.inputs[j].type;
- if (type && type !== 'hidden') {
+ if (!case_def.inputs[j].hidden) {
nonhidden = true;
break;
}
@@ -244,6 +247,58 @@
this.table.append(input_def.id);
},
+ /** Add a customized section
+ */
+ _addSection: function(input_def) {
+ // link this
+ var self = this;
+
+ // create sub section
+ var sub_section = new View(self.app, {
+ inputs : input_def.inputs,
+ cls : 'ui-table-plain'
+ });
+
+ // delete button
+ var button_visible = new Ui.ButtonIcon({
+ icon : 'fa-eye-slash',
+ tooltip : 'Show/hide section',
+ cls : 'ui-button-icon-plain'
+ });
+
+ // create portlet for sub section
+ var portlet = new Portlet.View({
+ title : input_def.label,
+ cls : 'ui-portlet-section',
+ operations : {
+ button_visible: button_visible
+ }
+ });
+ portlet.append(sub_section.$el);
+
+ // add event handler visibility button
+ var visible = false;
+ portlet.$content.hide();
+ portlet.$header.css('cursor', 'pointer');
+ portlet.$header.on('click', function() {
+ if (visible) {
+ visible = false;
+ portlet.$content.hide();
+ button_visible.setIcon('fa-eye-slash');
+ } else {
+ visible = true;
+ portlet.$content.fadeIn('fast');
+ button_visible.setIcon('fa-eye');
+ }
+ });
+
+ // create table row
+ this.table.add(portlet.$el);
+
+ // append row to table
+ this.table.append(input_def.id);
+ },
+
/** Add a single input field element
*/
_addRow: function(input_def) {
@@ -273,6 +328,11 @@
// append to table
this.table.append(id);
+ // hide row if neccessary
+ if (input_def.hidden) {
+ this.table.get(id).hide();
+ }
+
// return created field
return field;
},
@@ -316,7 +376,7 @@
field = this._fieldHidden(input_def);
break;
- // hidden field
+ // hidden data field
case 'hidden_data':
field = this._fieldHidden(input_def);
break;
@@ -465,9 +525,9 @@
_fieldText : function(input_def) {
var self = this;
return new Ui.Input({
- id : 'field-' + input_def.id,
- area : input_def.area,
- onchange: function() {
+ id : 'field-' + input_def.id,
+ area : input_def.area,
+ onchange : function() {
self.app.trigger('refresh');
}
});
@@ -476,11 +536,15 @@
/** Slider field
*/
_fieldSlider: function(input_def) {
+ var self = this;
return new Ui.Slider.View({
- id : 'field-' + input_def.id,
- precise : input_def.type == 'float',
- min : input_def.min,
- max : input_def.max
+ id : 'field-' + input_def.id,
+ precise : input_def.type == 'float',
+ min : input_def.min,
+ max : input_def.max,
+ onchange : function() {
+ self.app.trigger('refresh');
+ }
});
},
@@ -488,18 +552,22 @@
*/
_fieldHidden : function(input_def) {
return new Ui.Hidden({
- id : 'field-' + input_def.id,
- info : input_def.info
+ id : 'field-' + input_def.id,
+ info : input_def.info
});
},
/** Boolean field
*/
_fieldBoolean : function(input_def) {
+ var self = this;
return new Ui.RadioButton.View({
- id : 'field-' + input_def.id,
- data : [ { label : 'Yes', value : 'true' },
- { label : 'No', value : 'false' }]
+ id : 'field-' + input_def.id,
+ data : [ { label : 'Yes', value : 'true' },
+ { label : 'No', value : 'false' }],
+ onchange : function() {
+ self.app.trigger('refresh');
+ }
});
}
});
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a client/galaxy/scripts/mvc/tools/tools-tree.js
--- a/client/galaxy/scripts/mvc/tools/tools-tree.js
+++ b/client/galaxy/scripts/mvc/tools/tools-tree.js
@@ -108,22 +108,29 @@
convert(job_input_id, head[input.id + '-section-' + selectedCase]);
}
break;
+ // handle custom sub sections
+ case 'section':
+ convert('', node);
+ break;
default:
// get field
var field = self.app.field_list[input.id];
-
- // get and patch field value
- var value = field.value();
- if (patch[input.type]) {
- value = patch[input.type](value);
- }
-
- // handle default value
- if (!field.skip) {
- if (field.validate && !field.validate(value)) {
- value = null;
+ if (field && field.value) {
+ // get and patch field value
+ var value = field.value();
+ if (patch[input.type]) {
+ value = patch[input.type](value);
}
- add (job_input_id, input.id, value);
+
+ // handle default value
+ if (!field.skip) {
+ if (field.validate && !field.validate(value)) {
+ value = null;
+ }
+ if (input.ignore === undefined || (value && input.ignore != value)) {
+ add (job_input_id, input.id, value);
+ }
+ }
}
}
}
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a client/galaxy/scripts/mvc/ui/ui-misc.js
--- a/client/galaxy/scripts/mvc/ui/ui-misc.js
+++ b/client/galaxy/scripts/mvc/ui/ui-misc.js
@@ -193,6 +193,12 @@
this.disabled = false;
},
+ // change icon
+ setIcon: function(icon_cls) {
+ this.$('i').removeClass(this.options.icon).addClass(icon_cls);
+ this.options.icon = icon_cls;
+ },
+
// template
_template: function(options) {
// width
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a client/galaxy/scripts/mvc/ui/ui-portlet.js
--- a/client/galaxy/scripts/mvc/ui/ui-portlet.js
+++ b/client/galaxy/scripts/mvc/ui/ui-portlet.js
@@ -25,6 +25,7 @@
$content : null,
$buttons : null,
$operations : null,
+ $header : null,
// initialize
initialize : function(options) {
@@ -35,13 +36,16 @@
this.setElement(this._template(this.options));
// link content
- this.$content = this.$el.find('#content');
+ this.$content = this.$el.find('.content');
// link title
- this.$title = this.$el.find('#portlet-title-text');
+ this.$title = this.$el.find('.portlet-title-text');
+
+ // link header
+ this.$header = this.$el.find('.portlet-header');
// set content format
- var $portlet_content = this.$el.find('#portlet-content');
+ var $portlet_content = this.$el.find('.portlet-content');
if (!this.options.scrollable) {
if (this.options.title) {
$portlet_content.addClass('no-scroll');
@@ -59,7 +63,7 @@
}
// append buttons
- this.$buttons = $(this.el).find('#buttons');
+ this.$buttons = $(this.el).find('.buttons');
if (this.options.buttons) {
// link functions
var self = this;
@@ -72,7 +76,7 @@
}
// append operations
- this.$operations = $(this.el).find('#operations');
+ this.$operations = $(this.el).find('.operations');
if (this.options.operations) {
// link functions
var self = this;
@@ -161,27 +165,27 @@
var tmpl = '<div id="' + options.id + '" class="' + options.cls + '">';
if (options.title) {
- tmpl += '<div id="portlet-header" class="portlet-header">' +
- '<div id="operations" style="float: ' + options.operations_flt + ';"></div>' +
+ tmpl += '<div class="portlet-header">' +
+ '<div class="operations" style="float: ' + options.operations_flt + ';"></div>' +
'<div class="portlet-title">';
if (options.icon)
tmpl += '<i class="icon fa ' + options.icon + '"> </i>';
- tmpl += '<span id="portlet-title-text" class="portlet-title-text">' + options.title + '</span>' +
+ tmpl += '<span class="portlet-title-text">' + options.title + '</span>' +
'</div>' +
'</div>';
}
- tmpl += '<div id="portlet-content" class="portlet-content">';
+ tmpl += '<div class="portlet-content">';
if (options.placement == 'top') {
- tmpl += '<div id="buttons" class="buttons"></div>';
+ tmpl += '<div class="buttons"></div>';
}
- tmpl += '<div id="content" class="content"></div>';
+ tmpl += '<div class="content"></div>';
if (options.placement == 'bottom') {
- tmpl += '<div id="buttons" class="buttons"></div>';
+ tmpl += '<div class="buttons"></div>';
}
tmpl += '</div>' +
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a config/plugins/visualizations/charts/static/build-app.js
--- a/config/plugins/visualizations/charts/static/build-app.js
+++ b/config/plugins/visualizations/charts/static/build-app.js
@@ -1,6 +1,6 @@
-// Underscore.js 1.4.4
+// Underscore.js 1.7.0
// http://underscorejs.org
-// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
-define("mvc/ui/ui-modal",[],function(){var e=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast"),this.options.closing_callback&&this.options.closing_callback()},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="ui-modal modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:e}}),function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(x.has(e,o)&&t.call(r,e[o],o,e)===n)return};x.map=x.collect=function(e,t,n){var r=[];return e==null?r:h&&e.map===h?e.map(t,n):(T(e,function(e,i,s){r.push(t.call(n,e,i,s))}),r)};var N="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?void 0:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},x.shuffle=function(e){var t,n=0,r=[];return T(e,function(e){t=x.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return x.isFunction(e)?e:function(t){return t[e]}};x.sortBy=function(e,t,n){var r=k(t);return x.pluck(x.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t==null?x.identity:t);return T(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};x.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(x.has(e,t)?e[t]:e[t]=[]).push(n)})},x.countBy=function(e,t,n){return L(e,t,n,function(e,t){x.has(e,t)||(e[t]=0),e[t]++})},x.sortedIndex=function(e,t,n,r){n=n==null?x.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},x.toArray=function(e){return e?x.isArray(e)?u.call(e):e.length===+e.length?x.map(e,x.identity):x.values(e):[]},x.size=function(e){return e==null?0:e.length===+e.length?e.length:x.keys(e).length},x.first=x.head=x.take=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,0,t):e[0]},x.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},x.last=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},x.rest=x.tail=x.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},x.compact=function(e){return x.filter(e,x.identity)};var A=function(e,t,n){return T(e,function(e){x.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};x.flatten=function(e,t){return A(e,t,[])},x.without=function(e){return x.difference(e,u.call(arguments,1))},x.uniq=x.unique=function(e,t,n,r){x.isFunction(t)&&(r=n,n=t,t=!1);var i=n?x.map(e,n,r):e,s=[],o=[];return T(i,function(n,r){if(t?!r||o[o.length-1]!==n:!x.contains(o,n))o.push(n),s.push(e[r])}),s},x.union=function(){return x.uniq(a.apply(r,arguments))},x.intersection=function(e){var t=u.call(arguments,1);return x.filter(x.uniq(e),function(e){return x.every(t,function(t){return x.indexOf(t,e)>=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=x.pluck(e,""+r);return n},x.unzip=function(e){var t=[];return x.each(e,function(e,n){x.each(e,function(e,r){t.length<=r&&(t[r]=[]),t[r][n]=e})}),t},x.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},x.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=x.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(y&&e.indexOf===y)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},x.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(b&&e.lastIndexOf===b)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},x.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};x.bind=function(e,t){var n,r;if(e.bind===S&&S)return S.apply(e,u.call(arguments,1));if(!x.isFunction(e))throw new TypeError;return n=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=e.prototype;var i=new O;O.prototype=null;var s=e.apply(i,n.concat(u.call(arguments)));return Object(s)===s?s:i}return e.apply(t,n.concat(u.call(arguments)))}},x.partial=function(e){var t=u.call(arguments,1);return function(){return e.apply(this,t.concat(u.call(arguments)))}},x.bindAll=function(e){var t=u.call(arguments,1);if(t.length===0)throw new Error("bindAll must be passed function names");return T(t,function(t){e[t]=x.bind(e[t],e)}),e},x.memoize=function(e,t){var n={};return t||(t=x.identity),function(){var r=t.apply(this,arguments);return x.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},x.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},x.defer=function(e){return x.delay.apply(x,[e,1].concat(u.call(arguments,1)))},x.throttle=function(e,t,n){var r,i,s,o,u=0,a=function(){u=new Date,s=null,o=e.apply(r,i)};return function(){var f=new Date;!u&&n===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0?(clearTimeout(s),s=null,u=f,o=e.apply(r,i)):s||(s=setTimeout(a,l)),o}},x.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},x.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},x.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},x.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&t.push(n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]===void 0&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return M(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i<e;i++)r[i]=t.call(n,i);return r},x.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=x.invert(_.escape);var D={escape:new RegExp("["+x.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(_.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),x.result=function(e,t){if(e==null)return void 0;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(x,e))}})};var P=0;x.uniqueId=function(e){var t=++P+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(j,function(e){return"\\"+B[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var F=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}.call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e){return $("<div/>").text(e).html()}function n(e){top.__utils__get__=top.__utils__get__||{},e.cache&&top.__utils__get__[e.url]?(e.success&&e.success(top.__utils__get__[e.url]),console.debug("utils.js::get() - Fetching from cache ["+e.url+"].")):r({url:e.url,data:e.data,success:function(t){top.__utils__get__[e.url]=t,e.success&&e.success(t)},error:function(t){e.error&&e.error(t)}})}function r(e){var t={contentType:"application/json",type:e.type||"GET",data:e.data||{},url:e.url};t.type=="GET"||t.type=="DELETE"?(t.url.indexOf("?")==-1?t.url+="?":t.url+="&",t.url=t.url+$.param(t.data),t.data=null):(t.dataType="json",t.url=t.url,t.data=JSON.stringify(t.data)),$.ajax(t).done(function(t){if(typeof t=="string")try{t=t.replace("Infinity,",'"Infinity",'),t=jQuery.parseJSON(t)}catch(n){console.debug(n)}e.success&&e.success(t)}).fail(function(t){var n=null;try{n=jQuery.parseJSON(t.responseText)}catch(r){n=t.responseText}e.error&&e.error(n,t)})}function i(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function s(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function o(t,n){return t?e.defaults(t,n):n}function u(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function a(){return"x"+Math.random().toString(36).substring(2,9)}function f(e){var t=$("<p></p>");return t.append(e),t}function l(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:s,cssGetAttribute:i,get:n,merge:o,bytesToString:u,uuid:a,time:l,wrap:f,request:r,sanitize:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,scrollable:!0,nopadding:!1,operations:null,placement:"bottom",cls:"ui-portlet",operations_flt:"right"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find("#content"),this.$title=this.$el.find("#portlet-title-text");var n=this.$el.find("#portlet-content");this.options.scrollable?n.addClass("scroll"):this.options.title?n.addClass("no-scroll"):n.addClass("no-scroll-no-title"),this.options.nopadding&&(n.css("padding","0px"),this.$content.css("padding","0px")),this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var r=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),r.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find("#operations");if(this.options.operations){var r=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t,n){n?this.$content.append(t):this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div id="'+e.id+'" class="'+e.cls+'">';return e.title&&(t+='<div id="portlet-header" class="portlet-header"><div id="operations" style="float: '+e.operations_flt+';"></div>'+'<div class="portlet-title">',e.icon&&(t+='<i class="icon fa '+e.icon+'"> </i>'),t+='<span id="portlet-title-text" class="portlet-title-text">'+e.title+"</span>"+"</div>"+"</div>"),t+='<div id="portlet-content" class="portlet-content">',e.placement=="top"&&(t+='<div id="buttons" class="buttons"></div>'),t+='<div id="content" class="content"></div>',e.placement=="bottom"&&(t+='<div id="buttons" class="buttons"></div>'),t+="</div></div>",t}});return{View:t}}),define("mvc/ui/ui-select-default",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",error_text:"No data available",visible:!0,wait:!1,multiple:!1,searchable:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find(".select"),this.$icon=this.$el.find(".icon"),this.$button=this.$el.find(".button"),this.options.multiple?(this.$select.prop("multiple",!0),this.$select.addClass("ui-select-multiple"),this.$icon.remove()):this.$el.addClass("ui-select"),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value),this.options.visible||this.hide(),this.options.wait?this.wait():this.show();var n=this;this.$select.on("change",function(){n._change()}),this.on("change",function(){n._change()})},value:function(e){return e!==undefined&&(this.$select.val(e),this.$select.select2&&this.$select.select2("val",e)),this.$select.val()},first:function(){var e=this.$select.find("option");return e.length>0?e.val():undefined},validate:function(){var e=this.value();e instanceof Array||(e=[e]);for(var t in e)if([null,"null",undefined].indexOf(e[t])>-1)return!1;return!0},text:function(){return this.$select.find("option:selected").text()},show:function(){this.unwait(),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin")},unwait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down")},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){var t=this.$select.val();this.$select.find("option").remove();for(var n in e)this.$select.append(this._templateOption(e[n]));this._refresh(),this.$select.val(t),this.$select.val()||this.$select.val(this.first()),this.options.searchable&&(this.$button.hide(),this.$select.select2("destroy"),this.$select.select2())},setOnChange:function(e){this.options.onchange=e},exists:function(e){return this.$select.find('option[value="'+e+'"]').length>0},_change:function(){this.options.onchange&&this.options.onchange(this.$select.val())},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.disable(),this.$select.append(this._templateOption({value:"null",label:this.options.error_text}))):this.enable()},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){return'<div id="'+e.id+'">'+'<select id="select" class="select '+e.cls+" "+e.id+'"></select>'+'<div class="button">'+'<i class="icon"/>'+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-slider",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{min:null,max:null,step:null,precise:!1,split:1e4},initialize:function(t){var n=this;this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.useslider=this.options.max!==null&&this.options.min!==null&&this.options.max>this.options.min,this.options.step===null&&(this.options.step=1,this.options.precise&&this.useslider&&(this.options.step=(this.options.max-this.options.min)/this.options.split)),this.useslider?(this.$slider=this.$el.find("#slider"),this.$slider.slider(this.options),this.$slider.on("slide",function(e,t){n.value(t.value)})):this.$el.find(".ui-form-slider-text").css("width","100%"),this.$text=this.$el.find("#text"),this.options.value!==undefined&&this.value(this.options.value),this.$text.on("change",function(){n.value($(this).val())});var r=[];this.$text.on("keyup",function(e){r[e.which]=!1}),this.$text.on("keydown",function(e){var t=e.which;r[t]=!0,t==8||t==9||t==13||t==37||t==39||t>=48&&t<=57||t==190&&$(this).val().indexOf(".")==-1&&n.options.precise||t==189&&$(this).val().indexOf("-")==-1||r[91]||r[17]||event.preventDefault()})},value:function(e){return e!==undefined&&(isNaN(e)&&(e=0),this.options.max!==null&&(e=Math.min(e,this.options.max)),this.options.min!==null&&(e=Math.max(e,this.options.min)),this.options.onchange&&this.options.onchange(e),this.$slider&&this.$slider.slider("value",e),this.$text.val(e)),this.$text.val()},_template:function(e){return'<div id="'+e.id+'" class="ui-form-slider">'+'<input id="text" type="text" class="ui-form-slider-text"/>'+'<div id="slider" class="ui-form-slider-element"/>'+"</div>"}});return{View:t}}),define("mvc/ui/ui-options",["utils/utils"],function(e){var t=Backbone.View.extend({initialize:function(t){this.optionsDefault={visible:!0,data:[],id:e.uuid(),error_text:"No data available.",wait_text:"Please wait..."},this.options=e.merge(t,this.optionsDefault),this.setElement("<div/>"),this.$message=$("<div/>"),this.$options=$(this._template(t)),this.$el.append(this.$message),this.$el.append(this.$options),this.options.visible||this.$el.hide(),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value);var n=this;this.on("change",function(){n._change()})},update:function(e){var t=this._getValue();this.$options.empty();if(this._templateOptions)this.$options.append(this._templateOptions(e));else for(var n in e){var r=$(this._templateOption(e[n]));r.addClass("ui-option"),this.$options.append(r)}var i=this;this.$el.find("input").on("change",function(){i.value(i._getValue()),i._change()}),this._refresh(),this.value(t)},value:function(e){if(e!==undefined){e instanceof Array||(e=[e]),this.$el.find("input").prop("checked",!1);for(var t in e)this.$el.find('input[value="'+e[t]+'"]').first().prop("checked",!0)}return this._getValue()},exists:function(e){if(e!==undefined){e instanceof Array||(e=[e]);for(var t in e)if(this.$el.find('input[value="'+e[t]+'"]').length>0)return!0}return!1},first:function(){var e=this.$el.find("input");return e.length>0?e.val():undefined},validate:function(){var e=this.value();e instanceof Array||(e=[e]);for(var t in e)if([null,"null",undefined].indexOf(e[t])>-1)return!1;return!0},wait:function(){this._size()==0&&(this._messageShow(this.options.wait_text,"info"),this.$options.hide())},unwait:function(){this._messageHide(),this._refresh()},_change:function(){this.options.onchange&&this.options.onchange(this._getValue())},_refresh:function(){this._size()==0?(this._messageShow(this.options.error_text,"danger"),this.$options.hide()):(this._messageHide(),this.$options.css("display","inline-block"))},_getValue:function(){var e=this.$el.find(":checked");if(e.length==0)return"null";if(this.options.multiple){var t=[];return e.each(function(){t.push($(this).val())}),t}return e.val()},_size:function(){return this.$el.find(".ui-option").length},_messageShow:function(e,t){this.$message.show(),this.$message.removeClass(),this.$message.addClass("ui-message alert alert-"+t),this.$message.html(e)},_messageHide:function(){this.$message.hide()},_template:function(){return'<div class="ui-options"/>'}}),n={};n.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="radio" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var r={};r.View=t.extend({initialize:function(e){e.multiple=!0,t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="checkbox" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var i={};return i.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},value:function(e){return e!==undefined&&(this.$el.find("input").prop("checked",!1),this.$el.find("label").removeClass("active"),this.$el.find('[value="'+e+'"]').prop("checked",!0).closest("label").addClass("active")),this._getValue()},_templateOption:function(e){var t='<label class="btn btn-default">';return e.icon&&(t+='<i class="fa '+e.icon+'"/>'),t+='<input type="radio" name="'+this.options.id+'" value="'+e.value+'">'+e.label+"</label>",t},_template:function(){return'<div class="btn-group ui-radiobutton" data-toggle="buttons"/>'}}),{Base:t,Radio:n,RadioButton:i,Checkbox:r}}),define("mvc/ui/ui-drilldown",["utils/utils","mvc/ui/ui-options"],function(e,t){var n=t.Base.extend({initialize:function(e){this.display=e.display||"checkbox",e.multiple=this.display=="checkbox",t.Base.prototype.initialize.call(this,e)},_templateOption:function(e,t,n){return'<div><input name="'+this.options.id+'" class="ui-option" type="'+this.display+'" value="'+t+'">'+e+"<div/>"},_templateOptions:function(e){function n(e,t){function n(n){n?(t.fadeIn("fast"),e.removeClass("toggle-expand"),e.addClass("toggle"),e.is_expanded=!0):(t.hide(),e.removeClass("toggle"),e.addClass("toggle-expand"),e.is_expanded=!1)}e.on("click",function(){n(!e.is_expanded)})}function r(e,s){for(i in s){var o=s[i],u=o.options.length>0,a=$("<div/>");if(u){var f=$('<span class="ui-drilldown-button form-toggle icon-button toggle-expand" style="position: relative; top: 2px;"/>'),l=$("<div/>");l.append(f),l.append(t._templateOption(o.name,o.value)),a.append(l);var c=$('<div style="display: none; margin-left: 25px;"/>');r(c,o.options),a.append(c),n(f,c)}else a.append(t._templateOption(o.name,o.value));e.append(a)}}var t=this,s=$("<div/>");return r(s,e),s},_template:function(e){return'<div class="ui-options drilldown-container" id="'+e.id+'"/>'}});return{View:n}}),define("mvc/ui/ui-button-menu",["utils/utils"],function(e){return Backbone.View.extend({optionsDefault:{id:"",title:"",floating:"right",icon:null,onclick:null,cls:"ui-button-icon ui-button-menu",tooltip:"",target:"",href:"",onunload:null,visible:!0,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){$(".tooltip").hide(),e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide(),n.tooltip({title:t.tooltip,placement:"bottom"})},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null,cls:"button-menu btn-group"};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a class="dropdown-item" href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t="",n="";e.title?t="width: auto;":n="margin: 0px;";var r='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="dropdown '+e.cls+'">'+'<div class="root button dropdown-toggle" data-toggle="dropdown" style="'+n+'">'+'<i class="icon fa '+e.icon+'"/>';return e.title&&(r+=' <span class="title">'+e.title+"</span>"),r+="</div></div>",r}})}),define("mvc/ui/ui-misc",["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(e,t,n,r,i,s,o){var u=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},_template:function(e){return'<img class="ui-image '+e.cls+'" src="'+e.url+'"/>'}}),a=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<label class="ui-label '+e.cls+'">'+e.title+"</label>"},value:function(){return options.title}}),f=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" class="ui-icon"/> '+e.title+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="float: '+e.floating+';" type="button" class="'+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),c=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$button=this.$el.find(".button");var n=this;$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&!n.disabled&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled"),this.disabled=!0},enable:function(){this.$button.removeClass("disabled"),this.disabled=!1},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div class="button"><i class="icon fa '+e.icon+'"/> '+'<span class="title">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),h=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)" class="ui-anchor '+e.cls+'">'+e.title+"</a></div>"}}),p=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>"),this.options.message&&this.update(this.options)},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.find(".alert").append(t.message),this.$el.fadeIn(),this.timeout&&window.clearTimeout(this.timeout);if(!t.persistent){var n=this;this.timeout=window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="ui-message alert alert-'+e.status+'"/>'}}),d=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),v=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:!1,visible:!0,cls:"",area:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.$el.on("input",function(){n.options.onchange&&n.options.onchange(n.$el.val())})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return e.area?'<textarea id="'+e.id+'" class="ui-textarea '+e.cls+'"></textarea>':'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="ui-input '+e.cls+'">'}}),m=Backbone.View.extend({initialize:function(e){this.options=e,this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value)},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return'<hidden id="'+e.id+'" value="'+e.value+'"/>'}});return{Anchor:h,Button:l,ButtonIcon:c,ButtonMenu:s,Icon:f,Image:u,Input:v,Label:a,Message:p,Modal:o,RadioButton:r.RadioButton,Checkbox:r.Checkbox,Radio:r.Radio,Searchbox:d,Select:t,Hidden:m,Slider:n,Drilldown:i}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e,t,n,r,i){var s=this;e.state("wait","Requesting job results...");var o=e.get("dataset_id_job");o!=""?s._wait(e,r,i):s._submit(e,t,n,r,i)},cleanup:function(t){var n=this,r=t.get("dataset_id_job");r!=""&&(e.request({type:"PUT",url:config.root+"api/histories/none/contents/"+r,data:{deleted:!0},success:function(){n._refreshHdas()}}),t.set("dataset_id_job",""))},_submit:function(t,n,r,i,s){var o=this,u=t.id,a=t.get("type"),f=t.definition;data={tool_id:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,columns:r,settings:n}},t.state("wait","Sending job request..."),e.request({type:"POST",url:config.root+"api/tools",data:data,success:function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response."),s&&s();else{o._refreshHdas();var n=e.outputs[0];t.state("wait","Your job has been queued. You may close the browser window. The job will run in the background."),t.set("dataset_id_job",n.id),o.app.storage.save(),o._wait(t,i,s)}},error:function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the 'charts' tool. Please make sure it is installed. "+n),s&&s()}})},_wait:function(t,n,r){var i=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.get("dataset_id_job"),data:{},success:function(e){var s=!1;switch(e.state){case"ok":t.state("wait","Job completed successfully..."),n&&n(e),s=!0;break;case"error":t.state("failed","Job has failed. Please check the history for details."),r&&r(e),s=!0;break;case"running":t.state("wait","Your job is running. You may close the browser window. The job will continue in the background.")}s||setTimeout(function(){i._wait(t,n,r)},i.app.config.get("query_timeout"))}})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshContents()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e){e.groups?this._get_blocks(e):this._get_dataset(e.id,e.success,e.error)},_get_blocks:function(e){function c(i){l._get(i,function(){var s=!1;for(var o in e.groups){destination_group=e.groups[o],source_group=i.groups[o],destination_group.values||(destination_group.values=[]),destination_group.values=destination_group.values.concat(source_group.values);if(source_group.values.length==0){s=!0;break}}if(++f<u&&!s){n&&n(parseInt(f/u*100));var l=i.start+r;i=$.extend(!0,a,{start:l}),c(i)}else t()})}var t=e.success,n=e.progress,r=this.app.config.get("query_limit"),i=e.start||0,s=i+e.query_limit||i+this.app.config.get("query_limit"),o=Math.abs(s-i);if(o<=0){console.debug("FAILED - Datasets::request() - Invalid query range.");return}var u=Math.ceil(o/r)||1,a=$.extend(!0,{},e),f=0,l=this,h=$.extend(!0,a,{start:i});this._get_dataset(e.id,function(){c(h)})},_get_dataset:function(t,n,r){var i=this.list[t];if(i){n(i);return}var s=this;e.request({type:"GET",url:config.root+"api/datasets/"+t,success:function(e){switch(e.state){case"error":r&&r(e);break;default:s.list[t]=e,n(e)}}})},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.start+this.app.config.get("query_limit")+"_"+t},_get:function(e,t){e.start=e.start||0;var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f]||a==="auto"||a==="zero")continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){var t=e.start;console.debug("Datasets::_fill_from_cache() - Filling request from cache at "+t+".");var n=0;for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s],u=this._block_id(e,o.index),a=this.cache[u];a&&(n=Math.max(n,a.length))}}n==0&&console.debug("Datasets::_fill_from_cache() - Reached data range limit.");for(var r in e.groups){var i=e.groups[r];i.values=[];for(var f=0;f<n;f++)i.values[f]={x:parseInt(f)+t}}for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s];switch(o.index){case"auto":for(var f=0;f<n;f++){var l=i.values[f];l[s]=parseInt(f)+t}break;case"zero":for(var f=0;f<n;f++){var l=i.values[f];l[s]=0}break;default:var u=this._block_id(e,o.index),a=this.cache[u];for(var f=0;f<n;f++){var l=i.values[f],c=a[f];isNaN(c)&&!o.is_label&&(c=0),l[s]=c}}}}},_fetch:function(t,n){var r=t.start?t.start:0,i=this.app.config.get("query_limit"),s=0;t.columns&&(s=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+s+" column(s) at "+r+".")),s==0&&console.debug("Datasets::_fetch() - No columns requested");var o="";for(var u in t.columns)o+=t.columns[u]+",";o=o.substring(0,o.length-1);var a=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.dataset_id,data:{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},success:function(e){var t=new Array(s);for(var r=0;r<s;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var o in i){var u=i[o];u!==undefined&&u!=2147483647&&t[o].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)}})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})}),define("plugin/models/chart",["plugin/models/groups"],function(e){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(t){this.groups=new e,this.settings=new Backbone.Model},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state",e),this.set("state_info",t),this.trigger("set:state"),console.debug("Chart:state() - "+t+" ("+e+")")}})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group","mvc/visualization/visualization-model"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;var t=e.attributes.type;if(!t)return console.debug("Storage::load() - Chart type not provided. Invalid format."),!1;var r=this.app.types.get(t);if(!r)return console.debug("Storage::load() - Chart type not supported. Please re-configure the chart. Resetting chart."),!1;console.debug("Storage::load() - Loading chart type "+t+"."),this.chart.definition=r,this.chart.set(e.attributes),this.chart.state("ok","Loading saved visualization..."),this.chart.settings.set(e.settings);for(var i in e.groups)this.chart.groups.add(new n(e.groups[i]));return this.chart.set("modified",!1),!0}})}),define("utils/deferred",["utils/utils"],function(e){return Backbone.Model.extend({queue:[],process:{},counter:0,initialize:function(){this.on("refresh",function(){if(this.queue.length>0&&this.ready()){var e=this.queue[0];this.queue.splice(0,1),e&&e()}})},execute:function(e){this.queue.push(e),this.trigger("refresh")},register:function(){var t=e.uuid();return this.process[t]=!0,this.counter++,console.debug("Deferred:register() - Registering "+t),t},done:function(e){this.process[e]&&(delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh"))},reset:function(){this.queue=[]},ready:function(){return this.counter==0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({container_list:[],canvas_list:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,100),this._createContainer("div");var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("set:state",function(){var e=r.$el.find("#info"),t=r.$el.find(".charts-viewport-container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var i=r.chart.get("state");switch(i){case"ok":e.hide(),t.show();break;case"failed":n.addClass("icon fa fa-warning"),t.hide();break;default:n.addClass("icon fa fa-spinner fa-spin"),t.show()}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_createContainer:function(e,t){t=t||1;for(var n in this.container_list)this.container_list[n].remove();this.container_list=[],this.canvas_list=[];for(var n=0;n<t;n++){var r=$(this._templateContainer(e,parseInt(100/t)));this.$el.append(r),this.container_list[n]=r,this.canvas_list[n]=r.find(".charts-viewport-canvas").attr("id")}},_draw:function(e){var t=this,n=this.app.deferred.register(),r=e.get("type");this.chart_definition=e.definition;var i=1;e.settings.get("use_panels")==="true"&&(i=e.groups.length),this._createContainer(this.chart_definition.tag,i),e.state("wait","Please wait...");if(!this.chart_definition.execute||this.chart_definition.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+this.app.chartPath(r)+"/wrapper"],function(r){if(t.chart_definition.execute)t.app.jobs.request(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})},function(){this.app.deferred.done(n)});else var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){n++;for(var i in r.chart_definition.columns)t+=i+"_"+n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t={groups:[]};this.chart_definition.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var r=0,i=this;return e.groups.each(function(e){var s={};for(var o in i.chart_definition.columns){var u=i.chart_definition.columns[o];s[o]=n.merge({index:e.get(o)},u)}t.groups.push({key:++r+":"+e.get("key"),columns:s})}),t},_template:function(){return'<div class="charts-viewport"><div id="info" class="info"><span id="icon" class="icon"/><span id="text" class="text" /></div></div>'},_templateContainer:function(e,t){return'<div class="charts-viewport-container" style="width:'+t+'%;">'+'<div id="menu"/>'+"<"+e+' id="'+n.uuid()+'" class="charts-viewport-canvas">'+"</div>"}})}),define("plugin/library/screenshot",["libs/underscore"],function(e){function t(e){e.$el.find("svg").length>0?r(e):n(e)}function n(e){try{var t=e.$el.find(".jqplot-target"),n=t.jqplotToImageStr({});n&&(window.location.href=n.replace("image/png","image/octet-stream"))}catch(r){console.debug("FAILED - Screenshot::_fromCanvas() - "+r),e.error&&e.error("Please reduce your chart to a single panel and try again.")}}function r(e){var t=e.$el,n=e.url,r=e.name,s=new XMLSerializer,o=document.createElement("canvas"),u=$(o),a=t.find("svg").length,f=t.find("svg").first(),l=parseInt(f.css("height")),c=parseInt(f.css("width"));u.attr("width",c*a),u.attr("height",l),(!o.getContext||!o.getContext("2d"))&&alert("Your browser doesn't support this feature, please use a modern browser");var h=o.getContext("2d"),p=0;t.find("svg").each(function(){var e=$(this);e.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:c,height:l});var t=s.serializeToString(this);h.drawSvg(t,p,0,c,l),p+=c}),window.location.href=i(o,o.getContext("2d"),"white").replace("image/png","image/octet-stream")}function i(e,t,n){var r=e.width,i=e.height,s;if(n){s=t.getImageData(0,0,r,i);var o=t.globalCompositeOperation;t.globalCompositeOperation="destination-over",t.fillStyle=n,t.fillRect(0,0,r,i)}var u=e.toDataURL("image/png");return n&&(t.clearRect(0,0,r,i),t.putImageData(s,0,0),t.globalCompositeOperation=o),u}function s(e){window.location.href="data:none/none;base64,"+btoa(a(e).string)}function o(e){for(var t in document.styleSheets){var n=document.styleSheets[t],r=n.cssRules;if(r)for(var i=0,s=r.length;i<s;i++)try{e.find(r[i].selectorText).each(function(e,t){t.style.cssText+=r[i].style.cssText})}catch(o){}}}function u(e){var t=a(e),n={filename:name||"chart",type:"application/pdf",height:t.height,width:t.width,scale:2,svg:t.string},r=$("body"),i=r.find("#viewport-form");i.length===0&&(i=$("<form>",{id:"viewport-form",method:"post",action:"http://export.highcharts.com/",display:"none"}),r.append(i)),i.empty();for(name in n){var s=$("<input/>",{type:"hidden",name:name,value:n[name]});i.append(s)}try{i.submit()}catch(o){console.log(o)}}function a(e){if(e.$el.find("svg").length==0&&e.error){e.error("No SVG found. This chart type does not support SVG/PDF export.");return}var t=e.$el,n=t.find("svg").length,r=parseInt(t.find("svg").first().css("height")),i=parseInt(t.find("svg").first().css("width")),s=new XMLSerializer,u=$("<svg/>");u.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:i*n,height:r});var a="",f=0;return t.find("svg").each(function(){var e=$(this).clone();o(e);var t=$('<g transform="translate('+f+', 0)">');t.append(e.find("g").first()),u.append(t),f+=i}),{string:s.serializeToString(u[0]),height:r,width:i}}return{createPNG:t,createSVG:s,createPDF:u}}),define("plugin/views/viewer",["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-portlet","plugin/views/viewport","plugin/library/screenshot"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,s){this.app=e,this.chart=this.app.chart,this.viewport_view=new r(e);var o=this;this.message=new t.Message;var u=new t.ButtonMenu({icon:"fa-camera",title:"Screenshot",tooltip:"Download as PNG, SVG or PDF file"});u.addMenu({id:"button-png",title:"Save as PNG",icon:"fa-file",onclick:function(){o._wait(o.chart,function(){i.createPNG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-svg",title:"Save as SVG",icon:"fa-file-text-o",onclick:function(){o._wait(o.chart,function(){i.createSVG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-png",title:"Save as PDF",icon:"fa-file-o",onclick:function(){o.app.modal.show({title:"Send chart data for PDF creation",body:"Galaxy does not provide integrated PDF export scripts. You may click 'Continue' to create the PDF by using a 3rd party service (https://export.highcharts.com)",buttons:{Cancel:function(){o.app.modal.hide()},Continue:function(){o.app.modal.hide(),o._wait(o.chart,function(){i.createPDF({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}})}}),this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",scrollable:!1,operations:{edit_button:new t.ButtonIcon({icon:"fa-edit",tooltip:"Customize this chart",title:"Editor",onclick:function(){o._wait(o.chart,function(){o.app.go("editor")})}}),picture_button_menu:u}}),this.portlet.append(this.message.$el),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var o=this;this.chart.on("change:title",function(){o._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){this.app.deferred.ready()?t():this.message.update({message:"Your chart is currently being processed. Please wait and try again."})}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{title_new:"",operations:null,onnew:null,max:null,onchange:null},initialize:function(t){this.visible=!1,this.$nav=null,this.$content=null,this.first_tab=null,this.current_id=null,this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},size:function(){return _.size(this.list)},current:function(){return this.$el.find(".tab-pane.active").attr("id")},add:function(e){var t=this,n=e.id,r=$(this._template_tab(e)),i=$(this._template_tab_content(e));this.list[n]=e.ondel?!0:!1,this.options.onnew?this.$nav.find("#new-tab").before(r):this.$nav.append(r),i.append(e.$el),this.$content.append(i),this.size()==1&&(r.addClass("active"),i.addClass("active"),this.first_tab=n),this.options.max&&this.size()>=this.options.max&&this.$el.find("#new-tab").hide();if(e.ondel){var s=r.find("#delete");s.tooltip({title:"Delete this tab",placement:"bottom",container:t.$el}),s.on("click",function(){return s.tooltip("destroy"),t.$el.find(".tooltip").remove(),e.ondel(),!1})}r.on("click",function(r){r.preventDefault(),e.onclick?e.onclick():t.show(n)}),this.current_id||(this.current_id=n)},del:function(e){this.$el.find("#tab-"+e).remove(),this.$el.find("#"+e).remove(),this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab),this.list[e]&&delete this.list[e],this.size()<this.options.max&&this.$el.find("#new-tab").show()},delRemovable:function(){for(var e in this.list)this.del(e)},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&(this.$el.find("#tab-"+this.current_id).removeClass("active"),this.$el.find("#"+this.current_id).removeClass("active"),this.$el.find("#tab-"+e).addClass("active"),this.$el.find("#"+e).addClass("active"),this.current_id=e),this.options.onchange&&this.options.onchange(e)},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.$el.find("#tab-title-text-"+e);return t&&n.html(t),n.html()},retitle:function(e){var t=0;for(var n in this.list)this.title(n,++t+": "+e)},_template:function(e){return'<div class="ui-tabs tabbable tabs-left"><ul id="tab-navigation" class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div id="tab-content" class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i class="ui-tabs-add fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="tab-'+e.id+'" class="tab-element">'+'<a id="tab-title-link-'+e.id+'" title="" href="#'+e.id+'" data-original-title="">'+'<span id="tab-title-text-'+e.id+'" class="tab-title-text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" class="ui-tabs-delete fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("mvc/ui/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null,cls:"ui-table",cls_tr:""},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=this._row()},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},append:function(e,t){this._commit(e,t,!1)},prepend:function(e,t){this._commit(e,t,!0)},get:function(e){return this.$el.find("#"+e)},del:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},delAll:function(){this.$tbody.empty(),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t,n){this.del(e),this.row.attr("id",e),n?this.$tbody.prepend(this.row):this.$tbody.append(this.row),t&&(this.row.hide(),this.row.fadeIn()),this.row=this._row(),this.row_count++,this._refresh()},_row:function(){return $('<tr class="'+this.options.cls_tr+'"></tr>')},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n!=""&&n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="'+e.cls+'">'+"<thead></thead>"+"<tbody></tbody>"+"</table>"+"<tmessage>"+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(e){s.group.set("key",e)}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.chart.definition;this.table.delAll();var s={};for(var o in i.columns){var u=i.columns[o];if(!u){console.debug("Group::_refreshTable() - Skipping column definition.");continue}var a=new t.Select.View({id:"select_"+o,wait:!0}),f=u.title;u.is_unique&&(f+=" (all data labels)"),this.table.add(f,"25%"),this.table.add(a.$el),this.table.append(o),s[o]=a}this.chart.state("wait","Loading metadata...");var l=this.app.deferred.register(),c={id:e,success:function(e){for(var t in s)r._addRow(t,e,s,i.columns[t]);r.chart.state("ok","Metadata initialized..."),r.app.deferred.done(l)}};this.app.datasets.request(c)},_addRow:function(e,t,n,r){var i=this,s=r.is_label,o=r.is_auto,u=r.is_numeric,a=r.is_unique,f=r.is_zero,l=[],c=n[e];o&&l.push({label:"Column: Row Number",value:"auto"}),f&&l.push({label:"Column: None",value:"zero"});var h=t.metadata_column_types;for(var p in h){var d=!1;h[p]=="int"||h[p]=="float"?d=u:d=s,d&&l.push({label:"Column: "+(parseInt(p)+1)+" ["+h[p]+"]",value:p})}c.update(l),a&&this.chart.groups.first()&&this.group.set(e,this.chart.groups.first().get(e));if(!c.exists(this.group.get(e))){var v=c.first();console.debug('Group()::_addRow() - Switching model value from "'+this.group.get(e)+'" to "'+v+'".'),this.group.set(e,v)}c.value(this.group.get(e)),this.group.off("change:"+e),this.group.on("change:"+e,function(){c.value(i.group.get(e))}),c.setOnChange(function(t){a?i.chart.groups.each(function(n){n.set(e,t)}):i.group.set(e,t),i.chart.set("modified",!0)}),c.show()},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){var r=Backbone.View.extend({optionsDefault:{title:"",content:"",mode:""},list:[],initialize:function(r,i){this.app=r,this.options=n.merge(i,this.optionsDefault),this.table_title=new t.Label({title:this.options.title}),this.table=new e.View({content:this.options.content});var s=$('<div class="ui-table-form"/>');this.options.title&&s.append(n.wrap(this.table_title.$el)),s.append(n.wrap(this.table.$el)),this.setElement(s)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.delAll(),this.list=[];for(var n in e)this._add(e[n].id||n,e[n],t);for(var n in this.list)this.list[n].trigger("change")},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:"field-"+e,placeholder:n.placeholder,value:r.get(e),onchange:function(t){r.set(e,t)}});break;case"radiobutton":s=new t.RadioButton.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"select":s=new t.Select.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"dataset":s=new t.Select.View({id:"field-"+e,onchange:function(t){r.set(e,t)}}),i.app.datasets.on("all",function(){var t=[];i.app.datasets.each(function(e){e.get("datatype_id")==n.data&&t.push({value:e.get("id"),label:e.get("name")})}),s.update(t),r.get(e)||r.set(e,s.first()),s.value(r.get(e))}),i.app.datasets.trigger("all.datasets");break;case"textarea":s=new t.Textarea({id:"field-"+e,onchange:function(){r.set(e,s.value())}});break;case"separator":s=$("<div/>");break;default:s=new t.Input({id:"field-"+e,placeholder:n.placeholder,type:n.type,onchange:function(){r.set(e,s.value())}})}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),n.info&&u.append('<div class="ui-table-form-info">'+n.info+"</div>"),this.options.style=="bold"?(this.table.add((new t.Label({title:n.title,cls:"form-label"})).$el),this.table.add(u)):(this.table.add('<span class="ui-table-form-title">'+n.title+"</span>","25%"),this.table.add(u))}else this.table.add('<div class="ui-table-form-separator">'+n.title+":<div/>"),this.table.add($("<div/>"));this.table.append(e),n.hide&&this.table.get(e).hide()}});return{View:r}}),define("plugin/views/settings",["mvc/ui/ui-misc","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View(e,{title:"Configuration",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refresh()})},_refresh:function(){var e=this.chart.definition;if(!e)return;this.form.title(e.category+" - "+e.title+":"),this.form.update(e.settings,this.chart.settings)}})}),define("plugin/views/types",["utils/utils","mvc/ui/ui-misc"],function(e,t){return Backbone.View.extend({optionsDefault:{onchange:null,ondblclick:null},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(n,r){var i=this;this.app=n,this.options=e.merge(r,this.optionsDefault);var s=$('<div class="charts-grid"/>');s.append(e.wrap((new t.Label({title:"How many data points would you like to analyze?"})).$el)),this.library=new t.RadioButton.View({data:[{label:"Few (<500)",value:"small"},{label:"Some (<10k)",value:"medium"},{label:"Many (>10k)",value:"large"}],onchange:function(e){i._filter(e)}}),s.append(e.wrap(this.library.$el)),this.setElement(s),this._render(),this.library.value("small"),this.library.trigger("change")},value:function(e){var t=this.$el.find(".current").attr("id");e!==undefined&&(this.$el.find(".current").removeClass("current"),this.$el.find("#"+e).addClass("current"));var n=this.$el.find(".current").attr("id");return n===undefined?null:(n!=t&&this.options.onchange&&this.options.onchange(e),n)},_filter:function(e){this.$el.find(".header").hide();var t=this.app.types.attributes;for(var n in t){var r=t[n],i=this.$el.find("#"+n),s=this.$el.find("#types-header-"+this.categories_index[r.category]),o=r.keywords||"";o.indexOf(e)>=0?(i.show(),s.show()):i.hide()}},_render:function(){this.categories={},this.categories_index={};var e=0,t=this.app.types.attributes;for(var n in t){var r=t[n],i=r.category;this.categories[i]||(this.categories[i]={},this.categories_index[i]=e++),this.categories[i][n]=r}for(var i in this.categories){var s=$('<div style="clear: both;"/>');s.append(this._template_header({id:"types-header-"+this.categories_index[i],title:i}));for(var n in this.categories[i]){var r=this.categories[i][n],o=r.title+" ("+r.library+")";r.zoomable&&(o='<span class="fa fa-search-plus"/>'+o),s.append(this._template_item({id:n,title:o,url:config.app_root+"charts/"+this.app.chartPath(n)+"/logo.png"}))}this.$el.append(s)}},_onclick:function(e){var t=this.value(),n=$(e.target).closest(".item").attr("id");n!=""&&n&&t!=n&&this.value(n)},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_template_header:function(e){return'<div id="'+e.id+'" class="header">'+"• "+e.title+"<div>"},_template_item:function(e){return'<div id="'+e.id+'" class="item">'+'<img class="image" src="'+e.url+'">'+'<div class="title">'+e.title+"</div>"+"<div>"}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","mvc/ui/ui-misc","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings","plugin/views/types"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({initialize:function(i,s){var o=this;this.app=i,this.chart=this.app.chart,this.message=new t.Message,this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new t.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){o._saveChart()}}),back:new t.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Cancel",onclick:function(){o.app.go("viewer"),o.app.storage.load()}})}}),this.types=new a(i,{onchange:function(e){var t=o.app.types.get(e);t||console.debug("FAILED - Editor::onchange() - Chart type not supported."),o.chart.definition=t,o.chart.settings.clear(),o.chart.set({type:e}),o.chart.set("modified",!0),console.debug("Editor::onchange() - Switched chart type.")},ondblclick:function(e){o._saveChart()}}),this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=o._addGroupModel();o.tabs.show(e.id)}}),this.title=new t.Input({placeholder:"Chart title",onchange:function(){o.chart.set("title",o.title.value())}});var f=$("<div/>");f.append(r.wrap((new t.Label({title:"Provide a chart title:"})).$el)),f.append(r.wrap(this.title.$el)),f.append(r.wrap(this.types.$el)),this.tabs.add({id:"main",title:"Start",$el:f}),this.settings=new u(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.message.$el),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var o=this;this.chart.on("change:title",function(e){o._refreshTitle()}),this.chart.on("change:type",function(e){o.types.value(e.get("type"))}),this.chart.on("reset",function(e){o._resetChart()}),this.app.chart.on("redraw",function(e){o.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){o._addGroup(e)}),this.app.chart.groups.on("remove",function(e){o._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){o._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){o._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Data label"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new s({id:r.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new o(this.app,{group:e});this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",r.uuid()),this.chart.set("type","nvd3_bar"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.types.value(),title:this.title.value(),date:r.time()});if(this.chart.groups.length==0){this.message.update({message:"Please select data columns before drawing the chart."});var e=this._addGroupModel();this.tabs.show(e.id);return}var t=this,n=!0,i=this.chart.definition;this.chart.groups.each(function(e){if(!n)return;for(var r in i.columns)if(e.attributes[r]=="null"){t.message.update({status:"danger",message:"This chart type requires column types not found in your tabular file."}),t.tabs.show(e.id),n=!1;return}});if(!n)return;this.app.go("viewer");var t=this;this.app.deferred.execute(function(){t.app.storage.save(),t.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e4,query_timeout:100}})}),define("plugin/charts/forms/default",[],function(){return{title:"",category:"",library:"",tag:"",keywords:"",settings:{separator_x:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["x_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["x_axis_precision"]}},{label:"Float",value:"f",operations:{show:["x_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["x_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["x_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["x_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["x_axis_precision"]}}]},x_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_y:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["y_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["y_axis_precision"]}},{label:"Float",value:"f",operations:{show:["y_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["y_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["y_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["y_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["y_axis_precision"]}}]},y_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{title:"Use multi-panels",info:"Would you like to separate your data into individual panels?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),function(){function t(e,t){return(new Date(t,e+1,0)).getDate()}function n(e,t,n){return function(r,i,s){var o=e(r),u=[];o<r&&t(o);if(s>1)while(o<i){var a=new Date(+o);n(a)%s===0&&u.push(a),t(o)}else while(o<i)u.push(new Date(+o)),t(o);return u}}var e=window.nv||{};e.version="1.1.15b",e.dev=!0,window.nv=e,e.tooltip=e.tooltip||{},e.utils=e.utils||{},e.models=e.models||{},e.charts={},e.graphs=[],e.logs={},e.dispatch=d3.dispatch("render_start","render_end"),e.dev&&(e.dispatch.on("render_start",function(t){e.logs.startTime=+(new Date)}),e.dispatch.on("render_end",function(t){e.logs.endTime=+(new Date),e.logs.totalTime=e.logs.endTime-e.logs.startTime,e.log("total",e.logs.totalTime)})),e.log=function(){if(e.dev&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(e.dev&&typeof console.log=="function"&&Function.prototype.bind){var t=Function.prototype.bind.call(console.log,console);t.apply(console,arguments)}return arguments[arguments.length-1]},e.render=function(n){n=n||1,e.render.active=!0,e.dispatch.render_start(),setTimeout(function(){var t,r;for(var i=0;i<n&&(r=e.render.queue[i]);i++)t=r.generate(),typeof r.callback==typeof Function&&r.callback(t),e.graphs.push(t);e.render.queue.splice(0,i),e.render.queue.length?setTimeout(arguments.callee,0):(e.dispatch.render_end(),e.render.active=!1)},0)},e.render.active=!1,e.render.queue=[],e.addGraph=function(t){typeof arguments[0]==typeof Function&&(t={generate:arguments[0],callback:arguments[1]}),e.render.queue.push(t),e.render.active||e.render()},e.identity=function(e){return e},e.strip=function(e){return e.replace(/(\s|&)/g,"")},d3.time.monthEnd=function(e){return new Date(e.getFullYear(),e.getMonth(),0)},d3.time.monthEnds=n(d3.time.monthEnd,function(e){e.setUTCDate(e.getUTCDate()+1),e.setDate(t(e.getMonth()+1,e.getFullYear()))},function(e){return e.getMonth()}),e.interactiveGuideline=function(){function c(o){o.each(function(o){function g(){var e=d3.mouse(this),n=e[0],r=e[1],o=!0,a=!1;l&&(n=d3.event.offsetX,r=d3.event.offsetY,d3.event.target.tagName!=="svg"&&(o=!1),d3.event.target.className.baseVal.match("nv-legend")&&(a=!0)),o&&(n-=i.left,r-=i.top);if(n<0||r<0||n>p||r>d||d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined||a){if(l&&d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined&&d3.event.relatedTarget.className.match(t.nvPointerEventsClass))return;u.elementMouseout({mouseX:n,mouseY:r}),c.renderGuideLine(null);return}var f=s.invert(n);u.elementMousemove({mouseX:n,mouseY:r,pointXValue:f}),d3.event.type==="dblclick"&&u.elementDblclick({mouseX:n,mouseY:r,pointXValue:f})}var h=d3.select(this),p=n||960,d=r||400,v=h.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([o]),m=v.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");m.append("g").attr("class","nv-interactiveGuideLine");if(!f)return;f.on("mousemove",g,!0).on("mouseout",g,!0).on("dblclick",g),c.renderGuideLine=function(t){if(!a)return;var n=v.select(".nv-interactiveGuideLine").selectAll("line").data(t!=null?[e.utils.NaNtoZero(t)]:[],String);n.enter().append("line").attr("class","nv-guideline").attr("x1",function(e){return e}).attr("x2",function(e){return e}).attr("y1",d).attr("y2",0),n.exit().remove()}})}var t=e.models.tooltip(),n=null,r=null,i={left:0,top:0},s=d3.scale.linear(),o=d3.scale.linear(),u=d3.dispatch("elementMousemove","elementMouseout","elementDblclick"),a=!0,f=null,l=navigator.userAgent.indexOf("MSIE")!==-1;return c.dispatch=u,c.tooltip=t,c.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.left=typeof e.left!="undefined"?e.left:i.left,c):i},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.xScale=function(e){return arguments.length?(s=e,c):s},c.showGuideLine=function(e){return arguments.length?(a=e,c):a},c.svgContainer=function(e){return arguments.length?(f=e,c):f},c},e.interactiveBisect=function(e,t,n){if(!e instanceof Array)return null;typeof n!="function"&&(n=function(e,t){return e.x});var r=d3.bisector(n).left,i=d3.max([0,r(e,t)-1]),s=n(e[i],i);typeof s=="undefined"&&(s=i);if(s===t)return i;var o=d3.min([i+1,e.length-1]),u=n(e[o],o);return typeof u=="undefined"&&(u=o),Math.abs(u-t)>=Math.abs(s-t)?i:o},e.nearestValueIndex=function(e,t,n){var r=Infinity,i=null;return e.forEach(function(e,s){var o=Math.abs(t-e);o<=r&&o<n&&(r=o,i=s)}),i},function(){window.nv.tooltip={},window.nv.models.tooltip=function(){function y(){if(a){var e=d3.select(a);e.node().tagName!=="svg"&&(e=e.select("svg"));var t=e.node()?e.attr("viewBox"):null;if(t){t=t.split(" ");var n=parseInt(e.style("width"))/t[2];l.left=l.left*n,l.top=l.top*n}}}function b(e){var t;a?t=d3.select(a):t=d3.select("body");var n=t.select(".nvtooltip");return n.node()===null&&(n=t.append("div").attr("class","nvtooltip "+(u?u:"xy-tooltip")).attr("id",h)),n.node().innerHTML=e,n.style("top",0).style("left",0).style("opacity",0),n.selectAll("div, table, td, tr").classed(p,!0),n.classed(p,!0),n.node()}function w(){if(!c)return;if(!g(n))return;y();var t=l.left,u=o!=null?o:l.top,h=b(m(n));f=h;if(a){var p=a.getElementsByTagName("svg")[0],d=p?p.getBoundingClientRect():a.getBoundingClientRect(),v={left:0,top:0};if(p){var E=p.getBoundingClientRect(),S=a.getBoundingClientRect(),x=E.top;if(x<0){var T=a.getBoundingClientRect();x=Math.abs(x)>T.height?0:x}v.top=Math.abs(x-S.top),v.left=Math.abs(E.left-S.left)}t+=a.offsetLeft+v.left-2*a.scrollLeft,u+=a.offsetTop+v.top-2*a.scrollTop}return s&&s>0&&(u=Math.floor(u/s)*s),e.tooltip.calcTooltipPosition([t,u],r,i,h),w}var t=null,n=null,r="w",i=50,s=25,o=null,u=null,a=null,f=null,l={left:null,top:null},c=!0,h="nvtooltip-"+Math.floor(Math.random()*1e5),p="nv-pointer-events-none",d=function(e,t){return e},v=function(e){return e},m=function(e){if(t!=null)return t;if(e==null)return"";var n=d3.select(document.createElement("table")),r=n.selectAll("thead").data([e]).enter().append("thead");r.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(v(e.value));var i=n.selectAll("tbody").data([e]).enter().append("tbody"),s=i.selectAll("tr").data(function(e){return e.series}).enter().append("tr").classed("highlight",function(e){return e.highlight});s.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(e){return e.color}),s.append("td").classed("key",!0).html(function(e){return e.key}),s.append("td").classed("value",!0).html(function(e,t){return d(e.value,t)}),s.selectAll("td").each(function(e){if(e.highlight){var t=d3.scale.linear().domain([0,1]).range(["#fff",e.color]),n=.6;d3.select(this).style("border-bottom-color",t(n)).style("border-top-color",t(n))}});var o=n.node().outerHTML;return e.footer!==undefined&&(o+="<div class='footer'>"+e.footer+"</div>"),o},g=function(e){return e&&e.series&&e.series.length>0?!0:!1};return w.nvPointerEventsClass=p,w.content=function(e){return arguments.length?(t=e,w):t},w.tooltipElem=function(){return f},w.contentGenerator=function(e){return arguments.length?(typeof e=="function"&&(m=e),w):m},w.data=function(e){return arguments.length?(n=e,w):n},w.gravity=function(e){return arguments.length?(r=e,w):r},w.distance=function(e){return arguments.length?(i=e,w):i},w.snapDistance=function(e){return arguments.length?(s=e,w):s},w.classes=function(e){return arguments.length?(u=e,w):u},w.chartContainer=function(e){return arguments.length?(a=e,w):a},w.position=function(e){return arguments.length?(l.left=typeof e.left!="undefined"?e.left:l.left,l.top=typeof e.top!="undefined"?e.top:l.top,w):l},w.fixedTop=function(e){return arguments.length?(o=e,w):o},w.enabled=function(e){return arguments.length?(c=e,w):c},w.valueFormatter=function(e){return arguments.length?(typeof e=="function"&&(d=e),w):d},w.headerFormatter=function(e){return arguments.length?(typeof e=="function"&&(v=e),w):v},w.id=function(){return h},w},e.tooltip.show=function(t,n,r,i,s,o){var u=document.createElement("div");u.className="nvtooltip "+(o?o:"xy-tooltip");var a=s;if(!s||s.tagName.match(/g|svg/i))a=document.getElementsByTagName("body")[0];u.style.left=0,u.style.top=0,u.style.opacity=0,u.innerHTML=n,a.appendChild(u),s&&(t[0]=t[0]-s.scrollLeft,t[1]=t[1]-s.scrollTop),e.tooltip.calcTooltipPosition(t,r,i,u)},e.tooltip.findFirstNonSVGParent=function(e){while(e.tagName.match(/^g|svg$/i)!==null)e=e.parentNode;return e},e.tooltip.findTotalOffsetTop=function(e,t){var n=t;do isNaN(e.offsetTop)||(n+=e.offsetTop);while(e=e.offsetParent);return n},e.tooltip.findTotalOffsetLeft=function(e,t){var n=t;do isNaN(e.offsetLeft)||(n+=e.offsetLeft);while(e=e.offsetParent);return n},e.tooltip.calcTooltipPosition=function(t,n,r,i){var s=parseInt(i.offsetHeight),o=parseInt(i.offsetWidth),u=e.utils.windowSize().width,a=e.utils.windowSize().height,f=window.pageYOffset,l=window.pageXOffset,c,h;a=window.innerWidth>=document.body.scrollWidth?a:a-16,u=window.innerHeight>=document.body.scrollHeight?u:u-16,n=n||"s",r=r||20;var p=function(t){return e.tooltip.findTotalOffsetTop(t,h)},d=function(t){return e.tooltip.findTotalOffsetLeft(t,c)};switch(n){case"e":c=t[0]-o-r,h=t[1]-s/2;var v=d(i),m=p(i);v<l&&(c=t[0]+r>l?t[0]+r:l-v+c),m<f&&(h=f-m+h),m+s>f+a&&(h=f+a-m+h-s);break;case"w":c=t[0]+r,h=t[1]-s/2;var v=d(i),m=p(i);v+o>u&&(c=t[0]-o-r),m<f&&(h=f+5),m+s>f+a&&(h=f+a-m+h-s);break;case"n":c=t[0]-o/2-5,h=t[1]+r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),m+s>f+a&&(h=f+a-m+h-s);break;case"s":c=t[0]-o/2,h=t[1]-s-r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),f>m&&(h=f);break;case"none":c=t[0],h=t[1]-r;var v=d(i),m=p(i)}return i.style.left=c+"px",i.style.top=h+"px",i.style.opacity=1,i.style.position="absolute",i},e.tooltip.cleanup=function(){var e=document.getElementsByClassName("nvtooltip"),t=[];while(e.length)t.push(e[0]),e[0].style.transitionDelay="0 !important",e[0].style.opacity=0,e[0].className="nvtooltip-pending-removal";setTimeout(function(){while(t.length){var e=t.pop();e.parentNode.removeChild(e)}},500)}}(),e.utils.windowSize=function(){var e={width:640,height:480};return document.body&&document.body.offsetWidth&&(e.width=document.body.offsetWidth,e.height=document.body.offsetHeight),document.compatMode=="CSS1Compat"&&document.documentElement&&document.documentElement.offsetWidth&&(e.width=document.documentElement.offsetWidth,e.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(e.width=window.innerWidth,e.height=window.innerHeight),e},e.utils.windowResize=function(e){if(e===undefined)return;var t=window.onresize;window.onresize=function(n){typeof t=="function"&&t(n),e(n)}},e.utils.getColor=function(t){return arguments.length?Object.prototype.toString.call(t)==="[object Array]"?function(e,n){return e.color||t[n%t.length]}:t:e.utils.defaultColor()},e.utils.defaultColor=function(){var e=d3.scale.category20().range();return function(t,n){return t.color||e[n%e.length]}},e.utils.customTheme=function(e,t,n){t=t||function(e){return e.key},n=n||d3.scale.category20().range();var r=n.length;return function(i,s){var o=t(i);return r||(r=n.length),typeof e[o]!="undefined"?typeof e[o]=="function"?e[o]():e[o]:n[--r]}},e.utils.pjax=function(t,n){function r(r){d3.html(r,function(r){var i=d3.select(n).node();i.parentNode.replaceChild(d3.select(r).select(n).node(),i),e.utils.pjax(t,n)})}d3.selectAll(t).on("click",function(){history.pushState(this.href,this.textContent,this.href),r(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&r(d3.event.state)})},e.utils.calcApproxTextWidth=function(e){if(typeof e.style=="function"&&typeof e.text=="function"){var t=parseInt(e.style("font-size").replace("px","")),n=e.text().length;return n*t*.5}return 0},e.utils.NaNtoZero=function(e){return typeof e!="number"||isNaN(e)||e===null||e===Infinity?0:e},e.utils.optionsFunc=function(e){return e&&d3.map(e).forEach(function(e,t){typeof this[e]=="function"&&this[e](t)}.bind(this)),this},e.models.axis=function(){function m(e){return e.each(function(e){var i=d3.select(this),m=i.selectAll("g.nv-wrap.nv-axis").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),y=g.append("g"),b=m.select("g");p!==null?t.ticks(p):(t.orient()=="top"||t.orient()=="bottom")&&t.ticks(Math.abs(s.range()[1]-s.range()[0])/100),b.call(t),v=v||t.scale();var w=t.tickFormat();w==null&&(w=v.tickFormat());var E=b.selectAll("text.nv-axislabel").data([o||null]);E.exit().remove();switch(t.orient()){case"top":E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",0).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+s(e)+",0)"}).select("text").attr("dy","-0.5em").attr("y",-t.tickPadding()).attr("text-anchor","middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+s.range()[t]+",0)"})}break;case"bottom":var T=36,N=30,C=b.selectAll("g").select("text");if(f%360){C.each(function(e,t){var n=this.getBBox().width;n>N&&(N=n)});var k=Math.abs(Math.sin(f*Math.PI/180)),T=(k?k*N:N)+30;C.attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f%360>0?"start":"end")}E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",T).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data([s.domain()[0],s.domain()[s.domain().length-1]]);x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",t.tickPadding()).attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f?f%360>0?"start":"end":"middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"})}c&&C.attr("transform",function(e,t){return"translate(0,"+(t%2==0?"0":"12")+")"});break;case"right":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"begin").attr("transform",l?"rotate(90)":"").attr("y",l?-Math.max(n.right,r)+12:-10).attr("x",l?s.range()[0]/2:t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+s(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",t.tickPadding()).style("text-anchor","start").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}break;case"left":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"end").attr("transform",l?"rotate(-90)":"").attr("y",l?-Math.max(n.left,r)+d:-10).attr("x",l?-s.range()[0]/2:-t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+v(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-t.tickPadding()).attr("text-anchor","end").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}}E.text(function(e){return e}),u&&(t.orient()==="left"||t.orient()==="right")&&(b.selectAll("g").each(function(e,t){d3.select(this).select("text").attr("opacity",1);if(s(e)<s.range()[1]+10||s(e)>s.range()[0]-10)(e>1e-10||e<-1e-10)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0)}),s.domain()[0]==s.domain()[1]&&s.domain()[0]==0&&m.selectAll("g.nv-axisMaxMin").style("opacity",function(e,t){return t?0:1}));if(u&&(t.orient()==="top"||t.orient()==="bottom")){var L=[];m.selectAll("g.nv-axisMaxMin").each(function(e,t){try{t?L.push(s(e)-this.getBBox().width-4):L.push(s(e)+this.getBBox().width+4)}catch(n){t?L.push(s(e)-4):L.push(s(e)+4)}}),b.selectAll("g").each(function(e,t){if(s(e)<L[0]||s(e)>L[1])e>1e-10||e<-1e-10?d3.select(this).remove():d3.select(this).select("text").remove()})}a&&b.selectAll(".tick").filter(function(e){return!parseFloat(Math.round(e.__data__*1e5)/1e6)&&e.__data__!==undefined}).classed("zero",!0),v=s.copy()}),m}var t=d3.svg.axis(),n={top:0,right:0,bottom:0,left:0},r=75,i=60,s=d3.scale.linear(),o=null,u=!0,a=!0,f=0,l=!0,c=!1,h=!1,p=null,d=12;t.scale(s).orient("bottom").tickFormat(function(e){return e});var v;return m.axis=t,d3.rebind(m,t,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.ticks=function(e){return arguments.length?(p=e,m):p},m.height=function(e){return arguments.length?(i=e,m):i},m.axisLabel=function(e){return arguments.length?(o=e,m):o},m.showMaxMin=function(e){return arguments.length?(u=e,m):u},m.highlightZero=function(e){return arguments.length?(a=e,m):a},m.scale=function(e){return arguments.length?(s=e,t.scale(s),h=typeof s.rangeBands=="function",d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m):s},m.rotateYLabel=function(e){return arguments.length?(l=e,m):l},m.rotateLabels=function(e){return arguments.length?(f=e,m):f},m.staggerLabels=function(e){return arguments.length?(c=e,m):c},m.axisLabelDistance=function(e){return arguments.length?(d=e,m):d},m},e.models.historicalBar=function(){function w(E){return E.each(function(w){var E=n-t.left-t.right,S=r-t.top-t.bottom,T=d3.select(this);s.domain(d||d3.extent(w[0].values.map(u).concat(f))),c?s.range(m||[E*.5/w[0].values.length,E*(w[0].values.length-.5)/w[0].values.length]):s.range(m||[0,E]),o.domain(v||d3.extent(w[0].values.map(a).concat(l))).range(g||[S,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=T.selectAll("g.nv-wrap.nv-historicalBar-"+i).data([w[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+i),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-bars"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){y.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",E).attr("height",S),A.attr("clip-path",h?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-bars").selectAll(".nv-bar").data(function(e){return e},function(e,t){return u(e,t)});O.exit().remove();var M=O.enter().append("rect").attr("x",0).attr("y",function(t,n){return e.utils.NaNtoZero(o(Math.max(0,a(t,n))))}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.abs(o(a(t,n))-o(0)))}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).on("mouseover",function(e,t){if(!b)return;d3.select(this).classed("hover",!0),y.elementMouseover({point:e,series:w[0],pos:[s(u(e,t)),o(a(e,t))],pointIndex:t,seriesIndex:0,e:d3.event})}).on("mouseout",function(e,t){if(!b)return;d3.select(this).classed("hover",!1),y.elementMouseout({point:e,series:w[0],pointIndex:t,seriesIndex:0,e:d3.event})}).on("click",function(e,t){if(!b)return;y.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){if(!b)return;y.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("fill",function(e,t){return p(e,t)}).attr("class",function(e,t,n){return(a(e,t)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+n+"-"+t}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).attr("width",E/w[0].values.length*.9),O.attr("y",function(t,n){var r=a(t,n)<0?o(0):o(0)-o(a(t,n))<1?o(0)-1:o(a(t,n));return e.utils.NaNtoZero(r)}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.max(Math.abs(o(a(t,n))-o(0)),1))})}),w}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[],l=[0],c=!1,h=!0,p=e.utils.defaultColor(),d,v,m,g,y=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),b=!0;return w.highlightPoint=function(e,t){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar-0-"+e).classed("hover",t)},w.clearHighlights=function(){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar.hover").classed("hover",!1)},w.dispatch=y,w.options=e.utils.optionsFunc.bind(w),w.x=function(e){return arguments.length?(u=e,w):u},w.y=function(e){return arguments.length?(a=e,w):a},w.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,w):t},w.width=function(e){return arguments.length?(n=e,w):n},w.height=function(e){return arguments.length?(r=e,w):r},w.xScale=function(e){return arguments.length?(s=e,w):s},w.yScale=function(e){return arguments.length?(o=e,w):o},w.xDomain=function(e){return arguments.length?(d=e,w):d},w.yDomain=function(e){return arguments.length?(v=e,w):v},w.xRange=function(e){return arguments.length?(m=e,w):m},w.yRange=function(e){return arguments.length?(g=e,w):g},w.forceX=function(e){return arguments.length?(f=e,w):f},w.forceY=function(e){return arguments.length?(l=e,w):l},w.padData=function(e){return arguments.length?(c=e,w):c},w.clipEdge=function(e){return arguments.length?(h=e,w):h},w.color=function(t){return arguments.length?(p=e.utils.getColor(t),w):p},w.id=function(e){return arguments.length?(i=e,w):i},w.interactive=function(e){return arguments.length?(b=!1,w):b},w},e.models.bullet=function(){function m(e){return e.each(function(e,n){var p=c-t.left-t.right,m=h-t.top-t.bottom,g=d3.select(this),y=i.call(this,e,n).slice().sort(d3.descending),b=s.call(this,e,n).slice().sort(d3.descending),w=o.call(this,e,n).slice().sort(d3.descending),E=u.call(this,e,n).slice(),S=a.call(this,e,n).slice(),x=f.call(this,e,n).slice(),T=d3.scale.linear().domain(d3.extent(d3.merge([l,y]))).range(r?[p,0]:[0,p]),N=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(T.range());this.__chart__=T;var C=d3.min(y),k=d3.max(y),L=y[1],A=g.selectAll("g.nv-wrap.nv-bullet").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),M=O.append("g"),_=A.select("g");M.append("rect").attr("class","nv-range nv-rangeMax"),M.append("rect").attr("class","nv-range nv-rangeAvg"),M.append("rect").attr("class","nv-range nv-rangeMin"),M.append("rect").attr("class","nv-measure"),M.append("path").attr("class","nv-markerTriangle"),A.attr("transform","translate("+t.left+","+t.top+")");var D=function(e){return Math.abs(N(e)-N(0))},P=function(e){return Math.abs(T(e)-T(0))},H=function(e){return e<0?N(e):N(0)},B=function(e){return e<0?T(e):T(0)};_.select("rect.nv-rangeMax").attr("height",m).attr("width",P(k>0?k:C)).attr("x",B(k>0?k:C)).datum(k>0?k:C),_.select("rect.nv-rangeAvg").attr("height",m).attr("width",P(L)).attr("x",B(L)).datum(L),_.select("rect.nv-rangeMin").attr("height",m).attr("width",P(k)).attr("x",B(k)).attr("width",P(k>0?C:k)).attr("x",B(k>0?C:k)).datum(k>0?C:k),_.select("rect.nv-measure").style("fill",d).attr("height",m/3).attr("y",m/3).attr("width",w<0?T(0)-T(w[0]):T(w[0])-T(0)).attr("x",B(w)).on("mouseover",function(){v.elementMouseover({value:w[0],label:x[0]||"Current",pos:[T(w[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:w[0],label:x[0]||"Current"})});var j=m/6;b[0]?_.selectAll("path.nv-markerTriangle").attr("transform",function(e){return"translate("+T(b[0])+","+m/2+")"}).attr("d","M0,"+j+"L"+j+","+ -j+" "+ -j+","+ -j+"Z").on("mouseover",function(){v.elementMouseover({value:b[0],label:S[0]||"Previous",pos:[T(b[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:b[0],label:S[0]||"Previous"})}):_.selectAll("path.nv-markerTriangle").remove(),A.selectAll(".nv-range").on("mouseover",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseover({value:e,label:n,pos:[T(e),m/2]})}).on("mouseout",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseout({value:e,label:n})})}),m}var t={top:0,right:0,bottom:0,left:0},n="left",r=!1,i=function(e){return e.ranges},s=function(e){return e.markers},o=function(e){return e.measures},u=function(e){return e.rangeLabels?e.rangeLabels:[]},a=function(e){return e.markerLabels?e.markerLabels:[]},f=function(e){return e.measureLabels?e.measureLabels:[]},l=[0],c=380,h=30,p=null,d=e.utils.getColor(["#1f77b4"]),v=d3.dispatch("elementMouseover","elementMouseout");return m.dispatch=v,m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(i=e,m):i},m.markers=function(e){return arguments.length?(s=e,m):s},m.measures=function(e){return arguments.length?(o=e,m):o},m.forceX=function(e){return arguments.length?(l=e,m):l},m.width=function(e){return arguments.length?(c=e,m):c},m.height=function(e){return arguments.length?(h=e,m):h},m.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,m):t},m.tickFormat=function(e){return arguments.length?(p=e,m):p},m.color=function(t){return arguments.length?(d=e.utils.getColor(t),m):d},m},e.models.bulletChart=function(){function m(e){return e.each(function(n,h){var g=d3.select(this),y=(a||parseInt(g.style("width"))||960)-i.left-i.right,b=f-i.top-i.bottom,w=this;m.update=function(){m(e)},m.container=this;if(!n||!s.call(this,n,h)){var E=g.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+y/2).attr("y",18+i.top+b/2).text(function(e){return e}),m}g.selectAll(".nv-noData").remove();var S=s.call(this,n,h).slice().sort(d3.descending),x=o.call(this,n,h).slice().sort(d3.descending),T=u.call(this,n,h).slice().sort(d3.descending),N=g.selectAll("g.nv-wrap.nv-bulletChart").data([n]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-bulletWrap"),k.append("g").attr("class","nv-titles"),N.attr("transform","translate("+i.left+","+i.top+")");var A=d3.scale.linear().domain([0,Math.max(S[0],x[0],T[0])]).range(r?[y,0]:[0,y]),O=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(A.range());this.__chart__=A;var M=function(e){return Math.abs(O(e)-O(0))},_=function(e){return Math.abs(A(e)-A(0))},D=k.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(f-i.top-i.bottom)/2+")");D.append("text").attr("class","nv-title").text(function(e){return e.title}),D.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(e){return e.subtitle}),t.width(y).height(b);var P=L.select(".nv-bulletWrap");d3.transition(P).call(t);var H=l||A.tickFormat(y/100),B=L.selectAll("g.nv-tick").data(A.ticks(y/50),function(e){return this.textContent||H(e)}),j=B.enter().append("g").attr("class","nv-tick").attr("transform",function(e){return"translate("+O(e)+",0)"}).style("opacity",1e-6);j.append("line").attr("y1",b).attr("y2",b*7/6),j.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",b*7/6).text(H);var F=d3.transition(B).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1);F.select("line").attr("y1",b).attr("y2",b*7/6),F.select("text").attr("y",b*7/6),d3.transition(B.exit()).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1e-6).remove(),d.on("tooltipShow",function(e){e.key=n.title,c&&v(e,w.parentNode)})}),d3.timer.flush(),m}var t=e.models.bullet(),n="left",r=!1,i={top:5,right:40,bottom:20,left:120},s=function(e){return e.ranges},o=function(e){return e.markers},u=function(e){return e.measures},a=null,f=55,l=null,c=!0,h=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide"),v=function(t,n){var r=t.pos[0]+(n.offsetLeft||0)+i.left,s=t.pos[1]+(n.offsetTop||0)+i.top,o=h(t.key,t.label,t.value,t,m);e.tooltip.show([r,s],o,t.value<0?"e":"w",null,n)};return t.dispatch.on("elementMouseover.tooltip",function(e){d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),m.dispatch=d,m.bullet=t,d3.rebind(m,t,"color"),m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(s=e,m):s},m.markers=function(e){return arguments.length?(o=e,m):o},m.measures=function(e){return arguments.length?(u=e,m):u},m.width=function(e){return arguments.length?(a=e,m):a},m.height=function(e){return arguments.length?(f=e,m):f},m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.tickFormat=function(e){return arguments.length?(l=e,m):l},m.tooltips=function(e){return arguments.length?(c=e,m):c},m.tooltipContent=function(e){return arguments.length?(h=e,m):h},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.cumulativeLineChart=function(){function D(b){return b.each(function(b){function I(e,t){d3.select(D.container).style("cursor","ew-resize")}function q(e,t){M.x=d3.event.x,M.i=Math.round(O.invert(M.x)),nt()}function R(e,t){d3.select(D.container).style("cursor","auto"),x.index=M.i,k.stateChange(x)}function nt(){tt.data([M]);var e=D.transitionDuration();D.transitionDuration(0),D.update(),D.transitionDuration(e)}var L=d3.select(this).classed("nv-chart-"+S,!0),A=this,H=(f||parseInt(L.style("width"))||960)-u.left-u.right,B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom;D.update=function(){L.call(D)},D.container=this,x.disabled=b.map(function(e){return!!e.disabled});if(!T){var j;T={};for(j in x)x[j]instanceof Array?T[j]=x[j].slice(0):T[j]=x[j]}var F=d3.behavior.drag().on("dragstart",I).on("drag",q).on("dragend",R);if(!b||!b.length||!b.filter(function(e){return e.values.length}).length){var U=L.selectAll(".nv-noData").data([N]);return U.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),U.attr("x",u.left+H/2).attr("y",u.top+B/2).text(function(e){return e}),D}L.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();if(!y){var z=b.filter(function(e){return!e.disabled}).map(function(e,n){var r=d3.extent(e.values,t.y());return r[0]<-0.95&&(r[0]=-0.95),[(r[0]-r[1])/(1+r[1]),(r[1]-r[0])/(1+r[0])]}),W=[d3.min(z,function(e){return e[0]}),d3.max(z,function(e){return e[1]})];t.yDomain(W)}else t.yDomain(null);O.domain([0,b[0].values.length-1]).range([0,H]).clamp(!0);var b=P(M.i,b),X=g?"none":"all",V=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([b]),$=V.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),J=V.select("g");$.append("g").attr("class","nv-interactive"),$.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),$.append("g").attr("class","nv-y nv-axis"),$.append("g").attr("class","nv-background"),$.append("g").attr("class","nv-linesWrap").style("pointer-events",X),$.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),$.append("g").attr("class","nv-legendWrap"),$.append("g").attr("class","nv-controlsWrap"),c&&(i.width(H),J.select(".nv-legendWrap").datum(b).call(i),u.top!=i.height()&&(u.top=i.height(),B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom),J.select(".nv-legendWrap").attr("transform","translate(0,"+ -u.top+")"));if(m){var K=[{key:"Re-scale y-axis",disabled:!y}];s.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),J.select(".nv-controlsWrap").datum(K).attr("transform","translate(0,"+ -u.top+")").call(s)}V.attr("transform","translate("+u.left+","+u.top+")"),d&&J.select(".nv-y.nv-axis").attr("transform","translate("+H+",0)");var Q=b.filter(function(e){return e.tempDisabled});V.select(".tempDisabled").remove(),Q.length&&V.append("text").attr("class","tempDisabled").attr("x",H/2).attr("y","-.71em").style("text-anchor","end").text(Q.map(function(e){return e.key}).join(", ")+" values cannot be calculated for this time period."),g&&(o.width(H).height(B).margin({left:u.left,top:u.top}).svgContainer(L).xScale(w),V.select(".nv-interactive").call(o)),$.select(".nv-background").append("rect"),J.select(".nv-background rect").attr("width",H).attr("height",B),t.y(function(e){return e.display.y}).width(H).height(B).color(b.map(function(e,t){return e.color||a(e,t)}).filter(function(e,t){return!b[t].disabled&&!b[t].tempDisabled}));var G=J.select(".nv-linesWrap").datum(b.filter(function(e){return!e.disabled&&!e.tempDisabled}));G.call(t),b.forEach(function(e,t){e.seriesIndex=t});var Y=b.filter(function(e){return!e.disabled&&!!C(e)}),Z=J.select(".nv-avgLinesWrap").selectAll("line").data(Y,function(e){return e.key}),et=function(e){var t=E(C(e));return t<0?0:t>B?B:t};Z.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(e,n){return t.color()(e,e.seriesIndex)}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.style("stroke-opacity",function(e){var t=E(C(e));return t<0||t>B?0:1}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.exit().remove();var tt=G.selectAll(".nv-indexLine").data([M]);tt.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(F),tt.attr("transform",function(e){return"translate("+O(e.i)+",0)"}).attr("height",B),h&&(n.scale(w).ticks(Math.min(b[0].values.length,H/70)).tickSize(-B,0),J.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),d3.transition(J.select(".nv-x.nv-axis")).call(n)),p&&(r.scale(E).ticks(B/36).tickSize(-H,0),d3.transition(J.select(".nv-y.nv-axis")).call(r)),J.select(".nv-background rect").on("click",function(){M.x=d3.mouse(this)[0],M.i=Math.round(O.invert(M.x)),x.index=M.i,k.stateChange(x),nt()}),t.dispatch.on("elementClick",function(e){M.i=e.pointIndex,M.x=O(M.i),x.index=M.i,k.stateChange(x),nt()}),s.dispatch.on("legendClick",function(e,t){e.disabled=!e.disabled,y=!e.disabled,x.rescaleY=y,k.stateChange(x),D.update()}),i.dispatch.on("stateChange",function(e){x.disabled=e.disabled,k.stateChange(x),D.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,f,l,c=[];b.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,D.x()),t.highlightPoint(r,f,!0);var o=n.values[f];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof l=="undefined"&&(l=D.xScale()(D.x()(o,f))),c.push({key:n.key,value:D.y()(o,f),color:a(n,n.seriesIndex)})});if(c.length>2){var h=D.yScale().invert(i.mouseY),p=Math.abs(D.yScale().domain()[0]-D.yScale().domain()[1]),d=.03*p,m=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);m!==null&&(c[m].highlight=!0)}var g=n.tickFormat()(D.x()(s,f),f);o.tooltip.position({left:l+u.left,top:i.mouseY+u.top}).chartContainer(A.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:g,series:c})(),o.renderGuideLine(l)}),o.dispatch.on("elementMouseout",function(e){k.tooltipHide(),t.clearHighlights()}),k.on("tooltipShow",function(e){v&&_(e,A.parentNode)}),k.on("changeState",function(e){typeof e.disabled!="undefined"&&(b.forEach(function(t,n){t.disabled=e.disabled[n]}),x.disabled=e.disabled),typeof e.index!="undefined"&&(M.i=e.index,M.x=O(M.i),x.index=e.index,tt.data([M])),typeof e.rescaleY!="undefined"&&(y=e.rescaleY),D.update()})}),D}function P(e,n){return n.map(function(n,r){if(!n.values)return n;var i=n.values[e];if(i==null)return n;var s=t.y()(i,e);return s<-0.95&&!A?(n.tempDisabled=!0,n):(n.tempDisabled=!1,n.values=n.values.map(function(e,n){return e.display={y:(t.y()(e,n)-s)/(1+s)},e}),n)})}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:30,bottom:50,left:60},a=e.utils.defaultColor(),f=null,l=null,c=!0,h=!0,p=!0,d=!1,v=!0,m=!0,g=!1,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},w,E,S=t.id(),x={index:0,rescaleY:y},T=null,N="No Data Available.",C=function(e){return e.average},k=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),L=0,A=!1;n.orient("bottom").tickPadding(7),r.orient(d?"right":"left"),s.updateState(!1);var O=d3.scale.linear(),M={i:0,x:0},_=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,D);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],k.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){k.tooltipHide(e)}),k.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),D.dispatch=k,D.lines=t,D.legend=i,D.xAxis=n,D.yAxis=r,D.interactiveLayer=o,d3.rebind(D,t,"defined","isArea","x","y","xScale","yScale","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id"),D.options=e.utils.optionsFunc.bind(D),D.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,D):u},D.width=function(e){return arguments.length?(f=e,D):f},D.height=function(e){return arguments.length?(l=e,D):l},D.color=function(t){return arguments.length?(a=e.utils.getColor(t),i.color(a),D):a},D.rescaleY=function(e){return arguments.length?(y=e,D):y},D.showControls=function(e){return arguments.length?(m=e,D):m},D.useInteractiveGuideline=function(e){return arguments.length?(g=e,e===!0&&(D.interactive(!1),D.useVoronoi(!1)),D):g},D.showLegend=function(e){return arguments.length?(c=e,D):c},D.showXAxis=function(e){return arguments.length?(h=e,D):h},D.showYAxis=function(e){return arguments.length?(p=e,D):p},D.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),D):d},D.tooltips=function(e){return arguments.length?(v=e,D):v},D.tooltipContent=function(e){return arguments.length?(b=e,D):b},D.state=function(e){return arguments.length?(x=e,D):x},D.defaultState=function(e){return arguments.length?(T=e,D):T},D.noData=function(e){return arguments.length?(N=e,D):N},D.average=function(e){return arguments.length?(C=e,D):C},D.transitionDuration=function(e){return arguments.length?(L=e,D):L},D.noErrorCheck=function(e){return arguments.length?(A=e,D):A},D},e.models.discreteBar=function(){function E(e){return e.each(function(e){var i=n-t.left-t.right,E=r-t.top-t.bottom,S=d3.select(this);e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var T=p&&d?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0}})});s.domain(p||d3.merge(T).map(function(e){return e.x})).rangeBands(v||[0,i],.1),o.domain(d||d3.extent(d3.merge(T).map(function(e){return e.y}).concat(f))),c?o.range(m||[E-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(m||[E,0]),b=b||s,w=w||o.copy().range([o(0),o(0)]);var N=S.selectAll("g.nv-wrap.nv-discretebar").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-groups"),N.attr("transform","translate("+t.left+","+t.top+")");var A=N.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),A.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),A.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),A.style("stroke-opacity",1).style("fill-opacity",.75);var O=A.selectAll("g.nv-bar").data(function(e){return e.values});O.exit().remove();var M=O.enter().append("g").attr("transform",function(e,t,n){return"translate("+(s(u(e,t))+s.rangeBand()*.05)+", "+o(0)+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),g.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),g.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){g.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){g.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()});M.append("rect").attr("height",0).attr("width",s.rangeBand()*.9/e.length),c?(M.append("text").attr("text-anchor","middle"),O.select("text").text(function(e,t){return h(a(e,t))}).attr("x",s.rangeBand()*.9/2).attr("y",function(e,t){return a(e,t)<0?o(a(e,t))-o(0)+12:-4})):O.selectAll("text").remove(),O.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(e,t){return e.color||l(e,t)}).style("stroke",function(e,t){return e.color||l(e,t)}).select("rect").attr("class",y).attr("width",s.rangeBand()*.9/e.length),O.attr("transform",function(e,t){var n=s(u(e,t))+s.rangeBand()*.05,r=a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t));return"translate("+n+", "+r+")"}).select("rect").attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(d&&d[0]||0))||1)}),b=s.copy(),w=o.copy()}),E}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=!1,h=d3.format(",.2f"),p,d,v,m,g=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),y="discreteBar",b,w;return E.dispatch=g,E.options=e.utils.optionsFunc.bind(E),E.x=function(e){return arguments.length?(u=e,E):u},E.y=function(e){return arguments.length?(a=e,E):a},E.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.xScale=function(e){return arguments.length?(s=e,E):s},E.yScale=function(e){return arguments.length?(o=e,E):o},E.xDomain=function(e){return arguments.length?(p=e,E):p},E.yDomain=function(e){return arguments.length?(d=e,E):d},E.xRange=function(e){return arguments.length?(v=e,E):v},E.yRange=function(e){return arguments.length?(m=e,E):m},E.forceY=function(e){return arguments.length?(f=e,E):f},E.color=function(t){return arguments.length?(l=e.utils.getColor(t),E):l},E.id=function(e){return arguments.length?(i=e,E):i},E.showValues=function(e){return arguments.length?(c=e,E):c},E.valueFormat=function(e){return arguments.length?(h=e,E):h},E.rectClass=function(e){return arguments.length?(y=e,E):y},E},e.models.discreteBarChart=function(){function w(e){return e.each(function(e){var u=d3.select(this),p=this,y=(s||parseInt(u.style("width"))||960)-i.left-i.right,E=(o||parseInt(u.style("height"))||400)-i.top-i.bottom;w.update=function(){g.beforeUpdate(),u.call(w)},w.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var S=u.selectAll(".nv-noData").data([m]);return S.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),S.attr("x",i.left+y/2).attr("y",i.top+E/2).text(function(e){return e}),w}u.selectAll(".nv-noData").remove(),d=t.xScale(),v=t.yScale().clamp(!0);var T=u.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),C=N.append("defs"),k=T.select("g");N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),N.append("g").attr("class","nv-barsWrap"),k.attr("transform","translate("+i.left+","+i.top+")"),l&&k.select(".nv-y.nv-axis").attr("transform","translate("+y+",0)"),t.width(y).height(E);var L=k.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));L.call(t),C.append("clipPath").attr("id","nv-x-label-clip-"+t.id()).append("rect"),k.select("#nv-x-label-clip-"+t.id()+" rect").attr("width",d.rangeBand()*(c?2:1)).attr("height",16).attr("x",-d.rangeBand()/(c?1:2));if(a){n.scale(d).ticks(y/100).tickSize(-E,0),k.select(".nv-x.nv-axis").attr("transform","translate(0,"+(v.range()[0]+(t.showValues()&&v.domain()[0]<0?16:0))+")"),k.select(".nv-x.nv-axis").call(n);var A=k.select(".nv-x.nv-axis").selectAll("g");c&&A.selectAll("text").attr("transform",function(e,t,n){return"translate(0,"+(n%2==0?"5":"17")+")"})}f&&(r.scale(v).ticks(E/36).tickSize(-y,0),k.select(".nv-y.nv-axis").call(r)),k.select(".nv-zeroLine line").attr("x1",0).attr("x2",y).attr("y1",v(0)).attr("y2",v(0)),g.on("tooltipShow",function(e){h&&b(e,p.parentNode)})}),w}var t=e.models.discreteBar(),n=e.models.axis(),r=e.models.axis(),i={top:15,right:10,bottom:50,left:60},s=null,o=null,u=e.utils.getColor(),a=!0,f=!0,l=!1,c=!1,h=!0,p=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},d,v,m="No Data Available.",g=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate"),y=0;n.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(l?"right":"left").tickFormat(d3.format(",.1f"));var b=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=p(i.series.key,a,f,i,w);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+i.left,e.pos[1]+i.top],g.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){g.tooltipHide(e)}),g.on("tooltipHide",function(){h&&e.tooltip.cleanup()}),w.dispatch=g,w.discretebar=t,w.xAxis=n,w.yAxis=r,d3.rebind(w,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","id","showValues","valueFormat"),w.options=e.utils.optionsFunc.bind(w),w.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,w):i},w.width=function(e){return arguments.length?(s=e,w):s},w.height=function(e){return arguments.length?(o=e,w):o},w.color=function(n){return arguments.length?(u=e.utils.getColor(n),t.color(u),w):u},w.showXAxis=function(e){return arguments.length?(a=e,w):a},w.showYAxis=function(e){return arguments.length?(f=e,w):f},w.rightAlignYAxis=function(e){return arguments.length?(l=e,r.orient(e?"right":"left"),w):l},w.staggerLabels=function(e){return arguments.length?(c=e,w):c},w.tooltips=function(e){return arguments.length?(h=e,w):h},w.tooltipContent=function(e){return arguments.length?(p=e,w):p},w.noData=function(e){return arguments.length?(m=e,w):m},w.transitionDuration=function(e){return arguments.length?(y=e,w):y},w},e.models.distribution=function(){function l(e){return e.each(function(e){var a=n-(i==="x"?t.left+t.right:t.top+t.bottom),l=i=="x"?"y":"x",c=d3.select(this);f=f||u;var h=c.selectAll("g.nv-distribution").data([e]),p=h.enter().append("g").attr("class","nvd3 nv-distribution"),d=p.append("g"),v=h.select("g");h.attr("transform","translate("+t.left+","+t.top+")");var m=v.selectAll("g.nv-dist").data(function(e){return e},function(e){return e.key});m.enter().append("g"),m.attr("class",function(e,t){return"nv-dist nv-series-"+t}).style("stroke",function(e,t){return o(e,t)});var g=m.selectAll("line.nv-dist"+i).data(function(e){return e.values});g.enter().append("line").attr(i+"1",function(e,t){return f(s(e,t))}).attr(i+"2",function(e,t){return f(s(e,t))}),m.exit().selectAll("line.nv-dist"+i).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}).style("stroke-opacity",0).remove(),g.attr("class",function(e,t){return"nv-dist"+i+" nv-dist"+i+"-"+t}).attr(l+"1",0).attr(l+"2",r),g.attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}),f=u.copy()}),l}var t={top:0,right:0,bottom:0,left:0},n=400,r=8,i="x",s=function(e){return e[i]},o=e.utils.defaultColor(),u=d3.scale.linear(),a,f;return l.options=e.utils.optionsFunc.bind(l),l.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,l):t},l.width=function(e){return arguments.length?(n=e,l):n},l.axis=function(e){return arguments.length?(i=e,l):i},l.size=function(e){return arguments.length?(r=e,l):r},l.getData=function(e){return arguments.length?(s=d3.functor(e),l):s},l.scale=function(e){return arguments.length?(u=e,l):u},l.color=function(t){return arguments.length?(o=e.utils.getColor(t),l):o},l},e.models.historicalBarChart=function(){function x(e){return e.each(function(d){var E=d3.select(this),T=this,N=(u||parseInt(E.style("width"))||960)-s.left-s.right,C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom;x.update=function(){E.call(x)},x.container=this,g.disabled=d.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!d||!d.length||!d.filter(function(e){return e.values.length}).length){var L=E.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",s.left+N/2).attr("y",s.top+C/2).text(function(e){return e}),x}E.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();var A=E.selectAll("g.nv-wrap.nv-historicalBarChart").data([d]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),M=A.select("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-barsWrap"),O.append("g").attr("class","nv-legendWrap"),f&&(i.width(N),M.select(".nv-legendWrap").datum(d).call(i),s.top!=i.height()&&(s.top=i.height(),C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom),A.select(".nv-legendWrap").attr("transform","translate(0,"+ -s.top+")")),A.attr("transform","translate("+s.left+","+s.top+")"),h&&M.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)"),t.width(N).height(C).color(d.map(function(e,t){return e.color||o(e,t)}).filter(function(e,t){return!d[t].disabled}));var _=M.select(".nv-barsWrap").datum(d.filter(function(e){return!e.disabled}));_.call(t),l&&(n.scale(v).tickSize(-C,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+m.range()[0]+")"),M.select(".nv-x.nv-axis").call(n)),c&&(r.scale(m).ticks(C/36).tickSize(-N,0),M.select(".nv-y.nv-axis").call(r)),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,d.filter(function(e){return!e.disabled}).length||d.map(function(e){return e.disabled=!1,A.selectAll(".nv-series").classed("disabled",!1),e}),g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),e.call(x)}),i.dispatch.on("legendDblclick",function(e){d.forEach(function(e){e.disabled=!0}),e.disabled=!1,g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),x.update()}),w.on("tooltipShow",function(e){p&&S(e,T.parentNode)}),w.on("changeState",function(e){typeof e.disabled!="undefined"&&(d.forEach(function(t,n){t.disabled=e.disabled[n]}),g.disabled=e.disabled),x.update()})}),x}var t=e.models.historicalBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s={top:30,right:90,bottom:50,left:90},o=e.utils.defaultColor(),u=null,a=null,f=!1,l=!0,c=!0,h=!1,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},v,m,g={},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=0;n.orient("bottom").tickPadding(7),r.orient(h?"right":"left");var S=function(i,s){if(s){var o=d3.select(s).select("svg"),u=o.node()?o.attr("viewBox"):null;if(u){u=u.split(" ");var a=parseInt(o.style("width"))/u[2];i.pos[0]=i.pos[0]*a,i.pos[1]=i.pos[1]*a}}var f=i.pos[0]+(s.offsetLeft||0),l=i.pos[1]+(s.offsetTop||0),c=n.tickFormat()(t.x()(i.point,i.pointIndex)),h=r.tickFormat()(t.y()(i.point,i.pointIndex)),p=d(i.series.key,c,h,i,x);e.tooltip.show([f,l],p,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+s.left,e.pos[1]+s.top],w.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){p&&e.tooltip.cleanup()}),x.dispatch=w,x.bars=t,x.legend=i,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate","highlightPoint","clearHighlights","interactive"),x.options=e.utils.optionsFunc.bind(x),x.margin=function(e){return arguments.length?(s.top=typeof e.top!="undefined"?e.top:s.top,s.right=typeof e.right!="undefined"?e.right:s.right,s.bottom=typeof e.bottom!="undefined"?e.bottom:s.bottom,s.left=typeof e.left!="undefined"?e.left:s.left,x):s},x.width=function(e){return arguments.length?(u=e,x):u},x.height=function(e){return arguments.length?(a=e,x):a},x.color=function(t){return arguments.length?(o=e.utils.getColor(t),i.color(o),x):o},x.showLegend=function(e){return arguments.length?(f=e,x):f},x.showXAxis=function(e){return arguments.length?(l=e,x):l},x.showYAxis=function(e){return arguments.length?(c=e,x):c},x.rightAlignYAxis=function(e){return arguments.length?(h=e,r.orient(e?"right":"left"),x):h},x.tooltips=function(e){return arguments.length?(p=e,x):p},x.tooltipContent=function(e){return arguments.length?(d=e,x):d},x.state=function(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments.length?(b=e,x):b},x.transitionDuration=function(e){return arguments.length?(E=e,x):E},x},e.models.indentedTree=function(){function g(e){return e.each(function(e){function k(e,t,n){d3.event.stopPropagation();if(d3.event.shiftKey&&!n)return d3.event.shiftKey=!1,e.values&&e.values.forEach(function(e){(e.values||e._values)&&k(e,0,!0)}),!0;if(!O(e))return!0;e.values?(e._values=e.values,e.values=null):(e.values=e._values,e._values=null),g.update()}function L(e){return e._values&&e._values.length?h:e.values&&e.values.length?p:""}function A(e){return e._values&&e._values.length}function O(e){var t=e.values||e._values;return t&&t.length}var t=1,n=d3.select(this),i=d3.layout.tree().children(function(e){return e.values}).size([r,f]);g.update=function(){n.call(g)},e[0]||(e[0]={key:a});var s=i.nodes(e[0]),y=d3.select(this).selectAll("div").data([[s]]),b=y.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),w=b.append("table"),E=y.select("table").attr("width","100%").attr("class",c);if(o){var S=w.append("thead"),x=S.append("tr");l.forEach(function(e){x.append("th").attr("width",e.width?e.width:"10%").style("text-align",e.type=="numeric"?"right":"left").append("span").text(e.label)})}var T=E.selectAll("tbody").data(function(e){return e});T.enter().append("tbody"),t=d3.max(s,function(e){return e.depth}),i.size([r,t*f]);var N=T.selectAll("tr").data(function(e){return e.filter(function(e){return u&&!e.children?u(e):!0})},function(e,t){return e.id||e.id||++m});N.exit().remove(),N.select("img.nv-treeicon").attr("src",L).classed("folded",A);var C=N.enter().append("tr");l.forEach(function(e,t){var n=C.append("td").style("padding-left",function(e){return(t?0:e.depth*f+12+(L(e)?0:16))+"px"},"important").style("text-align",e.type=="numeric"?"right":"left");t==0&&n.append("img").classed("nv-treeicon",!0).classed("nv-folded",A).attr("src",L).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(e){return L(e)?"inline-block":"none"}).on("click",k),n.each(function(n){!t&&v(n)?d3.select(this).append("a").attr("href",v).attr("class",d3.functor(e.classes)).append("span"):d3.select(this).append("span"),d3.select(this).select("span").attr("class",d3.functor(e.classes)).text(function(t){return e.format?t[e.key]?e.format(t[e.key]):"-":t[e.key]||"-"})}),e.showCount&&(n.append("span").attr("class","nv-childrenCount"),N.selectAll("span.nv-childrenCount").text(function(e){return e.values&&e.values.length||e._values&&e._values.length?"("+(e.values&&e.values.filter(function(e){return u?u(e):!0}).length||e._values&&e._values.filter(function(e){return u?u(e):!0}).length||0)+")":""}))}),N.order().on("click",function(e){d.elementClick({row:this,data:e,pos:[e.x,e.y]})}).on("dblclick",function(e){d.elementDblclick({row:this,data:e,pos:[e.x,e.y]})}).on("mouseover",function(e){d.elementMouseover({row:this,data:e,pos:[e.x,e.y]})}).on("mouseout",function(e){d.elementMouseout({row:this,data:e,pos:[e.x,e.y]})})}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e4),o=!0,u=!1,a="No Data Available.",f=20,l=[{key:"key",label:"Name",type:"text"}],c=null,h="images/grey-plus.png",p="images/grey-minus.png",d=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),v=function(e){return e.url},m=0;return g.options=e.utils.optionsFunc.bind(g),g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),scatter.color(i),g):i},g.id=function(e){return arguments.length?(s=e,g):s},g.header=function(e){return arguments.length?(o=e,g):o},g.noData=function(e){return arguments.length?(a=e,g):a},g.filterZero=function(e){return arguments.length?(u=e,g):u},g.columns=function(e){return arguments.length?(l=e,g):l},g.tableClass=function(e){return arguments.length?(c=e,g):c},g.iconOpen=function(e){return arguments.length?(h=e,g):h},g.iconClose=function(e){return arguments.length?(p=e,g):p},g.getUrl=function(e){return arguments.length?(v=e,g):v},g},e.models.legend=function(){function c(h){return h.each(function(c){var h=n-t.left-t.right,p=d3.select(this),d=p.selectAll("g.nv-legend").data([c]),v=d.enter().append("g").attr("class","nvd3 nv-legend").append("g"),m=d.select("g");d.attr("transform","translate("+t.left+","+t.top+")");var g=m.selectAll(".nv-series").data(function(e){return e}),y=g.enter().append("g").attr("class","nv-series").on("mouseover",function(e,t){l.legendMouseover(e,t)}).on("mouseout",function(e,t){l.legendMouseout(e,t)}).on("click",function(e,t){l.legendClick(e,t),a&&(f?(c.forEach(function(e){e.disabled=!0}),e.disabled=!1):(e.disabled=!e.disabled,c.every(function(e){return e.disabled})&&c.forEach(function(e){e.disabled=!1})),l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))}).on("dblclick",function(e,t){l.legendDblclick(e,t),a&&(c.forEach(function(e){e.disabled=!0}),e.disabled=!1,l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))});y.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),y.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8"),g.classed("disabled",function(e){return e.disabled}),g.exit().remove(),g.select("circle").style("fill",function(e,t){return e.color||s(e,t)}).style("stroke",function(e,t){return e.color||s(e,t)}),g.select("text").text(i);if(o){var b=[];g.each(function(t,n){var r=d3.select(this).select("text"),i;try{i=r.getComputedTextLength();if(i<=0)throw Error()}catch(s){i=e.utils.calcApproxTextWidth(r)}b.push(i+28)});var w=0,E=0,S=[];while(E<h&&w<b.length)S[w]=b[w],E+=b[w++];w===0&&(w=1);while(E>h&&w>1){S=[],w--;for(var x=0;x<b.length;x++)b[x]>(S[x%w]||0)&&(S[x%w]=b[x]);E=S.reduce(function(e,t,n,r){return e+t})}var T=[];for(var N=0,C=0;N<w;N++)T[N]=C,C+=S[N];g.attr("transform",function(e,t){return"translate("+T[t%w]+","+(5+Math.floor(t/w)*20)+")"}),u?m.attr("transform","translate("+(n-t.right-E)+","+t.top+")"):m.attr("transform","translate(0,"+t.top+")"),r=t.top+t.bottom+Math.ceil(b.length/w)*20}else{var k=5,L=5,A=0,O;g.attr("transform",function(e,r){var i=d3.select(this).select("text").node().getComputedTextLength()+28;return O=L,n<t.left+t.right+O+i&&(L=O=5,k+=20),L+=i,L>A&&(A=L),"translate("+O+","+k+")"}),m.attr("transform","translate("+(n-t.right-A)+","+t.top+")"),r=t.top+t.bottom+k+15}}),c}var t={top:5,right:0,bottom:5,left:0},n=400,r=20,i=function(e){return e.key},s=e.utils.defaultColor(),o=!0,u=!0,a=!0,f=!1,l=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange");return c.dispatch=l,c.options=e.utils.optionsFunc.bind(c),c.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,c):t},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.key=function(e){return arguments.length?(i=e,c):i},c.color=function(t){return arguments.length?(s=e.utils.getColor(t),c):s},c.align=function(e){return arguments.length?(o=e,c):o},c.rightAlign=function(e){return arguments.length?(u=e,c):u},c.updateState=function(e){return arguments.length?(a=e,c):a},c.radioButtonMode=function(e){return arguments.length?(f=e,c):f},c},e.models.line=function(){function m(g){return g.each(function(m){var g=r-n.left-n.right,b=i-n.top-n.bottom,w=d3.select(this);c=t.xScale(),h=t.yScale(),d=d||c,v=v||h;var E=w.selectAll("g.nv-wrap.nv-line").data([m]),S=E.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),T=S.append("defs"),N=S.append("g"),C=E.select("g");N.append("g").attr("class","nv-groups"),N.append("g").attr("class","nv-scatterWrap"),E.attr("transform","translate("+n.left+","+n.top+")"),t.width(g).height(b);var k=E.select(".nv-scatterWrap");k.call(t),T.append("clipPath").attr("id","nv-edge-clip-"+t.id()).append("rect"),E.select("#nv-edge-clip-"+t.id()+" rect").attr("width",g).attr("height",b>0?b:0),C.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":""),k.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":"");var L=E.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});L.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),L.exit().remove(),L.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return s(e,t)}).style("stroke",function(e,t){return s(e,t)}),L.style("stroke-opacity",1).style("fill-opacity",.5);var A=L.selectAll("path.nv-area").data(function(e){return f(e)?[e]:[]});A.enter().append("path").attr("class","nv-area").attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])}),L.exit().selectAll("path.nv-area").remove(),A.attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))}).y1(function(e,t){return h(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])});var O=L.selectAll("path.nv-line").data(function(e){return[e.values]});O.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))})),O.attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))})),d=c.copy(),v=h.copy()}),m}var t=e.models.scatter(),n={top:0,right:0,bottom:0,left:0},r=960,i=500,s=e.utils.defaultColor(),o=function(e){return e.x},u=function(e){return e.y},a=function(e,t){return!isNaN(u(e,t))&&u(e,t)!==null},f=function(e){return e.area},l=!1,c,h,p="linear";t.size(16).sizeDomain([16,256]);var d,v;return m.dispatch=t.dispatch,m.scatter=t,d3.rebind(m,t,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","padData","highlightPoint","clearHighlights"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.height=function(e){return arguments.length?(i=e,m):i},m.x=function(e){return arguments.length?(o=e,t.x(e),m):o},m.y=function(e){return arguments.length?(u=e,t.y(e),m):u},m.clipEdge=function(e){return arguments.length?(l=e,m):l},m.color=function(n){return arguments.length?(s=e.utils.getColor(n),t.color(s),m):s},m.interpolate=function(e){return arguments.length?(p=e,m):p},m.defined=function(e){return arguments.length?(a=e,m):a},m.isArea=function(e){return arguments.length?(f=d3.functor(e),m):f},m},e.models.lineChart=function(){function N(m){return m.each(function(m){var x=d3.select(this),C=this,k=(a||parseInt(x.style("width"))||960)-o.left-o.right,L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom;N.update=function(){x.call(N)},N.container=this,b.disabled=m.map(function(e){return!!e.disabled});if(!w){var A;w={};for(A in b)b[A]instanceof Array?w[A]=b[A].slice(0):w[A]=b[A]}if(!m||!m.length||!m.filter(function(e){return e.values.length}).length){var O=x.selectAll(".nv-noData").data([E]);return O.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),O.attr("x",o.left+k/2).attr("y",o.top+L/2).text(function(e){return e}),N}x.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var M=x.selectAll("g.nv-wrap.nv-lineChart").data([m]),_=M.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),D=M.select("g");_.append("rect").style("opacity",0),_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y nv-axis"),_.append("g").attr("class","nv-linesWrap"),_.append("g").attr("class","nv-legendWrap"),_.append("g").attr("class","nv-interactive"),D.select("rect").attr("width",k).attr("height",L>0?L:0),l&&(i.width(k),D.select(".nv-legendWrap").datum(m).call(i),o.top!=i.height()&&(o.top=i.height(),L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate(0,"+ -o.top+")")),M.attr("transform","translate("+o.left+","+o.top+")"),p&&D.select(".nv-y.nv-axis").attr("transform","translate("+k+",0)"),d&&(s.width(k).height(L).margin({left:o.left,top:o.top}).svgContainer(x).xScale(g),M.select(".nv-interactive").call(s)),t.width(k).height(L).color(m.map(function(e,t){return e.color||u(e,t)}).filter(function(e,t){return!m[t].disabled}));var P=D.select(".nv-linesWrap").datum(m.filter(function(e){return!e.disabled}));P.call(t),c&&(n.scale(g).ticks(k/100).tickSize(-L,0),D.select(".nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),D.select(".nv-x.nv-axis").call(n)),h&&(r.scale(y).ticks(L/36).tickSize(-k,0),D.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),N.update()}),s.dispatch.on("elementMousemove",function(i){t.clearHighlights();var a,f,l,c=[];m.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,N.x()),t.highlightPoint(r,f,!0);var s=n.values[f];if(typeof s=="undefined")return;typeof a=="undefined"&&(a=s),typeof l=="undefined"&&(l=N.xScale()(N.x()(s,f))),c.push({key:n.key,value:N.y()(s,f),color:u(n,n.seriesIndex)})});if(c.length>2){var h=N.yScale().invert(i.mouseY),p=Math.abs(N.yScale().domain()[0]-N.yScale().domain()[1]),d=.03*p,g=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);g!==null&&(c[g].highlight=!0)}var y=n.tickFormat()(N.x()(a,f));s.tooltip.position({left:l+o.left,top:i.mouseY+o.top}).chartContainer(C.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:y,series:c})(),s.renderGuideLine(l)}),s.dispatch.on("elementMouseout",function(e){S.tooltipHide(),t.clearHighlights()}),S.on("tooltipShow",function(e){v&&T(e,C.parentNode)}),S.on("changeState",function(e){typeof e.disabled!="undefined"&&m.length===e.disabled.length&&(m.forEach(function(t,n){t.disabled=e.disabled[n]}),b.disabled=e.disabled),N.update()})}),N}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.interactiveGuideline(),o={top:30,right:20,bottom:50,left:60},u=e.utils.defaultColor(),a=null,f=null,l=!0,c=!0,h=!0,p=!1,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=0;n.orient("bottom").tickPadding(7),r.orient(p?"right":"left");var T=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,N);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),N.dispatch=S,N.lines=t,N.legend=i,N.xAxis=n,N.yAxis=r,N.interactiveLayer=s,d3.rebind(N,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id","interpolate"),N.options=e.utils.optionsFunc.bind(N),N.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,N):o},N.width=function(e){return arguments.length?(a=e,N):a},N.height=function(e){return arguments.length?(f=e,N):f},N.color=function(t){return arguments.length?(u=e.utils.getColor(t),i.color(u),N):u},N.showLegend=function(e){return arguments.length?(l=e,N):l},N.showXAxis=function(e){return arguments.length?(c=e,N):c},N.showYAxis=function(e){return arguments.length?(h=e,N):h},N.rightAlignYAxis=function(e){return arguments.length?(p=e,r.orient(e?"right":"left"),N):p},N.useInteractiveGuideline=function(e){return arguments.length?(d=e,e===!0&&(N.interactive(!1),N.useVoronoi(!1)),N):d},N.tooltips=function(e){return arguments.length?(v=e,N):v},N.tooltipContent=function(e){return arguments.length?(m=e,N):m},N.state=function(e){return arguments.length?(b=e,N):b},N.defaultState=function(e){return arguments.length?(w=e,N):w},N.noData=function(e){return arguments.length?(E=e,N):E},N.transitionDuration=function(e){return arguments.length?(x=e,N):x},N},e.models.linePlusBarChart=function(){function T(e){return e.each(function(e){var l=d3.select(this),c=this,v=(a||parseInt(l.style("width"))||960)-u.left-u.right,N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom;T.update=function(){l.call(T)},b.disabled=e.map(function(e){return!!e.disabled});if(!w){var C;w={};for(C in b)b[C]instanceof Array?w[C]=b[C].slice(0):w[C]=b[C]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var k=l.selectAll(".nv-noData").data([E]);return k.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),k.attr("x",u.left+v/2).attr("y",u.top+N/2).text(function(e){return e}),T}l.selectAll(".nv-noData").remove();var L=e.filter(function(e){return!e.disabled&&e.bar}),A=e.filter(function(e){return!e.bar});m=A.filter(function(e){return!e.disabled}).length&&A.filter(function(e){return!e.disabled})[0].values.length?t.xScale():n.xScale(),g=n.yScale(),y=t.yScale();var O=d3.select(this).selectAll("g.nv-wrap.nv-linePlusBar").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y1 nv-axis"),M.append("g").attr("class","nv-y2 nv-axis"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-linesWrap"),M.append("g").attr("class","nv-legendWrap"),p&&(o.width(v/2),_.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(o),u.top!=o.height()&&(u.top=o.height(),N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom),_.select(".nv-legendWrap").attr("transform","translate("+v/2+","+ -u.top+")")),O.attr("transform","translate("+u.left+","+u.top+")"),t.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar})),n.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar}));var D=_.select(".nv-barsWrap").datum(L.length?L:[{values:[]}]),P=_.select(".nv-linesWrap").datum(A[0]&&!A[0].disabled?A:[{values:[]}]);d3.transition(D).call(n),d3.transition(P).call(t),r.scale(m).ticks(v/100).tickSize(-N,0),_.select(".nv-x.nv-axis").attr("transform","translate(0,"+g.range()[0]+")"),d3.transition(_.select(".nv-x.nv-axis")).call(r),i.scale(g).ticks(N/36).tickSize(-v,0),d3.transition(_.select(".nv-y1.nv-axis")).style("opacity",L.length?1:0).call(i),s.scale(y).ticks(N/36).tickSize(L.length?0:-v,0),_.select(".nv-y2.nv-axis").style("opacity",A.length?1:0).attr("transform","translate("+v+",0)"),d3.transition(_.select(".nv-y2.nv-axis")).call(s),o.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),T.update()}),S.on("tooltipShow",function(e){d&&x(e,c.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),b.disabled=t.disabled),T.update()})}),T}var t=e.models.line(),n=e.models.historicalBar(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.legend(),u={top:30,right:60,bottom:50,left:60},a=null,f=null,l=function(e){return e.x},c=function(e){return e.y},h=e.utils.defaultColor(),p=!0,d=!0,v=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},m,g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.padData(!0),t.clipEdge(!1).padData(!0),r.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),s.orient("right");var x=function(n,o){var u=n.pos[0]+(o.offsetLeft||0),a=n.pos[1]+(o.offsetTop||0),f=r.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?i:s).tickFormat()(t.y()(n.point,n.pointIndex)),c=v(n.series.key,f,l,n,T);e.tooltip.show([u,a],c,n.value<0?"n":"s",null,o)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),n.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),n.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){d&&e.tooltip.cleanup()}),T.dispatch=S,T.legend=o,T.lines=t,T.bars=n,T.xAxis=r,T.y1Axis=i,T.y2Axis=s,d3.rebind(T,t,"defined","size","clipVoronoi","interpolate"),T.options=e.utils.optionsFunc.bind(T),T.x=function(e){return arguments.length?(l=e,t.x(e),n.x(e),T):l},T.y=function(e){return arguments.length?(c=e,t.y(e),n.y(e),T):c},T.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,T):u},T.width=function(e){return arguments.length?(a=e,T):a},T.height=function(e){return arguments.length?(f=e,T):f},T.color=function(t){return arguments.length?(h=e.utils.getColor(t),o.color(h),T):h},T.showLegend=function(e){return arguments.length?(p=e,T):p},T.tooltips=function(e){return arguments.length?(d=e,T):d},T.tooltipContent=function(e){return arguments.length?(v=e,T):v},T.state=function(e){return arguments.length?(b=e,T):b},T.defaultState=function(e){return arguments.length?(w=e,T):w},T.noData=function(e){return arguments.length?(E=e,T):E},T},e.models.lineWithFocusChart=function(){function k(e){return e.each(function(e){function R(e){var t=+(e=="e"),n=t?1:-1,r=O/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function U(){a.empty()||a.extent(w),F.data([a.empty()?g.domain():w]).each(function(e,t){var n=g(e[0])-v.range()[0],r=v.range()[1]-g(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",g(e[1])).attr("width",r<0?0:r)})}function z(){w=a.empty()?null:a.extent();var n=a.empty()?g.domain():a.extent();if(Math.abs(n[0]-n[1])<=1)return;T.brush({extent:n,brush:a}),U();var s=P.select(".nv-focus .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}).map(function(e,r){return{key:e.key,values:e.values.filter(function(e,r){return t.x()(e,r)>=n[0]&&t.x()(e,r)<=n[1]})}}));s.call(t),P.select(".nv-focus .nv-x.nv-axis").call(r),P.select(".nv-focus .nv-y.nv-axis").call(i)}var S=d3.select(this),N=this,L=(h||parseInt(S.style("width"))||960)-f.left-f.right,A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d,O=d-l.top-l.bottom;k.update=function(){S.call(k)},k.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var M=S.selectAll(".nv-noData").data([x]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",f.left+L/2).attr("y",f.top+A/2).text(function(e){return e}),k}S.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale(),g=n.xScale(),y=n.yScale();var _=S.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([e]),D=_.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),P=_.select("g");D.append("g").attr("class","nv-legendWrap");var H=D.append("g").attr("class","nv-focus");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-linesWrap");var B=D.append("g").attr("class","nv-context");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-linesWrap"),B.append("g").attr("class","nv-brushBackground"),B.append("g").attr("class","nv-x nv-brush"),b&&(u.width(L),P.select(".nv-legendWrap").datum(e).call(u),f.top!=u.height()&&(f.top=u.height(),A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d),P.select(".nv-legendWrap").attr("transform","translate(0,"+ -f.top+")")),_.attr("transform","translate("+f.left+","+f.top+")"),t.width(L).height(A).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),n.defined(t.defined()).width(L).height(O).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),P.select(".nv-context").attr("transform","translate(0,"+(A+f.bottom+l.top)+")");var j=P.select(".nv-context .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}));d3.transition(j).call(n),r.scale(v).ticks(L/100).tickSize(-A,0),i.scale(m).ticks(A/36).tickSize(-L,0),P.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+A+")"),a.x(g).on("brush",function(){var e=k.transitionDuration();k.transitionDuration(0),z(),k.transitionDuration(e)}),w&&a.extent(w);var F=P.select(".nv-brushBackground").selectAll("g").data([w||a.extent()]),I=F.enter().append("g");I.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",O),I.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",O);var q=P.select(".nv-x.nv-brush").call(a);q.selectAll("rect").attr("height",O),q.selectAll(".resize").append("path").attr("d",R),z(),s.scale(g).ticks(L/100).tickSize(-O,0),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.transition(P.select(".nv-context .nv-x.nv-axis")).call(s),o.scale(y).ticks(O/36).tickSize(-L,0),d3.transition(P.select(".nv-context .nv-y.nv-axis")).call(o),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),u.dispatch.on("stateChange",function(e){k.update()}),T.on("tooltipShow",function(e){E&&C(e,N.parentNode)})}),k}var t=e.models.line(),n=e.models.line(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.axis(),u=e.models.legend(),a=d3.svg.brush(),f={top:30,right:30,bottom:30,left:60},l={top:0,right:30,bottom:20,left:60},c=e.utils.defaultColor(),h=null,p=null,d=100,v,m,g,y,b=!0,w=null,E=!0,S=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},x="No Data Available.",T=d3.dispatch("tooltipShow","tooltipHide","brush"),N=0;t.clipEdge(!0),n.interactive(!1),r.orient("bottom").tickPadding(5),i.orient("left"),s.orient("bottom").tickPadding(5),o.orient("left");var C=function(n,s){var o=n.pos[0]+(s.offsetLeft||0),u=n.pos[1]+(s.offsetTop||0),a=r.tickFormat()(t.x()(n.point,n.pointIndex)),f=i.tickFormat()(t.y()(n.point,n.pointIndex)),l=S(n.series.key,a,f,n,k);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+f.left,e.pos[1]+f.top],T.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){E&&e.tooltip.cleanup()}),k.dispatch=T,k.legend=u,k.lines=t,k.lines2=n,k.xAxis=r,k.yAxis=i,k.x2Axis=s,k.y2Axis=o,d3.rebind(k,t,"defined","isArea","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),k.options=e.utils.optionsFunc.bind(k),k.x=function(e){return arguments.length?(t.x(e),n.x(e),k):t.x},k.y=function(e){return arguments.length?(t.y(e),n.y(e),k):t.y},k.margin=function(e){return arguments.length?(f.top=typeof e.top!="undefined"?e.top:f.top,f.right=typeof e.right!="undefined"?e.right:f.right,f.bottom=typeof e.bottom!="undefined"?e.bottom:f.bottom,f.left=typeof e.left!="undefined"?e.left:f.left,k):f},k.margin2=function(e){return arguments.length?(l=e,k):l},k.width=function(e){return arguments.length?(h=e,k):h},k.height=function(e){return arguments.length?(p=e,k):p},k.height2=function(e){return arguments.length?(d=e,k):d},k.color=function(t){return arguments.length?(c=e.utils.getColor(t),u.color(c),k):c},k.showLegend=function(e){return arguments.length?(b=e,k):b},k.tooltips=function(e){return arguments.length?(E=e,k):E},k.tooltipContent=function(e){return arguments.length?(S=e,k):S},k.interpolate=function(e){return arguments.length?(t.interpolate(e),n.interpolate(e),k):t.interpolate()},k.noData=function(e){return arguments.length?(x=e,k):x},k.xTickFormat=function(e){return arguments.length?(r.tickFormat(e),s.tickFormat(e),k):r.tickFormat()},k.yTickFormat=function(e){return arguments.length?(i.tickFormat(e),o.tickFormat(e),k):i.tickFormat()},k.brushExtent=function(e){return arguments.length?(w=e,k):w},k.transitionDuration=function(e){return arguments.length?(N=e,k):N},k},e.models.linePlusBarWithFocusChart=function(){function B(e){return e.each(function(e){function tt(e){var t=+(e=="e"),n=t?1:-1,r=I/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function nt(){h.empty()||h.extent(x),Y.data([h.empty()?k.domain():x]).each(function(e,t){var n=k(e[0])-k.range()[0],r=k.range()[1]-k(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",k(e[1])).attr("width",r<0?0:r)})}function rt(){x=h.empty()?null:h.extent(),S=h.empty()?k.domain():h.extent(),D.brush({extent:S,brush:h}),nt(),r.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),t.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var n=$.select(".nv-focus .nv-barsWrap").datum(R.length?R.map(function(e,t){return{key:e.key,values:e.values.filter(function(e,t){return r.x()(e,t)>=S[0]&&r.x()(e,t)<=S[1]})}}):[{values:[]}]),i=$.select(".nv-focus .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U.map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=S[0]&&t.x()(e,n)<=S[1]})}}));R.length?C=r.xScale():C=t.xScale(),s.scale(C).ticks(j/100).tickSize(-F,0),s.domain([Math.ceil(S[0]),Math.floor(S[1])]),$.select(".nv-x.nv-axis").call(s),n.call(r),i.call(t),$.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L.range()[0]+")"),u.scale(L).ticks(F/36).tickSize(-j,0),$.select(".nv-focus .nv-y1.nv-axis").style("opacity",R.length?1:0),a.scale(A).ticks(F/36).tickSize(R.length?0:-j,0),$.select(".nv-focus .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+C.range()[1]+",0)"),$.select(".nv-focus .nv-y1.nv-axis").call(u),$.select(".nv-focus .nv-y2.nv-axis").call(a)}var N=d3.select(this),P=this,j=(v||parseInt(N.style("width"))||960)-p.left-p.right,F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g,I=g-d.top-d.bottom;B.update=function(){N.call(B)},B.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=N.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",p.left+j/2).attr("y",p.top+F/2).text(function(e){return e}),B}N.selectAll(".nv-noData").remove();var R=e.filter(function(e){return!e.disabled&&e.bar}),U=e.filter(function(e){return!e.bar});C=r.xScale(),k=o.scale(),L=r.yScale(),A=t.yScale(),O=i.yScale(),M=n.yScale();var z=e.filter(function(e){return!e.disabled&&e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})}),W=e.filter(function(e){return!e.disabled&&!e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})});C.range([0,j]),k.domain(d3.extent(d3.merge(z.concat(W)),function(e){return e.x})).range([0,j]);var X=N.selectAll("g.nv-wrap.nv-linePlusBar").data([e]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),$=X.select("g");V.append("g").attr("class","nv-legendWrap");var J=V.append("g").attr("class","nv-focus");J.append("g").attr("class","nv-x nv-axis"),J.append("g").attr("class","nv-y1 nv-axis"),J.append("g").attr("class","nv-y2 nv-axis"),J.append("g").attr("class","nv-barsWrap"),J.append("g").attr("class","nv-linesWrap");var K=V.append("g").attr("class","nv-context");K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y1 nv-axis"),K.append("g").attr("class","nv-y2 nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-linesWrap"),K.append("g").attr("class","nv-brushBackground"),K.append("g").attr("class","nv-x nv-brush"),E&&(c.width(j/2),$.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(c),p.top!=c.height()&&(p.top=c.height(),F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g),$.select(".nv-legendWrap").attr("transform","translate("+j/2+","+ -p.top+")")),X.attr("transform","translate("+p.left+","+p.top+")"),i.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),n.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var Q=$.select(".nv-context .nv-barsWrap").datum(R.length?R:[{values:[]}]),G=$.select(".nv-context .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U);$.select(".nv-context").attr("transform","translate(0,"+(F+p.bottom+d.top)+")"),Q.call(i),G.call(n),h.x(k).on("brush",rt),x&&h.extent(x);var Y=$.select(".nv-brushBackground").selectAll("g").data([x||h.extent()]),Z=Y.enter().append("g");Z.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",I),Z.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",I);var et=$.select(".nv-x.nv-brush").call(h);et.selectAll("rect").attr("height",I),et.selectAll(".resize").append("path").attr("d",tt),o.ticks(j/100).tickSize(-I,0),$.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+O.range()[0]+")"),$.select(".nv-context .nv-x.nv-axis").call(o),f.scale(O).ticks(I/36).tickSize(-j,0),$.select(".nv-context .nv-y1.nv-axis").style("opacity",R.length?1:0).attr("transform","translate(0,"+k.range()[0]+")"),$.select(".nv-context .nv-y1.nv-axis").call(f),l.scale(M).ticks(I/36).tickSize(R.length?0:-j,0),$.select(".nv-context .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+k.range()[1]+",0)"),$.select(".nv-context .nv-y2.nv-axis").call(l),c.dispatch.on("stateChange",function(e){B.update()}),D.on("tooltipShow",function(e){T&&H(e,P.parentNode)}),rt()}),B}var t=e.models.line(),n=e.models.line(),r=e.models.historicalBar(),i=e.models.historicalBar(),s=e.models.axis(),o=e.models.axis(),u=e.models.axis(),a=e.models.axis(),f=e.models.axis(),l=e.models.axis(),c=e.models.legend(),h=d3.svg.brush(),p={top:30,right:30,bottom:30,left:60},d={top:0,right:30,bottom:20,left:60},v=null,m=null,g=100,y=function(e){return e.x},b=function(e){return e.y},w=e.utils.defaultColor(),E=!0,S,x=null,T=!0,N=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},C,k,L,A,O,M,_="No Data Available.",D=d3.dispatch("tooltipShow","tooltipHide","brush"),P=0;t.clipEdge(!0),n.interactive(!1),s.orient("bottom").tickPadding(5),u.orient("left"),a.orient("right"),o.orient("bottom").tickPadding(5),f.orient("left"),l.orient("right");var H=function(n,r){S&&(n.pointIndex+=Math.ceil(S[0]));var i=n.pos[0]+(r.offsetLeft||0),o=n.pos[1]+(r.offsetTop||0),f=s.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?u:a).tickFormat()(t.y()(n.point,n.pointIndex)),c=N(n.series.key,f,l,n,B);e.tooltip.show([i,o],c,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),r.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),r.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),D.on("tooltipHide",function(){T&&e.tooltip.cleanup()}),B.dispatch=D,B.legend=c,B.lines=t,B.lines2=n,B.bars=r,B.bars2=i,B.xAxis=s,B.x2Axis=o,B.y1Axis=u,B.y2Axis=a,B.y3Axis=f,B.y4Axis=l,d3.rebind(B,t,"defined","size","clipVoronoi","interpolate"),B.options=e.utils.optionsFunc.bind(B),B.x=function(e){return arguments.length?(y=e,t.x(e),r.x(e),B):y},B.y=function(e){return arguments.length?(b=e,t.y(e),r.y(e),B):b},B.margin=function(e){return arguments.length?(p.top=typeof e.top!="undefined"?e.top:p.top,p.right=typeof e.right!="undefined"?e.right:p.right,p.bottom=typeof e.bottom!="undefined"?e.bottom:p.bottom,p.left=typeof e.left!="undefined"?e.left:p.left,B):p},B.width=function(e){return arguments.length?(v=e,B):v},B.height=function(e){return arguments.length?(m=e,B):m},B.color=function(t){return arguments.length?(w=e.utils.getColor(t),c.color(w),B):w},B.showLegend=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(T=e,B):T},B.tooltipContent=function(e){return arguments.length?(N=e,B):N},B.noData=function(e){return arguments.length?(_=e,B):_},B.brushExtent=function(e){return arguments.length?(x=e,B):x},B},e.models.multiBar=function(){function C(e){return e.each(function(e){var g=n-t.left-t.right,C=r-t.top-t.bottom,k=d3.select(this);d&&e.length&&(d=[{values:e[0].values.map(function(e){return{x:e.x,y:0,series:e.series,size:.01}})}]),c&&(e=d3.layout.stack().offset(h).values(function(e){return e.values}).y(a)(!e.length&&d?d:e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),c&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i,i-=t.size):(t.y1=t.size+r,r+=t.size)})});var L=y&&b?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});i.domain(y||d3.merge(L).map(function(e){return e.x})).rangeBands(w||[0,g],S),s.domain(b||d3.extent(d3.merge(L).map(function(e){return c?e.y>0?e.y1:e.y1+e.y:e.y}).concat(f))).range(E||[C,0]),i.domain()[0]===i.domain()[1]&&(i.domain()[0]?i.domain([i.domain()[0]-i.domain()[0]*.01,i.domain()[1]+i.domain()[1]*.01]):i.domain([-1,1])),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]+s.domain()[0]*.01,s.domain()[1]-s.domain()[1]*.01]):s.domain([-1,1])),T=T||i,N=N||s;var A=k.selectAll("g.nv-wrap.nv-multibar").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),M=O.append("defs"),_=O.append("g"),D=A.select("g");_.append("g").attr("class","nv-groups"),A.attr("transform","translate("+t.left+","+t.top+")"),M.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),A.select("#nv-edge-clip-"+o+" rect").attr("width",g).attr("height",C),D.attr("clip-path",l?"url(#nv-edge-clip-"+o+")":"");var P=A.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});P.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),P.exit().selectAll("rect.nv-bar").attr("y",function(e){return c?N(e.y0):N(0)}).attr("height",0).remove(),P.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return p(e,t)}).style("stroke",function(e,t){return p(e,t)}),P.style("stroke-opacity",1).style("fill-opacity",.75);var H=P.selectAll("rect.nv-bar").data(function(t){return d&&!e.length?d.values:t.values});H.exit().remove();var B=H.enter().append("rect").attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(t,n,r){return c?0:r*i.rangeBand()/e.length}).attr("y",function(e){return N(c?e.y0:0)}).attr("height",0).attr("width",i.rangeBand()/(c?1:e.length)).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"});H.style("fill",function(e,t,n){return p(e,n,t)}).style("stroke",function(e,t,n){return p(e,n,t)}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"}),v&&(m||(m=e.map(function(){return!0})),H.style("fill",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()})),c?H.attr("y",function(e,t){return s(c?e.y1:0)}).attr("height",function(e,t){return Math.max(Math.abs(s(e.y+(c?e.y0:0))-s(c?e.y0:0)),1)}).attr("x",function(t,n){return c?0:t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/(c?1:e.length)):H.attr("x",function(t,n){return t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/e.length).attr("y",function(e,t){return a(e,t)<0?s(0):s(0)-s(a(e,t))<1?s(0)-1:s(a(e,t))||0}).attr("height",function(e,t){return Math.max(Math.abs(s(a(e,t))-s(0)),1)||0}),T=i.copy(),N=s.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=d3.scale.ordinal(),s=d3.scale.linear(),o=Math.floor(Math.random()*1e4),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=!0,c=!1,h="zero",p=e.utils.defaultColor(),d=!1,v=null,m,g=1200,y,b,w,E,S=.1,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(i=e,C):i},C.yScale=function(e){return arguments.length?(s=e,C):s},C.xDomain=function(e){return arguments.length?(y=e,C):y},C.yDomain=function(e){return arguments.length?(b=e,C):b},C.xRange=function(e){return arguments.length?(w=e,C):w},C.yRange=function(e){return arguments.length?(E=e,C):E},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(c=e,C):c},C.stackOffset=function(e){return arguments.length?(h=e,C):h},C.clipEdge=function(e){return arguments.length?(l=e,C):l},C.color=function(t){return arguments.length?(p=e.utils.getColor(t),C):p},C.barColor=function(t){return arguments.length?(v=e.utils.getColor(t),C):v},C.disabled=function(e){return arguments.length?(m=e,C):m},C.id=function(e){return arguments.length?(o=e,C):o},C.hideable=function(e){return arguments.length?(d=e,C):d},C.delay=function(e){return arguments.length?(g=e,C):g},C.groupSpacing=function(e){return arguments.length?(S=e,C):S},C},e.models.multiBarChart=function(){function A(e){return e.each(function(e){var b=d3.select(this),k=this,O=(u||parseInt(b.style("width"))||960)-o.left-o.right,M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom;A.update=function(){b.call(A)},A.container=this,S.disabled=e.map(function(e){return!!e.disabled});if(!x){var _;x={};for(_ in S)S[_]instanceof Array?x[_]=S[_].slice(0):x[_]=S[_]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var D=b.selectAll(".nv-noData").data([T]);return D.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),D.attr("x",o.left+O/2).attr("y",o.top+M/2).text(function(e){return e}),A}b.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();var P=b.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([e]),H=P.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),B=P.select("g");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-barsWrap"),H.append("g").attr("class","nv-legendWrap"),H.append("g").attr("class","nv-controlsWrap"),c&&(i.width(O-C()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),B.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom),B.select(".nv-legendWrap").attr("transform","translate("+C()+","+ -o.top+")"));if(l){var j=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(C()).color(["#444","#444","#444"]),B.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -o.top+")").call(s)}P.attr("transform","translate("+o.left+","+o.top+")"),d&&B.select(".nv-y.nv-axis").attr("transform","translate("+O+",0)"),t.disabled(e.map(function(e){return e.disabled})).width(O).height(M).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var F=B.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));F.call(t);if(h){n.scale(w).ticks(O/100).tickSize(-M,0),B.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),B.select(".nv-x.nv-axis").call(n);var I=B.select(".nv-x.nv-axis > g").selectAll("g");I.selectAll("line, text").style("opacity",1);if(m){var q=function(e,t){return"translate("+e+","+t+")"},R=5,U=17;I.selectAll("text").attr("transform",function(e,t,n){return q(0,n%2==0?R:U)});var z=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;B.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(e,t){return q(0,t===0||z%2!==0?U:R)})}v&&I.filter(function(t,n){return n%Math.ceil(e[0].values.length/(O/100))!==0}).selectAll("text, line").style("opacity",0),g&&I.selectAll(".tick text").attr("transform","rotate("+g+" 0,0)").style("text-anchor",g>0?"start":"end"),B.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}p&&(r.scale(E).ticks(M/36).tickSize(-O,0),B.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){S=e,N.stateChange(S),A.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;j=j.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}S.stacked=t.stacked(),N.stateChange(S),A.update()}),N.on("tooltipShow",function(e){y&&L(e,k.parentNode)}),N.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),S.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),S.stacked=n.stacked),A.update()})}),A}var t=e.models.multiBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=!1,g=0,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},w,E,S={stacked:!1},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=function(){return l?180:0},k=0;t.stacked(!1),n.orient("bottom").tickPadding(7).highlightZero(!0).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(d?"right":"left").tickFormat(d3.format(",.1f")),s.updateState(!1);var L=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,A);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],N.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){y&&e.tooltip.cleanup()}),A.dispatch=N,A.multibar=t,A.legend=i,A.xAxis=n,A.yAxis=r,d3.rebind(A,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","stacked","stackOffset","delay","barColor","groupSpacing"),A.options=e.utils.optionsFunc.bind(A),A.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,A):o},A.width=function(e){return arguments.length?(u=e,A):u},A.height=function(e){return arguments.length?(a=e,A):a},A.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),A):f},A.showControls=function(e){return arguments.length?(l=e,A):l},A.showLegend=function(e){return arguments.length?(c=e,A):c},A.showXAxis=function(e){return arguments.length?(h=e,A):h},A.showYAxis=function(e){return arguments.length?(p=e,A):p},A.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),A):d},A.reduceXTicks=function(e){return arguments.length?(v=e,A):v},A.rotateLabels=function(e){return arguments.length?(g=e,A):g},A.staggerLabels=function(e){return arguments.length?(m=e,A):m},A.tooltip=function(e){return arguments.length?(b=e,A):b},A.tooltips=function(e){return arguments.length?(y=e,A):y},A.tooltipContent=function(e){return arguments.length?(b=e,A):b},A.state=function(e){return arguments.length?(S=e,A):S},A.defaultState=function(e){return arguments.length?(x=e,A):x},A.noData=function(e){return arguments.length?(T=e,A):T},A.transitionDuration=function(e){return arguments.length?(k=e,A):k},A},e.models.multiBarHorizontal=function(){function C(e){return e.each(function(e){var i=n-t.left-t.right,y=r-t.top-t.bottom,C=d3.select(this);p&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),p&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i-t.size,i-=t.size):(t.y1=r,r+=t.size)})});var k=b&&w?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});s.domain(b||d3.merge(k).map(function(e){return e.x})).rangeBands(E||[0,y],.1),o.domain(w||d3.extent(d3.merge(k).map(function(e){return p?e.y>0?e.y1+e.y:e.y1:e.y}).concat(f))),d&&!p?o.range(S||[o.domain()[0]<0?m:0,i-(o.domain()[1]>0?m:0)]):o.range(S||[0,i]),T=T||s,N=N||d3.scale.linear().domain(o.domain()).range([o(0),o(0)]);var L=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([e]),A=L.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),O=A.append("defs"),M=A.append("g"),_=L.select("g");M.append("g").attr("class","nv-groups"),L.attr("transform","translate("+t.left+","+t.top+")");var D=L.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return l(e,t)}).style("stroke",function(e,t){return l(e,t)}),D.style("stroke-opacity",1).style("fill-opacity",.75);var P=D.selectAll("g.nv-bar").data(function(e){return e.values});P.exit().remove();var H=P.enter().append("g").attr("transform",function(t,n,r){return"translate("+N(p?t.y0:0)+","+(p?0:r*s.rangeBand()/e.length+s(u(t,n)))+")"});H.append("rect").attr("width",0).attr("height",s.rangeBand()/(p?1:e.length)),P.on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[o(a(t,n)+(p?t.y0:0)),s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.append("text"),d&&!p?(P.select("text").attr("text-anchor",function(e,t){return a(e,t)<0?"end":"start"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return g(a(e,t))}),P.select("text").attr("x",function(e,t){return a(e,t)<0?-4:o(a(e,t))-o(0)+4})):P.selectAll("text").text(""),v&&!p?(H.append("text").classed("nv-bar-label",!0),P.select("text.nv-bar-label").attr("text-anchor",function(e,t){return a(e,t)<0?"start":"end"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return u(e,t)}),P.select("text.nv-bar-label").attr("x",function(e,t){return a(e,t)<0?o(0)-o(a(e,t))+4:-4})):P.selectAll("text.nv-bar-label").text(""),P.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}),c&&(h||(h=e.map(function(){return!0})),P.style("fill",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()})),p?P.attr("transform",function(e,t){return"translate("+o(e.y1)+","+s(u(e,t))+")"}).select("rect").attr("width",function(e,t){return Math.abs(o(a(e,t)+e.y0)-o(e.y0))}).attr("height",s.rangeBand()):P.attr("transform",function(t,n){return"translate("+(a(t,n)<0?o(a(t,n)):o(0))+","+(t.series*s.rangeBand()/e.length+s(u(t,n)))+")"}).select("rect").attr("height",s.rangeBand()/e.length).attr("width",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)}),T=s.copy(),N=o.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=null,h,p=!1,d=!1,v=!1,m=60,g=d3.format(",.2f"),y=1200,b,w,E,S,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(s=e,C):s},C.yScale=function(e){return arguments.length?(o=e,C):o},C.xDomain=function(e){return arguments.length?(b=e,C):b},C.yDomain=function(e){return arguments.length?(w=e,C):w},C.xRange=function(e){return arguments.length?(E=e,C):E},C.yRange=function(e){return arguments.length?(S=e,C):S},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(p=e,C):p},C.color=function(t){return arguments.length?(l=e.utils.getColor(t),C):l},C.barColor=function(t){return arguments.length?(c=e.utils.getColor(t),C):c},C.disabled=function(e){return arguments.length?(h=e,C):h},C.id=function(e){return arguments.length?(i=e,C):i},C.delay=function(e){return arguments.length?(y=e,C):y},C.showValues=function(e){return arguments.length?(d=e,C):d},C.showBarLabels=function(e){return arguments.length?(v=e,C):v},C.valueFormat=function(e){return arguments.length?(g=e,C):g},C.valuePadding=function(e){return arguments.length?(m=e,C):m},C},e.models.multiBarHorizontalChart=function(){function C(e){return e.each(function(e){var d=d3.select(this),m=this,T=(u||parseInt(d.style("width"))||960)-o.left-o.right,k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom;C.update=function(){d.call(C)},C.container=this,b.disabled=e.map(function(e){return!!e.disabled});if(!w){var L;w={};for(L in b)b[L]instanceof Array?w[L]=b[L].slice(0):w[L]=b[L]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var A=d.selectAll(".nv-noData").data([E]);return A.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),A.attr("x",o.left+T/2).attr("y",o.top+k/2).text(function(e){return e}),C}d.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var O=d.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-legendWrap"),M.append("g").attr("class","nv-controlsWrap"),c&&(i.width(T-x()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),_.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom),_.select(".nv-legendWrap").attr("transform","translate("+x()+","+ -o.top+")"));if(l){var D=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(x()).color(["#444","#444","#444"]),_.select(".nv-controlsWrap").datum(D).attr("transform","translate(0,"+ -o.top+")").call(s)}O.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(e.map(function(e){return e.disabled})).width(T).height(k).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var P=_.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));P.call(t);if(h){n.scale(g).ticks(k/24).tickSize(-T,0),_.select(".nv-x.nv-axis").call(n);var H=_.select(".nv-x.nv-axis").selectAll("g");H.selectAll("line, text")}p&&(r.scale(y).ticks(T/100).tickSize(-k,0),_.select(".nv-y.nv-axis").attr("transform","translate(0,"+k+")"),_.select(".nv-y.nv-axis").call(r)),_.select(".nv-zeroLine line").attr("x1",y(0)).attr("x2",y(0)).attr("y1",0).attr("y2",-k),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),C.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;D=D.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}b.stacked=t.stacked(),S.stateChange(b),C.update()}),S.on("tooltipShow",function(e){v&&N(e,m.parentNode)}),S.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),b.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),b.stacked=n.stacked),C.update()})}),C}var t=e.models.multiBarHorizontal(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend().height(30),s=e.models.legend().height(30),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+" - "+t+"</h3>"+"<p>"+n+"</p>"},g,y,b={stacked:d},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=function(){return l?180:0},T=0;t.stacked(d),n.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("bottom").tickFormat(d3.format(",.1f")),s.updateState(!1);var N=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,C);e.tooltip.show([o,u],l,i.value<0?"e":"w",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),C.dispatch=S,C.multibar=t,C.legend=i,C.xAxis=n,C.yAxis=r,d3.rebind(C,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","delay","showValues","showBarLabels","valueFormat","stacked","barColor"),C.options=e.utils.optionsFunc.bind(C),C.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,C):o},C.width=function(e){return arguments.length?(u=e,C):u},C.height=function(e){return arguments.length?(a=e,C):a},C.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),C):f},C.showControls=function(e){return arguments.length?(l=e,C):l},C.showLegend=function(e){return arguments.length?(c=e,C):c},C.showXAxis=function(e){return arguments.length?(h=e,C):h},C.showYAxis=function(e){return arguments.length?(p=e,C):p},C.tooltip=function(e){return arguments.length?(m=e,C):m},C.tooltips=function(e){return arguments.length?(v=e,C):v},C.tooltipContent=function(e){return arguments.length?(m=e,C):m},C.state=function(e){return arguments.length?(b=e,C):b},C.defaultState=function(e){return arguments.length?(w=e,C):w},C.noData=function(e){return arguments.length?(E=e,C):E},C.transitionDuration=function(e){return arguments.length?(T=e,C):T},C},e.models.multiChart=function(){function C(e){return e.each(function(e){var u=d3.select(this),f=this;C.update=function(){u.call(C)},C.container=this;var k=(r||parseInt(u.style("width"))||960)-t.left-t.right,L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom,A=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==1}),O=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==2}),M=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==1}),_=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==2}),D=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==1}),P=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==2}),H=e.filter(function(e){return!e.disabled&&e.yAxis==1}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})}),B=e.filter(function(e){return!e.disabled&&e.yAxis==2}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})});a.domain(d3.extent(d3.merge(H.concat(B)),function(e){return e.x})).range([0,k]);var j=u.selectAll("g.wrap.multiChart").data([e]),F=j.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");F.append("g").attr("class","x axis"),F.append("g").attr("class","y1 axis"),F.append("g").attr("class","y2 axis"),F.append("g").attr("class","lines1Wrap"),F.append("g").attr("class","lines2Wrap"),F.append("g").attr("class","bars1Wrap"),F.append("g").attr("class","bars2Wrap"),F.append("g").attr("class","stack1Wrap"),F.append("g").attr("class","stack2Wrap"),F.append("g").attr("class","legendWrap");var I=j.select("g");s&&(x.width(k/2),I.select(".legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.yAxis==1?"":" (right axis)"),e})).call(x),t.top!=x.height()&&(t.top=x.height(),L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom),I.select(".legendWrap").attr("transform","translate("+k/2+","+ -t.top+")")),d.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="line"})),v.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="line"})),m.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="bar"})),g.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="bar"})),y.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="area"})),b.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="area"})),I.attr("transform","translate("+t.left+","+t.top+")");var q=I.select(".lines1Wrap").datum(A),R=I.select(".bars1Wrap").datum(M),U=I.select(".stack1Wrap").datum(D),z=I.select(".lines2Wrap").datum(O),W=I.select(".bars2Wrap").datum(_),X=I.select(".stack2Wrap").datum(P),V=D.length?D.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[],$=P.length?P.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[];h.domain(l||d3.extent(d3.merge(H).concat(V),function(e){return e.y})).range([0,L]),p.domain(c||d3.extent(d3.merge(B).concat($),function(e){return e.y})).range([0,L]),d.yDomain(h.domain()),m.yDomain(h.domain()),y.yDomain(h.domain()),v.yDomain(p.domain()),g.yDomain(p.domain()),b.yDomain(p.domain()),D.length&&d3.transition(U).call(y),P.length&&d3.transition(X).call(b),M.length&&d3.transition(R).call(m),_.length&&d3.transition(W).call(g),A.length&&d3.transition(q).call(d),O.length&&d3.transition(z).call(v),w.ticks(k/100).tickSize(-L,0),I.select(".x.axis").attr("transform","translate(0,"+L+")"),d3.transition(I.select(".x.axis")).call(w),E.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y1.axis")).call(E),S.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y2.axis")).call(S),I.select(".y2.axis").style("opacity",B.length?1:0).attr("transform","translate("+a.range()[1]+",0)"),x.dispatch.on("stateChange",function(e){C.update()}),T.on("tooltipShow",function(e){o&&N(e,f.parentNode)})}),C}var t={top:30,right:20,bottom:50,left:60},n=d3.scale.category20().range(),r=null,i=null,s=!0,o=!0,u=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},a,f,l,c,a=d3.scale.linear(),h=d3.scale.linear(),p=d3.scale.linear(),d=e.models.line().yScale(h),v=e.models.line().yScale(p),m=e.models.multiBar().stacked(!1).yScale(h),g=e.models.multiBar().stacked(!1).yScale(p),y=e.models.stackedArea().yScale(h),b=e.models.stackedArea().yScale(p),w=e.models.axis().scale(a).orient("bottom").tickPadding(5),E=e.models.axis().scale(h).orient("left"),S=e.models.axis().scale(p).orient("right"),x=e.models.legend().height(30),T=d3.dispatch("tooltipShow","tooltipHide"),N=function(t,n){var r=t.pos[0]+(n.offsetLeft||0),i=t.pos[1]+(n.offsetTop||0),s=w.tickFormat()(d.x()(t.point,t.pointIndex)),o=(t.series.yAxis==2?S:E).tickFormat()(d.y()(t.point,t.pointIndex)),a=u(t.series.key,s,o,t,C);e.tooltip.show([r,i],a,undefined,undefined,n.offsetParent)};return d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),m.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),m.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),g.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),g.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),y.dispatch.on("tooltipShow",function(e){if(!Math.round(y.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),y.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),b.dispatch.on("tooltipShow",function(e){if(!Math.round(b.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),b.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){o&&e.tooltip.cleanup()}),C.dispatch=T,C.lines1=d,C.lines2=v,C.bars1=m,C.bars2=g,C.stack1=y,C.stack2=b,C.xAxis=w,C.yAxis1=E,C.yAxis2=S,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(getX=e,d.x(e),m.x(e),C):getX},C.y=function(e){return arguments.length?(getY=e,d.y(e),m.y(e),C):getY},C.yDomain1=function(e){return arguments.length?(l=e,C):l},C.yDomain2=function(e){return arguments.length?(c=e,C):c},C.margin=function(e){return arguments.length?(t=e,C):t},C.width=function(e){return arguments.length?(r=e,C):r},C.height=function(e){return arguments.length?(i=e,C):i},C.color=function(e){return arguments.length?(n=e,x.color(e),C):n},C.showLegend=function(e){return arguments.length?(s=e,C):s},C.tooltips=function(e){return arguments.length?(o=e,C):o},C.tooltipContent=function(e){return arguments.length?(u=e,C):u},C},e.models.ohlcBar=function(){function x(e){return e.each(function(e){var g=n-t.left-t.right,x=r-t.top-t.bottom,T=d3.select(this);s.domain(y||d3.extent(e[0].values.map(u).concat(p))),v?s.range(w||[g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range(w||[0,g]),o.domain(b||[d3.min(e[0].values.map(h).concat(d)),d3.max(e[0].values.map(c).concat(d))]).range(E||[x,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([e[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-ticks"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){S.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",x),A.attr("clip-path",m?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-ticks").selectAll(".nv-tick").data(function(e){return e});O.exit().remove();var M=O.enter().append("path").attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"}).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),S.elementMouseover({point:t,series:e[0],pos:[s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),S.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){S.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){S.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}),d3.transition(O).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"})}),x}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=function(e){return e.open},l=function(e){return e.close},c=function(e){return e.high},h=function(e){return e.low},p=[],d=[],v=!1,m=!0,g=e.utils.defaultColor(),y,b,w,E,S=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return x.dispatch=S,x.options=e.utils.optionsFunc.bind(x),x.x=function(e){return arguments.length?(u=e,x):u},x.y=function(e){return arguments.length?(a=e,x):a},x.open=function(e){return arguments.length?(f=e,x):f},x.close=function(e){return arguments.length?(l=e,x):l},x.high=function(e){return arguments.length?(c=e,x):c},x.low=function(e){return arguments.length?(h=e,x):h},x.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,x):t},x.width=function(e){return arguments.length?(n=e,x):n},x.height=function(e){return arguments.length?(r=e,x):r},x.xScale=function(e){return arguments.length?(s=e,x):s},x.yScale=function(e){return arguments.length?(o=e,x):o},x.xDomain=function(e){return arguments.length?(y=e,x):y},x.yDomain=function(e){return arguments.length?(b=e,x):b},x.xRange=function(e){return arguments.length?(w=e,x):w},x.yRange=function(e){return arguments.length?(E=e,x):E},x.forceX=function(e){return arguments.length?(p=e,x):p},x.forceY=function(e){return arguments.length?(d=e,x):d},x.padData=function(e){return arguments.length?(v=e,x):v},x.clipEdge=function(e){return arguments.length?(m=e,x):m},x.color=function(t){return arguments.length?(g=e.utils.getColor(t),x):g},x.id=function(e){return arguments.length?(i=e,x):i},x},e.models.pie=function(){function S(e){return e.each(function(e){function q(e){var t=(e.startAngle+e.endAngle)*90/Math.PI-90;return t>90?t-180:t}function R(e){e.endAngle=isNaN(e.endAngle)?0:e.endAngle,e.startAngle=isNaN(e.startAngle)?0:e.startAngle,m||(e.innerRadius=0);var t=d3.interpolate(this._current,e);return this._current=t(0),function(e){return A(t(e))}}function U(e){e.innerRadius=0;var t=d3.interpolate({startAngle:0,endAngle:0},e);return function(e){return A(t(e))}}var o=n-t.left-t.right,f=r-t.top-t.bottom,S=Math.min(o,f)/2,x=S-S/5,T=d3.select(this),N=T.selectAll(".nv-wrap.nv-pie").data(e),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+u),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-pie"),k.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+t.left+","+t.top+")"),L.select(".nv-pie").attr("transform","translate("+o/2+","+f/2+")"),L.select(".nv-pieLabels").attr("transform","translate("+o/2+","+f/2+")"),T.on("click",function(e,t){E.chartClick({data:e,index:t,pos:d3.event,id:u})});var A=d3.svg.arc().outerRadius(x);y&&A.startAngle(y),b&&A.endAngle(b),m&&A.innerRadius(S*w);var O=d3.layout.pie().sort(null).value(function(e){return e.disabled?0:s(e)}),M=N.select(".nv-pie").selectAll(".nv-slice").data(O),_=N.select(".nv-pieLabels").selectAll(".nv-label").data(O);M.exit().remove(),_.exit().remove();var D=M.enter().append("g").attr("class","nv-slice").on("mouseover",function(e,t){d3.select(this).classed("hover",!0),E.elementMouseover({label:i(e.data),value:s(e.data),point:e.data,pointIndex:t,pos:[d3.event.pageX,d3.event.pageY],id:u})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),E.elementMouseout({label:i(e.data),value:s(e.data),point:e.data,index:t,id:u})}).on("click",function(e,t){E.elementClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()}).on("dblclick",function(e,t){E.elementDblClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()});M.attr("fill",function(e,t){return a(e,t)}).attr("stroke",function(e,t){return a(e,t)});var P=D.append("path").each(function(e){this._current=e});M.select("path").attr("d",A);if(l){var H=d3.svg.arc().innerRadius(0);c&&(H=A),h&&(H=d3.svg.arc().outerRadius(A.outerRadius())),_.enter().append("g").classed("nv-label",!0).each(function(e,t){var n=d3.select(this);n.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}return e.outerRadius=S+10,e.innerRadius=S+15,"translate("+H.centroid(e)+")"}),n.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),n.append("text").style("text-anchor",g?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")});var B={},j=14,F=140,I=function(e){return Math.floor(e[0]/F)*F+","+Math.floor(e[1]/j)*j};_.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}e.outerRadius=S+10,e.innerRadius=S+15;var n=H.centroid(e),r=I(n);return B[r]&&(n[1]-=j),B[I(n)]=!0,"translate("+n+")"}),_.select(".nv-label text").style("text-anchor",g?(d.startAngle+d.endAngle)/2<Math.PI?"start":"end":"middle").text(function(e,t){var n=(e.endAngle-e.startAngle)/(2*Math.PI),r={key:i(e.data),value:s(e.data),percent:d3.format("%")(n)};return e.value&&n>v?r[p]:""})}}),S}var t={top:0,right:0,bottom:0,left:0},n=500,r=500,i=function(e){return e.x},s=function(e){return e.y},o=function(e){return e.description},u=Math.floor(Math.random()*1e4),a=e.utils.defaultColor(),f=d3.format(",.2f"),l=!0,c=!0,h=!1,p="key",v=.02,m=!1,g=!1,y=!1,b=!1,w=.5,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return S.dispatch=E,S.options=e.utils.optionsFunc.bind(S),S.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,S):t},S.width=function(e){return arguments.length?(n=e,S):n},S.height=function(e){return arguments.length?(r=e,S):r},S.values=function(t){return e.log("pie.values() is no longer supported."),S},S.x=function(e){return arguments.length?(i=e,S):i},S.y=function(e){return arguments.length?(s=d3.functor(e),S):s},S.description=function(e){return arguments.length?(o=e,S):o},S.showLabels=function(e){return arguments.length?(l=e,S):l},S.labelSunbeamLayout=function(e){return arguments.length?(g=e,S):g},S.donutLabelsOutside=function(e){return arguments.length?(h=e,S):h},S.pieLabelsOutside=function(e){return arguments.length?(c=e,S):c},S.labelType=function(e){return arguments.length?(p=e,p=p||"key",S):p},S.donut=function(e){return arguments.length?(m=e,S):m},S.donutRatio=function(e){return arguments.length?(w=e,S):w},S.startAngle=function(e){return arguments.length?(y=e,S):y},S.endAngle=function(e){return arguments.length?(b=e,S):b},S.id=function(e){return arguments.length?(u=e,S):u},S.color=function(t){return arguments.length?(a=e.utils.getColor(t),S):a},S.valueFormat=function(e){return arguments.length?(f=e,S):f},S.labelThreshold=function(e){return arguments.length?(v=e,S):v},S},e.models.pieChart=function(){function v(e){return e.each(function(e){var u=d3.select(this),a=this,f=(i||parseInt(u.style("width"))||960)-r.left-r.right,d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom;v.update=function(){u.call(v)},v.container=this,l.disabled=e.map(function(e){return!!e.disabled});if(!c){var m;c={};for(m in l)l[m]instanceof Array?c[m]=l[m].slice(0):c[m]=l[m]}if(!e||!e.length){var g=u.selectAll(".nv-noData").data([h]);return g.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),g.attr("x",r.left+f/2).attr("y",r.top+d/2).text(function(e){return e}),v}u.selectAll(".nv-noData").remove();var y=u.selectAll("g.nv-wrap.nv-pieChart").data([e]),b=y.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),w=y.select("g");b.append("g").attr("class","nv-pieWrap"),b.append("g").attr("class","nv-legendWrap"),o&&(n.width(f).key(t.x()),y.select(".nv-legendWrap").datum(e).call(n),r.top!=n.height()&&(r.top=n.height(),d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom),y.select(".nv-legendWrap").attr("transform","translate(0,"+ -r.top+")")),y.attr("transform","translate("+r.left+","+r.top+")"),t.width(f).height(d);var E=w.select(".nv-pieWrap").datum([e]);d3.transition(E).call(t),n.dispatch.on("stateChange",function(e){l=e,p.stateChange(l),v.update()}),t.dispatch.on("elementMouseout.tooltip",function(e){p.tooltipHide(e)}),p.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),l.disabled=t.disabled),v.update()})}),v}var t=e.models.pie(),n=e.models.legend(),r={top:30,right:20,bottom:20,left:20},i=null,s=null,o=!0,u=e.utils.defaultColor(),a=!0,f=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+t+"</p>"},l={},c=null,h="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),d=function(n,r){var i=t.description()(n.point)||t.x()(n.point),s=n.pos[0]+(r&&r.offsetLeft||0),o=n.pos[1]+(r&&r.offsetTop||0),u=t.valueFormat()(t.y()(n.point)),a=f(i,u,n,v);e.tooltip.show([s,o],a,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+r.left,e.pos[1]+r.top],p.tooltipShow(e)}),p.on("tooltipShow",function(e){a&&d(e)}),p.on("tooltipHide",function(){a&&e.tooltip.cleanup()}),v.legend=n,v.dispatch=p,v.pie=t,d3.rebind(v,t,"valueFormat","values","x","y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","labelType","donut","donutRatio","labelThreshold"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(r.top=typeof e.top!="undefined"?e.top:r.top,r.right=typeof e.right!="undefined"?e.right:r.right,r.bottom=typeof e.bottom!="undefined"?e.bottom:r.bottom,r.left=typeof e.left!="undefined"?e.left:r.left,v):r},v.width=function(e){return arguments.length?(i=e,v):i},v.height=function(e){return arguments.length?(s=e,v):s},v.color=function(r){return arguments.length?(u=e.utils.getColor(r),n.color(u),t.color(u),v):u},v.showLegend=function(e){return arguments.length?(o=e,v):o},v.tooltips=function(e){return arguments.length?(a=e,v):a},v.tooltipContent=function(e){return arguments.length?(f=e,v):f},v.state=function(e){return arguments.length?(l=e,v):l},v.defaultState=function(e){return arguments.length?(c=e,v):c},v.noData=function(e){return arguments.length?(h=e,v):h},v},e.models.scatter=function(){function I(q){return q.each(function(I){function Q(){if(!g)return!1;var e,i=d3.merge(I.map(function(e,t){return e.values.map(function(e,n){var r=f(e,n),i=l(e,n);return[o(r),u(i),t,n,e]}).filter(function(e,t){return b(e[4],t)})}));if(D===!0){if(x){var a=X.select("defs").selectAll(".nv-point-clips").data([s]).enter();a.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+s);var c=X.select("#nv-points-clip-"+s).selectAll("circle").data(i);c.enter().append("circle").attr("r",T),c.exit().remove(),c.attr("cx",function(e){return e[0]}).attr("cy",function(e){return e[1]}),X.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+s+")")}i.length&&(i.push([o.range()[0]-20,u.range()[0]-20,null,null]),i.push([o.range()[1]+20,u.range()[1]+20,null,null]),i.push([o.range()[0]-20,u.range()[0]+20,null,null]),i.push([o.range()[1]+20,u.range()[1]-20,null,null]));var h=d3.geom.polygon([[-10,-10],[-10,r+10],[n+10,r+10],[n+10,-10]]),p=1e-6;i=i.sort(function(e,t){return e[0]-t[0]||e[1]-t[1]});for(var d=0;d<i.length-1;)Math.abs(i[d][0]-i[d+1][0])<p&&Math.abs(i[d][1]-i[d+1][1])<p?i.splice(d+1,1):d++;var v=d3.geom.voronoi(i).map(function(e,t){return{data:h.clip(e),series:i[t][2],point:i[t][3]}}),m=X.select(".nv-point-paths").selectAll("path").data(v);m.enter().append("path").attr("class",function(e,t){return"nv-path-"+t}),m.exit().remove(),m.attr("d",function(e){return!e||!e.data||e.data.length===0?"M 0 0":"M"+e.data.join("L")+"Z"});var y=function(e,n){if(F)return 0;var r=I[e.series];if(typeof r=="undefined")return;var i=r.values[e.point];n({point:i,series:r,pos:[o(f(i,e.point))+t.left,u(l(i,e.point))+t.top],seriesIndex:e.series,pointIndex:e.point})};m.on("click",function(e){y(e,_.elementClick)}).on("mouseover",function(e){y(e,_.elementMouseover)}).on("mouseout",function(e,t){y(e,_.elementMouseout)})}else X.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementClick({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseover",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementMouseover({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseout",function(e,t){if(F||!I[e.series])return 0;var n=I[e.series],r=n.values[t];_.elementMouseout({point:r,series:n,seriesIndex:e.series,pointIndex:t})});F=!1}var q=n-t.left-t.right,R=r-t.top-t.bottom,U=d3.select(this);I.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var W=N&&C&&A?[]:d3.merge(I.map(function(e){return e.values.map(function(e,t){return{x:f(e,t),y:l(e,t),size:c(e,t)}})}));o.domain(N||d3.extent(W.map(function(e){return e.x}).concat(d))),w&&I[0]?o.range(k||[(q*E+q)/(2*I[0].values.length),q-q*(1+E)/(2*I[0].values.length)]):o.range(k||[0,q]),u.domain(C||d3.extent(W.map(function(e){return e.y}).concat(v))).range(L||[R,0]),a.domain(A||d3.extent(W.map(function(e){return e.size}).concat(m))).range(O||[16,256]);if(o.domain()[0]===o.domain()[1]||u.domain()[0]===u.domain()[1])M=!0;o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]-o.domain()[0]*.01,o.domain()[1]+o.domain()[1]*.01]):o.domain([-1,1])),u.domain()[0]===u.domain()[1]&&(u.domain()[0]?u.domain([u.domain()[0]-u.domain()[0]*.01,u.domain()[1]+u.domain()[1]*.01]):u.domain([-1,1])),isNaN(o.domain()[0])&&o.domain([-1,1]),isNaN(u.domain()[0])&&u.domain([-1,1]),P=P||o,H=H||u,B=B||a;var X=U.selectAll("g.nv-wrap.nv-scatter").data([I]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+s+(M?" nv-single-point":"")),$=V.append("defs"),J=V.append("g"),K=X.select("g");J.append("g").attr("class","nv-groups"),J.append("g").attr("class","nv-point-paths"),X.attr("transform","translate("+t.left+","+t.top+")"),$.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),X.select("#nv-edge-clip-"+s+" rect").attr("width",q).attr("height",R>0?R:0),K.attr("clip-path",S?"url(#nv-edge-clip-"+s+")":""),F=!0;var G=X.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});G.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),G.exit().remove(),G.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),G.style("fill",function(e,t){return i(e,t)}).style("stroke",function(e,t){return i(e,t)}).style("stroke-opacity",1).style("fill-opacity",.5);if(p){var Y=G.selectAll("circle.nv-point").data(function(e){return e.values},y);Y.enter().append("circle").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("cx",function(t,n){return e.utils.NaNtoZero(P(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(H(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)}),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)})}else{var Y=G.selectAll("path.nv-point").data(function(e){return e.values});Y.enter().append("path").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("transform",function(e,t){return"translate("+P(f(e,t))+","+H(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))})),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))}))}clearTimeout(j),j=setTimeout(Q,300),P=o.copy(),H=u.copy(),B=a.copy()}),I}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=d3.scale.linear(),u=d3.scale.linear(),a=d3.scale.linear(),f=function(e){return e.x},l=function(e){return e.y},c=function(e){return e.size||1},h=function(e){return e.shape||"circle"},p=!0,d=[],v=[],m=[],g=!0,y=null,b=function(e){return!e.notActive},w=!1,E=.1,S=!1,x=!0,T=function(){return 25},N=null,C=null,k=null,L=null,A=null,O=null,M=!1,_=d3.dispatch("elementClick","elementMouseover","elementMouseout"),D=!0,P,H,B,j,F=!1;return I.clearHighlights=function(){d3.selectAll(".nv-chart-"+s+" .nv-point.hover").classed("hover",!1)},I.highlightPoint=function(e,t,n){d3.select(".nv-chart-"+s+" .nv-series-"+e+" .nv-point-"+t).classed("hover",n)},_.on("elementMouseover.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!0)}),_.on("elementMouseout.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!1)}),I.dispatch=_,I.options=e.utils.optionsFunc.bind(I),I.x=function(e){return arguments.length?(f=d3.functor(e),I):f},I.y=function(e){return arguments.length?(l=d3.functor(e),I):l},I.size=function(e){return arguments.length?(c=d3.functor(e),I):c},I.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,I):t},I.width=function(e){return arguments.length?(n=e,I):n},I.height=function(e){return arguments.length?(r=e,I):r},I.xScale=function(e){return arguments.length?(o=e,I):o},I.yScale=function(e){return arguments.length?(u=e,I):u},I.zScale=function(e){return arguments.length?(a=e,I):a},I.xDomain=function(e){return arguments.length?(N=e,I):N},I.yDomain=function(e){return arguments.length?(C=e,I):C},I.sizeDomain=function(e){return arguments.length?(A=e,I):A},I.xRange=function(e){return arguments.length?(k=e,I):k},I.yRange=function(e){return arguments.length?(L=e,I):L},I.sizeRange=function(e){return arguments.length?(O=e,I):O},I.forceX=function(e){return arguments.length?(d=e,I):d},I.forceY=function(e){return arguments.length?(v=e,I):v},I.forceSize=function(e){return arguments.length?(m=e,I):m},I.interactive=function(e){return arguments.length?(g=e,I):g},I.pointKey=function(e){return arguments.length?(y=e,I):y},I.pointActive=function(e){return arguments.length?(b=e,I):b},I.padData=function(e){return arguments.length?(w=e,I):w},I.padDataOuter=function(e){return arguments.length?(E=e,I):E},I.clipEdge=function(e){return arguments.length?(S=e,I):S},I.clipVoronoi=function(e){return arguments.length?(x=e,I):x},I.useVoronoi=function(e){return arguments.length?(D=e,D===!1&&(x=!1),I):D},I.clipRadius=function(e){return arguments.length?(T=e,I):T},I.color=function(t){return arguments.length?(i=e.utils.getColor(t),I):i},I.shape=function(e){return arguments.length?(h=e,I):h},I.onlyCircles=function(e){return arguments.length?(p=e,I):p},I.id=function(e){return arguments.length?(s=e,I):s},I.singlePoint=function(e){return arguments.length?(M=e,I):M},I},e.models.scatterChart=function(){function F(e){return e.each(function(e){function J(){if(T)return W.select(".nv-point-paths").style("pointer-events","all"),!1;W.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(x).focus(i[0]),p.distortion(x).focus(i[1]),W.select(".nv-scatterWrap").call(t),b&&W.select(".nv-x.nv-axis").call(n),w&&W.select(".nv-y.nv-axis").call(r),W.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),W.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var C=d3.select(this),k=this,L=(f||parseInt(C.style("width"))||960)-a.left-a.right,D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom;F.update=function(){C.call(F)},F.container=this,A.disabled=e.map(function(e){return!!e.disabled});if(!O){var I;O={};for(I in A)A[I]instanceof Array?O[I]=A[I].slice(0):O[I]=A[I]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=C.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",a.left+L/2).attr("y",a.top+D/2).text(function(e){return e}),F}C.selectAll(".nv-noData").remove(),P=P||h,H=H||p;var R=C.selectAll("g.nv-wrap.nv-scatterChart").data([e]),U=R.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),z=U.append("g"),W=R.select("g");z.append("rect").attr("class","nvd3 nv-background"),z.append("g").attr("class","nv-x nv-axis"),z.append("g").attr("class","nv-y nv-axis"),z.append("g").attr("class","nv-scatterWrap"),z.append("g").attr("class","nv-distWrap"),z.append("g").attr("class","nv-legendWrap"),z.append("g").attr("class","nv-controlsWrap");if(y){var X=S?L/2:L;i.width(X),R.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom),R.select(".nv-legendWrap").attr("transform","translate("+(L-X)+","+ -a.top+")")}S&&(s.width(180).color(["#444"]),W.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -a.top+")").call(s)),R.attr("transform","translate("+a.left+","+a.top+")"),E&&W.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),t.width(L).height(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),d!==0&&t.xDomain(null),v!==0&&t.yDomain(null),R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t);if(d!==0){var V=h.domain()[1]-h.domain()[0];t.xDomain([h.domain()[0]-d*V,h.domain()[1]+d*V])}if(v!==0){var $=p.domain()[1]-p.domain()[0];t.yDomain([p.domain()[0]-v*$,p.domain()[1]+v*$])}(v!==0||d!==0)&&R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),b&&(n.scale(h).ticks(n.ticks()&&n.ticks().length?n.ticks():L/100).tickSize(-D,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),w&&(r.scale(p).ticks(r.ticks()&&r.ticks().length?r.ticks():D/36).tickSize(-L,0),W.select(".nv-y.nv-axis").call(r)),m&&(o.getData(t.x()).scale(h).width(L).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),W.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),g&&(u.getData(t.y()).scale(p).width(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),W.select(".nv-distributionY").attr("transform","translate("+(E?L:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(W.select(".nv-background").attr("width",L).attr("height",D),W.select(".nv-background").on("mousemove",J),W.select(".nv-background").on("click",function(){T=!T}),t.dispatch.on("elementClick.freezeFisheye",function(){T=!T})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,x=e.disabled?0:2.5,W.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),W.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(x).focus(0),p.distortion(x).focus(0),W.select(".nv-scatterWrap").call(t),W.select(".nv-x.nv-axis").call(n),W.select(".nv-y.nv-axis").call(r)):T=!1,F.update()}),i.dispatch.on("stateChange",function(e){A.disabled=e.disabled,M.stateChange(A),F.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",function(t,n){return e.pos[1]-D}),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],M.tooltipShow(e)}),M.on("tooltipShow",function(e){N&&B(e,k.parentNode)}),M.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),A.disabled=t.disabled),F.update()}),P=h.copy(),H=p.copy()}),F}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=0,v=0,m=!1,g=!1,y=!0,b=!0,w=!0,E=!1,S=!!d3.fisheye,x=0,T=!1,N=!0,C=function(e,t,n){return"<strong>"+t+"</strong>"},k=function(e,t,n){return"<strong>"+n+"</strong>"},L=null,A={},O=null,M=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),_="No Data Available.",D=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(E?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var P,H,B=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));C!=null&&e.tooltip.show([f,l],C(i.series.key,v,m,i,F),"n",1,s,"x-nvtooltip"),k!=null&&e.tooltip.show([c,d],k(i.series.key,v,m,i,F),"e",1,s,"y-nvtooltip"),L!=null&&e.tooltip.show([o,u],L(i.series.key,v,m,i,F),i.value<0?"n":"s",null,s)},j=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){M.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),M.on("tooltipHide",function(){N&&e.tooltip.cleanup()}),F.dispatch=M,F.scatter=t,F.legend=i,F.controls=s,F.xAxis=n,F.yAxis=r,F.distX=o,F.distY=u,d3.rebind(F,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),F.options=e.utils.optionsFunc.bind(F),F.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,F):a},F.width=function(e){return arguments.length?(f=e,F):f},F.height=function(e){return arguments.length?(l=e,F):l},F.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),F):c},F.showDistX=function(e){return arguments.length?(m=e,F):m},F.showDistY=function(e){return arguments.length?(g=e,F):g},F.showControls=function(e){return arguments.length?(S=e,F):S},F.showLegend=function(e){return arguments.length?(y=e,F):y},F.showXAxis=function(e){return arguments.length?(b=e,F):b},F.showYAxis=function(e){return arguments.length?(w=e,F):w},F.rightAlignYAxis=function(e){return arguments.length?(E=e,r.orient(e?"right":"left"),F):E},F.fisheye=function(e){return arguments.length?(x=e,F):x},F.xPadding=function(e){return arguments.length?(d=e,F):d},F.yPadding=function(e){return arguments.length?(v=e,F):v},F.tooltips=function(e){return arguments.length?(N=e,F):N},F.tooltipContent=function(e){return arguments.length?(L=e,F):L},F.tooltipXContent=function(e){return arguments.length?(C=e,F):C},F.tooltipYContent=function(e){return arguments.length?(k=e,F):k},F.state=function(e){return arguments.length?(A=e,F):A},F.defaultState=function(e){return arguments.length?(O=e,F):O},F.noData=function(e){return arguments.length?(_=e,F):_},F.transitionDuration=function(e){return arguments.length?(D=e,F):D},F},e.models.scatterPlusLineChart=function(){function B(e){return e.each(function(e){function V(){if(S)return U.select(".nv-point-paths").style("pointer-events","all"),!1;U.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(E).focus(i[0]),p.distortion(E).focus(i[1]),U.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),g&&U.select(".nv-x.nv-axis").call(n),y&&U.select(".nv-y.nv-axis").call(r),U.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),U.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var T=d3.select(this),N=this,C=(f||parseInt(T.style("width"))||960)-a.left-a.right,M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom;B.update=function(){T.call(B)},B.container=this,k.disabled=e.map(function(e){return!!e.disabled});if(!L){var j;L={};for(j in k)k[j]instanceof Array?L[j]=k[j].slice(0):L[j]=k[j]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var F=T.selectAll(".nv-noData").data([O]);return F.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),F.attr("x",a.left+C/2).attr("y",a.top+M/2).text(function(e){return e}),B}T.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale(),_=_||h,D=D||p;var I=T.selectAll("g.nv-wrap.nv-scatterChart").data([e]),q=I.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),R=q.append("g"),U=I.select("g");R.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-scatterWrap"),R.append("g").attr("class","nv-regressionLinesWrap"),R.append("g").attr("class","nv-distWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),I.attr("transform","translate("+a.left+","+a.top+")"),b&&U.select(".nv-y.nv-axis").attr("transform","translate("+C+",0)"),m&&(i.width(C/2),I.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom),I.select(".nv-legendWrap").attr("transform","translate("+C/2+","+ -a.top+")")),w&&(s.width(180).color(["#444"]),U.select(".nv-controlsWrap").datum(H).attr("transform","translate(0,"+ -a.top+")").call(s)),t.width(C).height(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),I.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),I.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+t.id()+")");var z=I.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(e){return e});z.enter().append("g").attr("class","nv-regLines");var W=z.selectAll(".nv-regLine").data(function(e){return[e]}),X=W.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0);W.attr("x1",h.range()[0]).attr("x2",h.range()[1]).attr("y1",function(e,t){return p(h.domain()[0]*e.slope+e.intercept)}).attr("y2",function(e,t){return p(h.domain()[1]*e.slope+e.intercept)}).style("stroke",function(e,t,n){return c(e,n)}).style("stroke-opacity",function(e,t){return e.disabled||typeof e.slope=="undefined"||typeof e.intercept=="undefined"?0:1}),g&&(n.scale(h).ticks(n.ticks()?n.ticks():C/100).tickSize(-M,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),y&&(r.scale(p).ticks(r.ticks()?r.ticks():M/36).tickSize(-C,0),U.select(".nv-y.nv-axis").call(r)),d&&(o.getData(t.x()).scale(h).width(C).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),U.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),v&&(u.getData(t.y()).scale(p).width(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),U.select(".nv-distributionY").attr("transform","translate("+(b?C:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(U.select(".nv-background").attr("width",C).attr("height",M),U.select(".nv-background").on("mousemove",V),U.select(".nv-background").on("click",function(){S=!S}),t.dispatch.on("elementClick.freezeFisheye",function(){S=!S})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,E=e.disabled?0:2.5,U.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),U.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(E).focus(0),p.distortion(E).focus(0),U.select(".nv-scatterWrap").call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r)):S=!1,B.update()}),i.dispatch.on("stateChange",function(e){k=e,A.stateChange(k),B.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-M),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],A.tooltipShow(e)}),A.on("tooltipShow",function(e){x&&P(e,N.parentNode)}),A.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),k.disabled=t.disabled),B.update()}),_=h.copy(),D=p.copy()}),B}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=!1,v=!1,m=!0,g=!0,y=!0,b=!1,w=!!d3.fisheye,E=0,S=!1,x=!0,T=function(e,t,n){return"<strong>"+t+"</strong>"},N=function(e,t,n){return"<strong>"+n+"</strong>"},C=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+r+"</p>"},k={},L=null,A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),O="No Data Available.",M=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(b?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var _,D,P=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));T!=null&&e.tooltip.show([f,l],T(i.series.key,v,m,i,B),"n",1,s,"x-nvtooltip"),N!=null&&e.tooltip.show([c,d],N(i.series.key,v,m,i,B),"e",1,s,"y-nvtooltip"),C!=null&&e.tooltip.show([o,u],C(i.series.key,v,m,i.point.tooltip,i,B),i.value<0?"n":"s",null,s)},H=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){A.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),A.on("tooltipHide",function(){x&&e.tooltip.cleanup()}),B.dispatch=A,B.scatter=t,B.legend=i,B.controls=s,B.xAxis=n,B.yAxis=r,B.distX=o,B.distY=u,d3.rebind(B,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),B.options=e.utils.optionsFunc.bind(B),B.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,B):a},B.width=function(e){return arguments.length?(f=e,B):f},B.height=function(e){return arguments.length?(l=e,B):l},B.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),B):c},B.showDistX=function(e){return arguments.length?(d=e,B):d},B.showDistY=function(e){return arguments.length?(v=e,B):v},B.showControls=function(e){return arguments.length?(w=e,B):w},B.showLegend=function(e){return arguments.length?(m=e,B):m},B.showXAxis=function(e){return arguments.length?(g=e,B):g},B.showYAxis=function(e){return arguments.length?(y=e,B):y},B.rightAlignYAxis=function(e){return arguments.length?(b=e,r.orient(e?"right":"left"),B):b},B.fisheye=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(x=e,B):x},B.tooltipContent=function(e){return arguments.length?(C=e,B):C},B.tooltipXContent=function(e){return arguments.length?(T=e,B):T},B.tooltipYContent=function(e){return arguments.length?(N=e,B):N},B.state=function(e){return arguments.length?(k=e,B):k},B.defaultState=function(e){return arguments.length?(L=e,B):L},B.noData=function(e){return arguments.length?(O=e,B):O},B.transitionDuration=function(e){return arguments.length?(M=e,B):M},B},e.models.sparkline=function(){function d(e){return e.each(function(e){var i=n-t.left-t.right,d=r-t.top-t.bottom,v=d3.select(this);s.domain(l||d3.extent(e,u)).range(h||[0,i]),o.domain(c||d3.extent(e,a)).range(p||[d,0]);var m=v.selectAll("g.nv-wrap.nv-sparkline").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline"),b=g.append("g"),w=m.select("g");m.attr("transform","translate("+t.left+","+t.top+")");var E=m.selectAll("path").data(function(e){return[e]});E.enter().append("path"),E.exit().remove(),E.style("stroke",function(e,t){return e.color||f(e,t)}).attr("d",d3.svg.line().x(function(e,t){return s(u(e,t))}).y(function(e,t){return o(a(e,t))}));var S=m.selectAll("circle.nv-point").data(function(e){function n(t){if(t!=-1){var n=e[t];return n.pointIndex=t,n}return null}var t=e.map(function(e,t){return a(e,t)}),r=n(t.lastIndexOf(o.domain()[1])),i=n(t.indexOf(o.domain()[0])),s=n(t.length-1);return[i,r,s].filter(function(e){return e!=null})});S.enter().append("circle"),S.exit().remove(),S.attr("cx",function(e,t){return s(u(e,e.pointIndex))}).attr("cy",function(e,t){return o(a(e,e.pointIndex))}).attr("r",2).attr("class",function(e,t){return u(e,e.pointIndex)==s.domain()[1]?"nv-point nv-currentValue":a(e,e.pointIndex)==o.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),d}var t={top:2,right:0,bottom:2,left:0},n=400,r=32,i=!0,s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=e.utils.getColor(["#000"]),l,c,h,p;return d.options=e.utils.optionsFunc.bind(d),d.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,d):t},d.width=function(e){return arguments.length?(n=e,d):n},d.height=function(e){return arguments.length?(r=e,d):r},d.x=function(e){return arguments.length?(u=d3.functor(e),d):u},d.y=function(e){return arguments.length?(a=d3.functor(e),d):a},d.xScale=function(e){return arguments.length?(s=e,d):s},d.yScale=function(e){return arguments.length?(o=e,d):o},d.xDomain=function(e){return arguments.length?(l=e,d):l},d.yDomain=function(e){return arguments.length?(c=e,d):c},d.xRange=function(e){return arguments.length?(h=e,d):h},d.yRange=function(e){return arguments.length?(p=e,d):p},d.animate=function(e){return arguments.length?(i=e,d):i},d.color=function(t){return arguments.length?(f=e.utils.getColor(t),d):f},d},e.models.sparklinePlus=function(){function v(e){return e.each(function(c){function O(){if(a)return;var e=C.selectAll(".nv-hoverValue").data(u),r=e.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);e.exit().style("stroke-opacity",0).style("fill-opacity",0).remove(),e.attr("transform",function(e){return"translate("+s(t.x()(c[e],e))+",0)"}).style("stroke-opacity",1).style("fill-opacity",1);if(!u.length)return;r.append("line").attr("x1",0).attr("y1",-n.top).attr("x2",0).attr("y2",b),r.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-n.top).attr("text-anchor","end").attr("dy",".9em"),C.select(".nv-hoverValue .nv-xValue").text(f(t.x()(c[u[0]],u[0]))),r.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-n.top).attr("text-anchor","start").attr("dy",".9em"),C.select(".nv-hoverValue .nv-yValue").text(l(t.y()(c[u[0]],u[0])))}function M(){function r(e,n){var r=Math.abs(t.x()(e[0],0)-n),i=0;for(var s=0;s<e.length;s++)Math.abs(t.x()(e[s],s)-n)<r&&(r=Math.abs(t.x()(e[s],s)-n),i=s);return i}if(a)return;var e=d3.mouse(this)[0]-n.left;u=[r(c,Math.round(s.invert(e)))],O()}var m=d3.select(this),g=(r||parseInt(m.style("width"))||960)-n.left-n.right,b=(i||parseInt(m.style("height"))||400)-n.top-n.bottom;v.update=function(){v(e)},v.container=this;if(!c||!c.length){var w=m.selectAll(".nv-noData").data([d]);return w.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),w.attr("x",n.left+g/2).attr("y",n.top+b/2).text(function(e){return e}),v}m.selectAll(".nv-noData").remove();var E=t.y()(c[c.length-1],c.length-1);s=t.xScale(),o=t.yScale();var S=m.selectAll("g.nv-wrap.nv-sparklineplus").data([c]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-sparklineWrap"),N.append("g").attr("class","nv-valueWrap"),N.append("g").attr("class","nv-hoverArea"),S.attr("transform","translate("+n.left+","+n.top+")");var k=C.select(".nv-sparklineWrap");t.width(g).height(b),k.call(t);var L=C.select(".nv-valueWrap"),A=L.selectAll(".nv-currentValue").data([E]);A.enter().append("text").attr("class","nv-currentValue").attr("dx",p?-8:8).attr("dy",".9em").style("text-anchor",p?"end":"start"),A.attr("x",g+(p?n.right:0)).attr("y",h?function(e){return o(e)}:0).style("fill",t.color()(c[c.length-1],c.length-1)).text(l(E)),N.select(".nv-hoverArea").append("rect").on("mousemove",M).on("click",function(){a=!a}).on("mouseout",function(){u=[],O()}),C.select(".nv-hoverArea rect").attr("transform",function(e){return"translate("+ -n.left+","+ -n.top+")"}).attr("width",g+n.left+n.right).attr("height",b+n.top)}),v}var t=e.models.sparkline(),n={top:15,right:100,bottom:10,left:50},r=null,i=null,s,o,u=[],a=!1,f=d3.format(",r"),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d="No Data Available.";return v.sparkline=t,d3.rebind(v,t,"x","y","xScale","yScale","color"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,v):n},v.width=function(e){return arguments.length?(r=e,v):r},v.height=function(e){return arguments.length?(i=e,v):i},v.xTickFormat=function(e){return arguments.length?(f=e,v):f},v.yTickFormat=function(e){return arguments.length?(l=e,v):l},v.showValue=function(e){return arguments.length?(c=e,v):c},v.alignValue=function(e){return arguments.length?(h=e,v):h},v.rightAlignValue=function(e){return arguments.length?(p=e,v):p},v.noData=function(e){return arguments.length?(d=e,v):d},v},e.models.stackedArea=function(){function g(e){return e.each(function(e){var a=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);p=v.xScale(),d=v.yScale();var E=e;e.forEach(function(e,t){e.seriesIndex=t,e.values=e.values.map(function(e,n){return e.index=n,e.seriesIndex=t,e})});var S=e.filter(function(e){return!e.disabled});e=d3.layout.stack().order(l).offset(f).values(function(e){return e.values}).x(o).y(u).out(function(e,t,n){var r=u(e)===0?0:n;e.display={y:r,y0:t}})(S);var T=w.selectAll("g.nv-wrap.nv-stackedarea").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),C=N.append("defs"),k=N.append("g"),L=T.select("g");k.append("g").attr("class","nv-areaWrap"),k.append("g").attr("class","nv-scatterWrap"),T.attr("transform","translate("+t.left+","+t.top+")"),v.width(a).height(b).x(o).y(function(e){return e.display.y+e.display.y0}).forceY([0]).color(e.map(function(e,t){return e.color||i(e,e.seriesIndex)}));var A=L.select(".nv-scatterWrap").datum(e);A.call(v),C.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),T.select("#nv-edge-clip-"+s+" rect").attr("width",a).attr("height",b),L.attr("clip-path",h?"url(#nv-edge-clip-"+s+")":"");var O=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y+e.display.y0)}).interpolate(c),M=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y0)}),_=L.select(".nv-areaWrap").selectAll("path.nv-area").data(function(e){return e});_.enter().append("path").attr("class",function(e,t){return"nv-area nv-area-"+t}).attr("d",function(e,t){return M(e.values,e.seriesIndex)}).on("mouseover",function(e,t){d3.select(this).classed("hover",!0),m.areaMouseover({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),m.areaMouseout({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("click",function(e,t){d3.select(this).classed("hover",!1),m.areaClick({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}),_.exit().remove(),_.style("fill",function(e,t){return e.color||i(e,e.seriesIndex)}).style("stroke",function(e,t){return e.color||i(e,e.seriesIndex)}),_.attr("d",function(e,t){return O(e.values,t)}),v.dispatch.on("elementMouseover.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!0)}),v.dispatch.on("elementMouseout.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!1)}),g.d3_stackedOffset_stackPercent=function(e){var t=e.length,n=e[0].length,r=1/t,i,s,o,a=[];for(s=0;s<n;++s){for(i=0,o=0;i<E.length;i++)o+=u(E[i].values[s]);if(o)for(i=0;i<t;i++)e[i][s][1]/=o;else for(i=0;i<t;i++)e[i][s][1]=r}for(s=0;s<n;++s)a[s]=0;return a}}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=function(e){return e.x},u=function(e){return e.y},a="stack",f="zero",l="default",c="linear",h=!1,p,d,v=e.models.scatter(),m=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout");return v.size(2.2).sizeDomain([2.2,2.2]),v.dispatch.on("elementClick.area",function(e){m.areaClick(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],m.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){m.tooltipHide(e)}),g.dispatch=m,g.scatter=v,d3.rebind(g,v,"interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","highlightPoint","clearHighlights"),g.options=e.utils.optionsFunc.bind(g),g.x=function(e){return arguments.length?(o=d3.functor(e),g):o},g.y=function(e){return arguments.length?(u=d3.functor(e),g):u},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.clipEdge=function(e){return arguments.length?(h=e,g):h},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),g):i},g.offset=function(e){return arguments.length?(f=e,g):f},g.order=function(e){return arguments.length?(l=e,g):l},g.style=function(e){if(!arguments.length)return a;a=e;switch(a){case"stack":g.offset("zero"),g.order("default");break;case"stream":g.offset("wiggle"),g.order("inside-out");break;case"stream-center":g.offset("silhouette"),g.order("inside-out");break;case"expand":g.offset("expand"),g.order("default");break;case"stack_percent":g.offset(g.d3_stackedOffset_stackPercent),g.order("default")}return g},g.interpolate=function(e){return arguments.length?(c=e,g):c},g},e.models.stackedAreaChart=function(){function M(y){return y.each(function(y){var A=d3.select(this),_=this,D=(a||parseInt(A.style("width"))||960)-u.left-u.right,P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom;M.update=function(){A.call(M)},M.container=this,S.disabled=y.map(function(e){return!!e.disabled});if(!x){var H;x={};for(H in S)S[H]instanceof Array?x[H]=S[H].slice(0):x[H]=S[H]}if(!y||!y.length||!y.filter(function(e){return e.values.length}).length){var B=A.selectAll(".nv-noData").data([T]);return B.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),B.attr("x",u.left+D/2).attr("y",u.top+P/2).text(function(e){return e}),M}A.selectAll(".nv-noData").remove(),b=t.xScale(),w=t.yScale();var j=A.selectAll("g.nv-wrap.nv-stackedAreaChart").data([y]),F=j.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),I=j.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-stackedWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-controlsWrap"),F.append("g").attr("class","nv-interactive"),I.select("rect").attr("width",D).attr("height",P);if(h){var q=c?D-C:D;i.width(q),I.select(".nv-legendWrap").datum(y).call(i),u.top!=i.height()&&(u.top=i.height(),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-legendWrap").attr("transform","translate("+(D-q)+","+ -u.top+")")}if(c){var R=[{key:L.stacked||"Stacked",metaKey:"Stacked",disabled:t.style()!="stack",style:"stack"},{key:L.stream||"Stream",metaKey:"Stream",disabled:t.style()!="stream",style:"stream"},{key:L.expanded||"Expanded",metaKey:"Expanded",disabled:t.style()!="expand",style:"expand"},{key:L.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:t.style()!="stack_percent",style:"stack_percent"}];C=k.length/3*260,R=R.filter(function(e){return k.indexOf(e.metaKey)!==-1}),s.width(C).color(["#444","#444","#444"]),I.select(".nv-controlsWrap").datum(R).call(s),u.top!=Math.max(s.height(),i.height())&&(u.top=Math.max(s.height(),i.height()),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-controlsWrap").attr("transform","translate(0,"+ -u.top+")")}j.attr("transform","translate("+u.left+","+u.top+")"),v&&I.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),m&&(o.width(D).height(P).margin({left:u.left,top:u.top}).svgContainer(A).xScale(b),j.select(".nv-interactive").call(o)),t.width(D).height(P);var U=I.select(".nv-stackedWrap").datum(y);U.call(t),p&&(n.scale(b).ticks(D/100).tickSize(-P,0),I.select(".nv-x.nv-axis").attr("transform","translate(0,"+P+")"),I.select(".nv-x.nv-axis").call(n)),d&&(r.scale(w).ticks(t.offset()=="wiggle"?0:P/36).tickSize(-D,0).setTickFormat(t.style()=="expand"||t.style()=="stack_percent"?d3.format("%"):E),I.select(".nv-y.nv-axis").call(r)),t.dispatch.on("areaClick.toggle",function(e){y.filter(function(e){return!e.disabled}).length===1?y.forEach(function(e){e.disabled=!1}):y.forEach(function(t,n){t.disabled=n!=e.seriesIndex}),S.disabled=y.map(function(e){return!!e.disabled}),N.stateChange(S),M.update()}),i.dispatch.on("stateChange",function(e){S.disabled=e.disabled,N.stateChange(S),M.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;R=R.map(function(e){return e.disabled=!0,e}),e.disabled=!1,t.style(e.style),S.style=t.style(),N.stateChange(S),M.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,a,f,c=[];y.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){a=e.interactiveBisect(n.values,i.pointXValue,M.x()),t.highlightPoint(r,a,!0);var o=n.values[a];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof f=="undefined"&&(f=M.xScale()(M.x()(o,a)));var u=t.style()=="expand"?o.display.y:M.y()(o,a);c.push({key:n.key,value:u,color:l(n,n.seriesIndex),stackedValue:o.display})}),c.reverse();if(c.length>2){var h=M.yScale().invert(i.mouseY),p=Infinity,d=null;c.forEach(function(e,t){h=Math.abs(h);var n=Math.abs(e.stackedValue.y0),r=Math.abs(e.stackedValue.y);if(h>=n&&h<=r+n){d=t;return}}),d!=null&&(c[d].highlight=!0)}var v=n.tickFormat()(M.x()(s,a)),m=t.style()=="expand"?function(e,t){return d3.format(".1%")(e)}:function(e,t){return r.tickFormat()(e)};o.tooltip.position({left:f+u.left,top:i.mouseY+u.top}).chartContainer(_.parentNode).enabled(g).valueFormatter(m).data({value:v,series:c})(),o.renderGuideLine(f)}),o.dispatch.on("elementMouseout",function(e){N.tooltipHide(),t.clearHighlights()}),N.on("tooltipShow",function(e){g&&O(e,_.parentNode)}),N.on("changeState",function(e){typeof e.disabled!="undefined"&&y.length===e.disabled.length&&(y.forEach(function(t,n){t.disabled=e.disabled[n]}),S.disabled=e.disabled),typeof e.style!="undefined"&&t.style(e.style),M.update()})}),M}var t=e.models.stackedArea(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:25,bottom:50,left:60},a=null,f=null,l=e.utils.defaultColor(),c=!0,h=!0,p=!0,d=!0,v=!1,m=!1,g=!0,y=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},b,w,E=d3.format(",.2f"),S={style:t.style()},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=250,k=["Stacked","Stream","Expanded"],L={},A=0;n.orient("bottom").tickPadding(7),r.orient(v?"right":"left"),s.updateState(!1);var O=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=y(i.series.key,a,f,i,M);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("tooltipShow",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],N.tooltipShow(e)}),t.dispatch.on("tooltipHide",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){g&&e.tooltip.cleanup()}),M.dispatch=N,M.stacked=t,M.legend=i,M.controls=s,M.xAxis=n,M.yAxis=r,M.interactiveLayer=o,d3.rebind(M,t,"x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","sizeDomain","interactive","useVoronoi","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),M.options=e.utils.optionsFunc.bind(M),M.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,M):u},M.width=function(e){return arguments.length?(a=e,M):a},M.height=function(e){return arguments.length?(f=e,M):f},M.color=function(n){return arguments.length?(l=e.utils.getColor(n),i.color(l),t.color(l),M):l},M.showControls=function(e){return arguments.length?(c=e,M):c},M.showLegend=function(e){return arguments.length?(h=e,M):h},M.showXAxis=function(e){return arguments.length?(p=e,M):p},M.showYAxis=function(e){return arguments.length?(d=e,M):d},M.rightAlignYAxis=function(e){return arguments.length?(v=e,r.orient(e?"right":"left"),M):v},M.useInteractiveGuideline=function(e){return arguments.length?(m=e,e===!0&&(M.interactive(!1),M.useVoronoi(!1)),M):m},M.tooltip=function(e){return arguments.length?(y=e,M):y},M.tooltips=function(e){return arguments.length?(g=e,M):g},M.tooltipContent=function(e){return arguments.length?(y=e,M):y},M.state=function(e){return arguments.length?(S=e,M):S},M.defaultState=function(e){return arguments.length?(x=e,M):x},M.noData=function(e){return arguments.length?(T=e,M):T},M.transitionDuration=function(e){return arguments.length?(A=e,M):A},M.controlsData=function(e){return arguments.length?(k=e,M):k},M.controlLabels=function(e){return arguments.length?typeof e!="object"?L:(L=e,M):L},r.setTickFormat=r.tickFormat,r.tickFormat=function(e){return arguments.length?(E=e,r):E},M}}(),define("plugin/plugins/nvd3/nv.d3",function(){}),define("plugin/charts/nvd3/common/config",["plugin/charts/forms/default","plugin/plugins/nvd3/nv.d3"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"NVD3",tag:"svg",keywords:"small"})}),define("plugin/charts/nvd3/bar/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/line_focus/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus",category:"Others",zoomable:"native",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/pie/config",["plugin/plugins/nvd3/nv.d3"],function(){return $.extend(!0,{},{title:"Pie chart",category:"Area charts",library:"NVD3",tag:"svg",keywords:"small",columns:{label:{title:"Labels",is_label:!0,is_auto:!0},y:{title:"Values",is_numeric:!0}},settings:{main_separator:{type:"separator",title:"Pie chart settings"},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{init:"true",hide:!0}}})}),define("plugin/charts/nvd3/stackedarea_full/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Expanded",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea_stream/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stream",category:"Area charts",zoomable:!0,keywords:"default small",showmaxmin:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/histogram/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogram",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{x_axis_label:{init:"Values"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_precision:{init:".2"}}})}),define("plugin/charts/nvd3/line/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/scatter/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/common/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"jqPlot",tag:"div",zoomable:!0,keywords:"medium",settings:{separator_grid:{title:"Grids",type:"separator"},x_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the X axis?",type:"radiobutton",init:"false",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]},y_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the Y axis?",type:"radiobutton",init:"true",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]}}})}),define("plugin/charts/jqplot/bar/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/line/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/scatter/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}},settings:{x_axis_grid:{init:"true"}}})}),define("plugin/charts/jqplot/boxplot/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Box plot",category:"Data processing (requires 'charts' tool from Toolshed)",library:"jqPlot",tag:"div",execute:"boxplot",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{show_legend:{init:"false"}}})}),define("plugin/charts/jqplot/histogram_discrete/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Discrete Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogramdiscrete",keywords:"small medium large",columns:{x:{title:"Observations",is_label:!0}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"}}})}),define("plugin/charts/others/heatmap/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"Heatmap",category:"Others",library:"Custom",tag:"svg",keywords:"small",zoomable:!0,columns:{x:{title:"Column labels",is_label:!0,is_numeric:!0,is_unique:!0},y:{title:"Row labels",is_label:!0,is_numeric:!0,is_unique:!0},z:{title:"Observation",is_numeric:!0}},settings:{use_panels:{init:"true",hide:!0},color_set:{title:"Color scheme",info:"Select a color scheme for your heatmap",type:"select",init:"jet",data:[{label:"Cold-to-Hot",value:"hot"},{label:"Cool",value:"cool"},{label:"Copper",value:"copper"},{label:"Gray scale",value:"gray"},{label:"Jet",value:"jet"},{label:"No-Green",value:"no_green"},{label:"Ocean",value:"ocean"},{label:"Polar",value:"polar"},{label:"Red-to-Green",value:"redgreen"},{label:"Red-to-green (saturated)",value:"red2green"},{label:"Relief",value:"relief"},{label:"Seismograph",value:"seis"},{label:"Sealand",value:"sealand"},{label:"Split",value:"split"},{label:"Wysiwyg",value:"wysiwyg"}]},url_template:{title:"Url template",info:"Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.",type:"text",init:"",placeholder:"http://someurl.com?id=__LABEL__"}}})}),define("plugin/charts/others/heatmap_cluster/config",["plugin/charts/others/heatmap/config"],function(e){return $.extend(!0,{},e,{title:"Clustered Heatmap",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"heatmap",keywords:"small medium large"})}),define("plugin/charts/types",["plugin/charts/nvd3/bar/config","plugin/charts/nvd3/bar_stacked/config","plugin/charts/nvd3/bar_horizontal/config","plugin/charts/nvd3/bar_horizontal_stacked/config","plugin/charts/nvd3/line_focus/config","plugin/charts/nvd3/pie/config","plugin/charts/nvd3/stackedarea_full/config","plugin/charts/nvd3/stackedarea_stream/config","plugin/charts/nvd3/histogram/config","plugin/charts/nvd3/line/config","plugin/charts/nvd3/scatter/config","plugin/charts/nvd3/stackedarea/config","plugin/charts/jqplot/bar/config","plugin/charts/jqplot/line/config","plugin/charts/jqplot/scatter/config","plugin/charts/jqplot/boxplot/config","plugin/charts/jqplot/histogram_discrete/config","plugin/charts/others/heatmap/config","plugin/charts/others/heatmap_cluster/config"],function(e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y){return Backbone.Model.extend({defaults:{nvd3_bar:e,nvd3_bar_stacked:t,nvd3_bar_horizontal:n,nvd3_bar_horizontal_stacked:r,nvd3_line_focus:i,nvd3_stackedarea:c,nvd3_stackedarea_full:o,nvd3_stackedarea_stream:u,nvd3_pie:s,nvd3_line:f,nvd3_scatter:l,nvd3_histogram:a,jqplot_bar:h,jqplot_histogram_discrete:m,jqplot_line:p,jqplot_scatter:d,jqplot_boxplot:v,others_heatmap:g,others_heatmap_cluster:y}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","utils/deferred","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c,h){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new l,this.types=new h,this.chart=new c,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.deferred=new u,this.viewer_view=new a(this),this.editor_view=new f(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el);if(!this.storage.load())this.go("editor");else{this.go("viewer");var n=this;this.deferred.execute(function(){n.chart.trigger("redraw")})}},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},chartPath:function(e){var t=e.split(/_(.+)/);return t.length>=2?t[0]+"/"+t[1]:(console.debug("FAILED App:chartPath() - Invalid format: "+e),undefined)}})});
\ No newline at end of file
+define("mvc/ui/ui-modal",[],function(){var e=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast"),this.options.closing_callback&&this.options.closing_callback()},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="ui-modal modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:e}}),function(){var e=this,t=e._,n=Array.prototype,r=Object.prototype,i=Function.prototype,s=n.push,o=n.slice,u=n.concat,a=r.toString,f=r.hasOwnProperty,l=Array.isArray,c=Object.keys,h=i.bind,p=function(e){if(e instanceof p)return e;if(!(this instanceof p))return new p(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=p),exports._=p):e._=p,p.VERSION="1.7.0";var d=function(e,t,n){if(t===void 0)return e;switch(n==null?3:n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)};case 4:return function(n,r,i,s){return e.call(t,n,r,i,s)}}return function(){return e.apply(t,arguments)}};p.iteratee=function(e,t,n){return e==null?p.identity:p.isFunction(e)?d(e,t,n):p.isObject(e)?p.matches(e):p.property(e)},p.each=p.forEach=function(e,t,n){if(e==null)return e;t=d(t,n);var r,i=e.length;if(i===+i)for(r=0;r<i;r++)t(e[r],r,e);else{var s=p.keys(e);for(r=0,i=s.length;r<i;r++)t(e[s[r]],s[r],e)}return e},p.map=p.collect=function(e,t,n){if(e==null)return[];t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s=Array(i),o;for(var u=0;u<i;u++)o=r?r[u]:u,s[u]=t(e[o],o,e);return s};var v="Reduce of empty array with no initial value";p.reduce=p.foldl=p.inject=function(e,t,n,r){e==null&&(e=[]),t=d(t,r,4);var i=e.length!==+e.length&&p.keys(e),s=(i||e).length,o=0,u;if(arguments.length<3){if(!s)throw new TypeError(v);n=e[i?i[o++]:o++]}for(;o<s;o++)u=i?i[o]:o,n=t(n,e[u],u,e);return n},p.reduceRight=p.foldr=function(e,t,n,r){e==null&&(e=[]),t=d(t,r,4);var i=e.length!==+e.length&&p.keys(e),s=(i||e).length,o;if(arguments.length<3){if(!s)throw new TypeError(v);n=e[i?i[--s]:--s]}while(s--)o=i?i[s]:s,n=t(n,e[o],o,e);return n},p.find=p.detect=function(e,t,n){var r;return t=p.iteratee(t,n),p.some(e,function(e,n,i){if(t(e,n,i))return r=e,!0}),r},p.filter=p.select=function(e,t,n){var r=[];return e==null?r:(t=p.iteratee(t,n),p.each(e,function(e,n,i){t(e,n,i)&&r.push(e)}),r)},p.reject=function(e,t,n){return p.filter(e,p.negate(p.iteratee(t)),n)},p.every=p.all=function(e,t,n){if(e==null)return!0;t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s,o;for(s=0;s<i;s++){o=r?r[s]:s;if(!t(e[o],o,e))return!1}return!0},p.some=p.any=function(e,t,n){if(e==null)return!1;t=p.iteratee(t,n);var r=e.length!==+e.length&&p.keys(e),i=(r||e).length,s,o;for(s=0;s<i;s++){o=r?r[s]:s;if(t(e[o],o,e))return!0}return!1},p.contains=p.include=function(e,t){return e==null?!1:(e.length!==+e.length&&(e=p.values(e)),p.indexOf(e,t)>=0)},p.invoke=function(e,t){var n=o.call(arguments,2),r=p.isFunction(t);return p.map(e,function(e){return(r?t:e[t]).apply(e,n)})},p.pluck=function(e,t){return p.map(e,p.property(t))},p.where=function(e,t){return p.filter(e,p.matches(t))},p.findWhere=function(e,t){return p.find(e,p.matches(t))},p.max=function(e,t,n){var r=-Infinity,i=-Infinity,s,o;if(t==null&&e!=null){e=e.length===+e.length?e:p.values(e);for(var u=0,a=e.length;u<a;u++)s=e[u],s>r&&(r=s)}else t=p.iteratee(t,n),p.each(e,function(e,n,s){o=t(e,n,s);if(o>i||o===-Infinity&&r===-Infinity)r=e,i=o});return r},p.min=function(e,t,n){var r=Infinity,i=Infinity,s,o;if(t==null&&e!=null){e=e.length===+e.length?e:p.values(e);for(var u=0,a=e.length;u<a;u++)s=e[u],s<r&&(r=s)}else t=p.iteratee(t,n),p.each(e,function(e,n,s){o=t(e,n,s);if(o<i||o===Infinity&&r===Infinity)r=e,i=o});return r},p.shuffle=function(e){var t=e&&e.length===+e.length?e:p.values(e),n=t.length,r=Array(n);for(var i=0,s;i<n;i++)s=p.random(0,i),s!==i&&(r[i]=r[s]),r[s]=t[i];return r},p.sample=function(e,t,n){return t==null||n?(e.length!==+e.length&&(e=p.values(e)),e[p.random(e.length-1)]):p.shuffle(e).slice(0,Math.max(0,t))},p.sortBy=function(e,t,n){return t=p.iteratee(t,n),p.pluck(p.map(e,function(e,n,r){return{value:e,index:n,criteria:t(e,n,r)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index-t.index}),"value")};var m=function(e){return function(t,n,r){var i={};return n=p.iteratee(n,r),p.each(t,function(r,s){var o=n(r,s,t);e(i,r,o)}),i}};p.groupBy=m(function(e,t,n){p.has(e,n)?e[n].push(t):e[n]=[t]}),p.indexBy=m(function(e,t,n){e[n]=t}),p.countBy=m(function(e,t,n){p.has(e,n)?e[n]++:e[n]=1}),p.sortedIndex=function(e,t,n,r){n=p.iteratee(n,r,1);var i=n(t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n(e[u])<i?s=u+1:o=u}return s},p.toArray=function(e){return e?p.isArray(e)?o.call(e):e.length===+e.length?p.map(e,p.identity):p.values(e):[]},p.size=function(e){return e==null?0:e.length===+e.length?e.length:p.keys(e).length},p.partition=function(e,t,n){t=p.iteratee(t,n);var r=[],i=[];return p.each(e,function(e,n,s){(t(e,n,s)?r:i).push(e)}),[r,i]},p.first=p.head=p.take=function(e,t,n){return e==null?void 0:t==null||n?e[0]:t<0?[]:o.call(e,0,t)},p.initial=function(e,t,n){return o.call(e,0,Math.max(0,e.length-(t==null||n?1:t)))},p.last=function(e,t,n){return e==null?void 0:t==null||n?e[e.length-1]:o.call(e,Math.max(e.length-t,0))},p.rest=p.tail=p.drop=function(e,t,n){return o.call(e,t==null||n?1:t)},p.compact=function(e){return p.filter(e,p.identity)};var g=function(e,t,n,r){if(t&&p.every(e,p.isArray))return u.apply(r,e);for(var i=0,o=e.length;i<o;i++){var a=e[i];!p.isArray(a)&&!p.isArguments(a)?n||r.push(a):t?s.apply(r,a):g(a,t,n,r)}return r};p.flatten=function(e,t){return g(e,t,!1,[])},p.without=function(e){return p.difference(e,o.call(arguments,1))},p.uniq=p.unique=function(e,t,n,r){if(e==null)return[];p.isBoolean(t)||(r=n,n=t,t=!1),n!=null&&(n=p.iteratee(n,r));var i=[],s=[];for(var o=0,u=e.length;o<u;o++){var a=e[o];if(t)(!o||s!==a)&&i.push(a),s=a;else if(n){var f=n(a,o,e);p.indexOf(s,f)<0&&(s.push(f),i.push(a))}else p.indexOf(i,a)<0&&i.push(a)}return i},p.union=function(){return p.uniq(g(arguments,!0,!0,[]))},p.intersection=function(e){if(e==null)return[];var t=[],n=arguments.length;for(var r=0,i=e.length;r<i;r++){var s=e[r];if(p.contains(t,s))continue;for(var o=1;o<n;o++)if(!p.contains(arguments[o],s))break;o===n&&t.push(s)}return t},p.difference=function(e){var t=g(o.call(arguments,1),!0,!0,[]);return p.filter(e,function(e){return!p.contains(t,e)})},p.zip=function(e){if(e==null)return[];var t=p.max(arguments,"length").length,n=Array(t);for(var r=0;r<t;r++)n[r]=p.pluck(arguments,r);return n},p.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},p.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=p.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}for(;r<i;r++)if(e[r]===t)return r;return-1},p.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=e.length;typeof n=="number"&&(r=n<0?r+n+1:Math.min(r,n+1));while(--r>=0)if(e[r]===t)return r;return-1},p.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=n||1;var r=Math.max(Math.ceil((t-e)/n),0),i=Array(r);for(var s=0;s<r;s++,e+=n)i[s]=e;return i};var y=function(){};p.bind=function(e,t){var n,r;if(h&&e.bind===h)return h.apply(e,o.call(arguments,1));if(!p.isFunction(e))throw new TypeError("Bind must be called on a function");return n=o.call(arguments,2),r=function(){if(this instanceof r){y.prototype=e.prototype;var i=new y;y.prototype=null;var s=e.apply(i,n.concat(o.call(arguments)));return p.isObject(s)?s:i}return e.apply(t,n.concat(o.call(arguments)))},r},p.partial=function(e){var t=o.call(arguments,1);return function(){var n=0,r=t.slice();for(var i=0,s=r.length;i<s;i++)r[i]===p&&(r[i]=arguments[n++]);while(n<arguments.length)r.push(arguments[n++]);return e.apply(this,r)}},p.bindAll=function(e){var t,n=arguments.length,r;if(n<=1)throw new Error("bindAll must be passed function names");for(t=1;t<n;t++)r=arguments[t],e[r]=p.bind(e[r],e);return e},p.memoize=function(e,t){var n=function(r){var i=n.cache,s=t?t.apply(this,arguments):r;return p.has(i,s)||(i[s]=e.apply(this,arguments)),i[s]};return n.cache={},n},p.delay=function(e,t){var n=o.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},p.defer=function(e){return p.delay.apply(p,[e,1].concat(o.call(arguments,1)))},p.throttle=function(e,t,n){var r,i,s,o=null,u=0;n||(n={});var a=function(){u=n.leading===!1?0:p.now(),o=null,s=e.apply(r,i),o||(r=i=null)};return function(){var f=p.now();!u&&n.leading===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0||l>t?(clearTimeout(o),o=null,u=f,s=e.apply(r,i),o||(r=i=null)):!o&&n.trailing!==!1&&(o=setTimeout(a,l)),s}},p.debounce=function(e,t,n){var r,i,s,o,u,a=function(){var f=p.now()-o;f<t&&f>0?r=setTimeout(a,t-f):(r=null,n||(u=e.apply(s,i),r||(s=i=null)))};return function(){s=this,i=arguments,o=p.now();var f=n&&!r;return r||(r=setTimeout(a,t)),f&&(u=e.apply(s,i),s=i=null),u}},p.wrap=function(e,t){return p.partial(t,e)},p.negate=function(e){return function(){return!e.apply(this,arguments)}},p.compose=function(){var e=arguments,t=e.length-1;return function(){var n=t,r=e[t].apply(this,arguments);while(n--)r=e[n].call(this,r);return r}},p.after=function(e,t){return function(){if(--e<1)return t.apply(this,arguments)}},p.before=function(e,t){var n;return function(){return--e>0?n=t.apply(this,arguments):t=null,n}},p.once=p.partial(p.before,2),p.keys=function(e){if(!p.isObject(e))return[];if(c)return c(e);var t=[];for(var n in e)p.has(e,n)&&t.push(n);return t},p.values=function(e){var t=p.keys(e),n=t.length,r=Array(n);for(var i=0;i<n;i++)r[i]=e[t[i]];return r},p.pairs=function(e){var t=p.keys(e),n=t.length,r=Array(n);for(var i=0;i<n;i++)r[i]=[t[i],e[t[i]]];return r},p.invert=function(e){var t={},n=p.keys(e);for(var r=0,i=n.length;r<i;r++)t[e[n[r]]]=n[r];return t},p.functions=p.methods=function(e){var t=[];for(var n in e)p.isFunction(e[n])&&t.push(n);return t.sort()},p.extend=function(e){if(!p.isObject(e))return e;var t,n;for(var r=1,i=arguments.length;r<i;r++){t=arguments[r];for(n in t)f.call(t,n)&&(e[n]=t[n])}return e},p.pick=function(e,t,n){var r={},i;if(e==null)return r;if(p.isFunction(t)){t=d(t,n);for(i in e){var s=e[i];t(s,i,e)&&(r[i]=s)}}else{var a=u.apply([],o.call(arguments,1));e=new Object(e);for(var f=0,l=a.length;f<l;f++)i=a[f],i in e&&(r[i]=e[i])}return r},p.omit=function(e,t,n){if(p.isFunction(t))t=p.negate(t);else{var r=p.map(u.apply([],o.call(arguments,1)),String);t=function(e,t){return!p.contains(r,t)}}return p.pick(e,t,n)},p.defaults=function(e){if(!p.isObject(e))return e;for(var t=1,n=arguments.length;t<n;t++){var r=arguments[t];for(var i in r)e[i]===void 0&&(e[i]=r[i])}return e},p.clone=function(e){return p.isObject(e)?p.isArray(e)?e.slice():p.extend({},e):e},p.tap=function(e,t){return t(e),e};var b=function(e,t,n,r){if(e===t)return e!==0||1/e===1/t;if(e==null||t==null)return e===t;e instanceof p&&(e=e._wrapped),t instanceof p&&(t=t._wrapped);var i=a.call(e);if(i!==a.call(t))return!1;switch(i){case"[object RegExp]":case"[object String]":return""+e==""+t;case"[object Number]":if(+e!==+e)return+t!==+t;return+e===0?1/+e===1/t:+e===+t;case"[object Date]":case"[object Boolean]":return+e===+t}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]===e)return r[s]===t;var o=e.constructor,u=t.constructor;if(o!==u&&"constructor"in e&&"constructor"in t&&!(p.isFunction(o)&&o instanceof o&&p.isFunction(u)&&u instanceof u))return!1;n.push(e),r.push(t);var f,l;if(i==="[object Array]"){f=e.length,l=f===t.length;if(l)while(f--)if(!(l=b(e[f],t[f],n,r)))break}else{var c=p.keys(e),h;f=c.length,l=p.keys(t).length===f;if(l)while(f--){h=c[f];if(!(l=p.has(t,h)&&b(e[h],t[h],n,r)))break}}return n.pop(),r.pop(),l};p.isEqual=function(e,t){return b(e,t,[],[])},p.isEmpty=function(e){if(e==null)return!0;if(p.isArray(e)||p.isString(e)||p.isArguments(e))return e.length===0;for(var t in e)if(p.has(e,t))return!1;return!0},p.isElement=function(e){return!!e&&e.nodeType===1},p.isArray=l||function(e){return a.call(e)==="[object Array]"},p.isObject=function(e){var t=typeof e;return t==="function"||t==="object"&&!!e},p.each(["Arguments","Function","String","Number","Date","RegExp"],function(e){p["is"+e]=function(t){return a.call(t)==="[object "+e+"]"}}),p.isArguments(arguments)||(p.isArguments=function(e){return p.has(e,"callee")}),typeof /./!="function"&&(p.isFunction=function(e){return typeof e=="function"||!1}),p.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},p.isNaN=function(e){return p.isNumber(e)&&e!==+e},p.isBoolean=function(e){return e===!0||e===!1||a.call(e)==="[object Boolean]"},p.isNull=function(e){return e===null},p.isUndefined=function(e){return e===void 0},p.has=function(e,t){return e!=null&&f.call(e,t)},p.noConflict=function(){return e._=t,this},p.identity=function(e){return e},p.constant=function(e){return function(){return e}},p.noop=function(){},p.property=function(e){return function(t){return t[e]}},p.matches=function(e){var t=p.pairs(e),n=t.length;return function(e){if(e==null)return!n;e=new Object(e);for(var r=0;r<n;r++){var i=t[r],s=i[0];if(i[1]!==e[s]||!(s in e))return!1}return!0}},p.times=function(e,t,n){var r=Array(Math.max(0,e));t=d(t,n,1);for(var i=0;i<e;i++)r[i]=t(i);return r},p.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))},p.now=Date.now||function(){return(new Date).getTime()};var w={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},E=p.invert(w),S=function(e){var t=function(t){return e[t]},n="(?:"+p.keys(e).join("|")+")",r=RegExp(n),i=RegExp(n,"g");return function(e){return e=e==null?"":""+e,r.test(e)?e.replace(i,t):e}};p.escape=S(w),p.unescape=S(E),p.result=function(e,t){if(e==null)return void 0;var n=e[t];return p.isFunction(n)?e[t]():n};var x=0;p.uniqueId=function(e){var t=++x+"";return e?e+t:t},p.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,N={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},C=/\\|'|\r|\n|\u2028|\u2029/g,k=function(e){return"\\"+N[e]};p.template=function(e,t,n){!t&&n&&(t=n),t=p.defaults({},t,p.templateSettings);var r=RegExp([(t.escape||T).source,(t.interpolate||T).source,(t.evaluate||T).source].join("|")+"|$","g"),i=0,s="__p+='";e.replace(r,function(t,n,r,o,u){return s+=e.slice(i,u).replace(C,k),i=u+t.length,n?s+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?s+="'+\n((__t=("+r+"))==null?'':__t)+\n'":o&&(s+="';\n"+o+"\n__p+='"),t}),s+="';\n",t.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n";try{var o=new Function(t.variable||"obj","_",s)}catch(u){throw u.source=s,u}var a=function(e){return o.call(this,e,p)},f=t.variable||"obj";return a.source="function("+f+"){\n"+s+"}",a},p.chain=function(e){var t=p(e);return t._chain=!0,t};var L=function(e){return this._chain?p(e).chain():e};p.mixin=function(e){p.each(p.functions(e),function(t){var n=p[t]=e[t];p.prototype[t]=function(){var e=[this._wrapped];return s.apply(e,arguments),L.call(this,n.apply(p,e))}})},p.mixin(p),p.each(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=n[e];p.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e==="shift"||e==="splice")&&n.length===0&&delete n[0],L.call(this,n)}}),p.each(["concat","join","slice"],function(e){var t=n[e];p.prototype[e]=function(){return L.call(this,t.apply(this._wrapped,arguments))}}),p.prototype.value=function(){return this._wrapped},typeof define=="function"&&define.amd&&define("underscore",[],function(){return p})}.call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e){return $("<div/>").text(e).html()}function n(e){e instanceof Array||(e=[e]);for(var t in e)if(["None",null,"null",undefined,"undefined"].indexOf(e[t])>-1)return!1;return!0}function r(e){var e=e.toString();if(e){e=e.replace(/,/g,", ");var t=e.lastIndexOf(", ");return t!=-1&&(e=e.substr(0,t)+" or "+e.substr(t+1)),e}return""}function i(e){top.__utils__get__=top.__utils__get__||{},e.cache&&top.__utils__get__[e.url]?(e.success&&e.success(top.__utils__get__[e.url]),console.debug("utils.js::get() - Fetching from cache ["+e.url+"].")):s({url:e.url,data:e.data,success:function(t){top.__utils__get__[e.url]=t,e.success&&e.success(t)},error:function(t){e.error&&e.error(t)}})}function s(e){var t={contentType:"application/json",type:e.type||"GET",data:e.data||{},url:e.url};t.type=="GET"||t.type=="DELETE"?(t.url.indexOf("?")==-1?t.url+="?":t.url+="&",t.url=t.url+$.param(t.data),t.data=null):(t.dataType="json",t.url=t.url,t.data=JSON.stringify(t.data)),$.ajax(t).done(function(t){if(typeof t=="string")try{t=t.replace("Infinity,",'"Infinity",'),t=jQuery.parseJSON(t)}catch(n){console.debug(n)}e.success&&e.success(t)}).fail(function(t){var n=null;try{n=jQuery.parseJSON(t.responseText)}catch(r){n=t.responseText}e.error&&e.error(n,t)})}function o(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function u(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function a(t,n){return t?e.defaults(t,n):n}function f(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function l(){return"x"+Math.random().toString(36).substring(2,9)}function c(e){var t=$("<p></p>");return t.append(e),t}function h(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:u,cssGetAttribute:o,get:i,merge:a,bytesToString:f,uuid:l,time:h,wrap:c,request:s,sanitize:t,textify:r,validate:n}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,scrollable:!0,nopadding:!1,operations:null,placement:"bottom",cls:"ui-portlet",operations_flt:"right"},$title:null,$content:null,$buttons:null,$operations:null,$header:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find(".content"),this.$title=this.$el.find(".portlet-title-text"),this.$header=this.$el.find(".portlet-header");var n=this.$el.find(".portlet-content");this.options.scrollable?n.addClass("scroll"):this.options.title?n.addClass("no-scroll"):n.addClass("no-scroll-no-title"),this.options.nopadding&&(n.css("padding","0px"),this.$content.css("padding","0px")),this.$buttons=$(this.el).find(".buttons");if(this.options.buttons){var r=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),r.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find(".operations");if(this.options.operations){var r=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t,n){n?this.$content.append(t):this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div id="'+e.id+'" class="'+e.cls+'">';return e.title&&(t+='<div class="portlet-header"><div class="operations" style="float: '+e.operations_flt+';"></div>'+'<div class="portlet-title">',e.icon&&(t+='<i class="icon fa '+e.icon+'"> </i>'),t+='<span class="portlet-title-text">'+e.title+"</span>"+"</div>"+"</div>"),t+='<div class="portlet-content">',e.placement=="top"&&(t+='<div class="buttons"></div>'),t+='<div class="content"></div>',e.placement=="bottom"&&(t+='<div class="buttons"></div>'),t+="</div></div>",t}});return{View:t}}),define("mvc/ui/ui-select-default",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",error_text:"No data available",visible:!0,wait:!1,multiple:!1,searchable:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find(".select"),this.$icon=this.$el.find(".icon"),this.$button=this.$el.find(".button"),this.options.multiple?(this.$select.prop("multiple",!0),this.$select.addClass("ui-select-multiple"),this.$icon.remove()):this.$el.addClass("ui-select"),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value),this.options.visible||this.hide(),this.options.wait?this.wait():this.show();var n=this;this.$select.on("change",function(){n._change()}),this.on("change",function(){n._change()})},value:function(e){return e!==undefined&&(this.$select.val(e),this.$select.select2&&this.$select.select2("val",e)),this.$select.val()},first:function(){var e=this.$select.find("option");return e.length>0?e.val():undefined},validate:function(){return e.validate(this.value())},text:function(){return this.$select.find("option:selected").text()},show:function(){this.unwait(),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin")},unwait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down")},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){var t=this.$select.val();this.$select.find("option").remove();for(var n in e)this.$select.append(this._templateOption(e[n]));this._refresh(),this.$select.val(t),this.$select.val()||this.$select.val(this.first()),this.options.searchable&&(this.$button.hide(),this.$select.select2("destroy"),this.$select.select2())},setOnChange:function(e){this.options.onchange=e},exists:function(e){return this.$select.find('option[value="'+e+'"]').length>0},_change:function(){this.options.onchange&&this.options.onchange(this.$select.val())},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.disable(),this.$select.append(this._templateOption({value:"null",label:this.options.error_text}))):this.enable()},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){return'<div id="'+e.id+'">'+'<select id="select" class="select '+e.cls+" "+e.id+'"></select>'+'<div class="button">'+'<i class="icon"/>'+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-slider",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{min:null,max:null,step:null,precise:!1,split:1e4},initialize:function(t){var n=this;this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.useslider=this.options.max!==null&&this.options.min!==null&&this.options.max>this.options.min,this.options.step===null&&(this.options.step=1,this.options.precise&&this.useslider&&(this.options.step=(this.options.max-this.options.min)/this.options.split)),this.useslider?(this.$slider=this.$el.find("#slider"),this.$slider.slider(this.options),this.$slider.on("slide",function(e,t){n.value(t.value)})):this.$el.find(".ui-form-slider-text").css("width","100%"),this.$text=this.$el.find("#text"),this.options.value!==undefined&&this.value(this.options.value),this.$text.on("change",function(){n.value($(this).val())});var r=[];this.$text.on("keyup",function(e){r[e.which]=!1}),this.$text.on("keydown",function(e){var t=e.which;r[t]=!0,t==8||t==9||t==13||t==37||t==39||t>=48&&t<=57||t==190&&$(this).val().indexOf(".")==-1&&n.options.precise||t==189&&$(this).val().indexOf("-")==-1||r[91]||r[17]||event.preventDefault()})},value:function(e){return e!==undefined&&(isNaN(e)&&(e=0),this.options.max!==null&&(e=Math.min(e,this.options.max)),this.options.min!==null&&(e=Math.max(e,this.options.min)),this.options.onchange&&this.options.onchange(e),this.$slider&&this.$slider.slider("value",e),this.$text.val(e)),this.$text.val()},_template:function(e){return'<div id="'+e.id+'" class="ui-form-slider">'+'<input id="text" type="text" class="ui-form-slider-text"/>'+'<div id="slider" class="ui-form-slider-element"/>'+"</div>"}});return{View:t}}),define("mvc/ui/ui-options",["utils/utils"],function(e){var t=Backbone.View.extend({initialize:function(t){this.optionsDefault={visible:!0,data:[],id:e.uuid(),error_text:"No data available.",wait_text:"Please wait..."},this.options=e.merge(t,this.optionsDefault),this.setElement("<div/>"),this.$message=$("<div/>"),this.$options=$(this._template(t)),this.$el.append(this.$message),this.$el.append(this.$options),this.options.visible||this.$el.hide(),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value);var n=this;this.on("change",function(){n._change()})},update:function(e){var t=this._getValue();this.$options.empty();if(this._templateOptions)this.$options.append(this._templateOptions(e));else for(var n in e){var r=$(this._templateOption(e[n]));r.addClass("ui-option"),this.$options.append(r)}var i=this;this.$el.find("input").on("change",function(){i.value(i._getValue()),i._change()}),this._refresh(),this.value(t)},value:function(e){if(e!==undefined){e instanceof Array||(e=[e]),this.$el.find("input").prop("checked",!1);for(var t in e)this.$el.find('input[value="'+e[t]+'"]').first().prop("checked",!0)}return this._getValue()},exists:function(e){if(e!==undefined){e instanceof Array||(e=[e]);for(var t in e)if(this.$el.find('input[value="'+e[t]+'"]').length>0)return!0}return!1},first:function(){var e=this.$el.find("input");return e.length>0?e.val():undefined},validate:function(){return e.validate(this.value())},wait:function(){this._size()==0&&(this._messageShow(this.options.wait_text,"info"),this.$options.hide())},unwait:function(){this._messageHide(),this._refresh()},_change:function(){this.options.onchange&&this.options.onchange(this._getValue())},_refresh:function(){this._size()==0?(this._messageShow(this.options.error_text,"danger"),this.$options.hide()):(this._messageHide(),this.$options.css("display","inline-block"))},_getValue:function(){var e=this.$el.find(":checked");if(e.length==0)return"null";if(this.options.multiple){var t=[];return e.each(function(){t.push($(this).val())}),t}return e.val()},_size:function(){return this.$el.find(".ui-option").length},_messageShow:function(e,t){this.$message.show(),this.$message.removeClass(),this.$message.addClass("ui-message alert alert-"+t),this.$message.html(e)},_messageHide:function(){this.$message.hide()},_template:function(){return'<div class="ui-options"/>'}}),n={};n.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="radio" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var r={};r.View=t.extend({initialize:function(e){e.multiple=!0,t.prototype.initialize.call(this,e)},_templateOption:function(e){return'<div><input type="checkbox" name="'+this.options.id+'" value="'+e.value+'"/>'+e.label+"<br>"+"</div>"}});var i={};return i.View=t.extend({initialize:function(e){t.prototype.initialize.call(this,e)},value:function(e){return e!==undefined&&(this.$el.find("input").prop("checked",!1),this.$el.find("label").removeClass("active"),this.$el.find('[value="'+e+'"]').prop("checked",!0).closest("label").addClass("active")),this._getValue()},_templateOption:function(e){var t='<label class="btn btn-default">';return e.icon&&(t+='<i class="fa '+e.icon+'"/>'),t+='<input type="radio" name="'+this.options.id+'" value="'+e.value+'">'+e.label+"</label>",t},_template:function(){return'<div class="btn-group ui-radiobutton" data-toggle="buttons"/>'}}),{Base:t,Radio:n,RadioButton:i,Checkbox:r}}),define("mvc/ui/ui-drilldown",["utils/utils","mvc/ui/ui-options"],function(e,t){var n=t.Base.extend({initialize:function(e){this.display=e.display||"checkbox",e.multiple=this.display=="checkbox",t.Base.prototype.initialize.call(this,e)},_templateOption:function(e,t,n){return'<div><input name="'+this.options.id+'" class="ui-option" type="'+this.display+'" value="'+t+'">'+e+"<div/>"},_templateOptions:function(e){function n(e,t){function n(n){n?(t.fadeIn("fast"),e.removeClass("toggle-expand"),e.addClass("toggle"),e.is_expanded=!0):(t.hide(),e.removeClass("toggle"),e.addClass("toggle-expand"),e.is_expanded=!1)}e.on("click",function(){n(!e.is_expanded)})}function r(e,s){for(i in s){var o=s[i],u=o.options.length>0,a=$("<div/>");if(u){var f=$('<span class="ui-drilldown-button form-toggle icon-button toggle-expand" style="position: relative; top: 2px;"/>'),l=$("<div/>");l.append(f),l.append(t._templateOption(o.name,o.value)),a.append(l);var c=$('<div style="display: none; margin-left: 25px;"/>');r(c,o.options),a.append(c),n(f,c)}else a.append(t._templateOption(o.name,o.value));e.append(a)}}var t=this,s=$("<div/>");return r(s,e),s},_template:function(e){return'<div class="ui-options drilldown-container" id="'+e.id+'"/>'}});return{View:n}}),define("mvc/ui/ui-button-menu",["utils/utils"],function(e){return Backbone.View.extend({optionsDefault:{id:"",title:"",floating:"right",icon:null,onclick:null,cls:"ui-button-icon ui-button-menu",tooltip:"",target:"",href:"",onunload:null,visible:!0,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){$(".tooltip").hide(),e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide(),n.tooltip({title:t.tooltip,placement:"bottom"})},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null,cls:"button-menu btn-group"};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a class="dropdown-item" href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t="",n="";e.title?t="width: auto;":n="margin: 0px;";var r='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="dropdown '+e.cls+'">'+'<div class="root button dropdown-toggle" data-toggle="dropdown" style="'+n+'">'+'<i class="icon fa '+e.icon+'"/>';return e.title&&(r+=' <span class="title">'+e.title+"</span>"),r+="</div></div>",r}})}),define("mvc/ui/ui-misc",["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(e,t,n,r,i,s,o){var u=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},_template:function(e){return'<img class="ui-image '+e.cls+'" src="'+e.url+'"/>'}}),a=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<label class="ui-label '+e.cls+'">'+e.title+"</label>"},value:function(){return options.title}}),f=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" class="ui-icon"/> '+e.title+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="float: '+e.floating+';" type="button" class="'+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),c=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$button=this.$el.find(".button");var n=this;$(this.el).on("click",function(){$(".tooltip").hide(),t.onclick&&!n.disabled&&t.onclick()}),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled"),this.disabled=!0},enable:function(){this.$button.removeClass("disabled"),this.disabled=!1},setIcon:function(e){this.$("i").removeClass(this.options.icon).addClass(e),this.options.icon=e},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="float: '+e.floating+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div class="button"><i class="icon fa '+e.icon+'"/> '+'<span class="title">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),h=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)" class="ui-anchor '+e.cls+'">'+e.title+"</a></div>"}}),p=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>"),this.options.message&&this.update(this.options)},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.find(".alert").append(t.message),this.$el.fadeIn(),this.timeout&&window.clearTimeout(this.timeout);if(!t.persistent){var n=this;this.timeout=window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="ui-message alert alert-'+e.status+'"/>'}}),d=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),v=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:!1,visible:!0,cls:"",area:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.$el.on("input",function(){n.options.onchange&&n.options.onchange(n.$el.val())})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return e.area?'<textarea id="'+e.id+'" class="ui-textarea '+e.cls+'"></textarea>':'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="ui-input '+e.cls+'">'}}),m=Backbone.View.extend({initialize:function(e){this.options=e,this.setElement(this._template(this.options)),this.options.value!==undefined&&this.value(this.options.value)},value:function(e){return e!==undefined&&this.$("hidden").val(e),this.$("hidden").val()},_template:function(e){var t='<div id="'+e.id+'" >';return e.info&&(t+="<label>"+e.info+"</label>"),t+='<hidden value="'+e.value+'"/>'+"</div>",t}});return{Anchor:h,Button:l,ButtonIcon:c,ButtonMenu:s,Icon:f,Image:u,Input:v,Label:a,Message:p,Modal:o,RadioButton:r.RadioButton,Checkbox:r.Checkbox,Radio:r.Radio,Searchbox:d,Select:t,Hidden:m,Slider:n,Drilldown:i}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e,t,n,r,i){var s=this;e.state("wait","Requesting job results...");var o=e.get("dataset_id_job");o!=""?s._wait(e,r,i):s._submit(e,t,n,r,i)},cleanup:function(t){var n=this,r=t.get("dataset_id_job");r!=""&&(e.request({type:"PUT",url:config.root+"api/histories/none/contents/"+r,data:{deleted:!0},success:function(){n._refreshHdas()}}),t.set("dataset_id_job",""))},_submit:function(t,n,r,i,s){var o=this,u=t.id,a=t.get("type"),f=t.definition;data={tool_id:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,columns:r,settings:n}},t.state("wait","Sending job request..."),e.request({type:"POST",url:config.root+"api/tools",data:data,success:function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response."),s&&s();else{o._refreshHdas();var n=e.outputs[0];t.state("wait","Your job has been queued. You may close the browser window. The job will run in the background."),t.set("dataset_id_job",n.id),o.app.storage.save(),o._wait(t,i,s)}},error:function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the 'charts' tool. Please make sure it is installed. "+n),s&&s()}})},_wait:function(t,n,r){var i=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.get("dataset_id_job"),data:{},success:function(e){var s=!1;switch(e.state){case"ok":t.state("wait","Job completed successfully..."),n&&n(e),s=!0;break;case"error":t.state("failed","Job has failed. Please check the history for details."),r&&r(e),s=!0;break;case"running":t.state("wait","Your job is running. You may close the browser window. The job will continue in the background.")}s||setTimeout(function(){i._wait(t,n,r)},i.app.config.get("query_timeout"))}})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshContents()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(e){e.groups?this._get_blocks(e):this._get_dataset(e.id,e.success,e.error)},_get_blocks:function(e){function c(i){l._get(i,function(){var s=!1;for(var o in e.groups){destination_group=e.groups[o],source_group=i.groups[o],destination_group.values||(destination_group.values=[]),destination_group.values=destination_group.values.concat(source_group.values);if(source_group.values.length==0){s=!0;break}}if(++f<u&&!s){n&&n(parseInt(f/u*100));var l=i.start+r;i=$.extend(!0,a,{start:l}),c(i)}else t()})}var t=e.success,n=e.progress,r=this.app.config.get("query_limit"),i=e.start||0,s=i+e.query_limit||i+this.app.config.get("query_limit"),o=Math.abs(s-i);if(o<=0){console.debug("FAILED - Datasets::request() - Invalid query range.");return}var u=Math.ceil(o/r)||1,a=$.extend(!0,{},e),f=0,l=this,h=$.extend(!0,a,{start:i});this._get_dataset(e.id,function(){c(h)})},_get_dataset:function(t,n,r){var i=this.list[t];if(i){n(i);return}var s=this;e.request({type:"GET",url:config.root+"api/datasets/"+t,success:function(e){switch(e.state){case"error":r&&r(e);break;default:s.list[t]=e,n(e)}}})},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.start+this.app.config.get("query_limit")+"_"+t},_get:function(e,t){e.start=e.start||0;var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f]||a==="auto"||a==="zero")continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){var t=e.start;console.debug("Datasets::_fill_from_cache() - Filling request from cache at "+t+".");var n=0;for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s],u=this._block_id(e,o.index),a=this.cache[u];a&&(n=Math.max(n,a.length))}}n==0&&console.debug("Datasets::_fill_from_cache() - Reached data range limit.");for(var r in e.groups){var i=e.groups[r];i.values=[];for(var f=0;f<n;f++)i.values[f]={x:parseInt(f)+t}}for(var r in e.groups){var i=e.groups[r];for(var s in i.columns){var o=i.columns[s];switch(o.index){case"auto":for(var f=0;f<n;f++){var l=i.values[f];l[s]=parseInt(f)+t}break;case"zero":for(var f=0;f<n;f++){var l=i.values[f];l[s]=0}break;default:var u=this._block_id(e,o.index),a=this.cache[u];for(var f=0;f<n;f++){var l=i.values[f],c=a[f];isNaN(c)&&!o.is_label&&(c=0),l[s]=c}}}}},_fetch:function(t,n){var r=t.start?t.start:0,i=this.app.config.get("query_limit"),s=0;t.columns&&(s=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+s+" column(s) at "+r+".")),s==0&&console.debug("Datasets::_fetch() - No columns requested");var o="";for(var u in t.columns)o+=t.columns[u]+",";o=o.substring(0,o.length-1);var a=this;e.request({type:"GET",url:config.root+"api/datasets/"+t.dataset_id,data:{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},success:function(e){var t=new Array(s);for(var r=0;r<s;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var o in i){var u=i[o];u!==undefined&&u!=2147483647&&t[o].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)}})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})}),define("plugin/models/chart",["plugin/models/groups"],function(e){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(t){this.groups=new e,this.settings=new Backbone.Model},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state",e),this.set("state_info",t),this.trigger("set:state"),console.debug("Chart:state() - "+t+" ("+e+")")}})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group","mvc/visualization/visualization-model"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;var t=e.attributes.type;if(!t)return console.debug("Storage::load() - Chart type not provided. Invalid format."),!1;var r=this.app.types.get(t);if(!r)return console.debug("Storage::load() - Chart type not supported. Please re-configure the chart. Resetting chart."),!1;console.debug("Storage::load() - Loading chart type "+t+"."),this.chart.definition=r,this.chart.set(e.attributes),this.chart.state("ok","Loading saved visualization..."),this.chart.settings.set(e.settings);for(var i in e.groups)this.chart.groups.add(new n(e.groups[i]));return this.chart.set("modified",!1),!0}})}),define("utils/deferred",["utils/utils"],function(e){return Backbone.Model.extend({queue:[],process:{},counter:0,initialize:function(){this.on("refresh",function(){if(this.queue.length>0&&this.ready()){var e=this.queue[0];this.queue.splice(0,1),e&&e()}})},execute:function(e){this.queue.push(e),this.trigger("refresh")},register:function(){var t=e.uuid();return this.process[t]=!0,this.counter++,console.debug("Deferred:register() - Registering "+t),t},done:function(e){this.process[e]&&(delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh"))},reset:function(){this.queue=[]},ready:function(){return this.counter==0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({container_list:[],canvas_list:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,100),this._createContainer("div");var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("set:state",function(){var e=r.$el.find("#info"),t=r.$el.find(".charts-viewport-container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var i=r.chart.get("state");switch(i){case"ok":e.hide(),t.show();break;case"failed":n.addClass("icon fa fa-warning"),t.hide();break;default:n.addClass("icon fa fa-spinner fa-spin"),t.show()}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_createContainer:function(e,t){t=t||1;for(var n in this.container_list)this.container_list[n].remove();this.container_list=[],this.canvas_list=[];for(var n=0;n<t;n++){var r=$(this._templateContainer(e,parseInt(100/t)));this.$el.append(r),this.container_list[n]=r,this.canvas_list[n]=r.find(".charts-viewport-canvas").attr("id")}},_draw:function(e){var t=this,n=this.app.deferred.register(),r=e.get("type");this.chart_definition=e.definition;var i=1;e.settings.get("use_panels")==="true"&&(i=e.groups.length),this._createContainer(this.chart_definition.tag,i),e.state("wait","Please wait...");if(!this.chart_definition.execute||this.chart_definition.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+this.app.chartPath(r)+"/wrapper"],function(r){if(t.chart_definition.execute)t.app.jobs.request(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})},function(){this.app.deferred.done(n)});else var i=new r(t.app,{process_id:n,chart:e,request_dictionary:t._defaultRequestDictionary(e),canvas_list:t.canvas_list})})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){n++;for(var i in r.chart_definition.columns)t+=i+"_"+n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t={groups:[]};this.chart_definition.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var r=0,i=this;return e.groups.each(function(e){var s={};for(var o in i.chart_definition.columns){var u=i.chart_definition.columns[o];s[o]=n.merge({index:e.get(o)},u)}t.groups.push({key:++r+":"+e.get("key"),columns:s})}),t},_template:function(){return'<div class="charts-viewport"><div id="info" class="info"><span id="icon" class="icon"/><span id="text" class="text" /></div></div>'},_templateContainer:function(e,t){return'<div class="charts-viewport-container" style="width:'+t+'%;">'+'<div id="menu"/>'+"<"+e+' id="'+n.uuid()+'" class="charts-viewport-canvas">'+"</div>"}})}),define("plugin/library/screenshot",["libs/underscore"],function(e){function t(e){e.$el.find("svg").length>0?r(e):n(e)}function n(e){try{var t=e.$el.find(".jqplot-target"),n=t.jqplotToImageStr({});n&&(window.location.href=n.replace("image/png","image/octet-stream"))}catch(r){console.debug("FAILED - Screenshot::_fromCanvas() - "+r),e.error&&e.error("Please reduce your chart to a single panel and try again.")}}function r(e){var t=e.$el,n=e.url,r=e.name,s=new XMLSerializer,o=document.createElement("canvas"),u=$(o),a=t.find("svg").length,f=t.find("svg").first(),l=parseInt(f.css("height")),c=parseInt(f.css("width"));u.attr("width",c*a),u.attr("height",l),(!o.getContext||!o.getContext("2d"))&&alert("Your browser doesn't support this feature, please use a modern browser");var h=o.getContext("2d"),p=0;t.find("svg").each(function(){var e=$(this);e.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:c,height:l});var t=s.serializeToString(this);h.drawSvg(t,p,0,c,l),p+=c}),window.location.href=i(o,o.getContext("2d"),"white").replace("image/png","image/octet-stream")}function i(e,t,n){var r=e.width,i=e.height,s;if(n){s=t.getImageData(0,0,r,i);var o=t.globalCompositeOperation;t.globalCompositeOperation="destination-over",t.fillStyle=n,t.fillRect(0,0,r,i)}var u=e.toDataURL("image/png");return n&&(t.clearRect(0,0,r,i),t.putImageData(s,0,0),t.globalCompositeOperation=o),u}function s(e){window.location.href="data:none/none;base64,"+btoa(a(e).string)}function o(e){for(var t in document.styleSheets){var n=document.styleSheets[t],r=n.cssRules;if(r)for(var i=0,s=r.length;i<s;i++)try{e.find(r[i].selectorText).each(function(e,t){t.style.cssText+=r[i].style.cssText})}catch(o){}}}function u(e){var t=a(e),n={filename:name||"chart",type:"application/pdf",height:t.height,width:t.width,scale:2,svg:t.string},r=$("body"),i=r.find("#viewport-form");i.length===0&&(i=$("<form>",{id:"viewport-form",method:"post",action:"http://export.highcharts.com/",display:"none"}),r.append(i)),i.empty();for(name in n){var s=$("<input/>",{type:"hidden",name:name,value:n[name]});i.append(s)}try{i.submit()}catch(o){console.log(o)}}function a(e){if(e.$el.find("svg").length==0&&e.error){e.error("No SVG found. This chart type does not support SVG/PDF export.");return}var t=e.$el,n=t.find("svg").length,r=parseInt(t.find("svg").first().css("height")),i=parseInt(t.find("svg").first().css("width")),s=new XMLSerializer,u=$("<svg/>");u.attr({version:"1.1",xmlns:"http://www.w3.org/2000/svg",width:i*n,height:r});var a="",f=0;return t.find("svg").each(function(){var e=$(this).clone();o(e);var t=$('<g transform="translate('+f+', 0)">');t.append(e.find("g").first()),u.append(t),f+=i}),{string:s.serializeToString(u[0]),height:r,width:i}}return{createPNG:t,createSVG:s,createPDF:u}}),define("plugin/views/viewer",["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-portlet","plugin/views/viewport","plugin/library/screenshot"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,s){this.app=e,this.chart=this.app.chart,this.viewport_view=new r(e);var o=this;this.message=new t.Message;var u=new t.ButtonMenu({icon:"fa-camera",title:"Screenshot",tooltip:"Download as PNG, SVG or PDF file"});u.addMenu({id:"button-png",title:"Save as PNG",icon:"fa-file",onclick:function(){o._wait(o.chart,function(){i.createPNG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-svg",title:"Save as SVG",icon:"fa-file-text-o",onclick:function(){o._wait(o.chart,function(){i.createSVG({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}),u.addMenu({id:"button-png",title:"Save as PDF",icon:"fa-file-o",onclick:function(){o.app.modal.show({title:"Send chart data for PDF creation",body:"Galaxy does not provide integrated PDF export scripts. You may click 'Continue' to create the PDF by using a 3rd party service (https://export.highcharts.com)",buttons:{Cancel:function(){o.app.modal.hide()},Continue:function(){o.app.modal.hide(),o._wait(o.chart,function(){i.createPDF({$el:o.viewport_view.$el,title:o.chart.get("title"),error:function(e){o.message.update({message:e,status:"danger"})}})})}}})}}),this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",scrollable:!1,operations:{edit_button:new t.ButtonIcon({icon:"fa-edit",tooltip:"Customize this chart",title:"Editor",onclick:function(){o._wait(o.chart,function(){o.app.go("editor")})}}),picture_button_menu:u}}),this.portlet.append(this.message.$el),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var o=this;this.chart.on("change:title",function(){o._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){this.app.deferred.ready()?t():this.message.update({message:"Your chart is currently being processed. Please wait and try again."})}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{title_new:"",operations:null,onnew:null,max:null,onchange:null},initialize:function(t){this.visible=!1,this.$nav=null,this.$content=null,this.first_tab=null,this.current_id=null,this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},size:function(){return _.size(this.list)},current:function(){return this.$el.find(".tab-pane.active").attr("id")},add:function(e){var t=this,n=e.id,r=$(this._template_tab(e)),i=$(this._template_tab_content(e));this.list[n]=e.ondel?!0:!1,this.options.onnew?this.$nav.find("#new-tab").before(r):this.$nav.append(r),i.append(e.$el),this.$content.append(i),this.size()==1&&(r.addClass("active"),i.addClass("active"),this.first_tab=n),this.options.max&&this.size()>=this.options.max&&this.$el.find("#new-tab").hide();if(e.ondel){var s=r.find("#delete");s.tooltip({title:"Delete this tab",placement:"bottom",container:t.$el}),s.on("click",function(){return s.tooltip("destroy"),t.$el.find(".tooltip").remove(),e.ondel(),!1})}r.on("click",function(r){r.preventDefault(),e.onclick?e.onclick():t.show(n)}),this.current_id||(this.current_id=n)},del:function(e){this.$el.find("#tab-"+e).remove(),this.$el.find("#"+e).remove(),this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab),this.list[e]&&delete this.list[e],this.size()<this.options.max&&this.$el.find("#new-tab").show()},delRemovable:function(){for(var e in this.list)this.del(e)},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&(this.$el.find("#tab-"+this.current_id).removeClass("active"),this.$el.find("#"+this.current_id).removeClass("active"),this.$el.find("#tab-"+e).addClass("active"),this.$el.find("#"+e).addClass("active"),this.current_id=e),this.options.onchange&&this.options.onchange(e)},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.$el.find("#tab-title-text-"+e);return t&&n.html(t),n.html()},retitle:function(e){var t=0;for(var n in this.list)this.title(n,++t+": "+e)},_template:function(e){return'<div class="ui-tabs tabbable tabs-left"><ul id="tab-navigation" class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div id="tab-content" class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i class="ui-tabs-add fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="tab-'+e.id+'" class="tab-element">'+'<a id="tab-title-link-'+e.id+'" title="" href="#'+e.id+'" data-original-title="">'+'<span id="tab-title-text-'+e.id+'" class="tab-title-text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" class="ui-tabs-delete fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("mvc/ui/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null,cls:"ui-table",cls_tr:""},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=this._row()},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},append:function(e,t){this._commit(e,t,!1)},prepend:function(e,t){this._commit(e,t,!0)},get:function(e){return this.$el.find("#"+e)},del:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},delAll:function(){this.$tbody.empty(),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t,n){this.del(e),this.row.attr("id",e),n?this.$tbody.prepend(this.row):this.$tbody.append(this.row),t&&(this.row.hide(),this.row.fadeIn()),this.row=this._row(),this.row_count++,this._refresh()},_row:function(){return $('<tr class="'+this.options.cls_tr+'"></tr>')},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n!=""&&n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="'+e.cls+'">'+"<thead></thead>"+"<tbody></tbody>"+"</table>"+"<tmessage>"+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(e){s.group.set("key",e)}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.chart.definition;this.table.delAll();var s={};for(var o in i.columns){var u=i.columns[o];if(!u){console.debug("Group::_refreshTable() - Skipping column definition.");continue}var a=new t.Select.View({id:"select_"+o,wait:!0}),f=u.title;u.is_unique&&(f+=" (all data labels)"),this.table.add(f,"25%"),this.table.add(a.$el),this.table.append(o),s[o]=a}this.chart.state("wait","Loading metadata...");var l=this.app.deferred.register(),c={id:e,success:function(e){for(var t in s)r._addRow(t,e,s,i.columns[t]);r.chart.state("ok","Metadata initialized..."),r.app.deferred.done(l)}};this.app.datasets.request(c)},_addRow:function(e,t,n,r){var i=this,s=r.is_label,o=r.is_auto,u=r.is_numeric,a=r.is_unique,f=r.is_zero,l=[],c=n[e];o&&l.push({label:"Column: Row Number",value:"auto"}),f&&l.push({label:"Column: None",value:"zero"});var h=t.metadata_column_types;for(var p in h){var d=!1;h[p]=="int"||h[p]=="float"?d=u:d=s,d&&l.push({label:"Column: "+(parseInt(p)+1)+" ["+h[p]+"]",value:p})}c.update(l),a&&this.chart.groups.first()&&this.group.set(e,this.chart.groups.first().get(e));if(!c.exists(this.group.get(e))){var v=c.first();console.debug('Group()::_addRow() - Switching model value from "'+this.group.get(e)+'" to "'+v+'".'),this.group.set(e,v)}c.value(this.group.get(e)),this.group.off("change:"+e),this.group.on("change:"+e,function(){c.value(i.group.get(e))}),c.setOnChange(function(t){a?i.chart.groups.each(function(n){n.set(e,t)}):i.group.set(e,t),i.chart.set("modified",!0)}),c.show()},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["mvc/ui/ui-table","mvc/ui/ui-misc","utils/utils"],function(e,t,n){var r=Backbone.View.extend({optionsDefault:{title:"",content:"",mode:""},list:[],initialize:function(r,i){this.app=r,this.options=n.merge(i,this.optionsDefault),this.table_title=new t.Label({title:this.options.title}),this.table=new e.View({content:this.options.content});var s=$('<div class="ui-table-form"/>');this.options.title&&s.append(n.wrap(this.table_title.$el)),s.append(n.wrap(this.table.$el)),this.setElement(s)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.delAll(),this.list=[];for(var n in e)this._add(e[n].id||n,e[n],t);for(var n in this.list)this.list[n].trigger("change")},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:"field-"+e,placeholder:n.placeholder,value:r.get(e),onchange:function(t){r.set(e,t)}});break;case"radiobutton":s=new t.RadioButton.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"select":s=new t.Select.View({id:"field-"+e,data:n.data,value:r.get(e),onchange:function(t){r.set(e,t);var s=_.findWhere(n.data,{value:t});if(s&&s.operations){var o=s.operations;for(var u in o.show){var a=o.show[u];i.table.get(a).show()}for(var u in o.hide){var a=o.hide[u];i.table.get(a).hide()}}}});break;case"dataset":s=new t.Select.View({id:"field-"+e,onchange:function(t){r.set(e,t)}}),i.app.datasets.on("all",function(){var t=[];i.app.datasets.each(function(e){e.get("datatype_id")==n.data&&t.push({value:e.get("id"),label:e.get("name")})}),s.update(t),r.get(e)||r.set(e,s.first()),s.value(r.get(e))}),i.app.datasets.trigger("all.datasets");break;case"textarea":s=new t.Textarea({id:"field-"+e,onchange:function(){r.set(e,s.value())}});break;case"separator":s=$("<div/>");break;default:s=new t.Input({id:"field-"+e,placeholder:n.placeholder,type:n.type,onchange:function(){r.set(e,s.value())}})}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),n.info&&u.append('<div class="ui-table-form-info">'+n.info+"</div>"),this.options.style=="bold"?(this.table.add((new t.Label({title:n.title,cls:"form-label"})).$el),this.table.add(u)):(this.table.add('<span class="ui-table-form-title">'+n.title+"</span>","25%"),this.table.add(u))}else this.table.add('<div class="ui-table-form-separator">'+n.title+":<div/>"),this.table.add($("<div/>"));this.table.append(e),n.hide&&this.table.get(e).hide()}});return{View:r}}),define("plugin/views/settings",["mvc/ui/ui-misc","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View(e,{title:"Configuration",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refresh()})},_refresh:function(){var e=this.chart.definition;if(!e)return;this.form.title(e.category+" - "+e.title+":"),this.form.update(e.settings,this.chart.settings)}})}),define("plugin/views/types",["utils/utils","mvc/ui/ui-misc"],function(e,t){return Backbone.View.extend({optionsDefault:{onchange:null,ondblclick:null},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(n,r){var i=this;this.app=n,this.options=e.merge(r,this.optionsDefault);var s=$('<div class="charts-grid"/>');s.append(e.wrap((new t.Label({title:"How many data points would you like to analyze?"})).$el)),this.library=new t.RadioButton.View({data:[{label:"Few (<500)",value:"small"},{label:"Some (<10k)",value:"medium"},{label:"Many (>10k)",value:"large"}],onchange:function(e){i._filter(e)}}),s.append(e.wrap(this.library.$el)),this.setElement(s),this._render(),this.library.value("small"),this.library.trigger("change")},value:function(e){var t=this.$el.find(".current").attr("id");e!==undefined&&(this.$el.find(".current").removeClass("current"),this.$el.find("#"+e).addClass("current"));var n=this.$el.find(".current").attr("id");return n===undefined?null:(n!=t&&this.options.onchange&&this.options.onchange(e),n)},_filter:function(e){this.$el.find(".header").hide();var t=this.app.types.attributes;for(var n in t){var r=t[n],i=this.$el.find("#"+n),s=this.$el.find("#types-header-"+this.categories_index[r.category]),o=r.keywords||"";o.indexOf(e)>=0?(i.show(),s.show()):i.hide()}},_render:function(){this.categories={},this.categories_index={};var e=0,t=this.app.types.attributes;for(var n in t){var r=t[n],i=r.category;this.categories[i]||(this.categories[i]={},this.categories_index[i]=e++),this.categories[i][n]=r}for(var i in this.categories){var s=$('<div style="clear: both;"/>');s.append(this._template_header({id:"types-header-"+this.categories_index[i],title:i}));for(var n in this.categories[i]){var r=this.categories[i][n],o=r.title+" ("+r.library+")";r.zoomable&&(o='<span class="fa fa-search-plus"/>'+o),s.append(this._template_item({id:n,title:o,url:config.app_root+"charts/"+this.app.chartPath(n)+"/logo.png"}))}this.$el.append(s)}},_onclick:function(e){var t=this.value(),n=$(e.target).closest(".item").attr("id");n!=""&&n&&t!=n&&this.value(n)},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_template_header:function(e){return'<div id="'+e.id+'" class="header">'+"• "+e.title+"<div>"},_template_item:function(e){return'<div id="'+e.id+'" class="item">'+'<img class="image" src="'+e.url+'">'+'<div class="title">'+e.title+"</div>"+"<div>"}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","mvc/ui/ui-misc","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings","plugin/views/types"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({initialize:function(i,s){var o=this;this.app=i,this.chart=this.app.chart,this.message=new t.Message,this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new t.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){o._saveChart()}}),back:new t.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Cancel",onclick:function(){o.app.go("viewer"),o.app.storage.load()}})}}),this.types=new a(i,{onchange:function(e){var t=o.app.types.get(e);t||console.debug("FAILED - Editor::onchange() - Chart type not supported."),o.chart.definition=t,o.chart.settings.clear(),o.chart.set({type:e}),o.chart.set("modified",!0),console.debug("Editor::onchange() - Switched chart type.")},ondblclick:function(e){o._saveChart()}}),this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=o._addGroupModel();o.tabs.show(e.id)}}),this.title=new t.Input({placeholder:"Chart title",onchange:function(){o.chart.set("title",o.title.value())}});var f=$("<div/>");f.append(r.wrap((new t.Label({title:"Provide a chart title:"})).$el)),f.append(r.wrap(this.title.$el)),f.append(r.wrap(this.types.$el)),this.tabs.add({id:"main",title:"Start",$el:f}),this.settings=new u(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.message.$el),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var o=this;this.chart.on("change:title",function(e){o._refreshTitle()}),this.chart.on("change:type",function(e){o.types.value(e.get("type"))}),this.chart.on("reset",function(e){o._resetChart()}),this.app.chart.on("redraw",function(e){o.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){o._addGroup(e)}),this.app.chart.groups.on("remove",function(e){o._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){o._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){o._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Data label"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new s({id:r.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new o(this.app,{group:e});this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",r.uuid()),this.chart.set("type","nvd3_bar"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.types.value(),title:this.title.value(),date:r.time()});if(this.chart.groups.length==0){this.message.update({message:"Please select data columns before drawing the chart."});var e=this._addGroupModel();this.tabs.show(e.id);return}var t=this,n=!0,i=this.chart.definition;this.chart.groups.each(function(e){if(!n)return;for(var r in i.columns)if(e.attributes[r]=="null"){t.message.update({status:"danger",message:"This chart type requires column types not found in your tabular file."}),t.tabs.show(e.id),n=!1;return}});if(!n)return;this.app.go("viewer");var t=this;this.app.deferred.execute(function(){t.app.storage.save(),t.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e4,query_timeout:100}})}),define("plugin/charts/forms/default",[],function(){return{title:"",category:"",library:"",tag:"",keywords:"",settings:{separator_x:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["x_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["x_axis_precision"]}},{label:"Float",value:"f",operations:{show:["x_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["x_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["x_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["x_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["x_axis_precision"]}}]},x_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_y:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",operations:{hide:["y_axis_precision"]}},{label:"Auto",value:"auto",operations:{hide:["y_axis_precision"]}},{label:"Float",value:"f",operations:{show:["y_axis_precision"]}},{label:"Exponent",value:"e",operations:{show:["y_axis_precision"]}},{label:"Integer",value:"d",operations:{hide:["y_axis_precision"]}},{label:"Percentage",value:"p",operations:{show:["y_axis_precision"]}},{label:"SI-prefix",value:"s",operations:{hide:["y_axis_precision"]}}]},y_axis_precision:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:"1",data:[{label:"0.00001",value:"5"},{label:"0.0001",value:"4"},{label:"0.001",value:"3"},{label:"0.01",value:"2"},{label:"0.1",value:"1"},{label:"1",value:"0"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{title:"Use multi-panels",info:"Would you like to separate your data into individual panels?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),function(){function t(e,t){return(new Date(t,e+1,0)).getDate()}function n(e,t,n){return function(r,i,s){var o=e(r),u=[];o<r&&t(o);if(s>1)while(o<i){var a=new Date(+o);n(a)%s===0&&u.push(a),t(o)}else while(o<i)u.push(new Date(+o)),t(o);return u}}var e=window.nv||{};e.version="1.1.15b",e.dev=!0,window.nv=e,e.tooltip=e.tooltip||{},e.utils=e.utils||{},e.models=e.models||{},e.charts={},e.graphs=[],e.logs={},e.dispatch=d3.dispatch("render_start","render_end"),e.dev&&(e.dispatch.on("render_start",function(t){e.logs.startTime=+(new Date)}),e.dispatch.on("render_end",function(t){e.logs.endTime=+(new Date),e.logs.totalTime=e.logs.endTime-e.logs.startTime,e.log("total",e.logs.totalTime)})),e.log=function(){if(e.dev&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(e.dev&&typeof console.log=="function"&&Function.prototype.bind){var t=Function.prototype.bind.call(console.log,console);t.apply(console,arguments)}return arguments[arguments.length-1]},e.render=function(n){n=n||1,e.render.active=!0,e.dispatch.render_start(),setTimeout(function(){var t,r;for(var i=0;i<n&&(r=e.render.queue[i]);i++)t=r.generate(),typeof r.callback==typeof Function&&r.callback(t),e.graphs.push(t);e.render.queue.splice(0,i),e.render.queue.length?setTimeout(arguments.callee,0):(e.dispatch.render_end(),e.render.active=!1)},0)},e.render.active=!1,e.render.queue=[],e.addGraph=function(t){typeof arguments[0]==typeof Function&&(t={generate:arguments[0],callback:arguments[1]}),e.render.queue.push(t),e.render.active||e.render()},e.identity=function(e){return e},e.strip=function(e){return e.replace(/(\s|&)/g,"")},d3.time.monthEnd=function(e){return new Date(e.getFullYear(),e.getMonth(),0)},d3.time.monthEnds=n(d3.time.monthEnd,function(e){e.setUTCDate(e.getUTCDate()+1),e.setDate(t(e.getMonth()+1,e.getFullYear()))},function(e){return e.getMonth()}),e.interactiveGuideline=function(){function c(o){o.each(function(o){function g(){var e=d3.mouse(this),n=e[0],r=e[1],o=!0,a=!1;l&&(n=d3.event.offsetX,r=d3.event.offsetY,d3.event.target.tagName!=="svg"&&(o=!1),d3.event.target.className.baseVal.match("nv-legend")&&(a=!0)),o&&(n-=i.left,r-=i.top);if(n<0||r<0||n>p||r>d||d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined||a){if(l&&d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined&&d3.event.relatedTarget.className.match(t.nvPointerEventsClass))return;u.elementMouseout({mouseX:n,mouseY:r}),c.renderGuideLine(null);return}var f=s.invert(n);u.elementMousemove({mouseX:n,mouseY:r,pointXValue:f}),d3.event.type==="dblclick"&&u.elementDblclick({mouseX:n,mouseY:r,pointXValue:f})}var h=d3.select(this),p=n||960,d=r||400,v=h.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([o]),m=v.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");m.append("g").attr("class","nv-interactiveGuideLine");if(!f)return;f.on("mousemove",g,!0).on("mouseout",g,!0).on("dblclick",g),c.renderGuideLine=function(t){if(!a)return;var n=v.select(".nv-interactiveGuideLine").selectAll("line").data(t!=null?[e.utils.NaNtoZero(t)]:[],String);n.enter().append("line").attr("class","nv-guideline").attr("x1",function(e){return e}).attr("x2",function(e){return e}).attr("y1",d).attr("y2",0),n.exit().remove()}})}var t=e.models.tooltip(),n=null,r=null,i={left:0,top:0},s=d3.scale.linear(),o=d3.scale.linear(),u=d3.dispatch("elementMousemove","elementMouseout","elementDblclick"),a=!0,f=null,l=navigator.userAgent.indexOf("MSIE")!==-1;return c.dispatch=u,c.tooltip=t,c.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.left=typeof e.left!="undefined"?e.left:i.left,c):i},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.xScale=function(e){return arguments.length?(s=e,c):s},c.showGuideLine=function(e){return arguments.length?(a=e,c):a},c.svgContainer=function(e){return arguments.length?(f=e,c):f},c},e.interactiveBisect=function(e,t,n){if(!e instanceof Array)return null;typeof n!="function"&&(n=function(e,t){return e.x});var r=d3.bisector(n).left,i=d3.max([0,r(e,t)-1]),s=n(e[i],i);typeof s=="undefined"&&(s=i);if(s===t)return i;var o=d3.min([i+1,e.length-1]),u=n(e[o],o);return typeof u=="undefined"&&(u=o),Math.abs(u-t)>=Math.abs(s-t)?i:o},e.nearestValueIndex=function(e,t,n){var r=Infinity,i=null;return e.forEach(function(e,s){var o=Math.abs(t-e);o<=r&&o<n&&(r=o,i=s)}),i},function(){window.nv.tooltip={},window.nv.models.tooltip=function(){function y(){if(a){var e=d3.select(a);e.node().tagName!=="svg"&&(e=e.select("svg"));var t=e.node()?e.attr("viewBox"):null;if(t){t=t.split(" ");var n=parseInt(e.style("width"))/t[2];l.left=l.left*n,l.top=l.top*n}}}function b(e){var t;a?t=d3.select(a):t=d3.select("body");var n=t.select(".nvtooltip");return n.node()===null&&(n=t.append("div").attr("class","nvtooltip "+(u?u:"xy-tooltip")).attr("id",h)),n.node().innerHTML=e,n.style("top",0).style("left",0).style("opacity",0),n.selectAll("div, table, td, tr").classed(p,!0),n.classed(p,!0),n.node()}function w(){if(!c)return;if(!g(n))return;y();var t=l.left,u=o!=null?o:l.top,h=b(m(n));f=h;if(a){var p=a.getElementsByTagName("svg")[0],d=p?p.getBoundingClientRect():a.getBoundingClientRect(),v={left:0,top:0};if(p){var E=p.getBoundingClientRect(),S=a.getBoundingClientRect(),x=E.top;if(x<0){var T=a.getBoundingClientRect();x=Math.abs(x)>T.height?0:x}v.top=Math.abs(x-S.top),v.left=Math.abs(E.left-S.left)}t+=a.offsetLeft+v.left-2*a.scrollLeft,u+=a.offsetTop+v.top-2*a.scrollTop}return s&&s>0&&(u=Math.floor(u/s)*s),e.tooltip.calcTooltipPosition([t,u],r,i,h),w}var t=null,n=null,r="w",i=50,s=25,o=null,u=null,a=null,f=null,l={left:null,top:null},c=!0,h="nvtooltip-"+Math.floor(Math.random()*1e5),p="nv-pointer-events-none",d=function(e,t){return e},v=function(e){return e},m=function(e){if(t!=null)return t;if(e==null)return"";var n=d3.select(document.createElement("table")),r=n.selectAll("thead").data([e]).enter().append("thead");r.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(v(e.value));var i=n.selectAll("tbody").data([e]).enter().append("tbody"),s=i.selectAll("tr").data(function(e){return e.series}).enter().append("tr").classed("highlight",function(e){return e.highlight});s.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(e){return e.color}),s.append("td").classed("key",!0).html(function(e){return e.key}),s.append("td").classed("value",!0).html(function(e,t){return d(e.value,t)}),s.selectAll("td").each(function(e){if(e.highlight){var t=d3.scale.linear().domain([0,1]).range(["#fff",e.color]),n=.6;d3.select(this).style("border-bottom-color",t(n)).style("border-top-color",t(n))}});var o=n.node().outerHTML;return e.footer!==undefined&&(o+="<div class='footer'>"+e.footer+"</div>"),o},g=function(e){return e&&e.series&&e.series.length>0?!0:!1};return w.nvPointerEventsClass=p,w.content=function(e){return arguments.length?(t=e,w):t},w.tooltipElem=function(){return f},w.contentGenerator=function(e){return arguments.length?(typeof e=="function"&&(m=e),w):m},w.data=function(e){return arguments.length?(n=e,w):n},w.gravity=function(e){return arguments.length?(r=e,w):r},w.distance=function(e){return arguments.length?(i=e,w):i},w.snapDistance=function(e){return arguments.length?(s=e,w):s},w.classes=function(e){return arguments.length?(u=e,w):u},w.chartContainer=function(e){return arguments.length?(a=e,w):a},w.position=function(e){return arguments.length?(l.left=typeof e.left!="undefined"?e.left:l.left,l.top=typeof e.top!="undefined"?e.top:l.top,w):l},w.fixedTop=function(e){return arguments.length?(o=e,w):o},w.enabled=function(e){return arguments.length?(c=e,w):c},w.valueFormatter=function(e){return arguments.length?(typeof e=="function"&&(d=e),w):d},w.headerFormatter=function(e){return arguments.length?(typeof e=="function"&&(v=e),w):v},w.id=function(){return h},w},e.tooltip.show=function(t,n,r,i,s,o){var u=document.createElement("div");u.className="nvtooltip "+(o?o:"xy-tooltip");var a=s;if(!s||s.tagName.match(/g|svg/i))a=document.getElementsByTagName("body")[0];u.style.left=0,u.style.top=0,u.style.opacity=0,u.innerHTML=n,a.appendChild(u),s&&(t[0]=t[0]-s.scrollLeft,t[1]=t[1]-s.scrollTop),e.tooltip.calcTooltipPosition(t,r,i,u)},e.tooltip.findFirstNonSVGParent=function(e){while(e.tagName.match(/^g|svg$/i)!==null)e=e.parentNode;return e},e.tooltip.findTotalOffsetTop=function(e,t){var n=t;do isNaN(e.offsetTop)||(n+=e.offsetTop);while(e=e.offsetParent);return n},e.tooltip.findTotalOffsetLeft=function(e,t){var n=t;do isNaN(e.offsetLeft)||(n+=e.offsetLeft);while(e=e.offsetParent);return n},e.tooltip.calcTooltipPosition=function(t,n,r,i){var s=parseInt(i.offsetHeight),o=parseInt(i.offsetWidth),u=e.utils.windowSize().width,a=e.utils.windowSize().height,f=window.pageYOffset,l=window.pageXOffset,c,h;a=window.innerWidth>=document.body.scrollWidth?a:a-16,u=window.innerHeight>=document.body.scrollHeight?u:u-16,n=n||"s",r=r||20;var p=function(t){return e.tooltip.findTotalOffsetTop(t,h)},d=function(t){return e.tooltip.findTotalOffsetLeft(t,c)};switch(n){case"e":c=t[0]-o-r,h=t[1]-s/2;var v=d(i),m=p(i);v<l&&(c=t[0]+r>l?t[0]+r:l-v+c),m<f&&(h=f-m+h),m+s>f+a&&(h=f+a-m+h-s);break;case"w":c=t[0]+r,h=t[1]-s/2;var v=d(i),m=p(i);v+o>u&&(c=t[0]-o-r),m<f&&(h=f+5),m+s>f+a&&(h=f+a-m+h-s);break;case"n":c=t[0]-o/2-5,h=t[1]+r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),m+s>f+a&&(h=f+a-m+h-s);break;case"s":c=t[0]-o/2,h=t[1]-s-r;var v=d(i),m=p(i);v<l&&(c=l+5),v+o>u&&(c=c-o/2+5),f>m&&(h=f);break;case"none":c=t[0],h=t[1]-r;var v=d(i),m=p(i)}return i.style.left=c+"px",i.style.top=h+"px",i.style.opacity=1,i.style.position="absolute",i},e.tooltip.cleanup=function(){var e=document.getElementsByClassName("nvtooltip"),t=[];while(e.length)t.push(e[0]),e[0].style.transitionDelay="0 !important",e[0].style.opacity=0,e[0].className="nvtooltip-pending-removal";setTimeout(function(){while(t.length){var e=t.pop();e.parentNode.removeChild(e)}},500)}}(),e.utils.windowSize=function(){var e={width:640,height:480};return document.body&&document.body.offsetWidth&&(e.width=document.body.offsetWidth,e.height=document.body.offsetHeight),document.compatMode=="CSS1Compat"&&document.documentElement&&document.documentElement.offsetWidth&&(e.width=document.documentElement.offsetWidth,e.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(e.width=window.innerWidth,e.height=window.innerHeight),e},e.utils.windowResize=function(e){if(e===undefined)return;var t=window.onresize;window.onresize=function(n){typeof t=="function"&&t(n),e(n)}},e.utils.getColor=function(t){return arguments.length?Object.prototype.toString.call(t)==="[object Array]"?function(e,n){return e.color||t[n%t.length]}:t:e.utils.defaultColor()},e.utils.defaultColor=function(){var e=d3.scale.category20().range();return function(t,n){return t.color||e[n%e.length]}},e.utils.customTheme=function(e,t,n){t=t||function(e){return e.key},n=n||d3.scale.category20().range();var r=n.length;return function(i,s){var o=t(i);return r||(r=n.length),typeof e[o]!="undefined"?typeof e[o]=="function"?e[o]():e[o]:n[--r]}},e.utils.pjax=function(t,n){function r(r){d3.html(r,function(r){var i=d3.select(n).node();i.parentNode.replaceChild(d3.select(r).select(n).node(),i),e.utils.pjax(t,n)})}d3.selectAll(t).on("click",function(){history.pushState(this.href,this.textContent,this.href),r(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&r(d3.event.state)})},e.utils.calcApproxTextWidth=function(e){if(typeof e.style=="function"&&typeof e.text=="function"){var t=parseInt(e.style("font-size").replace("px","")),n=e.text().length;return n*t*.5}return 0},e.utils.NaNtoZero=function(e){return typeof e!="number"||isNaN(e)||e===null||e===Infinity?0:e},e.utils.optionsFunc=function(e){return e&&d3.map(e).forEach(function(e,t){typeof this[e]=="function"&&this[e](t)}.bind(this)),this},e.models.axis=function(){function m(e){return e.each(function(e){var i=d3.select(this),m=i.selectAll("g.nv-wrap.nv-axis").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),y=g.append("g"),b=m.select("g");p!==null?t.ticks(p):(t.orient()=="top"||t.orient()=="bottom")&&t.ticks(Math.abs(s.range()[1]-s.range()[0])/100),b.call(t),v=v||t.scale();var w=t.tickFormat();w==null&&(w=v.tickFormat());var E=b.selectAll("text.nv-axislabel").data([o||null]);E.exit().remove();switch(t.orient()){case"top":E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",0).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+s(e)+",0)"}).select("text").attr("dy","-0.5em").attr("y",-t.tickPadding()).attr("text-anchor","middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+s.range()[t]+",0)"})}break;case"bottom":var T=36,N=30,C=b.selectAll("g").select("text");if(f%360){C.each(function(e,t){var n=this.getBBox().width;n>N&&(N=n)});var k=Math.abs(Math.sin(f*Math.PI/180)),T=(k?k*N:N)+30;C.attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f%360>0?"start":"end")}E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",T).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data([s.domain()[0],s.domain()[s.domain().length-1]]);x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",t.tickPadding()).attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f?f%360>0?"start":"end":"middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"})}c&&C.attr("transform",function(e,t){return"translate(0,"+(t%2==0?"0":"12")+")"});break;case"right":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"begin").attr("transform",l?"rotate(90)":"").attr("y",l?-Math.max(n.right,r)+12:-10).attr("x",l?s.range()[0]/2:t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+s(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",t.tickPadding()).style("text-anchor","start").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}break;case"left":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"end").attr("transform",l?"rotate(-90)":"").attr("y",l?-Math.max(n.left,r)+d:-10).attr("x",l?-s.range()[0]/2:-t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+v(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-t.tickPadding()).attr("text-anchor","end").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}}E.text(function(e){return e}),u&&(t.orient()==="left"||t.orient()==="right")&&(b.selectAll("g").each(function(e,t){d3.select(this).select("text").attr("opacity",1);if(s(e)<s.range()[1]+10||s(e)>s.range()[0]-10)(e>1e-10||e<-1e-10)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0)}),s.domain()[0]==s.domain()[1]&&s.domain()[0]==0&&m.selectAll("g.nv-axisMaxMin").style("opacity",function(e,t){return t?0:1}));if(u&&(t.orient()==="top"||t.orient()==="bottom")){var L=[];m.selectAll("g.nv-axisMaxMin").each(function(e,t){try{t?L.push(s(e)-this.getBBox().width-4):L.push(s(e)+this.getBBox().width+4)}catch(n){t?L.push(s(e)-4):L.push(s(e)+4)}}),b.selectAll("g").each(function(e,t){if(s(e)<L[0]||s(e)>L[1])e>1e-10||e<-1e-10?d3.select(this).remove():d3.select(this).select("text").remove()})}a&&b.selectAll(".tick").filter(function(e){return!parseFloat(Math.round(e.__data__*1e5)/1e6)&&e.__data__!==undefined}).classed("zero",!0),v=s.copy()}),m}var t=d3.svg.axis(),n={top:0,right:0,bottom:0,left:0},r=75,i=60,s=d3.scale.linear(),o=null,u=!0,a=!0,f=0,l=!0,c=!1,h=!1,p=null,d=12;t.scale(s).orient("bottom").tickFormat(function(e){return e});var v;return m.axis=t,d3.rebind(m,t,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.ticks=function(e){return arguments.length?(p=e,m):p},m.height=function(e){return arguments.length?(i=e,m):i},m.axisLabel=function(e){return arguments.length?(o=e,m):o},m.showMaxMin=function(e){return arguments.length?(u=e,m):u},m.highlightZero=function(e){return arguments.length?(a=e,m):a},m.scale=function(e){return arguments.length?(s=e,t.scale(s),h=typeof s.rangeBands=="function",d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m):s},m.rotateYLabel=function(e){return arguments.length?(l=e,m):l},m.rotateLabels=function(e){return arguments.length?(f=e,m):f},m.staggerLabels=function(e){return arguments.length?(c=e,m):c},m.axisLabelDistance=function(e){return arguments.length?(d=e,m):d},m},e.models.historicalBar=function(){function w(E){return E.each(function(w){var E=n-t.left-t.right,S=r-t.top-t.bottom,T=d3.select(this);s.domain(d||d3.extent(w[0].values.map(u).concat(f))),c?s.range(m||[E*.5/w[0].values.length,E*(w[0].values.length-.5)/w[0].values.length]):s.range(m||[0,E]),o.domain(v||d3.extent(w[0].values.map(a).concat(l))).range(g||[S,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=T.selectAll("g.nv-wrap.nv-historicalBar-"+i).data([w[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+i),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-bars"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){y.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",E).attr("height",S),A.attr("clip-path",h?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-bars").selectAll(".nv-bar").data(function(e){return e},function(e,t){return u(e,t)});O.exit().remove();var M=O.enter().append("rect").attr("x",0).attr("y",function(t,n){return e.utils.NaNtoZero(o(Math.max(0,a(t,n))))}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.abs(o(a(t,n))-o(0)))}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).on("mouseover",function(e,t){if(!b)return;d3.select(this).classed("hover",!0),y.elementMouseover({point:e,series:w[0],pos:[s(u(e,t)),o(a(e,t))],pointIndex:t,seriesIndex:0,e:d3.event})}).on("mouseout",function(e,t){if(!b)return;d3.select(this).classed("hover",!1),y.elementMouseout({point:e,series:w[0],pointIndex:t,seriesIndex:0,e:d3.event})}).on("click",function(e,t){if(!b)return;y.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){if(!b)return;y.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("fill",function(e,t){return p(e,t)}).attr("class",function(e,t,n){return(a(e,t)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+n+"-"+t}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).attr("width",E/w[0].values.length*.9),O.attr("y",function(t,n){var r=a(t,n)<0?o(0):o(0)-o(a(t,n))<1?o(0)-1:o(a(t,n));return e.utils.NaNtoZero(r)}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.max(Math.abs(o(a(t,n))-o(0)),1))})}),w}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[],l=[0],c=!1,h=!0,p=e.utils.defaultColor(),d,v,m,g,y=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),b=!0;return w.highlightPoint=function(e,t){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar-0-"+e).classed("hover",t)},w.clearHighlights=function(){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar.hover").classed("hover",!1)},w.dispatch=y,w.options=e.utils.optionsFunc.bind(w),w.x=function(e){return arguments.length?(u=e,w):u},w.y=function(e){return arguments.length?(a=e,w):a},w.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,w):t},w.width=function(e){return arguments.length?(n=e,w):n},w.height=function(e){return arguments.length?(r=e,w):r},w.xScale=function(e){return arguments.length?(s=e,w):s},w.yScale=function(e){return arguments.length?(o=e,w):o},w.xDomain=function(e){return arguments.length?(d=e,w):d},w.yDomain=function(e){return arguments.length?(v=e,w):v},w.xRange=function(e){return arguments.length?(m=e,w):m},w.yRange=function(e){return arguments.length?(g=e,w):g},w.forceX=function(e){return arguments.length?(f=e,w):f},w.forceY=function(e){return arguments.length?(l=e,w):l},w.padData=function(e){return arguments.length?(c=e,w):c},w.clipEdge=function(e){return arguments.length?(h=e,w):h},w.color=function(t){return arguments.length?(p=e.utils.getColor(t),w):p},w.id=function(e){return arguments.length?(i=e,w):i},w.interactive=function(e){return arguments.length?(b=!1,w):b},w},e.models.bullet=function(){function m(e){return e.each(function(e,n){var p=c-t.left-t.right,m=h-t.top-t.bottom,g=d3.select(this),y=i.call(this,e,n).slice().sort(d3.descending),b=s.call(this,e,n).slice().sort(d3.descending),w=o.call(this,e,n).slice().sort(d3.descending),E=u.call(this,e,n).slice(),S=a.call(this,e,n).slice(),x=f.call(this,e,n).slice(),T=d3.scale.linear().domain(d3.extent(d3.merge([l,y]))).range(r?[p,0]:[0,p]),N=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(T.range());this.__chart__=T;var C=d3.min(y),k=d3.max(y),L=y[1],A=g.selectAll("g.nv-wrap.nv-bullet").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),M=O.append("g"),_=A.select("g");M.append("rect").attr("class","nv-range nv-rangeMax"),M.append("rect").attr("class","nv-range nv-rangeAvg"),M.append("rect").attr("class","nv-range nv-rangeMin"),M.append("rect").attr("class","nv-measure"),M.append("path").attr("class","nv-markerTriangle"),A.attr("transform","translate("+t.left+","+t.top+")");var D=function(e){return Math.abs(N(e)-N(0))},P=function(e){return Math.abs(T(e)-T(0))},H=function(e){return e<0?N(e):N(0)},B=function(e){return e<0?T(e):T(0)};_.select("rect.nv-rangeMax").attr("height",m).attr("width",P(k>0?k:C)).attr("x",B(k>0?k:C)).datum(k>0?k:C),_.select("rect.nv-rangeAvg").attr("height",m).attr("width",P(L)).attr("x",B(L)).datum(L),_.select("rect.nv-rangeMin").attr("height",m).attr("width",P(k)).attr("x",B(k)).attr("width",P(k>0?C:k)).attr("x",B(k>0?C:k)).datum(k>0?C:k),_.select("rect.nv-measure").style("fill",d).attr("height",m/3).attr("y",m/3).attr("width",w<0?T(0)-T(w[0]):T(w[0])-T(0)).attr("x",B(w)).on("mouseover",function(){v.elementMouseover({value:w[0],label:x[0]||"Current",pos:[T(w[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:w[0],label:x[0]||"Current"})});var j=m/6;b[0]?_.selectAll("path.nv-markerTriangle").attr("transform",function(e){return"translate("+T(b[0])+","+m/2+")"}).attr("d","M0,"+j+"L"+j+","+ -j+" "+ -j+","+ -j+"Z").on("mouseover",function(){v.elementMouseover({value:b[0],label:S[0]||"Previous",pos:[T(b[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:b[0],label:S[0]||"Previous"})}):_.selectAll("path.nv-markerTriangle").remove(),A.selectAll(".nv-range").on("mouseover",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseover({value:e,label:n,pos:[T(e),m/2]})}).on("mouseout",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseout({value:e,label:n})})}),m}var t={top:0,right:0,bottom:0,left:0},n="left",r=!1,i=function(e){return e.ranges},s=function(e){return e.markers},o=function(e){return e.measures},u=function(e){return e.rangeLabels?e.rangeLabels:[]},a=function(e){return e.markerLabels?e.markerLabels:[]},f=function(e){return e.measureLabels?e.measureLabels:[]},l=[0],c=380,h=30,p=null,d=e.utils.getColor(["#1f77b4"]),v=d3.dispatch("elementMouseover","elementMouseout");return m.dispatch=v,m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(i=e,m):i},m.markers=function(e){return arguments.length?(s=e,m):s},m.measures=function(e){return arguments.length?(o=e,m):o},m.forceX=function(e){return arguments.length?(l=e,m):l},m.width=function(e){return arguments.length?(c=e,m):c},m.height=function(e){return arguments.length?(h=e,m):h},m.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,m):t},m.tickFormat=function(e){return arguments.length?(p=e,m):p},m.color=function(t){return arguments.length?(d=e.utils.getColor(t),m):d},m},e.models.bulletChart=function(){function m(e){return e.each(function(n,h){var g=d3.select(this),y=(a||parseInt(g.style("width"))||960)-i.left-i.right,b=f-i.top-i.bottom,w=this;m.update=function(){m(e)},m.container=this;if(!n||!s.call(this,n,h)){var E=g.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+y/2).attr("y",18+i.top+b/2).text(function(e){return e}),m}g.selectAll(".nv-noData").remove();var S=s.call(this,n,h).slice().sort(d3.descending),x=o.call(this,n,h).slice().sort(d3.descending),T=u.call(this,n,h).slice().sort(d3.descending),N=g.selectAll("g.nv-wrap.nv-bulletChart").data([n]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-bulletWrap"),k.append("g").attr("class","nv-titles"),N.attr("transform","translate("+i.left+","+i.top+")");var A=d3.scale.linear().domain([0,Math.max(S[0],x[0],T[0])]).range(r?[y,0]:[0,y]),O=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(A.range());this.__chart__=A;var M=function(e){return Math.abs(O(e)-O(0))},_=function(e){return Math.abs(A(e)-A(0))},D=k.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(f-i.top-i.bottom)/2+")");D.append("text").attr("class","nv-title").text(function(e){return e.title}),D.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(e){return e.subtitle}),t.width(y).height(b);var P=L.select(".nv-bulletWrap");d3.transition(P).call(t);var H=l||A.tickFormat(y/100),B=L.selectAll("g.nv-tick").data(A.ticks(y/50),function(e){return this.textContent||H(e)}),j=B.enter().append("g").attr("class","nv-tick").attr("transform",function(e){return"translate("+O(e)+",0)"}).style("opacity",1e-6);j.append("line").attr("y1",b).attr("y2",b*7/6),j.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",b*7/6).text(H);var F=d3.transition(B).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1);F.select("line").attr("y1",b).attr("y2",b*7/6),F.select("text").attr("y",b*7/6),d3.transition(B.exit()).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1e-6).remove(),d.on("tooltipShow",function(e){e.key=n.title,c&&v(e,w.parentNode)})}),d3.timer.flush(),m}var t=e.models.bullet(),n="left",r=!1,i={top:5,right:40,bottom:20,left:120},s=function(e){return e.ranges},o=function(e){return e.markers},u=function(e){return e.measures},a=null,f=55,l=null,c=!0,h=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide"),v=function(t,n){var r=t.pos[0]+(n.offsetLeft||0)+i.left,s=t.pos[1]+(n.offsetTop||0)+i.top,o=h(t.key,t.label,t.value,t,m);e.tooltip.show([r,s],o,t.value<0?"e":"w",null,n)};return t.dispatch.on("elementMouseover.tooltip",function(e){d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),m.dispatch=d,m.bullet=t,d3.rebind(m,t,"color"),m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(s=e,m):s},m.markers=function(e){return arguments.length?(o=e,m):o},m.measures=function(e){return arguments.length?(u=e,m):u},m.width=function(e){return arguments.length?(a=e,m):a},m.height=function(e){return arguments.length?(f=e,m):f},m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.tickFormat=function(e){return arguments.length?(l=e,m):l},m.tooltips=function(e){return arguments.length?(c=e,m):c},m.tooltipContent=function(e){return arguments.length?(h=e,m):h},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.cumulativeLineChart=function(){function D(b){return b.each(function(b){function I(e,t){d3.select(D.container).style("cursor","ew-resize")}function q(e,t){M.x=d3.event.x,M.i=Math.round(O.invert(M.x)),nt()}function R(e,t){d3.select(D.container).style("cursor","auto"),x.index=M.i,k.stateChange(x)}function nt(){tt.data([M]);var e=D.transitionDuration();D.transitionDuration(0),D.update(),D.transitionDuration(e)}var L=d3.select(this).classed("nv-chart-"+S,!0),A=this,H=(f||parseInt(L.style("width"))||960)-u.left-u.right,B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom;D.update=function(){L.call(D)},D.container=this,x.disabled=b.map(function(e){return!!e.disabled});if(!T){var j;T={};for(j in x)x[j]instanceof Array?T[j]=x[j].slice(0):T[j]=x[j]}var F=d3.behavior.drag().on("dragstart",I).on("drag",q).on("dragend",R);if(!b||!b.length||!b.filter(function(e){return e.values.length}).length){var U=L.selectAll(".nv-noData").data([N]);return U.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),U.attr("x",u.left+H/2).attr("y",u.top+B/2).text(function(e){return e}),D}L.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();if(!y){var z=b.filter(function(e){return!e.disabled}).map(function(e,n){var r=d3.extent(e.values,t.y());return r[0]<-0.95&&(r[0]=-0.95),[(r[0]-r[1])/(1+r[1]),(r[1]-r[0])/(1+r[0])]}),W=[d3.min(z,function(e){return e[0]}),d3.max(z,function(e){return e[1]})];t.yDomain(W)}else t.yDomain(null);O.domain([0,b[0].values.length-1]).range([0,H]).clamp(!0);var b=P(M.i,b),X=g?"none":"all",V=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([b]),$=V.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),J=V.select("g");$.append("g").attr("class","nv-interactive"),$.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),$.append("g").attr("class","nv-y nv-axis"),$.append("g").attr("class","nv-background"),$.append("g").attr("class","nv-linesWrap").style("pointer-events",X),$.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),$.append("g").attr("class","nv-legendWrap"),$.append("g").attr("class","nv-controlsWrap"),c&&(i.width(H),J.select(".nv-legendWrap").datum(b).call(i),u.top!=i.height()&&(u.top=i.height(),B=(l||parseInt(L.style("height"))||400)-u.top-u.bottom),J.select(".nv-legendWrap").attr("transform","translate(0,"+ -u.top+")"));if(m){var K=[{key:"Re-scale y-axis",disabled:!y}];s.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),J.select(".nv-controlsWrap").datum(K).attr("transform","translate(0,"+ -u.top+")").call(s)}V.attr("transform","translate("+u.left+","+u.top+")"),d&&J.select(".nv-y.nv-axis").attr("transform","translate("+H+",0)");var Q=b.filter(function(e){return e.tempDisabled});V.select(".tempDisabled").remove(),Q.length&&V.append("text").attr("class","tempDisabled").attr("x",H/2).attr("y","-.71em").style("text-anchor","end").text(Q.map(function(e){return e.key}).join(", ")+" values cannot be calculated for this time period."),g&&(o.width(H).height(B).margin({left:u.left,top:u.top}).svgContainer(L).xScale(w),V.select(".nv-interactive").call(o)),$.select(".nv-background").append("rect"),J.select(".nv-background rect").attr("width",H).attr("height",B),t.y(function(e){return e.display.y}).width(H).height(B).color(b.map(function(e,t){return e.color||a(e,t)}).filter(function(e,t){return!b[t].disabled&&!b[t].tempDisabled}));var G=J.select(".nv-linesWrap").datum(b.filter(function(e){return!e.disabled&&!e.tempDisabled}));G.call(t),b.forEach(function(e,t){e.seriesIndex=t});var Y=b.filter(function(e){return!e.disabled&&!!C(e)}),Z=J.select(".nv-avgLinesWrap").selectAll("line").data(Y,function(e){return e.key}),et=function(e){var t=E(C(e));return t<0?0:t>B?B:t};Z.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(e,n){return t.color()(e,e.seriesIndex)}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.style("stroke-opacity",function(e){var t=E(C(e));return t<0||t>B?0:1}).attr("x1",0).attr("x2",H).attr("y1",et).attr("y2",et),Z.exit().remove();var tt=G.selectAll(".nv-indexLine").data([M]);tt.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(F),tt.attr("transform",function(e){return"translate("+O(e.i)+",0)"}).attr("height",B),h&&(n.scale(w).ticks(Math.min(b[0].values.length,H/70)).tickSize(-B,0),J.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),d3.transition(J.select(".nv-x.nv-axis")).call(n)),p&&(r.scale(E).ticks(B/36).tickSize(-H,0),d3.transition(J.select(".nv-y.nv-axis")).call(r)),J.select(".nv-background rect").on("click",function(){M.x=d3.mouse(this)[0],M.i=Math.round(O.invert(M.x)),x.index=M.i,k.stateChange(x),nt()}),t.dispatch.on("elementClick",function(e){M.i=e.pointIndex,M.x=O(M.i),x.index=M.i,k.stateChange(x),nt()}),s.dispatch.on("legendClick",function(e,t){e.disabled=!e.disabled,y=!e.disabled,x.rescaleY=y,k.stateChange(x),D.update()}),i.dispatch.on("stateChange",function(e){x.disabled=e.disabled,k.stateChange(x),D.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,f,l,c=[];b.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,D.x()),t.highlightPoint(r,f,!0);var o=n.values[f];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof l=="undefined"&&(l=D.xScale()(D.x()(o,f))),c.push({key:n.key,value:D.y()(o,f),color:a(n,n.seriesIndex)})});if(c.length>2){var h=D.yScale().invert(i.mouseY),p=Math.abs(D.yScale().domain()[0]-D.yScale().domain()[1]),d=.03*p,m=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);m!==null&&(c[m].highlight=!0)}var g=n.tickFormat()(D.x()(s,f),f);o.tooltip.position({left:l+u.left,top:i.mouseY+u.top}).chartContainer(A.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:g,series:c})(),o.renderGuideLine(l)}),o.dispatch.on("elementMouseout",function(e){k.tooltipHide(),t.clearHighlights()}),k.on("tooltipShow",function(e){v&&_(e,A.parentNode)}),k.on("changeState",function(e){typeof e.disabled!="undefined"&&(b.forEach(function(t,n){t.disabled=e.disabled[n]}),x.disabled=e.disabled),typeof e.index!="undefined"&&(M.i=e.index,M.x=O(M.i),x.index=e.index,tt.data([M])),typeof e.rescaleY!="undefined"&&(y=e.rescaleY),D.update()})}),D}function P(e,n){return n.map(function(n,r){if(!n.values)return n;var i=n.values[e];if(i==null)return n;var s=t.y()(i,e);return s<-0.95&&!A?(n.tempDisabled=!0,n):(n.tempDisabled=!1,n.values=n.values.map(function(e,n){return e.display={y:(t.y()(e,n)-s)/(1+s)},e}),n)})}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:30,bottom:50,left:60},a=e.utils.defaultColor(),f=null,l=null,c=!0,h=!0,p=!0,d=!1,v=!0,m=!0,g=!1,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},w,E,S=t.id(),x={index:0,rescaleY:y},T=null,N="No Data Available.",C=function(e){return e.average},k=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),L=0,A=!1;n.orient("bottom").tickPadding(7),r.orient(d?"right":"left"),s.updateState(!1);var O=d3.scale.linear(),M={i:0,x:0},_=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,D);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],k.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){k.tooltipHide(e)}),k.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),D.dispatch=k,D.lines=t,D.legend=i,D.xAxis=n,D.yAxis=r,D.interactiveLayer=o,d3.rebind(D,t,"defined","isArea","x","y","xScale","yScale","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id"),D.options=e.utils.optionsFunc.bind(D),D.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,D):u},D.width=function(e){return arguments.length?(f=e,D):f},D.height=function(e){return arguments.length?(l=e,D):l},D.color=function(t){return arguments.length?(a=e.utils.getColor(t),i.color(a),D):a},D.rescaleY=function(e){return arguments.length?(y=e,D):y},D.showControls=function(e){return arguments.length?(m=e,D):m},D.useInteractiveGuideline=function(e){return arguments.length?(g=e,e===!0&&(D.interactive(!1),D.useVoronoi(!1)),D):g},D.showLegend=function(e){return arguments.length?(c=e,D):c},D.showXAxis=function(e){return arguments.length?(h=e,D):h},D.showYAxis=function(e){return arguments.length?(p=e,D):p},D.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),D):d},D.tooltips=function(e){return arguments.length?(v=e,D):v},D.tooltipContent=function(e){return arguments.length?(b=e,D):b},D.state=function(e){return arguments.length?(x=e,D):x},D.defaultState=function(e){return arguments.length?(T=e,D):T},D.noData=function(e){return arguments.length?(N=e,D):N},D.average=function(e){return arguments.length?(C=e,D):C},D.transitionDuration=function(e){return arguments.length?(L=e,D):L},D.noErrorCheck=function(e){return arguments.length?(A=e,D):A},D},e.models.discreteBar=function(){function E(e){return e.each(function(e){var i=n-t.left-t.right,E=r-t.top-t.bottom,S=d3.select(this);e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var T=p&&d?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0}})});s.domain(p||d3.merge(T).map(function(e){return e.x})).rangeBands(v||[0,i],.1),o.domain(d||d3.extent(d3.merge(T).map(function(e){return e.y}).concat(f))),c?o.range(m||[E-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(m||[E,0]),b=b||s,w=w||o.copy().range([o(0),o(0)]);var N=S.selectAll("g.nv-wrap.nv-discretebar").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-groups"),N.attr("transform","translate("+t.left+","+t.top+")");var A=N.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),A.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),A.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),A.style("stroke-opacity",1).style("fill-opacity",.75);var O=A.selectAll("g.nv-bar").data(function(e){return e.values});O.exit().remove();var M=O.enter().append("g").attr("transform",function(e,t,n){return"translate("+(s(u(e,t))+s.rangeBand()*.05)+", "+o(0)+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),g.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),g.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){g.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){g.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()});M.append("rect").attr("height",0).attr("width",s.rangeBand()*.9/e.length),c?(M.append("text").attr("text-anchor","middle"),O.select("text").text(function(e,t){return h(a(e,t))}).attr("x",s.rangeBand()*.9/2).attr("y",function(e,t){return a(e,t)<0?o(a(e,t))-o(0)+12:-4})):O.selectAll("text").remove(),O.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(e,t){return e.color||l(e,t)}).style("stroke",function(e,t){return e.color||l(e,t)}).select("rect").attr("class",y).attr("width",s.rangeBand()*.9/e.length),O.attr("transform",function(e,t){var n=s(u(e,t))+s.rangeBand()*.05,r=a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t));return"translate("+n+", "+r+")"}).select("rect").attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(d&&d[0]||0))||1)}),b=s.copy(),w=o.copy()}),E}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=!1,h=d3.format(",.2f"),p,d,v,m,g=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),y="discreteBar",b,w;return E.dispatch=g,E.options=e.utils.optionsFunc.bind(E),E.x=function(e){return arguments.length?(u=e,E):u},E.y=function(e){return arguments.length?(a=e,E):a},E.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.xScale=function(e){return arguments.length?(s=e,E):s},E.yScale=function(e){return arguments.length?(o=e,E):o},E.xDomain=function(e){return arguments.length?(p=e,E):p},E.yDomain=function(e){return arguments.length?(d=e,E):d},E.xRange=function(e){return arguments.length?(v=e,E):v},E.yRange=function(e){return arguments.length?(m=e,E):m},E.forceY=function(e){return arguments.length?(f=e,E):f},E.color=function(t){return arguments.length?(l=e.utils.getColor(t),E):l},E.id=function(e){return arguments.length?(i=e,E):i},E.showValues=function(e){return arguments.length?(c=e,E):c},E.valueFormat=function(e){return arguments.length?(h=e,E):h},E.rectClass=function(e){return arguments.length?(y=e,E):y},E},e.models.discreteBarChart=function(){function w(e){return e.each(function(e){var u=d3.select(this),p=this,y=(s||parseInt(u.style("width"))||960)-i.left-i.right,E=(o||parseInt(u.style("height"))||400)-i.top-i.bottom;w.update=function(){g.beforeUpdate(),u.call(w)},w.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var S=u.selectAll(".nv-noData").data([m]);return S.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),S.attr("x",i.left+y/2).attr("y",i.top+E/2).text(function(e){return e}),w}u.selectAll(".nv-noData").remove(),d=t.xScale(),v=t.yScale().clamp(!0);var T=u.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),C=N.append("defs"),k=T.select("g");N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),N.append("g").attr("class","nv-barsWrap"),k.attr("transform","translate("+i.left+","+i.top+")"),l&&k.select(".nv-y.nv-axis").attr("transform","translate("+y+",0)"),t.width(y).height(E);var L=k.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));L.call(t),C.append("clipPath").attr("id","nv-x-label-clip-"+t.id()).append("rect"),k.select("#nv-x-label-clip-"+t.id()+" rect").attr("width",d.rangeBand()*(c?2:1)).attr("height",16).attr("x",-d.rangeBand()/(c?1:2));if(a){n.scale(d).ticks(y/100).tickSize(-E,0),k.select(".nv-x.nv-axis").attr("transform","translate(0,"+(v.range()[0]+(t.showValues()&&v.domain()[0]<0?16:0))+")"),k.select(".nv-x.nv-axis").call(n);var A=k.select(".nv-x.nv-axis").selectAll("g");c&&A.selectAll("text").attr("transform",function(e,t,n){return"translate(0,"+(n%2==0?"5":"17")+")"})}f&&(r.scale(v).ticks(E/36).tickSize(-y,0),k.select(".nv-y.nv-axis").call(r)),k.select(".nv-zeroLine line").attr("x1",0).attr("x2",y).attr("y1",v(0)).attr("y2",v(0)),g.on("tooltipShow",function(e){h&&b(e,p.parentNode)})}),w}var t=e.models.discreteBar(),n=e.models.axis(),r=e.models.axis(),i={top:15,right:10,bottom:50,left:60},s=null,o=null,u=e.utils.getColor(),a=!0,f=!0,l=!1,c=!1,h=!0,p=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},d,v,m="No Data Available.",g=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate"),y=0;n.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(l?"right":"left").tickFormat(d3.format(",.1f"));var b=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=p(i.series.key,a,f,i,w);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+i.left,e.pos[1]+i.top],g.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){g.tooltipHide(e)}),g.on("tooltipHide",function(){h&&e.tooltip.cleanup()}),w.dispatch=g,w.discretebar=t,w.xAxis=n,w.yAxis=r,d3.rebind(w,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","id","showValues","valueFormat"),w.options=e.utils.optionsFunc.bind(w),w.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,w):i},w.width=function(e){return arguments.length?(s=e,w):s},w.height=function(e){return arguments.length?(o=e,w):o},w.color=function(n){return arguments.length?(u=e.utils.getColor(n),t.color(u),w):u},w.showXAxis=function(e){return arguments.length?(a=e,w):a},w.showYAxis=function(e){return arguments.length?(f=e,w):f},w.rightAlignYAxis=function(e){return arguments.length?(l=e,r.orient(e?"right":"left"),w):l},w.staggerLabels=function(e){return arguments.length?(c=e,w):c},w.tooltips=function(e){return arguments.length?(h=e,w):h},w.tooltipContent=function(e){return arguments.length?(p=e,w):p},w.noData=function(e){return arguments.length?(m=e,w):m},w.transitionDuration=function(e){return arguments.length?(y=e,w):y},w},e.models.distribution=function(){function l(e){return e.each(function(e){var a=n-(i==="x"?t.left+t.right:t.top+t.bottom),l=i=="x"?"y":"x",c=d3.select(this);f=f||u;var h=c.selectAll("g.nv-distribution").data([e]),p=h.enter().append("g").attr("class","nvd3 nv-distribution"),d=p.append("g"),v=h.select("g");h.attr("transform","translate("+t.left+","+t.top+")");var m=v.selectAll("g.nv-dist").data(function(e){return e},function(e){return e.key});m.enter().append("g"),m.attr("class",function(e,t){return"nv-dist nv-series-"+t}).style("stroke",function(e,t){return o(e,t)});var g=m.selectAll("line.nv-dist"+i).data(function(e){return e.values});g.enter().append("line").attr(i+"1",function(e,t){return f(s(e,t))}).attr(i+"2",function(e,t){return f(s(e,t))}),m.exit().selectAll("line.nv-dist"+i).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}).style("stroke-opacity",0).remove(),g.attr("class",function(e,t){return"nv-dist"+i+" nv-dist"+i+"-"+t}).attr(l+"1",0).attr(l+"2",r),g.attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}),f=u.copy()}),l}var t={top:0,right:0,bottom:0,left:0},n=400,r=8,i="x",s=function(e){return e[i]},o=e.utils.defaultColor(),u=d3.scale.linear(),a,f;return l.options=e.utils.optionsFunc.bind(l),l.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,l):t},l.width=function(e){return arguments.length?(n=e,l):n},l.axis=function(e){return arguments.length?(i=e,l):i},l.size=function(e){return arguments.length?(r=e,l):r},l.getData=function(e){return arguments.length?(s=d3.functor(e),l):s},l.scale=function(e){return arguments.length?(u=e,l):u},l.color=function(t){return arguments.length?(o=e.utils.getColor(t),l):o},l},e.models.historicalBarChart=function(){function x(e){return e.each(function(d){var E=d3.select(this),T=this,N=(u||parseInt(E.style("width"))||960)-s.left-s.right,C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom;x.update=function(){E.call(x)},x.container=this,g.disabled=d.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!d||!d.length||!d.filter(function(e){return e.values.length}).length){var L=E.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",s.left+N/2).attr("y",s.top+C/2).text(function(e){return e}),x}E.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();var A=E.selectAll("g.nv-wrap.nv-historicalBarChart").data([d]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),M=A.select("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-barsWrap"),O.append("g").attr("class","nv-legendWrap"),f&&(i.width(N),M.select(".nv-legendWrap").datum(d).call(i),s.top!=i.height()&&(s.top=i.height(),C=(a||parseInt(E.style("height"))||400)-s.top-s.bottom),A.select(".nv-legendWrap").attr("transform","translate(0,"+ -s.top+")")),A.attr("transform","translate("+s.left+","+s.top+")"),h&&M.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)"),t.width(N).height(C).color(d.map(function(e,t){return e.color||o(e,t)}).filter(function(e,t){return!d[t].disabled}));var _=M.select(".nv-barsWrap").datum(d.filter(function(e){return!e.disabled}));_.call(t),l&&(n.scale(v).tickSize(-C,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+m.range()[0]+")"),M.select(".nv-x.nv-axis").call(n)),c&&(r.scale(m).ticks(C/36).tickSize(-N,0),M.select(".nv-y.nv-axis").call(r)),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,d.filter(function(e){return!e.disabled}).length||d.map(function(e){return e.disabled=!1,A.selectAll(".nv-series").classed("disabled",!1),e}),g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),e.call(x)}),i.dispatch.on("legendDblclick",function(e){d.forEach(function(e){e.disabled=!0}),e.disabled=!1,g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),x.update()}),w.on("tooltipShow",function(e){p&&S(e,T.parentNode)}),w.on("changeState",function(e){typeof e.disabled!="undefined"&&(d.forEach(function(t,n){t.disabled=e.disabled[n]}),g.disabled=e.disabled),x.update()})}),x}var t=e.models.historicalBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s={top:30,right:90,bottom:50,left:90},o=e.utils.defaultColor(),u=null,a=null,f=!1,l=!0,c=!0,h=!1,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},v,m,g={},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=0;n.orient("bottom").tickPadding(7),r.orient(h?"right":"left");var S=function(i,s){if(s){var o=d3.select(s).select("svg"),u=o.node()?o.attr("viewBox"):null;if(u){u=u.split(" ");var a=parseInt(o.style("width"))/u[2];i.pos[0]=i.pos[0]*a,i.pos[1]=i.pos[1]*a}}var f=i.pos[0]+(s.offsetLeft||0),l=i.pos[1]+(s.offsetTop||0),c=n.tickFormat()(t.x()(i.point,i.pointIndex)),h=r.tickFormat()(t.y()(i.point,i.pointIndex)),p=d(i.series.key,c,h,i,x);e.tooltip.show([f,l],p,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+s.left,e.pos[1]+s.top],w.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){p&&e.tooltip.cleanup()}),x.dispatch=w,x.bars=t,x.legend=i,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate","highlightPoint","clearHighlights","interactive"),x.options=e.utils.optionsFunc.bind(x),x.margin=function(e){return arguments.length?(s.top=typeof e.top!="undefined"?e.top:s.top,s.right=typeof e.right!="undefined"?e.right:s.right,s.bottom=typeof e.bottom!="undefined"?e.bottom:s.bottom,s.left=typeof e.left!="undefined"?e.left:s.left,x):s},x.width=function(e){return arguments.length?(u=e,x):u},x.height=function(e){return arguments.length?(a=e,x):a},x.color=function(t){return arguments.length?(o=e.utils.getColor(t),i.color(o),x):o},x.showLegend=function(e){return arguments.length?(f=e,x):f},x.showXAxis=function(e){return arguments.length?(l=e,x):l},x.showYAxis=function(e){return arguments.length?(c=e,x):c},x.rightAlignYAxis=function(e){return arguments.length?(h=e,r.orient(e?"right":"left"),x):h},x.tooltips=function(e){return arguments.length?(p=e,x):p},x.tooltipContent=function(e){return arguments.length?(d=e,x):d},x.state=function(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments.length?(b=e,x):b},x.transitionDuration=function(e){return arguments.length?(E=e,x):E},x},e.models.indentedTree=function(){function g(e){return e.each(function(e){function k(e,t,n){d3.event.stopPropagation();if(d3.event.shiftKey&&!n)return d3.event.shiftKey=!1,e.values&&e.values.forEach(function(e){(e.values||e._values)&&k(e,0,!0)}),!0;if(!O(e))return!0;e.values?(e._values=e.values,e.values=null):(e.values=e._values,e._values=null),g.update()}function L(e){return e._values&&e._values.length?h:e.values&&e.values.length?p:""}function A(e){return e._values&&e._values.length}function O(e){var t=e.values||e._values;return t&&t.length}var t=1,n=d3.select(this),i=d3.layout.tree().children(function(e){return e.values}).size([r,f]);g.update=function(){n.call(g)},e[0]||(e[0]={key:a});var s=i.nodes(e[0]),y=d3.select(this).selectAll("div").data([[s]]),b=y.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),w=b.append("table"),E=y.select("table").attr("width","100%").attr("class",c);if(o){var S=w.append("thead"),x=S.append("tr");l.forEach(function(e){x.append("th").attr("width",e.width?e.width:"10%").style("text-align",e.type=="numeric"?"right":"left").append("span").text(e.label)})}var T=E.selectAll("tbody").data(function(e){return e});T.enter().append("tbody"),t=d3.max(s,function(e){return e.depth}),i.size([r,t*f]);var N=T.selectAll("tr").data(function(e){return e.filter(function(e){return u&&!e.children?u(e):!0})},function(e,t){return e.id||e.id||++m});N.exit().remove(),N.select("img.nv-treeicon").attr("src",L).classed("folded",A);var C=N.enter().append("tr");l.forEach(function(e,t){var n=C.append("td").style("padding-left",function(e){return(t?0:e.depth*f+12+(L(e)?0:16))+"px"},"important").style("text-align",e.type=="numeric"?"right":"left");t==0&&n.append("img").classed("nv-treeicon",!0).classed("nv-folded",A).attr("src",L).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(e){return L(e)?"inline-block":"none"}).on("click",k),n.each(function(n){!t&&v(n)?d3.select(this).append("a").attr("href",v).attr("class",d3.functor(e.classes)).append("span"):d3.select(this).append("span"),d3.select(this).select("span").attr("class",d3.functor(e.classes)).text(function(t){return e.format?t[e.key]?e.format(t[e.key]):"-":t[e.key]||"-"})}),e.showCount&&(n.append("span").attr("class","nv-childrenCount"),N.selectAll("span.nv-childrenCount").text(function(e){return e.values&&e.values.length||e._values&&e._values.length?"("+(e.values&&e.values.filter(function(e){return u?u(e):!0}).length||e._values&&e._values.filter(function(e){return u?u(e):!0}).length||0)+")":""}))}),N.order().on("click",function(e){d.elementClick({row:this,data:e,pos:[e.x,e.y]})}).on("dblclick",function(e){d.elementDblclick({row:this,data:e,pos:[e.x,e.y]})}).on("mouseover",function(e){d.elementMouseover({row:this,data:e,pos:[e.x,e.y]})}).on("mouseout",function(e){d.elementMouseout({row:this,data:e,pos:[e.x,e.y]})})}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e4),o=!0,u=!1,a="No Data Available.",f=20,l=[{key:"key",label:"Name",type:"text"}],c=null,h="images/grey-plus.png",p="images/grey-minus.png",d=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),v=function(e){return e.url},m=0;return g.options=e.utils.optionsFunc.bind(g),g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),scatter.color(i),g):i},g.id=function(e){return arguments.length?(s=e,g):s},g.header=function(e){return arguments.length?(o=e,g):o},g.noData=function(e){return arguments.length?(a=e,g):a},g.filterZero=function(e){return arguments.length?(u=e,g):u},g.columns=function(e){return arguments.length?(l=e,g):l},g.tableClass=function(e){return arguments.length?(c=e,g):c},g.iconOpen=function(e){return arguments.length?(h=e,g):h},g.iconClose=function(e){return arguments.length?(p=e,g):p},g.getUrl=function(e){return arguments.length?(v=e,g):v},g},e.models.legend=function(){function c(h){return h.each(function(c){var h=n-t.left-t.right,p=d3.select(this),d=p.selectAll("g.nv-legend").data([c]),v=d.enter().append("g").attr("class","nvd3 nv-legend").append("g"),m=d.select("g");d.attr("transform","translate("+t.left+","+t.top+")");var g=m.selectAll(".nv-series").data(function(e){return e}),y=g.enter().append("g").attr("class","nv-series").on("mouseover",function(e,t){l.legendMouseover(e,t)}).on("mouseout",function(e,t){l.legendMouseout(e,t)}).on("click",function(e,t){l.legendClick(e,t),a&&(f?(c.forEach(function(e){e.disabled=!0}),e.disabled=!1):(e.disabled=!e.disabled,c.every(function(e){return e.disabled})&&c.forEach(function(e){e.disabled=!1})),l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))}).on("dblclick",function(e,t){l.legendDblclick(e,t),a&&(c.forEach(function(e){e.disabled=!0}),e.disabled=!1,l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))});y.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),y.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8"),g.classed("disabled",function(e){return e.disabled}),g.exit().remove(),g.select("circle").style("fill",function(e,t){return e.color||s(e,t)}).style("stroke",function(e,t){return e.color||s(e,t)}),g.select("text").text(i);if(o){var b=[];g.each(function(t,n){var r=d3.select(this).select("text"),i;try{i=r.getComputedTextLength();if(i<=0)throw Error()}catch(s){i=e.utils.calcApproxTextWidth(r)}b.push(i+28)});var w=0,E=0,S=[];while(E<h&&w<b.length)S[w]=b[w],E+=b[w++];w===0&&(w=1);while(E>h&&w>1){S=[],w--;for(var x=0;x<b.length;x++)b[x]>(S[x%w]||0)&&(S[x%w]=b[x]);E=S.reduce(function(e,t,n,r){return e+t})}var T=[];for(var N=0,C=0;N<w;N++)T[N]=C,C+=S[N];g.attr("transform",function(e,t){return"translate("+T[t%w]+","+(5+Math.floor(t/w)*20)+")"}),u?m.attr("transform","translate("+(n-t.right-E)+","+t.top+")"):m.attr("transform","translate(0,"+t.top+")"),r=t.top+t.bottom+Math.ceil(b.length/w)*20}else{var k=5,L=5,A=0,O;g.attr("transform",function(e,r){var i=d3.select(this).select("text").node().getComputedTextLength()+28;return O=L,n<t.left+t.right+O+i&&(L=O=5,k+=20),L+=i,L>A&&(A=L),"translate("+O+","+k+")"}),m.attr("transform","translate("+(n-t.right-A)+","+t.top+")"),r=t.top+t.bottom+k+15}}),c}var t={top:5,right:0,bottom:5,left:0},n=400,r=20,i=function(e){return e.key},s=e.utils.defaultColor(),o=!0,u=!0,a=!0,f=!1,l=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange");return c.dispatch=l,c.options=e.utils.optionsFunc.bind(c),c.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,c):t},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.key=function(e){return arguments.length?(i=e,c):i},c.color=function(t){return arguments.length?(s=e.utils.getColor(t),c):s},c.align=function(e){return arguments.length?(o=e,c):o},c.rightAlign=function(e){return arguments.length?(u=e,c):u},c.updateState=function(e){return arguments.length?(a=e,c):a},c.radioButtonMode=function(e){return arguments.length?(f=e,c):f},c},e.models.line=function(){function m(g){return g.each(function(m){var g=r-n.left-n.right,b=i-n.top-n.bottom,w=d3.select(this);c=t.xScale(),h=t.yScale(),d=d||c,v=v||h;var E=w.selectAll("g.nv-wrap.nv-line").data([m]),S=E.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),T=S.append("defs"),N=S.append("g"),C=E.select("g");N.append("g").attr("class","nv-groups"),N.append("g").attr("class","nv-scatterWrap"),E.attr("transform","translate("+n.left+","+n.top+")"),t.width(g).height(b);var k=E.select(".nv-scatterWrap");k.call(t),T.append("clipPath").attr("id","nv-edge-clip-"+t.id()).append("rect"),E.select("#nv-edge-clip-"+t.id()+" rect").attr("width",g).attr("height",b>0?b:0),C.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":""),k.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":"");var L=E.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});L.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),L.exit().remove(),L.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return s(e,t)}).style("stroke",function(e,t){return s(e,t)}),L.style("stroke-opacity",1).style("fill-opacity",.5);var A=L.selectAll("path.nv-area").data(function(e){return f(e)?[e]:[]});A.enter().append("path").attr("class","nv-area").attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])}),L.exit().selectAll("path.nv-area").remove(),A.attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))}).y1(function(e,t){return h(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])});var O=L.selectAll("path.nv-line").data(function(e){return[e.values]});O.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))})),O.attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))})),d=c.copy(),v=h.copy()}),m}var t=e.models.scatter(),n={top:0,right:0,bottom:0,left:0},r=960,i=500,s=e.utils.defaultColor(),o=function(e){return e.x},u=function(e){return e.y},a=function(e,t){return!isNaN(u(e,t))&&u(e,t)!==null},f=function(e){return e.area},l=!1,c,h,p="linear";t.size(16).sizeDomain([16,256]);var d,v;return m.dispatch=t.dispatch,m.scatter=t,d3.rebind(m,t,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","padData","highlightPoint","clearHighlights"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.height=function(e){return arguments.length?(i=e,m):i},m.x=function(e){return arguments.length?(o=e,t.x(e),m):o},m.y=function(e){return arguments.length?(u=e,t.y(e),m):u},m.clipEdge=function(e){return arguments.length?(l=e,m):l},m.color=function(n){return arguments.length?(s=e.utils.getColor(n),t.color(s),m):s},m.interpolate=function(e){return arguments.length?(p=e,m):p},m.defined=function(e){return arguments.length?(a=e,m):a},m.isArea=function(e){return arguments.length?(f=d3.functor(e),m):f},m},e.models.lineChart=function(){function N(m){return m.each(function(m){var x=d3.select(this),C=this,k=(a||parseInt(x.style("width"))||960)-o.left-o.right,L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom;N.update=function(){x.call(N)},N.container=this,b.disabled=m.map(function(e){return!!e.disabled});if(!w){var A;w={};for(A in b)b[A]instanceof Array?w[A]=b[A].slice(0):w[A]=b[A]}if(!m||!m.length||!m.filter(function(e){return e.values.length}).length){var O=x.selectAll(".nv-noData").data([E]);return O.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),O.attr("x",o.left+k/2).attr("y",o.top+L/2).text(function(e){return e}),N}x.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var M=x.selectAll("g.nv-wrap.nv-lineChart").data([m]),_=M.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),D=M.select("g");_.append("rect").style("opacity",0),_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y nv-axis"),_.append("g").attr("class","nv-linesWrap"),_.append("g").attr("class","nv-legendWrap"),_.append("g").attr("class","nv-interactive"),D.select("rect").attr("width",k).attr("height",L>0?L:0),l&&(i.width(k),D.select(".nv-legendWrap").datum(m).call(i),o.top!=i.height()&&(o.top=i.height(),L=(f||parseInt(x.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate(0,"+ -o.top+")")),M.attr("transform","translate("+o.left+","+o.top+")"),p&&D.select(".nv-y.nv-axis").attr("transform","translate("+k+",0)"),d&&(s.width(k).height(L).margin({left:o.left,top:o.top}).svgContainer(x).xScale(g),M.select(".nv-interactive").call(s)),t.width(k).height(L).color(m.map(function(e,t){return e.color||u(e,t)}).filter(function(e,t){return!m[t].disabled}));var P=D.select(".nv-linesWrap").datum(m.filter(function(e){return!e.disabled}));P.call(t),c&&(n.scale(g).ticks(k/100).tickSize(-L,0),D.select(".nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),D.select(".nv-x.nv-axis").call(n)),h&&(r.scale(y).ticks(L/36).tickSize(-k,0),D.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),N.update()}),s.dispatch.on("elementMousemove",function(i){t.clearHighlights();var a,f,l,c=[];m.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,N.x()),t.highlightPoint(r,f,!0);var s=n.values[f];if(typeof s=="undefined")return;typeof a=="undefined"&&(a=s),typeof l=="undefined"&&(l=N.xScale()(N.x()(s,f))),c.push({key:n.key,value:N.y()(s,f),color:u(n,n.seriesIndex)})});if(c.length>2){var h=N.yScale().invert(i.mouseY),p=Math.abs(N.yScale().domain()[0]-N.yScale().domain()[1]),d=.03*p,g=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);g!==null&&(c[g].highlight=!0)}var y=n.tickFormat()(N.x()(a,f));s.tooltip.position({left:l+o.left,top:i.mouseY+o.top}).chartContainer(C.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:y,series:c})(),s.renderGuideLine(l)}),s.dispatch.on("elementMouseout",function(e){S.tooltipHide(),t.clearHighlights()}),S.on("tooltipShow",function(e){v&&T(e,C.parentNode)}),S.on("changeState",function(e){typeof e.disabled!="undefined"&&m.length===e.disabled.length&&(m.forEach(function(t,n){t.disabled=e.disabled[n]}),b.disabled=e.disabled),N.update()})}),N}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.interactiveGuideline(),o={top:30,right:20,bottom:50,left:60},u=e.utils.defaultColor(),a=null,f=null,l=!0,c=!0,h=!0,p=!1,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=0;n.orient("bottom").tickPadding(7),r.orient(p?"right":"left");var T=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,N);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),N.dispatch=S,N.lines=t,N.legend=i,N.xAxis=n,N.yAxis=r,N.interactiveLayer=s,d3.rebind(N,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id","interpolate"),N.options=e.utils.optionsFunc.bind(N),N.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,N):o},N.width=function(e){return arguments.length?(a=e,N):a},N.height=function(e){return arguments.length?(f=e,N):f},N.color=function(t){return arguments.length?(u=e.utils.getColor(t),i.color(u),N):u},N.showLegend=function(e){return arguments.length?(l=e,N):l},N.showXAxis=function(e){return arguments.length?(c=e,N):c},N.showYAxis=function(e){return arguments.length?(h=e,N):h},N.rightAlignYAxis=function(e){return arguments.length?(p=e,r.orient(e?"right":"left"),N):p},N.useInteractiveGuideline=function(e){return arguments.length?(d=e,e===!0&&(N.interactive(!1),N.useVoronoi(!1)),N):d},N.tooltips=function(e){return arguments.length?(v=e,N):v},N.tooltipContent=function(e){return arguments.length?(m=e,N):m},N.state=function(e){return arguments.length?(b=e,N):b},N.defaultState=function(e){return arguments.length?(w=e,N):w},N.noData=function(e){return arguments.length?(E=e,N):E},N.transitionDuration=function(e){return arguments.length?(x=e,N):x},N},e.models.linePlusBarChart=function(){function T(e){return e.each(function(e){var l=d3.select(this),c=this,v=(a||parseInt(l.style("width"))||960)-u.left-u.right,N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom;T.update=function(){l.call(T)},b.disabled=e.map(function(e){return!!e.disabled});if(!w){var C;w={};for(C in b)b[C]instanceof Array?w[C]=b[C].slice(0):w[C]=b[C]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var k=l.selectAll(".nv-noData").data([E]);return k.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),k.attr("x",u.left+v/2).attr("y",u.top+N/2).text(function(e){return e}),T}l.selectAll(".nv-noData").remove();var L=e.filter(function(e){return!e.disabled&&e.bar}),A=e.filter(function(e){return!e.bar});m=A.filter(function(e){return!e.disabled}).length&&A.filter(function(e){return!e.disabled})[0].values.length?t.xScale():n.xScale(),g=n.yScale(),y=t.yScale();var O=d3.select(this).selectAll("g.nv-wrap.nv-linePlusBar").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y1 nv-axis"),M.append("g").attr("class","nv-y2 nv-axis"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-linesWrap"),M.append("g").attr("class","nv-legendWrap"),p&&(o.width(v/2),_.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(o),u.top!=o.height()&&(u.top=o.height(),N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom),_.select(".nv-legendWrap").attr("transform","translate("+v/2+","+ -u.top+")")),O.attr("transform","translate("+u.left+","+u.top+")"),t.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar})),n.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar}));var D=_.select(".nv-barsWrap").datum(L.length?L:[{values:[]}]),P=_.select(".nv-linesWrap").datum(A[0]&&!A[0].disabled?A:[{values:[]}]);d3.transition(D).call(n),d3.transition(P).call(t),r.scale(m).ticks(v/100).tickSize(-N,0),_.select(".nv-x.nv-axis").attr("transform","translate(0,"+g.range()[0]+")"),d3.transition(_.select(".nv-x.nv-axis")).call(r),i.scale(g).ticks(N/36).tickSize(-v,0),d3.transition(_.select(".nv-y1.nv-axis")).style("opacity",L.length?1:0).call(i),s.scale(y).ticks(N/36).tickSize(L.length?0:-v,0),_.select(".nv-y2.nv-axis").style("opacity",A.length?1:0).attr("transform","translate("+v+",0)"),d3.transition(_.select(".nv-y2.nv-axis")).call(s),o.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),T.update()}),S.on("tooltipShow",function(e){d&&x(e,c.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),b.disabled=t.disabled),T.update()})}),T}var t=e.models.line(),n=e.models.historicalBar(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.legend(),u={top:30,right:60,bottom:50,left:60},a=null,f=null,l=function(e){return e.x},c=function(e){return e.y},h=e.utils.defaultColor(),p=!0,d=!0,v=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},m,g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.padData(!0),t.clipEdge(!1).padData(!0),r.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),s.orient("right");var x=function(n,o){var u=n.pos[0]+(o.offsetLeft||0),a=n.pos[1]+(o.offsetTop||0),f=r.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?i:s).tickFormat()(t.y()(n.point,n.pointIndex)),c=v(n.series.key,f,l,n,T);e.tooltip.show([u,a],c,n.value<0?"n":"s",null,o)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),n.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),n.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){d&&e.tooltip.cleanup()}),T.dispatch=S,T.legend=o,T.lines=t,T.bars=n,T.xAxis=r,T.y1Axis=i,T.y2Axis=s,d3.rebind(T,t,"defined","size","clipVoronoi","interpolate"),T.options=e.utils.optionsFunc.bind(T),T.x=function(e){return arguments.length?(l=e,t.x(e),n.x(e),T):l},T.y=function(e){return arguments.length?(c=e,t.y(e),n.y(e),T):c},T.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,T):u},T.width=function(e){return arguments.length?(a=e,T):a},T.height=function(e){return arguments.length?(f=e,T):f},T.color=function(t){return arguments.length?(h=e.utils.getColor(t),o.color(h),T):h},T.showLegend=function(e){return arguments.length?(p=e,T):p},T.tooltips=function(e){return arguments.length?(d=e,T):d},T.tooltipContent=function(e){return arguments.length?(v=e,T):v},T.state=function(e){return arguments.length?(b=e,T):b},T.defaultState=function(e){return arguments.length?(w=e,T):w},T.noData=function(e){return arguments.length?(E=e,T):E},T},e.models.lineWithFocusChart=function(){function k(e){return e.each(function(e){function R(e){var t=+(e=="e"),n=t?1:-1,r=O/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function U(){a.empty()||a.extent(w),F.data([a.empty()?g.domain():w]).each(function(e,t){var n=g(e[0])-v.range()[0],r=v.range()[1]-g(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",g(e[1])).attr("width",r<0?0:r)})}function z(){w=a.empty()?null:a.extent();var n=a.empty()?g.domain():a.extent();if(Math.abs(n[0]-n[1])<=1)return;T.brush({extent:n,brush:a}),U();var s=P.select(".nv-focus .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}).map(function(e,r){return{key:e.key,values:e.values.filter(function(e,r){return t.x()(e,r)>=n[0]&&t.x()(e,r)<=n[1]})}}));s.call(t),P.select(".nv-focus .nv-x.nv-axis").call(r),P.select(".nv-focus .nv-y.nv-axis").call(i)}var S=d3.select(this),N=this,L=(h||parseInt(S.style("width"))||960)-f.left-f.right,A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d,O=d-l.top-l.bottom;k.update=function(){S.call(k)},k.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var M=S.selectAll(".nv-noData").data([x]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",f.left+L/2).attr("y",f.top+A/2).text(function(e){return e}),k}S.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale(),g=n.xScale(),y=n.yScale();var _=S.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([e]),D=_.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),P=_.select("g");D.append("g").attr("class","nv-legendWrap");var H=D.append("g").attr("class","nv-focus");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-linesWrap");var B=D.append("g").attr("class","nv-context");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-linesWrap"),B.append("g").attr("class","nv-brushBackground"),B.append("g").attr("class","nv-x nv-brush"),b&&(u.width(L),P.select(".nv-legendWrap").datum(e).call(u),f.top!=u.height()&&(f.top=u.height(),A=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d),P.select(".nv-legendWrap").attr("transform","translate(0,"+ -f.top+")")),_.attr("transform","translate("+f.left+","+f.top+")"),t.width(L).height(A).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),n.defined(t.defined()).width(L).height(O).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),P.select(".nv-context").attr("transform","translate(0,"+(A+f.bottom+l.top)+")");var j=P.select(".nv-context .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}));d3.transition(j).call(n),r.scale(v).ticks(L/100).tickSize(-A,0),i.scale(m).ticks(A/36).tickSize(-L,0),P.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+A+")"),a.x(g).on("brush",function(){var e=k.transitionDuration();k.transitionDuration(0),z(),k.transitionDuration(e)}),w&&a.extent(w);var F=P.select(".nv-brushBackground").selectAll("g").data([w||a.extent()]),I=F.enter().append("g");I.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",O),I.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",O);var q=P.select(".nv-x.nv-brush").call(a);q.selectAll("rect").attr("height",O),q.selectAll(".resize").append("path").attr("d",R),z(),s.scale(g).ticks(L/100).tickSize(-O,0),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.transition(P.select(".nv-context .nv-x.nv-axis")).call(s),o.scale(y).ticks(O/36).tickSize(-L,0),d3.transition(P.select(".nv-context .nv-y.nv-axis")).call(o),P.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),u.dispatch.on("stateChange",function(e){k.update()}),T.on("tooltipShow",function(e){E&&C(e,N.parentNode)})}),k}var t=e.models.line(),n=e.models.line(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.axis(),u=e.models.legend(),a=d3.svg.brush(),f={top:30,right:30,bottom:30,left:60},l={top:0,right:30,bottom:20,left:60},c=e.utils.defaultColor(),h=null,p=null,d=100,v,m,g,y,b=!0,w=null,E=!0,S=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},x="No Data Available.",T=d3.dispatch("tooltipShow","tooltipHide","brush"),N=0;t.clipEdge(!0),n.interactive(!1),r.orient("bottom").tickPadding(5),i.orient("left"),s.orient("bottom").tickPadding(5),o.orient("left");var C=function(n,s){var o=n.pos[0]+(s.offsetLeft||0),u=n.pos[1]+(s.offsetTop||0),a=r.tickFormat()(t.x()(n.point,n.pointIndex)),f=i.tickFormat()(t.y()(n.point,n.pointIndex)),l=S(n.series.key,a,f,n,k);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+f.left,e.pos[1]+f.top],T.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){E&&e.tooltip.cleanup()}),k.dispatch=T,k.legend=u,k.lines=t,k.lines2=n,k.xAxis=r,k.yAxis=i,k.x2Axis=s,k.y2Axis=o,d3.rebind(k,t,"defined","isArea","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),k.options=e.utils.optionsFunc.bind(k),k.x=function(e){return arguments.length?(t.x(e),n.x(e),k):t.x},k.y=function(e){return arguments.length?(t.y(e),n.y(e),k):t.y},k.margin=function(e){return arguments.length?(f.top=typeof e.top!="undefined"?e.top:f.top,f.right=typeof e.right!="undefined"?e.right:f.right,f.bottom=typeof e.bottom!="undefined"?e.bottom:f.bottom,f.left=typeof e.left!="undefined"?e.left:f.left,k):f},k.margin2=function(e){return arguments.length?(l=e,k):l},k.width=function(e){return arguments.length?(h=e,k):h},k.height=function(e){return arguments.length?(p=e,k):p},k.height2=function(e){return arguments.length?(d=e,k):d},k.color=function(t){return arguments.length?(c=e.utils.getColor(t),u.color(c),k):c},k.showLegend=function(e){return arguments.length?(b=e,k):b},k.tooltips=function(e){return arguments.length?(E=e,k):E},k.tooltipContent=function(e){return arguments.length?(S=e,k):S},k.interpolate=function(e){return arguments.length?(t.interpolate(e),n.interpolate(e),k):t.interpolate()},k.noData=function(e){return arguments.length?(x=e,k):x},k.xTickFormat=function(e){return arguments.length?(r.tickFormat(e),s.tickFormat(e),k):r.tickFormat()},k.yTickFormat=function(e){return arguments.length?(i.tickFormat(e),o.tickFormat(e),k):i.tickFormat()},k.brushExtent=function(e){return arguments.length?(w=e,k):w},k.transitionDuration=function(e){return arguments.length?(N=e,k):N},k},e.models.linePlusBarWithFocusChart=function(){function B(e){return e.each(function(e){function tt(e){var t=+(e=="e"),n=t?1:-1,r=I/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function nt(){h.empty()||h.extent(x),Y.data([h.empty()?k.domain():x]).each(function(e,t){var n=k(e[0])-k.range()[0],r=k.range()[1]-k(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",k(e[1])).attr("width",r<0?0:r)})}function rt(){x=h.empty()?null:h.extent(),S=h.empty()?k.domain():h.extent(),D.brush({extent:S,brush:h}),nt(),r.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),t.width(j).height(F).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var n=$.select(".nv-focus .nv-barsWrap").datum(R.length?R.map(function(e,t){return{key:e.key,values:e.values.filter(function(e,t){return r.x()(e,t)>=S[0]&&r.x()(e,t)<=S[1]})}}):[{values:[]}]),i=$.select(".nv-focus .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U.map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=S[0]&&t.x()(e,n)<=S[1]})}}));R.length?C=r.xScale():C=t.xScale(),s.scale(C).ticks(j/100).tickSize(-F,0),s.domain([Math.ceil(S[0]),Math.floor(S[1])]),$.select(".nv-x.nv-axis").call(s),n.call(r),i.call(t),$.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L.range()[0]+")"),u.scale(L).ticks(F/36).tickSize(-j,0),$.select(".nv-focus .nv-y1.nv-axis").style("opacity",R.length?1:0),a.scale(A).ticks(F/36).tickSize(R.length?0:-j,0),$.select(".nv-focus .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+C.range()[1]+",0)"),$.select(".nv-focus .nv-y1.nv-axis").call(u),$.select(".nv-focus .nv-y2.nv-axis").call(a)}var N=d3.select(this),P=this,j=(v||parseInt(N.style("width"))||960)-p.left-p.right,F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g,I=g-d.top-d.bottom;B.update=function(){N.call(B)},B.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=N.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",p.left+j/2).attr("y",p.top+F/2).text(function(e){return e}),B}N.selectAll(".nv-noData").remove();var R=e.filter(function(e){return!e.disabled&&e.bar}),U=e.filter(function(e){return!e.bar});C=r.xScale(),k=o.scale(),L=r.yScale(),A=t.yScale(),O=i.yScale(),M=n.yScale();var z=e.filter(function(e){return!e.disabled&&e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})}),W=e.filter(function(e){return!e.disabled&&!e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})});C.range([0,j]),k.domain(d3.extent(d3.merge(z.concat(W)),function(e){return e.x})).range([0,j]);var X=N.selectAll("g.nv-wrap.nv-linePlusBar").data([e]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),$=X.select("g");V.append("g").attr("class","nv-legendWrap");var J=V.append("g").attr("class","nv-focus");J.append("g").attr("class","nv-x nv-axis"),J.append("g").attr("class","nv-y1 nv-axis"),J.append("g").attr("class","nv-y2 nv-axis"),J.append("g").attr("class","nv-barsWrap"),J.append("g").attr("class","nv-linesWrap");var K=V.append("g").attr("class","nv-context");K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y1 nv-axis"),K.append("g").attr("class","nv-y2 nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-linesWrap"),K.append("g").attr("class","nv-brushBackground"),K.append("g").attr("class","nv-x nv-brush"),E&&(c.width(j/2),$.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(c),p.top!=c.height()&&(p.top=c.height(),F=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g),$.select(".nv-legendWrap").attr("transform","translate("+j/2+","+ -p.top+")")),X.attr("transform","translate("+p.left+","+p.top+")"),i.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),n.width(j).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var Q=$.select(".nv-context .nv-barsWrap").datum(R.length?R:[{values:[]}]),G=$.select(".nv-context .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U);$.select(".nv-context").attr("transform","translate(0,"+(F+p.bottom+d.top)+")"),Q.call(i),G.call(n),h.x(k).on("brush",rt),x&&h.extent(x);var Y=$.select(".nv-brushBackground").selectAll("g").data([x||h.extent()]),Z=Y.enter().append("g");Z.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",I),Z.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",I);var et=$.select(".nv-x.nv-brush").call(h);et.selectAll("rect").attr("height",I),et.selectAll(".resize").append("path").attr("d",tt),o.ticks(j/100).tickSize(-I,0),$.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+O.range()[0]+")"),$.select(".nv-context .nv-x.nv-axis").call(o),f.scale(O).ticks(I/36).tickSize(-j,0),$.select(".nv-context .nv-y1.nv-axis").style("opacity",R.length?1:0).attr("transform","translate(0,"+k.range()[0]+")"),$.select(".nv-context .nv-y1.nv-axis").call(f),l.scale(M).ticks(I/36).tickSize(R.length?0:-j,0),$.select(".nv-context .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+k.range()[1]+",0)"),$.select(".nv-context .nv-y2.nv-axis").call(l),c.dispatch.on("stateChange",function(e){B.update()}),D.on("tooltipShow",function(e){T&&H(e,P.parentNode)}),rt()}),B}var t=e.models.line(),n=e.models.line(),r=e.models.historicalBar(),i=e.models.historicalBar(),s=e.models.axis(),o=e.models.axis(),u=e.models.axis(),a=e.models.axis(),f=e.models.axis(),l=e.models.axis(),c=e.models.legend(),h=d3.svg.brush(),p={top:30,right:30,bottom:30,left:60},d={top:0,right:30,bottom:20,left:60},v=null,m=null,g=100,y=function(e){return e.x},b=function(e){return e.y},w=e.utils.defaultColor(),E=!0,S,x=null,T=!0,N=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},C,k,L,A,O,M,_="No Data Available.",D=d3.dispatch("tooltipShow","tooltipHide","brush"),P=0;t.clipEdge(!0),n.interactive(!1),s.orient("bottom").tickPadding(5),u.orient("left"),a.orient("right"),o.orient("bottom").tickPadding(5),f.orient("left"),l.orient("right");var H=function(n,r){S&&(n.pointIndex+=Math.ceil(S[0]));var i=n.pos[0]+(r.offsetLeft||0),o=n.pos[1]+(r.offsetTop||0),f=s.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?u:a).tickFormat()(t.y()(n.point,n.pointIndex)),c=N(n.series.key,f,l,n,B);e.tooltip.show([i,o],c,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),r.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),r.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),D.on("tooltipHide",function(){T&&e.tooltip.cleanup()}),B.dispatch=D,B.legend=c,B.lines=t,B.lines2=n,B.bars=r,B.bars2=i,B.xAxis=s,B.x2Axis=o,B.y1Axis=u,B.y2Axis=a,B.y3Axis=f,B.y4Axis=l,d3.rebind(B,t,"defined","size","clipVoronoi","interpolate"),B.options=e.utils.optionsFunc.bind(B),B.x=function(e){return arguments.length?(y=e,t.x(e),r.x(e),B):y},B.y=function(e){return arguments.length?(b=e,t.y(e),r.y(e),B):b},B.margin=function(e){return arguments.length?(p.top=typeof e.top!="undefined"?e.top:p.top,p.right=typeof e.right!="undefined"?e.right:p.right,p.bottom=typeof e.bottom!="undefined"?e.bottom:p.bottom,p.left=typeof e.left!="undefined"?e.left:p.left,B):p},B.width=function(e){return arguments.length?(v=e,B):v},B.height=function(e){return arguments.length?(m=e,B):m},B.color=function(t){return arguments.length?(w=e.utils.getColor(t),c.color(w),B):w},B.showLegend=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(T=e,B):T},B.tooltipContent=function(e){return arguments.length?(N=e,B):N},B.noData=function(e){return arguments.length?(_=e,B):_},B.brushExtent=function(e){return arguments.length?(x=e,B):x},B},e.models.multiBar=function(){function C(e){return e.each(function(e){var g=n-t.left-t.right,C=r-t.top-t.bottom,k=d3.select(this);d&&e.length&&(d=[{values:e[0].values.map(function(e){return{x:e.x,y:0,series:e.series,size:.01}})}]),c&&(e=d3.layout.stack().offset(h).values(function(e){return e.values}).y(a)(!e.length&&d?d:e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),c&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i,i-=t.size):(t.y1=t.size+r,r+=t.size)})});var L=y&&b?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});i.domain(y||d3.merge(L).map(function(e){return e.x})).rangeBands(w||[0,g],S),s.domain(b||d3.extent(d3.merge(L).map(function(e){return c?e.y>0?e.y1:e.y1+e.y:e.y}).concat(f))).range(E||[C,0]),i.domain()[0]===i.domain()[1]&&(i.domain()[0]?i.domain([i.domain()[0]-i.domain()[0]*.01,i.domain()[1]+i.domain()[1]*.01]):i.domain([-1,1])),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]+s.domain()[0]*.01,s.domain()[1]-s.domain()[1]*.01]):s.domain([-1,1])),T=T||i,N=N||s;var A=k.selectAll("g.nv-wrap.nv-multibar").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),M=O.append("defs"),_=O.append("g"),D=A.select("g");_.append("g").attr("class","nv-groups"),A.attr("transform","translate("+t.left+","+t.top+")"),M.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),A.select("#nv-edge-clip-"+o+" rect").attr("width",g).attr("height",C),D.attr("clip-path",l?"url(#nv-edge-clip-"+o+")":"");var P=A.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});P.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),P.exit().selectAll("rect.nv-bar").attr("y",function(e){return c?N(e.y0):N(0)}).attr("height",0).remove(),P.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return p(e,t)}).style("stroke",function(e,t){return p(e,t)}),P.style("stroke-opacity",1).style("fill-opacity",.75);var H=P.selectAll("rect.nv-bar").data(function(t){return d&&!e.length?d.values:t.values});H.exit().remove();var B=H.enter().append("rect").attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(t,n,r){return c?0:r*i.rangeBand()/e.length}).attr("y",function(e){return N(c?e.y0:0)}).attr("height",0).attr("width",i.rangeBand()/(c?1:e.length)).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"});H.style("fill",function(e,t,n){return p(e,n,t)}).style("stroke",function(e,t,n){return p(e,n,t)}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"}),v&&(m||(m=e.map(function(){return!0})),H.style("fill",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()})),c?H.attr("y",function(e,t){return s(c?e.y1:0)}).attr("height",function(e,t){return Math.max(Math.abs(s(e.y+(c?e.y0:0))-s(c?e.y0:0)),1)}).attr("x",function(t,n){return c?0:t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/(c?1:e.length)):H.attr("x",function(t,n){return t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/e.length).attr("y",function(e,t){return a(e,t)<0?s(0):s(0)-s(a(e,t))<1?s(0)-1:s(a(e,t))||0}).attr("height",function(e,t){return Math.max(Math.abs(s(a(e,t))-s(0)),1)||0}),T=i.copy(),N=s.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=d3.scale.ordinal(),s=d3.scale.linear(),o=Math.floor(Math.random()*1e4),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=!0,c=!1,h="zero",p=e.utils.defaultColor(),d=!1,v=null,m,g=1200,y,b,w,E,S=.1,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(i=e,C):i},C.yScale=function(e){return arguments.length?(s=e,C):s},C.xDomain=function(e){return arguments.length?(y=e,C):y},C.yDomain=function(e){return arguments.length?(b=e,C):b},C.xRange=function(e){return arguments.length?(w=e,C):w},C.yRange=function(e){return arguments.length?(E=e,C):E},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(c=e,C):c},C.stackOffset=function(e){return arguments.length?(h=e,C):h},C.clipEdge=function(e){return arguments.length?(l=e,C):l},C.color=function(t){return arguments.length?(p=e.utils.getColor(t),C):p},C.barColor=function(t){return arguments.length?(v=e.utils.getColor(t),C):v},C.disabled=function(e){return arguments.length?(m=e,C):m},C.id=function(e){return arguments.length?(o=e,C):o},C.hideable=function(e){return arguments.length?(d=e,C):d},C.delay=function(e){return arguments.length?(g=e,C):g},C.groupSpacing=function(e){return arguments.length?(S=e,C):S},C},e.models.multiBarChart=function(){function A(e){return e.each(function(e){var b=d3.select(this),k=this,O=(u||parseInt(b.style("width"))||960)-o.left-o.right,M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom;A.update=function(){b.call(A)},A.container=this,S.disabled=e.map(function(e){return!!e.disabled});if(!x){var _;x={};for(_ in S)S[_]instanceof Array?x[_]=S[_].slice(0):x[_]=S[_]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var D=b.selectAll(".nv-noData").data([T]);return D.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),D.attr("x",o.left+O/2).attr("y",o.top+M/2).text(function(e){return e}),A}b.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();var P=b.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([e]),H=P.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),B=P.select("g");H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-barsWrap"),H.append("g").attr("class","nv-legendWrap"),H.append("g").attr("class","nv-controlsWrap"),c&&(i.width(O-C()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),B.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),M=(a||parseInt(b.style("height"))||400)-o.top-o.bottom),B.select(".nv-legendWrap").attr("transform","translate("+C()+","+ -o.top+")"));if(l){var j=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(C()).color(["#444","#444","#444"]),B.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -o.top+")").call(s)}P.attr("transform","translate("+o.left+","+o.top+")"),d&&B.select(".nv-y.nv-axis").attr("transform","translate("+O+",0)"),t.disabled(e.map(function(e){return e.disabled})).width(O).height(M).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var F=B.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));F.call(t);if(h){n.scale(w).ticks(O/100).tickSize(-M,0),B.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),B.select(".nv-x.nv-axis").call(n);var I=B.select(".nv-x.nv-axis > g").selectAll("g");I.selectAll("line, text").style("opacity",1);if(m){var q=function(e,t){return"translate("+e+","+t+")"},R=5,U=17;I.selectAll("text").attr("transform",function(e,t,n){return q(0,n%2==0?R:U)});var z=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;B.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(e,t){return q(0,t===0||z%2!==0?U:R)})}v&&I.filter(function(t,n){return n%Math.ceil(e[0].values.length/(O/100))!==0}).selectAll("text, line").style("opacity",0),g&&I.selectAll(".tick text").attr("transform","rotate("+g+" 0,0)").style("text-anchor",g>0?"start":"end"),B.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}p&&(r.scale(E).ticks(M/36).tickSize(-O,0),B.select(".nv-y.nv-axis").call(r)),i.dispatch.on("stateChange",function(e){S=e,N.stateChange(S),A.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;j=j.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}S.stacked=t.stacked(),N.stateChange(S),A.update()}),N.on("tooltipShow",function(e){y&&L(e,k.parentNode)}),N.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),S.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),S.stacked=n.stacked),A.update()})}),A}var t=e.models.multiBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=!1,g=0,y=!0,b=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},w,E,S={stacked:!1},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=function(){return l?180:0},k=0;t.stacked(!1),n.orient("bottom").tickPadding(7).highlightZero(!0).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(d?"right":"left").tickFormat(d3.format(",.1f")),s.updateState(!1);var L=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,A);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],N.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){y&&e.tooltip.cleanup()}),A.dispatch=N,A.multibar=t,A.legend=i,A.xAxis=n,A.yAxis=r,d3.rebind(A,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","stacked","stackOffset","delay","barColor","groupSpacing"),A.options=e.utils.optionsFunc.bind(A),A.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,A):o},A.width=function(e){return arguments.length?(u=e,A):u},A.height=function(e){return arguments.length?(a=e,A):a},A.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),A):f},A.showControls=function(e){return arguments.length?(l=e,A):l},A.showLegend=function(e){return arguments.length?(c=e,A):c},A.showXAxis=function(e){return arguments.length?(h=e,A):h},A.showYAxis=function(e){return arguments.length?(p=e,A):p},A.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),A):d},A.reduceXTicks=function(e){return arguments.length?(v=e,A):v},A.rotateLabels=function(e){return arguments.length?(g=e,A):g},A.staggerLabels=function(e){return arguments.length?(m=e,A):m},A.tooltip=function(e){return arguments.length?(b=e,A):b},A.tooltips=function(e){return arguments.length?(y=e,A):y},A.tooltipContent=function(e){return arguments.length?(b=e,A):b},A.state=function(e){return arguments.length?(S=e,A):S},A.defaultState=function(e){return arguments.length?(x=e,A):x},A.noData=function(e){return arguments.length?(T=e,A):T},A.transitionDuration=function(e){return arguments.length?(k=e,A):k},A},e.models.multiBarHorizontal=function(){function C(e){return e.each(function(e){var i=n-t.left-t.right,y=r-t.top-t.bottom,C=d3.select(this);p&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),p&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i-t.size,i-=t.size):(t.y1=r,r+=t.size)})});var k=b&&w?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});s.domain(b||d3.merge(k).map(function(e){return e.x})).rangeBands(E||[0,y],.1),o.domain(w||d3.extent(d3.merge(k).map(function(e){return p?e.y>0?e.y1+e.y:e.y1:e.y}).concat(f))),d&&!p?o.range(S||[o.domain()[0]<0?m:0,i-(o.domain()[1]>0?m:0)]):o.range(S||[0,i]),T=T||s,N=N||d3.scale.linear().domain(o.domain()).range([o(0),o(0)]);var L=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([e]),A=L.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),O=A.append("defs"),M=A.append("g"),_=L.select("g");M.append("g").attr("class","nv-groups"),L.attr("transform","translate("+t.left+","+t.top+")");var D=L.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return l(e,t)}).style("stroke",function(e,t){return l(e,t)}),D.style("stroke-opacity",1).style("fill-opacity",.75);var P=D.selectAll("g.nv-bar").data(function(e){return e.values});P.exit().remove();var H=P.enter().append("g").attr("transform",function(t,n,r){return"translate("+N(p?t.y0:0)+","+(p?0:r*s.rangeBand()/e.length+s(u(t,n)))+")"});H.append("rect").attr("width",0).attr("height",s.rangeBand()/(p?1:e.length)),P.on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[o(a(t,n)+(p?t.y0:0)),s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.append("text"),d&&!p?(P.select("text").attr("text-anchor",function(e,t){return a(e,t)<0?"end":"start"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return g(a(e,t))}),P.select("text").attr("x",function(e,t){return a(e,t)<0?-4:o(a(e,t))-o(0)+4})):P.selectAll("text").text(""),v&&!p?(H.append("text").classed("nv-bar-label",!0),P.select("text.nv-bar-label").attr("text-anchor",function(e,t){return a(e,t)<0?"start":"end"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return u(e,t)}),P.select("text.nv-bar-label").attr("x",function(e,t){return a(e,t)<0?o(0)-o(a(e,t))+4:-4})):P.selectAll("text.nv-bar-label").text(""),P.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}),c&&(h||(h=e.map(function(){return!0})),P.style("fill",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()})),p?P.attr("transform",function(e,t){return"translate("+o(e.y1)+","+s(u(e,t))+")"}).select("rect").attr("width",function(e,t){return Math.abs(o(a(e,t)+e.y0)-o(e.y0))}).attr("height",s.rangeBand()):P.attr("transform",function(t,n){return"translate("+(a(t,n)<0?o(a(t,n)):o(0))+","+(t.series*s.rangeBand()/e.length+s(u(t,n)))+")"}).select("rect").attr("height",s.rangeBand()/e.length).attr("width",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)}),T=s.copy(),N=o.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=null,h,p=!1,d=!1,v=!1,m=60,g=d3.format(",.2f"),y=1200,b,w,E,S,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(s=e,C):s},C.yScale=function(e){return arguments.length?(o=e,C):o},C.xDomain=function(e){return arguments.length?(b=e,C):b},C.yDomain=function(e){return arguments.length?(w=e,C):w},C.xRange=function(e){return arguments.length?(E=e,C):E},C.yRange=function(e){return arguments.length?(S=e,C):S},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(p=e,C):p},C.color=function(t){return arguments.length?(l=e.utils.getColor(t),C):l},C.barColor=function(t){return arguments.length?(c=e.utils.getColor(t),C):c},C.disabled=function(e){return arguments.length?(h=e,C):h},C.id=function(e){return arguments.length?(i=e,C):i},C.delay=function(e){return arguments.length?(y=e,C):y},C.showValues=function(e){return arguments.length?(d=e,C):d},C.showBarLabels=function(e){return arguments.length?(v=e,C):v},C.valueFormat=function(e){return arguments.length?(g=e,C):g},C.valuePadding=function(e){return arguments.length?(m=e,C):m},C},e.models.multiBarHorizontalChart=function(){function C(e){return e.each(function(e){var d=d3.select(this),m=this,T=(u||parseInt(d.style("width"))||960)-o.left-o.right,k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom;C.update=function(){d.call(C)},C.container=this,b.disabled=e.map(function(e){return!!e.disabled});if(!w){var L;w={};for(L in b)b[L]instanceof Array?w[L]=b[L].slice(0):w[L]=b[L]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var A=d.selectAll(".nv-noData").data([E]);return A.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),A.attr("x",o.left+T/2).attr("y",o.top+k/2).text(function(e){return e}),C}d.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var O=d.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-legendWrap"),M.append("g").attr("class","nv-controlsWrap"),c&&(i.width(T-x()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),_.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),k=(a||parseInt(d.style("height"))||400)-o.top-o.bottom),_.select(".nv-legendWrap").attr("transform","translate("+x()+","+ -o.top+")"));if(l){var D=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(x()).color(["#444","#444","#444"]),_.select(".nv-controlsWrap").datum(D).attr("transform","translate(0,"+ -o.top+")").call(s)}O.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(e.map(function(e){return e.disabled})).width(T).height(k).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var P=_.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));P.call(t);if(h){n.scale(g).ticks(k/24).tickSize(-T,0),_.select(".nv-x.nv-axis").call(n);var H=_.select(".nv-x.nv-axis").selectAll("g");H.selectAll("line, text")}p&&(r.scale(y).ticks(T/100).tickSize(-k,0),_.select(".nv-y.nv-axis").attr("transform","translate(0,"+k+")"),_.select(".nv-y.nv-axis").call(r)),_.select(".nv-zeroLine line").attr("x1",y(0)).attr("x2",y(0)).attr("y1",0).attr("y2",-k),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),C.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;D=D.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}b.stacked=t.stacked(),S.stateChange(b),C.update()}),S.on("tooltipShow",function(e){v&&N(e,m.parentNode)}),S.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),b.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),b.stacked=n.stacked),C.update()})}),C}var t=e.models.multiBarHorizontal(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend().height(30),s=e.models.legend().height(30),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+" - "+t+"</h3>"+"<p>"+n+"</p>"},g,y,b={stacked:d},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=function(){return l?180:0},T=0;t.stacked(d),n.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("bottom").tickFormat(d3.format(",.1f")),s.updateState(!1);var N=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,C);e.tooltip.show([o,u],l,i.value<0?"e":"w",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),C.dispatch=S,C.multibar=t,C.legend=i,C.xAxis=n,C.yAxis=r,d3.rebind(C,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","delay","showValues","showBarLabels","valueFormat","stacked","barColor"),C.options=e.utils.optionsFunc.bind(C),C.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,C):o},C.width=function(e){return arguments.length?(u=e,C):u},C.height=function(e){return arguments.length?(a=e,C):a},C.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),C):f},C.showControls=function(e){return arguments.length?(l=e,C):l},C.showLegend=function(e){return arguments.length?(c=e,C):c},C.showXAxis=function(e){return arguments.length?(h=e,C):h},C.showYAxis=function(e){return arguments.length?(p=e,C):p},C.tooltip=function(e){return arguments.length?(m=e,C):m},C.tooltips=function(e){return arguments.length?(v=e,C):v},C.tooltipContent=function(e){return arguments.length?(m=e,C):m},C.state=function(e){return arguments.length?(b=e,C):b},C.defaultState=function(e){return arguments.length?(w=e,C):w},C.noData=function(e){return arguments.length?(E=e,C):E},C.transitionDuration=function(e){return arguments.length?(T=e,C):T},C},e.models.multiChart=function(){function C(e){return e.each(function(e){var u=d3.select(this),f=this;C.update=function(){u.call(C)},C.container=this;var k=(r||parseInt(u.style("width"))||960)-t.left-t.right,L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom,A=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==1}),O=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==2}),M=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==1}),_=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==2}),D=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==1}),P=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==2}),H=e.filter(function(e){return!e.disabled&&e.yAxis==1}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})}),B=e.filter(function(e){return!e.disabled&&e.yAxis==2}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})});a.domain(d3.extent(d3.merge(H.concat(B)),function(e){return e.x})).range([0,k]);var j=u.selectAll("g.wrap.multiChart").data([e]),F=j.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");F.append("g").attr("class","x axis"),F.append("g").attr("class","y1 axis"),F.append("g").attr("class","y2 axis"),F.append("g").attr("class","lines1Wrap"),F.append("g").attr("class","lines2Wrap"),F.append("g").attr("class","bars1Wrap"),F.append("g").attr("class","bars2Wrap"),F.append("g").attr("class","stack1Wrap"),F.append("g").attr("class","stack2Wrap"),F.append("g").attr("class","legendWrap");var I=j.select("g");s&&(x.width(k/2),I.select(".legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.yAxis==1?"":" (right axis)"),e})).call(x),t.top!=x.height()&&(t.top=x.height(),L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom),I.select(".legendWrap").attr("transform","translate("+k/2+","+ -t.top+")")),d.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="line"})),v.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="line"})),m.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="bar"})),g.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="bar"})),y.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="area"})),b.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="area"})),I.attr("transform","translate("+t.left+","+t.top+")");var q=I.select(".lines1Wrap").datum(A),R=I.select(".bars1Wrap").datum(M),U=I.select(".stack1Wrap").datum(D),z=I.select(".lines2Wrap").datum(O),W=I.select(".bars2Wrap").datum(_),X=I.select(".stack2Wrap").datum(P),V=D.length?D.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[],$=P.length?P.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[];h.domain(l||d3.extent(d3.merge(H).concat(V),function(e){return e.y})).range([0,L]),p.domain(c||d3.extent(d3.merge(B).concat($),function(e){return e.y})).range([0,L]),d.yDomain(h.domain()),m.yDomain(h.domain()),y.yDomain(h.domain()),v.yDomain(p.domain()),g.yDomain(p.domain()),b.yDomain(p.domain()),D.length&&d3.transition(U).call(y),P.length&&d3.transition(X).call(b),M.length&&d3.transition(R).call(m),_.length&&d3.transition(W).call(g),A.length&&d3.transition(q).call(d),O.length&&d3.transition(z).call(v),w.ticks(k/100).tickSize(-L,0),I.select(".x.axis").attr("transform","translate(0,"+L+")"),d3.transition(I.select(".x.axis")).call(w),E.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y1.axis")).call(E),S.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y2.axis")).call(S),I.select(".y2.axis").style("opacity",B.length?1:0).attr("transform","translate("+a.range()[1]+",0)"),x.dispatch.on("stateChange",function(e){C.update()}),T.on("tooltipShow",function(e){o&&N(e,f.parentNode)})}),C}var t={top:30,right:20,bottom:50,left:60},n=d3.scale.category20().range(),r=null,i=null,s=!0,o=!0,u=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},a,f,l,c,a=d3.scale.linear(),h=d3.scale.linear(),p=d3.scale.linear(),d=e.models.line().yScale(h),v=e.models.line().yScale(p),m=e.models.multiBar().stacked(!1).yScale(h),g=e.models.multiBar().stacked(!1).yScale(p),y=e.models.stackedArea().yScale(h),b=e.models.stackedArea().yScale(p),w=e.models.axis().scale(a).orient("bottom").tickPadding(5),E=e.models.axis().scale(h).orient("left"),S=e.models.axis().scale(p).orient("right"),x=e.models.legend().height(30),T=d3.dispatch("tooltipShow","tooltipHide"),N=function(t,n){var r=t.pos[0]+(n.offsetLeft||0),i=t.pos[1]+(n.offsetTop||0),s=w.tickFormat()(d.x()(t.point,t.pointIndex)),o=(t.series.yAxis==2?S:E).tickFormat()(d.y()(t.point,t.pointIndex)),a=u(t.series.key,s,o,t,C);e.tooltip.show([r,i],a,undefined,undefined,n.offsetParent)};return d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),m.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),m.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),g.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),g.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),y.dispatch.on("tooltipShow",function(e){if(!Math.round(y.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),y.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),b.dispatch.on("tooltipShow",function(e){if(!Math.round(b.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),b.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){o&&e.tooltip.cleanup()}),C.dispatch=T,C.lines1=d,C.lines2=v,C.bars1=m,C.bars2=g,C.stack1=y,C.stack2=b,C.xAxis=w,C.yAxis1=E,C.yAxis2=S,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(getX=e,d.x(e),m.x(e),C):getX},C.y=function(e){return arguments.length?(getY=e,d.y(e),m.y(e),C):getY},C.yDomain1=function(e){return arguments.length?(l=e,C):l},C.yDomain2=function(e){return arguments.length?(c=e,C):c},C.margin=function(e){return arguments.length?(t=e,C):t},C.width=function(e){return arguments.length?(r=e,C):r},C.height=function(e){return arguments.length?(i=e,C):i},C.color=function(e){return arguments.length?(n=e,x.color(e),C):n},C.showLegend=function(e){return arguments.length?(s=e,C):s},C.tooltips=function(e){return arguments.length?(o=e,C):o},C.tooltipContent=function(e){return arguments.length?(u=e,C):u},C},e.models.ohlcBar=function(){function x(e){return e.each(function(e){var g=n-t.left-t.right,x=r-t.top-t.bottom,T=d3.select(this);s.domain(y||d3.extent(e[0].values.map(u).concat(p))),v?s.range(w||[g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range(w||[0,g]),o.domain(b||[d3.min(e[0].values.map(h).concat(d)),d3.max(e[0].values.map(c).concat(d))]).range(E||[x,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([e[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-ticks"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){S.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",x),A.attr("clip-path",m?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-ticks").selectAll(".nv-tick").data(function(e){return e});O.exit().remove();var M=O.enter().append("path").attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"}).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),S.elementMouseover({point:t,series:e[0],pos:[s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),S.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){S.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){S.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}),d3.transition(O).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"})}),x}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=function(e){return e.open},l=function(e){return e.close},c=function(e){return e.high},h=function(e){return e.low},p=[],d=[],v=!1,m=!0,g=e.utils.defaultColor(),y,b,w,E,S=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return x.dispatch=S,x.options=e.utils.optionsFunc.bind(x),x.x=function(e){return arguments.length?(u=e,x):u},x.y=function(e){return arguments.length?(a=e,x):a},x.open=function(e){return arguments.length?(f=e,x):f},x.close=function(e){return arguments.length?(l=e,x):l},x.high=function(e){return arguments.length?(c=e,x):c},x.low=function(e){return arguments.length?(h=e,x):h},x.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,x):t},x.width=function(e){return arguments.length?(n=e,x):n},x.height=function(e){return arguments.length?(r=e,x):r},x.xScale=function(e){return arguments.length?(s=e,x):s},x.yScale=function(e){return arguments.length?(o=e,x):o},x.xDomain=function(e){return arguments.length?(y=e,x):y},x.yDomain=function(e){return arguments.length?(b=e,x):b},x.xRange=function(e){return arguments.length?(w=e,x):w},x.yRange=function(e){return arguments.length?(E=e,x):E},x.forceX=function(e){return arguments.length?(p=e,x):p},x.forceY=function(e){return arguments.length?(d=e,x):d},x.padData=function(e){return arguments.length?(v=e,x):v},x.clipEdge=function(e){return arguments.length?(m=e,x):m},x.color=function(t){return arguments.length?(g=e.utils.getColor(t),x):g},x.id=function(e){return arguments.length?(i=e,x):i},x},e.models.pie=function(){function S(e){return e.each(function(e){function q(e){var t=(e.startAngle+e.endAngle)*90/Math.PI-90;return t>90?t-180:t}function R(e){e.endAngle=isNaN(e.endAngle)?0:e.endAngle,e.startAngle=isNaN(e.startAngle)?0:e.startAngle,m||(e.innerRadius=0);var t=d3.interpolate(this._current,e);return this._current=t(0),function(e){return A(t(e))}}function U(e){e.innerRadius=0;var t=d3.interpolate({startAngle:0,endAngle:0},e);return function(e){return A(t(e))}}var o=n-t.left-t.right,f=r-t.top-t.bottom,S=Math.min(o,f)/2,x=S-S/5,T=d3.select(this),N=T.selectAll(".nv-wrap.nv-pie").data(e),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+u),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-pie"),k.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+t.left+","+t.top+")"),L.select(".nv-pie").attr("transform","translate("+o/2+","+f/2+")"),L.select(".nv-pieLabels").attr("transform","translate("+o/2+","+f/2+")"),T.on("click",function(e,t){E.chartClick({data:e,index:t,pos:d3.event,id:u})});var A=d3.svg.arc().outerRadius(x);y&&A.startAngle(y),b&&A.endAngle(b),m&&A.innerRadius(S*w);var O=d3.layout.pie().sort(null).value(function(e){return e.disabled?0:s(e)}),M=N.select(".nv-pie").selectAll(".nv-slice").data(O),_=N.select(".nv-pieLabels").selectAll(".nv-label").data(O);M.exit().remove(),_.exit().remove();var D=M.enter().append("g").attr("class","nv-slice").on("mouseover",function(e,t){d3.select(this).classed("hover",!0),E.elementMouseover({label:i(e.data),value:s(e.data),point:e.data,pointIndex:t,pos:[d3.event.pageX,d3.event.pageY],id:u})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),E.elementMouseout({label:i(e.data),value:s(e.data),point:e.data,index:t,id:u})}).on("click",function(e,t){E.elementClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()}).on("dblclick",function(e,t){E.elementDblClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()});M.attr("fill",function(e,t){return a(e,t)}).attr("stroke",function(e,t){return a(e,t)});var P=D.append("path").each(function(e){this._current=e});M.select("path").attr("d",A);if(l){var H=d3.svg.arc().innerRadius(0);c&&(H=A),h&&(H=d3.svg.arc().outerRadius(A.outerRadius())),_.enter().append("g").classed("nv-label",!0).each(function(e,t){var n=d3.select(this);n.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}return e.outerRadius=S+10,e.innerRadius=S+15,"translate("+H.centroid(e)+")"}),n.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),n.append("text").style("text-anchor",g?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")});var B={},j=14,F=140,I=function(e){return Math.floor(e[0]/F)*F+","+Math.floor(e[1]/j)*j};_.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+H.centroid(e)+") rotate("+t+")"}e.outerRadius=S+10,e.innerRadius=S+15;var n=H.centroid(e),r=I(n);return B[r]&&(n[1]-=j),B[I(n)]=!0,"translate("+n+")"}),_.select(".nv-label text").style("text-anchor",g?(d.startAngle+d.endAngle)/2<Math.PI?"start":"end":"middle").text(function(e,t){var n=(e.endAngle-e.startAngle)/(2*Math.PI),r={key:i(e.data),value:s(e.data),percent:d3.format("%")(n)};return e.value&&n>v?r[p]:""})}}),S}var t={top:0,right:0,bottom:0,left:0},n=500,r=500,i=function(e){return e.x},s=function(e){return e.y},o=function(e){return e.description},u=Math.floor(Math.random()*1e4),a=e.utils.defaultColor(),f=d3.format(",.2f"),l=!0,c=!0,h=!1,p="key",v=.02,m=!1,g=!1,y=!1,b=!1,w=.5,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return S.dispatch=E,S.options=e.utils.optionsFunc.bind(S),S.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,S):t},S.width=function(e){return arguments.length?(n=e,S):n},S.height=function(e){return arguments.length?(r=e,S):r},S.values=function(t){return e.log("pie.values() is no longer supported."),S},S.x=function(e){return arguments.length?(i=e,S):i},S.y=function(e){return arguments.length?(s=d3.functor(e),S):s},S.description=function(e){return arguments.length?(o=e,S):o},S.showLabels=function(e){return arguments.length?(l=e,S):l},S.labelSunbeamLayout=function(e){return arguments.length?(g=e,S):g},S.donutLabelsOutside=function(e){return arguments.length?(h=e,S):h},S.pieLabelsOutside=function(e){return arguments.length?(c=e,S):c},S.labelType=function(e){return arguments.length?(p=e,p=p||"key",S):p},S.donut=function(e){return arguments.length?(m=e,S):m},S.donutRatio=function(e){return arguments.length?(w=e,S):w},S.startAngle=function(e){return arguments.length?(y=e,S):y},S.endAngle=function(e){return arguments.length?(b=e,S):b},S.id=function(e){return arguments.length?(u=e,S):u},S.color=function(t){return arguments.length?(a=e.utils.getColor(t),S):a},S.valueFormat=function(e){return arguments.length?(f=e,S):f},S.labelThreshold=function(e){return arguments.length?(v=e,S):v},S},e.models.pieChart=function(){function v(e){return e.each(function(e){var u=d3.select(this),a=this,f=(i||parseInt(u.style("width"))||960)-r.left-r.right,d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom;v.update=function(){u.call(v)},v.container=this,l.disabled=e.map(function(e){return!!e.disabled});if(!c){var m;c={};for(m in l)l[m]instanceof Array?c[m]=l[m].slice(0):c[m]=l[m]}if(!e||!e.length){var g=u.selectAll(".nv-noData").data([h]);return g.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),g.attr("x",r.left+f/2).attr("y",r.top+d/2).text(function(e){return e}),v}u.selectAll(".nv-noData").remove();var y=u.selectAll("g.nv-wrap.nv-pieChart").data([e]),b=y.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),w=y.select("g");b.append("g").attr("class","nv-pieWrap"),b.append("g").attr("class","nv-legendWrap"),o&&(n.width(f).key(t.x()),y.select(".nv-legendWrap").datum(e).call(n),r.top!=n.height()&&(r.top=n.height(),d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom),y.select(".nv-legendWrap").attr("transform","translate(0,"+ -r.top+")")),y.attr("transform","translate("+r.left+","+r.top+")"),t.width(f).height(d);var E=w.select(".nv-pieWrap").datum([e]);d3.transition(E).call(t),n.dispatch.on("stateChange",function(e){l=e,p.stateChange(l),v.update()}),t.dispatch.on("elementMouseout.tooltip",function(e){p.tooltipHide(e)}),p.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),l.disabled=t.disabled),v.update()})}),v}var t=e.models.pie(),n=e.models.legend(),r={top:30,right:20,bottom:20,left:20},i=null,s=null,o=!0,u=e.utils.defaultColor(),a=!0,f=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+t+"</p>"},l={},c=null,h="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),d=function(n,r){var i=t.description()(n.point)||t.x()(n.point),s=n.pos[0]+(r&&r.offsetLeft||0),o=n.pos[1]+(r&&r.offsetTop||0),u=t.valueFormat()(t.y()(n.point)),a=f(i,u,n,v);e.tooltip.show([s,o],a,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+r.left,e.pos[1]+r.top],p.tooltipShow(e)}),p.on("tooltipShow",function(e){a&&d(e)}),p.on("tooltipHide",function(){a&&e.tooltip.cleanup()}),v.legend=n,v.dispatch=p,v.pie=t,d3.rebind(v,t,"valueFormat","values","x","y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","labelType","donut","donutRatio","labelThreshold"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(r.top=typeof e.top!="undefined"?e.top:r.top,r.right=typeof e.right!="undefined"?e.right:r.right,r.bottom=typeof e.bottom!="undefined"?e.bottom:r.bottom,r.left=typeof e.left!="undefined"?e.left:r.left,v):r},v.width=function(e){return arguments.length?(i=e,v):i},v.height=function(e){return arguments.length?(s=e,v):s},v.color=function(r){return arguments.length?(u=e.utils.getColor(r),n.color(u),t.color(u),v):u},v.showLegend=function(e){return arguments.length?(o=e,v):o},v.tooltips=function(e){return arguments.length?(a=e,v):a},v.tooltipContent=function(e){return arguments.length?(f=e,v):f},v.state=function(e){return arguments.length?(l=e,v):l},v.defaultState=function(e){return arguments.length?(c=e,v):c},v.noData=function(e){return arguments.length?(h=e,v):h},v},e.models.scatter=function(){function I(q){return q.each(function(I){function Q(){if(!g)return!1;var e,i=d3.merge(I.map(function(e,t){return e.values.map(function(e,n){var r=f(e,n),i=l(e,n);return[o(r),u(i),t,n,e]}).filter(function(e,t){return b(e[4],t)})}));if(D===!0){if(x){var a=X.select("defs").selectAll(".nv-point-clips").data([s]).enter();a.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+s);var c=X.select("#nv-points-clip-"+s).selectAll("circle").data(i);c.enter().append("circle").attr("r",T),c.exit().remove(),c.attr("cx",function(e){return e[0]}).attr("cy",function(e){return e[1]}),X.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+s+")")}i.length&&(i.push([o.range()[0]-20,u.range()[0]-20,null,null]),i.push([o.range()[1]+20,u.range()[1]+20,null,null]),i.push([o.range()[0]-20,u.range()[0]+20,null,null]),i.push([o.range()[1]+20,u.range()[1]-20,null,null]));var h=d3.geom.polygon([[-10,-10],[-10,r+10],[n+10,r+10],[n+10,-10]]),p=1e-6;i=i.sort(function(e,t){return e[0]-t[0]||e[1]-t[1]});for(var d=0;d<i.length-1;)Math.abs(i[d][0]-i[d+1][0])<p&&Math.abs(i[d][1]-i[d+1][1])<p?i.splice(d+1,1):d++;var v=d3.geom.voronoi(i).map(function(e,t){return{data:h.clip(e),series:i[t][2],point:i[t][3]}}),m=X.select(".nv-point-paths").selectAll("path").data(v);m.enter().append("path").attr("class",function(e,t){return"nv-path-"+t}),m.exit().remove(),m.attr("d",function(e){return!e||!e.data||e.data.length===0?"M 0 0":"M"+e.data.join("L")+"Z"});var y=function(e,n){if(F)return 0;var r=I[e.series];if(typeof r=="undefined")return;var i=r.values[e.point];n({point:i,series:r,pos:[o(f(i,e.point))+t.left,u(l(i,e.point))+t.top],seriesIndex:e.series,pointIndex:e.point})};m.on("click",function(e){y(e,_.elementClick)}).on("mouseover",function(e){y(e,_.elementMouseover)}).on("mouseout",function(e,t){y(e,_.elementMouseout)})}else X.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementClick({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseover",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementMouseover({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseout",function(e,t){if(F||!I[e.series])return 0;var n=I[e.series],r=n.values[t];_.elementMouseout({point:r,series:n,seriesIndex:e.series,pointIndex:t})});F=!1}var q=n-t.left-t.right,R=r-t.top-t.bottom,U=d3.select(this);I.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var W=N&&C&&A?[]:d3.merge(I.map(function(e){return e.values.map(function(e,t){return{x:f(e,t),y:l(e,t),size:c(e,t)}})}));o.domain(N||d3.extent(W.map(function(e){return e.x}).concat(d))),w&&I[0]?o.range(k||[(q*E+q)/(2*I[0].values.length),q-q*(1+E)/(2*I[0].values.length)]):o.range(k||[0,q]),u.domain(C||d3.extent(W.map(function(e){return e.y}).concat(v))).range(L||[R,0]),a.domain(A||d3.extent(W.map(function(e){return e.size}).concat(m))).range(O||[16,256]);if(o.domain()[0]===o.domain()[1]||u.domain()[0]===u.domain()[1])M=!0;o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]-o.domain()[0]*.01,o.domain()[1]+o.domain()[1]*.01]):o.domain([-1,1])),u.domain()[0]===u.domain()[1]&&(u.domain()[0]?u.domain([u.domain()[0]-u.domain()[0]*.01,u.domain()[1]+u.domain()[1]*.01]):u.domain([-1,1])),isNaN(o.domain()[0])&&o.domain([-1,1]),isNaN(u.domain()[0])&&u.domain([-1,1]),P=P||o,H=H||u,B=B||a;var X=U.selectAll("g.nv-wrap.nv-scatter").data([I]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+s+(M?" nv-single-point":"")),$=V.append("defs"),J=V.append("g"),K=X.select("g");J.append("g").attr("class","nv-groups"),J.append("g").attr("class","nv-point-paths"),X.attr("transform","translate("+t.left+","+t.top+")"),$.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),X.select("#nv-edge-clip-"+s+" rect").attr("width",q).attr("height",R>0?R:0),K.attr("clip-path",S?"url(#nv-edge-clip-"+s+")":""),F=!0;var G=X.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});G.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),G.exit().remove(),G.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),G.style("fill",function(e,t){return i(e,t)}).style("stroke",function(e,t){return i(e,t)}).style("stroke-opacity",1).style("fill-opacity",.5);if(p){var Y=G.selectAll("circle.nv-point").data(function(e){return e.values},y);Y.enter().append("circle").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("cx",function(t,n){return e.utils.NaNtoZero(P(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(H(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)}),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)})}else{var Y=G.selectAll("path.nv-point").data(function(e){return e.values});Y.enter().append("path").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("transform",function(e,t){return"translate("+P(f(e,t))+","+H(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))})),Y.exit().remove(),G.exit().selectAll("path.nv-point").attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))}))}clearTimeout(j),j=setTimeout(Q,300),P=o.copy(),H=u.copy(),B=a.copy()}),I}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=d3.scale.linear(),u=d3.scale.linear(),a=d3.scale.linear(),f=function(e){return e.x},l=function(e){return e.y},c=function(e){return e.size||1},h=function(e){return e.shape||"circle"},p=!0,d=[],v=[],m=[],g=!0,y=null,b=function(e){return!e.notActive},w=!1,E=.1,S=!1,x=!0,T=function(){return 25},N=null,C=null,k=null,L=null,A=null,O=null,M=!1,_=d3.dispatch("elementClick","elementMouseover","elementMouseout"),D=!0,P,H,B,j,F=!1;return I.clearHighlights=function(){d3.selectAll(".nv-chart-"+s+" .nv-point.hover").classed("hover",!1)},I.highlightPoint=function(e,t,n){d3.select(".nv-chart-"+s+" .nv-series-"+e+" .nv-point-"+t).classed("hover",n)},_.on("elementMouseover.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!0)}),_.on("elementMouseout.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!1)}),I.dispatch=_,I.options=e.utils.optionsFunc.bind(I),I.x=function(e){return arguments.length?(f=d3.functor(e),I):f},I.y=function(e){return arguments.length?(l=d3.functor(e),I):l},I.size=function(e){return arguments.length?(c=d3.functor(e),I):c},I.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,I):t},I.width=function(e){return arguments.length?(n=e,I):n},I.height=function(e){return arguments.length?(r=e,I):r},I.xScale=function(e){return arguments.length?(o=e,I):o},I.yScale=function(e){return arguments.length?(u=e,I):u},I.zScale=function(e){return arguments.length?(a=e,I):a},I.xDomain=function(e){return arguments.length?(N=e,I):N},I.yDomain=function(e){return arguments.length?(C=e,I):C},I.sizeDomain=function(e){return arguments.length?(A=e,I):A},I.xRange=function(e){return arguments.length?(k=e,I):k},I.yRange=function(e){return arguments.length?(L=e,I):L},I.sizeRange=function(e){return arguments.length?(O=e,I):O},I.forceX=function(e){return arguments.length?(d=e,I):d},I.forceY=function(e){return arguments.length?(v=e,I):v},I.forceSize=function(e){return arguments.length?(m=e,I):m},I.interactive=function(e){return arguments.length?(g=e,I):g},I.pointKey=function(e){return arguments.length?(y=e,I):y},I.pointActive=function(e){return arguments.length?(b=e,I):b},I.padData=function(e){return arguments.length?(w=e,I):w},I.padDataOuter=function(e){return arguments.length?(E=e,I):E},I.clipEdge=function(e){return arguments.length?(S=e,I):S},I.clipVoronoi=function(e){return arguments.length?(x=e,I):x},I.useVoronoi=function(e){return arguments.length?(D=e,D===!1&&(x=!1),I):D},I.clipRadius=function(e){return arguments.length?(T=e,I):T},I.color=function(t){return arguments.length?(i=e.utils.getColor(t),I):i},I.shape=function(e){return arguments.length?(h=e,I):h},I.onlyCircles=function(e){return arguments.length?(p=e,I):p},I.id=function(e){return arguments.length?(s=e,I):s},I.singlePoint=function(e){return arguments.length?(M=e,I):M},I},e.models.scatterChart=function(){function F(e){return e.each(function(e){function J(){if(T)return W.select(".nv-point-paths").style("pointer-events","all"),!1;W.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(x).focus(i[0]),p.distortion(x).focus(i[1]),W.select(".nv-scatterWrap").call(t),b&&W.select(".nv-x.nv-axis").call(n),w&&W.select(".nv-y.nv-axis").call(r),W.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),W.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var C=d3.select(this),k=this,L=(f||parseInt(C.style("width"))||960)-a.left-a.right,D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom;F.update=function(){C.call(F)},F.container=this,A.disabled=e.map(function(e){return!!e.disabled});if(!O){var I;O={};for(I in A)A[I]instanceof Array?O[I]=A[I].slice(0):O[I]=A[I]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var q=C.selectAll(".nv-noData").data([_]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",a.left+L/2).attr("y",a.top+D/2).text(function(e){return e}),F}C.selectAll(".nv-noData").remove(),P=P||h,H=H||p;var R=C.selectAll("g.nv-wrap.nv-scatterChart").data([e]),U=R.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),z=U.append("g"),W=R.select("g");z.append("rect").attr("class","nvd3 nv-background"),z.append("g").attr("class","nv-x nv-axis"),z.append("g").attr("class","nv-y nv-axis"),z.append("g").attr("class","nv-scatterWrap"),z.append("g").attr("class","nv-distWrap"),z.append("g").attr("class","nv-legendWrap"),z.append("g").attr("class","nv-controlsWrap");if(y){var X=S?L/2:L;i.width(X),R.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),D=(l||parseInt(C.style("height"))||400)-a.top-a.bottom),R.select(".nv-legendWrap").attr("transform","translate("+(L-X)+","+ -a.top+")")}S&&(s.width(180).color(["#444"]),W.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -a.top+")").call(s)),R.attr("transform","translate("+a.left+","+a.top+")"),E&&W.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),t.width(L).height(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),d!==0&&t.xDomain(null),v!==0&&t.yDomain(null),R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t);if(d!==0){var V=h.domain()[1]-h.domain()[0];t.xDomain([h.domain()[0]-d*V,h.domain()[1]+d*V])}if(v!==0){var $=p.domain()[1]-p.domain()[0];t.yDomain([p.domain()[0]-v*$,p.domain()[1]+v*$])}(v!==0||d!==0)&&R.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),b&&(n.scale(h).ticks(n.ticks()&&n.ticks().length?n.ticks():L/100).tickSize(-D,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),w&&(r.scale(p).ticks(r.ticks()&&r.ticks().length?r.ticks():D/36).tickSize(-L,0),W.select(".nv-y.nv-axis").call(r)),m&&(o.getData(t.x()).scale(h).width(L).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),W.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),g&&(u.getData(t.y()).scale(p).width(D).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),z.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),W.select(".nv-distributionY").attr("transform","translate("+(E?L:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(W.select(".nv-background").attr("width",L).attr("height",D),W.select(".nv-background").on("mousemove",J),W.select(".nv-background").on("click",function(){T=!T}),t.dispatch.on("elementClick.freezeFisheye",function(){T=!T})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,x=e.disabled?0:2.5,W.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),W.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(x).focus(0),p.distortion(x).focus(0),W.select(".nv-scatterWrap").call(t),W.select(".nv-x.nv-axis").call(n),W.select(".nv-y.nv-axis").call(r)):T=!1,F.update()}),i.dispatch.on("stateChange",function(e){A.disabled=e.disabled,M.stateChange(A),F.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",function(t,n){return e.pos[1]-D}),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],M.tooltipShow(e)}),M.on("tooltipShow",function(e){N&&B(e,k.parentNode)}),M.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),A.disabled=t.disabled),F.update()}),P=h.copy(),H=p.copy()}),F}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=0,v=0,m=!1,g=!1,y=!0,b=!0,w=!0,E=!1,S=!!d3.fisheye,x=0,T=!1,N=!0,C=function(e,t,n){return"<strong>"+t+"</strong>"},k=function(e,t,n){return"<strong>"+n+"</strong>"},L=null,A={},O=null,M=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),_="No Data Available.",D=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(E?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var P,H,B=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));C!=null&&e.tooltip.show([f,l],C(i.series.key,v,m,i,F),"n",1,s,"x-nvtooltip"),k!=null&&e.tooltip.show([c,d],k(i.series.key,v,m,i,F),"e",1,s,"y-nvtooltip"),L!=null&&e.tooltip.show([o,u],L(i.series.key,v,m,i,F),i.value<0?"n":"s",null,s)},j=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){M.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),M.on("tooltipHide",function(){N&&e.tooltip.cleanup()}),F.dispatch=M,F.scatter=t,F.legend=i,F.controls=s,F.xAxis=n,F.yAxis=r,F.distX=o,F.distY=u,d3.rebind(F,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),F.options=e.utils.optionsFunc.bind(F),F.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,F):a},F.width=function(e){return arguments.length?(f=e,F):f},F.height=function(e){return arguments.length?(l=e,F):l},F.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),F):c},F.showDistX=function(e){return arguments.length?(m=e,F):m},F.showDistY=function(e){return arguments.length?(g=e,F):g},F.showControls=function(e){return arguments.length?(S=e,F):S},F.showLegend=function(e){return arguments.length?(y=e,F):y},F.showXAxis=function(e){return arguments.length?(b=e,F):b},F.showYAxis=function(e){return arguments.length?(w=e,F):w},F.rightAlignYAxis=function(e){return arguments.length?(E=e,r.orient(e?"right":"left"),F):E},F.fisheye=function(e){return arguments.length?(x=e,F):x},F.xPadding=function(e){return arguments.length?(d=e,F):d},F.yPadding=function(e){return arguments.length?(v=e,F):v},F.tooltips=function(e){return arguments.length?(N=e,F):N},F.tooltipContent=function(e){return arguments.length?(L=e,F):L},F.tooltipXContent=function(e){return arguments.length?(C=e,F):C},F.tooltipYContent=function(e){return arguments.length?(k=e,F):k},F.state=function(e){return arguments.length?(A=e,F):A},F.defaultState=function(e){return arguments.length?(O=e,F):O},F.noData=function(e){return arguments.length?(_=e,F):_},F.transitionDuration=function(e){return arguments.length?(D=e,F):D},F},e.models.scatterPlusLineChart=function(){function B(e){return e.each(function(e){function V(){if(S)return U.select(".nv-point-paths").style("pointer-events","all"),!1;U.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(E).focus(i[0]),p.distortion(E).focus(i[1]),U.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),g&&U.select(".nv-x.nv-axis").call(n),y&&U.select(".nv-y.nv-axis").call(r),U.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),U.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var T=d3.select(this),N=this,C=(f||parseInt(T.style("width"))||960)-a.left-a.right,M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom;B.update=function(){T.call(B)},B.container=this,k.disabled=e.map(function(e){return!!e.disabled});if(!L){var j;L={};for(j in k)k[j]instanceof Array?L[j]=k[j].slice(0):L[j]=k[j]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var F=T.selectAll(".nv-noData").data([O]);return F.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),F.attr("x",a.left+C/2).attr("y",a.top+M/2).text(function(e){return e}),B}T.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale(),_=_||h,D=D||p;var I=T.selectAll("g.nv-wrap.nv-scatterChart").data([e]),q=I.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),R=q.append("g"),U=I.select("g");R.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-scatterWrap"),R.append("g").attr("class","nv-regressionLinesWrap"),R.append("g").attr("class","nv-distWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),I.attr("transform","translate("+a.left+","+a.top+")"),b&&U.select(".nv-y.nv-axis").attr("transform","translate("+C+",0)"),m&&(i.width(C/2),I.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),M=(l||parseInt(T.style("height"))||400)-a.top-a.bottom),I.select(".nv-legendWrap").attr("transform","translate("+C/2+","+ -a.top+")")),w&&(s.width(180).color(["#444"]),U.select(".nv-controlsWrap").datum(H).attr("transform","translate(0,"+ -a.top+")").call(s)),t.width(C).height(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),I.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),I.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+t.id()+")");var z=I.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(e){return e});z.enter().append("g").attr("class","nv-regLines");var W=z.selectAll(".nv-regLine").data(function(e){return[e]}),X=W.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0);W.attr("x1",h.range()[0]).attr("x2",h.range()[1]).attr("y1",function(e,t){return p(h.domain()[0]*e.slope+e.intercept)}).attr("y2",function(e,t){return p(h.domain()[1]*e.slope+e.intercept)}).style("stroke",function(e,t,n){return c(e,n)}).style("stroke-opacity",function(e,t){return e.disabled||typeof e.slope=="undefined"||typeof e.intercept=="undefined"?0:1}),g&&(n.scale(h).ticks(n.ticks()?n.ticks():C/100).tickSize(-M,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),y&&(r.scale(p).ticks(r.ticks()?r.ticks():M/36).tickSize(-C,0),U.select(".nv-y.nv-axis").call(r)),d&&(o.getData(t.x()).scale(h).width(C).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),U.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),v&&(u.getData(t.y()).scale(p).width(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),U.select(".nv-distributionY").attr("transform","translate("+(b?C:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(U.select(".nv-background").attr("width",C).attr("height",M),U.select(".nv-background").on("mousemove",V),U.select(".nv-background").on("click",function(){S=!S}),t.dispatch.on("elementClick.freezeFisheye",function(){S=!S})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,E=e.disabled?0:2.5,U.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),U.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(E).focus(0),p.distortion(E).focus(0),U.select(".nv-scatterWrap").call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r)):S=!1,B.update()}),i.dispatch.on("stateChange",function(e){k=e,A.stateChange(k),B.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-M),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],A.tooltipShow(e)}),A.on("tooltipShow",function(e){x&&P(e,N.parentNode)}),A.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),k.disabled=t.disabled),B.update()}),_=h.copy(),D=p.copy()}),B}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=!1,v=!1,m=!0,g=!0,y=!0,b=!1,w=!!d3.fisheye,E=0,S=!1,x=!0,T=function(e,t,n){return"<strong>"+t+"</strong>"},N=function(e,t,n){return"<strong>"+n+"</strong>"},C=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+r+"</p>"},k={},L=null,A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),O="No Data Available.",M=0;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(b?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var _,D,P=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));T!=null&&e.tooltip.show([f,l],T(i.series.key,v,m,i,B),"n",1,s,"x-nvtooltip"),N!=null&&e.tooltip.show([c,d],N(i.series.key,v,m,i,B),"e",1,s,"y-nvtooltip"),C!=null&&e.tooltip.show([o,u],C(i.series.key,v,m,i.point.tooltip,i,B),i.value<0?"n":"s",null,s)},H=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){A.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),A.on("tooltipHide",function(){x&&e.tooltip.cleanup()}),B.dispatch=A,B.scatter=t,B.legend=i,B.controls=s,B.xAxis=n,B.yAxis=r,B.distX=o,B.distY=u,d3.rebind(B,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),B.options=e.utils.optionsFunc.bind(B),B.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,B):a},B.width=function(e){return arguments.length?(f=e,B):f},B.height=function(e){return arguments.length?(l=e,B):l},B.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),B):c},B.showDistX=function(e){return arguments.length?(d=e,B):d},B.showDistY=function(e){return arguments.length?(v=e,B):v},B.showControls=function(e){return arguments.length?(w=e,B):w},B.showLegend=function(e){return arguments.length?(m=e,B):m},B.showXAxis=function(e){return arguments.length?(g=e,B):g},B.showYAxis=function(e){return arguments.length?(y=e,B):y},B.rightAlignYAxis=function(e){return arguments.length?(b=e,r.orient(e?"right":"left"),B):b},B.fisheye=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(x=e,B):x},B.tooltipContent=function(e){return arguments.length?(C=e,B):C},B.tooltipXContent=function(e){return arguments.length?(T=e,B):T},B.tooltipYContent=function(e){return arguments.length?(N=e,B):N},B.state=function(e){return arguments.length?(k=e,B):k},B.defaultState=function(e){return arguments.length?(L=e,B):L},B.noData=function(e){return arguments.length?(O=e,B):O},B.transitionDuration=function(e){return arguments.length?(M=e,B):M},B},e.models.sparkline=function(){function d(e){return e.each(function(e){var i=n-t.left-t.right,d=r-t.top-t.bottom,v=d3.select(this);s.domain(l||d3.extent(e,u)).range(h||[0,i]),o.domain(c||d3.extent(e,a)).range(p||[d,0]);var m=v.selectAll("g.nv-wrap.nv-sparkline").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline"),b=g.append("g"),w=m.select("g");m.attr("transform","translate("+t.left+","+t.top+")");var E=m.selectAll("path").data(function(e){return[e]});E.enter().append("path"),E.exit().remove(),E.style("stroke",function(e,t){return e.color||f(e,t)}).attr("d",d3.svg.line().x(function(e,t){return s(u(e,t))}).y(function(e,t){return o(a(e,t))}));var S=m.selectAll("circle.nv-point").data(function(e){function n(t){if(t!=-1){var n=e[t];return n.pointIndex=t,n}return null}var t=e.map(function(e,t){return a(e,t)}),r=n(t.lastIndexOf(o.domain()[1])),i=n(t.indexOf(o.domain()[0])),s=n(t.length-1);return[i,r,s].filter(function(e){return e!=null})});S.enter().append("circle"),S.exit().remove(),S.attr("cx",function(e,t){return s(u(e,e.pointIndex))}).attr("cy",function(e,t){return o(a(e,e.pointIndex))}).attr("r",2).attr("class",function(e,t){return u(e,e.pointIndex)==s.domain()[1]?"nv-point nv-currentValue":a(e,e.pointIndex)==o.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),d}var t={top:2,right:0,bottom:2,left:0},n=400,r=32,i=!0,s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=e.utils.getColor(["#000"]),l,c,h,p;return d.options=e.utils.optionsFunc.bind(d),d.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,d):t},d.width=function(e){return arguments.length?(n=e,d):n},d.height=function(e){return arguments.length?(r=e,d):r},d.x=function(e){return arguments.length?(u=d3.functor(e),d):u},d.y=function(e){return arguments.length?(a=d3.functor(e),d):a},d.xScale=function(e){return arguments.length?(s=e,d):s},d.yScale=function(e){return arguments.length?(o=e,d):o},d.xDomain=function(e){return arguments.length?(l=e,d):l},d.yDomain=function(e){return arguments.length?(c=e,d):c},d.xRange=function(e){return arguments.length?(h=e,d):h},d.yRange=function(e){return arguments.length?(p=e,d):p},d.animate=function(e){return arguments.length?(i=e,d):i},d.color=function(t){return arguments.length?(f=e.utils.getColor(t),d):f},d},e.models.sparklinePlus=function(){function v(e){return e.each(function(c){function O(){if(a)return;var e=C.selectAll(".nv-hoverValue").data(u),r=e.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);e.exit().style("stroke-opacity",0).style("fill-opacity",0).remove(),e.attr("transform",function(e){return"translate("+s(t.x()(c[e],e))+",0)"}).style("stroke-opacity",1).style("fill-opacity",1);if(!u.length)return;r.append("line").attr("x1",0).attr("y1",-n.top).attr("x2",0).attr("y2",b),r.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-n.top).attr("text-anchor","end").attr("dy",".9em"),C.select(".nv-hoverValue .nv-xValue").text(f(t.x()(c[u[0]],u[0]))),r.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-n.top).attr("text-anchor","start").attr("dy",".9em"),C.select(".nv-hoverValue .nv-yValue").text(l(t.y()(c[u[0]],u[0])))}function M(){function r(e,n){var r=Math.abs(t.x()(e[0],0)-n),i=0;for(var s=0;s<e.length;s++)Math.abs(t.x()(e[s],s)-n)<r&&(r=Math.abs(t.x()(e[s],s)-n),i=s);return i}if(a)return;var e=d3.mouse(this)[0]-n.left;u=[r(c,Math.round(s.invert(e)))],O()}var m=d3.select(this),g=(r||parseInt(m.style("width"))||960)-n.left-n.right,b=(i||parseInt(m.style("height"))||400)-n.top-n.bottom;v.update=function(){v(e)},v.container=this;if(!c||!c.length){var w=m.selectAll(".nv-noData").data([d]);return w.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),w.attr("x",n.left+g/2).attr("y",n.top+b/2).text(function(e){return e}),v}m.selectAll(".nv-noData").remove();var E=t.y()(c[c.length-1],c.length-1);s=t.xScale(),o=t.yScale();var S=m.selectAll("g.nv-wrap.nv-sparklineplus").data([c]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-sparklineWrap"),N.append("g").attr("class","nv-valueWrap"),N.append("g").attr("class","nv-hoverArea"),S.attr("transform","translate("+n.left+","+n.top+")");var k=C.select(".nv-sparklineWrap");t.width(g).height(b),k.call(t);var L=C.select(".nv-valueWrap"),A=L.selectAll(".nv-currentValue").data([E]);A.enter().append("text").attr("class","nv-currentValue").attr("dx",p?-8:8).attr("dy",".9em").style("text-anchor",p?"end":"start"),A.attr("x",g+(p?n.right:0)).attr("y",h?function(e){return o(e)}:0).style("fill",t.color()(c[c.length-1],c.length-1)).text(l(E)),N.select(".nv-hoverArea").append("rect").on("mousemove",M).on("click",function(){a=!a}).on("mouseout",function(){u=[],O()}),C.select(".nv-hoverArea rect").attr("transform",function(e){return"translate("+ -n.left+","+ -n.top+")"}).attr("width",g+n.left+n.right).attr("height",b+n.top)}),v}var t=e.models.sparkline(),n={top:15,right:100,bottom:10,left:50},r=null,i=null,s,o,u=[],a=!1,f=d3.format(",r"),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d="No Data Available.";return v.sparkline=t,d3.rebind(v,t,"x","y","xScale","yScale","color"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,v):n},v.width=function(e){return arguments.length?(r=e,v):r},v.height=function(e){return arguments.length?(i=e,v):i},v.xTickFormat=function(e){return arguments.length?(f=e,v):f},v.yTickFormat=function(e){return arguments.length?(l=e,v):l},v.showValue=function(e){return arguments.length?(c=e,v):c},v.alignValue=function(e){return arguments.length?(h=e,v):h},v.rightAlignValue=function(e){return arguments.length?(p=e,v):p},v.noData=function(e){return arguments.length?(d=e,v):d},v},e.models.stackedArea=function(){function g(e){return e.each(function(e){var a=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);p=v.xScale(),d=v.yScale();var E=e;e.forEach(function(e,t){e.seriesIndex=t,e.values=e.values.map(function(e,n){return e.index=n,e.seriesIndex=t,e})});var S=e.filter(function(e){return!e.disabled});e=d3.layout.stack().order(l).offset(f).values(function(e){return e.values}).x(o).y(u).out(function(e,t,n){var r=u(e)===0?0:n;e.display={y:r,y0:t}})(S);var T=w.selectAll("g.nv-wrap.nv-stackedarea").data([e]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),C=N.append("defs"),k=N.append("g"),L=T.select("g");k.append("g").attr("class","nv-areaWrap"),k.append("g").attr("class","nv-scatterWrap"),T.attr("transform","translate("+t.left+","+t.top+")"),v.width(a).height(b).x(o).y(function(e){return e.display.y+e.display.y0}).forceY([0]).color(e.map(function(e,t){return e.color||i(e,e.seriesIndex)}));var A=L.select(".nv-scatterWrap").datum(e);A.call(v),C.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),T.select("#nv-edge-clip-"+s+" rect").attr("width",a).attr("height",b),L.attr("clip-path",h?"url(#nv-edge-clip-"+s+")":"");var O=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y+e.display.y0)}).interpolate(c),M=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y0)}),_=L.select(".nv-areaWrap").selectAll("path.nv-area").data(function(e){return e});_.enter().append("path").attr("class",function(e,t){return"nv-area nv-area-"+t}).attr("d",function(e,t){return M(e.values,e.seriesIndex)}).on("mouseover",function(e,t){d3.select(this).classed("hover",!0),m.areaMouseover({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),m.areaMouseout({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}).on("click",function(e,t){d3.select(this).classed("hover",!1),m.areaClick({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:e.seriesIndex})}),_.exit().remove(),_.style("fill",function(e,t){return e.color||i(e,e.seriesIndex)}).style("stroke",function(e,t){return e.color||i(e,e.seriesIndex)}),_.attr("d",function(e,t){return O(e.values,t)}),v.dispatch.on("elementMouseover.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!0)}),v.dispatch.on("elementMouseout.area",function(e){L.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!1)}),g.d3_stackedOffset_stackPercent=function(e){var t=e.length,n=e[0].length,r=1/t,i,s,o,a=[];for(s=0;s<n;++s){for(i=0,o=0;i<E.length;i++)o+=u(E[i].values[s]);if(o)for(i=0;i<t;i++)e[i][s][1]/=o;else for(i=0;i<t;i++)e[i][s][1]=r}for(s=0;s<n;++s)a[s]=0;return a}}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=function(e){return e.x},u=function(e){return e.y},a="stack",f="zero",l="default",c="linear",h=!1,p,d,v=e.models.scatter(),m=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout");return v.size(2.2).sizeDomain([2.2,2.2]),v.dispatch.on("elementClick.area",function(e){m.areaClick(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],m.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){m.tooltipHide(e)}),g.dispatch=m,g.scatter=v,d3.rebind(g,v,"interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","highlightPoint","clearHighlights"),g.options=e.utils.optionsFunc.bind(g),g.x=function(e){return arguments.length?(o=d3.functor(e),g):o},g.y=function(e){return arguments.length?(u=d3.functor(e),g):u},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.clipEdge=function(e){return arguments.length?(h=e,g):h},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),g):i},g.offset=function(e){return arguments.length?(f=e,g):f},g.order=function(e){return arguments.length?(l=e,g):l},g.style=function(e){if(!arguments.length)return a;a=e;switch(a){case"stack":g.offset("zero"),g.order("default");break;case"stream":g.offset("wiggle"),g.order("inside-out");break;case"stream-center":g.offset("silhouette"),g.order("inside-out");break;case"expand":g.offset("expand"),g.order("default");break;case"stack_percent":g.offset(g.d3_stackedOffset_stackPercent),g.order("default")}return g},g.interpolate=function(e){return arguments.length?(c=e,g):c},g},e.models.stackedAreaChart=function(){function M(y){return y.each(function(y){var A=d3.select(this),_=this,D=(a||parseInt(A.style("width"))||960)-u.left-u.right,P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom;M.update=function(){A.call(M)},M.container=this,S.disabled=y.map(function(e){return!!e.disabled});if(!x){var H;x={};for(H in S)S[H]instanceof Array?x[H]=S[H].slice(0):x[H]=S[H]}if(!y||!y.length||!y.filter(function(e){return e.values.length}).length){var B=A.selectAll(".nv-noData").data([T]);return B.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),B.attr("x",u.left+D/2).attr("y",u.top+P/2).text(function(e){return e}),M}A.selectAll(".nv-noData").remove(),b=t.xScale(),w=t.yScale();var j=A.selectAll("g.nv-wrap.nv-stackedAreaChart").data([y]),F=j.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),I=j.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-stackedWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-controlsWrap"),F.append("g").attr("class","nv-interactive"),I.select("rect").attr("width",D).attr("height",P);if(h){var q=c?D-C:D;i.width(q),I.select(".nv-legendWrap").datum(y).call(i),u.top!=i.height()&&(u.top=i.height(),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-legendWrap").attr("transform","translate("+(D-q)+","+ -u.top+")")}if(c){var R=[{key:L.stacked||"Stacked",metaKey:"Stacked",disabled:t.style()!="stack",style:"stack"},{key:L.stream||"Stream",metaKey:"Stream",disabled:t.style()!="stream",style:"stream"},{key:L.expanded||"Expanded",metaKey:"Expanded",disabled:t.style()!="expand",style:"expand"},{key:L.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:t.style()!="stack_percent",style:"stack_percent"}];C=k.length/3*260,R=R.filter(function(e){return k.indexOf(e.metaKey)!==-1}),s.width(C).color(["#444","#444","#444"]),I.select(".nv-controlsWrap").datum(R).call(s),u.top!=Math.max(s.height(),i.height())&&(u.top=Math.max(s.height(),i.height()),P=(f||parseInt(A.style("height"))||400)-u.top-u.bottom),I.select(".nv-controlsWrap").attr("transform","translate(0,"+ -u.top+")")}j.attr("transform","translate("+u.left+","+u.top+")"),v&&I.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),m&&(o.width(D).height(P).margin({left:u.left,top:u.top}).svgContainer(A).xScale(b),j.select(".nv-interactive").call(o)),t.width(D).height(P);var U=I.select(".nv-stackedWrap").datum(y);U.call(t),p&&(n.scale(b).ticks(D/100).tickSize(-P,0),I.select(".nv-x.nv-axis").attr("transform","translate(0,"+P+")"),I.select(".nv-x.nv-axis").call(n)),d&&(r.scale(w).ticks(t.offset()=="wiggle"?0:P/36).tickSize(-D,0).setTickFormat(t.style()=="expand"||t.style()=="stack_percent"?d3.format("%"):E),I.select(".nv-y.nv-axis").call(r)),t.dispatch.on("areaClick.toggle",function(e){y.filter(function(e){return!e.disabled}).length===1?y.forEach(function(e){e.disabled=!1}):y.forEach(function(t,n){t.disabled=n!=e.seriesIndex}),S.disabled=y.map(function(e){return!!e.disabled}),N.stateChange(S),M.update()}),i.dispatch.on("stateChange",function(e){S.disabled=e.disabled,N.stateChange(S),M.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;R=R.map(function(e){return e.disabled=!0,e}),e.disabled=!1,t.style(e.style),S.style=t.style(),N.stateChange(S),M.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,a,f,c=[];y.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){a=e.interactiveBisect(n.values,i.pointXValue,M.x()),t.highlightPoint(r,a,!0);var o=n.values[a];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof f=="undefined"&&(f=M.xScale()(M.x()(o,a)));var u=t.style()=="expand"?o.display.y:M.y()(o,a);c.push({key:n.key,value:u,color:l(n,n.seriesIndex),stackedValue:o.display})}),c.reverse();if(c.length>2){var h=M.yScale().invert(i.mouseY),p=Infinity,d=null;c.forEach(function(e,t){h=Math.abs(h);var n=Math.abs(e.stackedValue.y0),r=Math.abs(e.stackedValue.y);if(h>=n&&h<=r+n){d=t;return}}),d!=null&&(c[d].highlight=!0)}var v=n.tickFormat()(M.x()(s,a)),m=t.style()=="expand"?function(e,t){return d3.format(".1%")(e)}:function(e,t){return r.tickFormat()(e)};o.tooltip.position({left:f+u.left,top:i.mouseY+u.top}).chartContainer(_.parentNode).enabled(g).valueFormatter(m).data({value:v,series:c})(),o.renderGuideLine(f)}),o.dispatch.on("elementMouseout",function(e){N.tooltipHide(),t.clearHighlights()}),N.on("tooltipShow",function(e){g&&O(e,_.parentNode)}),N.on("changeState",function(e){typeof e.disabled!="undefined"&&y.length===e.disabled.length&&(y.forEach(function(t,n){t.disabled=e.disabled[n]}),S.disabled=e.disabled),typeof e.style!="undefined"&&t.style(e.style),M.update()})}),M}var t=e.models.stackedArea(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:25,bottom:50,left:60},a=null,f=null,l=e.utils.defaultColor(),c=!0,h=!0,p=!0,d=!0,v=!1,m=!1,g=!0,y=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},b,w,E=d3.format(",.2f"),S={style:t.style()},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=250,k=["Stacked","Stream","Expanded"],L={},A=0;n.orient("bottom").tickPadding(7),r.orient(v?"right":"left"),s.updateState(!1);var O=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=y(i.series.key,a,f,i,M);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("tooltipShow",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],N.tooltipShow(e)}),t.dispatch.on("tooltipHide",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){g&&e.tooltip.cleanup()}),M.dispatch=N,M.stacked=t,M.legend=i,M.controls=s,M.xAxis=n,M.yAxis=r,M.interactiveLayer=o,d3.rebind(M,t,"x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","sizeDomain","interactive","useVoronoi","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),M.options=e.utils.optionsFunc.bind(M),M.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,M):u},M.width=function(e){return arguments.length?(a=e,M):a},M.height=function(e){return arguments.length?(f=e,M):f},M.color=function(n){return arguments.length?(l=e.utils.getColor(n),i.color(l),t.color(l),M):l},M.showControls=function(e){return arguments.length?(c=e,M):c},M.showLegend=function(e){return arguments.length?(h=e,M):h},M.showXAxis=function(e){return arguments.length?(p=e,M):p},M.showYAxis=function(e){return arguments.length?(d=e,M):d},M.rightAlignYAxis=function(e){return arguments.length?(v=e,r.orient(e?"right":"left"),M):v},M.useInteractiveGuideline=function(e){return arguments.length?(m=e,e===!0&&(M.interactive(!1),M.useVoronoi(!1)),M):m},M.tooltip=function(e){return arguments.length?(y=e,M):y},M.tooltips=function(e){return arguments.length?(g=e,M):g},M.tooltipContent=function(e){return arguments.length?(y=e,M):y},M.state=function(e){return arguments.length?(S=e,M):S},M.defaultState=function(e){return arguments.length?(x=e,M):x},M.noData=function(e){return arguments.length?(T=e,M):T},M.transitionDuration=function(e){return arguments.length?(A=e,M):A},M.controlsData=function(e){return arguments.length?(k=e,M):k},M.controlLabels=function(e){return arguments.length?typeof e!="object"?L:(L=e,M):L},r.setTickFormat=r.tickFormat,r.tickFormat=function(e){return arguments.length?(E=e,r):E},M}}(),define("plugin/plugins/nvd3/nv.d3",function(){}),define("plugin/charts/nvd3/common/config",["plugin/charts/forms/default","plugin/plugins/nvd3/nv.d3"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"NVD3",tag:"svg",keywords:"small"})}),define("plugin/charts/nvd3/bar/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/bar_horizontal_stacked/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stacked horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}},columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/line_focus/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus",category:"Others",zoomable:"native",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/pie/config",["plugin/plugins/nvd3/nv.d3"],function(){return $.extend(!0,{},{title:"Pie chart",category:"Area charts",library:"NVD3",tag:"svg",keywords:"small",columns:{label:{title:"Labels",is_label:!0,is_auto:!0},y:{title:"Values",is_numeric:!0}},settings:{main_separator:{type:"separator",title:"Pie chart settings"},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"radiobutton",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},use_panels:{init:"true",hide:!0}}})}),define("plugin/charts/nvd3/stackedarea_full/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Expanded",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea_stream/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Stream",category:"Area charts",zoomable:!0,keywords:"default small",showmaxmin:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/histogram/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogram",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{x_axis_label:{init:"Values"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_precision:{init:".2"}}})}),define("plugin/charts/nvd3/line/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/scatter/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",zoomable:!0,columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/nvd3/stackedarea/config",["plugin/charts/nvd3/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",zoomable:!0,category:"Area charts",keywords:"default small",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/common/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"",category:"",library:"jqPlot",tag:"div",zoomable:!0,keywords:"medium",settings:{separator_grid:{title:"Grids",type:"separator"},x_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the X axis?",type:"radiobutton",init:"false",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]},y_axis_grid:{title:"Axis grid",info:"Would you like to show grid lines for the Y axis?",type:"radiobutton",init:"true",data:[{label:"On",value:"true"},{label:"Off",value:"false"}]}}})}),define("plugin/charts/jqplot/bar/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/line/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others",columns:{x:{title:"Values for x-axis",is_label:!0,is_auto:!0,is_unique:!0},y:{title:"Values for y-axis",is_numeric:!0}}})}),define("plugin/charts/jqplot/scatter/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",columns:{x:{title:"Values for x-axis",is_numeric:!0},y:{title:"Values for y-axis",is_numeric:!0}},settings:{x_axis_grid:{init:"true"}}})}),define("plugin/charts/jqplot/boxplot/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Box plot",category:"Data processing (requires 'charts' tool from Toolshed)",library:"jqPlot",tag:"div",execute:"boxplot",keywords:"small medium large",columns:{y:{title:"Observations",is_numeric:!0}},settings:{show_legend:{init:"false"}}})}),define("plugin/charts/jqplot/histogram_discrete/config",["plugin/charts/jqplot/common/config"],function(e){return $.extend(!0,{},e,{title:"Discrete Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogramdiscrete",keywords:"small medium large",columns:{x:{title:"Observations",is_label:!0}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"}}})}),define("plugin/charts/others/heatmap/config",["plugin/charts/forms/default"],function(e){return $.extend(!0,{},e,{title:"Heatmap",category:"Others",library:"Custom",tag:"svg",keywords:"small",zoomable:!0,columns:{x:{title:"Column labels",is_label:!0,is_numeric:!0,is_unique:!0},y:{title:"Row labels",is_label:!0,is_numeric:!0,is_unique:!0},z:{title:"Observation",is_numeric:!0}},settings:{use_panels:{init:"true",hide:!0},color_set:{title:"Color scheme",info:"Select a color scheme for your heatmap",type:"select",init:"jet",data:[{label:"Cold-to-Hot",value:"hot"},{label:"Cool",value:"cool"},{label:"Copper",value:"copper"},{label:"Gray scale",value:"gray"},{label:"Jet",value:"jet"},{label:"No-Green",value:"no_green"},{label:"Ocean",value:"ocean"},{label:"Polar",value:"polar"},{label:"Red-to-Green",value:"redgreen"},{label:"Red-to-green (saturated)",value:"red2green"},{label:"Relief",value:"relief"},{label:"Seismograph",value:"seis"},{label:"Sealand",value:"sealand"},{label:"Split",value:"split"},{label:"Wysiwyg",value:"wysiwyg"}]},url_template:{title:"Url template",info:"Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.",type:"text",init:"",placeholder:"http://someurl.com?id=__LABEL__"}}})}),define("plugin/charts/others/heatmap_cluster/config",["plugin/charts/others/heatmap/config"],function(e){return $.extend(!0,{},e,{title:"Clustered Heatmap",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"heatmap",keywords:"small medium large"})}),define("plugin/charts/types",["plugin/charts/nvd3/bar/config","plugin/charts/nvd3/bar_stacked/config","plugin/charts/nvd3/bar_horizontal/config","plugin/charts/nvd3/bar_horizontal_stacked/config","plugin/charts/nvd3/line_focus/config","plugin/charts/nvd3/pie/config","plugin/charts/nvd3/stackedarea_full/config","plugin/charts/nvd3/stackedarea_stream/config","plugin/charts/nvd3/histogram/config","plugin/charts/nvd3/line/config","plugin/charts/nvd3/scatter/config","plugin/charts/nvd3/stackedarea/config","plugin/charts/jqplot/bar/config","plugin/charts/jqplot/line/config","plugin/charts/jqplot/scatter/config","plugin/charts/jqplot/boxplot/config","plugin/charts/jqplot/histogram_discrete/config","plugin/charts/others/heatmap/config","plugin/charts/others/heatmap_cluster/config"],function(e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y){return Backbone.Model.extend({defaults:{nvd3_bar:e,nvd3_bar_stacked:t,nvd3_bar_horizontal:n,nvd3_bar_horizontal_stacked:r,nvd3_line_focus:i,nvd3_stackedarea:c,nvd3_stackedarea_full:o,nvd3_stackedarea_stream:u,nvd3_pie:s,nvd3_line:f,nvd3_scatter:l,nvd3_histogram:a,jqplot_bar:h,jqplot_histogram_discrete:m,jqplot_line:p,jqplot_scatter:d,jqplot_boxplot:v,others_heatmap:g,others_heatmap_cluster:y}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","mvc/ui/ui-misc","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","utils/deferred","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c,h){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new l,this.types=new h,this.chart=new c,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.deferred=new u,this.viewer_view=new a(this),this.editor_view=new f(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el);if(!this.storage.load())this.go("editor");else{this.go("viewer");var n=this;this.deferred.execute(function(){n.chart.trigger("redraw")})}},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},chartPath:function(e){var t=e.split(/_(.+)/);return t.length>=2?t[0]+"/"+t[1]:(console.debug("FAILED App:chartPath() - Invalid format: "+e),undefined)}})});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -46,6 +46,7 @@
self.refresh_on_change_values = []
self.name = input_source.get("name")
self.type = input_source.get("type")
+ self.hidden = input_source.get("hidden", False)
self.label = input_source.parse_label()
self.help = input_source.parse_help()
sanitizer_elem = input_source.parse_sanitizer_elem()
@@ -213,6 +214,7 @@
tool_dict[ 'model_class' ] = self.__class__.__name__
tool_dict[ 'optional' ] = self.optional
+ tool_dict[ 'hidden' ] = self.hidden
if hasattr( self, 'value' ):
tool_dict[ 'value' ] = self.value
return tool_dict
@@ -630,6 +632,7 @@
input_source = ensure_input_source( input_source )
ToolParameter.__init__( self, tool, input_source )
self.value = input_source.get( 'value' )
+ self.hidden = True
def get_html_field( self, trans=None, value=None, other_values={} ):
return form_builder.HiddenField( self.name, self.value )
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -1089,7 +1089,11 @@
if ( this.active_node != node ) {
this.check_changes_in_active_form();
this.clear_active_node();
- parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ if (parent.__NEWTOOLFORM__) {
+ parent.show_form_for_tool( node.form_html, node );
+ } else {
+ parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ }
node.make_active();
this.active_node = node;
}
@@ -1099,7 +1103,11 @@
if ( this.active_node == node && (!parent.__NEWTOOLFORM__ || force)) {
// Reactive with new form_html
this.check_changes_in_active_form(); //Force changes to be saved even on new connection (previously dumped)
- parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ if (parent.__NEWTOOLFORM__) {
+ parent.show_form_for_tool( node.form_html, node );
+ } else {
+ parent.show_form_for_tool( node.form_html + node.tooltip, node );
+ }
}
},
layout : function () {
@@ -1305,13 +1313,6 @@
return node;
}
-function update_node( data ) {
- var node = workflow.active_node;
- if (node) {
- node.update_field_data(data, true);
- }
-}
-
var ext_to_type = null;
var type_to_type = null;
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/mvc/tools/tools-form-base.js
--- a/static/scripts/mvc/tools/tools-form-base.js
+++ b/static/scripts/mvc/tools/tools-form-base.js
@@ -276,6 +276,11 @@
buttons : this.buttons
});
+ // remove padding
+ if (this.options.workflow) {
+ this.portlet.$content.css('padding', '0px');
+ }
+
// append message
this.portlet.append(this.message.$el, true);
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/mvc/tools/tools-form-workflow.js
--- a/static/scripts/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/mvc/tools/tools-form-workflow.js
@@ -7,8 +7,199 @@
// create form view
var View = ToolFormBase.extend({
initialize: function(options) {
+ // link with node representation in workflow module
+ this.node = workflow.active_node;
+ if (!this.node) {
+ console.debug('FAILED - tools-form-workflow:initialize() - Node not found in workflow.');
+ return;
+ }
+
+ // initialize parameters
this.workflow = true;
- ToolFormBase.prototype.initialize.call(this, options);
+ this.options = options;
+
+ // load extension
+ var self = this;
+ Utils.get({
+ url : galaxy_config.root + 'api/datatypes',
+ cache : true,
+ success : function(datatypes) {
+ self.datatypes = datatypes;
+ self._makeSections(options.inputs);
+ ToolFormBase.prototype.initialize.call(self, options);
+ }
+ });
+ },
+
+ /** Builds all sub sections
+ */
+ _makeSections: function(inputs){
+ // for annotation
+ inputs[Utils.uuid()] = {
+ label : 'Edit Step Attributes',
+ type : 'section',
+ inputs : [{
+ label : 'Annotation / Notes',
+ name : 'annotation',
+ type : 'text',
+ area : true,
+ help : 'Add an annotation or notes to this step; annotations are available when a workflow is viewed.',
+ value : this.node.annotation
+ }]
+ }
+
+ // for actions
+ this.post_job_actions = this.node.post_job_actions;
+ for (var i in this.node.output_terminals) {
+ inputs[Utils.uuid()] = this._makeSection(i);
+ }
+ },
+
+ /** Builds sub section with step actions/annotation
+ */
+ _makeSection: function(output_id){
+ // format datatypes
+ var extensions = [];
+ for (key in this.datatypes) {
+ extensions.push({
+ 0 : this.datatypes[key],
+ 1 : this.datatypes[key]
+ });
+ }
+
+ // sort extensions
+ extensions.sort(function(a, b) {
+ return a.label > b.label ? 1 : a.label < b.label ? -1 : 0;
+ });
+
+ // add additional options
+ extensions.unshift({
+ 0 : 'Sequences',
+ 1 : 'Sequences'
+ });
+ extensions.unshift({
+ 0 : 'Roadmaps',
+ 1 : 'Roadmaps'
+ });
+ extensions.unshift({
+ 0 : 'Leave unchanged',
+ 1 : 'None'
+ });
+
+ // create custom sub section
+ var input_config = {
+ label : 'Edit Step Action: \'' + output_id + '\'',
+ type : 'section',
+ inputs : [{
+ action : 'RenameDatasetAction',
+ argument : 'newname',
+ label : 'Rename dataset',
+ type : 'text',
+ value : '',
+ ignore : '',
+ help : 'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'
+ },{
+ action : 'ChangeDatatypeAction',
+ argument : 'newtype',
+ label : 'Change datatype',
+ type : 'select',
+ ignore : 'None',
+ options : extensions,
+ help : 'This action will change the datatype of the output to the indicated value.'
+ },{
+ action : 'TagDatasetAction',
+ argument : 'tags',
+ label : 'Tags',
+ type : 'text',
+ value : '',
+ ignore : '',
+ help : 'This action will set tags for the dataset.'
+ },{
+ label : 'Assign columns',
+ type : 'section',
+ inputs : [{
+ action : 'ColumnSetAction',
+ argument : 'chromCol',
+ label : 'Chrom column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'startCol',
+ label : 'Start column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'endCol',
+ label : 'End column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'strandCol',
+ label : 'Strand column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ },{
+ action : 'ColumnSetAction',
+ argument : 'nameCol',
+ label : 'Name column',
+ type : 'text',
+ value : '',
+ ignore : ''
+ }],
+ help : 'This action will set column assignments in the output dataset. Blank fields are ignored.'
+ },{
+ action : 'EmailAction',
+ label : 'Email notification',
+ type : 'boolean',
+ value : 'false',
+ ignore : 'false',
+ help : 'This action will send an email notifying you when the job is done.'
+ },{
+ action : 'DeleteIntermediatesAction',
+ label : 'Delete non-outputs',
+ type : 'boolean',
+ value : 'false',
+ ignore : 'false',
+ help : 'All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect.'
+ }]
+ };
+
+ // visit input nodes and enrich by name/value pairs from server data
+ var self = this;
+ function visit (inputs) {
+ for (var i in inputs) {
+ var input = inputs[i];
+ if (input.action) {
+ input.name = 'pja__' + output_id + '__' + input.action;
+ if (input.argument) {
+ input.name += '__' + input.argument;
+ }
+ var d = self.post_job_actions[input.action + output_id];
+ if (d) {
+ if (input.argument) {
+ input.value = d.action_arguments && d.action_arguments[input.argument] || input.value;
+ } else {
+ input.value = 'true';
+ }
+ }
+ } else {
+ if (input.inputs) {
+ visit(input.inputs);
+ }
+ }
+ }
+ }
+ visit(input_config.inputs);
+
+ // return final configuration
+ return input_config;
},
/** Builds a new model through api call and recreates the entire form
@@ -38,15 +229,16 @@
type : 'GET',
url : model_url,
data : current_state,
- success : function(node) {
- parent.update_node(node);
+ success : function(data) {
+ // update node in workflow module
+ self.node.update_field_data(data, true);
// process completed
self.deferred.done(process_id);
// log success
console.debug('tools-form::_refreshForm() - States refreshed.');
- console.debug(node);
+ console.debug(data);
},
error : function(response) {
// process completed
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/mvc/tools/tools-section.js
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -1,8 +1,8 @@
/**
This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _createField() function.
*/
-define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content', 'mvc/tools/tools-input'],
- function(Utils, Table, Ui, Repeat, SelectContent, InputElement) {
+define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content', 'mvc/tools/tools-input'],
+ function(Utils, Table, Ui, Portlet, Repeat, SelectContent, InputElement) {
// create form view
var View = Backbone.View.extend({
@@ -36,13 +36,13 @@
// load settings elements into table
for (var i in this.inputs) {
- this._add(this.inputs[i]);
+ this.add(this.inputs[i]);
}
},
/** Add a new input element
*/
- _add: function(input) {
+ add: function(input) {
// link this
var self = this;
@@ -66,6 +66,10 @@
case 'repeat':
this._addRepeat(input_def);
break;
+ // customized section
+ case 'section':
+ this._addSection(input_def);
+ break;
// default single element row
default:
this._addRow(input_def);
@@ -103,8 +107,7 @@
// check if non-hidden elements exist
var nonhidden = false;
for (var j in case_def.inputs) {
- var type = case_def.inputs[j].type;
- if (type && type !== 'hidden') {
+ if (!case_def.inputs[j].hidden) {
nonhidden = true;
break;
}
@@ -244,6 +247,58 @@
this.table.append(input_def.id);
},
+ /** Add a customized section
+ */
+ _addSection: function(input_def) {
+ // link this
+ var self = this;
+
+ // create sub section
+ var sub_section = new View(self.app, {
+ inputs : input_def.inputs,
+ cls : 'ui-table-plain'
+ });
+
+ // delete button
+ var button_visible = new Ui.ButtonIcon({
+ icon : 'fa-eye-slash',
+ tooltip : 'Show/hide section',
+ cls : 'ui-button-icon-plain'
+ });
+
+ // create portlet for sub section
+ var portlet = new Portlet.View({
+ title : input_def.label,
+ cls : 'ui-portlet-section',
+ operations : {
+ button_visible: button_visible
+ }
+ });
+ portlet.append(sub_section.$el);
+
+ // add event handler visibility button
+ var visible = false;
+ portlet.$content.hide();
+ portlet.$header.css('cursor', 'pointer');
+ portlet.$header.on('click', function() {
+ if (visible) {
+ visible = false;
+ portlet.$content.hide();
+ button_visible.setIcon('fa-eye-slash');
+ } else {
+ visible = true;
+ portlet.$content.fadeIn('fast');
+ button_visible.setIcon('fa-eye');
+ }
+ });
+
+ // create table row
+ this.table.add(portlet.$el);
+
+ // append row to table
+ this.table.append(input_def.id);
+ },
+
/** Add a single input field element
*/
_addRow: function(input_def) {
@@ -273,6 +328,11 @@
// append to table
this.table.append(id);
+ // hide row if neccessary
+ if (input_def.hidden) {
+ this.table.get(id).hide();
+ }
+
// return created field
return field;
},
@@ -316,7 +376,7 @@
field = this._fieldHidden(input_def);
break;
- // hidden field
+ // hidden data field
case 'hidden_data':
field = this._fieldHidden(input_def);
break;
@@ -465,9 +525,9 @@
_fieldText : function(input_def) {
var self = this;
return new Ui.Input({
- id : 'field-' + input_def.id,
- area : input_def.area,
- onchange: function() {
+ id : 'field-' + input_def.id,
+ area : input_def.area,
+ onchange : function() {
self.app.trigger('refresh');
}
});
@@ -476,11 +536,15 @@
/** Slider field
*/
_fieldSlider: function(input_def) {
+ var self = this;
return new Ui.Slider.View({
- id : 'field-' + input_def.id,
- precise : input_def.type == 'float',
- min : input_def.min,
- max : input_def.max
+ id : 'field-' + input_def.id,
+ precise : input_def.type == 'float',
+ min : input_def.min,
+ max : input_def.max,
+ onchange : function() {
+ self.app.trigger('refresh');
+ }
});
},
@@ -488,18 +552,22 @@
*/
_fieldHidden : function(input_def) {
return new Ui.Hidden({
- id : 'field-' + input_def.id,
- info : input_def.info
+ id : 'field-' + input_def.id,
+ info : input_def.info
});
},
/** Boolean field
*/
_fieldBoolean : function(input_def) {
+ var self = this;
return new Ui.RadioButton.View({
- id : 'field-' + input_def.id,
- data : [ { label : 'Yes', value : 'true' },
- { label : 'No', value : 'false' }]
+ id : 'field-' + input_def.id,
+ data : [ { label : 'Yes', value : 'true' },
+ { label : 'No', value : 'false' }],
+ onchange : function() {
+ self.app.trigger('refresh');
+ }
});
}
});
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/mvc/tools/tools-tree.js
--- a/static/scripts/mvc/tools/tools-tree.js
+++ b/static/scripts/mvc/tools/tools-tree.js
@@ -108,22 +108,29 @@
convert(job_input_id, head[input.id + '-section-' + selectedCase]);
}
break;
+ // handle custom sub sections
+ case 'section':
+ convert('', node);
+ break;
default:
// get field
var field = self.app.field_list[input.id];
-
- // get and patch field value
- var value = field.value();
- if (patch[input.type]) {
- value = patch[input.type](value);
- }
-
- // handle default value
- if (!field.skip) {
- if (field.validate && !field.validate(value)) {
- value = null;
+ if (field && field.value) {
+ // get and patch field value
+ var value = field.value();
+ if (patch[input.type]) {
+ value = patch[input.type](value);
}
- add (job_input_id, input.id, value);
+
+ // handle default value
+ if (!field.skip) {
+ if (field.validate && !field.validate(value)) {
+ value = null;
+ }
+ if (input.ignore === undefined || (value && input.ignore != value)) {
+ add (job_input_id, input.id, value);
+ }
+ }
}
}
}
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/mvc/ui/ui-misc.js
--- a/static/scripts/mvc/ui/ui-misc.js
+++ b/static/scripts/mvc/ui/ui-misc.js
@@ -193,6 +193,12 @@
this.disabled = false;
},
+ // change icon
+ setIcon: function(icon_cls) {
+ this.$('i').removeClass(this.options.icon).addClass(icon_cls);
+ this.options.icon = icon_cls;
+ },
+
// template
_template: function(options) {
// width
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/mvc/ui/ui-portlet.js
--- a/static/scripts/mvc/ui/ui-portlet.js
+++ b/static/scripts/mvc/ui/ui-portlet.js
@@ -25,6 +25,7 @@
$content : null,
$buttons : null,
$operations : null,
+ $header : null,
// initialize
initialize : function(options) {
@@ -35,13 +36,16 @@
this.setElement(this._template(this.options));
// link content
- this.$content = this.$el.find('#content');
+ this.$content = this.$el.find('.content');
// link title
- this.$title = this.$el.find('#portlet-title-text');
+ this.$title = this.$el.find('.portlet-title-text');
+
+ // link header
+ this.$header = this.$el.find('.portlet-header');
// set content format
- var $portlet_content = this.$el.find('#portlet-content');
+ var $portlet_content = this.$el.find('.portlet-content');
if (!this.options.scrollable) {
if (this.options.title) {
$portlet_content.addClass('no-scroll');
@@ -59,7 +63,7 @@
}
// append buttons
- this.$buttons = $(this.el).find('#buttons');
+ this.$buttons = $(this.el).find('.buttons');
if (this.options.buttons) {
// link functions
var self = this;
@@ -72,7 +76,7 @@
}
// append operations
- this.$operations = $(this.el).find('#operations');
+ this.$operations = $(this.el).find('.operations');
if (this.options.operations) {
// link functions
var self = this;
@@ -161,27 +165,27 @@
var tmpl = '<div id="' + options.id + '" class="' + options.cls + '">';
if (options.title) {
- tmpl += '<div id="portlet-header" class="portlet-header">' +
- '<div id="operations" style="float: ' + options.operations_flt + ';"></div>' +
+ tmpl += '<div class="portlet-header">' +
+ '<div class="operations" style="float: ' + options.operations_flt + ';"></div>' +
'<div class="portlet-title">';
if (options.icon)
tmpl += '<i class="icon fa ' + options.icon + '"> </i>';
- tmpl += '<span id="portlet-title-text" class="portlet-title-text">' + options.title + '</span>' +
+ tmpl += '<span class="portlet-title-text">' + options.title + '</span>' +
'</div>' +
'</div>';
}
- tmpl += '<div id="portlet-content" class="portlet-content">';
+ tmpl += '<div class="portlet-content">';
if (options.placement == 'top') {
- tmpl += '<div id="buttons" class="buttons"></div>';
+ tmpl += '<div class="buttons"></div>';
}
- tmpl += '<div id="content" class="content"></div>';
+ tmpl += '<div class="content"></div>';
if (options.placement == 'bottom') {
- tmpl += '<div id="buttons" class="buttons"></div>';
+ tmpl += '<div class="buttons"></div>';
}
tmpl += '</div>' +
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.css("color","red")}},onMouseLeave:function(a){this.$el.css("color","black")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasConnectedOutputTerminals()&&!this.node.hasConnectedMappedInputTerminals()){_.each(this.node.mappedInputTerminals(),function(b){b.resetMappingIfNeeded()})}var a=!this.node.hasMappedOverInputTerminals();if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(this._collectionAttached()){inputsFilled=true}else{a=false}}else{a=true}}return a},_collectionAttached:function(){if(!this.connected()){return false}else{var a=this.connectors[0].handle1;if(!a){return false}else{if(a.isDataCollectionInput||a.isMappedOver()||a.datatypes.indexOf("input_collection")>0){return true}else{return false}}}},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(this.connected()&&!this._collectionAttached()){return false}if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(b){var a=[];$.each(b,function(c,d){if(d.connectors.length>0){a.push(d)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){a.push(d)}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.label=b.label;this.uuid=b.uuid;this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this,true)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,uuid:f.uuid,label:f.label,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a,b){this.has_changes=true;if(this.active_node==a&&(!parent.__NEWTOOLFORM__||b)){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}function update_node(b){var a=workflow.active_node;if(a){a.update_field_data(b,true)}}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(b,c){var a=c.proxy.terminal.connectors[0];if(a){a.destroy()}$(c.proxy).remove();$(c.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.css("color","red")}},onMouseLeave:function(a){this.$el.css("color","black")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasConnectedOutputTerminals()&&!this.node.hasConnectedMappedInputTerminals()){_.each(this.node.mappedInputTerminals(),function(b){b.resetMappingIfNeeded()})}var a=!this.node.hasMappedOverInputTerminals();if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(this._collectionAttached()){inputsFilled=true}else{a=false}}else{a=true}}return a},_collectionAttached:function(){if(!this.connected()){return false}else{var a=this.connectors[0].handle1;if(!a){return false}else{if(a.isDataCollectionInput||a.isMappedOver()||a.datatypes.indexOf("input_collection")>0){return true}else{return false}}}},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(this.connected()&&!this._collectionAttached()){return false}if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(b){var a=[];$.each(b,function(c,d){if(d.connectors.length>0){a.push(d)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){a.push(d)}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.label=b.label;this.uuid=b.uuid;this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this,true)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,uuid:f.uuid,label:f.label,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();if(parent.__NEWTOOLFORM__){parent.show_form_for_tool(a.form_html,a)}else{parent.show_form_for_tool(a.form_html+a.tooltip,a)}a.make_active();this.active_node=a}},node_changed:function(a,b){this.has_changes=true;if(this.active_node==a&&(!parent.__NEWTOOLFORM__||b)){this.check_changes_in_active_form();if(parent.__NEWTOOLFORM__){parent.show_form_for_tool(a.form_html,a)}else{parent.show_form_for_tool(a.form_html+a.tooltip,a)}}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(b,c){var a=c.proxy.terminal.connectors[0];if(a){a.destroy()}$(c.proxy).remove();$(c.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/packed/mvc/tools/tools-form-base.js
--- a/static/scripts/packed/mvc/tools/tools-form-base.js
+++ b/static/scripts/packed/mvc/tools/tools-form-base.js
@@ -1,1 +1,1 @@
-define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(!this.workflow&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}})},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:"Versions",tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:"Options",tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
+define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(!this.workflow&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}})},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:"Versions",tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:"Options",tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});if(this.options.workflow){this.portlet.$content.css("padding","0px")}this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/packed/mvc/tools/tools-form-workflow.js
--- a/static/scripts/packed/mvc/tools/tools-form-workflow.js
+++ b/static/scripts/packed/mvc/tools/tools-form-workflow.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(d){this.workflow=true;a.prototype.initialize.call(this,d)},_buildModel:function(){},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){parent.update_node(h);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
+define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.workflow=true;this.options=e;var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Edit Step Attributes",type:"section",inputs:[{label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or notes to this step; annotations are available when a workflow is viewed.",value:this.node.annotation}]};this.post_job_actions=this.node.post_job_actions;for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:"None"});var f={label:"Edit Step Action: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"None",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"text",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"text",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."},{action:"EmailAction",label:"Email notification",type:"boolean",value:"false",ignore:"false",help:"This action will send an email notifying you when the job is done."},{action:"DeleteIntermediatesAction",label:"Delete non-outputs",type:"boolean",value:"false",ignore:"false",help:"All non-output steps of this workflow will have datasets deleted if they are no longer being used as job inputs when the job this action is attached to is finished. You *must* be using workflow outputs (the snowflake) in your workflow for this to have any effect."}]};var d=this;function e(j){for(var l in j){var k=j[l];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}var m=d.post_job_actions[k.action+h];if(m){if(k.argument){k.value=m.action_arguments&&m.action_arguments[k.argument]||k.value}else{k.value="true"}}}else{if(k.inputs){e(k.inputs)}}}}e(f.inputs);return f},_buildModel:function(){},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h,true);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/packed/mvc/tools/tools-section.js
--- a/static/scripts/packed/mvc/tools/tools-section.js
+++ b/static/scripts/packed/mvc/tools/tools-section.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(d,b,g,c,a,e){var f=Backbone.View.extend({initialize:function(i,h){this.app=i;this.inputs=h.inputs;h.cls_tr="section-row";this.table=new b.View(h);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var h in this.inputs){this._add(this.inputs[h])}},_add:function(j){var i=this;var h=jQuery.extend(true,{},j);h.id=j.id=d.uuid();this.app.input_list[h.id]=h;var k=h.type;switch(k){case"conditional":this._addConditional(h);break;case"repeat":this._addRepeat(h);break;default:this._addRow(h)}},_addConditional:function(h){var j=this;h.test_param.id=h.id;var m=this._addRow(h.test_param);m.options.onchange=function(t){var p=j.app.tree.matchCase(h,t);for(var r in h.cases){var w=h.cases[r];var u=h.id+"-section-"+r;var o=j.table.get(u);var v=false;for(var q in w.inputs){var s=w.inputs[q].type;if(s&&s!=="hidden"){v=true;break}}if(r==p&&v){o.fadeIn("fast")}else{o.hide()}}j.app.trigger("refresh")};for(var l in h.cases){var k=h.id+"-section-"+l;var n=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});n.$el.addClass("ui-table-form-section");this.table.add(n.$el);this.table.append(k)}m.trigger("change")},_addRepeat:function(o){var r=this;var p=0;function m(i,t){var s=o.id+"-section-"+(p++);var u=null;if(t){u=function(){k.del(s);k.retitle(o.title);r.app.trigger("refresh")}}var v=new f(r.app,{inputs:i,cls:"ui-table-plain"});k.add({id:s,title:o.title,$el:v.$el,ondel:u});k.retitle(o.title)}var k=new c.View({title_new:o.title,max:o.max,onnew:function(){m(o.inputs,true);r.app.trigger("refresh")}});var h=o.min;var q=_.size(o.cache);for(var l=0;l<Math.max(q,h);l++){var n=null;if(l<q){n=o.cache[l]}else{n=o.inputs}m(n,l>=h)}var j=new e(this.app,{label:o.title,help:o.help,field:k});j.$el.addClass("ui-table-form-section");this.table.add(j.$el);this.table.append(o.id)},_addRow:function(h){var k=h.id;var i=this._createField(h);this.app.field_list[k]=i;var j=new e(this.app,{label:h.label,optional:h.optional,help:h.help,field:i});this.app.element_list[k]=j;this.table.add(j.$el);this.table.append(k);return i},_createField:function(h){var i=null;switch(h.type){case"text":i=this._fieldText(h);break;case"select":i=this._fieldSelect(h);break;case"data":i=this._fieldData(h);break;case"data_collection":i=this._fieldData(h);break;case"data_column":h.error_text="Missing columns in referenced dataset.";i=this._fieldSelect(h);break;case"hidden":i=this._fieldHidden(h);break;case"hidden_data":i=this._fieldHidden(h);break;case"integer":i=this._fieldSlider(h);break;case"float":i=this._fieldSlider(h);break;case"boolean":i=this._fieldBoolean(h);break;case"genomebuild":h.searchable=true;i=this._fieldSelect(h);break;case"drill_down":i=this._fieldDrilldown(h);break;case"baseurl":i=this._fieldHidden(h);break;default:this.app.incompatible=true;if(h.options){i=this._fieldSelect(h)}else{i=this._fieldText(h)}console.debug("tools-form::_addRow() : Auto matched field type ("+h.type+").")}if(h.value!==undefined){i.value(h.value)}return i},_fieldData:function(h){if(this.app.workflow){var j=d.textify(h.extensions.toString());h.info="Data input '"+h.name+"' ("+j+")";return this._fieldHidden(h)}var i=this;return new a.View(this.app,{id:"field-"+h.id,extensions:h.extensions,multiple:h.multiple,type:h.type,data:h.options,onchange:function(){i.app.trigger("refresh")}})},_fieldSelect:function(h){if(this.app.workflow&&h.is_dynamic){if(!d.validate(h.value)){h.value=""}return this._fieldText(h)}var k=[];for(var l in h.options){var m=h.options[l];k.push({label:m[0],value:m[1]})}var n=g.Select;switch(h.display){case"checkboxes":n=g.Checkbox;break;case"radio":n=g.Radio;break}var j=this;return new n.View({id:"field-"+h.id,data:k,error_text:h.error_text||"No options available",multiple:h.multiple,searchable:h.searchable,onchange:function(){j.app.trigger("refresh")}})},_fieldDrilldown:function(h){var i=this;return new g.Drilldown.View({id:"field-"+h.id,data:h.options,display:h.display,onchange:function(){i.app.trigger("refresh")}})},_fieldText:function(h){var i=this;return new g.Input({id:"field-"+h.id,area:h.area,onchange:function(){i.app.trigger("refresh")}})},_fieldSlider:function(h){return new g.Slider.View({id:"field-"+h.id,precise:h.type=="float",min:h.min,max:h.max})},_fieldHidden:function(h){return new g.Hidden({id:"field-"+h.id,info:h.info})},_fieldBoolean:function(h){return new g.RadioButton.View({id:"field-"+h.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]})}});return{View:f}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(e,b,h,d,c,a,f){var g=Backbone.View.extend({initialize:function(j,i){this.app=j;this.inputs=i.inputs;i.cls_tr="section-row";this.table=new b.View(i);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var j in this.inputs){this.add(this.inputs[j])}},add:function(k){var j=this;var i=jQuery.extend(true,{},k);i.id=k.id=e.uuid();this.app.input_list[i.id]=i;var l=i.type;switch(l){case"conditional":this._addConditional(i);break;case"repeat":this._addRepeat(i);break;case"section":this._addSection(i);break;default:this._addRow(i)}},_addConditional:function(j){var k=this;j.test_param.id=j.id;var n=this._addRow(j.test_param);n.options.onchange=function(w){var v=k.app.tree.matchCase(j,w);for(var u in j.cases){var q=j.cases[u];var t=j.id+"-section-"+u;var p=k.table.get(t);var s=false;for(var r in q.inputs){if(!q.inputs[r].hidden){s=true;break}}if(u==v&&s){p.fadeIn("fast")}else{p.hide()}}k.app.trigger("refresh")};for(var m in j.cases){var l=j.id+"-section-"+m;var o=new g(this.app,{inputs:j.cases[m].inputs,cls:"ui-table-plain"});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(l)}n.trigger("change")},_addRepeat:function(p){var s=this;var q=0;function n(i,u){var t=p.id+"-section-"+(q++);var v=null;if(u){v=function(){l.del(t);l.retitle(p.title);s.app.trigger("refresh")}}var w=new g(s.app,{inputs:i,cls:"ui-table-plain"});l.add({id:t,title:p.title,$el:w.$el,ondel:v});l.retitle(p.title)}var l=new c.View({title_new:p.title,max:p.max,onnew:function(){n(p.inputs,true);s.app.trigger("refresh")}});var j=p.min;var r=_.size(p.cache);for(var m=0;m<Math.max(r,j);m++){var o=null;if(m<r){o=p.cache[m]}else{o=p.inputs}n(o,m>=j)}var k=new f(this.app,{label:p.title,help:p.help,field:l});k.$el.addClass("ui-table-form-section");this.table.add(k.$el);this.table.append(p.id)},_addSection:function(i){var j=this;var n=new g(j.app,{inputs:i.inputs,cls:"ui-table-plain"});var m=new h.ButtonIcon({icon:"fa-eye-slash",tooltip:"Show/hide section",cls:"ui-button-icon-plain"});var l=new d.View({title:i.label,cls:"ui-portlet-section",operations:{button_visible:m}});l.append(n.$el);var k=false;l.$content.hide();l.$header.css("cursor","pointer");l.$header.on("click",function(){if(k){k=false;l.$content.hide();m.setIcon("fa-eye-slash")}else{k=true;l.$content.fadeIn("fast");m.setIcon("fa-eye")}});this.table.add(l.$el);this.table.append(i.id)},_addRow:function(i){var l=i.id;var j=this._createField(i);this.app.field_list[l]=j;var k=new f(this.app,{label:i.label,optional:i.optional,help:i.help,field:j});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);if(i.hidden){this.table.get(l).hide()}return j},_createField:function(i){var j=null;switch(i.type){case"text":j=this._fieldText(i);break;case"select":j=this._fieldSelect(i);break;case"data":j=this._fieldData(i);break;case"data_collection":j=this._fieldData(i);break;case"data_column":i.error_text="Missing columns in referenced dataset.";j=this._fieldSelect(i);break;case"hidden":j=this._fieldHidden(i);break;case"hidden_data":j=this._fieldHidden(i);break;case"integer":j=this._fieldSlider(i);break;case"float":j=this._fieldSlider(i);break;case"boolean":j=this._fieldBoolean(i);break;case"genomebuild":i.searchable=true;j=this._fieldSelect(i);break;case"drill_down":j=this._fieldDrilldown(i);break;case"baseurl":j=this._fieldHidden(i);break;default:this.app.incompatible=true;if(i.options){j=this._fieldSelect(i)}else{j=this._fieldText(i)}console.debug("tools-form::_addRow() : Auto matched field type ("+i.type+").")}if(i.value!==undefined){j.value(i.value)}return j},_fieldData:function(i){if(this.app.workflow){var k=e.textify(i.extensions.toString());i.info="Data input '"+i.name+"' ("+k+")";return this._fieldHidden(i)}var j=this;return new a.View(this.app,{id:"field-"+i.id,extensions:i.extensions,multiple:i.multiple,type:i.type,data:i.options,onchange:function(){j.app.trigger("refresh")}})},_fieldSelect:function(j){if(this.app.workflow&&j.is_dynamic){if(!e.validate(j.value)){j.value=""}return this._fieldText(j)}var l=[];for(var m in j.options){var n=j.options[m];l.push({label:n[0],value:n[1]})}var o=h.Select;switch(j.display){case"checkboxes":o=h.Checkbox;break;case"radio":o=h.Radio;break}var k=this;return new o.View({id:"field-"+j.id,data:l,error_text:j.error_text||"No options available",multiple:j.multiple,searchable:j.searchable,onchange:function(){k.app.trigger("refresh")}})},_fieldDrilldown:function(i){var j=this;return new h.Drilldown.View({id:"field-"+i.id,data:i.options,display:i.display,onchange:function(){j.app.trigger("refresh")}})},_fieldText:function(i){var j=this;return new h.Input({id:"field-"+i.id,area:i.area,onchange:function(){j.app.trigger("refresh")}})},_fieldSlider:function(i){var j=this;return new h.Slider.View({id:"field-"+i.id,precise:i.type=="float",min:i.min,max:i.max,onchange:function(){j.app.trigger("refresh")}})},_fieldHidden:function(i){return new h.Hidden({id:"field-"+i.id,info:i.info})},_fieldBoolean:function(i){var j=this;return new h.RadioButton.View({id:"field-"+i.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:function(){j.app.trigger("refresh")}})}});return{View:g}});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/packed/mvc/tools/tools-tree.js
--- a/static/scripts/packed/mvc/tools/tools-tree.js
+++ b/static/scripts/packed/mvc/tools/tools-tree.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(o,r){for(var m in r){var k=r[m];if(k.input){var t=k.input;var n=o;if(o!=""){n+="|"}n+=t.name;switch(t.type){case"repeat":var j="section-";var w=[];var q=null;for(var v in k){var p=v.indexOf(j);if(p!=-1){p+=j.length;w.push(parseInt(v.substr(p)));if(!q){q=v.substr(0,p)}}}w.sort(function(x,i){return x-i});var m=0;for(var l in w){c(n+"_"+m++,k[q+w[l]])}break;case"conditional":var u=b.app.field_list[t.id].value();if(g[t.test_param.type]){u=g[t.test_param.type](u)}d(n+"|"+t.test_param.name,t.id,u);var h=b.matchCase(t,u);if(h!=-1){c(n,r[t.id+"-section-"+h])}break;default:var s=b.app.field_list[t.id];var u=s.value();if(g[t.type]){u=g[t.type](u)}if(!s.skip){if(s.validate&&!s.validate(u)){u=null}d(n,t.id,u)}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(o,r){for(var m in r){var k=r[m];if(k.input){var t=k.input;var n=o;if(o!=""){n+="|"}n+=t.name;switch(t.type){case"repeat":var j="section-";var w=[];var q=null;for(var v in k){var p=v.indexOf(j);if(p!=-1){p+=j.length;w.push(parseInt(v.substr(p)));if(!q){q=v.substr(0,p)}}}w.sort(function(x,i){return x-i});var m=0;for(var l in w){c(n+"_"+m++,k[q+w[l]])}break;case"conditional":var u=b.app.field_list[t.id].value();if(g[t.test_param.type]){u=g[t.test_param.type](u)}d(n+"|"+t.test_param.name,t.id,u);var h=b.matchCase(t,u);if(h!=-1){c(n,r[t.id+"-section-"+h])}break;case"section":c("",k);break;default:var s=b.app.field_list[t.id];if(s&&s.value){var u=s.value();if(g[t.type]){u=g[t.type](u)}if(!s.skip){if(s.validate&&!s.validate(u)){u=null}if(t.ignore===undefined||(u&&t.ignore!=u)){d(n,t.id,u)}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/packed/mvc/ui/ui-misc.js
--- a/static/scripts/packed/mvc/ui/ui-misc.js
+++ b/static/scripts/packed/mvc/ui/ui-misc.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(k,b,e,o,l,q,m){var d=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},_template:function(r){return'<img class="ui-image '+r.cls+'" src="'+r.url+'"/>'}});var j=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},title:function(r){this.$el.html(r)},_template:function(r){return'<label class="ui-label '+r.cls+'">'+r.title+"</label>"},value:function(){return options.title}});var c=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){return'<div><span class="fa '+r.icon+'" class="ui-icon"/> '+r.title+"</div>"}});var g=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",function(){$(".tooltip").hide();if(r.onclick){r.onclick()}});$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){var s='<button id="'+r.id+'" type="submit" style="float: '+r.floating+';" type="button" class="'+r.cls+'">';if(r.icon){s+='<i class="icon fa '+r.icon+'"></i> '}s+=r.title+"</button>";return s}});var h=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));this.$button=this.$el.find(".button");var r=this;$(this.el).on("click",function(){$(".tooltip").hide();if(s.onclick&&!r.disabled){s.onclick()}});$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled");this.disabled=true},enable:function(){this.$button.removeClass("disabled");this.disabled=false},_template:function(r){var s="";if(r.title){s="width: auto;"}var t='<div id="'+r.id+'" style="float: '+r.floating+"; "+s+'" class="'+r.cls+'">';if(r.title){t+='<div class="button"><i class="icon fa '+r.icon+'"/> <span class="title">'+r.title+"</span></div>"}else{t+='<i class="icon fa '+r.icon+'"/>'}t+="</div>";return t}});var f=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",r.onclick)},_template:function(r){return'<div><a href="javascript:void(0)" class="ui-anchor '+r.cls+'">'+r.title+"</a></div>"}});var n=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:false},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement("<div></div>");if(this.options.message){this.update(this.options)}},update:function(s){this.options=k.merge(s,this.optionsDefault);if(s.message!=""){this.$el.html(this._template(this.options));this.$el.find(".alert").append(s.message);this.$el.fadeIn();if(this.timeout){window.clearTimeout(this.timeout)}if(!s.persistent){var r=this;this.timeout=window.setTimeout(function(){if(r.$el.is(":visible")){r.$el.fadeOut()}else{r.$el.hide()}},3000)}}else{this.$el.fadeOut()}},_template:function(r){return'<div class="ui-message alert alert-'+r.status+'"/>'}});var a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));var r=this;if(this.options.onclick){this.$el.on("submit",function(u){var t=r.$el.find("#search");r.options.onclick(t.val())})}},_template:function(r){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+r.searchword+'"><button type="submit" class="btn search-btn"><i class="fa fa-search"></i></button></form></div>'}});var i=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:false,visible:true,cls:"",area:false},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}if(this.options.disabled){this.$el.prop("disabled",true)}if(!this.options.visible){this.$el.hide()}var r=this;this.$el.on("input",function(){if(r.options.onchange){r.options.onchange(r.$el.val())}})},value:function(r){if(r!==undefined){this.$el.val(r)}return this.$el.val()},_template:function(r){if(r.area){return'<textarea id="'+r.id+'" class="ui-textarea '+r.cls+'"></textarea>'}else{return'<input id="'+r.id+'" type="'+r.type+'" value="'+r.value+'" placeholder="'+r.placeholder+'" class="ui-input '+r.cls+'">'}}});var p=Backbone.View.extend({initialize:function(r){this.options=r;this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}},value:function(r){if(r!==undefined){this.$("hidden").val(r)}return this.$("hidden").val()},_template:function(s){var r='<div id="'+s.id+'" >';if(s.info){r+="<label>"+s.info+"</label>"}r+='<hidden value="'+s.value+'"/></div>';return r}});return{Anchor:f,Button:g,ButtonIcon:h,ButtonMenu:q,Icon:c,Image:d,Input:i,Label:j,Message:n,Modal:m,RadioButton:o.RadioButton,Checkbox:o.Checkbox,Radio:o.Radio,Searchbox:a,Select:b,Hidden:p,Slider:e,Drilldown:l}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(k,b,e,o,l,q,m){var d=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},_template:function(r){return'<img class="ui-image '+r.cls+'" src="'+r.url+'"/>'}});var j=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},title:function(r){this.$el.html(r)},_template:function(r){return'<label class="ui-label '+r.cls+'">'+r.title+"</label>"},value:function(){return options.title}});var c=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){return'<div><span class="fa '+r.icon+'" class="ui-icon"/> '+r.title+"</div>"}});var g=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",function(){$(".tooltip").hide();if(r.onclick){r.onclick()}});$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){var s='<button id="'+r.id+'" type="submit" style="float: '+r.floating+';" type="button" class="'+r.cls+'">';if(r.icon){s+='<i class="icon fa '+r.icon+'"></i> '}s+=r.title+"</button>";return s}});var h=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));this.$button=this.$el.find(".button");var r=this;$(this.el).on("click",function(){$(".tooltip").hide();if(s.onclick&&!r.disabled){s.onclick()}});$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled");this.disabled=true},enable:function(){this.$button.removeClass("disabled");this.disabled=false},setIcon:function(r){this.$("i").removeClass(this.options.icon).addClass(r);this.options.icon=r},_template:function(r){var s="";if(r.title){s="width: auto;"}var t='<div id="'+r.id+'" style="float: '+r.floating+"; "+s+'" class="'+r.cls+'">';if(r.title){t+='<div class="button"><i class="icon fa '+r.icon+'"/> <span class="title">'+r.title+"</span></div>"}else{t+='<i class="icon fa '+r.icon+'"/>'}t+="</div>";return t}});var f=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",r.onclick)},_template:function(r){return'<div><a href="javascript:void(0)" class="ui-anchor '+r.cls+'">'+r.title+"</a></div>"}});var n=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:false},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement("<div></div>");if(this.options.message){this.update(this.options)}},update:function(s){this.options=k.merge(s,this.optionsDefault);if(s.message!=""){this.$el.html(this._template(this.options));this.$el.find(".alert").append(s.message);this.$el.fadeIn();if(this.timeout){window.clearTimeout(this.timeout)}if(!s.persistent){var r=this;this.timeout=window.setTimeout(function(){if(r.$el.is(":visible")){r.$el.fadeOut()}else{r.$el.hide()}},3000)}}else{this.$el.fadeOut()}},_template:function(r){return'<div class="ui-message alert alert-'+r.status+'"/>'}});var a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));var r=this;if(this.options.onclick){this.$el.on("submit",function(u){var t=r.$el.find("#search");r.options.onclick(t.val())})}},_template:function(r){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+r.searchword+'"><button type="submit" class="btn search-btn"><i class="fa fa-search"></i></button></form></div>'}});var i=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:false,visible:true,cls:"",area:false},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}if(this.options.disabled){this.$el.prop("disabled",true)}if(!this.options.visible){this.$el.hide()}var r=this;this.$el.on("input",function(){if(r.options.onchange){r.options.onchange(r.$el.val())}})},value:function(r){if(r!==undefined){this.$el.val(r)}return this.$el.val()},_template:function(r){if(r.area){return'<textarea id="'+r.id+'" class="ui-textarea '+r.cls+'"></textarea>'}else{return'<input id="'+r.id+'" type="'+r.type+'" value="'+r.value+'" placeholder="'+r.placeholder+'" class="ui-input '+r.cls+'">'}}});var p=Backbone.View.extend({initialize:function(r){this.options=r;this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}},value:function(r){if(r!==undefined){this.$("hidden").val(r)}return this.$("hidden").val()},_template:function(s){var r='<div id="'+s.id+'" >';if(s.info){r+="<label>"+s.info+"</label>"}r+='<hidden value="'+s.value+'"/></div>';return r}});return{Anchor:f,Button:g,ButtonIcon:h,ButtonMenu:q,Icon:c,Image:d,Input:i,Label:j,Message:n,Modal:m,RadioButton:o.RadioButton,Checkbox:o.Checkbox,Radio:o.Radio,Searchbox:a,Select:b,Hidden:p,Slider:e,Drilldown:l}});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/scripts/packed/mvc/ui/ui-portlet.js
--- a/static/scripts/packed/mvc/ui/ui-portlet.js
+++ b/static/scripts/packed/mvc/ui/ui-portlet.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({visible:false,optionsDefault:{title:"",icon:"",buttons:null,body:null,scrollable:true,nopadding:false,operations:null,placement:"bottom",cls:"ui-portlet",operations_flt:"right"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(e){this.options=a.merge(e,this.optionsDefault);this.setElement(this._template(this.options));this.$content=this.$el.find("#content");this.$title=this.$el.find("#portlet-title-text");var d=this.$el.find("#portlet-content");if(!this.options.scrollable){if(this.options.title){d.addClass("no-scroll")}else{d.addClass("no-scroll-no-title")}}else{d.addClass("scroll")}if(this.options.nopadding){d.css("padding","0px");this.$content.css("padding","0px")}this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var c=this;$.each(this.options.buttons,function(f,g){g.$el.prop("id",f);c.$buttons.append(g.$el)})}else{this.$buttons.remove()}this.$operations=$(this.el).find("#operations");if(this.options.operations){var c=this;$.each(this.options.operations,function(f,g){g.$el.prop("id",f);c.$operations.append(g.$el)})}if(this.options.body){this.append(this.options.body)}},append:function(d,c){if(c){this.$content.append(d)}else{this.$content.append(a.wrap(d))}},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast");this.visible=true},hide:function(){this.$el.fadeOut("fast");this.visible=false},enableButton:function(c){this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(c){this.$buttons.find("#"+c).prop("disabled",true)},hideOperation:function(c){this.$operations.find("#"+c).hide()},showOperation:function(c){this.$operations.find("#"+c).show()},setOperation:function(e,d){var c=this.$operations.find("#"+e);c.off("click");c.on("click",d)},title:function(d){var c=this.$title;if(d){c.html(d)}return c.html()},_template:function(d){var c='<div id="'+d.id+'" class="'+d.cls+'">';if(d.title){c+='<div id="portlet-header" class="portlet-header"><div id="operations" style="float: '+d.operations_flt+';"></div><div class="portlet-title">';if(d.icon){c+='<i class="icon fa '+d.icon+'"> </i>'}c+='<span id="portlet-title-text" class="portlet-title-text">'+d.title+"</span></div></div>"}c+='<div id="portlet-content" class="portlet-content">';if(d.placement=="top"){c+='<div id="buttons" class="buttons"></div>'}c+='<div id="content" class="content"></div>';if(d.placement=="bottom"){c+='<div id="buttons" class="buttons"></div>'}c+="</div></div>";return c}});return{View:b}});
\ No newline at end of file
+define(["utils/utils"],function(a){var b=Backbone.View.extend({visible:false,optionsDefault:{title:"",icon:"",buttons:null,body:null,scrollable:true,nopadding:false,operations:null,placement:"bottom",cls:"ui-portlet",operations_flt:"right"},$title:null,$content:null,$buttons:null,$operations:null,$header:null,initialize:function(e){this.options=a.merge(e,this.optionsDefault);this.setElement(this._template(this.options));this.$content=this.$el.find(".content");this.$title=this.$el.find(".portlet-title-text");this.$header=this.$el.find(".portlet-header");var d=this.$el.find(".portlet-content");if(!this.options.scrollable){if(this.options.title){d.addClass("no-scroll")}else{d.addClass("no-scroll-no-title")}}else{d.addClass("scroll")}if(this.options.nopadding){d.css("padding","0px");this.$content.css("padding","0px")}this.$buttons=$(this.el).find(".buttons");if(this.options.buttons){var c=this;$.each(this.options.buttons,function(f,g){g.$el.prop("id",f);c.$buttons.append(g.$el)})}else{this.$buttons.remove()}this.$operations=$(this.el).find(".operations");if(this.options.operations){var c=this;$.each(this.options.operations,function(f,g){g.$el.prop("id",f);c.$operations.append(g.$el)})}if(this.options.body){this.append(this.options.body)}},append:function(d,c){if(c){this.$content.append(d)}else{this.$content.append(a.wrap(d))}},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast");this.visible=true},hide:function(){this.$el.fadeOut("fast");this.visible=false},enableButton:function(c){this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(c){this.$buttons.find("#"+c).prop("disabled",true)},hideOperation:function(c){this.$operations.find("#"+c).hide()},showOperation:function(c){this.$operations.find("#"+c).show()},setOperation:function(e,d){var c=this.$operations.find("#"+e);c.off("click");c.on("click",d)},title:function(d){var c=this.$title;if(d){c.html(d)}return c.html()},_template:function(d){var c='<div id="'+d.id+'" class="'+d.cls+'">';if(d.title){c+='<div class="portlet-header"><div class="operations" style="float: '+d.operations_flt+';"></div><div class="portlet-title">';if(d.icon){c+='<i class="icon fa '+d.icon+'"> </i>'}c+='<span class="portlet-title-text">'+d.title+"</span></div></div>"}c+='<div class="portlet-content">';if(d.placement=="top"){c+='<div class="buttons"></div>'}c+='<div class="content"></div>';if(d.placement=="bottom"){c+='<div class="buttons"></div>'}c+="</div></div>";return c}});return{View:b}});
\ No newline at end of file
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1389,7 +1389,7 @@
.upload-ftp .upload-ftp-help{margin-bottom:10px}
.upload-ftp .upload-ftp-warning{text-align:center;margin-top:20px}
.upload-settings .upload-settings-cover{position:absolute;width:100%;height:100%;top:0px;left:0px;background:#fff;opacity:0.4;cursor:no-drop}
-.no-highlight,.ui-button-icon,.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none;}
+.no-highlight,.ui-button-icon,.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none;}
.ui-error{-moz-border-radius:3px;border-radius:3px;background:#f9c7c5;padding:5px}
.ui-table-form-error{display:none}.ui-table-form-error .ui-table-form-error-text{padding-left:5px}
.ui-table tbody{cursor:pointer}
@@ -1404,7 +1404,7 @@
.ui-label{font-weight:bold}
.ui-message{padding:2px 10px 2px 10px;margin-bottom:5px}
.ui-icon{font-size:1.2em}
-.ui-button-icon{margin-right:5px}.ui-button-icon ul i{font-size:1.2em;margin-right:5px;position:relative;top:1px}
+.ui-button-icon{margin-right:5px;height:auto !important}.ui-button-icon ul i{font-size:1.2em;margin-right:5px;position:relative;top:1px}
.ui-button-icon .button{margin-right:5px;margin-left:5px}.ui-button-icon .button .title{position:relative;font-size:0.8em;font-weight:normal;top:-1px}
.ui-button-icon .button.disabled{filter:alpha(opacity=65);opacity:.65;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=65);filter:alpha(opacity=65)}
.ui-button-menu .dropdown-menu{min-width:50px}
@@ -1412,14 +1412,15 @@
.ui-button-icon-plain{border:none !important;background:none !important;height:inherit !important;width:inherit !important;padding-right:3px !important}
.ui-tabs .ui-tabs-add{font-size:0.8em;margin-right:5px}
.ui-tabs .ui-tabs-delete{font-size:0.8em;margin-left:5px;cursor:pointer}
-.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-slim,.ui-portlet-repeat{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;clear:both;width:auto;height:100%}.ui-portlet .portlet-header,.ui-portlet-slim .portlet-header{background:#ebd9b2;border-bottom:solid #d6b161 1px;padding:2px 8px;overflow:visible;float:right;width:100%}.ui-portlet .portlet-header .portlet-title,.ui-portlet-slim .portlet-header .portlet-title{display:inline;vertical-align:middle}.ui-portlet .portlet-header .portlet-title .portlet-title-text,.ui-portlet-slim .portlet-header .portlet-title .portlet-title-text{vertical-align:middle}
+.ui-portlet,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section,.ui-portlet-slim,.ui-portlet-repeat,.ui-portlet-section{border:solid #d6b161 1px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;clear:both;width:auto;height:100%}.ui-portlet .portlet-header,.ui-portlet-slim .portlet-header{background:#ebd9b2;border-bottom:solid #d6b161 1px;padding:2px 8px;overflow:visible;float:right;width:100%}.ui-portlet .portlet-header .portlet-title,.ui-portlet-slim .portlet-header .portlet-title{display:inline;vertical-align:middle}.ui-portlet .portlet-header .portlet-title .portlet-title-text,.ui-portlet-slim .portlet-header .portlet-title .portlet-title-text{vertical-align:middle}
.ui-portlet .portlet-header .portlet-title .icon,.ui-portlet-slim .portlet-header .portlet-title .icon{font-size:1.2em;vertical-align:middle}
.ui-portlet .portlet-buttons,.ui-portlet-slim .portlet-buttons{height:50px;padding:10px}
.ui-portlet .portlet-content,.ui-portlet-slim .portlet-content{height:inherit;padding:10px;clear:both}.ui-portlet .portlet-content .content,.ui-portlet-slim .portlet-content .content{padding:10px;height:100%;width:100%}.ui-portlet .portlet-content .content .buttons,.ui-portlet-slim .portlet-content .content .buttons{height:50px;padding:10px}
.ui-portlet .no-scroll,.ui-portlet-slim .no-scroll{height:calc(100% - 80px)}
.ui-portlet-slim{max-width:900px}
-.ui-portlet-repeat{border:none;border-left:solid 3px #ebd9b2;border-radius:5px}.ui-portlet-repeat .portlet-header{background:#ebd9b2;border-radius:3px;border-bottom-left-radius:0px;padding:0px 2px}
-.ui-portlet-repeat .portlet-content{padding:0px}.ui-portlet-repeat .portlet-content .content{padding:0px;padding-left:10px}
+.ui-portlet-repeat,.ui-portlet-section,.ui-portlet-section{border:none;border-left:solid 3px #ebd9b2;border-radius:5px}.ui-portlet-repeat .portlet-header,.ui-portlet-section .portlet-header{background:#ebd9b2;border-radius:3px;border-bottom-left-radius:0px;padding:0px 2px}
+.ui-portlet-repeat .portlet-content,.ui-portlet-section .portlet-content{padding:0px}.ui-portlet-repeat .portlet-content .content,.ui-portlet-section .portlet-content .content{padding:0px;padding-left:10px}
+.ui-portlet-section{border-left:solid 3px #dfe5f9;border-radius:5px}.ui-portlet-section .portlet-header{background:#dfe5f9;border-bottom:solid #b4c2f1 1px}
.ui-popover{max-width:700px;display:none}.ui-popover .popover-close{position:absolute;right:10px;top:7px;font-size:1.2em;cursor:pointer}
.ui-popover .popover-title{padding:4px 10px}
.ui-input,.ui-textarea,.ui-options,.ui-form-slider .ui-form-slider-text,.ui-select-multiple,.ui-textarea,.ui-options,.ui-form-slider .ui-form-slider-text,.ui-select-multiple{background:transparent}
@@ -1742,7 +1743,7 @@
#masthead li.dropdown>a:hover .caret{border-top-color:gold;border-bottom-color:gold}
#masthead .navbar-brand{position:absolute;left:0;top:0;font-family:verdana;font-weight:bold;font-size:20px;line-height:1;color:white;padding:5px 20px 12px;margin-left:-15px;z-index:2000}#masthead .navbar-brand img{display:inline;width:26px;vertical-align:top}
#masthead .navbar-brand a{color:white;text-decoration:none}
-#masthead .iconbar{position:absolute;top:7px;right:110px;cursor:pointer;color:#999;overflow:hidden}#masthead .iconbar .symbol{float:left;margin:0px 10px;height:26px;font-size:11px}
+#masthead .iconbar{position:absolute;top:7px;right:110px;cursor:pointer;color:#999;overflow:hidden}#masthead .iconbar .symbol{float:left;margin:0px 10px;font-size:11px}
#masthead .iconbar .symbol .number{font-weight:bold;font-size:10px;font-family:"Lucida Grande",verdana,arial,helvetica,sans-serif;position:relative;left:23px;top:-12px}
#masthead .iconbar .toggle{color:gold}
.quota-meter-container{position:absolute;top:0;right:0;height:32px}
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/style/src/less/base.less
--- a/static/style/src/less/base.less
+++ b/static/style/src/less/base.less
@@ -435,7 +435,6 @@
{
float : left;
margin : 0px 10px;
- height : 26px;
font-size : 11px;
}
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a static/style/src/less/ui.less
--- a/static/style/src/less/ui.less
+++ b/static/style/src/less/ui.less
@@ -92,6 +92,7 @@
&:extend(.icon-btn);
&:extend(.no-highlight);
margin-right: 5px;
+ height: auto !important;
ul {
i {
font-size: 1.2em; margin-right: 5px; position: relative; top: 1px;
@@ -228,6 +229,16 @@
}
}
+.ui-portlet-section {
+ &:extend(.ui-portlet-repeat all);
+ border-left: solid 3px @side-panel-bg;
+ border-radius: 5px;
+ .portlet-header {
+ background: @side-panel-bg;
+ border-bottom: solid darken(@side-panel-bg, 10%) 1px;
+ }
+}
+
.ui-popover {
max-width: 700px;
display: none;
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a templates/webapps/galaxy/workflow/editor.mako
--- a/templates/webapps/galaxy/workflow/editor.mako
+++ b/templates/webapps/galaxy/workflow/editor.mako
@@ -32,6 +32,9 @@
<![endif]--><script type='text/javascript'>
+ // Switch for new tool form
+ __NEWTOOLFORM__ = false;
+
// Globals
workflow = null;
canvas_manager = null;
diff -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 -r a2308bdc93b897af974766b190abe019ade49e9a templates/webapps/galaxy/workflow/editor_tool_form.mako
--- a/templates/webapps/galaxy/workflow/editor_tool_form.mako
+++ b/templates/webapps/galaxy/workflow/editor_tool_form.mako
@@ -18,18 +18,12 @@
})
%><script>
- parent.__NEWTOOLFORM__ = true;
require(['mvc/tools/tools-form-workflow'], function(ToolsForm){
$(function(){
var form = new ToolsForm.View(${ h.dumps(self.form_config) });
});
});
</script>
- <form method="post" action="${h.url_for(controller='workflow', action='editor_form_post' )}">
- <div class="toolForm">
- <input type="hidden" name="tool_id" value="${tool.id}" />
- </div>
- </form>
%else:
<%
from galaxy.tools.parameters import DataToolParameter, RuntimeValue
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/45932ad3f1ce/
Changeset: 45932ad3f1ce
User: dannon
Date: 2015-01-12 22:47:12+00:00
Summary: Trailing whitespace in parameters.basic.
Affected #: 1 file
diff -r 85e8fb54b2851454a000cab23d57ce102af6aa30 -r 45932ad3f1ce1b0455413d3d9c097510493a14c9 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -487,7 +487,7 @@
d['truevalue'] = self.truevalue
d['falsevalue'] = self.falsevalue
return d
-
+
@property
def legal_values( self ):
return [ self.truevalue, self.falsevalue ]
@@ -670,7 +670,7 @@
def get_label( self ):
# BaseURLToolParameters are ultimately "hidden" parameters
return None
-
+
def to_dict( self, trans, view='collection', value_mapper=None ):
d = super( BaseURLToolParameter, self ).to_dict( trans )
d['value'] = self.get_value( trans )
@@ -1033,7 +1033,7 @@
# Found selected option.
value = option[1]
d[ 'value' ] = value
-
+
d['display'] = self.display
d['multiple'] = self.multiple
d['is_dynamic'] = self.is_dynamic
@@ -1114,7 +1114,7 @@
'display' : self.display,
'multiple' : self.multiple
})
-
+
return d
def _get_dbkey_names( self, trans=None ):
@@ -1316,10 +1316,10 @@
# add data reference
d['data_ref'] = self.data_ref
-
+
# add numerical flag
d['numerical'] = self.numerical
-
+
# return
return d
@@ -2111,7 +2111,7 @@
d['multiple'] = self.multiple
d['is_dynamic'] = True
d['options'] = {'hda': [], 'hdca': []}
-
+
# return default content if context is not available
if other_values is None:
return d
@@ -2120,7 +2120,7 @@
dataset_matcher = DatasetMatcher( trans, self, None, other_values )
history = trans.history
multiple = self.multiple
-
+
# add datasets
for hda in history.active_datasets_children_and_roles:
match = dataset_matcher.hda_match( hda )
@@ -2133,7 +2133,7 @@
'name' : m.name,
'src' : 'hda'
})
-
+
# add dataset collections
dataset_collection_matcher = DatasetCollectionMatcher( dataset_matcher )
for hdca in history.active_dataset_collections:
@@ -2352,7 +2352,7 @@
d['multiple'] = self.multiple
d['is_dynamic'] = False
d['options'] = {'hda': [], 'hdca': []}
-
+
# return default content if context is not available
if other_values is None:
return d
@@ -2360,7 +2360,7 @@
# prepare dataset/collection matching
dataset_matcher = DatasetMatcher( trans, self, None, other_values )
history = trans.history
-
+
# append directly matched collections
for hdca in self.match_collections( trans, history, dataset_matcher ):
d['options']['hdca'].append({
https://bitbucket.org/galaxy/galaxy-central/commits/50e31bdc72cf/
Changeset: 50e31bdc72cf
User: dannon
Date: 2015-01-12 22:50:10+00:00
Summary: Make SelectToolParameter behave the same way as DrillDownSelectToolParameter for (deprecated) dynamic_options w/ trans. TODO: Revisit this and figure out what the replacement for dynamic_options is.
Affected #: 1 file
diff -r 45932ad3f1ce1b0455413d3d9c097510493a14c9 -r 50e31bdc72cf9cfdf619342926ac894d1314a469 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -782,8 +782,11 @@
if self.options:
return self.options.get_options( trans, other_values )
elif self.dynamic_options:
+ call_other_values = {"__trans__": trans}
+ if other_values:
+ call_other_values.update( other_values.dict )
try:
- return eval( self.dynamic_options, self.tool.code_namespace, other_values )
+ return eval( self.dynamic_options, self.tool.code_namespace, call_other_values )
except Exception:
return []
else:
https://bitbucket.org/galaxy/galaxy-central/commits/336f89e2f013/
Changeset: 336f89e2f013
User: dannon
Date: 2015-01-12 22:50:25+00:00
Summary: Merge.
Affected #: 10 files
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 client/galaxy/scripts/viz/trackster.js
--- a/client/galaxy/scripts/viz/trackster.js
+++ b/client/galaxy/scripts/viz/trackster.js
@@ -12,7 +12,6 @@
[
// load js libraries
'utils/utils',
- 'mvc/ui/icon-button',
'libs/jquery/jquery.event.drag',
'libs/jquery/jquery.event.hover',
'libs/jquery/jquery.mousewheel',
@@ -32,9 +31,8 @@
});
// trackster viewer
-define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization"],
- function(_, base, tracks, visualization) {
-
+define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization", "mvc/ui/icon-button" ],
+ function(_, base, tracks, visualization, mod_icon_btn) {
/**
* User interface controls for trackster
*/
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -140,6 +140,7 @@
<datatype extension="rgb" type="galaxy.datatypes.images:Rgb" mimetype="image/rgb"/><datatype extension="pbm" type="galaxy.datatypes.images:Pbm" mimetype="image/pbm"/><datatype extension="pgm" type="galaxy.datatypes.images:Pgm" mimetype="image/pgm"/>
+ <datatype extension="rna_eps" type="galaxy.datatypes.sequence:RNADotPlotMatrix" mimetype="image/eps" display_in_upload="True"/><datatype extension="eps" type="galaxy.datatypes.images:Eps" mimetype="image/eps"/><datatype extension="rast" type="galaxy.datatypes.images:Rast" mimetype="image/rast"/><datatype extension="laj" type="galaxy.datatypes.images:Laj"/>
@@ -304,6 +305,7 @@
<sniffer type="galaxy.datatypes.text:Arff"/><sniffer type="galaxy.datatypes.text:Ipynb"/><sniffer type="galaxy.datatypes.text:Json"/>
+ <sniffer type="galaxy.datatypes.sequence:RNADotPlotMatrix"/><sniffer type="galaxy.datatypes.images:Jpg"/><sniffer type="galaxy.datatypes.images:Png"/><sniffer type="galaxy.datatypes.images:Tiff"/>
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 eggs.ini
--- a/eggs.ini
+++ b/eggs.ini
@@ -15,7 +15,7 @@
bx_python = 0.7.2
Cheetah = 2.2.2
MarkupSafe = 0.12
-mercurial = 2.2.3
+mercurial = 3.2.4
MySQL_python = 1.2.3c1
PyRods = 3.2.4
numpy = 1.6.0
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 lib/galaxy/datatypes/sequence.py
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -17,7 +17,7 @@
from galaxy.datatypes.checkers import is_gzip
from galaxy.datatypes.sniff import get_test_fname, get_headers
from galaxy.datatypes.metadata import MetadataElement
-
+from galaxy.datatypes.util.image_util import check_image_type
try:
eggs.require( "bx-python" )
@@ -814,3 +814,34 @@
except:
return False
+
+class RNADotPlotMatrix( data.Data ):
+ file_ext = "rna_eps"
+
+ def set_peek( self, dataset, is_multi_byte=False ):
+ if not dataset.dataset.purged:
+ dataset.peek = 'RNA Dot Plot format (Postscript derivative)'
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+
+ def sniff(self, filename):
+ """Determine if the file is in RNA dot plot format."""
+ if check_image_type( filename, ['EPS'] ):
+ seq = False
+ coor = False
+ pairs = False
+ with open( filename ) as handle:
+ for line in handle:
+ line = line.strip()
+ if line:
+ if line.startswith('/sequence'):
+ seq = True
+ elif line.startswith('/coor'):
+ coor = True
+ elif line.startswith('/pairs'):
+ pairs = True
+ if seq and coor and pairs:
+ return True
+ return False
\ No newline at end of file
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 lib/galaxy/datatypes/util/image_util.py
--- a/lib/galaxy/datatypes/util/image_util.py
+++ b/lib/galaxy/datatypes/util/image_util.py
@@ -71,6 +71,4 @@
return 'pbm'
if format == 'PGM':
return 'pgm'
- if format == 'EPS':
- return 'eps'
return None
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 lib/galaxy/tools/toolbox/base.py
--- a/lib/galaxy/tools/toolbox/base.py
+++ b/lib/galaxy/tools/toolbox/base.py
@@ -394,7 +394,7 @@
section.elems.stub_label( section_id )
self._integrated_tool_panel.append_section( key, section )
elif elem.tag == 'label':
- section.stub_label( key )
+ self._integrated_tool_panel.stub_label( key )
def _write_integrated_tool_panel_config_file( self ):
"""
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 lib/tool_shed/util/hg_util.py
--- a/lib/tool_shed/util/hg_util.py
+++ b/lib/tool_shed/util/hg_util.py
@@ -16,7 +16,7 @@
from mercurial import commands
from mercurial import hg
from mercurial import ui
-from mercurial.changegroup import readbundle
+from mercurial.exchange import readbundle
from mercurial.changegroup import readexactly
from tool_shed.util import basic_util
@@ -26,7 +26,7 @@
INITIAL_CHANGELOG_HASH = '000000000000'
def add_changeset( repo_ui, repo, path_to_filename_in_archive ):
- commands.add( repo_ui, repo, path_to_filename_in_archive )
+ commands.add( repo_ui, repo, str( path_to_filename_in_archive ) )
def archive_repository_revision( app, repository, archive_dir, changeset_revision ):
'''Create an un-versioned archive of a repository.'''
@@ -49,7 +49,7 @@
command line) to a json object.
"""
# See http://www.wstein.org/home/wstein/www/home/was/patches/hg_json
- hg_unbundle10_obj = readbundle( fh, None )
+ hg_unbundle10_obj = readbundle( None, fh, None )
groups = [ group for group in unpack_groups( hg_unbundle10_obj ) ]
return json.dumps( groups, indent=4 )
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 static/scripts/packed/viz/trackster.js
--- a/static/scripts/packed/viz/trackster.js
+++ b/static/scripts/packed/viz/trackster.js
@@ -1,1 +1,1 @@
-var ui=null;var view=null;var browser_router=null;require(["utils/utils","mvc/ui/icon-button","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/select2","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating"],function(b,a){b.cssLoadFile("static/style/jquery.rating.css");b.cssLoadFile("static/style/autocomplete_tagging.css");b.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css");b.cssLoadFile("static/style/library.css");b.cssLoadFile("static/style/trackster.css")});define(["libs/underscore","base","viz/trackster/tracks","viz/visualization"],function(b,e,a,c){var d=e.Base.extend({initialize:function(g){this.baseURL=g},save_viz:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});var g=[];$(".bookmark").each(function(){g.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var h=(view.overview_drawable?view.overview_drawable.config.get_value("name"):null),j={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:h},bookmarks:g};return $.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:view.vis_id,title:view.config.get_value("name"),dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(j)}}).success(function(k){Galaxy.modal.hide();view.vis_id=k.vis_id;view.has_changes=false;window.history.pushState({},"",k.url+window.location.hash)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})},createButtonMenu:function(){var g=this,h=mod_icon_btn.create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){c.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":view.dbkey},function(j){b.each(j,function(k){view.add_drawable(a.object_from_template(k,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new a.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=g.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){g.save_viz()}},{icon_class:"cross-circle",title:"Close",on_click:function(){g.handle_unsaved_changes(view)}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=h;return h},add_bookmarks:function(){var g=this,h=this.baseURL;Galaxy.modal.show({title:"Select dataset for new bookmarks",body:"progress"});$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(j){Galaxy.modal.show({title:"Select dataset for new bookmarks",body:j,buttons:{Cancel:function(){Galaxy.modal.hide()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var k,l=$(this).val();if($(this).attr("name")==="id"){k={hda_id:l}}else{k={ldda_id:l}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:k,dataType:"json"}).then(function(m){for(i=0;i<m.data.length;i++){var n=m.data[i];g.add_bookmark(n[0],n[1])}})});Galaxy.modal.hide()}}})}})},add_bookmark:function(l,j,g){var n=$("#right .unified-panel-body"),p=$("<div/>").addClass("bookmark").appendTo(n);var q=$("<div/>").addClass("position").appendTo(p),m=$("<a href=''/>").text(l).appendTo(q).click(function(){view.go_to(l);return false}),k=$("<div/>").text(j).appendTo(p);if(g){var o=$("<div/>").addClass("delete-icon-container").prependTo(p).click(function(){p.slideUp("fast");p.remove();view.has_changes=true;return false}),h=$("<a href=''/>").addClass("icon-button delete").appendTo(o);k.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return p},create_visualization:function(m,g,l,n,k){var j=this,h=new a.TracksterView(b.extend(m,{header:false}));h.editor=true;$.when(h.load_chroms_deferred).then(function(y){if(g){var w=g.chrom,o=g.start,t=g.end,q=g.overview;if(w&&(o!==undefined)&&t){h.change_chrom(w,o,t)}else{h.change_chrom(y[0].chrom)}}else{h.change_chrom(y[0].chrom)}if(l){var r,p,s;for(var u=0;u<l.length;u++){h.add_drawable(a.object_from_template(l[u],h,h))}}var x;for(var u=0;u<h.drawables.length;u++){if(h.drawables[u].config.get_value("name")===q){h.set_overview(h.drawables[u]);break}}if(n){var v;for(var u=0;u<n.length;u++){v=n[u];j.add_bookmark(v.position,v.annotation,k)}}h.has_changes=false});this.set_up_router({view:h});return h},set_up_router:function(g){new c.TrackBrowserRouter(g);Backbone.history.start()},init_keyboard_nav:function(g){$(document).keyup(function(h){if($(h.srcElement).is(":input")){return}switch(h.which){case 37:g.move_fraction(0.25);break;case 38:var j=Math.round(g.viewport_container.height()/15);g.viewport_container.scrollTop(g.viewport_container.scrollTop()-20);break;case 39:g.move_fraction(-0.25);break;case 40:var j=Math.round(g.viewport_container.height()/15);g.viewport_container.scrollTop(g.viewport_container.scrollTop()+20);break}})},handle_unsaved_changes:function(g){if(g.has_changes){var h=this;Galaxy.modal.show({title:"Close visualization",body:"There are unsaved changes to your visualization which will be lost if you do not save them.",buttons:{Cancel:function(){Galaxy.modal.hide()},"Leave without Saving":function(){$(window).off("beforeunload");window.location=galaxy_config.root+"visualization"},Save:function(){$.when(h.save_viz()).then(function(){window.location=galaxy_config.root+"visualization"})}}})}else{window.location=galaxy_config.root+"visualization"}}});var f=e.Backbone.View.extend({initialize:function(){ui=new d(galaxy_config.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right .unified-panel-title").append("Bookmarks");$("#right .unified-panel-icons").append("<a id='add-bookmark-button' class='icon-button menu-button plus-button' href='javascript:void(0);' title='Add bookmark'></a>");$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(galaxy_config.app.id){this.view_existing()}else{this.view_new()}},view_existing:function(){var g=galaxy_config.app.viz_config;view=ui.create_visualization({container:$("#center .unified-panel-body"),name:g.title,vis_id:g.vis_id,dbkey:g.dbkey},g.viewport,g.tracks,g.bookmarks,true);this.init_editor()},view_new:function(){var g=this;$.ajax({url:galaxy_config.root+"api/genomes?chrom_info=True",data:{},error:function(){alert("Couldn't create new browser.")},success:function(h){Galaxy.modal.show({title:"New Visualization",body:g.template_view_new(h),buttons:{Cancel:function(){window.location=galaxy_config.root+"visualization/list"},Create:function(){g.create_browser($("#new-title").val(),$("#new-dbkey").val());Galaxy.modal.hide()}}});if(galaxy_config.app.default_dbkey){$("#new-dbkey").val(galaxy_config.app.default_dbkey)}$("#new-title").focus();$("select[name='dbkey']").select2();$("#overlay").css("overflow","auto")}})},template_view_new:function(g){var j='<form id="new-browser-form" action="javascript:void(0);" method="post" onsubmit="return false;"><div class="form-row"><label for="new-title">Browser name:</label><div class="form-row-input"><input type="text" name="title" id="new-title" value="Unnamed"></input></div><div style="clear: both;"></div></div><div class="form-row"><label for="new-dbkey">Reference genome build (dbkey): </label><div class="form-row-input"><select name="dbkey" id="new-dbkey">';for(var h=0;h<g.length;h++){j+='<option value="'+g[h][1]+'">'+g[h][0]+"</option>"}j+='</select></div><div style="clear: both;"></div></div><div class="form-row">Is the build not listed here? <a href="'+galaxy_config.root+'user/dbkeys?use_panels=True">Add a Custom Build</a></div></form>';return j},create_browser:function(h,g){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#center .unified-panel-body"),name:h,dbkey:g},galaxy_config.app.gene_region);this.init_editor();view.editor=true},init_editor:function(){$("#center .unified-panel-title").text(view.config.get_value("name")+" ("+view.dbkey+")");if(galaxy_config.app.add_dataset){$.ajax({url:galaxy_config.root+"api/datasets/"+galaxy_config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(g){view.add_drawable(a.object_from_template(g,view,view))}})}$("#add-bookmark-button").click(function(){var h=view.chrom+":"+view.low+"-"+view.high,g="Bookmark description";return ui.add_bookmark(h,g,true)});ui.init_keyboard_nav(view);$(window).on("beforeunload",function(){if(view.has_changes){return"There are unsaved changes to your visualization that will be lost if you leave this page."}})}});return{TracksterUI:d,GalaxyApp:f}});
\ No newline at end of file
+var ui=null;var view=null;var browser_router=null;require(["utils/utils","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/select2","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating"],function(b,a){b.cssLoadFile("static/style/jquery.rating.css");b.cssLoadFile("static/style/autocomplete_tagging.css");b.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css");b.cssLoadFile("static/style/library.css");b.cssLoadFile("static/style/trackster.css")});define(["libs/underscore","base","viz/trackster/tracks","viz/visualization","mvc/ui/icon-button"],function(b,f,a,d,c){var e=f.Base.extend({initialize:function(h){this.baseURL=h},save_viz:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});var h=[];$(".bookmark").each(function(){h.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var j=(view.overview_drawable?view.overview_drawable.config.get_value("name"):null),k={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:j},bookmarks:h};return $.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:view.vis_id,title:view.config.get_value("name"),dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(k)}}).success(function(l){Galaxy.modal.hide();view.vis_id=l.vis_id;view.has_changes=false;window.history.pushState({},"",l.url+window.location.hash)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})},createButtonMenu:function(){var h=this,j=c.create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){d.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":view.dbkey},function(k){b.each(k,function(l){view.add_drawable(a.object_from_template(l,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new a.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=h.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){h.save_viz()}},{icon_class:"cross-circle",title:"Close",on_click:function(){h.handle_unsaved_changes(view)}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=j;return j},add_bookmarks:function(){var h=this,j=this.baseURL;Galaxy.modal.show({title:"Select dataset for new bookmarks",body:"progress"});$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(k){Galaxy.modal.show({title:"Select dataset for new bookmarks",body:k,buttons:{Cancel:function(){Galaxy.modal.hide()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var l,m=$(this).val();if($(this).attr("name")==="id"){l={hda_id:m}}else{l={ldda_id:m}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:l,dataType:"json"}).then(function(n){for(i=0;i<n.data.length;i++){var o=n.data[i];h.add_bookmark(o[0],o[1])}})});Galaxy.modal.hide()}}})}})},add_bookmark:function(m,k,h){var o=$("#right .unified-panel-body"),q=$("<div/>").addClass("bookmark").appendTo(o);var r=$("<div/>").addClass("position").appendTo(q),n=$("<a href=''/>").text(m).appendTo(r).click(function(){view.go_to(m);return false}),l=$("<div/>").text(k).appendTo(q);if(h){var p=$("<div/>").addClass("delete-icon-container").prependTo(q).click(function(){q.slideUp("fast");q.remove();view.has_changes=true;return false}),j=$("<a href=''/>").addClass("icon-button delete").appendTo(p);l.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return q},create_visualization:function(n,h,m,o,l){var k=this,j=new a.TracksterView(b.extend(n,{header:false}));j.editor=true;$.when(j.load_chroms_deferred).then(function(z){if(h){var x=h.chrom,p=h.start,u=h.end,r=h.overview;if(x&&(p!==undefined)&&u){j.change_chrom(x,p,u)}else{j.change_chrom(z[0].chrom)}}else{j.change_chrom(z[0].chrom)}if(m){var s,q,t;for(var v=0;v<m.length;v++){j.add_drawable(a.object_from_template(m[v],j,j))}}var y;for(var v=0;v<j.drawables.length;v++){if(j.drawables[v].config.get_value("name")===r){j.set_overview(j.drawables[v]);break}}if(o){var w;for(var v=0;v<o.length;v++){w=o[v];k.add_bookmark(w.position,w.annotation,l)}}j.has_changes=false});this.set_up_router({view:j});return j},set_up_router:function(h){new d.TrackBrowserRouter(h);Backbone.history.start()},init_keyboard_nav:function(h){$(document).keyup(function(j){if($(j.srcElement).is(":input")){return}switch(j.which){case 37:h.move_fraction(0.25);break;case 38:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()-20);break;case 39:h.move_fraction(-0.25);break;case 40:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()+20);break}})},handle_unsaved_changes:function(h){if(h.has_changes){var j=this;Galaxy.modal.show({title:"Close visualization",body:"There are unsaved changes to your visualization which will be lost if you do not save them.",buttons:{Cancel:function(){Galaxy.modal.hide()},"Leave without Saving":function(){$(window).off("beforeunload");window.location=galaxy_config.root+"visualization"},Save:function(){$.when(j.save_viz()).then(function(){window.location=galaxy_config.root+"visualization"})}}})}else{window.location=galaxy_config.root+"visualization"}}});var g=f.Backbone.View.extend({initialize:function(){ui=new e(galaxy_config.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right .unified-panel-title").append("Bookmarks");$("#right .unified-panel-icons").append("<a id='add-bookmark-button' class='icon-button menu-button plus-button' href='javascript:void(0);' title='Add bookmark'></a>");$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(galaxy_config.app.id){this.view_existing()}else{this.view_new()}},view_existing:function(){var h=galaxy_config.app.viz_config;view=ui.create_visualization({container:$("#center .unified-panel-body"),name:h.title,vis_id:h.vis_id,dbkey:h.dbkey},h.viewport,h.tracks,h.bookmarks,true);this.init_editor()},view_new:function(){var h=this;$.ajax({url:galaxy_config.root+"api/genomes?chrom_info=True",data:{},error:function(){alert("Couldn't create new browser.")},success:function(j){Galaxy.modal.show({title:"New Visualization",body:h.template_view_new(j),buttons:{Cancel:function(){window.location=galaxy_config.root+"visualization/list"},Create:function(){h.create_browser($("#new-title").val(),$("#new-dbkey").val());Galaxy.modal.hide()}}});if(galaxy_config.app.default_dbkey){$("#new-dbkey").val(galaxy_config.app.default_dbkey)}$("#new-title").focus();$("select[name='dbkey']").select2();$("#overlay").css("overflow","auto")}})},template_view_new:function(h){var k='<form id="new-browser-form" action="javascript:void(0);" method="post" onsubmit="return false;"><div class="form-row"><label for="new-title">Browser name:</label><div class="form-row-input"><input type="text" name="title" id="new-title" value="Unnamed"></input></div><div style="clear: both;"></div></div><div class="form-row"><label for="new-dbkey">Reference genome build (dbkey): </label><div class="form-row-input"><select name="dbkey" id="new-dbkey">';for(var j=0;j<h.length;j++){k+='<option value="'+h[j][1]+'">'+h[j][0]+"</option>"}k+='</select></div><div style="clear: both;"></div></div><div class="form-row">Is the build not listed here? <a href="'+galaxy_config.root+'user/dbkeys?use_panels=True">Add a Custom Build</a></div></form>';return k},create_browser:function(j,h){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#center .unified-panel-body"),name:j,dbkey:h},galaxy_config.app.gene_region);this.init_editor();view.editor=true},init_editor:function(){$("#center .unified-panel-title").text(view.config.get_value("name")+" ("+view.dbkey+")");if(galaxy_config.app.add_dataset){$.ajax({url:galaxy_config.root+"api/datasets/"+galaxy_config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(h){view.add_drawable(a.object_from_template(h,view,view))}})}$("#add-bookmark-button").click(function(){var j=view.chrom+":"+view.low+"-"+view.high,h="Bookmark description";return ui.add_bookmark(j,h,true)});ui.init_keyboard_nav(view);$(window).on("beforeunload",function(){if(view.has_changes){return"There are unsaved changes to your visualization that will be lost if you leave this page."}})}});return{TracksterUI:e,GalaxyApp:g}});
\ No newline at end of file
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -12,7 +12,6 @@
[
// load js libraries
'utils/utils',
- 'mvc/ui/icon-button',
'libs/jquery/jquery.event.drag',
'libs/jquery/jquery.event.hover',
'libs/jquery/jquery.mousewheel',
@@ -32,9 +31,8 @@
});
// trackster viewer
-define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization"],
- function(_, base, tracks, visualization) {
-
+define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization", "mvc/ui/icon-button" ],
+ function(_, base, tracks, visualization, mod_icon_btn) {
/**
* User interface controls for trackster
*/
diff -r 50e31bdc72cf9cfdf619342926ac894d1314a469 -r 336f89e2f013b0c547b9955f2d9036f91b2217d8 templates/tagging_common.mako
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -89,7 +89,7 @@
<%def name="render_tool_tagging_elements()"><%
elt_id = int ( floor ( random()*maxint ) )
- tags = trans.app.tag_handler.get_tool_tags( trans )
+ tags = trans.app.tag_handler.get_tool_tags()
%>
${self.render_tagging_element_html(elt_id=elt_id, \
tags=tags, \
@@ -105,7 +105,7 @@
## Build HTML.
<%
elt_id = int ( floor ( random()*maxint ) )
- community_tags = trans.app.tag_handler.get_community_tags( trans, item=tagged_item, limit=5 )
+ community_tags = trans.app.tag_handler.get_community_tags( item=tagged_item, limit=5 )
%>
${self.render_tagging_element_html(elt_id=elt_id, \
tags=community_tags, \
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: dannon: Merged in BjoernGruening/galaxy-central-1/rna_eps_format (pull request #625)
by commits-noreply@bitbucket.org 12 Jan '15
by commits-noreply@bitbucket.org 12 Jan '15
12 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7f27fc6cb8b6/
Changeset: 7f27fc6cb8b6
User: dannon
Date: 2015-01-12 21:55:10+00:00
Summary: Merged in BjoernGruening/galaxy-central-1/rna_eps_format (pull request #625)
Add RNA dotplot matrix as datatype.
Affected #: 3 files
diff -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 -r 7f27fc6cb8b6fa31b24267a25ee375ef346dde02 config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -140,6 +140,7 @@
<datatype extension="rgb" type="galaxy.datatypes.images:Rgb" mimetype="image/rgb"/><datatype extension="pbm" type="galaxy.datatypes.images:Pbm" mimetype="image/pbm"/><datatype extension="pgm" type="galaxy.datatypes.images:Pgm" mimetype="image/pgm"/>
+ <datatype extension="rna_eps" type="galaxy.datatypes.sequence:RNADotPlotMatrix" mimetype="image/eps" display_in_upload="True"/><datatype extension="eps" type="galaxy.datatypes.images:Eps" mimetype="image/eps"/><datatype extension="rast" type="galaxy.datatypes.images:Rast" mimetype="image/rast"/><datatype extension="laj" type="galaxy.datatypes.images:Laj"/>
@@ -304,6 +305,7 @@
<sniffer type="galaxy.datatypes.text:Arff"/><sniffer type="galaxy.datatypes.text:Ipynb"/><sniffer type="galaxy.datatypes.text:Json"/>
+ <sniffer type="galaxy.datatypes.sequence:RNADotPlotMatrix"/><sniffer type="galaxy.datatypes.images:Jpg"/><sniffer type="galaxy.datatypes.images:Png"/><sniffer type="galaxy.datatypes.images:Tiff"/>
diff -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 -r 7f27fc6cb8b6fa31b24267a25ee375ef346dde02 lib/galaxy/datatypes/sequence.py
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -17,7 +17,7 @@
from galaxy.datatypes.checkers import is_gzip
from galaxy.datatypes.sniff import get_test_fname, get_headers
from galaxy.datatypes.metadata import MetadataElement
-
+from galaxy.datatypes.util.image_util import check_image_type
try:
eggs.require( "bx-python" )
@@ -814,3 +814,34 @@
except:
return False
+
+class RNADotPlotMatrix( data.Data ):
+ file_ext = "rna_eps"
+
+ def set_peek( self, dataset, is_multi_byte=False ):
+ if not dataset.dataset.purged:
+ dataset.peek = 'RNA Dot Plot format (Postscript derivative)'
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+
+ def sniff(self, filename):
+ """Determine if the file is in RNA dot plot format."""
+ if check_image_type( filename, ['EPS'] ):
+ seq = False
+ coor = False
+ pairs = False
+ with open( filename ) as handle:
+ for line in handle:
+ line = line.strip()
+ if line:
+ if line.startswith('/sequence'):
+ seq = True
+ elif line.startswith('/coor'):
+ coor = True
+ elif line.startswith('/pairs'):
+ pairs = True
+ if seq and coor and pairs:
+ return True
+ return False
\ No newline at end of file
diff -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 -r 7f27fc6cb8b6fa31b24267a25ee375ef346dde02 lib/galaxy/datatypes/util/image_util.py
--- a/lib/galaxy/datatypes/util/image_util.py
+++ b/lib/galaxy/datatypes/util/image_util.py
@@ -71,6 +71,4 @@
return 'pbm'
if format == 'PGM':
return 'pgm'
- if format == 'EPS':
- return 'eps'
return None
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
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/dd67f14145f7/
Changeset: dd67f14145f7
Branch: rna_eps_format
User: BjoernGruening
Date: 2015-01-06 16:17:39+00:00
Summary: Add RNA dotplot matrix file type. This is a EPS file with additional informations.
Affected #: 2 files
diff -r d50ee9520583c225e48c577ab977f18fd6cb7d6a -r dd67f14145f75cbbe9ab3e73d40088a669139f07 lib/galaxy/datatypes/sequence.py
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -814,3 +814,34 @@
except:
return False
+
+class RNADotPlotMatrix( data.Data ):
+ file_ext = "rna_eps"
+
+ def set_peek( self, dataset, is_multi_byte=False ):
+ if not dataset.dataset.purged:
+ dataset.peek = 'RNA Dot Plot format (Postscript derivative)'
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+
+ def sniff(self, filename, image=None):
+ """Determine if the file is in RNA dot plot format."""
+ seq = False
+ coor = False
+ pairs = False
+ with open( filename ) as handle:
+ for line in handle:
+ line = line.strip()
+ if line:
+ if line.startswith('/sequence'):
+ seq = True
+ elif line.startswith('/coor'):
+ coor = True
+ elif line.startswith('/pairs'):
+ pairs = True
+ if seq and coor and pairs:
+ return True
+ return False
+
diff -r d50ee9520583c225e48c577ab977f18fd6cb7d6a -r dd67f14145f75cbbe9ab3e73d40088a669139f07 lib/galaxy/datatypes/util/image_util.py
--- a/lib/galaxy/datatypes/util/image_util.py
+++ b/lib/galaxy/datatypes/util/image_util.py
@@ -71,6 +71,4 @@
return 'pbm'
if format == 'PGM':
return 'pgm'
- if format == 'EPS':
- return 'eps'
return None
https://bitbucket.org/galaxy/galaxy-central/commits/e89b5465e914/
Changeset: e89b5465e914
Branch: rna_eps_format
User: BjoernGruening
Date: 2015-01-06 16:18:01+00:00
Summary: add rna_eps filetype
Affected #: 1 file
diff -r dd67f14145f75cbbe9ab3e73d40088a669139f07 -r e89b5465e914bec84d946c6163b415ebd57a038e config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -140,6 +140,7 @@
<datatype extension="rgb" type="galaxy.datatypes.images:Rgb" mimetype="image/rgb"/><datatype extension="pbm" type="galaxy.datatypes.images:Pbm" mimetype="image/pbm"/><datatype extension="pgm" type="galaxy.datatypes.images:Pgm" mimetype="image/pgm"/>
+ <datatype extension="rna_eps" type="galaxy.datatypes.sequence:RNADotPlotMatrix" mimetype="image/eps" display_in_upload="True"/><datatype extension="eps" type="galaxy.datatypes.images:Eps" mimetype="image/eps"/><datatype extension="rast" type="galaxy.datatypes.images:Rast" mimetype="image/rast"/><datatype extension="laj" type="galaxy.datatypes.images:Laj"/>
@@ -302,6 +303,7 @@
<sniffer type="galaxy.datatypes.text:Arff"/><sniffer type="galaxy.datatypes.text:Ipynb"/><sniffer type="galaxy.datatypes.text:Json"/>
+ <sniffer type="galaxy.datatypes.sequence:RNADotPlotMatrix"/><sniffer type="galaxy.datatypes.images:Jpg"/><sniffer type="galaxy.datatypes.images:Png"/><sniffer type="galaxy.datatypes.images:Tiff"/>
https://bitbucket.org/galaxy/galaxy-central/commits/f5278f9e74a2/
Changeset: f5278f9e74a2
Branch: rna_eps_format
User: BjoernGruening
Date: 2015-01-06 17:54:03+00:00
Summary: Only walk through the file if it is a EPS file.
Affected #: 1 file
diff -r e89b5465e914bec84d946c6163b415ebd57a038e -r f5278f9e74a2e2855bf6661dc998d37abc6f86ff lib/galaxy/datatypes/sequence.py
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -17,7 +17,7 @@
from galaxy.datatypes.checkers import is_gzip
from galaxy.datatypes.sniff import get_test_fname, get_headers
from galaxy.datatypes.metadata import MetadataElement
-
+from galaxy.datatypes.util.image_util import check_image_type
try:
eggs.require( "bx-python" )
@@ -826,22 +826,22 @@
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
- def sniff(self, filename, image=None):
+ def sniff(self, filename):
"""Determine if the file is in RNA dot plot format."""
- seq = False
- coor = False
- pairs = False
- with open( filename ) as handle:
- for line in handle:
- line = line.strip()
- if line:
- if line.startswith('/sequence'):
- seq = True
- elif line.startswith('/coor'):
- coor = True
- elif line.startswith('/pairs'):
- pairs = True
- if seq and coor and pairs:
- return True
- return False
-
+ if check_image_type( filename, ['EPS'] ):
+ seq = False
+ coor = False
+ pairs = False
+ with open( filename ) as handle:
+ for line in handle:
+ line = line.strip()
+ if line:
+ if line.startswith('/sequence'):
+ seq = True
+ elif line.startswith('/coor'):
+ coor = True
+ elif line.startswith('/pairs'):
+ pairs = True
+ if seq and coor and pairs:
+ return True
+ return False
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/7f27fc6cb8b6/
Changeset: 7f27fc6cb8b6
User: dannon
Date: 2015-01-12 21:55:10+00:00
Summary: Merged in BjoernGruening/galaxy-central-1/rna_eps_format (pull request #625)
Add RNA dotplot matrix as datatype.
Affected #: 3 files
diff -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 -r 7f27fc6cb8b6fa31b24267a25ee375ef346dde02 config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -140,6 +140,7 @@
<datatype extension="rgb" type="galaxy.datatypes.images:Rgb" mimetype="image/rgb"/><datatype extension="pbm" type="galaxy.datatypes.images:Pbm" mimetype="image/pbm"/><datatype extension="pgm" type="galaxy.datatypes.images:Pgm" mimetype="image/pgm"/>
+ <datatype extension="rna_eps" type="galaxy.datatypes.sequence:RNADotPlotMatrix" mimetype="image/eps" display_in_upload="True"/><datatype extension="eps" type="galaxy.datatypes.images:Eps" mimetype="image/eps"/><datatype extension="rast" type="galaxy.datatypes.images:Rast" mimetype="image/rast"/><datatype extension="laj" type="galaxy.datatypes.images:Laj"/>
@@ -304,6 +305,7 @@
<sniffer type="galaxy.datatypes.text:Arff"/><sniffer type="galaxy.datatypes.text:Ipynb"/><sniffer type="galaxy.datatypes.text:Json"/>
+ <sniffer type="galaxy.datatypes.sequence:RNADotPlotMatrix"/><sniffer type="galaxy.datatypes.images:Jpg"/><sniffer type="galaxy.datatypes.images:Png"/><sniffer type="galaxy.datatypes.images:Tiff"/>
diff -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 -r 7f27fc6cb8b6fa31b24267a25ee375ef346dde02 lib/galaxy/datatypes/sequence.py
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -17,7 +17,7 @@
from galaxy.datatypes.checkers import is_gzip
from galaxy.datatypes.sniff import get_test_fname, get_headers
from galaxy.datatypes.metadata import MetadataElement
-
+from galaxy.datatypes.util.image_util import check_image_type
try:
eggs.require( "bx-python" )
@@ -814,3 +814,34 @@
except:
return False
+
+class RNADotPlotMatrix( data.Data ):
+ file_ext = "rna_eps"
+
+ def set_peek( self, dataset, is_multi_byte=False ):
+ if not dataset.dataset.purged:
+ dataset.peek = 'RNA Dot Plot format (Postscript derivative)'
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+
+ def sniff(self, filename):
+ """Determine if the file is in RNA dot plot format."""
+ if check_image_type( filename, ['EPS'] ):
+ seq = False
+ coor = False
+ pairs = False
+ with open( filename ) as handle:
+ for line in handle:
+ line = line.strip()
+ if line:
+ if line.startswith('/sequence'):
+ seq = True
+ elif line.startswith('/coor'):
+ coor = True
+ elif line.startswith('/pairs'):
+ pairs = True
+ if seq and coor and pairs:
+ return True
+ return False
\ No newline at end of file
diff -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 -r 7f27fc6cb8b6fa31b24267a25ee375ef346dde02 lib/galaxy/datatypes/util/image_util.py
--- a/lib/galaxy/datatypes/util/image_util.py
+++ b/lib/galaxy/datatypes/util/image_util.py
@@ -71,6 +71,4 @@
return 'pbm'
if format == 'PGM':
return 'pgm'
- if format == 'EPS':
- return 'eps'
return None
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: Fix to UI modularization & trackster: add mod_icon_btn to the proper closure; Fix to TagManager refactoring: remove trans from tagging_common.mako method calls
by commits-noreply@bitbucket.org 12 Jan '15
by commits-noreply@bitbucket.org 12 Jan '15
12 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/748cb48d79e8/
Changeset: 748cb48d79e8
User: carlfeberhard
Date: 2015-01-12 21:06:43+00:00
Summary: Fix to UI modularization & trackster: add mod_icon_btn to the proper closure; Fix to TagManager refactoring: remove trans from tagging_common.mako method calls
Affected #: 4 files
diff -r b5c7266dbb69f81864d96247ff11be42246e94de -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 client/galaxy/scripts/viz/trackster.js
--- a/client/galaxy/scripts/viz/trackster.js
+++ b/client/galaxy/scripts/viz/trackster.js
@@ -12,7 +12,6 @@
[
// load js libraries
'utils/utils',
- 'mvc/ui/icon-button',
'libs/jquery/jquery.event.drag',
'libs/jquery/jquery.event.hover',
'libs/jquery/jquery.mousewheel',
@@ -32,9 +31,8 @@
});
// trackster viewer
-define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization"],
- function(_, base, tracks, visualization) {
-
+define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization", "mvc/ui/icon-button" ],
+ function(_, base, tracks, visualization, mod_icon_btn) {
/**
* User interface controls for trackster
*/
diff -r b5c7266dbb69f81864d96247ff11be42246e94de -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 static/scripts/packed/viz/trackster.js
--- a/static/scripts/packed/viz/trackster.js
+++ b/static/scripts/packed/viz/trackster.js
@@ -1,1 +1,1 @@
-var ui=null;var view=null;var browser_router=null;require(["utils/utils","mvc/ui/icon-button","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/select2","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating"],function(b,a){b.cssLoadFile("static/style/jquery.rating.css");b.cssLoadFile("static/style/autocomplete_tagging.css");b.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css");b.cssLoadFile("static/style/library.css");b.cssLoadFile("static/style/trackster.css")});define(["libs/underscore","base","viz/trackster/tracks","viz/visualization"],function(b,e,a,c){var d=e.Base.extend({initialize:function(g){this.baseURL=g},save_viz:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});var g=[];$(".bookmark").each(function(){g.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var h=(view.overview_drawable?view.overview_drawable.config.get_value("name"):null),j={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:h},bookmarks:g};return $.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:view.vis_id,title:view.config.get_value("name"),dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(j)}}).success(function(k){Galaxy.modal.hide();view.vis_id=k.vis_id;view.has_changes=false;window.history.pushState({},"",k.url+window.location.hash)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})},createButtonMenu:function(){var g=this,h=mod_icon_btn.create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){c.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":view.dbkey},function(j){b.each(j,function(k){view.add_drawable(a.object_from_template(k,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new a.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=g.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){g.save_viz()}},{icon_class:"cross-circle",title:"Close",on_click:function(){g.handle_unsaved_changes(view)}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=h;return h},add_bookmarks:function(){var g=this,h=this.baseURL;Galaxy.modal.show({title:"Select dataset for new bookmarks",body:"progress"});$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(j){Galaxy.modal.show({title:"Select dataset for new bookmarks",body:j,buttons:{Cancel:function(){Galaxy.modal.hide()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var k,l=$(this).val();if($(this).attr("name")==="id"){k={hda_id:l}}else{k={ldda_id:l}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:k,dataType:"json"}).then(function(m){for(i=0;i<m.data.length;i++){var n=m.data[i];g.add_bookmark(n[0],n[1])}})});Galaxy.modal.hide()}}})}})},add_bookmark:function(l,j,g){var n=$("#right .unified-panel-body"),p=$("<div/>").addClass("bookmark").appendTo(n);var q=$("<div/>").addClass("position").appendTo(p),m=$("<a href=''/>").text(l).appendTo(q).click(function(){view.go_to(l);return false}),k=$("<div/>").text(j).appendTo(p);if(g){var o=$("<div/>").addClass("delete-icon-container").prependTo(p).click(function(){p.slideUp("fast");p.remove();view.has_changes=true;return false}),h=$("<a href=''/>").addClass("icon-button delete").appendTo(o);k.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return p},create_visualization:function(m,g,l,n,k){var j=this,h=new a.TracksterView(b.extend(m,{header:false}));h.editor=true;$.when(h.load_chroms_deferred).then(function(y){if(g){var w=g.chrom,o=g.start,t=g.end,q=g.overview;if(w&&(o!==undefined)&&t){h.change_chrom(w,o,t)}else{h.change_chrom(y[0].chrom)}}else{h.change_chrom(y[0].chrom)}if(l){var r,p,s;for(var u=0;u<l.length;u++){h.add_drawable(a.object_from_template(l[u],h,h))}}var x;for(var u=0;u<h.drawables.length;u++){if(h.drawables[u].config.get_value("name")===q){h.set_overview(h.drawables[u]);break}}if(n){var v;for(var u=0;u<n.length;u++){v=n[u];j.add_bookmark(v.position,v.annotation,k)}}h.has_changes=false});this.set_up_router({view:h});return h},set_up_router:function(g){new c.TrackBrowserRouter(g);Backbone.history.start()},init_keyboard_nav:function(g){$(document).keyup(function(h){if($(h.srcElement).is(":input")){return}switch(h.which){case 37:g.move_fraction(0.25);break;case 38:var j=Math.round(g.viewport_container.height()/15);g.viewport_container.scrollTop(g.viewport_container.scrollTop()-20);break;case 39:g.move_fraction(-0.25);break;case 40:var j=Math.round(g.viewport_container.height()/15);g.viewport_container.scrollTop(g.viewport_container.scrollTop()+20);break}})},handle_unsaved_changes:function(g){if(g.has_changes){var h=this;Galaxy.modal.show({title:"Close visualization",body:"There are unsaved changes to your visualization which will be lost if you do not save them.",buttons:{Cancel:function(){Galaxy.modal.hide()},"Leave without Saving":function(){$(window).off("beforeunload");window.location=galaxy_config.root+"visualization"},Save:function(){$.when(h.save_viz()).then(function(){window.location=galaxy_config.root+"visualization"})}}})}else{window.location=galaxy_config.root+"visualization"}}});var f=e.Backbone.View.extend({initialize:function(){ui=new d(galaxy_config.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right .unified-panel-title").append("Bookmarks");$("#right .unified-panel-icons").append("<a id='add-bookmark-button' class='icon-button menu-button plus-button' href='javascript:void(0);' title='Add bookmark'></a>");$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(galaxy_config.app.id){this.view_existing()}else{this.view_new()}},view_existing:function(){var g=galaxy_config.app.viz_config;view=ui.create_visualization({container:$("#center .unified-panel-body"),name:g.title,vis_id:g.vis_id,dbkey:g.dbkey},g.viewport,g.tracks,g.bookmarks,true);this.init_editor()},view_new:function(){var g=this;$.ajax({url:galaxy_config.root+"api/genomes?chrom_info=True",data:{},error:function(){alert("Couldn't create new browser.")},success:function(h){Galaxy.modal.show({title:"New Visualization",body:g.template_view_new(h),buttons:{Cancel:function(){window.location=galaxy_config.root+"visualization/list"},Create:function(){g.create_browser($("#new-title").val(),$("#new-dbkey").val());Galaxy.modal.hide()}}});if(galaxy_config.app.default_dbkey){$("#new-dbkey").val(galaxy_config.app.default_dbkey)}$("#new-title").focus();$("select[name='dbkey']").select2();$("#overlay").css("overflow","auto")}})},template_view_new:function(g){var j='<form id="new-browser-form" action="javascript:void(0);" method="post" onsubmit="return false;"><div class="form-row"><label for="new-title">Browser name:</label><div class="form-row-input"><input type="text" name="title" id="new-title" value="Unnamed"></input></div><div style="clear: both;"></div></div><div class="form-row"><label for="new-dbkey">Reference genome build (dbkey): </label><div class="form-row-input"><select name="dbkey" id="new-dbkey">';for(var h=0;h<g.length;h++){j+='<option value="'+g[h][1]+'">'+g[h][0]+"</option>"}j+='</select></div><div style="clear: both;"></div></div><div class="form-row">Is the build not listed here? <a href="'+galaxy_config.root+'user/dbkeys?use_panels=True">Add a Custom Build</a></div></form>';return j},create_browser:function(h,g){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#center .unified-panel-body"),name:h,dbkey:g},galaxy_config.app.gene_region);this.init_editor();view.editor=true},init_editor:function(){$("#center .unified-panel-title").text(view.config.get_value("name")+" ("+view.dbkey+")");if(galaxy_config.app.add_dataset){$.ajax({url:galaxy_config.root+"api/datasets/"+galaxy_config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(g){view.add_drawable(a.object_from_template(g,view,view))}})}$("#add-bookmark-button").click(function(){var h=view.chrom+":"+view.low+"-"+view.high,g="Bookmark description";return ui.add_bookmark(h,g,true)});ui.init_keyboard_nav(view);$(window).on("beforeunload",function(){if(view.has_changes){return"There are unsaved changes to your visualization that will be lost if you leave this page."}})}});return{TracksterUI:d,GalaxyApp:f}});
\ No newline at end of file
+var ui=null;var view=null;var browser_router=null;require(["utils/utils","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/select2","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating"],function(b,a){b.cssLoadFile("static/style/jquery.rating.css");b.cssLoadFile("static/style/autocomplete_tagging.css");b.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css");b.cssLoadFile("static/style/library.css");b.cssLoadFile("static/style/trackster.css")});define(["libs/underscore","base","viz/trackster/tracks","viz/visualization","mvc/ui/icon-button"],function(b,f,a,d,c){var e=f.Base.extend({initialize:function(h){this.baseURL=h},save_viz:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});var h=[];$(".bookmark").each(function(){h.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var j=(view.overview_drawable?view.overview_drawable.config.get_value("name"):null),k={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:j},bookmarks:h};return $.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:view.vis_id,title:view.config.get_value("name"),dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(k)}}).success(function(l){Galaxy.modal.hide();view.vis_id=l.vis_id;view.has_changes=false;window.history.pushState({},"",l.url+window.location.hash)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})},createButtonMenu:function(){var h=this,j=c.create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){d.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":view.dbkey},function(k){b.each(k,function(l){view.add_drawable(a.object_from_template(l,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new a.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=h.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){h.save_viz()}},{icon_class:"cross-circle",title:"Close",on_click:function(){h.handle_unsaved_changes(view)}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=j;return j},add_bookmarks:function(){var h=this,j=this.baseURL;Galaxy.modal.show({title:"Select dataset for new bookmarks",body:"progress"});$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(k){Galaxy.modal.show({title:"Select dataset for new bookmarks",body:k,buttons:{Cancel:function(){Galaxy.modal.hide()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var l,m=$(this).val();if($(this).attr("name")==="id"){l={hda_id:m}}else{l={ldda_id:m}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:l,dataType:"json"}).then(function(n){for(i=0;i<n.data.length;i++){var o=n.data[i];h.add_bookmark(o[0],o[1])}})});Galaxy.modal.hide()}}})}})},add_bookmark:function(m,k,h){var o=$("#right .unified-panel-body"),q=$("<div/>").addClass("bookmark").appendTo(o);var r=$("<div/>").addClass("position").appendTo(q),n=$("<a href=''/>").text(m).appendTo(r).click(function(){view.go_to(m);return false}),l=$("<div/>").text(k).appendTo(q);if(h){var p=$("<div/>").addClass("delete-icon-container").prependTo(q).click(function(){q.slideUp("fast");q.remove();view.has_changes=true;return false}),j=$("<a href=''/>").addClass("icon-button delete").appendTo(p);l.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return q},create_visualization:function(n,h,m,o,l){var k=this,j=new a.TracksterView(b.extend(n,{header:false}));j.editor=true;$.when(j.load_chroms_deferred).then(function(z){if(h){var x=h.chrom,p=h.start,u=h.end,r=h.overview;if(x&&(p!==undefined)&&u){j.change_chrom(x,p,u)}else{j.change_chrom(z[0].chrom)}}else{j.change_chrom(z[0].chrom)}if(m){var s,q,t;for(var v=0;v<m.length;v++){j.add_drawable(a.object_from_template(m[v],j,j))}}var y;for(var v=0;v<j.drawables.length;v++){if(j.drawables[v].config.get_value("name")===r){j.set_overview(j.drawables[v]);break}}if(o){var w;for(var v=0;v<o.length;v++){w=o[v];k.add_bookmark(w.position,w.annotation,l)}}j.has_changes=false});this.set_up_router({view:j});return j},set_up_router:function(h){new d.TrackBrowserRouter(h);Backbone.history.start()},init_keyboard_nav:function(h){$(document).keyup(function(j){if($(j.srcElement).is(":input")){return}switch(j.which){case 37:h.move_fraction(0.25);break;case 38:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()-20);break;case 39:h.move_fraction(-0.25);break;case 40:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()+20);break}})},handle_unsaved_changes:function(h){if(h.has_changes){var j=this;Galaxy.modal.show({title:"Close visualization",body:"There are unsaved changes to your visualization which will be lost if you do not save them.",buttons:{Cancel:function(){Galaxy.modal.hide()},"Leave without Saving":function(){$(window).off("beforeunload");window.location=galaxy_config.root+"visualization"},Save:function(){$.when(j.save_viz()).then(function(){window.location=galaxy_config.root+"visualization"})}}})}else{window.location=galaxy_config.root+"visualization"}}});var g=f.Backbone.View.extend({initialize:function(){ui=new e(galaxy_config.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right .unified-panel-title").append("Bookmarks");$("#right .unified-panel-icons").append("<a id='add-bookmark-button' class='icon-button menu-button plus-button' href='javascript:void(0);' title='Add bookmark'></a>");$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(galaxy_config.app.id){this.view_existing()}else{this.view_new()}},view_existing:function(){var h=galaxy_config.app.viz_config;view=ui.create_visualization({container:$("#center .unified-panel-body"),name:h.title,vis_id:h.vis_id,dbkey:h.dbkey},h.viewport,h.tracks,h.bookmarks,true);this.init_editor()},view_new:function(){var h=this;$.ajax({url:galaxy_config.root+"api/genomes?chrom_info=True",data:{},error:function(){alert("Couldn't create new browser.")},success:function(j){Galaxy.modal.show({title:"New Visualization",body:h.template_view_new(j),buttons:{Cancel:function(){window.location=galaxy_config.root+"visualization/list"},Create:function(){h.create_browser($("#new-title").val(),$("#new-dbkey").val());Galaxy.modal.hide()}}});if(galaxy_config.app.default_dbkey){$("#new-dbkey").val(galaxy_config.app.default_dbkey)}$("#new-title").focus();$("select[name='dbkey']").select2();$("#overlay").css("overflow","auto")}})},template_view_new:function(h){var k='<form id="new-browser-form" action="javascript:void(0);" method="post" onsubmit="return false;"><div class="form-row"><label for="new-title">Browser name:</label><div class="form-row-input"><input type="text" name="title" id="new-title" value="Unnamed"></input></div><div style="clear: both;"></div></div><div class="form-row"><label for="new-dbkey">Reference genome build (dbkey): </label><div class="form-row-input"><select name="dbkey" id="new-dbkey">';for(var j=0;j<h.length;j++){k+='<option value="'+h[j][1]+'">'+h[j][0]+"</option>"}k+='</select></div><div style="clear: both;"></div></div><div class="form-row">Is the build not listed here? <a href="'+galaxy_config.root+'user/dbkeys?use_panels=True">Add a Custom Build</a></div></form>';return k},create_browser:function(j,h){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#center .unified-panel-body"),name:j,dbkey:h},galaxy_config.app.gene_region);this.init_editor();view.editor=true},init_editor:function(){$("#center .unified-panel-title").text(view.config.get_value("name")+" ("+view.dbkey+")");if(galaxy_config.app.add_dataset){$.ajax({url:galaxy_config.root+"api/datasets/"+galaxy_config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(h){view.add_drawable(a.object_from_template(h,view,view))}})}$("#add-bookmark-button").click(function(){var j=view.chrom+":"+view.low+"-"+view.high,h="Bookmark description";return ui.add_bookmark(j,h,true)});ui.init_keyboard_nav(view);$(window).on("beforeunload",function(){if(view.has_changes){return"There are unsaved changes to your visualization that will be lost if you leave this page."}})}});return{TracksterUI:e,GalaxyApp:g}});
\ No newline at end of file
diff -r b5c7266dbb69f81864d96247ff11be42246e94de -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -12,7 +12,6 @@
[
// load js libraries
'utils/utils',
- 'mvc/ui/icon-button',
'libs/jquery/jquery.event.drag',
'libs/jquery/jquery.event.hover',
'libs/jquery/jquery.mousewheel',
@@ -32,9 +31,8 @@
});
// trackster viewer
-define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization"],
- function(_, base, tracks, visualization) {
-
+define( ["libs/underscore", "base", "viz/trackster/tracks", "viz/visualization", "mvc/ui/icon-button" ],
+ function(_, base, tracks, visualization, mod_icon_btn) {
/**
* User interface controls for trackster
*/
diff -r b5c7266dbb69f81864d96247ff11be42246e94de -r 748cb48d79e8c3770623a0a76e2b56e332b19cc7 templates/tagging_common.mako
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -89,7 +89,7 @@
<%def name="render_tool_tagging_elements()"><%
elt_id = int ( floor ( random()*maxint ) )
- tags = trans.app.tag_handler.get_tool_tags( trans )
+ tags = trans.app.tag_handler.get_tool_tags()
%>
${self.render_tagging_element_html(elt_id=elt_id, \
tags=tags, \
@@ -105,7 +105,7 @@
## Build HTML.
<%
elt_id = int ( floor ( random()*maxint ) )
- community_tags = trans.app.tag_handler.get_community_tags( trans, item=tagged_item, limit=5 )
+ community_tags = trans.app.tag_handler.get_community_tags( item=tagged_item, limit=5 )
%>
${self.render_tagging_element_html(elt_id=elt_id, \
tags=community_tags, \
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: jmchilton: Fix typo introduced in 67ae665.
by commits-noreply@bitbucket.org 12 Jan '15
by commits-noreply@bitbucket.org 12 Jan '15
12 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b5c7266dbb69/
Changeset: b5c7266dbb69
User: jmchilton
Date: 2015-01-12 20:36:05+00:00
Summary: Fix typo introduced in 67ae665.
Affected #: 1 file
diff -r 4c98158b1f031fbaee88ca7b04bf2be84cb507e9 -r b5c7266dbb69f81864d96247ff11be42246e94de lib/galaxy/tools/toolbox/base.py
--- a/lib/galaxy/tools/toolbox/base.py
+++ b/lib/galaxy/tools/toolbox/base.py
@@ -394,7 +394,7 @@
section.elems.stub_label( section_id )
self._integrated_tool_panel.append_section( key, section )
elif elem.tag == 'label':
- section.stub_label( key )
+ self._integrated_tool_panel.stub_label( key )
def _write_integrated_tool_panel_config_file( self ):
"""
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
12 Jan '15
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 37fb7f60c62f9f3b28645483d08fd2e8cd195a85
https://github.com/galaxyproject/usegalaxy-playbook/commit/37fb7f60c62f9f3b…
Author: martenson <cech.marten(a)gmail.com>
Date: 2015-01-12 (Mon, 12 Jan 2015)
Changed paths:
M templates/galaxy/common/static/welcome.html.j2
Log Message:
-----------
update the cycling event name
1
0
commit/galaxy-central: dannon: Merged in davebgx/galaxy-central (pull request #626)
by commits-noreply@bitbucket.org 12 Jan '15
by commits-noreply@bitbucket.org 12 Jan '15
12 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4c98158b1f03/
Changeset: 4c98158b1f03
User: dannon
Date: 2015-01-12 15:19:57+00:00
Summary: Merged in davebgx/galaxy-central (pull request #626)
Upgrade mercurial egg to 3.2.4.
Affected #: 2 files
diff -r 85e8fb54b2851454a000cab23d57ce102af6aa30 -r 4c98158b1f031fbaee88ca7b04bf2be84cb507e9 eggs.ini
--- a/eggs.ini
+++ b/eggs.ini
@@ -15,7 +15,7 @@
bx_python = 0.7.2
Cheetah = 2.2.2
MarkupSafe = 0.12
-mercurial = 2.2.3
+mercurial = 3.2.4
MySQL_python = 1.2.3c1
PyRods = 3.2.4
numpy = 1.6.0
diff -r 85e8fb54b2851454a000cab23d57ce102af6aa30 -r 4c98158b1f031fbaee88ca7b04bf2be84cb507e9 lib/tool_shed/util/hg_util.py
--- a/lib/tool_shed/util/hg_util.py
+++ b/lib/tool_shed/util/hg_util.py
@@ -16,7 +16,7 @@
from mercurial import commands
from mercurial import hg
from mercurial import ui
-from mercurial.changegroup import readbundle
+from mercurial.exchange import readbundle
from mercurial.changegroup import readexactly
from tool_shed.util import basic_util
@@ -26,7 +26,7 @@
INITIAL_CHANGELOG_HASH = '000000000000'
def add_changeset( repo_ui, repo, path_to_filename_in_archive ):
- commands.add( repo_ui, repo, path_to_filename_in_archive )
+ commands.add( repo_ui, repo, str( path_to_filename_in_archive ) )
def archive_repository_revision( app, repository, archive_dir, changeset_revision ):
'''Create an un-versioned archive of a repository.'''
@@ -49,7 +49,7 @@
command line) to a json object.
"""
# See http://www.wstein.org/home/wstein/www/home/was/patches/hg_json
- hg_unbundle10_obj = readbundle( fh, None )
+ hg_unbundle10_obj = readbundle( None, fh, None )
groups = [ group for group in unpack_groups( hg_unbundle10_obj ) ]
return json.dumps( groups, indent=4 )
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/625bf1fd88ee/
Changeset: 625bf1fd88ee
User: davebgx
Date: 2015-01-07 18:48:17+00:00
Summary: Upgrade mercurial egg to 3.2.4.
Affected #: 2 files
diff -r 81e27001166b0e01b89eabc79d32b0adf72d5ef5 -r 625bf1fd88ee1258998ba378c90ccbc3bccdfbff eggs.ini
--- a/eggs.ini
+++ b/eggs.ini
@@ -15,7 +15,7 @@
bx_python = 0.7.2
Cheetah = 2.2.2
MarkupSafe = 0.12
-mercurial = 2.2.3
+mercurial = 3.2.4
MySQL_python = 1.2.3c1
PyRods = 3.2.4
numpy = 1.6.0
diff -r 81e27001166b0e01b89eabc79d32b0adf72d5ef5 -r 625bf1fd88ee1258998ba378c90ccbc3bccdfbff lib/tool_shed/util/hg_util.py
--- a/lib/tool_shed/util/hg_util.py
+++ b/lib/tool_shed/util/hg_util.py
@@ -16,7 +16,7 @@
from mercurial import commands
from mercurial import hg
from mercurial import ui
-from mercurial.changegroup import readbundle
+from mercurial.exchange import readbundle
from mercurial.changegroup import readexactly
from tool_shed.util import basic_util
@@ -26,7 +26,7 @@
INITIAL_CHANGELOG_HASH = '000000000000'
def add_changeset( repo_ui, repo, path_to_filename_in_archive ):
- commands.add( repo_ui, repo, path_to_filename_in_archive )
+ commands.add( repo_ui, repo, str( path_to_filename_in_archive ) )
def archive_repository_revision( app, repository, archive_dir, changeset_revision ):
'''Create an un-versioned archive of a repository.'''
@@ -49,7 +49,7 @@
command line) to a json object.
"""
# See http://www.wstein.org/home/wstein/www/home/was/patches/hg_json
- hg_unbundle10_obj = readbundle( fh, None )
+ hg_unbundle10_obj = readbundle( None, fh, None )
groups = [ group for group in unpack_groups( hg_unbundle10_obj ) ]
return json.dumps( groups, indent=4 )
https://bitbucket.org/galaxy/galaxy-central/commits/4c98158b1f03/
Changeset: 4c98158b1f03
User: dannon
Date: 2015-01-12 15:19:57+00:00
Summary: Merged in davebgx/galaxy-central (pull request #626)
Upgrade mercurial egg to 3.2.4.
Affected #: 2 files
diff -r 85e8fb54b2851454a000cab23d57ce102af6aa30 -r 4c98158b1f031fbaee88ca7b04bf2be84cb507e9 eggs.ini
--- a/eggs.ini
+++ b/eggs.ini
@@ -15,7 +15,7 @@
bx_python = 0.7.2
Cheetah = 2.2.2
MarkupSafe = 0.12
-mercurial = 2.2.3
+mercurial = 3.2.4
MySQL_python = 1.2.3c1
PyRods = 3.2.4
numpy = 1.6.0
diff -r 85e8fb54b2851454a000cab23d57ce102af6aa30 -r 4c98158b1f031fbaee88ca7b04bf2be84cb507e9 lib/tool_shed/util/hg_util.py
--- a/lib/tool_shed/util/hg_util.py
+++ b/lib/tool_shed/util/hg_util.py
@@ -16,7 +16,7 @@
from mercurial import commands
from mercurial import hg
from mercurial import ui
-from mercurial.changegroup import readbundle
+from mercurial.exchange import readbundle
from mercurial.changegroup import readexactly
from tool_shed.util import basic_util
@@ -26,7 +26,7 @@
INITIAL_CHANGELOG_HASH = '000000000000'
def add_changeset( repo_ui, repo, path_to_filename_in_archive ):
- commands.add( repo_ui, repo, path_to_filename_in_archive )
+ commands.add( repo_ui, repo, str( path_to_filename_in_archive ) )
def archive_repository_revision( app, repository, archive_dir, changeset_revision ):
'''Create an un-versioned archive of a repository.'''
@@ -49,7 +49,7 @@
command line) to a json object.
"""
# See http://www.wstein.org/home/wstein/www/home/was/patches/hg_json
- hg_unbundle10_obj = readbundle( fh, None )
+ hg_unbundle10_obj = readbundle( None, fh, None )
groups = [ group for group in unpack_groups( hg_unbundle10_obj ) ]
return json.dumps( groups, indent=4 )
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