commit/galaxy-central: 45 new changesets
45 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/02a1a5f1132f/ Changeset: 02a1a5f1132f User: dan Date: 2015-02-27 20:50:13+00:00 Summary: Allow External display applications to use Tool Data Tables. Affected #: 7 files diff -r 0468d285f89c799559926c94f300c42d05e8c47a -r 02a1a5f1132f722100097afef1be8d6b9725e783 lib/galaxy/app.py --- a/lib/galaxy/app.py +++ b/lib/galaxy/app.py @@ -88,7 +88,7 @@ # Load proprietary datatype converters and display applications. self.installed_repository_manager.load_proprietary_converters_and_display_applications() # Load datatype display applications defined in local datatypes_conf.xml - self.datatypes_registry.load_display_applications() + self.datatypes_registry.load_display_applications( self ) # Load datatype converters defined in local datatypes_conf.xml self.datatypes_registry.load_datatype_converters( self.toolbox ) # Load external metadata tool diff -r 0468d285f89c799559926c94f300c42d05e8c47a -r 02a1a5f1132f722100097afef1be8d6b9725e783 lib/galaxy/datatypes/display_applications/application.py --- a/lib/galaxy/datatypes/display_applications/application.py +++ b/lib/galaxy/datatypes/display_applications/application.py @@ -80,21 +80,57 @@ return True class DynamicDisplayApplicationBuilder( object ): - @classmethod + def __init__( self, elem, display_application, build_sites ): - rval = [] filename = None + data_table = None if elem.get( 'site_type', None ) is not None: filename = build_sites.get( elem.get( 'site_type' ) ) else: filename = elem.get( 'from_file', None ) - assert filename is not None, 'Filename and id attributes required for dynamic_links' + if filename is None: + data_table_name = elem.get( 'from_data_table', None ) + if data_table_name: + data_table = display_application.app.tool_data_tables.get( data_table_name, None ) + assert data_table is not None, 'Unable to find data table named "%s".' % data_table_name + + assert filename is not None or data_table is not None,'Filename or data Table is required for dynamic_links.' skip_startswith = elem.get( 'skip_startswith', None ) separator = elem.get( 'separator', '\t' ) - id_col = int( elem.get( 'id', None ) ) - name_col = int( elem.get( 'name', id_col ) ) + id_col = elem.get( 'id', None ) + try: + id_col = int( id_col ) + except: + if data_table: + if id_col is None: + id_col = data_table.columns.get( 'id', None ) + if id_col is None: + id_col = data_table.columns.get( 'value', None ) + try: + id_col = int( id_col ) + except: + # id is set to a string or None, use column by that name if available + id_col = data_table.columns.get( id_col, None ) + id_col = int( id_col ) + name_col = elem.get( 'name', None ) + try: + name_col = int( name_col ) + except: + if data_table: + if name_col is None: + name_col = data_table.columns.get( 'name', None ) + else: + name_col = data_table.columns.get( name_col, None ) + else: + name_col = None + if name_col is None: + name_col = id_col + max_col = max( id_col, name_col ) dynamic_params = {} - max_col = max( id_col, name_col ) + if data_table is not None: + max_col = max( [ max_col ] + data_table.columns.values() ) + for key, value in data_table.columns.items(): + dynamic_params[key] = { 'column': value, 'split': False, 'separator': ',' } for dynamic_param in elem.findall( 'dynamic_param' ): name = dynamic_param.get( 'name' ) value = int( dynamic_param.get( 'value' ) ) @@ -102,27 +138,38 @@ param_separator = dynamic_param.get( 'separator', ',' ) max_col = max( max_col, value ) dynamic_params[name] = { 'column': value, 'split': split, 'separator': param_separator } - for line in open( filename ): - if not skip_startswith or not line.startswith( skip_startswith ): - line = line.rstrip( '\n\r' ) - if not line: + if filename: + data_iter = open( filename ) + elif data_table: + version, data_iter = data_table.get_version_fields() + display_application.add_data_table_watch( data_table.name, version ) + links = [] + for line in data_iter: + if isinstance( line, basestring ): + if not skip_startswith or not line.startswith( skip_startswith ): + line = line.rstrip( '\n\r' ) + if not line: + continue + fields = line.split( separator ) + else: continue - fields = line.split( separator ) - if len( fields ) > max_col: - new_elem = deepcopy( elem ) - new_elem.set( 'id', fields[id_col] ) - new_elem.set( 'name', fields[name_col] ) - dynamic_values = {} - for key, attributes in dynamic_params.iteritems(): - value = fields[ attributes[ 'column' ] ] - if attributes['split']: - value = value.split( attributes['separator'] ) - dynamic_values[key] = value - #now populate - rval.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) ) - else: - log.warning( 'Invalid dynamic display application link specified in %s: "%s"' % ( filename, line ) ) - self.links = rval + else: + fields = line + if len( fields ) > max_col: + new_elem = deepcopy( elem ) + new_elem.set( 'id', fields[id_col] ) + new_elem.set( 'name', fields[name_col] ) + dynamic_values = {} + for key, attributes in dynamic_params.iteritems(): + value = fields[ attributes[ 'column' ] ] + if attributes['split']: + value = value.split( attributes['separator'] ) + dynamic_values[key] = value + #now populate + links.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) ) + else: + log.warning( 'Invalid dynamic display application link specified in %s: "%s"' % ( filename, line ) ) + self.links = links def __iter__( self ): return iter( self.links ) @@ -166,12 +213,12 @@ class DisplayApplication( object ): @classmethod - def from_file( cls, filename, datatypes_registry ): - return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry, filename=filename ) + def from_file( cls, filename, app ): + return cls.from_elem( parse_xml( filename ).getroot(), app, filename=filename ) @classmethod - def from_elem( cls, elem, datatypes_registry, filename=None ): + def from_elem( cls, elem, app, filename=None ): att_dict = cls._get_attributes_from_elem( elem ) - rval = DisplayApplication( att_dict['id'], att_dict['name'], datatypes_registry, att_dict['version'], filename=filename, elem=elem ) + rval = DisplayApplication( att_dict['id'], att_dict['name'], app, att_dict['version'], filename=filename, elem=elem ) rval._load_links_from_elem( elem ) return rval @classmethod @@ -181,29 +228,32 @@ name = elem.get( 'name', display_id ) version = elem.get( 'version', None ) return dict( id=display_id, name=name, version=version ) - def __init__( self, display_id, name, datatypes_registry, version = None, filename=None, elem=None ): + def __init__( self, display_id, name, app, version = None, filename=None, elem=None ): self.id = display_id self.name = name - self.datatypes_registry = datatypes_registry + self.app = app if version is None: version = "1.0.0" self.version = version self.links = odict() self._filename = filename self._elem = elem + self._data_table_versions = {} def _load_links_from_elem( self, elem ): for link_elem in elem.findall( 'link' ): link = DisplayApplicationLink.from_elem( link_elem, self ) if link: self.links[ link.id ] = link for dynamic_links in elem.findall( 'dynamic_links' ): - for link in DynamicDisplayApplicationBuilder( dynamic_links, self, self.datatypes_registry.build_sites ): + for link in DynamicDisplayApplicationBuilder( dynamic_links, self, self.app.datatypes_registry.build_sites ): self.links[ link.id ] = link def get_link( self, link_name, data, dataset_hash, user_hash, trans, app_kwds ): #returns a link object with data knowledge to generate links + self._check_and_reload() return PopulatedDisplayApplicationLink( self.links[ link_name ], data, dataset_hash, user_hash, trans, app_kwds ) def filter_by_dataset( self, data, trans ): - filtered = DisplayApplication( self.id, self.name, self.datatypes_registry, version = self.version ) + self._check_and_reload() + filtered = DisplayApplication( self.id, self.name, self.app, version = self.version ) for link_name, link_value in self.links.iteritems(): if link_value.filter_by_dataset( data, trans ): filtered.links[link_name] = link_value @@ -222,9 +272,24 @@ # clear old links for key in self.links.keys(): del self.links[key] + #clear data table versions: + for key in self._data_table_versions.keys(): + del self._data_table_versions[ key ] # Set new attributes for key, value in attr_dict.iteritems(): setattr( self, key, value ) # Load new links self._load_links_from_elem( elem ) return self + def add_data_table_watch( self, table_name, version=None ): + self._data_table_versions[ table_name ] = version + def _requires_reload( self ): + for key, value in self._data_table_versions.iteritems(): + table = self.app.tool_data_tables.get( key, None ) + if table and not table.is_current_version( value ): + return True + return False + def _check_and_reload( self ): + if self._requires_reload(): + self.reload() + diff -r 0468d285f89c799559926c94f300c42d05e8c47a -r 02a1a5f1132f722100097afef1be8d6b9725e783 lib/galaxy/datatypes/display_applications/parameters.py --- a/lib/galaxy/datatypes/display_applications/parameters.py +++ b/lib/galaxy/datatypes/display_applications/parameters.py @@ -59,7 +59,7 @@ @property def formats( self ): if self.extensions: - return tuple( map( type, map( self.link.display_application.datatypes_registry.get_datatype_by_extension, self.extensions ) ) ) + return tuple( map( type, map( self.link.display_application.app.datatypes_registry.get_datatype_by_extension, self.extensions ) ) ) return None def _get_dataset_like_object( self, other_values ): #this returned object has file_name, state, and states attributes equivalent to a DatasetAssociation diff -r 0468d285f89c799559926c94f300c42d05e8c47a -r 02a1a5f1132f722100097afef1be8d6b9725e783 lib/galaxy/datatypes/registry.py --- a/lib/galaxy/datatypes/registry.py +++ b/lib/galaxy/datatypes/registry.py @@ -546,7 +546,7 @@ else: self.log.exception( "Error loading converter (%s): %s" % ( converter_path, str( e ) ) ) - def load_display_applications( self, installed_repository_dict=None, deactivate=False ): + def load_display_applications( self, app, installed_repository_dict=None, deactivate=False ): """ If deactivate is False, add display applications from self.display_app_containers or self.proprietary_display_app_containers to appropriate datatypes. If deactivate is @@ -570,7 +570,7 @@ config_path = os.path.join( self.display_applications_path, display_file ) try: inherit = galaxy.util.string_as_bool( display_app.get( 'inherit', 'False' ) ) - display_app = DisplayApplication.from_file( config_path, self ) + display_app = DisplayApplication.from_file( config_path, app ) if display_app: if display_app.id in self.display_applications: if deactivate: diff -r 0468d285f89c799559926c94f300c42d05e8c47a -r 02a1a5f1132f722100097afef1be8d6b9725e783 lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py --- a/lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py +++ b/lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py @@ -214,5 +214,5 @@ def load_installed_display_applications( self, installed_repository_dict, deactivate=False ): """Load or deactivate custom datatype display applications.""" - self.app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict, + self.app.datatypes_registry.load_display_applications( self.app, installed_repository_dict=installed_repository_dict, deactivate=deactivate ) diff -r 0468d285f89c799559926c94f300c42d05e8c47a -r 02a1a5f1132f722100097afef1be8d6b9725e783 lib/tool_shed/galaxy_install/install_manager.py --- a/lib/tool_shed/galaxy_install/install_manager.py +++ b/lib/tool_shed/galaxy_install/install_manager.py @@ -624,7 +624,7 @@ self.app.datatypes_registry.load_datatype_converters( self.app.toolbox, installed_repository_dict=repository_dict ) if display_path: # Load proprietary datatype display applications - self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict ) + self.app.datatypes_registry.load_display_applications( self.app, installed_repository_dict=repository_dict ) def handle_tool_shed_repositories( self, installation_dict ): # The following installation_dict entries are all required. diff -r 0468d285f89c799559926c94f300c42d05e8c47a -r 02a1a5f1132f722100097afef1be8d6b9725e783 lib/tool_shed/galaxy_install/tool_migration_manager.py --- a/lib/tool_shed/galaxy_install/tool_migration_manager.py +++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py @@ -523,7 +523,7 @@ installed_repository_dict=repository_dict ) if display_path: # Load proprietary datatype display applications - self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict ) + self.app.datatypes_registry.load_display_applications( self.app, installed_repository_dict=repository_dict ) basic_util.remove_dir( work_dir ) def install_repository( self, repository_elem, tool_shed_repository, install_dependencies, is_repository_dependency=False ): https://bitbucket.org/galaxy/galaxy-central/commits/2158ee156a60/ Changeset: 2158ee156a60 User: dan Date: 2015-02-27 20:50:28+00:00 Summary: Have IGV external display application load a set of links for available genomes via a tool data table that reads a URL (http://igv.broadinstitute.org/genomes/genomes.txt). The manually specified builds links should now be used to add additional builds, or for alias mapping (e.g. hg_g1k_v37-->b37). Affected #: 4 files diff -r 02a1a5f1132f722100097afef1be8d6b9725e783 -r 2158ee156a601bdc77e81d77363ebcd0f4b9f0f9 config/tool_data_table_conf.xml.sample --- a/config/tool_data_table_conf.xml.sample +++ b/config/tool_data_table_conf.xml.sample @@ -65,4 +65,9 @@ <columns>value, path</columns><file path="tool-data/twobit.loc" /></table> + <!-- Available IGV builds, loaded from URL --> + <table name="igv_broad_genomes" comment_char="#"> + <columns>name, url, value</columns> + <file url="http://igv.broadinstitute.org/genomes/genomes.txt" /> + </table></tables> diff -r 02a1a5f1132f722100097afef1be8d6b9725e783 -r 2158ee156a601bdc77e81d77363ebcd0f4b9f0f9 display_applications/igv/bam.xml --- a/display_applications/igv/bam.xml +++ b/display_applications/igv/bam.xml @@ -93,7 +93,20 @@ #end if </param></dynamic_links> - + + + <dynamic_links from_data_table="igv_broad_genomes" skip_startswith="#" id="value" name="name"> + + <!-- Our input data table is one line per dbkey --> + <filter>${ $dataset.dbkey == $value }</filter> + + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --> + <url>http://www.broadinstitute.org/igv/projects/current/igv.php?sessionURL=${bam_file.qp}&genome=${bam_file.dbkey}&merge=true&name=${qp( $bam_file.name )}</url> + + <param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" /> + <param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" /> + + </dynamic_links></display><!-- Dan Blankenberg --> diff -r 02a1a5f1132f722100097afef1be8d6b9725e783 -r 2158ee156a601bdc77e81d77363ebcd0f4b9f0f9 display_applications/igv/vcf.xml --- a/display_applications/igv/vcf.xml +++ b/display_applications/igv/vcf.xml @@ -93,7 +93,20 @@ #end if </param></dynamic_links> - + + + <dynamic_links from_data_table="igv_broad_genomes" skip_startswith="#" id="value" name="name"> + + <!-- Our input data table is one line per dbkey --> + <filter>${ $dataset.dbkey == $value }</filter> + + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --> + <url>http://www.broadinstitute.org/igv/projects/current/igv.php?sessionURL=${bgzip_file.qp}&genome=$bgzip_file.dbkey&merge=true&name=${qp( $bgzip_file.name )}</url> + + <param type="data" name="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz" format="vcf_bgzip" /> + <param type="data" name="tabix_file" dataset="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz.tbi" format="tabix" /> + + </dynamic_links></display><!-- Dan Blankenberg --> diff -r 02a1a5f1132f722100097afef1be8d6b9725e783 -r 2158ee156a601bdc77e81d77363ebcd0f4b9f0f9 tool-data/shared/igv/igv_build_sites.txt.sample --- a/tool-data/shared/igv/igv_build_sites.txt.sample +++ b/tool-data/shared/igv/igv_build_sites.txt.sample @@ -1,4 +1,4 @@ #site_id site_name site_url dbkey ivg_build_name -web_link_main web current http://www.broadinstitute.org/igv/projects/current/igv.php hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum +web_link_main web current http://www.broadinstitute.org/igv/projects/current/igv.php hg_g1k_v37 b37 #web_jnlp_1.5 web 1.5 http://www.broadinstitute.org/igvdata/jws/prod hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum -#local_default local http://localhost:60151/load hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum \ No newline at end of file +#local_default local http://localhost:60151/load hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum https://bitbucket.org/galaxy/galaxy-central/commits/9886c5e657d1/ Changeset: 9886c5e657d1 User: guerler Date: 2015-02-28 06:33:15+00:00 Summary: ToolForm: Update biostar url for tool search Affected #: 3 files diff -r 2158ee156a601bdc77e81d77363ebcd0f4b9f0f9 -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 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 @@ -230,7 +230,7 @@ title : 'Search', tooltip : 'Search help for this tool (Biostar)', onclick : function() { - window.open(options.biostar_url + '/t/' + options.id + '/'); + window.open(options.biostar_url + '/local/search/page/?q=' + options.name); } }); }; diff -r 2158ee156a601bdc77e81d77363ebcd0f4b9f0f9 -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 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 @@ -230,7 +230,7 @@ title : 'Search', tooltip : 'Search help for this tool (Biostar)', onclick : function() { - window.open(options.biostar_url + '/t/' + options.id + '/'); + window.open(options.biostar_url + '/local/search/page/?q=' + options.name); } }); }; diff -r 2158ee156a601bdc77e81d77363ebcd0f4b9f0f9 -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 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){this.optionsDefault={is_dynamic:true,narrow:false,initial_errors:false,cls_portlet:"ui-portlet-limited"};this.options=g.merge(l,this.optionsDefault);console.debug(this.options);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.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this.build(this.options)},build:function(n){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);l.options.inputs=n&&n.inputs;this._renderForm(n);var m=this.tree.finalize();if(n.initial_errors){this._errors(n)}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){var o=l.tree.finalize();if(!_.isEqual(o,m)){m=o;l._updateModel($.extend(true,{},m))}})});this.on("reset",function(){for(var o in this.element_list){this.element_list[o].reset()}})},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){$("html, body").animate({scrollTop:o.$el.offset().top-20},500)}}},_errors:function(n){this.trigger("reset");if(n&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in this.element_list){var l=this.element_list[m];if(o[m]){this.highlight(m,o[m],true)}}}},_renderForm:function(t){var s=this;this.message=new k.Message();var m=new k.ButtonMenu({icon:"fa-cubes",title:(!t.narrow&&"Versions")||null,tooltip:"Select another tool version"});if(t.versions&&t.versions.length>1){for(var o in t.versions){var q=t.versions[o];if(q!=t.version){m.addMenu({title:"Switch to "+q,version:q,icon:"fa-cube",onclick:function(){s.options.id=s.options.id.replace(s.options.version,this.version);s.options.version=this.version;s.deferred.reset();s.deferred.execute(function(){s._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!t.narrow&&"Options")||null,tooltip:"View available options"});if(t.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(t.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(t.biostar_url+"/t/"+t.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="+t.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/"+t.id+"/download"}})}if(t.requirements&&t.requirements.length>0){p.addMenu({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;s.message.update({persistent:true,message:c.requirements(t),status:"info"})}else{this.visible=false;s.message.update({message:""})}}})}if(this.options.sharable_url){p.addMenu({icon:"fa-external-link",title:"See in Tool Shed",tooltip:"Access the repository",onclick:function(){window.open(s.options.sharable_url)}})}this.section=new j.View(s,{inputs:t.inputs});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+t.name+"</b> "+t.description+" (Galaxy Tool Version "+t.version+")",cls:this.options.cls_portlet,operations:{menu:p,versions:m},buttons:this.buttons});this.portlet.append(this.message.$el.addClass("ui-margin-top"));this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(t.help!=""){this.$el.append(c.help(t.help))}if(t.citations){var r=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=t.id;var n=new a.CitationListView({el:r,collection:l});n.render();l.fetch();this.$el.append(r)}if(t.message){this.message.update({persistent:true,status:"warning",message:t.message})}console.debug("tools-form-base::initialize() - Completed.")}})}); \ 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){this.optionsDefault={is_dynamic:true,narrow:false,initial_errors:false,cls_portlet:"ui-portlet-limited"};this.options=g.merge(l,this.optionsDefault);console.debug(this.options);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.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this.build(this.options)},build:function(n){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);l.options.inputs=n&&n.inputs;this._renderForm(n);var m=this.tree.finalize();if(n.initial_errors){this._errors(n)}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){var o=l.tree.finalize();if(!_.isEqual(o,m)){m=o;l._updateModel($.extend(true,{},m))}})});this.on("reset",function(){for(var o in this.element_list){this.element_list[o].reset()}})},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){$("html, body").animate({scrollTop:o.$el.offset().top-20},500)}}},_errors:function(n){this.trigger("reset");if(n&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in this.element_list){var l=this.element_list[m];if(o[m]){this.highlight(m,o[m],true)}}}},_renderForm:function(t){var s=this;this.message=new k.Message();var m=new k.ButtonMenu({icon:"fa-cubes",title:(!t.narrow&&"Versions")||null,tooltip:"Select another tool version"});if(t.versions&&t.versions.length>1){for(var o in t.versions){var q=t.versions[o];if(q!=t.version){m.addMenu({title:"Switch to "+q,version:q,icon:"fa-cube",onclick:function(){s.options.id=s.options.id.replace(s.options.version,this.version);s.options.version=this.version;s.deferred.reset();s.deferred.execute(function(){s._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!t.narrow&&"Options")||null,tooltip:"View available options"});if(t.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(t.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(t.biostar_url+"/local/search/page/?q="+t.name)}})}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="+t.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/"+t.id+"/download"}})}if(t.requirements&&t.requirements.length>0){p.addMenu({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;s.message.update({persistent:true,message:c.requirements(t),status:"info"})}else{this.visible=false;s.message.update({message:""})}}})}if(this.options.sharable_url){p.addMenu({icon:"fa-external-link",title:"See in Tool Shed",tooltip:"Access the repository",onclick:function(){window.open(s.options.sharable_url)}})}this.section=new j.View(s,{inputs:t.inputs});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+t.name+"</b> "+t.description+" (Galaxy Tool Version "+t.version+")",cls:this.options.cls_portlet,operations:{menu:p,versions:m},buttons:this.buttons});this.portlet.append(this.message.$el.addClass("ui-margin-top"));this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(t.help!=""){this.$el.append(c.help(t.help))}if(t.citations){var r=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=t.id;var n=new a.CitationListView({el:r,collection:l});n.render();l.fetch();this.$el.append(r)}if(t.message){this.message.update({persistent:true,status:"warning",message:t.message})}console.debug("tools-form-base::initialize() - Completed.")}})}); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/071f254a1c43/ Changeset: 071f254a1c43 User: guerler Date: 2015-02-28 08:01:14+00:00 Summary: ToolForm: Remove unnecessary helper class Affected #: 9 files diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 client/galaxy/scripts/mvc/tools/tools-content.js --- a/client/galaxy/scripts/mvc/tools/tools-content.js +++ /dev/null @@ -1,55 +0,0 @@ -define(['utils/utils'], function(Utils){ - return Backbone.Model.extend({ - // initialize - initialize: function(app) { - this.summary = {}; - }, - - /** Add new content elements - */ - add: function(content_list) { - // add/update content in summary list - for (var i in content_list) { - for (var j in content_list[i]) { - var c = content_list[i][j]; - this.summary[c.id + '_' + c.src] = c; - } - } - }, - - /** Returns matched content from summary. - */ - get: function(options) { - return _.findWhere(this.summary, options) || {}; - }, - - /** Get details of a content by id. - */ - getDetails: function(options) { - // check id - if (!options.id || options.id === 'null') { - options.success && options.success(); - return; - } - - // create url - var api_url = this.base_url + '/datasets/' + options.id; - if (options.src == 'hdca') { - api_url = this.base_url + '/dataset_collections/' + options.id; - } - - // request details - Utils.get({ - url : api_url, - success : function(response) { - options.success && options.success(response); - }, - error : function(response) { - options.success && options.success(); - console.debug('tools-content::getDetails() - Ajax request for content failed.'); - console.debug(response); - } - }); - } - }); -}); \ No newline at end of file diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 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 @@ -3,9 +3,9 @@ */ 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'], + 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-section', 'mvc/tools/tools-tree'], function(Utils, Deferred, Portlet, Ui, CitationModel, CitationView, - Tools, ToolTemplate, ToolContent, ToolSection, ToolTree) { + Tools, ToolTemplate, ToolSection, ToolTree) { // create form view return Backbone.View.extend({ @@ -83,8 +83,8 @@ // creates a tree/json data structure from the input form this.tree = new ToolTree(this); - // request history content and build form - this.content = new ToolContent(this); + // keeps track of history items + this.history = {}; // update model data self.options.inputs = options && options.inputs; diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 client/galaxy/scripts/mvc/tools/tools-select-content.js --- a/client/galaxy/scripts/mvc/tools/tools-select-content.js +++ b/client/galaxy/scripts/mvc/tools/tools-select-content.js @@ -179,6 +179,7 @@ /** Update content selector */ update: function(options) { // update a particular select field + var self = this; function _update(field, options) { if (field) { // identify available options @@ -189,6 +190,8 @@ label: item.hid + ': ' + item.name, value: item.id }); + // backup to local history + self.app.history[item.id + '_' + item.src] = item; } // update field field.update(select_options); @@ -199,9 +202,6 @@ _update(this.select_single, options.hda); _update(this.select_multiple, options.hda); _update(this.select_collection, options.hdca); - - // add to content list - this.app.content.add(options); }, /** Return the currently selected dataset values */ @@ -266,7 +266,7 @@ // append to dataset ids for (var i in id_list) { - var details = this.app.content.get({ + var details = _.findWhere(this.app.history, { id : id_list[i], src : this.list[this.current].type }); @@ -312,7 +312,7 @@ /** Assists in identifying the batch mode */ _batch: function() { if (this.current == 'collection') { - var hdca = this.app.content.get({ + var hdca = _.findWhere(this.app.history, { id : this._select().value(), src : 'hdca' }); diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 static/scripts/mvc/tools/tools-content.js --- a/static/scripts/mvc/tools/tools-content.js +++ /dev/null @@ -1,55 +0,0 @@ -define(['utils/utils'], function(Utils){ - return Backbone.Model.extend({ - // initialize - initialize: function(app) { - this.summary = {}; - }, - - /** Add new content elements - */ - add: function(content_list) { - // add/update content in summary list - for (var i in content_list) { - for (var j in content_list[i]) { - var c = content_list[i][j]; - this.summary[c.id + '_' + c.src] = c; - } - } - }, - - /** Returns matched content from summary. - */ - get: function(options) { - return _.findWhere(this.summary, options) || {}; - }, - - /** Get details of a content by id. - */ - getDetails: function(options) { - // check id - if (!options.id || options.id === 'null') { - options.success && options.success(); - return; - } - - // create url - var api_url = this.base_url + '/datasets/' + options.id; - if (options.src == 'hdca') { - api_url = this.base_url + '/dataset_collections/' + options.id; - } - - // request details - Utils.get({ - url : api_url, - success : function(response) { - options.success && options.success(response); - }, - error : function(response) { - options.success && options.success(); - console.debug('tools-content::getDetails() - Ajax request for content failed.'); - console.debug(response); - } - }); - } - }); -}); \ No newline at end of file diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 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 @@ -3,9 +3,9 @@ */ 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'], + 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-section', 'mvc/tools/tools-tree'], function(Utils, Deferred, Portlet, Ui, CitationModel, CitationView, - Tools, ToolTemplate, ToolContent, ToolSection, ToolTree) { + Tools, ToolTemplate, ToolSection, ToolTree) { // create form view return Backbone.View.extend({ @@ -83,8 +83,8 @@ // creates a tree/json data structure from the input form this.tree = new ToolTree(this); - // request history content and build form - this.content = new ToolContent(this); + // keeps track of history items + this.history = {}; // update model data self.options.inputs = options && options.inputs; diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 static/scripts/mvc/tools/tools-select-content.js --- a/static/scripts/mvc/tools/tools-select-content.js +++ b/static/scripts/mvc/tools/tools-select-content.js @@ -179,6 +179,7 @@ /** Update content selector */ update: function(options) { // update a particular select field + var self = this; function _update(field, options) { if (field) { // identify available options @@ -189,6 +190,8 @@ label: item.hid + ': ' + item.name, value: item.id }); + // backup to local history + self.app.history[item.id + '_' + item.src] = item; } // update field field.update(select_options); @@ -199,9 +202,6 @@ _update(this.select_single, options.hda); _update(this.select_multiple, options.hda); _update(this.select_collection, options.hdca); - - // add to content list - this.app.content.add(options); }, /** Return the currently selected dataset values */ @@ -266,7 +266,7 @@ // append to dataset ids for (var i in id_list) { - var details = this.app.content.get({ + var details = _.findWhere(this.app.history, { id : id_list[i], src : this.list[this.current].type }); @@ -312,7 +312,7 @@ /** Assists in identifying the batch mode */ _batch: function() { if (this.current == 'collection') { - var hdca = this.app.content.get({ + var hdca = _.findWhere(this.app.history, { id : this._select().value(), src : 'hdca' }); diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 static/scripts/packed/mvc/tools/tools-content.js --- a/static/scripts/packed/mvc/tools/tools-content.js +++ /dev/null @@ -1,1 +0,0 @@ -define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.summary={}},add:function(e){for(var d in e){for(var b in e[d]){var f=e[d][b];this.summary[f.id+"_"+f.src]=f}}},get:function(b){return _.findWhere(this.summary,b)||{}},getDetails:function(b){if(!b.id||b.id==="null"){b.success&&b.success();return}var c=this.base_url+"/datasets/"+b.id;if(b.src=="hdca"){c=this.base_url+"/dataset_collections/"+b.id}a.get({url:c,success:function(d){b.success&&b.success(d)},error:function(d){b.success&&b.success();console.debug("tools-content::getDetails() - Ajax request for content failed.");console.debug(d)}})}})}); \ No newline at end of file diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 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){this.optionsDefault={is_dynamic:true,narrow:false,initial_errors:false,cls_portlet:"ui-portlet-limited"};this.options=g.merge(l,this.optionsDefault);console.debug(this.options);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.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this.build(this.options)},build:function(n){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);l.options.inputs=n&&n.inputs;this._renderForm(n);var m=this.tree.finalize();if(n.initial_errors){this._errors(n)}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){var o=l.tree.finalize();if(!_.isEqual(o,m)){m=o;l._updateModel($.extend(true,{},m))}})});this.on("reset",function(){for(var o in this.element_list){this.element_list[o].reset()}})},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){$("html, body").animate({scrollTop:o.$el.offset().top-20},500)}}},_errors:function(n){this.trigger("reset");if(n&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in this.element_list){var l=this.element_list[m];if(o[m]){this.highlight(m,o[m],true)}}}},_renderForm:function(t){var s=this;this.message=new k.Message();var m=new k.ButtonMenu({icon:"fa-cubes",title:(!t.narrow&&"Versions")||null,tooltip:"Select another tool version"});if(t.versions&&t.versions.length>1){for(var o in t.versions){var q=t.versions[o];if(q!=t.version){m.addMenu({title:"Switch to "+q,version:q,icon:"fa-cube",onclick:function(){s.options.id=s.options.id.replace(s.options.version,this.version);s.options.version=this.version;s.deferred.reset();s.deferred.execute(function(){s._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:(!t.narrow&&"Options")||null,tooltip:"View available options"});if(t.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(t.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(t.biostar_url+"/local/search/page/?q="+t.name)}})}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="+t.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/"+t.id+"/download"}})}if(t.requirements&&t.requirements.length>0){p.addMenu({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;s.message.update({persistent:true,message:c.requirements(t),status:"info"})}else{this.visible=false;s.message.update({message:""})}}})}if(this.options.sharable_url){p.addMenu({icon:"fa-external-link",title:"See in Tool Shed",tooltip:"Access the repository",onclick:function(){window.open(s.options.sharable_url)}})}this.section=new j.View(s,{inputs:t.inputs});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+t.name+"</b> "+t.description+" (Galaxy Tool Version "+t.version+")",cls:this.options.cls_portlet,operations:{menu:p,versions:m},buttons:this.buttons});this.portlet.append(this.message.$el.addClass("ui-margin-top"));this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(t.help!=""){this.$el.append(c.help(t.help))}if(t.citations){var r=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=t.id;var n=new a.CitationListView({el:r,collection:l});n.render();l.fetch();this.$el.append(r)}if(t.message){this.message.update({persistent:true,status:"warning",message:t.message})}console.debug("tools-form-base::initialize() - Completed.")}})}); \ 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-section","mvc/tools/tools-tree"],function(f,g,e,j,h,a,d,c,i,b){return Backbone.View.extend({initialize:function(k){this.optionsDefault={is_dynamic:true,narrow:false,initial_errors:false,cls_portlet:"ui-portlet-limited"};this.options=f.merge(k,this.optionsDefault);console.debug(this.options);var l=parent.Galaxy;if(l&&l.modal){this.modal=l.modal}else{this.modal=new j.Modal.View()}if(l&&l.currUser){this.is_admin=l.currUser.get("is_admin")}else{this.is_admin=false}this.container=this.options.container||"body";this.deferred=new g();this.setElement("<div/>");$(this.container).append(this.$el);this.build(this.options)},build:function(m){var k=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.history={};k.options.inputs=m&&m.inputs;this._renderForm(m);var l=this.tree.finalize();if(m.initial_errors){this._errors(m)}this.on("refresh",function(){k.deferred.reset();k.deferred.execute(function(){var n=k.tree.finalize();if(!_.isEqual(n,l)){l=n;k._updateModel($.extend({},l))}})});this.on("reset",function(){for(var n in this.element_list){this.element_list[n].reset()}})},reciept:function(k){$(this.container).empty();$(this.container).append(k)},highlight:function(l,m,k){var n=this.element_list[l];if(n){n.error(m||"Please verify this parameter.");if(!k){$("html, body").animate({scrollTop:n.$el.offset().top-20},500)}}},_errors:function(m){this.trigger("reset");if(m&&m.errors){var n=this.tree.matchResponse(m.errors);for(var l in this.element_list){var k=this.element_list[l];if(n[l]){this.highlight(l,n[l],true)}}}},_renderForm:function(s){var r=this;this.message=new j.Message();var l=new j.ButtonMenu({icon:"fa-cubes",title:(!s.narrow&&"Versions")||null,tooltip:"Select another tool version"});if(s.versions&&s.versions.length>1){for(var n in s.versions){var p=s.versions[n];if(p!=s.version){l.addMenu({title:"Switch to "+p,version:p,icon:"fa-cube",onclick:function(){r.options.id=r.options.id.replace(r.options.version,this.version);r.options.version=this.version;r.deferred.reset();r.deferred.execute(function(){r._buildModel()})}})}}}else{l.$el.hide()}var o=new j.ButtonMenu({icon:"fa-caret-down",title:(!s.narrow&&"Options")||null,tooltip:"View available options"});if(s.biostar_url){o.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(s.biostar_url+"/p/new/post/")}});o.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(s.biostar_url+"/t/"+s.id+"/")}})}o.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="+s.id)}});if(this.is_admin){o.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+s.id+"/download"}})}if(s.requirements&&s.requirements.length>0){o.addMenu({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;r.message.update({persistent:true,message:c.requirements(s),status:"info"})}else{this.visible=false;r.message.update({message:""})}}})}if(this.options.sharable_url){o.addMenu({icon:"fa-external-link",title:"See in Tool Shed",tooltip:"Access the repository",onclick:function(){window.open(r.options.sharable_url)}})}this.section=new i.View(r,{inputs:s.inputs});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new e.View({icon:"fa-wrench",title:"<b>"+s.name+"</b> "+s.description+" (Galaxy Tool Version "+s.version+")",cls:this.options.cls_portlet,operations:{menu:o,versions:l},buttons:this.buttons});this.portlet.append(this.message.$el.addClass("ui-margin-top"));this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(s.help!=""){this.$el.append(c.help(s.help))}if(s.citations){var q=$("<div/>");var k=new h.ToolCitationCollection();k.tool_id=s.id;var m=new a.CitationListView({el:q,collection:k});m.render();k.fetch();this.$el.append(q)}if(s.message){this.message.update({persistent:true,status:"warning",message:s.message})}console.debug("tools-form-base::initialize() - Completed.")}})}); diff -r 9886c5e657d1f004c8c0f362cb4f62f1326d0c74 -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 static/scripts/packed/mvc/tools/tools-select-content.js --- a/static/scripts/packed/mvc/tools/tools-select-content.js +++ b/static/scripts/packed/mvc/tools/tools-select-content.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(g,p){this.app=g;this.options=p;var o=this;this.setElement('<div class="ui-select-content"/>');this.list={};var m=[];if(p.type=="data_collection"){this.mode="collection"}else{if(p.multiple){this.mode="multiple"}else{this.mode="single"}}this.current=this.mode;this.list={};var k=c.textify(p.extensions);var j="No dataset available.";if(k){j="No "+k+" dataset available."}var l="No dataset list available.";if(k){l="No "+k+" dataset collection available."}if(this.mode=="single"){m.push({icon:"fa-file-o",value:"single",tooltip:"Single dataset"});this.select_single=new e.Select.View({optional:p.optional,error_text:j,onchange:function(){o.trigger("change")}});this.list.single={field:this.select_single,type:"hda"}}if(this.mode=="single"||this.mode=="multiple"){m.push({icon:"fa-files-o",value:"multiple",tooltip:"Multiple datasets"});this.select_multiple=new e.Select.View({multiple:true,searchable:false,error_text:j,onchange:function(){o.trigger("change")}});this.list.multiple={field:this.select_multiple,type:"hda"}}if(this.mode=="single"||this.mode=="multiple"||this.mode=="collection"){m.push({icon:"fa-folder-o",value:"collection",tooltip:"Dataset collection"});this.select_collection=new e.Select.View({error_text:l,optional:p.optional,onchange:function(){o.trigger("change")}});this.list.collection={field:this.select_collection,type:"hdca"}}this.button_type=new e.RadioButton.View({value:this.current,data:m,onchange:function(i){o.current=i;o.refresh();o.trigger("change")}});this.$batch=$(a.batchMode());var f=_.size(this.list);var n=0;if(f>1){this.$el.append(this.button_type.$el);n=Math.max(0,_.size(this.list)*35)+"px"}for(var h in this.list){this.$el.append(this.list[h].field.$el.css({"margin-left":n}))}this.$el.append(this.$batch.css({"margin-left":n}));this.update(p.data);if(this.options.value!==undefined){this.value(this.options.value)}this.refresh();this.on("change",function(){if(p.onchange){p.onchange(o.value())}})},wait:function(){for(var f in this.list){this.list[f].field.wait()}},unwait:function(){for(var f in this.list){this.list[f].field.unwait()}},update:function(g){function f(l,h){if(l){var m=[];for(var j in h){var k=h[j];m.push({label:k.hid+": "+k.name,value:k.id})}l.update(m)}}f(this.select_single,g.hda);f(this.select_multiple,g.hda);f(this.select_collection,g.hdca);this.app.content.add(g)},value:function(j){if(j!==undefined){if(j&&j.values){try{var m=[];for(var h in j.values){m.push(j.values[h].id)}if(j&&j.values.length>0&&j.values[0].src=="hcda"){this.current="collection";this.select_collection.value(m[0])}else{if(this.mode=="multiple"){this.current="multiple";this.select_multiple.value(m)}else{this.current="single";this.select_single.value(m[0])}}}catch(l){console.debug("tools-select-content::value() - Skipped.")}}else{for(var h in this.list){this.list[h].field.value(null)}}}this.refresh();var k=this._select().value();if(k===null){return null}if(!(k instanceof Array)){k=[k]}if(k.length===0){return null}var f={batch:this._batch(),values:[]};for(var h in k){var g=this.app.content.get({id:k[h],src:this.list[this.current].type});if(g){f.values.push(g)}else{return null}}f.values.sort(function(n,i){return n.hid-i.hid});return f},refresh:function(){this.button_type.value(this.current);for(var g in this.list){var f=this.list[g].field.$el;if(this.current==g){f.show()}else{f.hide()}}if(this._batch()){this.$batch.show()}else{this.$batch.hide()}},_select:function(){return this.list[this.current].field},_batch:function(){if(this.current=="collection"){var f=this.app.content.get({id:this._select().value(),src:"hdca"});if(f&&f.map_over_type){return true}}if(this.current!="single"){if(this.mode=="single"){return true}}return false}});return{View:d}}); \ No newline at end of file +define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(g,p){this.app=g;this.options=p;var o=this;this.setElement('<div class="ui-select-content"/>');this.list={};var m=[];if(p.type=="data_collection"){this.mode="collection"}else{if(p.multiple){this.mode="multiple"}else{this.mode="single"}}this.current=this.mode;this.list={};var k=c.textify(p.extensions);var j="No dataset available.";if(k){j="No "+k+" dataset available."}var l="No dataset list available.";if(k){l="No "+k+" dataset collection available."}if(this.mode=="single"){m.push({icon:"fa-file-o",value:"single",tooltip:"Single dataset"});this.select_single=new e.Select.View({optional:p.optional,error_text:j,onchange:function(){o.trigger("change")}});this.list.single={field:this.select_single,type:"hda"}}if(this.mode=="single"||this.mode=="multiple"){m.push({icon:"fa-files-o",value:"multiple",tooltip:"Multiple datasets"});this.select_multiple=new e.Select.View({multiple:true,searchable:false,error_text:j,onchange:function(){o.trigger("change")}});this.list.multiple={field:this.select_multiple,type:"hda"}}if(this.mode=="single"||this.mode=="multiple"||this.mode=="collection"){m.push({icon:"fa-folder-o",value:"collection",tooltip:"Dataset collection"});this.select_collection=new e.Select.View({error_text:l,optional:p.optional,onchange:function(){o.trigger("change")}});this.list.collection={field:this.select_collection,type:"hdca"}}this.button_type=new e.RadioButton.View({value:this.current,data:m,onchange:function(i){o.current=i;o.refresh();o.trigger("change")}});this.$batch=$(a.batchMode());var f=_.size(this.list);var n=0;if(f>1){this.$el.append(this.button_type.$el);n=Math.max(0,_.size(this.list)*35)+"px"}for(var h in this.list){this.$el.append(this.list[h].field.$el.css({"margin-left":n}))}this.$el.append(this.$batch.css({"margin-left":n}));this.update(p.data);if(this.options.value!==undefined){this.value(this.options.value)}this.refresh();this.on("change",function(){if(p.onchange){p.onchange(o.value())}})},wait:function(){for(var f in this.list){this.list[f].field.wait()}},unwait:function(){for(var f in this.list){this.list[f].field.unwait()}},update:function(h){var f=this;function g(m,j){if(m){var n=[];for(var k in j){var l=j[k];n.push({label:l.hid+": "+l.name,value:l.id});f.app.history[l.id+"_"+l.src]=l}m.update(n)}}g(this.select_single,h.hda);g(this.select_multiple,h.hda);g(this.select_collection,h.hdca)},value:function(j){if(j!==undefined){if(j&&j.values){try{var m=[];for(var h in j.values){m.push(j.values[h].id)}if(j&&j.values.length>0&&j.values[0].src=="hcda"){this.current="collection";this.select_collection.value(m[0])}else{if(this.mode=="multiple"){this.current="multiple";this.select_multiple.value(m)}else{this.current="single";this.select_single.value(m[0])}}}catch(l){console.debug("tools-select-content::value() - Skipped.")}}else{for(var h in this.list){this.list[h].field.value(null)}}}this.refresh();var k=this._select().value();if(k===null){return null}if(!(k instanceof Array)){k=[k]}if(k.length===0){return null}var f={batch:this._batch(),values:[]};for(var h in k){var g=_.findWhere(this.app.history,{id:k[h],src:this.list[this.current].type});if(g){f.values.push(g)}else{return null}}f.values.sort(function(n,i){return n.hid-i.hid});return f},refresh:function(){this.button_type.value(this.current);for(var g in this.list){var f=this.list[g].field.$el;if(this.current==g){f.show()}else{f.hide()}}if(this._batch()){this.$batch.show()}else{this.$batch.hide()}},_select:function(){return this.list[this.current].field},_batch:function(){if(this.current=="collection"){var f=_.findWhere(this.app.history,{id:this._select().value(),src:"hdca"});if(f&&f.map_over_type){return true}}if(this.current!="single"){if(this.mode=="single"){return true}}return false}});return{View:d}}); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/d0bfc1c72bab/ Changeset: d0bfc1c72bab User: guerler Date: 2015-02-28 09:30:14+00:00 Summary: ToolForm: Do not show submission error if user closes progress modal Affected #: 3 files diff -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 -r d0bfc1c72bab6a8f390ee44f4d052810c2b94900 client/galaxy/scripts/mvc/tools/tools-jobs.js --- a/client/galaxy/scripts/mvc/tools/tools-jobs.js +++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js @@ -34,7 +34,13 @@ console.debug(job_def); // show progress modal - this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { 'Close' : function () {self.app.modal.hide();} }}); + var user_is_waiting = true; + this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { + 'Close' : function () { + self.app.modal.hide(); + user_is_waiting = false; + } + }}); // post job Utils.request({ @@ -57,7 +63,7 @@ } else { // show error message with details console.debug(response); - self.app.modal.show({ + user_is_waiting && self.app.modal.show({ title : 'Job submission failed', body : ToolTemplate.error(job_def), buttons : { diff -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 -r d0bfc1c72bab6a8f390ee44f4d052810c2b94900 static/scripts/mvc/tools/tools-jobs.js --- a/static/scripts/mvc/tools/tools-jobs.js +++ b/static/scripts/mvc/tools/tools-jobs.js @@ -34,7 +34,13 @@ console.debug(job_def); // show progress modal - this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { 'Close' : function () {self.app.modal.hide();} }}); + var user_is_waiting = true; + this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { + 'Close' : function () { + self.app.modal.hide(); + user_is_waiting = false; + } + }}); // post job Utils.request({ @@ -57,7 +63,7 @@ } else { // show error message with details console.debug(response); - self.app.modal.show({ + user_is_waiting && self.app.modal.show({ title : 'Job submission failed', body : ToolTemplate.error(job_def), buttons : { diff -r 071f254a1c43fbde264dc196c9941d5ce5afcf68 -r d0bfc1c72bab6a8f390ee44f4d052810c2b94900 static/scripts/packed/mvc/tools/tools-jobs.js --- a/static/scripts/packed/mvc/tools/tools-jobs.js +++ b/static/scripts/packed/mvc/tools/tools-jobs.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var d={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(d)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(d);this.app.modal.show({title:"Please wait...",body:"progress",closing_events:true,buttons:{Close:function(){c.app.modal.hide()}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:d,success:function(e){c.app.modal.hide();c.app.reciept(a.success(e));c._refreshHdas()},error:function(e,g){c.app.modal.hide();if(e&&e.message&&e.message.data){var h=c.app.tree.matchResponse(e.message.data);for(var f in h){c.app.highlight(f,h[f]);break}}else{console.debug(e);c.app.modal.show({title:"Job submission failed",body:a.error(d),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); \ No newline at end of file +define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var e={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(e)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(e);var d=true;this.app.modal.show({title:"Please wait...",body:"progress",closing_events:true,buttons:{Close:function(){c.app.modal.hide();d=false}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:e,success:function(f){c.app.modal.hide();c.app.reciept(a.success(f));c._refreshHdas()},error:function(f,h){c.app.modal.hide();if(f&&f.message&&f.message.data){var i=c.app.tree.matchResponse(f.message.data);for(var g in i){c.app.highlight(g,i[g]);break}}else{console.debug(f);d&&c.app.modal.show({title:"Job submission failed",body:a.error(e),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/a4bb127f32c3/ Changeset: a4bb127f32c3 User: guerler Date: 2015-02-28 09:37:37+00:00 Summary: ToolForm: Use default closing behaviour for progress modal Affected #: 3 files diff -r d0bfc1c72bab6a8f390ee44f4d052810c2b94900 -r a4bb127f32c3c2b85f02e138f4ac13475cd15704 client/galaxy/scripts/mvc/tools/tools-jobs.js --- a/client/galaxy/scripts/mvc/tools/tools-jobs.js +++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js @@ -35,7 +35,7 @@ // show progress modal var user_is_waiting = true; - this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { + this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { 'Close' : function () { self.app.modal.hide(); user_is_waiting = false; diff -r d0bfc1c72bab6a8f390ee44f4d052810c2b94900 -r a4bb127f32c3c2b85f02e138f4ac13475cd15704 static/scripts/mvc/tools/tools-jobs.js --- a/static/scripts/mvc/tools/tools-jobs.js +++ b/static/scripts/mvc/tools/tools-jobs.js @@ -35,7 +35,7 @@ // show progress modal var user_is_waiting = true; - this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { + this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { 'Close' : function () { self.app.modal.hide(); user_is_waiting = false; diff -r d0bfc1c72bab6a8f390ee44f4d052810c2b94900 -r a4bb127f32c3c2b85f02e138f4ac13475cd15704 static/scripts/packed/mvc/tools/tools-jobs.js --- a/static/scripts/packed/mvc/tools/tools-jobs.js +++ b/static/scripts/packed/mvc/tools/tools-jobs.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var e={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(e)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(e);var d=true;this.app.modal.show({title:"Please wait...",body:"progress",closing_events:true,buttons:{Close:function(){c.app.modal.hide();d=false}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:e,success:function(f){c.app.modal.hide();c.app.reciept(a.success(f));c._refreshHdas()},error:function(f,h){c.app.modal.hide();if(f&&f.message&&f.message.data){var i=c.app.tree.matchResponse(f.message.data);for(var g in i){c.app.highlight(g,i[g]);break}}else{console.debug(f);d&&c.app.modal.show({title:"Job submission failed",body:a.error(e),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); \ No newline at end of file +define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var e={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(e)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(e);var d=true;this.app.modal.show({title:"Please wait...",body:"progress",buttons:{Close:function(){c.app.modal.hide();d=false}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:e,success:function(f){c.app.modal.hide();c.app.reciept(a.success(f));c._refreshHdas()},error:function(f,h){c.app.modal.hide();if(f&&f.message&&f.message.data){var i=c.app.tree.matchResponse(f.message.data);for(var g in i){c.app.highlight(g,i[g]);break}}else{console.debug(f);d&&c.app.modal.show({title:"Job submission failed",body:a.error(e),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/24ff3e302d60/ Changeset: 24ff3e302d60 User: guerler Date: 2015-02-28 09:30:14+00:00 Summary: ToolForm: Do not show submission error if user closes progress modal Affected #: 3 files diff -r a4bb127f32c3c2b85f02e138f4ac13475cd15704 -r 24ff3e302d60f610db061461417d2f0ba31fda30 client/galaxy/scripts/mvc/tools/tools-jobs.js --- a/client/galaxy/scripts/mvc/tools/tools-jobs.js +++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js @@ -35,7 +35,7 @@ // show progress modal var user_is_waiting = true; - this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { + this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { 'Close' : function () { self.app.modal.hide(); user_is_waiting = false; @@ -157,4 +157,4 @@ } }); -}); \ No newline at end of file +}); diff -r a4bb127f32c3c2b85f02e138f4ac13475cd15704 -r 24ff3e302d60f610db061461417d2f0ba31fda30 static/scripts/mvc/tools/tools-jobs.js --- a/static/scripts/mvc/tools/tools-jobs.js +++ b/static/scripts/mvc/tools/tools-jobs.js @@ -35,7 +35,7 @@ // show progress modal var user_is_waiting = true; - this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { + this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { 'Close' : function () { self.app.modal.hide(); user_is_waiting = false; @@ -157,4 +157,4 @@ } }); -}); \ No newline at end of file +}); diff -r a4bb127f32c3c2b85f02e138f4ac13475cd15704 -r 24ff3e302d60f610db061461417d2f0ba31fda30 static/scripts/packed/mvc/tools/tools-jobs.js --- a/static/scripts/packed/mvc/tools/tools-jobs.js +++ b/static/scripts/packed/mvc/tools/tools-jobs.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var e={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(e)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(e);var d=true;this.app.modal.show({title:"Please wait...",body:"progress",buttons:{Close:function(){c.app.modal.hide();d=false}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:e,success:function(f){c.app.modal.hide();c.app.reciept(a.success(f));c._refreshHdas()},error:function(f,h){c.app.modal.hide();if(f&&f.message&&f.message.data){var i=c.app.tree.matchResponse(f.message.data);for(var g in i){c.app.highlight(g,i[g]);break}}else{console.debug(f);d&&c.app.modal.show({title:"Job submission failed",body:a.error(e),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); \ No newline at end of file +define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var e={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(e)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(e);var d=true;this.app.modal.show({title:"Please wait...",body:"progress",closing_events:true,buttons:{Close:function(){c.app.modal.hide();d=false}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:e,success:function(f){c.app.modal.hide();c.app.reciept(a.success(f));c._refreshHdas()},error:function(f,h){c.app.modal.hide();if(f&&f.message&&f.message.data){var i=c.app.tree.matchResponse(f.message.data);for(var g in i){c.app.highlight(g,i[g]);break}}else{console.debug(f);d&&c.app.modal.show({title:"Job submission failed",body:a.error(e),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); https://bitbucket.org/galaxy/galaxy-central/commits/3570617751c5/ Changeset: 3570617751c5 User: guerler Date: 2015-02-28 09:37:37+00:00 Summary: ToolForm: Use default closing behaviour for progress modal Affected #: 3 files diff -r 24ff3e302d60f610db061461417d2f0ba31fda30 -r 3570617751c579e323725444a432415d7af3607e client/galaxy/scripts/mvc/tools/tools-jobs.js --- a/client/galaxy/scripts/mvc/tools/tools-jobs.js +++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js @@ -35,7 +35,7 @@ // show progress modal var user_is_waiting = true; - this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { + this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { 'Close' : function () { self.app.modal.hide(); user_is_waiting = false; diff -r 24ff3e302d60f610db061461417d2f0ba31fda30 -r 3570617751c579e323725444a432415d7af3607e static/scripts/mvc/tools/tools-jobs.js --- a/static/scripts/mvc/tools/tools-jobs.js +++ b/static/scripts/mvc/tools/tools-jobs.js @@ -35,7 +35,7 @@ // show progress modal var user_is_waiting = true; - this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { + this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { 'Close' : function () { self.app.modal.hide(); user_is_waiting = false; diff -r 24ff3e302d60f610db061461417d2f0ba31fda30 -r 3570617751c579e323725444a432415d7af3607e static/scripts/packed/mvc/tools/tools-jobs.js --- a/static/scripts/packed/mvc/tools/tools-jobs.js +++ b/static/scripts/packed/mvc/tools/tools-jobs.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var e={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(e)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(e);var d=true;this.app.modal.show({title:"Please wait...",body:"progress",closing_events:true,buttons:{Close:function(){c.app.modal.hide();d=false}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:e,success:function(f){c.app.modal.hide();c.app.reciept(a.success(f));c._refreshHdas()},error:function(f,h){c.app.modal.hide();if(f&&f.message&&f.message.data){var i=c.app.tree.matchResponse(f.message.data);for(var g in i){c.app.highlight(g,i[g]);break}}else{console.debug(f);d&&c.app.modal.show({title:"Job submission failed",body:a.error(e),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); +define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var e={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(e)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(e);var d=true;this.app.modal.show({title:"Please wait...",body:"progress",buttons:{Close:function(){c.app.modal.hide();d=false}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:e,success:function(f){c.app.modal.hide();c.app.reciept(a.success(f));c._refreshHdas()},error:function(f,h){c.app.modal.hide();if(f&&f.message&&f.message.data){var i=c.app.tree.matchResponse(f.message.data);for(var g in i){c.app.highlight(g,i[g]);break}}else{console.debug(f);d&&c.app.modal.show({title:"Job submission failed",body:a.error(e),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})}); https://bitbucket.org/galaxy/galaxy-central/commits/11d5bb0dd643/ Changeset: 11d5bb0dd643 User: guerler Date: 2015-02-28 10:01:55+00:00 Summary: Parameters: Remove unused uncoded id from data parameter dictionaries Affected #: 1 file diff -r 3570617751c579e323725444a432415d7af3607e -r 11d5bb0dd643c90472bebd5cc2b2d000c9ace85c lib/galaxy/tools/parameters/basic.py --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -2172,7 +2172,6 @@ m = match.hda d['options']['hda'].append({ 'id' : trans.security.encode_id( m.id ), - 'id_uncoded' : m.id, 'hid' : m.hid, 'name' : m.name, 'src' : 'hda' @@ -2184,7 +2183,6 @@ if dataset_collection_matcher.hdca_match( hdca, reduction=multiple ): d['options']['hdca'].append({ 'id' : trans.security.encode_id( hdca.id ), - 'id_uncoded' : hdca.id, 'hid' : hdca.hid, 'name' : hdca.name, 'src' : 'hdca' @@ -2391,7 +2389,6 @@ for hdca in self.match_collections( trans, history, dataset_matcher ): d['options']['hdca'].append({ 'id' : trans.security.encode_id( hdca.id ), - 'id_uncoded' : hdca.id, 'hid' : hdca.hid, 'name' : hdca.name, 'src' : 'hdca' @@ -2402,7 +2399,6 @@ subcollection_type = self._history_query( trans ).collection_type_description.collection_type d['options']['hdca'].append({ 'id' : trans.security.encode_id( hdca.id ), - 'id_uncoded' : hdca.id, 'hid' : hdca.hid, 'name' : hdca.name, 'src' : 'hdca', https://bitbucket.org/galaxy/galaxy-central/commits/56e108003f4e/ Changeset: 56e108003f4e User: guerler Date: 2015-02-28 17:12:10+00:00 Summary: Charts: Add data point labels to all nvd3 charts (without this gene expression analysis using scatter plots is not very useful) Affected #: 6 files diff -r 11d5bb0dd643c90472bebd5cc2b2d000c9ace85c -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 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,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]);if(e.length===0)return!1;for(var t in e)if(["__null__","__undefined__","None",null,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,!0),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(){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: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.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(".portlet-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(e){this.$content.append(e)},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="portlet-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:"ui-select",error_text:"No data available",empty_text:"No selection",visible:!0,wait:!1,multiple:!1,searchable:!0,optional:!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.$el.addClass("ui-select-multiple"),this.$select.prop("multiple",!0),this.$button.remove()),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&&(e===null&&(e="__null__"),this.$select.val(e),this.$select.select2&&this.$select.select2("val",e)),this._getValue()},first:function(){var e=this.$select.find("option").first();return e.length>0?e.val():null},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._getValue();this.$select.find("option").remove(),!this.options.multiple&&this.options.optional&&this.$select.append(this._templateOption({value:"__null__",label:this.options.empty_text}));for(var n in e)this.$select.append(this._templateOption(e[n]));this._refresh(),this.options.searchable&&(this.$select.select2("destroy"),this.$select.select2()),this.value(t),this._getValue()===null&&this.value(this.first())},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._getValue())},_getValue:function(){var t=this.$select.val();return e.validate(t)?t:null},_refresh:function(){var e=this.$select.find("option").length;e==0?(this.disable(),this.$select.empty(),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+'" class="'+e.cls+'">'+'<select id="'+e.id+'_select" class="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.$slider&&this.$slider.slider("value",e),this.$text.val(e),this.options.onchange&&this.options.onchange(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-button-check",["utils/utils"],function(e){return Backbone.View.extend({optionsDefault:{icons:["fa fa-square-o","fa fa-minus-square-o","fa fa-check-square-o"],value:0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($("<div/>")),this.value(this.options.value);var n=this;this.$el.on("click",function(){n.current=!n.current&&2||0,n.value(n.current),n.options.onclick&&n.options.onclick()})},value:function(e){return e!==undefined&&(this.current=e,this.$el.removeClass().addClass("ui-button-check").addClass(this.options.icons[e]),this.options.onchange&&this.options.onchange(e)),this.current}})}),define("mvc/ui/ui-options",["utils/utils","mvc/ui/ui-button-check"],function(e,t){var n=Backbone.View.extend({initialize:function(n){this.optionsDefault={visible:!0,data:[],id:e.uuid(),error_text:"No data available.",wait_text:"Please wait...",multiple:!1},this.options=e.merge(n,this.optionsDefault),this.setElement('<div class="ui-options"/>'),this.$message=$("<div/>"),this.$options=$(this._template(n)),this.$menu=$('<div class="ui-options-menu"/>'),this.$el.append(this.$message),this.$el.append(this.$menu),this.$el.append(this.$options),this.options.multiple&&(this.select_button=new t({onclick:function(){r.$("input").prop("checked",r.select_button.value()!==0),r._change()}}),this.$menu.addClass("ui-margin-bottom"),this.$menu.append(this.select_button.$el),this.$menu.append("Select/Unselect all")),this.options.visible||this.$el.hide(),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value);var r=this;this.on("change",function(){r._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"),r.tooltip({title:e[n].tooltip,placement:"bottom"}),this.$options.append(r)}var i=this;this.$("input").on("change",function(){i.value(i._getValue()),i._change()}),this.value(t)},value:function(e){if(e!==undefined){this.$("input").prop("checked",!1);if(e!==null){e instanceof Array||(e=[e]);for(var t in e)this.$('input[value="'+e[t]+'"]').first().prop("checked",!0)}}return this._refresh(),this._getValue()},exists:function(e){if(e!==undefined){e instanceof Array||(e=[e]);for(var t in e)if(this.$('input[value="'+e[t]+'"]').length>0)return!0}return!1},first:function(){var e=this.$("input").first();return e.length>0?e.val():null},wait:function(){this._size()==0&&(this._messageShow(this.options.wait_text,"info"),this.$options.hide(),this.$menu.hide())},unwait:function(){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.$menu.hide()):(this._messageHide(),this.$options.css("display","inline-block"),this.$menu.show());if(this.select_button){var e=this._size(),t=this._getValue();t instanceof Array?t.length!==e?this.select_button.value(1):this.select_button.value(2):this.select_button.value(0)}},_getValue:function(){var t=[];return this.$(":checked").each(function(){t.push($(this).val())}),e.validate(t)?this.options.multiple?t:t[0]:null},_size:function(){return this.$(".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-list"/>'}}),r=n.extend({_templateOption:function(t){var n=e.uuid();return'<div class="ui-option"><input id="'+n+'" type="'+this.options.type+'" name="'+this.options.id+'" value="'+t.value+'"/>'+'<label class="ui-options-label" for="'+n+'">'+t.label+"</label>"+"</div>"}}),i={};i.View=r.extend({initialize:function(e){e.type="radio",r.prototype.initialize.call(this,e)}});var s={};s.View=r.extend({initialize:function(e){e.multiple=!0,e.type="checkbox",r.prototype.initialize.call(this,e)}});var o={};return o.View=n.extend({initialize:function(e){n.prototype.initialize.call(this,e)},value:function(e){return e!==undefined&&(this.$("input").prop("checked",!1),this.$("label").removeClass("active"),this.$('[value="'+e+'"]').prop("checked",!0).closest("label").addClass("active")),this._getValue()},_templateOption:function(e){var t="fa "+e.icon;e.label||(t+=" no-padding");var n='<label class="btn btn-default">';return e.icon&&(n+='<i class="'+t+'"/>'),n+='<input type="radio" name="'+this.options.id+'" value="'+e.value+'"/>',e.label&&(n+=e.label),n+="</label>",n},_template:function(){return'<div class="btn-group ui-radiobutton" data-toggle="buttons"/>'}}),{Base:n,BaseIcons:r,Radio:i,RadioButton:o,Checkbox:s}}),define("mvc/ui/ui-drilldown",["utils/utils","mvc/ui/ui-options"],function(e,t){var n=t.BaseIcons.extend({initialize:function(e){e.type=e.display||"checkbox",e.multiple=e.display=="checkbox",t.BaseIcons.prototype.initialize.call(this,e),this.initial=!0},value:function(e){var n=t.BaseIcons.prototype.value.call(this,e);if(this.initial&&n!==null&&this.header_index){this.initial=!1;var r=n;$.isArray(r)||(r=[r]);for(var i in r){var s=this.header_index[r[i]];for(var o in s)this._setState(s[o],!0)}}return n},_setState:function(e,t){var n=this.$("#button-"+e),r=this.$("#subgroup-"+e);n.data("is_expanded",t),t?(r.fadeIn("fast"),n.removeClass("toggle-expand"),n.addClass("toggle")):(r.hide(),n.removeClass("toggle"),n.addClass("toggle-expand"))},_templateOptions:function(t){function r(e,t){var r=e.find("#button-"+t);r.on("click",function(){n._setState(t,!r.data("is_expanded"))})}function s(t,o,u){u=u||[];for(i in o){var a=o[i],f=a.options.length>0,l=u.slice(0);n.header_index[a.value]=l.slice(0);var c=$("<div/>");if(f){var h=e.uuid(),p=$('<span id="button-'+h+'" class="ui-drilldown-button form-toggle icon-button toggle-expand"/>'),d=$('<div id="subgroup-'+h+'" style="display: none; margin-left: 25px;"/>');l.push(h);var v=$("<div/>");v.append(p),v.append(n._templateOption({label:a.name,value:a.value})),c.append(v),s(d,a.options,l),c.append(d),r(c,h)}else c.append(n._templateOption({label:a.name,value:a.value}));t.append(c)}}var n=this;this.header_index={};var o=$("<div/>");return s(o,t),o},_template:function(e){return'<div class="ui-options-list 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-button-check","mvc/ui/ui-modal"],function(e,t,n,r,i,s,o,u){var a=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+'"/>'}}),f=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}}),l=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>"}}),c=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}}),h=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}}),p=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>"}}),d=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+'"/>'}}),v=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>"}}),m=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+'">'}}),g=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+="<div>"+e.info+"</div>"),t+='<hidden value="'+e.value+'"/>'+"</div>",t}});return{Anchor:p,Button:c,ButtonIcon:h,ButtonCheck:o,ButtonMenu:s,Icon:l,Image:a,Input:m,Label:f,Message:d,Modal:u,RadioButton:r.RadioButton,Checkbox:r.Checkbox,Radio:r.Radio,Searchbox:v,Select:t,Hidden:g,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,50);var r=$("body").css("overflow");this.$el.on("mouseover",function(){$("body").css("overflow","hidden")}).on("mouseout",function(){$("body").css("overflow",r)}),this._createContainer("div");var i=this;this.chart.on("redraw",function(){i._draw(i.chart)}),this.chart.on("set:state",function(){var e=i.$el.find("#info"),t=i.$el.find(".charts-viewport-container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(i.chart.get("state_info"));var r=i.chart.get("state");switch(r){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",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.addClass("ui-margin-top")),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(n,r){this.app=n;var i=this;this.chart=this.app.chart,this.group=r.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(e){i.group.set("key",e)}}),this.table=new e.View({content:"No data column."});var s=$("<div/>");s.append((new t.Label({title:"Provide a label:"})).$el),s.append(this.group_key.$el.addClass("ui-margin-bottom")),s.append((new t.Label({title:"Select columns:"})).$el.addClass("ui-margin-top")),s.append(this.table.$el.addClass("ui-margin-bottom")),this.setElement(s);var i=this;this.chart.on("change:dataset_id",function(){i._refreshTable()}),this.chart.on("change:type",function(){i._refreshTable()}),this.group.on("change:key",function(){i._refreshGroupKey()}),this.group.on("change",function(){i._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),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(this.table_title.$el),s.append(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((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(this.library.$el.addClass("ui-margin-bottom")),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(r,i){var s=this;this.app=r,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(){s._saveChart()}}),back:new t.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Cancel",onclick:function(){s.app.go("viewer"),s.app.storage.load()}})}}),this.types=new a(r,{onchange:function(e){var t=s.app.types.get(e);t||console.debug("FAILED - Editor::onchange() - Chart type not supported."),s.chart.definition=t,s.chart.settings.clear(),s.chart.set({type:e}),s.chart.set("modified",!0),console.debug("Editor::onchange() - Switched chart type.")},ondblclick:function(e){s._saveChart()}}),this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=s._addGroupModel();s.tabs.show(e.id)}}),this.title=new t.Input({placeholder:"Chart title",onchange:function(){s.chart.set("title",s.title.value())}});var o=$("<div/>");o.append((new t.Label({title:"Provide a chart title:"})).$el),o.append(this.title.$el),o.append($("<div/>").addClass("ui-table-form-info").html("This title will appear in the list of 'Saved Visualizations'. Charts are saved upon creation.")),o.append(this.types.$el.addClass("ui-margin-top")),this.tabs.add({id:"main",title:"Start",$el:o}),this.settings=new u(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.message.$el.addClass("ui-margin-top")),this.portlet.append(this.tabs.$el.addClass("ui-margin-top")),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var s=this;this.chart.on("change:title",function(e){s._refreshTitle()}),this.chart.on("change:type",function(e){s.types.value(e.get("type"))}),this.chart.on("reset",function(e){s._resetChart()}),this.app.chart.on("redraw",function(e){s.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){s._addGroup(e)}),this.app.chart.groups.on("remove",function(e){s._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){s._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){s._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&&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]);if(e.length===0)return!1;for(var t in e)if(["__null__","__undefined__","None",null,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,!0),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(){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: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.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(".portlet-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(e){this.$content.append(e)},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="portlet-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:"ui-select",error_text:"No data available",empty_text:"No selection",visible:!0,wait:!1,multiple:!1,searchable:!0,optional:!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.$el.addClass("ui-select-multiple"),this.$select.prop("multiple",!0),this.$button.remove()),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){if(e!==undefined){e===null&&(e="__null__");if(this.exists(e)||this.options.multiple)this.$select.val(e),this.$select.select2&&this.$select.select2("val",e)}return this._getValue()},first:function(){var e=this.$select.find("option").first();return e.length>0?e.val():null},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._getValue();this.$select.find("option").remove(),!this.options.multiple&&this.options.optional&&this.$select.append(this._templateOption({value:"__null__",label:this.options.empty_text}));for(var n in e)this.$select.append(this._templateOption(e[n]));this._refresh(),this.options.searchable&&(this.$select.select2("destroy"),this.$select.select2()),this.value(t),this._getValue()===null&&this.value(this.first())},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._getValue())},_getValue:function(){var t=this.$select.val();return e.validate(t)?t:null},_refresh:function(){var e=this.$select.find("option").length;e==0?(this.disable(),this.$select.empty(),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+'" class="'+e.cls+'">'+'<select id="'+e.id+'_select" class="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.$slider&&this.$slider.slider("value",e),this.$text.val(e),this.options.onchange&&this.options.onchange(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-button-check",["utils/utils"],function(e){return Backbone.View.extend({optionsDefault:{icons:["fa fa-square-o","fa fa-minus-square-o","fa fa-check-square-o"],value:0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($("<div/>")),this.value(this.options.value);var n=this;this.$el.on("click",function(){n.current=!n.current&&2||0,n.value(n.current),n.options.onclick&&n.options.onclick()})},value:function(e){return e!==undefined&&(this.current=e,this.$el.removeClass().addClass("ui-button-check").addClass(this.options.icons[e]),this.options.onchange&&this.options.onchange(e)),this.current}})}),define("mvc/ui/ui-options",["utils/utils","mvc/ui/ui-button-check"],function(e,t){var n=Backbone.View.extend({initialize:function(n){this.optionsDefault={visible:!0,data:[],id:e.uuid(),error_text:"No data available.",wait_text:"Please wait...",multiple:!1},this.options=e.merge(n,this.optionsDefault),this.setElement('<div class="ui-options"/>'),this.$message=$("<div/>"),this.$options=$(this._template(n)),this.$menu=$('<div class="ui-options-menu"/>'),this.$el.append(this.$message),this.$el.append(this.$menu),this.$el.append(this.$options),this.options.multiple&&(this.select_button=new t({onclick:function(){r.$("input").prop("checked",r.select_button.value()!==0),r._change()}}),this.$menu.addClass("ui-margin-bottom"),this.$menu.append(this.select_button.$el),this.$menu.append("Select/Unselect all")),this.options.visible||this.$el.hide(),this.update(this.options.data),this.options.value!==undefined&&this.value(this.options.value);var r=this;this.on("change",function(){r._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"),r.tooltip({title:e[n].tooltip,placement:"bottom"}),this.$options.append(r)}var i=this;this.$("input").on("change",function(){i.value(i._getValue()),i._change()}),this.value(t)},value:function(e){if(e!==undefined){this.$("input").prop("checked",!1);if(e!==null){e instanceof Array||(e=[e]);for(var t in e)this.$('input[value="'+e[t]+'"]').first().prop("checked",!0)}}return this._refresh(),this._getValue()},exists:function(e){if(e!==undefined){e instanceof Array||(e=[e]);for(var t in e)if(this.$('input[value="'+e[t]+'"]').length>0)return!0}return!1},first:function(){var e=this.$("input").first();return e.length>0?e.val():null},wait:function(){this._size()==0&&(this._messageShow(this.options.wait_text,"info"),this.$options.hide(),this.$menu.hide())},unwait:function(){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.$menu.hide()):(this._messageHide(),this.$options.css("display","inline-block"),this.$menu.show());if(this.select_button){var e=this._size(),t=this._getValue();t instanceof Array?t.length!==e?this.select_button.value(1):this.select_button.value(2):this.select_button.value(0)}},_getValue:function(){var t=[];return this.$(":checked").each(function(){t.push($(this).val())}),e.validate(t)?this.options.multiple?t:t[0]:null},_size:function(){return this.$(".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-list"/>'}}),r=n.extend({_templateOption:function(t){var n=e.uuid();return'<div class="ui-option"><input id="'+n+'" type="'+this.options.type+'" name="'+this.options.id+'" value="'+t.value+'"/>'+'<label class="ui-options-label" for="'+n+'">'+t.label+"</label>"+"</div>"}}),i={};i.View=r.extend({initialize:function(e){e.type="radio",r.prototype.initialize.call(this,e)}});var s={};s.View=r.extend({initialize:function(e){e.multiple=!0,e.type="checkbox",r.prototype.initialize.call(this,e)}});var o={};return o.View=n.extend({initialize:function(e){n.prototype.initialize.call(this,e)},value:function(e){return e!==undefined&&(this.$("input").prop("checked",!1),this.$("label").removeClass("active"),this.$('[value="'+e+'"]').prop("checked",!0).closest("label").addClass("active")),this._getValue()},_templateOption:function(e){var t="fa "+e.icon;e.label||(t+=" no-padding");var n='<label class="btn btn-default">';return e.icon&&(n+='<i class="'+t+'"/>'),n+='<input type="radio" name="'+this.options.id+'" value="'+e.value+'"/>',e.label&&(n+=e.label),n+="</label>",n},_template:function(){return'<div class="btn-group ui-radiobutton" data-toggle="buttons"/>'}}),{Base:n,BaseIcons:r,Radio:i,RadioButton:o,Checkbox:s}}),define("mvc/ui/ui-drilldown",["utils/utils","mvc/ui/ui-options"],function(e,t){var n=t.BaseIcons.extend({initialize:function(e){e.type=e.display||"checkbox",e.multiple=e.display=="checkbox",t.BaseIcons.prototype.initialize.call(this,e),this.initial=!0},value:function(e){var n=t.BaseIcons.prototype.value.call(this,e);if(this.initial&&n!==null&&this.header_index){this.initial=!1;var r=n;$.isArray(r)||(r=[r]);for(var i in r){var s=this.header_index[r[i]];for(var o in s)this._setState(s[o],!0)}}return n},_setState:function(e,t){var n=this.$("#button-"+e),r=this.$("#subgroup-"+e);n.data("is_expanded",t),t?(r.fadeIn("fast"),n.removeClass("toggle-expand"),n.addClass("toggle")):(r.hide(),n.removeClass("toggle"),n.addClass("toggle-expand"))},_templateOptions:function(t){function r(e,t){var r=e.find("#button-"+t);r.on("click",function(){n._setState(t,!r.data("is_expanded"))})}function s(t,o,u){u=u||[];for(i in o){var a=o[i],f=a.options.length>0,l=u.slice(0);n.header_index[a.value]=l.slice(0);var c=$("<div/>");if(f){var h=e.uuid(),p=$('<span id="button-'+h+'" class="ui-drilldown-button form-toggle icon-button toggle-expand"/>'),d=$('<div id="subgroup-'+h+'" style="display: none; margin-left: 25px;"/>');l.push(h);var v=$("<div/>");v.append(p),v.append(n._templateOption({label:a.name,value:a.value})),c.append(v),s(d,a.options,l),c.append(d),r(c,h)}else c.append(n._templateOption({label:a.name,value:a.value}));t.append(c)}}var n=this;this.header_index={};var o=$("<div/>");return s(o,t),o},_template:function(e){return'<div class="ui-options-list 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-button-check","mvc/ui/ui-modal"],function(e,t,n,r,i,s,o,u){var a=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+'"/>'}}),f=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}}),l=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>"}}),c=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}}),h=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}}),p=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>"}}),d=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+'"/>'}}),v=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>"}}),m=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+'">'}}),g=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+="<div>"+e.info+"</div>"),t+='<hidden value="'+e.value+'"/>'+"</div>",t}});return{Anchor:p,Button:c,ButtonIcon:h,ButtonCheck:o,ButtonMenu:s,Icon:l,Image:a,Input:m,Label:f,Message:d,Modal:u,RadioButton:r.RadioButton,Checkbox:r.Checkbox,Radio:r.Radio,Searchbox:v,Select:t,Hidden:g,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&&!o.is_text&&(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,50);var r=$("body").css("overflow");this.$el.on("mouseover",function(){$("body").css("overflow","hidden")}).on("mouseout",function(){$("body").css("overflow",r)}),this._createContainer("div");var i=this;this.chart.on("redraw",function(){i._draw(i.chart)}),this.chart.on("set:state",function(){var e=i.$el.find("#info"),t=i.$el.find(".charts-viewport-container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(i.chart.get("state_info"));var r=i.chart.get("state");switch(r){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",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.addClass("ui-margin-top")),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(n,r){this.app=n;var i=this;this.chart=this.app.chart,this.group=r.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(e){i.group.set("key",e)}}),this.table=new e.View({content:"No data column."});var s=$("<div/>");s.append((new t.Label({title:"Provide a label:"})).$el),s.append(this.group_key.$el.addClass("ui-margin-bottom")),s.append((new t.Label({title:"Select columns:"})).$el.addClass("ui-margin-top")),s.append(this.table.$el.addClass("ui-margin-bottom")),this.setElement(s);var i=this;this.chart.on("change:dataset_id",function(){i._refreshTable()}),this.chart.on("change:type",function(){i._refreshTable()}),this.group.on("change:key",function(){i._refreshGroupKey()}),this.group.on("change",function(){i._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=r.is_text,c=[],h=n[e];o&&c.push({label:"Column: Row Number",value:"auto"}),f&&c.push({label:"Column: None",value:"zero"});var p=t.metadata_column_types;for(var d in p){var v=!1;p[d]=="int"||p[d]=="float"?v=u:v=l||s,v&&c.push({label:"Column: "+(parseInt(d)+1),value:d})}h.update(c),a&&this.chart.groups.first()&&this.group.set(e,this.chart.groups.first().get(e));if(!h.exists(this.group.get(e))){var m=h.first();console.debug('Group()::_addRow() - Switching model value from "'+this.group.get(e)+'" to "'+m+'".'),this.group.set(e,m)}h.value(this.group.get(e)),this.group.off("change:"+e),this.group.on("change:"+e,function(){h.value(i.group.get(e))}),h.setOnChange(function(t){a?i.chart.groups.each(function(n){n.set(e,t)}):i.group.set(e,t),i.chart.set("modified",!0)}),h.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(this.table_title.$el),s.append(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((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(this.library.$el.addClass("ui-margin-bottom")),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(r,i){var s=this;this.app=r,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(){s._saveChart()}}),back:new t.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Cancel",onclick:function(){s.app.go("viewer"),s.app.storage.load()}})}}),this.types=new a(r,{onchange:function(e){var t=s.app.types.get(e);t||console.debug("FAILED - Editor::onchange() - Chart type not supported."),s.chart.definition=t,s.chart.settings.clear(),s.chart.set({type:e}),s.chart.set("modified",!0),console.debug("Editor::onchange() - Switched chart type.")},ondblclick:function(e){s._saveChart()}}),this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=s._addGroupModel();s.tabs.show(e.id)}}),this.title=new t.Input({placeholder:"Chart title",onchange:function(){s.chart.set("title",s.title.value())}});var o=$("<div/>");o.append((new t.Label({title:"Provide a chart title:"})).$el),o.append(this.title.$el),o.append($("<div/>").addClass("ui-table-form-info").html("This title will appear in the list of 'Saved Visualizations'. Charts are saved upon creation.")),o.append(this.types.$el.addClass("ui-margin-top")),this.tabs.add({id:"main",title:"Start",$el:o}),this.settings=new u(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.message.$el.addClass("ui-margin-top")),this.portlet.append(this.tabs.$el.addClass("ui-margin-top")),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var s=this;this.chart.on("change:title",function(e){s._refreshTitle()}),this.chart.on("change:type",function(e){s.types.value(e.get("type"))}),this.chart.on("reset",function(e){s._resetChart()}),this.app.chart.on("redraw",function(e){s.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){s._addGroup(e)}),this.app.chart.groups.on("remove",function(e){s._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){s._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){s._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&&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",columns:{tooltip:{title:"Data point labels",is_text:!0,is_numeric:!0,is_auto:!0}}})}),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 11d5bb0dd643c90472bebd5cc2b2d000c9ace85c -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 config/plugins/visualizations/charts/static/charts/nvd3/common/config.js --- a/config/plugins/visualizations/charts/static/charts/nvd3/common/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/common/config.js @@ -4,7 +4,15 @@ category : '', library : 'NVD3', tag : 'svg', - keywords : 'small' + keywords : 'small', + columns : { + tooltip : { + title : 'Data point labels', + is_text : true, + is_numeric : true, + is_auto : true + } + } }); }); \ No newline at end of file diff -r 11d5bb0dd643c90472bebd5cc2b2d000c9ace85c -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 config/plugins/visualizations/charts/static/charts/nvd3/common/wrapper.js --- a/config/plugins/visualizations/charts/static/charts/nvd3/common/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/common/wrapper.js @@ -15,71 +15,76 @@ options.render = function(canvas_id, groups) { return self.render(canvas_id, groups) }; - + // call panel helper Tools.panelHelper(app, options); }, - + // render render : function(canvas_id, groups) { var chart = this.options.chart; var type = this.options.type; var makeConfig = this.options.makeConfig; - + // create nvd3 model var d3chart = nv.models[type]() - + // request data var self = this; nv.addGraph(function() { try { // x axis label d3chart.xAxis.axisLabel(chart.settings.get('x_axis_label')); - + // y axis label d3chart.yAxis.axisLabel(chart.settings.get('y_axis_label')) .axisLabelDistance(30); - + // controls d3chart.options({showControls: false}); - + // legend if (d3chart.showLegend) { d3chart.showLegend(chart.settings.get('show_legend') == 'true'); } - + // make categories self._makeAxes(d3chart, groups, chart.settings); - + // custom callback if (makeConfig) { makeConfig(d3chart); } - + // hide controls if in multi-viewer mode if (chart.settings.get('use_panels') === 'true') { d3chart.options({showControls: false}); } - + // hide min/max values d3chart.xAxis.showMaxMin(false); d3chart.yAxis.showMaxMin(chart.definition.showmaxmin); - + + // configure tooltips + d3chart.tooltipContent(function(key, x, y, graph) { + return '<h3>' + (graph.point.tooltip || key) + '</h3>'; + }); + // draw chart if ($('#' + canvas_id).length == 0) { return; } var canvas = d3.select('#' + canvas_id); - canvas.datum(groups) + canvas.datum(groups) .call(d3chart); - + // add zoom/pan handler if (chart.definition.zoomable && chart.definition.zoomable != 'native') { // clip edges if (d3chart.clipEdge) { d3chart.clipEdge(true); } - + // add zoom Tools.addZoom({ xAxis : d3chart.xAxis, @@ -97,16 +102,16 @@ self._handleError(chart, err); } }); - + // return return true; }, - + // create axes formatting _makeAxes: function(d3chart, groups, settings) { // result var categories = Tools.makeCategories(groups); - + // make axes function makeTickFormat (id) { Tools.makeTickFormat({ @@ -125,7 +130,7 @@ makeTickFormat('x'); makeTickFormat('y'); }, - + // handle error _handleError: function(chart, err) { chart.state('failed', err); diff -r 11d5bb0dd643c90472bebd5cc2b2d000c9ace85c -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 config/plugins/visualizations/charts/static/charts/nvd3/scatter/config.js --- a/config/plugins/visualizations/charts/static/charts/nvd3/scatter/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/scatter/config.js @@ -6,11 +6,11 @@ zoomable : true, columns : { x : { - title : 'Values for x-axis', + title : 'Values for x-axis', is_numeric : true }, y : { - title : 'Values for y-axis', + title : 'Values for y-axis', is_numeric : true } } diff -r 11d5bb0dd643c90472bebd5cc2b2d000c9ace85c -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 config/plugins/visualizations/charts/static/library/datasets.js --- a/config/plugins/visualizations/charts/static/library/datasets.js +++ b/config/plugins/visualizations/charts/static/library/datasets.js @@ -299,7 +299,7 @@ // get/fix value var v = column_data[j]; - if (isNaN(v) && !column.is_label) { + if (isNaN(v) && !column.is_label && !column.is_text) { v = 0; } diff -r 11d5bb0dd643c90472bebd5cc2b2d000c9ace85c -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 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 @@ -145,12 +145,13 @@ // link this var self = this; - // is a numeric number required + // available column options var is_label = column_definition.is_label; var is_auto = column_definition.is_auto; var is_numeric = column_definition.is_numeric; var is_unique = column_definition.is_unique; var is_zero = column_definition.is_zero; + var is_text = column_definition.is_text; // configure columns var columns = []; @@ -182,7 +183,7 @@ if (meta[key] == 'int' || meta[key] == 'float') { valid = is_numeric; } else { - valid = is_label; + valid = is_text || is_label; } // check type https://bitbucket.org/galaxy/galaxy-central/commits/b8fa3f9d0350/ Changeset: b8fa3f9d0350 User: arobinson Date: 2015-02-17 18:21:03+00:00 Summary: Added Custom Authentication module support (CustomAuth) Initial modules: - ActiveDirectory (ldap) - LocalDB (fall back to galaxy users) - AlwaysAccept (whitelist) - AlwaysReject (blacklist) Sysadmin documentation at: https://docs.google.com/document/d/1CJp_m3vW7QKtAyBTMbE1MLgV6FAMuG3VO4HR-wHP... Testing documentation at: https://docs.google.com/document/d/1Cocx6Rt3eqPdm8IjOKYAR4RaY-9P2iFNXCt3AYg3... Affected #: 16 files diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 config/galaxy.ini.sample --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -844,6 +844,13 @@ #openid_config_file = config/openid_conf.xml #openid_consumer_cache_path = database/openid_consumer_cache +# Enable the use of custom authentication providers. Allows users to use their +# Active Directory (or other) account instead of local authentication +#enable_customauth = False +#customauth_config_file = config/customauth_conf.xml +# print debugging info for customauth +#enable_customauth_echo = True + # Optional list of email addresses of API users who can make calls on behalf of # other users #api_allow_run_as = None diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -441,6 +441,10 @@ # Default chunk size for chunkable datatypes -- 64k self.display_chunk_size = int( kwargs.get( 'display_chunk_size', 65536) ) + # customauth + self.enable_customauth = string_as_bool( kwargs.get( 'enable_customauth', False ) ) + self.customauth_config_file = resolve_path( kwargs.get( 'customauth_config_file', 'config/customauth_conf.xml' ), self.root ) + self.enable_customauth_echo = string_as_bool( kwargs.get( 'enable_customauth_echo', False ) ) self.citation_cache_type = kwargs.get( "citation_cache_type", "file" ) self.citation_cache_data_dir = self.resolve_path( kwargs.get( "citation_cache_data_dir", "database/citations/data" ) ) diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/__init__.py --- /dev/null +++ b/lib/galaxy/customauth/__init__.py @@ -0,0 +1,208 @@ +''' +Contains implementations of custom auth logic +''' + +import traceback +import xml.etree.ElementTree +from yapsy.PluginManager import PluginManager + +from galaxy.security.validate_user_input import validate_publicname + +import logging +logging.basicConfig(level=logging.DEBUG) + +# <customauth> +# <authenticator> +# <type>activedirectory</type> +# <filter>'[username]'.endswith('@students.latrobe.edu.au')</filter> +# <options> +# <auto-register>True</auto-register> +# <server>ldap://STUDENTS.ltu.edu.au</server> +# [<search-filter>(&(objectClass=user)(mail={username}))</search-filter> +# <search-base>dc=STUDENTS,dc=ltu,dc=edu,dc=au</search-base> +# <search-user>jsmith</search-user> +# <search-password>mysecret</search-password> +# <search-fields>sAMAccountName</search-fields>] +# <bind-user>{sAMAccountName}@STUDENTS.ltu.edu.au</bind-user> +# <bind-password>{password}</bind-password> +# <auto-register-username>{sAMAccountName}</auto-register-username> +# </options> +# </authenticator> +# ... +# </customauth> + + +def check_registration_allowed(trans, email, password, configfile, debug=False): + '''Checks if the provided email is allowed to register.''' + + message = '' + status = 'done' + + for provider,options in activeAuthProviderGenerator(email, password, configfile, debug): + allowreg = _getTriState(options, 'allow-register', True) + if allowreg is None: # i.e. challenge + authresult, msg = provider.authenticate(email, password, options, debug) + if authresult == True: + break + if authresult is None: + message = 'Invalid email address or password' + status = 'error' + break + elif allowreg is True: + break + elif allowreg is False: + message = 'Account registration not required for your account. Please simply login.' + status = 'error' + break + + return message, status + + +def check_auto_registration(trans, email, password, configfile, debug=False): + '''Checks the email/password using custom auth providers and if matches returns + the 'auto-register' option for that provider''' + + for provider,options in activeAuthProviderGenerator(email, password, configfile, debug): + if provider is None: + if debug: + print "Unable to find module: %s" % options + else: + authresult, autousername = provider.authenticate(email, password, options, debug) + autousername = str(autousername).lower() + if authresult is True: + # make username unique + if validate_publicname( trans, autousername ) != '': + i = 1 + while i <= 10: # stop after 10 tries + if validate_publicname( trans, "%s-%i" % (autousername, i) ) == '': + autousername = "%s-%i" % (autousername, i) + break + i += 1 + else: + break # end for loop if we can't make a unique username + if debug: + print "Email: %s, auto-register with username: %s" % (email, autousername) + return (_getBool(options, 'auto-register', False), autousername) + elif authresult is None: + print "Email: %s, stopping due to failed non-continue" % (email) + break # end authentication (skip rest) + + return (False, '') + + +def check_password(user, password, configfile, debug=False): + '''Checks the email/password using custom auth providers''' + + if debug: + print ("Checking with CustomAuth") + + + for provider,options in activeAuthProviderGenerator(user.email, password, configfile, debug): + if provider is None: + if debug: + print "Unable to find module: %s" % options + else: + authresult = provider.authenticateUser(user, password, options, debug) + if authresult is True: + return True # accept user + elif authresult is None: + break # end authentication (skip rest) + + return False + +def check_change_password(user, current_password, configfile, debug=False): + '''Checks that provider allows password changes and current_password matches''' + + if debug: + print ("Checking password change with CustomAuth") + + for provider,options in activeAuthProviderGenerator(user.email, current_password, configfile, debug): + if provider is None: + if debug: + print "Unable to find module: %s" % options + else: + if _getBool(options, "allow-password-change", False): + authresult = provider.authenticateUser(user, current_password, options, debug) + if authresult is True: + return (True, '') # accept user + elif authresult is None: + break # end authentication (skip rest) + else: + return (False, 'Password change not supported') + return (False, 'Invalid current password') + + + +def activeAuthProviderGenerator(username, password, configfile, debug): + '''Yields CustomAuthProvider instances for the provided configfile that match the filters''' + + try: + # load the yapsy plugins + manager = PluginManager() + manager.setPluginPlaces(["lib/galaxy/customauth/providers"]) + manager.collectPlugins() + + if debug: + print ("Plugins found:") + for plugin in manager.getAllPlugins(): + print ("- %s" % (plugin.path)) + + # parse XML + ct = xml.etree.ElementTree.parse(configfile) + confroot = ct.getroot() + + # process authenticators + for authelem in confroot.getchildren(): + typeelem = authelem.iter('type').next() + + # check filterelem + filterelem = _getChildElement(authelem, 'filter') + if filterelem is not None: + filterstr = str(filterelem.text).format(username=username, password=password) + if debug: + print ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__":None},{'str':str}))) + if not eval(filterstr, {"__builtins__":None},{'str':str}): + continue # skip to next + + # extract options + optionselem = _getChildElement(authelem, 'options') + options = {} + if optionselem is not None: + for opt in optionselem: + options[opt.tag] = opt.text + + # get the instance + plugin = manager.getPluginByName(typeelem.text) + yield (plugin.plugin_object, options) # excepts if type is spelled incorrectly + except GeneratorExit: + return + except: + if debug: + print ('CustomAuth: Exception:\n%s' % (traceback.format_exc(),)) + + +def _getBool(d, k, o): + if k in d: + if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): + return True + else: + return False + else: + return o + +def _getTriState(d, k, o): + if k in d: + if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): + return True + elif d[k] in ('False', 'false', 'No', 'no', '0', 0, False): + return False + else: + return None + else: + return o + +def _getChildElement(parent, childname): + try: + return parent.iter(childname).next() + except StopIteration: + return None diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/base.py --- /dev/null +++ b/lib/galaxy/customauth/base.py @@ -0,0 +1,41 @@ +''' +Created on 15/07/2014 + +@author: Andrew Robinson +''' + + +from yapsy.IPlugin import IPlugin + +class CustomAuthProvider(IPlugin): + '''A base class for all Custom Auth Providers''' + + def authenticate(self, username, password, options, debug=False): + ''' + Check the username and password are correct. + + NOTE: Used within auto-registration to check its ok to register this user + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + + return False + + def authenticateUser(self, user, password, options, debug=False): + ''' + Same as authenticate, except User object is provided instead of username. + + NOTE: used on normal login to check authentication and update user details if required. + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + + return False diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/activedirectory.py --- /dev/null +++ b/lib/galaxy/customauth/providers/activedirectory.py @@ -0,0 +1,119 @@ +''' +Created on 15/07/2014 + +@author: Andrew Robinson +''' + +import traceback +import galaxy.customauth.base + + +def _getsubs(d, k, vars, default=''): + if k in d: + return str(d[k]).format(**vars) + return str(default).format(**vars) + +def _getopt(d, k, default): + if k in d: + return d[k] + return default + +class ActiveDirectory(galaxy.customauth.base.CustomAuthProvider): + ''' + Attempts to authenticate them against the Active directory + + If options include search-fields then it will attempt to search the AD for + those fields first. After that it will bind to the AD with the username + (formatted as specified) + ''' + + def authenticate(self, username, password, options, debug=False): + ''' + Check the username and password are correct. + + NOTE: Used within auto-registration to check its ok to register this user + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + + if debug: + print ("Username: %s" % username) + print ("Options: %s" % options) + + failuremode = False # reject but continue + if _getopt(options, 'continue-on-failure', 'False') == 'False': + failuremode = None # reject and do not continue + + try: + import ldap + except: + if debug: + print ("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) + return (failuremode, '') + + ## do AD search (if required) ## + vars = {'username': username, 'password': password} + if 'search-fields' in options: + try: + # setup connection + ldap.set_option(ldap.OPT_REFERRALS, 0) + l = ldap.initialize(_getsubs(options,'server',vars)) + l.protocol_version = 3 + l.simple_bind_s(_getsubs(options,'search-user',vars), _getsubs(options,'search-password',vars)) + scope = ldap.SCOPE_SUBTREE + + # setup search + attributes = map(lambda s: s.strip().format(**vars), options['search-fields'].split(',')) + result = l.search(_getsubs(options,'search-base',vars), scope, _getsubs(options,'search-filter',vars), attributes) + + # parse results + _,suser = l.result(result,60) + _,attrs = suser[0] + if debug: + print ("AD Search attributes: %s" % attrs) + if hasattr(attrs, 'has_key'): + for attr in attributes: + if attrs.has_key(attr): + vars[attr] = str(attrs[attr][0]) + else: + vars[attr] = "" + except Exception: + if debug: + print('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) + return (failuremode, '') + # end search + + # bind as user to check their credentials + try: + # setup connection + ldap.set_option(ldap.OPT_REFERRALS, 0) + l = ldap.initialize(_getsubs(options,'server',vars)) + l.protocol_version = 3 + l.simple_bind_s(_getsubs(options,'bind-user',vars), _getsubs(options,'bind-password',vars)) + except Exception: + if debug: + print('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc(),)) + return (failuremode, '') + + if debug: + print "User: %s, ACTIVEDIRECTORY: True" % (username) + return (True, _getsubs(options,'auto-register-username',vars)) + + def authenticateUser(self, user, password, options, debug=False): + ''' + Same as authenticate, except User object is provided instead of username. + + NOTE: used on normal login to check authentication and update user details if required. + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + + return self.authenticate(user.email, password, options, debug)[0] diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/activedirectory.yapsy-plugin --- /dev/null +++ b/lib/galaxy/customauth/providers/activedirectory.yapsy-plugin @@ -0,0 +1,8 @@ +[Core] +Name = ActiveDirectory +Module = activedirectory + +[Documentation] +Author = Andrew Robinson +Version = 0.1 +Description = Custom Authentication Provider that authenticates against an ActiveDirectory (via LDAP). Requires python-ldap module. \ No newline at end of file diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/alwaysaccept.py --- /dev/null +++ b/lib/galaxy/customauth/providers/alwaysaccept.py @@ -0,0 +1,49 @@ +''' +Created on 16/07/2014 + +@author: Andrew Robinson +''' + +import traceback, re, string +import galaxy.customauth.base + + +class AlwaysAccept(galaxy.customauth.base.CustomAuthProvider): + '''A simple authenticator that just accepts user (doesn't care about their password)''' + + def authenticate(self, username, password, options, debug=False): + ''' + Check the username and password are correct. + + NOTE: Used within auto-registration to check its ok to register this user + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + if debug: + print ("User: %s, ALWAYSACCEPT: True (%s)" % (username, _stripUsername(username))) + return (True, _stripUsername(username)) + + def authenticateUser(self, user, password, options, debug=False): + ''' + Same as authenticate, except User object is provided instead of username. + + NOTE: used on normal login to check authentication and update user details if required. + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + + if debug: + print ("User: %s, ALWAYSACCEPT: True" % (user.email)) + return True + +def _stripUsername(username): + pattern = re.compile('[^a-zA-Z0-9\-]+') + return pattern.sub("-", username) diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/alwaysaccept.yapsy-plugin --- /dev/null +++ b/lib/galaxy/customauth/providers/alwaysaccept.yapsy-plugin @@ -0,0 +1,8 @@ +[Core] +Name = AlwaysAccept +Module = alwaysaccept + +[Documentation] +Author = Andrew Robinson +Version = 0.1 +Description = Custom Authentication Provider that is used for whitelisting usernames (i.e. accept any password) \ No newline at end of file diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/alwaysreject.py --- /dev/null +++ b/lib/galaxy/customauth/providers/alwaysreject.py @@ -0,0 +1,42 @@ +''' +Created on 16/07/2014 + +@author: Andrew Robinson +''' + +import traceback +import galaxy.customauth.base + +class AlwaysReject(galaxy.customauth.base.CustomAuthProvider): + '''A simple authenticator that just accepts user (doesn't care about their password)''' + + def authenticate(self, username, password, options, debug=False): + ''' + Check the username and password are correct. + + NOTE: Used within auto-registration to check its ok to register this user + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + return (None, '') + + def authenticateUser(self, user, password, options, debug=False): + ''' + Same as authenticate, except User object is provided instead of username. + + NOTE: used on normal login to check authentication and update user details if required. + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + + if debug: + print ("User: %s, ALWAYSREJECT: None" % (user.email)) + return None diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/alwaysreject.yapsy-plugin --- /dev/null +++ b/lib/galaxy/customauth/providers/alwaysreject.yapsy-plugin @@ -0,0 +1,8 @@ +[Core] +Name = AlwaysReject +Module = alwaysreject + +[Documentation] +Author = Andrew Robinson +Version = 0.1 +Description = Custom Authentication Provider that is used for blacklisting usernames (i.e. accept no password) \ No newline at end of file diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/localdb.py --- /dev/null +++ b/lib/galaxy/customauth/providers/localdb.py @@ -0,0 +1,44 @@ +''' +Created on 16/07/2014 + +@author: Andrew Robinson +''' + +import traceback +import galaxy.customauth.base + +class LocalDB(galaxy.customauth.base.CustomAuthProvider): + '''Checks against local DB (as per usual)''' + + def authenticate(self, username, password, options, debug=False): + ''' + Check the username and password are correct. + + NOTE: Used within auto-registration to check its ok to register this user + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: (boolean, str), True: accept user, False: reject user and None: reject user and don't try any other providers. str is the username to register with if accepting. + ''' + + return (False, '') # it can never auto-create based of localdb (chicken-egg) + + def authenticateUser(self, user, password, options, debug=False): + ''' + Same as authenticate, except User object is provided instead of username. + + NOTE: used on normal login to check authentication and update user details if required. + + @param username: the users email address + @param password: the plain text passord they typed + @param options: dictionary of options provided by admin in customauth xml config file + @param debug: boolean, False indicating admin wants debugging information printed + @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers + ''' + + user_ok = user.check_password(password) + if debug: + print ("User: %s, LOCALDB: %s" % (user.email, user_ok)) + return user_ok diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/customauth/providers/localdb.yapsy-plugin --- /dev/null +++ b/lib/galaxy/customauth/providers/localdb.yapsy-plugin @@ -0,0 +1,8 @@ +[Core] +Name = LocalDB +Module = localdb + +[Documentation] +Author = Andrew Robinson +Version = 0.1 +Description = Custom Authentication Provider that checks against the local database as per normal. \ No newline at end of file diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/webapps/galaxy/api/authenticate.py --- a/lib/galaxy/webapps/galaxy/api/authenticate.py +++ b/lib/galaxy/webapps/galaxy/api/authenticate.py @@ -18,6 +18,7 @@ from galaxy.managers import api_keys from galaxy import exceptions from galaxy.web.base.controller import BaseAPIController +import galaxy.customauth import logging log = logging.getLogger( __name__ ) @@ -52,7 +53,10 @@ raise exceptions.InconsistentDatabase( 'An error occured, please contact your administrator.' ) else: user = user[0] - is_valid_user = user.check_password( password ) + if (trans.app.config.enable_customauth): + is_valid_user = galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + else: + is_valid_user = user.check_password( password ) if ( is_valid_user ): key = self.api_keys_manager.get_or_create_api_key( user ) return dict( api_key=key ) diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/webapps/galaxy/controllers/mobile.py --- a/lib/galaxy/webapps/galaxy/controllers/mobile.py +++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py @@ -1,6 +1,7 @@ from galaxy import web from galaxy.web.base.controller import * +import galaxy.customauth class Mobile( BaseUIController ): @@ -58,12 +59,35 @@ # error = password_error = None # user = trans.sa_session.query( model.User ).filter_by( email = email ).first() # if not user: - # error = "No such user (please note that login is case sensitive)" + # if trans.app.config.enable_customauth: + # autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + # if autoreg[0]: + # kwd = {} + # kwd['username'] = autoreg[1] + # params = util.Params( kwd ) + # message = validate_email( trans, email ) + # if not message: + # message, status, user, success = self.__register( trans, 'user', False, **kwd ) + # if success: + # The handle_user_login() method has a call to the history_set_default_permissions() method + # (needed when logging in with a history), user needs to have default permissions set before logging in + # trans.handle_user_login( user ) + # trans.log_event( "User (auto) created a new account" ) + # trans.log_event( "User logged in" ) + # else: + # message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + # else: + # message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + # else: + # message = "No such user (please note that login is case sensitive)" + # else: + # message = "No such user (please note that login is case sensitive)" # elif user.deleted: # error = "This account has been marked deleted, contact your Galaxy administrator to restore the account." # elif user.external: # error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." - # elif not user.check_password( password ): + # elif not trans.app.config.enable_customauth and not user.check_password( password ) or \ + # trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo): # error = "Invalid password" # else: # trans.handle_user_login( user ) diff -r 56e108003f4eb1d35ea304ebdd3240c0508a91c4 -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -28,6 +28,7 @@ UsesFormDefinitionsMixin) from galaxy.web.form_builder import build_select_field, CheckboxField from galaxy.web.framework.helpers import escape, grids, time_ago +import galaxy.customauth log = logging.getLogger( __name__ ) @@ -513,8 +514,33 @@ redirect = kwd.get( 'redirect', trans.request.referer ).strip() success = False user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first() + if trans.app.config.enable_customauth_echo: + print ("trans.app.config.enable_customauth: %s" % trans.app.config.enable_customauth) + print ("trans.app.config.customauth_config_file: %s" % trans.app.config.customauth_config_file) + print ("trans.app.config.enable_customauth_echo: %s WARNING: don't use in production" % trans.app.config.enable_customauth_echo) if not user: - message = "No such user (please note that login is case sensitive)" + if trans.app.config.enable_customauth: + autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + if autoreg[0]: + kwd['username'] = autoreg[1] + params = util.Params( kwd ) + message = validate_email( trans, email ) #self.__validate( trans, params, email, password, password, username ) + if not message: + message, status, user, success = self.__register( trans, 'user', False, **kwd ) + if success: + # The handle_user_login() method has a call to the history_set_default_permissions() method + # (needed when logging in with a history), user needs to have default permissions set before logging in + trans.handle_user_login( user ) + trans.log_event( "User (auto) created a new account" ) + trans.log_event( "User logged in" ) + else: + message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + else: + message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + else: + message = "No such user or invalid password" + else: + message = "No such user (please note that login is case sensitive)" elif user.deleted: message = "This account has been marked deleted, contact your local Galaxy administrator to restore the account." if trans.app.config.error_email_to is not None: @@ -523,7 +549,8 @@ message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." if trans.app.config.error_email_to is not None: message += ' Contact: %s' % trans.app.config.error_email_to - elif not user.check_password( password ): + elif not trans.app.config.enable_customauth and not user.check_password( password ) or \ + trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo): message = "Invalid password" elif trans.app.config.user_activation_on and not user.active: # activation is ON and the user is INACTIVE if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON @@ -651,41 +678,46 @@ message += ' Contact: %s' % trans.app.config.error_email_to status = 'error' else: - if not refresh_frames: - if trans.webapp.name == 'galaxy': - if trans.app.config.require_login: - refresh_frames = [ 'masthead', 'history', 'tools' ] + # check user is allowed to register + message = '' + if trans.app.config.enable_customauth: + message, status = galaxy.customauth.check_registration_allowed(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + if message == '': + if not refresh_frames: + if trans.webapp.name == 'galaxy': + if trans.app.config.require_login: + refresh_frames = [ 'masthead', 'history', 'tools' ] + else: + refresh_frames = [ 'masthead', 'history' ] else: - refresh_frames = [ 'masthead', 'history' ] - else: - refresh_frames = [ 'masthead' ] - # Create the user, save all the user info and login to Galaxy - if params.get( 'create_user_button', False ): - # Check email and password validity - message = self.__validate( trans, params, email, password, confirm, username ) - if not message: - # All the values are valid - message, status, user, success = self.__register( trans, - cntrller, - subscribe_checked, - **kwd ) - if trans.webapp.name == 'tool_shed': - redirect_url = url_for( '/' ) - if success and not is_admin: - # The handle_user_login() method has a call to the history_set_default_permissions() method - # (needed when logging in with a history), user needs to have default permissions set before logging in - trans.handle_user_login( user ) - trans.log_event( "User created a new account" ) - trans.log_event( "User logged in" ) - if success and is_admin: - message = 'Created new user account (%s)' % escape( user.email ) - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - cntrller=cntrller, - message=message, - status=status ) ) - else: - status = 'error' + refresh_frames = [ 'masthead' ] + # Create the user, save all the user info and login to Galaxy + if params.get( 'create_user_button', False ): + # Check email and password validity + message = self.__validate( trans, params, email, password, confirm, username ) + if not message: + # All the values are valid + message, status, user, success = self.__register( trans, + cntrller, + subscribe_checked, + **kwd ) + if trans.webapp.name == 'tool_shed': + redirect_url = url_for( '/' ) + if success and not is_admin: + # The handle_user_login() method has a call to the history_set_default_permissions() method + # (needed when logging in with a history), user needs to have default permissions set before logging in + trans.handle_user_login( user ) + trans.log_event( "User created a new account" ) + trans.log_event( "User logged in" ) + if success and is_admin: + message = 'Created new user account (%s)' % escape( user.email ) + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + cntrller=cntrller, + message=message, + status=status ) ) + else: + status = 'error' if trans.webapp.name == 'galaxy': user_type_form_definition = self.__get_user_type_form_definition( trans, user=None, **kwd ) user_type_fd_id = params.get( 'user_type_fd_id', 'none' ) @@ -1100,7 +1132,13 @@ 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 ): + if trans.app.config.enable_customauth: + (ok, message) = galaxy.customauth.check_change_password(trans.user, current, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + if ok: + user = trans.user + else: + status = "error" + elif trans.user.check_password( current ): user = trans.user else: message = 'Invalid current password' https://bitbucket.org/galaxy/galaxy-central/commits/29d484334434/ Changeset: 29d484334434 User: nsoranzo Date: 2015-02-17 18:34:32+00:00 Summary: Rename enable_customauth_echo config option to customauth_debug. Affected #: 5 files diff -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 -r 29d48433443418575d112e9aa21e4f4669d861a5 config/galaxy.ini.sample --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -845,14 +845,14 @@ #openid_consumer_cache_path = database/openid_consumer_cache # Enable the use of custom authentication providers. Allows users to use their -# Active Directory (or other) account instead of local authentication +# Active Directory (or other) account instead of local authentication. #enable_customauth = False #customauth_config_file = config/customauth_conf.xml -# print debugging info for customauth -#enable_customauth_echo = True +# Print debugging info for customauth +#customauth_debug = False # Optional list of email addresses of API users who can make calls on behalf of -# other users +# other users. #api_allow_run_as = None # Master key that allows many API admin actions to be used without actually diff -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 -r 29d48433443418575d112e9aa21e4f4669d861a5 lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -444,7 +444,7 @@ # customauth self.enable_customauth = string_as_bool( kwargs.get( 'enable_customauth', False ) ) self.customauth_config_file = resolve_path( kwargs.get( 'customauth_config_file', 'config/customauth_conf.xml' ), self.root ) - self.enable_customauth_echo = string_as_bool( kwargs.get( 'enable_customauth_echo', False ) ) + self.customauth_debug = string_as_bool( kwargs.get( 'customauth_debug', False ) ) self.citation_cache_type = kwargs.get( "citation_cache_type", "file" ) self.citation_cache_data_dir = self.resolve_path( kwargs.get( "citation_cache_data_dir", "database/citations/data" ) ) diff -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 -r 29d48433443418575d112e9aa21e4f4669d861a5 lib/galaxy/webapps/galaxy/api/authenticate.py --- a/lib/galaxy/webapps/galaxy/api/authenticate.py +++ b/lib/galaxy/webapps/galaxy/api/authenticate.py @@ -54,7 +54,7 @@ else: user = user[0] if (trans.app.config.enable_customauth): - is_valid_user = galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + is_valid_user = galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) else: is_valid_user = user.check_password( password ) if ( is_valid_user ): diff -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 -r 29d48433443418575d112e9aa21e4f4669d861a5 lib/galaxy/webapps/galaxy/controllers/mobile.py --- a/lib/galaxy/webapps/galaxy/controllers/mobile.py +++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py @@ -60,7 +60,7 @@ # user = trans.sa_session.query( model.User ).filter_by( email = email ).first() # if not user: # if trans.app.config.enable_customauth: - # autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + # autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) # if autoreg[0]: # kwd = {} # kwd['username'] = autoreg[1] @@ -87,7 +87,7 @@ # elif user.external: # error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." # elif not trans.app.config.enable_customauth and not user.check_password( password ) or \ - # trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo): + # trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): # error = "Invalid password" # else: # trans.handle_user_login( user ) diff -r b8fa3f9d03500f83704e792e769e6be1f9c4a077 -r 29d48433443418575d112e9aa21e4f4669d861a5 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -514,13 +514,13 @@ redirect = kwd.get( 'redirect', trans.request.referer ).strip() success = False user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first() - if trans.app.config.enable_customauth_echo: + if trans.app.config.customauth_debug: print ("trans.app.config.enable_customauth: %s" % trans.app.config.enable_customauth) print ("trans.app.config.customauth_config_file: %s" % trans.app.config.customauth_config_file) - print ("trans.app.config.enable_customauth_echo: %s WARNING: don't use in production" % trans.app.config.enable_customauth_echo) + print ("trans.app.config.customauth_debug: %s WARNING: don't use in production" % trans.app.config.customauth_debug) if not user: if trans.app.config.enable_customauth: - autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) if autoreg[0]: kwd['username'] = autoreg[1] params = util.Params( kwd ) @@ -550,7 +550,7 @@ if trans.app.config.error_email_to is not None: message += ' Contact: %s' % trans.app.config.error_email_to elif not trans.app.config.enable_customauth and not user.check_password( password ) or \ - trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo): + trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): message = "Invalid password" elif trans.app.config.user_activation_on and not user.active: # activation is ON and the user is INACTIVE if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON @@ -681,7 +681,7 @@ # check user is allowed to register message = '' if trans.app.config.enable_customauth: - message, status = galaxy.customauth.check_registration_allowed(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + message, status = galaxy.customauth.check_registration_allowed(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) if message == '': if not refresh_frames: if trans.webapp.name == 'galaxy': @@ -1133,7 +1133,7 @@ else: # The user is changing their own password, validate their current password if trans.app.config.enable_customauth: - (ok, message) = galaxy.customauth.check_change_password(trans.user, current, trans.app.config.customauth_config_file, trans.app.config.enable_customauth_echo) + (ok, message) = galaxy.customauth.check_change_password(trans.user, current, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) if ok: user = trans.user else: https://bitbucket.org/galaxy/galaxy-central/commits/8ae0eb0b5567/ Changeset: 8ae0eb0b5567 User: nsoranzo Date: 2015-02-17 19:10:11+00:00 Summary: Remove AlwaysAccept customauth plugin. Affected #: 2 files diff -r 29d48433443418575d112e9aa21e4f4669d861a5 -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 lib/galaxy/customauth/providers/alwaysaccept.py --- a/lib/galaxy/customauth/providers/alwaysaccept.py +++ /dev/null @@ -1,49 +0,0 @@ -''' -Created on 16/07/2014 - -@author: Andrew Robinson -''' - -import traceback, re, string -import galaxy.customauth.base - - -class AlwaysAccept(galaxy.customauth.base.CustomAuthProvider): - '''A simple authenticator that just accepts user (doesn't care about their password)''' - - def authenticate(self, username, password, options, debug=False): - ''' - Check the username and password are correct. - - NOTE: Used within auto-registration to check its ok to register this user - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - if debug: - print ("User: %s, ALWAYSACCEPT: True (%s)" % (username, _stripUsername(username))) - return (True, _stripUsername(username)) - - def authenticateUser(self, user, password, options, debug=False): - ''' - Same as authenticate, except User object is provided instead of username. - - NOTE: used on normal login to check authentication and update user details if required. - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - - if debug: - print ("User: %s, ALWAYSACCEPT: True" % (user.email)) - return True - -def _stripUsername(username): - pattern = re.compile('[^a-zA-Z0-9\-]+') - return pattern.sub("-", username) diff -r 29d48433443418575d112e9aa21e4f4669d861a5 -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 lib/galaxy/customauth/providers/alwaysaccept.yapsy-plugin --- a/lib/galaxy/customauth/providers/alwaysaccept.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = AlwaysAccept -Module = alwaysaccept - -[Documentation] -Author = Andrew Robinson -Version = 0.1 -Description = Custom Authentication Provider that is used for whitelisting usernames (i.e. accept any password) \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/5ae99e242774/ Changeset: 5ae99e242774 User: nsoranzo Date: 2015-02-17 19:50:30+00:00 Summary: PEP-8, doc and other fixes suggested in PR #555 review. Affected #: 7 files diff -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 -r 5ae99e2427746abb436eb82231372c69a61017e0 lib/galaxy/customauth/__init__.py --- a/lib/galaxy/customauth/__init__.py +++ b/lib/galaxy/customauth/__init__.py @@ -1,6 +1,6 @@ -''' -Contains implementations of custom auth logic -''' +""" +Contains implementations of custom auth logic. +""" import traceback import xml.etree.ElementTree @@ -31,14 +31,11 @@ # ... # </customauth> - -def check_registration_allowed(trans, email, password, configfile, debug=False): - '''Checks if the provided email is allowed to register.''' - +def check_registration_allowed(email, password, configfile, debug=False): + """Checks if the provided email is allowed to register.""" message = '' status = 'done' - - for provider,options in activeAuthProviderGenerator(email, password, configfile, debug): + for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): allowreg = _getTriState(options, 'allow-register', True) if allowreg is None: # i.e. challenge authresult, msg = provider.authenticate(email, password, options, debug) @@ -54,15 +51,13 @@ message = 'Account registration not required for your account. Please simply login.' status = 'error' break - return message, status - def check_auto_registration(trans, email, password, configfile, debug=False): - '''Checks the email/password using custom auth providers and if matches returns - the 'auto-register' option for that provider''' - - for provider,options in activeAuthProviderGenerator(email, password, configfile, debug): + """Checks the email/password using custom auth providers and if matches + returns the 'auto-register' option for that provider. + """ + for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): if provider is None: if debug: print "Unable to find module: %s" % options @@ -86,18 +81,14 @@ elif authresult is None: print "Email: %s, stopping due to failed non-continue" % (email) break # end authentication (skip rest) - return (False, '') - def check_password(user, password, configfile, debug=False): - '''Checks the email/password using custom auth providers''' - + """Checks the email/password using custom auth providers.""" if debug: print ("Checking with CustomAuth") - - - for provider,options in activeAuthProviderGenerator(user.email, password, configfile, debug): + + for provider, options in activeAuthProviderGenerator(user.email, password, configfile, debug): if provider is None: if debug: print "Unable to find module: %s" % options @@ -107,16 +98,15 @@ return True # accept user elif authresult is None: break # end authentication (skip rest) - return False def check_change_password(user, current_password, configfile, debug=False): - '''Checks that provider allows password changes and current_password matches''' - + """Checks that provider allows password changes and current_password + matches. + """ if debug: print ("Checking password change with CustomAuth") - - for provider,options in activeAuthProviderGenerator(user.email, current_password, configfile, debug): + for provider, options in activeAuthProviderGenerator(user.email, current_password, configfile, debug): if provider is None: if debug: print "Unable to find module: %s" % options @@ -130,31 +120,30 @@ else: return (False, 'Password change not supported') return (False, 'Invalid current password') - - def activeAuthProviderGenerator(username, password, configfile, debug): - '''Yields CustomAuthProvider instances for the provided configfile that match the filters''' - + """Yields CustomAuthProvider instances for the provided configfile that + match the filters. + """ try: # load the yapsy plugins manager = PluginManager() - manager.setPluginPlaces(["lib/galaxy/customauth/providers"]) + manager.setPluginPlaces(["lib/galaxy/customauth/providers"]) manager.collectPlugins() - + if debug: print ("Plugins found:") for plugin in manager.getAllPlugins(): print ("- %s" % (plugin.path)) - + # parse XML ct = xml.etree.ElementTree.parse(configfile) confroot = ct.getroot() - + # process authenticators for authelem in confroot.getchildren(): typeelem = authelem.iter('type').next() - + # check filterelem filterelem = _getChildElement(authelem, 'filter') if filterelem is not None: @@ -163,14 +152,14 @@ print ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__":None},{'str':str}))) if not eval(filterstr, {"__builtins__":None},{'str':str}): continue # skip to next - + # extract options optionselem = _getChildElement(authelem, 'options') options = {} if optionselem is not None: for opt in optionselem: options[opt.tag] = opt.text - + # get the instance plugin = manager.getPluginByName(typeelem.text) yield (plugin.plugin_object, options) # excepts if type is spelled incorrectly @@ -180,7 +169,6 @@ if debug: print ('CustomAuth: Exception:\n%s' % (traceback.format_exc(),)) - def _getBool(d, k, o): if k in d: if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): @@ -189,7 +177,7 @@ return False else: return o - + def _getTriState(d, k, o): if k in d: if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): diff -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 -r 5ae99e2427746abb436eb82231372c69a61017e0 lib/galaxy/customauth/base.py --- a/lib/galaxy/customauth/base.py +++ b/lib/galaxy/customauth/base.py @@ -1,41 +1,54 @@ -''' +""" Created on 15/07/2014 @author: Andrew Robinson -''' - +""" from yapsy.IPlugin import IPlugin class CustomAuthProvider(IPlugin): - '''A base class for all Custom Auth Providers''' - + """A base class for all Custom Auth Providers.""" + def authenticate(self, username, password, options, debug=False): - ''' - Check the username and password are correct. - - NOTE: Used within auto-registration to check its ok to register this user - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - - return False - + """ + Check that the username and password are correct. + + NOTE: Used within auto-registration to check it is ok to register this + user. + + :param username: the users email address + :type username: str + :param password: the plain text password they typed + :type password: str + :param options: options provided in customauth XML config file + :type options: dict + :param debug: whether to print debugging info (defaults to False) + :type debug: bool + :returns: True: accept user, False: reject user and None: reject user + and don't try any other providers. str is the username to register + with if accepting + :rtype: (bool, str) + """ + raise NotImplementedError() + def authenticateUser(self, user, password, options, debug=False): - ''' - Same as authenticate, except User object is provided instead of username. - - NOTE: used on normal login to check authentication and update user details if required. - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - - return False + """ + Same as authenticate() method, except an User object is provided instead + of a username. + + NOTE: used on normal login to check authentication and update user + details if required. + + :param username: the users email address + :type username: str + :param password: the plain text password they typed + :type password: str + :param options: options provided in customauth XML config file + :type options: dict + :param debug: whether to print debugging info (defaults to False) + :type debug: bool + :returns: True: accept user, False: reject user and None: reject user + and don't try any other providers + :rtype: bool + """ + raise NotImplementedError() diff -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 -r 5ae99e2427746abb436eb82231372c69a61017e0 lib/galaxy/customauth/providers/activedirectory.py --- a/lib/galaxy/customauth/providers/activedirectory.py +++ b/lib/galaxy/customauth/providers/activedirectory.py @@ -1,8 +1,8 @@ -''' +""" Created on 15/07/2014 @author: Andrew Robinson -''' +""" import traceback import galaxy.customauth.base @@ -13,48 +13,35 @@ return str(d[k]).format(**vars) return str(default).format(**vars) -def _getopt(d, k, default): - if k in d: - return d[k] - return default class ActiveDirectory(galaxy.customauth.base.CustomAuthProvider): - ''' - Attempts to authenticate them against the Active directory - - If options include search-fields then it will attempt to search the AD for - those fields first. After that it will bind to the AD with the username - (formatted as specified) - ''' - + """ + Attempts to authenticate users against an Active Directory server. + + If options include search-fields then it will attempt to search the AD for + those fields first. After that it will bind to the AD with the username + (formatted as specified). + """ + def authenticate(self, username, password, options, debug=False): - ''' - Check the username and password are correct. - - NOTE: Used within auto-registration to check its ok to register this user - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - + """ + See abstract method documentation. + """ if debug: print ("Username: %s" % username) print ("Options: %s" % options) - + failuremode = False # reject but continue - if _getopt(options, 'continue-on-failure', 'False') == 'False': + if options.get('continue-on-failure', 'False') == 'False': failuremode = None # reject and do not continue - + try: import ldap except: if debug: print ("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) return (failuremode, '') - + ## do AD search (if required) ## vars = {'username': username, 'password': password} if 'search-fields' in options: @@ -65,11 +52,11 @@ l.protocol_version = 3 l.simple_bind_s(_getsubs(options,'search-user',vars), _getsubs(options,'search-password',vars)) scope = ldap.SCOPE_SUBTREE - + # setup search attributes = map(lambda s: s.strip().format(**vars), options['search-fields'].split(',')) result = l.search(_getsubs(options,'search-base',vars), scope, _getsubs(options,'search-filter',vars), attributes) - + # parse results _,suser = l.result(result,60) _,attrs = suser[0] @@ -86,7 +73,7 @@ print('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) return (failuremode, '') # end search - + # bind as user to check their credentials try: # setup connection @@ -98,22 +85,13 @@ if debug: print('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc(),)) return (failuremode, '') - + if debug: print "User: %s, ACTIVEDIRECTORY: True" % (username) return (True, _getsubs(options,'auto-register-username',vars)) - + def authenticateUser(self, user, password, options, debug=False): - ''' - Same as authenticate, except User object is provided instead of username. - - NOTE: used on normal login to check authentication and update user details if required. - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - + """ + See abstract method documentation. + """ return self.authenticate(user.email, password, options, debug)[0] diff -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 -r 5ae99e2427746abb436eb82231372c69a61017e0 lib/galaxy/customauth/providers/alwaysreject.py --- a/lib/galaxy/customauth/providers/alwaysreject.py +++ b/lib/galaxy/customauth/providers/alwaysreject.py @@ -1,42 +1,26 @@ -''' +""" Created on 16/07/2014 @author: Andrew Robinson -''' +""" -import traceback import galaxy.customauth.base class AlwaysReject(galaxy.customauth.base.CustomAuthProvider): - '''A simple authenticator that just accepts user (doesn't care about their password)''' - + """A simple authenticator that just accepts users (does not care about their + password). + """ + def authenticate(self, username, password, options, debug=False): - ''' - Check the username and password are correct. - - NOTE: Used within auto-registration to check its ok to register this user - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' + """ + See abstract method documentation. + """ return (None, '') - + def authenticateUser(self, user, password, options, debug=False): - ''' - Same as authenticate, except User object is provided instead of username. - - NOTE: used on normal login to check authentication and update user details if required. - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - + """ + See abstract method documentation. + """ if debug: print ("User: %s, ALWAYSREJECT: None" % (user.email)) return None diff -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 -r 5ae99e2427746abb436eb82231372c69a61017e0 lib/galaxy/customauth/providers/localdb.py --- a/lib/galaxy/customauth/providers/localdb.py +++ b/lib/galaxy/customauth/providers/localdb.py @@ -1,43 +1,24 @@ -''' +""" Created on 16/07/2014 @author: Andrew Robinson -''' +""" -import traceback import galaxy.customauth.base class LocalDB(galaxy.customauth.base.CustomAuthProvider): - '''Checks against local DB (as per usual)''' - + """Authenticate users against the local Galaxy database (as per usual).""" + def authenticate(self, username, password, options, debug=False): - ''' - Check the username and password are correct. - - NOTE: Used within auto-registration to check its ok to register this user - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: (boolean, str), True: accept user, False: reject user and None: reject user and don't try any other providers. str is the username to register with if accepting. - ''' - + """ + See abstract method documentation. + """ return (False, '') # it can never auto-create based of localdb (chicken-egg) - + def authenticateUser(self, user, password, options, debug=False): - ''' - Same as authenticate, except User object is provided instead of username. - - NOTE: used on normal login to check authentication and update user details if required. - - @param username: the users email address - @param password: the plain text passord they typed - @param options: dictionary of options provided by admin in customauth xml config file - @param debug: boolean, False indicating admin wants debugging information printed - @return: boolean, True: accept user, False: reject user and None: reject user and don't try any other providers - ''' - + """ + See abstract method documentation. + """ user_ok = user.check_password(password) if debug: print ("User: %s, LOCALDB: %s" % (user.email, user_ok)) diff -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 -r 5ae99e2427746abb436eb82231372c69a61017e0 lib/galaxy/webapps/galaxy/api/authenticate.py --- a/lib/galaxy/webapps/galaxy/api/authenticate.py +++ b/lib/galaxy/webapps/galaxy/api/authenticate.py @@ -46,18 +46,18 @@ user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).all() - if ( len( user ) == 0 ): + if len( user ) == 0: raise exceptions.ObjectNotFound( 'The user does not exist.' ) - elif ( len( user ) > 1 ): + elif len( user ) > 1: # DB is inconsistent and we have more users with the same email. raise exceptions.InconsistentDatabase( 'An error occured, please contact your administrator.' ) else: user = user[0] - if (trans.app.config.enable_customauth): + if trans.app.config.enable_customauth: is_valid_user = galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) else: is_valid_user = user.check_password( password ) - if ( is_valid_user ): + if is_valid_user: key = self.api_keys_manager.get_or_create_api_key( user ) return dict( api_key=key ) else: diff -r 8ae0eb0b556790796c2da2477db0fcd777ae13a7 -r 5ae99e2427746abb436eb82231372c69a61017e0 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -681,7 +681,7 @@ # check user is allowed to register message = '' if trans.app.config.enable_customauth: - message, status = galaxy.customauth.check_registration_allowed(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + message, status = galaxy.customauth.check_registration_allowed(email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) if message == '': if not refresh_frames: if trans.webapp.name == 'galaxy': https://bitbucket.org/galaxy/galaxy-central/commits/868d69d100d2/ Changeset: 868d69d100d2 User: nsoranzo Date: 2015-02-17 21:44:28+00:00 Summary: Make customauth always active. Added a config/customauth_conf.xml.sample file containing only the normal Galaxy database authentication method. Removed enable_customauth config option. Affected #: 6 files diff -r 5ae99e2427746abb436eb82231372c69a61017e0 -r 868d69d100d2aa855df35efb91ba418fef6491dd config/customauth_conf.xml.sample --- /dev/null +++ b/config/customauth_conf.xml.sample @@ -0,0 +1,6 @@ +<?xml version="1.0"?> +<customauth> + <authenticator> + <type>localdb</type> + </authenticator> +</customauth> diff -r 5ae99e2427746abb436eb82231372c69a61017e0 -r 868d69d100d2aa855df35efb91ba418fef6491dd config/galaxy.ini.sample --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -844,9 +844,9 @@ #openid_config_file = config/openid_conf.xml #openid_consumer_cache_path = database/openid_consumer_cache -# Enable the use of custom authentication providers. Allows users to use their -# Active Directory (or other) account instead of local authentication. -#enable_customauth = False +# XML config file that allows the use of custom authentication providers (e.g. +# Active Directory) instead or in addition to local authentication (.sample is +# used if default does not exist). #customauth_config_file = config/customauth_conf.xml # Print debugging info for customauth #customauth_debug = False diff -r 5ae99e2427746abb436eb82231372c69a61017e0 -r 868d69d100d2aa855df35efb91ba418fef6491dd lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -442,8 +442,6 @@ # Default chunk size for chunkable datatypes -- 64k self.display_chunk_size = int( kwargs.get( 'display_chunk_size', 65536) ) # customauth - self.enable_customauth = string_as_bool( kwargs.get( 'enable_customauth', False ) ) - self.customauth_config_file = resolve_path( kwargs.get( 'customauth_config_file', 'config/customauth_conf.xml' ), self.root ) self.customauth_debug = string_as_bool( kwargs.get( 'customauth_debug', False ) ) self.citation_cache_type = kwargs.get( "citation_cache_type", "file" ) @@ -466,6 +464,7 @@ Backwards compatibility for config files moved to the config/ dir. """ defaults = dict( + customauth_config_file=[ 'config/customauth_conf.xml', 'config/customauth_conf.xml.sample' ], data_manager_config_file=[ 'config/data_manager_conf.xml', 'data_manager_conf.xml', 'config/data_manager_conf.xml.sample' ], datatypes_config_file=[ 'config/datatypes_conf.xml', 'datatypes_conf.xml', 'config/datatypes_conf.xml.sample' ], external_service_type_config_file=[ 'config/external_service_types_conf.xml', 'external_service_types_conf.xml', 'config/external_service_types_conf.xml.sample' ], diff -r 5ae99e2427746abb436eb82231372c69a61017e0 -r 868d69d100d2aa855df35efb91ba418fef6491dd lib/galaxy/webapps/galaxy/api/authenticate.py --- a/lib/galaxy/webapps/galaxy/api/authenticate.py +++ b/lib/galaxy/webapps/galaxy/api/authenticate.py @@ -53,10 +53,7 @@ raise exceptions.InconsistentDatabase( 'An error occured, please contact your administrator.' ) else: user = user[0] - if trans.app.config.enable_customauth: - is_valid_user = galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) - else: - is_valid_user = user.check_password( password ) + is_valid_user = galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) if is_valid_user: key = self.api_keys_manager.get_or_create_api_key( user ) return dict( api_key=key ) diff -r 5ae99e2427746abb436eb82231372c69a61017e0 -r 868d69d100d2aa855df35efb91ba418fef6491dd lib/galaxy/webapps/galaxy/controllers/mobile.py --- a/lib/galaxy/webapps/galaxy/controllers/mobile.py +++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py @@ -59,35 +59,31 @@ # error = password_error = None # user = trans.sa_session.query( model.User ).filter_by( email = email ).first() # if not user: - # if trans.app.config.enable_customauth: - # autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) - # if autoreg[0]: - # kwd = {} - # kwd['username'] = autoreg[1] - # params = util.Params( kwd ) - # message = validate_email( trans, email ) - # if not message: - # message, status, user, success = self.__register( trans, 'user', False, **kwd ) - # if success: - # The handle_user_login() method has a call to the history_set_default_permissions() method - # (needed when logging in with a history), user needs to have default permissions set before logging in - # trans.handle_user_login( user ) - # trans.log_event( "User (auto) created a new account" ) - # trans.log_event( "User logged in" ) - # else: - # message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + # autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + # if autoreg[0]: + # kwd = {} + # kwd['username'] = autoreg[1] + # params = util.Params( kwd ) + # message = validate_email( trans, email ) + # if not message: + # message, status, user, success = self.__register( trans, 'user', False, **kwd ) + # if success: + # # The handle_user_login() method has a call to the history_set_default_permissions() method + # # (needed when logging in with a history), user needs to have default permissions set before logging in + # trans.handle_user_login( user ) + # trans.log_event( "User (auto) created a new account" ) + # trans.log_event( "User logged in" ) # else: - # message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + # message = "Auto-registration failed, contact your local Galaxy administrator. %s" % message # else: - # message = "No such user (please note that login is case sensitive)" + # message = "Auto-registration failed, contact your local Galaxy administrator. %s" % message # else: # message = "No such user (please note that login is case sensitive)" # elif user.deleted: # error = "This account has been marked deleted, contact your Galaxy administrator to restore the account." # elif user.external: # error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." - # elif not trans.app.config.enable_customauth and not user.check_password( password ) or \ - # trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): + # elif not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): # error = "Invalid password" # else: # trans.handle_user_login( user ) diff -r 5ae99e2427746abb436eb82231372c69a61017e0 -r 868d69d100d2aa855df35efb91ba418fef6491dd lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -515,32 +515,28 @@ success = False user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first() if trans.app.config.customauth_debug: - print ("trans.app.config.enable_customauth: %s" % trans.app.config.enable_customauth) print ("trans.app.config.customauth_config_file: %s" % trans.app.config.customauth_config_file) print ("trans.app.config.customauth_debug: %s WARNING: don't use in production" % trans.app.config.customauth_debug) if not user: - if trans.app.config.enable_customauth: - autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) - if autoreg[0]: - kwd['username'] = autoreg[1] - params = util.Params( kwd ) - message = validate_email( trans, email ) #self.__validate( trans, params, email, password, password, username ) - if not message: - message, status, user, success = self.__register( trans, 'user', False, **kwd ) - if success: - # The handle_user_login() method has a call to the history_set_default_permissions() method - # (needed when logging in with a history), user needs to have default permissions set before logging in - trans.handle_user_login( user ) - trans.log_event( "User (auto) created a new account" ) - trans.log_event( "User logged in" ) - else: - message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + if autoreg[0]: + kwd['username'] = autoreg[1] + params = util.Params( kwd ) + message = validate_email( trans, email ) #self.__validate( trans, params, email, password, password, username ) + if not message: + message, status, user, success = self.__register( trans, 'user', False, **kwd ) + if success: + # The handle_user_login() method has a call to the history_set_default_permissions() method + # (needed when logging in with a history), user needs to have default permissions set before logging in + trans.handle_user_login( user ) + trans.log_event( "User (auto) created a new account" ) + trans.log_event( "User logged in" ) else: - message = "Auto-registration failed, contact your local Galaxy administrator. %s" %message + message = "Auto-registration failed, contact your local Galaxy administrator. %s" % message else: - message = "No such user or invalid password" + message = "Auto-registration failed, contact your local Galaxy administrator. %s" % message else: - message = "No such user (please note that login is case sensitive)" + message = "No such user or invalid password" elif user.deleted: message = "This account has been marked deleted, contact your local Galaxy administrator to restore the account." if trans.app.config.error_email_to is not None: @@ -549,8 +545,7 @@ message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." if trans.app.config.error_email_to is not None: message += ' Contact: %s' % trans.app.config.error_email_to - elif not trans.app.config.enable_customauth and not user.check_password( password ) or \ - trans.app.config.enable_customauth and not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): + elif not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): message = "Invalid password" elif trans.app.config.user_activation_on and not user.active: # activation is ON and the user is INACTIVE if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON @@ -679,9 +674,7 @@ status = 'error' else: # check user is allowed to register - message = '' - if trans.app.config.enable_customauth: - message, status = galaxy.customauth.check_registration_allowed(email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + message, status = galaxy.customauth.check_registration_allowed(email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) if message == '': if not refresh_frames: if trans.webapp.name == 'galaxy': @@ -1132,16 +1125,10 @@ 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.app.config.enable_customauth: - (ok, message) = galaxy.customauth.check_change_password(trans.user, current, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) - if ok: - user = trans.user - else: - status = "error" - elif trans.user.check_password( current ): + (ok, message) = galaxy.customauth.check_change_password(trans.user, current, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + if ok: user = trans.user else: - message = 'Invalid current password' status = 'error' if user: # Validate the new password https://bitbucket.org/galaxy/galaxy-central/commits/8d0ea77d02b4/ Changeset: 8d0ea77d02b4 User: nsoranzo Date: 2015-02-20 18:20:40+00:00 Summary: Rename CustomAuth to Auth. Affected #: 25 files diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 config/auth_conf.xml.sample --- /dev/null +++ b/config/auth_conf.xml.sample @@ -0,0 +1,6 @@ +<?xml version="1.0"?> +<auth> + <authenticator> + <type>localdb</type> + </authenticator> +</auth> diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 config/customauth_conf.xml.sample --- a/config/customauth_conf.xml.sample +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<customauth> - <authenticator> - <type>localdb</type> - </authenticator> -</customauth> diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 config/galaxy.ini.sample --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -844,12 +844,12 @@ #openid_config_file = config/openid_conf.xml #openid_consumer_cache_path = database/openid_consumer_cache -# XML config file that allows the use of custom authentication providers (e.g. -# Active Directory) instead or in addition to local authentication (.sample is -# used if default does not exist). -#customauth_config_file = config/customauth_conf.xml -# Print debugging info for customauth -#customauth_debug = False +# XML config file that allows the use of different authentication providers +# (e.g. Active Directory) instead or in addition to local authentication +# (.sample is used if default does not exist). +#auth_config_file = config/auth_conf.xml +# Print debugging info for auth +#auth_debug = False # Optional list of email addresses of API users who can make calls on behalf of # other users. diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/__init__.py --- /dev/null +++ b/lib/galaxy/auth/__init__.py @@ -0,0 +1,192 @@ +""" +Contains implementations of the authentication logic. +""" + +import traceback +import xml.etree.ElementTree +from yapsy.PluginManager import PluginManager + +from galaxy.security.validate_user_input import validate_publicname + +import logging +logging.basicConfig(level=logging.DEBUG) + +# <auth> +# <authenticator> +# <type>activedirectory</type> +# <filter>'[username]'.endswith('@students.latrobe.edu.au')</filter> +# <options> +# <auto-register>True</auto-register> +# <server>ldap://STUDENTS.ltu.edu.au</server> +# [<search-filter>(&(objectClass=user)(mail={username}))</search-filter> +# <search-base>dc=STUDENTS,dc=ltu,dc=edu,dc=au</search-base> +# <search-user>jsmith</search-user> +# <search-password>mysecret</search-password> +# <search-fields>sAMAccountName</search-fields>] +# <bind-user>{sAMAccountName}@STUDENTS.ltu.edu.au</bind-user> +# <bind-password>{password}</bind-password> +# <auto-register-username>{sAMAccountName}</auto-register-username> +# </options> +# </authenticator> +# ... +# </auth> + +def check_registration_allowed(email, password, configfile, debug=False): + """Checks if the provided email is allowed to register.""" + message = '' + status = 'done' + for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): + allowreg = _getTriState(options, 'allow-register', True) + if allowreg is None: # i.e. challenge + authresult, msg = provider.authenticate(email, password, options, debug) + if authresult == True: + break + if authresult is None: + message = 'Invalid email address or password' + status = 'error' + break + elif allowreg is True: + break + elif allowreg is False: + message = 'Account registration not required for your account. Please simply login.' + status = 'error' + break + return message, status + +def check_auto_registration(trans, email, password, configfile, debug=False): + """ + Checks the email/password using auth providers in order. If a match is + found, returns the 'auto-register' option for that provider. + """ + for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): + if provider is None: + if debug: + print "Unable to find module: %s" % options + else: + authresult, autousername = provider.authenticate(email, password, options, debug) + autousername = str(autousername).lower() + if authresult is True: + # make username unique + if validate_publicname( trans, autousername ) != '': + i = 1 + while i <= 10: # stop after 10 tries + if validate_publicname( trans, "%s-%i" % (autousername, i) ) == '': + autousername = "%s-%i" % (autousername, i) + break + i += 1 + else: + break # end for loop if we can't make a unique username + if debug: + print "Email: %s, auto-register with username: %s" % (email, autousername) + return (_getBool(options, 'auto-register', False), autousername) + elif authresult is None: + print "Email: %s, stopping due to failed non-continue" % (email) + break # end authentication (skip rest) + return (False, '') + +def check_password(user, password, configfile, debug=False): + """Checks the email/password using auth providers.""" + for provider, options in activeAuthProviderGenerator(user.email, password, configfile, debug): + if provider is None: + if debug: + print "Unable to find module: %s" % options + else: + authresult = provider.authenticateUser(user, password, options, debug) + if authresult is True: + return True # accept user + elif authresult is None: + break # end authentication (skip rest) + return False + +def check_change_password(user, current_password, configfile, debug=False): + """Checks that auth provider allows password changes and current_password + matches. + """ + for provider, options in activeAuthProviderGenerator(user.email, current_password, configfile, debug): + if provider is None: + if debug: + print "Unable to find module: %s" % options + else: + if _getBool(options, "allow-password-change", False): + authresult = provider.authenticateUser(user, current_password, options, debug) + if authresult is True: + return (True, '') # accept user + elif authresult is None: + break # end authentication (skip rest) + else: + return (False, 'Password change not supported') + return (False, 'Invalid current password') + +def activeAuthProviderGenerator(username, password, configfile, debug): + """Yields AuthProvider instances for the provided configfile that match the + filters. + """ + try: + # load the yapsy plugins + manager = PluginManager() + manager.setPluginPlaces(["lib/galaxy/auth/providers"]) + manager.collectPlugins() + + if debug: + print ("Plugins found:") + for plugin in manager.getAllPlugins(): + print ("- %s" % (plugin.path)) + + # parse XML + ct = xml.etree.ElementTree.parse(configfile) + confroot = ct.getroot() + + # process authenticators + for authelem in confroot.getchildren(): + typeelem = authelem.iter('type').next() + + # check filterelem + filterelem = _getChildElement(authelem, 'filter') + if filterelem is not None: + filterstr = str(filterelem.text).format(username=username, password=password) + if debug: + print ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__":None},{'str':str}))) + if not eval(filterstr, {"__builtins__":None},{'str':str}): + continue # skip to next + + # extract options + optionselem = _getChildElement(authelem, 'options') + options = {} + if optionselem is not None: + for opt in optionselem: + options[opt.tag] = opt.text + + # get the instance + plugin = manager.getPluginByName(typeelem.text) + yield (plugin.plugin_object, options) # excepts if type is spelled incorrectly + except GeneratorExit: + return + except: + if debug: + print ('Auth: Exception:\n%s' % (traceback.format_exc(),)) + +def _getBool(d, k, o): + if k in d: + if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): + return True + else: + return False + else: + return o + +def _getTriState(d, k, o): + if k in d: + if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): + return True + elif d[k] in ('False', 'false', 'No', 'no', '0', 0, False): + return False + else: + return None + else: + return o + +def _getChildElement(parent, childname): + try: + return parent.iter(childname).next() + except StopIteration: + return None diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/base.py --- /dev/null +++ b/lib/galaxy/auth/base.py @@ -0,0 +1,54 @@ +""" +Created on 15/07/2014 + +@author: Andrew Robinson +""" + +from yapsy.IPlugin import IPlugin + +class AuthProvider(IPlugin): + """A base class for all Auth Providers.""" + + def authenticate(self, username, password, options, debug=False): + """ + Check that the username and password are correct. + + NOTE: Used within auto-registration to check it is ok to register this + user. + + :param username: the users email address + :type username: str + :param password: the plain text password they typed + :type password: str + :param options: options provided in auth_config_file + :type options: dict + :param debug: whether to print debugging info (defaults to False) + :type debug: bool + :returns: True: accept user, False: reject user and None: reject user + and don't try any other providers. str is the username to register + with if accepting + :rtype: (bool, str) + """ + raise NotImplementedError() + + def authenticateUser(self, user, password, options, debug=False): + """ + Same as authenticate() method, except an User object is provided instead + of a username. + + NOTE: used on normal login to check authentication and update user + details if required. + + :param username: the users email address + :type username: str + :param password: the plain text password they typed + :type password: str + :param options: options provided in auth_config_file + :type options: dict + :param debug: whether to print debugging info (defaults to False) + :type debug: bool + :returns: True: accept user, False: reject user and None: reject user + and don't try any other providers + :rtype: bool + """ + raise NotImplementedError() diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/providers/activedirectory.py --- /dev/null +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -0,0 +1,97 @@ +""" +Created on 15/07/2014 + +@author: Andrew Robinson +""" + +import traceback +import galaxy.auth.base + + +def _getsubs(d, k, vars, default=''): + if k in d: + return str(d[k]).format(**vars) + return str(default).format(**vars) + + +class ActiveDirectory(galaxy.auth.base.AuthProvider): + """ + Attempts to authenticate users against an Active Directory server. + + If options include search-fields then it will attempt to search the AD for + those fields first. After that it will bind to the AD with the username + (formatted as specified). + """ + + def authenticate(self, username, password, options, debug=False): + """ + See abstract method documentation. + """ + if debug: + print ("Username: %s" % username) + print ("Options: %s" % options) + + failuremode = False # reject but continue + if options.get('continue-on-failure', 'False') == 'False': + failuremode = None # reject and do not continue + + try: + import ldap + except: + if debug: + print ("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) + return (failuremode, '') + + ## do AD search (if required) ## + vars = {'username': username, 'password': password} + if 'search-fields' in options: + try: + # setup connection + ldap.set_option(ldap.OPT_REFERRALS, 0) + l = ldap.initialize(_getsubs(options,'server',vars)) + l.protocol_version = 3 + l.simple_bind_s(_getsubs(options,'search-user',vars), _getsubs(options,'search-password',vars)) + scope = ldap.SCOPE_SUBTREE + + # setup search + attributes = map(lambda s: s.strip().format(**vars), options['search-fields'].split(',')) + result = l.search(_getsubs(options,'search-base',vars), scope, _getsubs(options,'search-filter',vars), attributes) + + # parse results + _,suser = l.result(result,60) + _,attrs = suser[0] + if debug: + print ("AD Search attributes: %s" % attrs) + if hasattr(attrs, 'has_key'): + for attr in attributes: + if attrs.has_key(attr): + vars[attr] = str(attrs[attr][0]) + else: + vars[attr] = "" + except Exception: + if debug: + print('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) + return (failuremode, '') + # end search + + # bind as user to check their credentials + try: + # setup connection + ldap.set_option(ldap.OPT_REFERRALS, 0) + l = ldap.initialize(_getsubs(options,'server',vars)) + l.protocol_version = 3 + l.simple_bind_s(_getsubs(options,'bind-user',vars), _getsubs(options,'bind-password',vars)) + except Exception: + if debug: + print('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc(),)) + return (failuremode, '') + + if debug: + print "User: %s, ACTIVEDIRECTORY: True" % (username) + return (True, _getsubs(options,'auto-register-username',vars)) + + def authenticateUser(self, user, password, options, debug=False): + """ + See abstract method documentation. + """ + return self.authenticate(user.email, password, options, debug)[0] diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/providers/activedirectory.yapsy-plugin --- /dev/null +++ b/lib/galaxy/auth/providers/activedirectory.yapsy-plugin @@ -0,0 +1,8 @@ +[Core] +Name = ActiveDirectory +Module = activedirectory + +[Documentation] +Author = Andrew Robinson +Version = 0.1 +Description = Authentication Provider that authenticates against an ActiveDirectory (via LDAP). Requires python-ldap module. diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/providers/alwaysreject.py --- /dev/null +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -0,0 +1,26 @@ +""" +Created on 16/07/2014 + +@author: Andrew Robinson +""" + +import galaxy.auth.base + +class AlwaysReject(galaxy.auth.base.AuthProvider): + """A simple authenticator that just accepts users (does not care about their + password). + """ + + def authenticate(self, username, password, options, debug=False): + """ + See abstract method documentation. + """ + return (None, '') + + def authenticateUser(self, user, password, options, debug=False): + """ + See abstract method documentation. + """ + if debug: + print ("User: %s, ALWAYSREJECT: None" % (user.email)) + return None diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/providers/alwaysreject.yapsy-plugin --- /dev/null +++ b/lib/galaxy/auth/providers/alwaysreject.yapsy-plugin @@ -0,0 +1,8 @@ +[Core] +Name = AlwaysReject +Module = alwaysreject + +[Documentation] +Author = Andrew Robinson +Version = 0.1 +Description = Authentication Provider that is used for blacklisting usernames (i.e. accept no password) diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/providers/localdb.py --- /dev/null +++ b/lib/galaxy/auth/providers/localdb.py @@ -0,0 +1,25 @@ +""" +Created on 16/07/2014 + +@author: Andrew Robinson +""" + +import galaxy.auth.base + +class LocalDB(galaxy.auth.base.AuthProvider): + """Authenticate users against the local Galaxy database (as per usual).""" + + def authenticate(self, username, password, options, debug=False): + """ + See abstract method documentation. + """ + return (False, '') # it can never auto-create based of localdb (chicken-egg) + + def authenticateUser(self, user, password, options, debug=False): + """ + See abstract method documentation. + """ + user_ok = user.check_password(password) + if debug: + print ("User: %s, LOCALDB: %s" % (user.email, user_ok)) + return user_ok diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/auth/providers/localdb.yapsy-plugin --- /dev/null +++ b/lib/galaxy/auth/providers/localdb.yapsy-plugin @@ -0,0 +1,8 @@ +[Core] +Name = LocalDB +Module = localdb + +[Documentation] +Author = Andrew Robinson +Version = 0.1 +Description = Authentication Provider that checks against the local database as per normal. diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -441,8 +441,8 @@ # Default chunk size for chunkable datatypes -- 64k self.display_chunk_size = int( kwargs.get( 'display_chunk_size', 65536) ) - # customauth - self.customauth_debug = string_as_bool( kwargs.get( 'customauth_debug', False ) ) + # auth + self.auth_debug = string_as_bool( kwargs.get( 'auth_debug', False ) ) self.citation_cache_type = kwargs.get( "citation_cache_type", "file" ) self.citation_cache_data_dir = self.resolve_path( kwargs.get( "citation_cache_data_dir", "database/citations/data" ) ) @@ -464,7 +464,7 @@ Backwards compatibility for config files moved to the config/ dir. """ defaults = dict( - customauth_config_file=[ 'config/customauth_conf.xml', 'config/customauth_conf.xml.sample' ], + auth_config_file=[ 'config/auth_conf.xml', 'config/auth_conf.xml.sample' ], data_manager_config_file=[ 'config/data_manager_conf.xml', 'data_manager_conf.xml', 'config/data_manager_conf.xml.sample' ], datatypes_config_file=[ 'config/datatypes_conf.xml', 'datatypes_conf.xml', 'config/datatypes_conf.xml.sample' ], external_service_type_config_file=[ 'config/external_service_types_conf.xml', 'external_service_types_conf.xml', 'config/external_service_types_conf.xml.sample' ], diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/__init__.py --- a/lib/galaxy/customauth/__init__.py +++ /dev/null @@ -1,196 +0,0 @@ -""" -Contains implementations of custom auth logic. -""" - -import traceback -import xml.etree.ElementTree -from yapsy.PluginManager import PluginManager - -from galaxy.security.validate_user_input import validate_publicname - -import logging -logging.basicConfig(level=logging.DEBUG) - -# <customauth> -# <authenticator> -# <type>activedirectory</type> -# <filter>'[username]'.endswith('@students.latrobe.edu.au')</filter> -# <options> -# <auto-register>True</auto-register> -# <server>ldap://STUDENTS.ltu.edu.au</server> -# [<search-filter>(&(objectClass=user)(mail={username}))</search-filter> -# <search-base>dc=STUDENTS,dc=ltu,dc=edu,dc=au</search-base> -# <search-user>jsmith</search-user> -# <search-password>mysecret</search-password> -# <search-fields>sAMAccountName</search-fields>] -# <bind-user>{sAMAccountName}@STUDENTS.ltu.edu.au</bind-user> -# <bind-password>{password}</bind-password> -# <auto-register-username>{sAMAccountName}</auto-register-username> -# </options> -# </authenticator> -# ... -# </customauth> - -def check_registration_allowed(email, password, configfile, debug=False): - """Checks if the provided email is allowed to register.""" - message = '' - status = 'done' - for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): - allowreg = _getTriState(options, 'allow-register', True) - if allowreg is None: # i.e. challenge - authresult, msg = provider.authenticate(email, password, options, debug) - if authresult == True: - break - if authresult is None: - message = 'Invalid email address or password' - status = 'error' - break - elif allowreg is True: - break - elif allowreg is False: - message = 'Account registration not required for your account. Please simply login.' - status = 'error' - break - return message, status - -def check_auto_registration(trans, email, password, configfile, debug=False): - """Checks the email/password using custom auth providers and if matches - returns the 'auto-register' option for that provider. - """ - for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): - if provider is None: - if debug: - print "Unable to find module: %s" % options - else: - authresult, autousername = provider.authenticate(email, password, options, debug) - autousername = str(autousername).lower() - if authresult is True: - # make username unique - if validate_publicname( trans, autousername ) != '': - i = 1 - while i <= 10: # stop after 10 tries - if validate_publicname( trans, "%s-%i" % (autousername, i) ) == '': - autousername = "%s-%i" % (autousername, i) - break - i += 1 - else: - break # end for loop if we can't make a unique username - if debug: - print "Email: %s, auto-register with username: %s" % (email, autousername) - return (_getBool(options, 'auto-register', False), autousername) - elif authresult is None: - print "Email: %s, stopping due to failed non-continue" % (email) - break # end authentication (skip rest) - return (False, '') - -def check_password(user, password, configfile, debug=False): - """Checks the email/password using custom auth providers.""" - if debug: - print ("Checking with CustomAuth") - - for provider, options in activeAuthProviderGenerator(user.email, password, configfile, debug): - if provider is None: - if debug: - print "Unable to find module: %s" % options - else: - authresult = provider.authenticateUser(user, password, options, debug) - if authresult is True: - return True # accept user - elif authresult is None: - break # end authentication (skip rest) - return False - -def check_change_password(user, current_password, configfile, debug=False): - """Checks that provider allows password changes and current_password - matches. - """ - if debug: - print ("Checking password change with CustomAuth") - for provider, options in activeAuthProviderGenerator(user.email, current_password, configfile, debug): - if provider is None: - if debug: - print "Unable to find module: %s" % options - else: - if _getBool(options, "allow-password-change", False): - authresult = provider.authenticateUser(user, current_password, options, debug) - if authresult is True: - return (True, '') # accept user - elif authresult is None: - break # end authentication (skip rest) - else: - return (False, 'Password change not supported') - return (False, 'Invalid current password') - -def activeAuthProviderGenerator(username, password, configfile, debug): - """Yields CustomAuthProvider instances for the provided configfile that - match the filters. - """ - try: - # load the yapsy plugins - manager = PluginManager() - manager.setPluginPlaces(["lib/galaxy/customauth/providers"]) - manager.collectPlugins() - - if debug: - print ("Plugins found:") - for plugin in manager.getAllPlugins(): - print ("- %s" % (plugin.path)) - - # parse XML - ct = xml.etree.ElementTree.parse(configfile) - confroot = ct.getroot() - - # process authenticators - for authelem in confroot.getchildren(): - typeelem = authelem.iter('type').next() - - # check filterelem - filterelem = _getChildElement(authelem, 'filter') - if filterelem is not None: - filterstr = str(filterelem.text).format(username=username, password=password) - if debug: - print ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__":None},{'str':str}))) - if not eval(filterstr, {"__builtins__":None},{'str':str}): - continue # skip to next - - # extract options - optionselem = _getChildElement(authelem, 'options') - options = {} - if optionselem is not None: - for opt in optionselem: - options[opt.tag] = opt.text - - # get the instance - plugin = manager.getPluginByName(typeelem.text) - yield (plugin.plugin_object, options) # excepts if type is spelled incorrectly - except GeneratorExit: - return - except: - if debug: - print ('CustomAuth: Exception:\n%s' % (traceback.format_exc(),)) - -def _getBool(d, k, o): - if k in d: - if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): - return True - else: - return False - else: - return o - -def _getTriState(d, k, o): - if k in d: - if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): - return True - elif d[k] in ('False', 'false', 'No', 'no', '0', 0, False): - return False - else: - return None - else: - return o - -def _getChildElement(parent, childname): - try: - return parent.iter(childname).next() - except StopIteration: - return None diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/base.py --- a/lib/galaxy/customauth/base.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Created on 15/07/2014 - -@author: Andrew Robinson -""" - -from yapsy.IPlugin import IPlugin - -class CustomAuthProvider(IPlugin): - """A base class for all Custom Auth Providers.""" - - def authenticate(self, username, password, options, debug=False): - """ - Check that the username and password are correct. - - NOTE: Used within auto-registration to check it is ok to register this - user. - - :param username: the users email address - :type username: str - :param password: the plain text password they typed - :type password: str - :param options: options provided in customauth XML config file - :type options: dict - :param debug: whether to print debugging info (defaults to False) - :type debug: bool - :returns: True: accept user, False: reject user and None: reject user - and don't try any other providers. str is the username to register - with if accepting - :rtype: (bool, str) - """ - raise NotImplementedError() - - def authenticateUser(self, user, password, options, debug=False): - """ - Same as authenticate() method, except an User object is provided instead - of a username. - - NOTE: used on normal login to check authentication and update user - details if required. - - :param username: the users email address - :type username: str - :param password: the plain text password they typed - :type password: str - :param options: options provided in customauth XML config file - :type options: dict - :param debug: whether to print debugging info (defaults to False) - :type debug: bool - :returns: True: accept user, False: reject user and None: reject user - and don't try any other providers - :rtype: bool - """ - raise NotImplementedError() diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/providers/activedirectory.py --- a/lib/galaxy/customauth/providers/activedirectory.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Created on 15/07/2014 - -@author: Andrew Robinson -""" - -import traceback -import galaxy.customauth.base - - -def _getsubs(d, k, vars, default=''): - if k in d: - return str(d[k]).format(**vars) - return str(default).format(**vars) - - -class ActiveDirectory(galaxy.customauth.base.CustomAuthProvider): - """ - Attempts to authenticate users against an Active Directory server. - - If options include search-fields then it will attempt to search the AD for - those fields first. After that it will bind to the AD with the username - (formatted as specified). - """ - - def authenticate(self, username, password, options, debug=False): - """ - See abstract method documentation. - """ - if debug: - print ("Username: %s" % username) - print ("Options: %s" % options) - - failuremode = False # reject but continue - if options.get('continue-on-failure', 'False') == 'False': - failuremode = None # reject and do not continue - - try: - import ldap - except: - if debug: - print ("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) - return (failuremode, '') - - ## do AD search (if required) ## - vars = {'username': username, 'password': password} - if 'search-fields' in options: - try: - # setup connection - ldap.set_option(ldap.OPT_REFERRALS, 0) - l = ldap.initialize(_getsubs(options,'server',vars)) - l.protocol_version = 3 - l.simple_bind_s(_getsubs(options,'search-user',vars), _getsubs(options,'search-password',vars)) - scope = ldap.SCOPE_SUBTREE - - # setup search - attributes = map(lambda s: s.strip().format(**vars), options['search-fields'].split(',')) - result = l.search(_getsubs(options,'search-base',vars), scope, _getsubs(options,'search-filter',vars), attributes) - - # parse results - _,suser = l.result(result,60) - _,attrs = suser[0] - if debug: - print ("AD Search attributes: %s" % attrs) - if hasattr(attrs, 'has_key'): - for attr in attributes: - if attrs.has_key(attr): - vars[attr] = str(attrs[attr][0]) - else: - vars[attr] = "" - except Exception: - if debug: - print('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) - return (failuremode, '') - # end search - - # bind as user to check their credentials - try: - # setup connection - ldap.set_option(ldap.OPT_REFERRALS, 0) - l = ldap.initialize(_getsubs(options,'server',vars)) - l.protocol_version = 3 - l.simple_bind_s(_getsubs(options,'bind-user',vars), _getsubs(options,'bind-password',vars)) - except Exception: - if debug: - print('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc(),)) - return (failuremode, '') - - if debug: - print "User: %s, ACTIVEDIRECTORY: True" % (username) - return (True, _getsubs(options,'auto-register-username',vars)) - - def authenticateUser(self, user, password, options, debug=False): - """ - See abstract method documentation. - """ - return self.authenticate(user.email, password, options, debug)[0] diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/providers/activedirectory.yapsy-plugin --- a/lib/galaxy/customauth/providers/activedirectory.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = ActiveDirectory -Module = activedirectory - -[Documentation] -Author = Andrew Robinson -Version = 0.1 -Description = Custom Authentication Provider that authenticates against an ActiveDirectory (via LDAP). Requires python-ldap module. \ No newline at end of file diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/providers/alwaysreject.py --- a/lib/galaxy/customauth/providers/alwaysreject.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -Created on 16/07/2014 - -@author: Andrew Robinson -""" - -import galaxy.customauth.base - -class AlwaysReject(galaxy.customauth.base.CustomAuthProvider): - """A simple authenticator that just accepts users (does not care about their - password). - """ - - def authenticate(self, username, password, options, debug=False): - """ - See abstract method documentation. - """ - return (None, '') - - def authenticateUser(self, user, password, options, debug=False): - """ - See abstract method documentation. - """ - if debug: - print ("User: %s, ALWAYSREJECT: None" % (user.email)) - return None diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/providers/alwaysreject.yapsy-plugin --- a/lib/galaxy/customauth/providers/alwaysreject.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = AlwaysReject -Module = alwaysreject - -[Documentation] -Author = Andrew Robinson -Version = 0.1 -Description = Custom Authentication Provider that is used for blacklisting usernames (i.e. accept no password) \ No newline at end of file diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/providers/localdb.py --- a/lib/galaxy/customauth/providers/localdb.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Created on 16/07/2014 - -@author: Andrew Robinson -""" - -import galaxy.customauth.base - -class LocalDB(galaxy.customauth.base.CustomAuthProvider): - """Authenticate users against the local Galaxy database (as per usual).""" - - def authenticate(self, username, password, options, debug=False): - """ - See abstract method documentation. - """ - return (False, '') # it can never auto-create based of localdb (chicken-egg) - - def authenticateUser(self, user, password, options, debug=False): - """ - See abstract method documentation. - """ - user_ok = user.check_password(password) - if debug: - print ("User: %s, LOCALDB: %s" % (user.email, user_ok)) - return user_ok diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/customauth/providers/localdb.yapsy-plugin --- a/lib/galaxy/customauth/providers/localdb.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = LocalDB -Module = localdb - -[Documentation] -Author = Andrew Robinson -Version = 0.1 -Description = Custom Authentication Provider that checks against the local database as per normal. \ No newline at end of file diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/webapps/galaxy/api/authenticate.py --- a/lib/galaxy/webapps/galaxy/api/authenticate.py +++ b/lib/galaxy/webapps/galaxy/api/authenticate.py @@ -18,7 +18,7 @@ from galaxy.managers import api_keys from galaxy import exceptions from galaxy.web.base.controller import BaseAPIController -import galaxy.customauth +import galaxy.auth import logging log = logging.getLogger( __name__ ) @@ -53,7 +53,7 @@ raise exceptions.InconsistentDatabase( 'An error occured, please contact your administrator.' ) else: user = user[0] - is_valid_user = galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + is_valid_user = galaxy.auth.check_password(user, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) if is_valid_user: key = self.api_keys_manager.get_or_create_api_key( user ) return dict( api_key=key ) diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/webapps/galaxy/controllers/mobile.py --- a/lib/galaxy/webapps/galaxy/controllers/mobile.py +++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py @@ -1,7 +1,7 @@ from galaxy import web from galaxy.web.base.controller import * -import galaxy.customauth +import galaxy.auth class Mobile( BaseUIController ): @@ -59,7 +59,7 @@ # error = password_error = None # user = trans.sa_session.query( model.User ).filter_by( email = email ).first() # if not user: - # autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + # autoreg = galaxy.auth.check_auto_registration(trans, email, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) # if autoreg[0]: # kwd = {} # kwd['username'] = autoreg[1] @@ -83,7 +83,7 @@ # error = "This account has been marked deleted, contact your Galaxy administrator to restore the account." # elif user.external: # error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." - # elif not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): + # elif not galaxy.auth.check_password(user, password, trans.app.config.auth_config_file, trans.app.config.auth_debug): # error = "Invalid password" # else: # trans.handle_user_login( user ) diff -r 868d69d100d2aa855df35efb91ba418fef6491dd -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -28,7 +28,7 @@ UsesFormDefinitionsMixin) from galaxy.web.form_builder import build_select_field, CheckboxField from galaxy.web.framework.helpers import escape, grids, time_ago -import galaxy.customauth +import galaxy.auth log = logging.getLogger( __name__ ) @@ -514,11 +514,11 @@ redirect = kwd.get( 'redirect', trans.request.referer ).strip() success = False user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first() - if trans.app.config.customauth_debug: - print ("trans.app.config.customauth_config_file: %s" % trans.app.config.customauth_config_file) - print ("trans.app.config.customauth_debug: %s WARNING: don't use in production" % trans.app.config.customauth_debug) + if trans.app.config.auth_debug: + print ("trans.app.config.auth_config_file: %s" % trans.app.config.auth_config_file) + print ("trans.app.config.auth_debug: %s WARNING: don't use in production" % trans.app.config.auth_debug) if not user: - autoreg = galaxy.customauth.check_auto_registration(trans, email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + autoreg = galaxy.auth.check_auto_registration(trans, email, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) if autoreg[0]: kwd['username'] = autoreg[1] params = util.Params( kwd ) @@ -545,7 +545,7 @@ message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." if trans.app.config.error_email_to is not None: message += ' Contact: %s' % trans.app.config.error_email_to - elif not galaxy.customauth.check_password(user, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug): + elif not galaxy.auth.check_password(user, password, trans.app.config.auth_config_file, trans.app.config.auth_debug): message = "Invalid password" elif trans.app.config.user_activation_on and not user.active: # activation is ON and the user is INACTIVE if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON @@ -674,7 +674,7 @@ status = 'error' else: # check user is allowed to register - message, status = galaxy.customauth.check_registration_allowed(email, password, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + message, status = galaxy.auth.check_registration_allowed(email, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) if message == '': if not refresh_frames: if trans.webapp.name == 'galaxy': @@ -1125,7 +1125,7 @@ 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 - (ok, message) = galaxy.customauth.check_change_password(trans.user, current, trans.app.config.customauth_config_file, trans.app.config.customauth_debug) + (ok, message) = galaxy.auth.check_change_password(trans.user, current, trans.app.config.auth_config_file, trans.app.config.auth_debug) if ok: user = trans.user else: https://bitbucket.org/galaxy/galaxy-central/commits/74fcdbccf5a7/ Changeset: 74fcdbccf5a7 User: nsoranzo Date: 2015-02-24 23:06:25+00:00 Summary: WIP: Initial work on yapsy removal from galaxy.auth . Affected #: 8 files diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/base.py --- a/lib/galaxy/auth/base.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Created on 15/07/2014 - -@author: Andrew Robinson -""" - -from yapsy.IPlugin import IPlugin - -class AuthProvider(IPlugin): - """A base class for all Auth Providers.""" - - def authenticate(self, username, password, options, debug=False): - """ - Check that the username and password are correct. - - NOTE: Used within auto-registration to check it is ok to register this - user. - - :param username: the users email address - :type username: str - :param password: the plain text password they typed - :type password: str - :param options: options provided in auth_config_file - :type options: dict - :param debug: whether to print debugging info (defaults to False) - :type debug: bool - :returns: True: accept user, False: reject user and None: reject user - and don't try any other providers. str is the username to register - with if accepting - :rtype: (bool, str) - """ - raise NotImplementedError() - - def authenticateUser(self, user, password, options, debug=False): - """ - Same as authenticate() method, except an User object is provided instead - of a username. - - NOTE: used on normal login to check authentication and update user - details if required. - - :param username: the users email address - :type username: str - :param password: the plain text password they typed - :type password: str - :param options: options provided in auth_config_file - :type options: dict - :param debug: whether to print debugging info (defaults to False) - :type debug: bool - :returns: True: accept user, False: reject user and None: reject user - and don't try any other providers - :rtype: bool - """ - raise NotImplementedError() diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/providers/__init__.py --- a/lib/galaxy/auth/providers/__init__.py +++ b/lib/galaxy/auth/providers/__init__.py @@ -0,0 +1,59 @@ +""" +Created on 15/07/2014 + +@author: Andrew Robinson +""" + +import abc + +class AuthProvider(object): + """A base class for all Auth Providers.""" + __metaclass__ = abc.ABCMeta + + @abc.abstractproperty + def plugin_type(self): + """ Short string providing labelling this plugin """ + + @abc.abstractmethod + def authenticate(self, username, password, options, debug=False): + """ + Check that the username and password are correct. + + NOTE: Used within auto-registration to check it is ok to register this + user. + + :param username: the users email address + :type username: str + :param password: the plain text password they typed + :type password: str + :param options: options provided in auth_config_file + :type options: dict + :param debug: whether to print debugging info (defaults to False) + :type debug: bool + :returns: True: accept user, False: reject user and None: reject user + and don't try any other providers. str is the username to register + with if accepting + :rtype: (bool, str) + """ + + @abc.abstractmethod + def authenticateUser(self, user, password, options, debug=False): + """ + Same as authenticate() method, except an User object is provided instead + of a username. + + NOTE: used on normal login to check authentication and update user + details if required. + + :param username: the users email address + :type username: str + :param password: the plain text password they typed + :type password: str + :param options: options provided in auth_config_file + :type options: dict + :param debug: whether to print debugging info (defaults to False) + :type debug: bool + :returns: True: accept user, False: reject user and None: reject user + and don't try any other providers + :rtype: bool + """ diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -5,7 +5,7 @@ """ import traceback -import galaxy.auth.base +from ..providers import AuthProvider def _getsubs(d, k, vars, default=''): @@ -14,7 +14,7 @@ return str(default).format(**vars) -class ActiveDirectory(galaxy.auth.base.AuthProvider): +class ActiveDirectory(AuthProvider): """ Attempts to authenticate users against an Active Directory server. @@ -22,6 +22,9 @@ those fields first. After that it will bind to the AD with the username (formatted as specified). """ + @property + def plugin_type(self): + return 'activedirectory' def authenticate(self, username, password, options, debug=False): """ @@ -48,18 +51,18 @@ try: # setup connection ldap.set_option(ldap.OPT_REFERRALS, 0) - l = ldap.initialize(_getsubs(options,'server',vars)) + l = ldap.initialize(_getsubs(options, 'server', vars)) l.protocol_version = 3 - l.simple_bind_s(_getsubs(options,'search-user',vars), _getsubs(options,'search-password',vars)) + l.simple_bind_s(_getsubs(options, 'search-user', vars), _getsubs(options, 'search-password', vars)) scope = ldap.SCOPE_SUBTREE # setup search attributes = map(lambda s: s.strip().format(**vars), options['search-fields'].split(',')) - result = l.search(_getsubs(options,'search-base',vars), scope, _getsubs(options,'search-filter',vars), attributes) + result = l.search(_getsubs(options, 'search-base', vars), scope, _getsubs(options, 'search-filter', vars), attributes) # parse results - _,suser = l.result(result,60) - _,attrs = suser[0] + _, suser = l.result(result, 60) + _, attrs = suser[0] if debug: print ("AD Search attributes: %s" % attrs) if hasattr(attrs, 'has_key'): @@ -78,20 +81,23 @@ try: # setup connection ldap.set_option(ldap.OPT_REFERRALS, 0) - l = ldap.initialize(_getsubs(options,'server',vars)) + l = ldap.initialize(_getsubs(options, 'server', vars)) l.protocol_version = 3 - l.simple_bind_s(_getsubs(options,'bind-user',vars), _getsubs(options,'bind-password',vars)) + l.simple_bind_s(_getsubs(options, 'bind-user', vars), _getsubs(options, 'bind-password', vars)) except Exception: if debug: - print('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc(),)) + print('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) return (failuremode, '') if debug: print "User: %s, ACTIVEDIRECTORY: True" % (username) - return (True, _getsubs(options,'auto-register-username',vars)) + return (True, _getsubs(options, 'auto-register-username', vars)) def authenticateUser(self, user, password, options, debug=False): """ See abstract method documentation. """ return self.authenticate(user.email, password, options, debug)[0] + + +__all__ = ['ActiveDirectory'] diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/providers/activedirectory.yapsy-plugin --- a/lib/galaxy/auth/providers/activedirectory.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = ActiveDirectory -Module = activedirectory - -[Documentation] -Author = Andrew Robinson -Version = 0.1 -Description = Authentication Provider that authenticates against an ActiveDirectory (via LDAP). Requires python-ldap module. diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/providers/alwaysreject.py --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -4,12 +4,16 @@ @author: Andrew Robinson """ -import galaxy.auth.base +from ..providers import AuthProvider -class AlwaysReject(galaxy.auth.base.AuthProvider): + +class AlwaysReject(AuthProvider): """A simple authenticator that just accepts users (does not care about their password). """ + @property + def plugin_type(self): + return 'alwaysreject' def authenticate(self, username, password, options, debug=False): """ @@ -24,3 +28,6 @@ if debug: print ("User: %s, ALWAYSREJECT: None" % (user.email)) return None + + +__all__ = ['AlwaysReject'] diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/providers/alwaysreject.yapsy-plugin --- a/lib/galaxy/auth/providers/alwaysreject.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = AlwaysReject -Module = alwaysreject - -[Documentation] -Author = Andrew Robinson -Version = 0.1 -Description = Authentication Provider that is used for blacklisting usernames (i.e. accept no password) diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/providers/localdb.py --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -4,10 +4,14 @@ @author: Andrew Robinson """ -import galaxy.auth.base +from ..providers import AuthProvider -class LocalDB(galaxy.auth.base.AuthProvider): + +class LocalDB(AuthProvider): """Authenticate users against the local Galaxy database (as per usual).""" + @property + def plugin_type(self): + return 'localdb' def authenticate(self, username, password, options, debug=False): """ @@ -23,3 +27,6 @@ if debug: print ("User: %s, LOCALDB: %s" % (user.email, user_ok)) return user_ok + + +__all__ = ['LocalDB'] diff -r 8d0ea77d02b404a17a4c2e058f4b537bf7a05ba0 -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e lib/galaxy/auth/providers/localdb.yapsy-plugin --- a/lib/galaxy/auth/providers/localdb.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = LocalDB -Module = localdb - -[Documentation] -Author = Andrew Robinson -Version = 0.1 -Description = Authentication Provider that checks against the local database as per normal. https://bitbucket.org/galaxy/galaxy-central/commits/dd0d3b4df70f/ Changeset: dd0d3b4df70f User: jmchilton Date: 2015-03-02 01:08:29+00:00 Summary: Use galaxy-style logging instead of print in galaxy.auth. Affected #: 1 file diff -r 74fcdbccf5a79b51dc1e30f30eb0aabcc5484f6e -r dd0d3b4df70ff7c0dae880cd7488aeec42af7878 lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -9,7 +9,7 @@ from galaxy.security.validate_user_input import validate_publicname import logging -logging.basicConfig(level=logging.DEBUG) +log = logging.getLogger(__name__) # <auth> # <authenticator> @@ -61,7 +61,7 @@ for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): if provider is None: if debug: - print "Unable to find module: %s" % options + log.debug( "Unable to find module: %s" % options ) else: authresult, autousername = provider.authenticate(email, password, options, debug) autousername = str(autousername).lower() @@ -77,10 +77,10 @@ else: break # end for loop if we can't make a unique username if debug: - print "Email: %s, auto-register with username: %s" % (email, autousername) + log.debug( "Email: %s, auto-register with username: %s" % (email, autousername) ) return (_getBool(options, 'auto-register', False), autousername) elif authresult is None: - print "Email: %s, stopping due to failed non-continue" % (email) + log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) break # end authentication (skip rest) return (False, '') @@ -89,7 +89,7 @@ for provider, options in activeAuthProviderGenerator(user.email, password, configfile, debug): if provider is None: if debug: - print "Unable to find module: %s" % options + log.debug( "Unable to find module: %s" % options ) else: authresult = provider.authenticateUser(user, password, options, debug) if authresult is True: @@ -105,7 +105,7 @@ for provider, options in activeAuthProviderGenerator(user.email, current_password, configfile, debug): if provider is None: if debug: - print "Unable to find module: %s" % options + log.debug( "Unable to find module: %s" % options ) else: if _getBool(options, "allow-password-change", False): authresult = provider.authenticateUser(user, current_password, options, debug) @@ -128,9 +128,9 @@ manager.collectPlugins() if debug: - print ("Plugins found:") + log.debug( ("Plugins found:") ) for plugin in manager.getAllPlugins(): - print ("- %s" % (plugin.path)) + log.debug( ("- %s" % (plugin.path)) ) # parse XML ct = xml.etree.ElementTree.parse(configfile) @@ -145,7 +145,7 @@ if filterelem is not None: filterstr = str(filterelem.text).format(username=username, password=password) if debug: - print ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__":None},{'str':str}))) + log.debug( ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__":None},{'str':str}))) ) if not eval(filterstr, {"__builtins__":None},{'str':str}): continue # skip to next @@ -163,7 +163,7 @@ return except: if debug: - print ('Auth: Exception:\n%s' % (traceback.format_exc(),)) + log.debug( ('Auth: Exception:\n%s' % (traceback.format_exc(),)) ) def _getBool(d, k, o): if k in d: https://bitbucket.org/galaxy/galaxy-central/commits/56d21c8237db/ Changeset: 56d21c8237db User: jmchilton Date: 2015-03-02 01:11:14+00:00 Summary: Reuse galaxy.util bool checking in galaxy.auth. Affected #: 1 file diff -r dd0d3b4df70ff7c0dae880cd7488aeec42af7878 -r 56d21c8237dbd121825ec79c6f0b476e1374ac7e lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -8,6 +8,11 @@ from galaxy.security.validate_user_input import validate_publicname +from galaxy.util import ( + string_as_bool, + string_as_bool_or_none, +) + import logging log = logging.getLogger(__name__) @@ -167,21 +172,13 @@ def _getBool(d, k, o): if k in d: - if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): - return True - else: - return False + return string_as_bool(d[k]) else: return o def _getTriState(d, k, o): if k in d: - if d[k] in ('True', 'true', 'Yes', 'yes', '1', 1, True): - return True - elif d[k] in ('False', 'false', 'No', 'no', '0', 0, False): - return False - else: - return None + return string_as_bool_or_none(d[k]) else: return o https://bitbucket.org/galaxy/galaxy-central/commits/a47c91afe317/ Changeset: a47c91afe317 User: jmchilton Date: 2015-03-02 01:17:11+00:00 Summary: PEP-8 fixes for auth code. Affected #: 4 files diff -r 56d21c8237dbd121825ec79c6f0b476e1374ac7e -r a47c91afe31716b7a4dd527fc32804fab305989b lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -36,15 +36,16 @@ # ... # </auth> + def check_registration_allowed(email, password, configfile, debug=False): """Checks if the provided email is allowed to register.""" message = '' status = 'done' for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): allowreg = _getTriState(options, 'allow-register', True) - if allowreg is None: # i.e. challenge + if allowreg is None: # i.e. challenge authresult, msg = provider.authenticate(email, password, options, debug) - if authresult == True: + if authresult is True: break if authresult is None: message = 'Invalid email address or password' @@ -58,6 +59,7 @@ break return message, status + def check_auto_registration(trans, email, password, configfile, debug=False): """ Checks the email/password using auth providers in order. If a match is @@ -74,21 +76,22 @@ # make username unique if validate_publicname( trans, autousername ) != '': i = 1 - while i <= 10: # stop after 10 tries + while i <= 10: # stop after 10 tries if validate_publicname( trans, "%s-%i" % (autousername, i) ) == '': autousername = "%s-%i" % (autousername, i) break i += 1 else: - break # end for loop if we can't make a unique username + break # end for loop if we can't make a unique username if debug: log.debug( "Email: %s, auto-register with username: %s" % (email, autousername) ) return (_getBool(options, 'auto-register', False), autousername) elif authresult is None: log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) - break # end authentication (skip rest) + break # end authentication (skip rest) return (False, '') + def check_password(user, password, configfile, debug=False): """Checks the email/password using auth providers.""" for provider, options in activeAuthProviderGenerator(user.email, password, configfile, debug): @@ -98,11 +101,12 @@ else: authresult = provider.authenticateUser(user, password, options, debug) if authresult is True: - return True # accept user + return True # accept user elif authresult is None: - break # end authentication (skip rest) + break # end authentication (skip rest) return False + def check_change_password(user, current_password, configfile, debug=False): """Checks that auth provider allows password changes and current_password matches. @@ -115,13 +119,14 @@ if _getBool(options, "allow-password-change", False): authresult = provider.authenticateUser(user, current_password, options, debug) if authresult is True: - return (True, '') # accept user + return (True, '') # accept user elif authresult is None: - break # end authentication (skip rest) + break # end authentication (skip rest) else: return (False, 'Password change not supported') return (False, 'Invalid current password') + def activeAuthProviderGenerator(username, password, configfile, debug): """Yields AuthProvider instances for the provided configfile that match the filters. @@ -150,9 +155,9 @@ if filterelem is not None: filterstr = str(filterelem.text).format(username=username, password=password) if debug: - log.debug( ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__":None},{'str':str}))) ) - if not eval(filterstr, {"__builtins__":None},{'str':str}): - continue # skip to next + log.debug( ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__": None}, {'str': str}))) ) + if not eval(filterstr, {"__builtins__": None}, {'str': str}): + continue # skip to next # extract options optionselem = _getChildElement(authelem, 'options') @@ -170,18 +175,21 @@ if debug: log.debug( ('Auth: Exception:\n%s' % (traceback.format_exc(),)) ) + def _getBool(d, k, o): if k in d: return string_as_bool(d[k]) else: return o + def _getTriState(d, k, o): if k in d: return string_as_bool_or_none(d[k]) else: return o + def _getChildElement(parent, childname): try: return parent.iter(childname).next() diff -r 56d21c8237dbd121825ec79c6f0b476e1374ac7e -r a47c91afe31716b7a4dd527fc32804fab305989b lib/galaxy/auth/providers/__init__.py --- a/lib/galaxy/auth/providers/__init__.py +++ b/lib/galaxy/auth/providers/__init__.py @@ -6,6 +6,7 @@ import abc + class AuthProvider(object): """A base class for all Auth Providers.""" __metaclass__ = abc.ABCMeta diff -r 56d21c8237dbd121825ec79c6f0b476e1374ac7e -r a47c91afe31716b7a4dd527fc32804fab305989b lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -34,9 +34,9 @@ print ("Username: %s" % username) print ("Options: %s" % options) - failuremode = False # reject but continue + failuremode = False # reject but continue if options.get('continue-on-failure', 'False') == 'False': - failuremode = None # reject and do not continue + failuremode = None # reject and do not continue try: import ldap @@ -45,7 +45,7 @@ print ("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) return (failuremode, '') - ## do AD search (if required) ## + # do AD search (if required) vars = {'username': username, 'password': password} if 'search-fields' in options: try: @@ -67,7 +67,7 @@ print ("AD Search attributes: %s" % attrs) if hasattr(attrs, 'has_key'): for attr in attributes: - if attrs.has_key(attr): + if attr in attrs: vars[attr] = str(attrs[attr][0]) else: vars[attr] = "" diff -r 56d21c8237dbd121825ec79c6f0b476e1374ac7e -r a47c91afe31716b7a4dd527fc32804fab305989b lib/galaxy/auth/providers/localdb.py --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -17,7 +17,7 @@ """ See abstract method documentation. """ - return (False, '') # it can never auto-create based of localdb (chicken-egg) + return (False, '') # it can never auto-create based of localdb (chicken-egg) def authenticateUser(self, user, password, options, debug=False): """ https://bitbucket.org/galaxy/galaxy-central/commits/e3aa33dfb08e/ Changeset: e3aa33dfb08e User: jmchilton Date: 2015-03-02 01:18:40+00:00 Summary: Finish replacing YAPSY with galaxy.util.plugin_config. Affected #: 1 file diff -r a47c91afe31716b7a4dd527fc32804fab305989b -r e3aa33dfb08e8a287a69f695e862ec89c646d04d lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -4,7 +4,6 @@ import traceback import xml.etree.ElementTree -from yapsy.PluginManager import PluginManager from galaxy.security.validate_user_input import validate_publicname @@ -13,6 +12,9 @@ string_as_bool_or_none, ) +from galaxy.util import plugin_config + + import logging log = logging.getLogger(__name__) @@ -132,15 +134,13 @@ filters. """ try: - # load the yapsy plugins - manager = PluginManager() - manager.setPluginPlaces(["lib/galaxy/auth/providers"]) - manager.collectPlugins() + import galaxy.auth.providers + plugins_dict = plugin_config.plugins_dict( galaxy.auth.providers, 'plugin_type' ) if debug: log.debug( ("Plugins found:") ) - for plugin in manager.getAllPlugins(): - log.debug( ("- %s" % (plugin.path)) ) + for plugin in plugins_dict: + log.debug( ("- %s" % (plugin)) ) # parse XML ct = xml.etree.ElementTree.parse(configfile) @@ -167,7 +167,7 @@ options[opt.tag] = opt.text # get the instance - plugin = manager.getPluginByName(typeelem.text) + plugin = plugins_dict.get(typeelem.text) yield (plugin.plugin_object, options) # excepts if type is spelled incorrectly except GeneratorExit: return https://bitbucket.org/galaxy/galaxy-central/commits/9562cb4c7b7d/ Changeset: 9562cb4c7b7d User: jmchilton Date: 2015-03-02 01:56:53+00:00 Summary: Rearrange auth to use a Galaxy manager object pattern. On the positive-side this feels much more like a traditional Galaxy style access pattern and each operation is likely much more efficient since the plugins aren't be reloaded and XML re-parsed for each action. The downside is a Galaxy restart is required to update the authentication providers for Galaxy - while this is less than ideal in some ways - it is what Galaxy admins would expect for the other configuration files anyway so it is arguably better to not be more clever here. Affected #: 7 files diff -r e3aa33dfb08e8a287a69f695e862ec89c646d04d -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 lib/galaxy/app.py --- a/lib/galaxy/app.py +++ b/lib/galaxy/app.py @@ -120,6 +120,8 @@ else: self.openid_providers = OpenIDProviders() # Start the heartbeat process if configured and available + from galaxy import auth + self.auth_manager = auth.AuthManager( self ) if self.config.use_heartbeat: from galaxy.util import heartbeat if heartbeat.Heartbeat: diff -r e3aa33dfb08e8a287a69f695e862ec89c646d04d -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -2,6 +2,7 @@ Contains implementations of the authentication logic. """ +from collections import namedtuple import traceback import xml.etree.ElementTree @@ -39,125 +40,33 @@ # </auth> -def check_registration_allowed(email, password, configfile, debug=False): - """Checks if the provided email is allowed to register.""" - message = '' - status = 'done' - for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): - allowreg = _getTriState(options, 'allow-register', True) - if allowreg is None: # i.e. challenge - authresult, msg = provider.authenticate(email, password, options, debug) - if authresult is True: - break - if authresult is None: - message = 'Invalid email address or password' - status = 'error' - break - elif allowreg is True: - break - elif allowreg is False: - message = 'Account registration not required for your account. Please simply login.' - status = 'error' - break - return message, status +class AuthManager(object): + def __init__(self, app): + self.__app = app + import galaxy.auth.providers + self.__plugins_dict = plugin_config.plugins_dict( galaxy.auth.providers, 'plugin_type' ) + auth_config_file = app.config.auth_config_file + self.__init_authenticators(auth_config_file) + self.debug = getattr(app.config, 'auth_debug', False) -def check_auto_registration(trans, email, password, configfile, debug=False): - """ - Checks the email/password using auth providers in order. If a match is - found, returns the 'auto-register' option for that provider. - """ - for provider, options in activeAuthProviderGenerator(email, password, configfile, debug): - if provider is None: - if debug: - log.debug( "Unable to find module: %s" % options ) - else: - authresult, autousername = provider.authenticate(email, password, options, debug) - autousername = str(autousername).lower() - if authresult is True: - # make username unique - if validate_publicname( trans, autousername ) != '': - i = 1 - while i <= 10: # stop after 10 tries - if validate_publicname( trans, "%s-%i" % (autousername, i) ) == '': - autousername = "%s-%i" % (autousername, i) - break - i += 1 - else: - break # end for loop if we can't make a unique username - if debug: - log.debug( "Email: %s, auto-register with username: %s" % (email, autousername) ) - return (_getBool(options, 'auto-register', False), autousername) - elif authresult is None: - log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) - break # end authentication (skip rest) - return (False, '') - - -def check_password(user, password, configfile, debug=False): - """Checks the email/password using auth providers.""" - for provider, options in activeAuthProviderGenerator(user.email, password, configfile, debug): - if provider is None: - if debug: - log.debug( "Unable to find module: %s" % options ) - else: - authresult = provider.authenticateUser(user, password, options, debug) - if authresult is True: - return True # accept user - elif authresult is None: - break # end authentication (skip rest) - return False - - -def check_change_password(user, current_password, configfile, debug=False): - """Checks that auth provider allows password changes and current_password - matches. - """ - for provider, options in activeAuthProviderGenerator(user.email, current_password, configfile, debug): - if provider is None: - if debug: - log.debug( "Unable to find module: %s" % options ) - else: - if _getBool(options, "allow-password-change", False): - authresult = provider.authenticateUser(user, current_password, options, debug) - if authresult is True: - return (True, '') # accept user - elif authresult is None: - break # end authentication (skip rest) - else: - return (False, 'Password change not supported') - return (False, 'Invalid current password') - - -def activeAuthProviderGenerator(username, password, configfile, debug): - """Yields AuthProvider instances for the provided configfile that match the - filters. - """ - try: - import galaxy.auth.providers - plugins_dict = plugin_config.plugins_dict( galaxy.auth.providers, 'plugin_type' ) - - if debug: - log.debug( ("Plugins found:") ) - for plugin in plugins_dict: - log.debug( ("- %s" % (plugin)) ) - + def __init_authenticators(self, auth_config_file): # parse XML - ct = xml.etree.ElementTree.parse(configfile) + ct = xml.etree.ElementTree.parse(auth_config_file) confroot = ct.getroot() + authenticators = [] # process authenticators for authelem in confroot.getchildren(): typeelem = authelem.iter('type').next() + plugin = self.__plugins_dict.get(typeelem.text) # check filterelem - filterelem = _getChildElement(authelem, 'filter') - if filterelem is not None: - filterstr = str(filterelem.text).format(username=username, password=password) - if debug: - log.debug( ("Filter: %s == %s" % (filterstr, eval(filterstr, {"__builtins__": None}, {'str': str}))) ) - if not eval(filterstr, {"__builtins__": None}, {'str': str}): - continue # skip to next + filter_elem = _getChildElement(authelem, 'filter') + if filter_elem is not None: + filter_template = str(filter_elem.text) + else: + filter_template = None # extract options optionselem = _getChildElement(authelem, 'options') @@ -165,15 +74,118 @@ if optionselem is not None: for opt in optionselem: options[opt.tag] = opt.text + authenticator = Authenticator( + plugin=plugin, + filter_template=filter_template, + options=options, + ) + authenticators.append(authenticator) + self.authenticators = authenticators - # get the instance - plugin = plugins_dict.get(typeelem.text) - yield (plugin.plugin_object, options) # excepts if type is spelled incorrectly - except GeneratorExit: - return - except: - if debug: - log.debug( ('Auth: Exception:\n%s' % (traceback.format_exc(),)) ) + def check_registration_allowed(self, email, password): + """Checks if the provided email is allowed to register.""" + message = '' + status = 'done' + for provider, options in self.activeAuthProviderGenerator(email, password): + allowreg = _getTriState(options, 'allow-register', True) + if allowreg is None: # i.e. challenge + authresult, msg = provider.authenticate(email, password, options) + if authresult is True: + break + if authresult is None: + message = 'Invalid email address or password' + status = 'error' + break + elif allowreg is True: + break + elif allowreg is False: + message = 'Account registration not required for your account. Please simply login.' + status = 'error' + break + return message, status + + def check_auto_registration(self, trans, email, password, debug=False): + """ + Checks the email/password using auth providers in order. If a match is + found, returns the 'auto-register' option for that provider. + """ + for provider, options in self.activeAuthProviderGenerator(email, password, debug): + if provider is None: + if debug: + log.debug( "Unable to find module: %s" % options ) + else: + authresult, autousername = provider.authenticate(email, password, options, debug) + autousername = str(autousername).lower() + if authresult is True: + # make username unique + if validate_publicname( trans, autousername ) != '': + i = 1 + while i <= 10: # stop after 10 tries + if validate_publicname( trans, "%s-%i" % (autousername, i) ) == '': + autousername = "%s-%i" % (autousername, i) + break + i += 1 + else: + break # end for loop if we can't make a unique username + if debug: + log.debug( "Email: %s, auto-register with username: %s" % (email, autousername) ) + return (_getBool(options, 'auto-register', False), autousername) + elif authresult is None: + log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) + break # end authentication (skip rest) + return (False, '') + + def check_password(self, user, password): + """Checks the email/password using auth providers.""" + for provider, options in self.activeAuthProviderGenerator(user.email, password): + if provider is None: + if self.debug: + log.debug( "Unable to find module: %s" % options ) + else: + authresult = provider.authenticateUser(user, password, options) + if authresult is True: + return True # accept user + elif authresult is None: + break # end authentication (skip rest) + return False + + def check_change_password(self, user, current_password): + """Checks that auth provider allows password changes and current_password + matches. + """ + for provider, options in self.activeAuthProviderGenerator(user.email, current_password): + if provider is None: + if self.debug: + log.debug( "Unable to find module: %s" % options ) + else: + if _getBool(options, "allow-password-change", False): + authresult = provider.authenticateUser(user, current_password, options) + if authresult is True: + return (True, '') # accept user + elif authresult is None: + break # end authentication (skip rest) + else: + return (False, 'Password change not supported') + return (False, 'Invalid current password') + + def activeAuthProviderGenerator(self, username, password): + """Yields AuthProvider instances for the provided configfile that match the + filters. + """ + try: + for authenticator in self.authenticators: + filter_template = authenticator.filter_template + if filter_template: + filter_str = filter_template.format(username=username, password=password) + if not eval(filter_str, {"__builtins__": None}, {'str': str}): + continue # skip to next + yield authenticator.plugin, authenticator.options + except Exception: + if self.debug: + log.debug( ('Auth: Exception:\n%s' % (traceback.format_exc(),)) ) + raise + +Authenticator = namedtuple('Authenticator', ['plugin', 'filter_template', 'options']) def _getBool(d, k, o): diff -r e3aa33dfb08e8a287a69f695e862ec89c646d04d -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 lib/galaxy/webapps/galaxy/api/authenticate.py --- a/lib/galaxy/webapps/galaxy/api/authenticate.py +++ b/lib/galaxy/webapps/galaxy/api/authenticate.py @@ -18,7 +18,6 @@ from galaxy.managers import api_keys from galaxy import exceptions from galaxy.web.base.controller import BaseAPIController -import galaxy.auth import logging log = logging.getLogger( __name__ ) @@ -53,7 +52,7 @@ raise exceptions.InconsistentDatabase( 'An error occured, please contact your administrator.' ) else: user = user[0] - is_valid_user = galaxy.auth.check_password(user, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) + is_valid_user = self.auth_manager.check_password(user, password) if is_valid_user: key = self.api_keys_manager.get_or_create_api_key( user ) return dict( api_key=key ) diff -r e3aa33dfb08e8a287a69f695e862ec89c646d04d -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 lib/galaxy/webapps/galaxy/controllers/mobile.py --- a/lib/galaxy/webapps/galaxy/controllers/mobile.py +++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py @@ -1,7 +1,6 @@ from galaxy import web from galaxy.web.base.controller import * -import galaxy.auth class Mobile( BaseUIController ): diff -r e3aa33dfb08e8a287a69f695e862ec89c646d04d -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -28,7 +28,7 @@ UsesFormDefinitionsMixin) from galaxy.web.form_builder import build_select_field, CheckboxField from galaxy.web.framework.helpers import escape, grids, time_ago -import galaxy.auth + log = logging.getLogger( __name__ ) @@ -518,7 +518,7 @@ print ("trans.app.config.auth_config_file: %s" % trans.app.config.auth_config_file) print ("trans.app.config.auth_debug: %s WARNING: don't use in production" % trans.app.config.auth_debug) if not user: - autoreg = galaxy.auth.check_auto_registration(trans, email, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) + autoreg = trans.app.auth_manager.check_auto_registration(trans, email, password) if autoreg[0]: kwd['username'] = autoreg[1] params = util.Params( kwd ) @@ -545,7 +545,7 @@ message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." if trans.app.config.error_email_to is not None: message += ' Contact: %s' % trans.app.config.error_email_to - elif not galaxy.auth.check_password(user, password, trans.app.config.auth_config_file, trans.app.config.auth_debug): + elif not trans.app.auth_manager.check_password(user, password): message = "Invalid password" elif trans.app.config.user_activation_on and not user.active: # activation is ON and the user is INACTIVE if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON @@ -674,7 +674,7 @@ status = 'error' else: # check user is allowed to register - message, status = galaxy.auth.check_registration_allowed(email, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) + message, status = trans.app.auth_manager.check_registration_allowed(email, password) if message == '': if not refresh_frames: if trans.webapp.name == 'galaxy': @@ -1125,7 +1125,7 @@ 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 - (ok, message) = galaxy.auth.check_change_password(trans.user, current, trans.app.config.auth_config_file, trans.app.config.auth_debug) + (ok, message) = trans.app.auth_manager.check_change_password(trans.user, current ) if ok: user = trans.user else: diff -r e3aa33dfb08e8a287a69f695e862ec89c646d04d -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 lib/galaxy/webapps/tool_shed/app.py --- a/lib/galaxy/webapps/tool_shed/app.py +++ b/lib/galaxy/webapps/tool_shed/app.py @@ -53,6 +53,8 @@ # because the Tool Shed should always have an empty dictionary! self.tool_data_tables = galaxy.tools.data.ToolDataTableManager( self.config.tool_data_path ) self.genome_builds = GenomeBuilds( self ) + from galaxy import auth + self.auth_manager = auth.AuthManager( self ) # Citation manager needed to load tools. from galaxy.managers.citations import CitationsManager self.citations_manager = CitationsManager( self ) diff -r e3aa33dfb08e8a287a69f695e862ec89c646d04d -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 lib/galaxy/webapps/tool_shed/config.py --- a/lib/galaxy/webapps/tool_shed/config.py +++ b/lib/galaxy/webapps/tool_shed/config.py @@ -132,6 +132,7 @@ if global_conf and "__file__" in global_conf: global_conf_parser.read(global_conf['__file__']) self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) ) + self.auth_debug = string_as_bool( kwargs.get( 'auth_debug', False ) ) self.citation_cache_type = kwargs.get( "citation_cache_type", "file" ) self.citation_cache_data_dir = resolve_path( kwargs.get( "citation_cache_data_dir", "database/tool_shed_citations/data" ), self.root ) self.citation_cache_lock_dir = resolve_path( kwargs.get( "citation_cache_lock_dir", "database/tool_shed_citations/locks" ), self.root ) @@ -155,6 +156,7 @@ def __parse_config_file_options( self, kwargs ): defaults = dict( + auth_config_file=[ 'config/auth_conf.xml', 'config/auth_conf.xml.sample' ], datatypes_config_file = [ 'config/datatypes_conf.xml', 'datatypes_conf.xml', 'config/datatypes_conf.xml.sample' ], shed_tool_data_table_config = [ 'shed_tool_data_table_conf.xml', 'config/shed_tool_data_table_conf.xml' ], ) https://bitbucket.org/galaxy/galaxy-central/commits/1c373ec50827/ Changeset: 1c373ec50827 User: jmchilton Date: 2015-03-02 02:38:39+00:00 Summary: Default auth provider should allow password change. Affected #: 1 file diff -r 9562cb4c7b7dc4e75465c9bf26b8c322cc2b8342 -r 1c373ec50827490069fbff58020bcaf784261959 config/auth_conf.xml.sample --- a/config/auth_conf.xml.sample +++ b/config/auth_conf.xml.sample @@ -1,6 +1,9 @@ <?xml version="1.0"?><auth> - <authenticator> - <type>localdb</type> - </authenticator> + <authenticator> + <type>localdb</type> + <options> + <allow-password-change>true</allow-password-change> + </options> + </authenticator></auth> https://bitbucket.org/galaxy/galaxy-central/commits/03e964afd157/ Changeset: 03e964afd157 User: jmchilton Date: 2015-03-02 02:39:23+00:00 Summary: Auth fixes for switch from YAPSY to plugin_config. Affected #: 4 files diff -r 1c373ec50827490069fbff58020bcaf784261959 -r 03e964afd1578a1df236e70cbe55659967458028 lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -59,7 +59,7 @@ # process authenticators for authelem in confroot.getchildren(): typeelem = authelem.iter('type').next() - plugin = self.__plugins_dict.get(typeelem.text) + plugin = self.__plugins_dict.get(typeelem.text)() # check filterelem filter_elem = _getChildElement(authelem, 'filter') @@ -177,7 +177,8 @@ filter_template = authenticator.filter_template if filter_template: filter_str = filter_template.format(username=username, password=password) - if not eval(filter_str, {"__builtins__": None}, {'str': str}): + passed_filter = eval(filter_str, {"__builtins__": None}, {'str': str}) + if not passed_filter: continue # skip to next yield authenticator.plugin, authenticator.options except Exception: diff -r 1c373ec50827490069fbff58020bcaf784261959 -r 03e964afd1578a1df236e70cbe55659967458028 lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -22,9 +22,7 @@ those fields first. After that it will bind to the AD with the username (formatted as specified). """ - @property - def plugin_type(self): - return 'activedirectory' + plugin_type = 'activedirectory' def authenticate(self, username, password, options, debug=False): """ diff -r 1c373ec50827490069fbff58020bcaf784261959 -r 03e964afd1578a1df236e70cbe55659967458028 lib/galaxy/auth/providers/alwaysreject.py --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -11,9 +11,7 @@ """A simple authenticator that just accepts users (does not care about their password). """ - @property - def plugin_type(self): - return 'alwaysreject' + plugin_type = 'alwaysreject' def authenticate(self, username, password, options, debug=False): """ diff -r 1c373ec50827490069fbff58020bcaf784261959 -r 03e964afd1578a1df236e70cbe55659967458028 lib/galaxy/auth/providers/localdb.py --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -5,13 +5,13 @@ """ from ..providers import AuthProvider +import logging +log = logging.getLogger(__name__) class LocalDB(AuthProvider): """Authenticate users against the local Galaxy database (as per usual).""" - @property - def plugin_type(self): - return 'localdb' + plugin_type = 'localdb' def authenticate(self, username, password, options, debug=False): """ https://bitbucket.org/galaxy/galaxy-central/commits/77ad730cd686/ Changeset: 77ad730cd686 User: jmchilton Date: 2015-03-02 03:09:34+00:00 Summary: Replace print statements with log statements in auth providers. This is more galactic. Affected #: 3 files diff -r 03e964afd1578a1df236e70cbe55659967458028 -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -7,6 +7,9 @@ import traceback from ..providers import AuthProvider +import logging +log = logging.getLogger(__name__) + def _getsubs(d, k, vars, default=''): if k in d: @@ -29,8 +32,8 @@ See abstract method documentation. """ if debug: - print ("Username: %s" % username) - print ("Options: %s" % options) + log.debug("Username: %s" % username) + log.debug("Options: %s" % options) failuremode = False # reject but continue if options.get('continue-on-failure', 'False') == 'False': @@ -40,7 +43,7 @@ import ldap except: if debug: - print ("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) + log.debug("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) return (failuremode, '') # do AD search (if required) @@ -62,7 +65,7 @@ _, suser = l.result(result, 60) _, attrs = suser[0] if debug: - print ("AD Search attributes: %s" % attrs) + log.debug(("AD Search attributes: %s" % attrs)) if hasattr(attrs, 'has_key'): for attr in attributes: if attr in attrs: @@ -71,7 +74,7 @@ vars[attr] = "" except Exception: if debug: - print('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) + log.debug('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) return (failuremode, '') # end search @@ -84,11 +87,11 @@ l.simple_bind_s(_getsubs(options, 'bind-user', vars), _getsubs(options, 'bind-password', vars)) except Exception: if debug: - print('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) + log.debug('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) return (failuremode, '') if debug: - print "User: %s, ACTIVEDIRECTORY: True" % (username) + log.debug("User: %s, ACTIVEDIRECTORY: True" % (username)) return (True, _getsubs(options, 'auto-register-username', vars)) def authenticateUser(self, user, password, options, debug=False): diff -r 03e964afd1578a1df236e70cbe55659967458028 -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 lib/galaxy/auth/providers/alwaysreject.py --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -6,6 +6,9 @@ from ..providers import AuthProvider +import logging +log = logging.getLogger(__name__) + class AlwaysReject(AuthProvider): """A simple authenticator that just accepts users (does not care about their @@ -24,7 +27,7 @@ See abstract method documentation. """ if debug: - print ("User: %s, ALWAYSREJECT: None" % (user.email)) + log.debug("User: %s, ALWAYSREJECT: None" % (user.email)) return None diff -r 03e964afd1578a1df236e70cbe55659967458028 -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 lib/galaxy/auth/providers/localdb.py --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -25,7 +25,7 @@ """ user_ok = user.check_password(password) if debug: - print ("User: %s, LOCALDB: %s" % (user.email, user_ok)) + log.debug("User: %s, LOCALDB: %s" % (user.email, user_ok)) return user_ok https://bitbucket.org/galaxy/galaxy-central/commits/bf6d42e86784/ Changeset: bf6d42e86784 User: jmchilton Date: 2015-03-02 03:12:38+00:00 Summary: PEP-8 method names in galaxy.auth and submodules. Affected #: 5 files diff -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 -r bf6d42e8678467f7f369bc22d5ddb4abe7a915c7 lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -62,14 +62,14 @@ plugin = self.__plugins_dict.get(typeelem.text)() # check filterelem - filter_elem = _getChildElement(authelem, 'filter') + filter_elem = _get_child_element(authelem, 'filter') if filter_elem is not None: filter_template = str(filter_elem.text) else: filter_template = None # extract options - optionselem = _getChildElement(authelem, 'options') + optionselem = _get_child_element(authelem, 'options') options = {} if optionselem is not None: for opt in optionselem: @@ -86,8 +86,8 @@ """Checks if the provided email is allowed to register.""" message = '' status = 'done' - for provider, options in self.activeAuthProviderGenerator(email, password): - allowreg = _getTriState(options, 'allow-register', True) + for provider, options in self.active_authenticators(email, password): + allowreg = _get_tri_state(options, 'allow-register', True) if allowreg is None: # i.e. challenge authresult, msg = provider.authenticate(email, password, options) if authresult is True: @@ -109,7 +109,7 @@ Checks the email/password using auth providers in order. If a match is found, returns the 'auto-register' option for that provider. """ - for provider, options in self.activeAuthProviderGenerator(email, password, debug): + for provider, options in self.active_authenticators(email, password, debug): if provider is None: if debug: log.debug( "Unable to find module: %s" % options ) @@ -129,7 +129,7 @@ break # end for loop if we can't make a unique username if debug: log.debug( "Email: %s, auto-register with username: %s" % (email, autousername) ) - return (_getBool(options, 'auto-register', False), autousername) + return (_get_bool(options, 'auto-register', False), autousername) elif authresult is None: log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) break # end authentication (skip rest) @@ -137,12 +137,12 @@ def check_password(self, user, password): """Checks the email/password using auth providers.""" - for provider, options in self.activeAuthProviderGenerator(user.email, password): + for provider, options in self.active_authenticators(user.email, password): if provider is None: if self.debug: log.debug( "Unable to find module: %s" % options ) else: - authresult = provider.authenticateUser(user, password, options) + authresult = provider.authenticate_user(user, password, options) if authresult is True: return True # accept user elif authresult is None: @@ -153,13 +153,13 @@ """Checks that auth provider allows password changes and current_password matches. """ - for provider, options in self.activeAuthProviderGenerator(user.email, current_password): + for provider, options in self.active_authenticators(user.email, current_password): if provider is None: if self.debug: log.debug( "Unable to find module: %s" % options ) else: - if _getBool(options, "allow-password-change", False): - authresult = provider.authenticateUser(user, current_password, options) + if _get_bool(options, "allow-password-change", False): + authresult = provider.authenticate_user(user, current_password, options) if authresult is True: return (True, '') # accept user elif authresult is None: @@ -168,7 +168,7 @@ return (False, 'Password change not supported') return (False, 'Invalid current password') - def activeAuthProviderGenerator(self, username, password): + def active_authenticators(self, username, password): """Yields AuthProvider instances for the provided configfile that match the filters. """ @@ -189,21 +189,21 @@ Authenticator = namedtuple('Authenticator', ['plugin', 'filter_template', 'options']) -def _getBool(d, k, o): +def _get_bool(d, k, o): if k in d: return string_as_bool(d[k]) else: return o -def _getTriState(d, k, o): +def _get_tri_state(d, k, o): if k in d: return string_as_bool_or_none(d[k]) else: return o -def _getChildElement(parent, childname): +def _get_child_element(parent, childname): try: return parent.iter(childname).next() except StopIteration: diff -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 -r bf6d42e8678467f7f369bc22d5ddb4abe7a915c7 lib/galaxy/auth/providers/__init__.py --- a/lib/galaxy/auth/providers/__init__.py +++ b/lib/galaxy/auth/providers/__init__.py @@ -38,7 +38,7 @@ """ @abc.abstractmethod - def authenticateUser(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options, debug=False): """ Same as authenticate() method, except an User object is provided instead of a username. diff -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 -r bf6d42e8678467f7f369bc22d5ddb4abe7a915c7 lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -11,7 +11,7 @@ log = logging.getLogger(__name__) -def _getsubs(d, k, vars, default=''): +def _get_subs(d, k, vars, default=''): if k in d: return str(d[k]).format(**vars) return str(default).format(**vars) @@ -52,14 +52,14 @@ try: # setup connection ldap.set_option(ldap.OPT_REFERRALS, 0) - l = ldap.initialize(_getsubs(options, 'server', vars)) + l = ldap.initialize(_get_subs(options, 'server', vars)) l.protocol_version = 3 - l.simple_bind_s(_getsubs(options, 'search-user', vars), _getsubs(options, 'search-password', vars)) + l.simple_bind_s(_get_subs(options, 'search-user', vars), _get_subs(options, 'search-password', vars)) scope = ldap.SCOPE_SUBTREE # setup search attributes = map(lambda s: s.strip().format(**vars), options['search-fields'].split(',')) - result = l.search(_getsubs(options, 'search-base', vars), scope, _getsubs(options, 'search-filter', vars), attributes) + result = l.search(_get_subs(options, 'search-base', vars), scope, _get_subs(options, 'search-filter', vars), attributes) # parse results _, suser = l.result(result, 60) @@ -82,9 +82,9 @@ try: # setup connection ldap.set_option(ldap.OPT_REFERRALS, 0) - l = ldap.initialize(_getsubs(options, 'server', vars)) + l = ldap.initialize(_get_subs(options, 'server', vars)) l.protocol_version = 3 - l.simple_bind_s(_getsubs(options, 'bind-user', vars), _getsubs(options, 'bind-password', vars)) + l.simple_bind_s(_get_subs(options, 'bind-user', vars), _get_subs(options, 'bind-password', vars)) except Exception: if debug: log.debug('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) @@ -92,9 +92,9 @@ if debug: log.debug("User: %s, ACTIVEDIRECTORY: True" % (username)) - return (True, _getsubs(options, 'auto-register-username', vars)) + return (True, _get_subs(options, 'auto-register-username', vars)) - def authenticateUser(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options, debug=False): """ See abstract method documentation. """ diff -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 -r bf6d42e8678467f7f369bc22d5ddb4abe7a915c7 lib/galaxy/auth/providers/alwaysreject.py --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -22,7 +22,7 @@ """ return (None, '') - def authenticateUser(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options, debug=False): """ See abstract method documentation. """ diff -r 77ad730cd6866e89cb8bcad865cacef66a15fd49 -r bf6d42e8678467f7f369bc22d5ddb4abe7a915c7 lib/galaxy/auth/providers/localdb.py --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -19,7 +19,7 @@ """ return (False, '') # it can never auto-create based of localdb (chicken-egg) - def authenticateUser(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options, debug=False): """ See abstract method documentation. """ https://bitbucket.org/galaxy/galaxy-central/commits/c70db1a9c9a9/ Changeset: c70db1a9c9a9 User: jmchilton Date: 2015-03-02 03:15:26+00:00 Summary: PEP-8 variable names in galaxy.auth and submodules. Affected #: 2 files diff -r bf6d42e8678467f7f369bc22d5ddb4abe7a915c7 -r c70db1a9c9a9ad6915d8e282e371d27cf9cb84e9 lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -53,26 +53,26 @@ def __init_authenticators(self, auth_config_file): # parse XML ct = xml.etree.ElementTree.parse(auth_config_file) - confroot = ct.getroot() + conf_root = ct.getroot() authenticators = [] # process authenticators - for authelem in confroot.getchildren(): - typeelem = authelem.iter('type').next() - plugin = self.__plugins_dict.get(typeelem.text)() + for auth_elem in conf_root.getchildren(): + type_elem = auth_elem.iter('type').next() + plugin = self.__plugins_dict.get(type_elem.text)() # check filterelem - filter_elem = _get_child_element(authelem, 'filter') + filter_elem = _get_child_element(auth_elem, 'filter') if filter_elem is not None: filter_template = str(filter_elem.text) else: filter_template = None # extract options - optionselem = _get_child_element(authelem, 'options') + options_elem = _get_child_element(auth_elem, 'options') options = {} - if optionselem is not None: - for opt in optionselem: + if options_elem is not None: + for opt in options_elem: options[opt.tag] = opt.text authenticator = Authenticator( plugin=plugin, @@ -87,18 +87,18 @@ message = '' status = 'done' for provider, options in self.active_authenticators(email, password): - allowreg = _get_tri_state(options, 'allow-register', True) - if allowreg is None: # i.e. challenge - authresult, msg = provider.authenticate(email, password, options) - if authresult is True: + allow_reg = _get_tri_state(options, 'allow-register', True) + if allow_reg is None: # i.e. challenge + auth_result, msg = provider.authenticate(email, password, options) + if auth_result is True: break - if authresult is None: + if auth_result is None: message = 'Invalid email address or password' status = 'error' break - elif allowreg is True: + elif allow_reg is True: break - elif allowreg is False: + elif allow_reg is False: message = 'Account registration not required for your account. Please simply login.' status = 'error' break @@ -114,23 +114,23 @@ if debug: log.debug( "Unable to find module: %s" % options ) else: - authresult, autousername = provider.authenticate(email, password, options, debug) - autousername = str(autousername).lower() - if authresult is True: + auth_result, auto_username = provider.authenticate(email, password, options, debug) + auto_username = str(auto_username).lower() + if auth_result is True: # make username unique - if validate_publicname( trans, autousername ) != '': + if validate_publicname( trans, auto_username ) != '': i = 1 while i <= 10: # stop after 10 tries - if validate_publicname( trans, "%s-%i" % (autousername, i) ) == '': - autousername = "%s-%i" % (autousername, i) + if validate_publicname( trans, "%s-%i" % (auto_username, i) ) == '': + auto_username = "%s-%i" % (auto_username, i) break i += 1 else: break # end for loop if we can't make a unique username if debug: - log.debug( "Email: %s, auto-register with username: %s" % (email, autousername) ) - return (_get_bool(options, 'auto-register', False), autousername) - elif authresult is None: + log.debug( "Email: %s, auto-register with username: %s" % (email, auto_username) ) + return (_get_bool(options, 'auto-register', False), auto_username) + elif auth_result is None: log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) break # end authentication (skip rest) return (False, '') @@ -142,10 +142,10 @@ if self.debug: log.debug( "Unable to find module: %s" % options ) else: - authresult = provider.authenticate_user(user, password, options) - if authresult is True: + auth_result = provider.authenticate_user(user, password, options) + if auth_result is True: return True # accept user - elif authresult is None: + elif auth_result is None: break # end authentication (skip rest) return False @@ -159,10 +159,10 @@ log.debug( "Unable to find module: %s" % options ) else: if _get_bool(options, "allow-password-change", False): - authresult = provider.authenticate_user(user, current_password, options) - if authresult is True: + auth_result = provider.authenticate_user(user, current_password, options) + if auth_result is True: return (True, '') # accept user - elif authresult is None: + elif auth_result is None: break # end authentication (skip rest) else: return (False, 'Password change not supported') diff -r bf6d42e8678467f7f369bc22d5ddb4abe7a915c7 -r c70db1a9c9a9ad6915d8e282e371d27cf9cb84e9 lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -35,16 +35,16 @@ log.debug("Username: %s" % username) log.debug("Options: %s" % options) - failuremode = False # reject but continue + failure_mode = False # reject but continue if options.get('continue-on-failure', 'False') == 'False': - failuremode = None # reject and do not continue + failure_mode = None # reject and do not continue try: import ldap except: if debug: log.debug("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) - return (failuremode, '') + return (failure_mode, '') # do AD search (if required) vars = {'username': username, 'password': password} @@ -75,7 +75,7 @@ except Exception: if debug: log.debug('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) - return (failuremode, '') + return (failure_mode, '') # end search # bind as user to check their credentials @@ -88,7 +88,7 @@ except Exception: if debug: log.debug('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) - return (failuremode, '') + return (failure_mode, '') if debug: log.debug("User: %s, ACTIVEDIRECTORY: True" % (username)) https://bitbucket.org/galaxy/galaxy-central/commits/3a144d3b729d/ Changeset: 3a144d3b729d User: dannon Date: 2015-03-02 15:12:21+00:00 Summary: Fix customauth to be python2.6 compatible. Affected #: 1 file diff -r c70db1a9c9a9ad6915d8e282e371d27cf9cb84e9 -r 3a144d3b729d27f35905bdf278e536d48ffc3c0b lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -58,7 +58,7 @@ authenticators = [] # process authenticators for auth_elem in conf_root.getchildren(): - type_elem = auth_elem.iter('type').next() + type_elem = auth_elem.find('type') plugin = self.__plugins_dict.get(type_elem.text)() # check filterelem @@ -204,7 +204,4 @@ def _get_child_element(parent, childname): - try: - return parent.iter(childname).next() - except StopIteration: - return None + return parent.find(childname) https://bitbucket.org/galaxy/galaxy-central/commits/729c25276e7d/ Changeset: 729c25276e7d User: dannon Date: 2015-03-02 15:15:27+00:00 Summary: Remove unnecessary complexity of _get_child_element Affected #: 1 file diff -r 3a144d3b729d27f35905bdf278e536d48ffc3c0b -r 729c25276e7da9c28eff9d678c819bfb40a13d2c lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -62,14 +62,14 @@ plugin = self.__plugins_dict.get(type_elem.text)() # check filterelem - filter_elem = _get_child_element(auth_elem, 'filter') + filter_elem = auth_elem.find('filter') if filter_elem is not None: filter_template = str(filter_elem.text) else: filter_template = None # extract options - options_elem = _get_child_element(auth_elem, 'options') + options_elem = auth_elem.find('options') options = {} if options_elem is not None: for opt in options_elem: @@ -201,7 +201,3 @@ return string_as_bool_or_none(d[k]) else: return o - - -def _get_child_element(parent, childname): - return parent.find(childname) https://bitbucket.org/galaxy/galaxy-central/commits/0a878e33a786/ Changeset: 0a878e33a786 User: carlfeberhard Date: 2015-03-02 16:20:37+00:00 Summary: Fix to sessionStorage Model to surpress QUOTA DOMExceptions when Safari users are in private browsing mode Affected #: 3 files diff -r 729c25276e7da9c28eff9d678c819bfb40a13d2c -r 0a878e33a78666e7c36dd447a017307cb113a462 client/galaxy/scripts/mvc/base-mvc.js --- a/client/galaxy/scripts/mvc/base-mvc.js +++ b/client/galaxy/scripts/mvc/base-mvc.js @@ -94,7 +94,7 @@ if( !options.silent ){ model.trigger( 'request', model, {}, options ); } - var returned; + var returned = {}; switch( method ){ case 'create' : returned = this._create( model ); break; case 'read' : returned = this._read( model ); break; @@ -111,9 +111,19 @@ /** set storage to the stringified item */ _create : function( model ){ - var json = model.toJSON(), - set = sessionStorage.setItem( model.id, JSON.stringify( json ) ); - return ( set === null )?( set ):( json ); + try { + var json = model.toJSON(), + set = sessionStorage.setItem( model.id, JSON.stringify( json ) ); + return ( set === null )?( set ):( json ); + // DOMException is thrown in Safari if in private browsing mode and sessionStorage is attempted: + // http://stackoverflow.com/questions/14555347 + // TODO: this could probably use a more general soln - like detecting priv. mode + safari => non-ajaxing Model + } catch( err ){ + if( !( ( err instanceof DOMException ) && ( navigator.userAgent.indexOf("Safari") > -1 ) ) ){ + throw err; + } + } + return null; }, /** read and parse json from storage */ diff -r 729c25276e7da9c28eff9d678c819bfb40a13d2c -r 0a878e33a78666e7c36dd447a017307cb113a462 static/scripts/mvc/base-mvc.js --- a/static/scripts/mvc/base-mvc.js +++ b/static/scripts/mvc/base-mvc.js @@ -94,7 +94,7 @@ if( !options.silent ){ model.trigger( 'request', model, {}, options ); } - var returned; + var returned = {}; switch( method ){ case 'create' : returned = this._create( model ); break; case 'read' : returned = this._read( model ); break; @@ -111,9 +111,19 @@ /** set storage to the stringified item */ _create : function( model ){ - var json = model.toJSON(), - set = sessionStorage.setItem( model.id, JSON.stringify( json ) ); - return ( set === null )?( set ):( json ); + try { + var json = model.toJSON(), + set = sessionStorage.setItem( model.id, JSON.stringify( json ) ); + return ( set === null )?( set ):( json ); + // DOMException is thrown in Safari if in private browsing mode and sessionStorage is attempted: + // http://stackoverflow.com/questions/14555347 + // TODO: this could probably use a more general soln - like detecting priv. mode + safari => non-ajaxing Model + } catch( err ){ + if( !( ( err instanceof DOMException ) && ( navigator.userAgent.indexOf("Safari") > -1 ) ) ){ + throw err; + } + } + return null; }, /** read and parse json from storage */ diff -r 729c25276e7da9c28eff9d678c819bfb40a13d2c -r 0a878e33a78666e7c36dd447a017307cb113a462 static/scripts/packed/mvc/base-mvc.js --- a/static/scripts/packed/mvc/base-mvc.js +++ b/static/scripts/packed/mvc/base-mvc.js @@ -1,1 +1,1 @@ -define(["utils/add-logging","utils/localization"],function(h,b){var i={logger:null,_logNamespace:"?",log:function(){if(this.logger){var k=this.logger.log;if(typeof this.logger.log==="object"){k=Function.prototype.bind.call(this.logger.log,this.logger)}return k.apply(this.logger,arguments)}return undefined}};h(i);var a=Backbone.Model.extend({initialize:function(l){this._checkEnabledSessionStorage();if(!l.id){throw new Error("SessionStorageModel requires an id in the initial attributes")}this.id=l.id;var k=(!this.isNew())?(this._read(this)):({});this.clear({silent:true});this.save(_.extend({},this.defaults,k,l),{silent:true});this.on("change",function(){this.save()})},_checkEnabledSessionStorage:function(){try{return sessionStorage.length}catch(k){alert("Please enable cookies in your browser for this Galaxy site");return false}},sync:function(n,l,k){if(!k.silent){l.trigger("request",l,{},k)}var m;switch(n){case"create":m=this._create(l);break;case"read":m=this._read(l);break;case"update":m=this._update(l);break;case"delete":m=this._delete(l);break}if(m!==undefined||m!==null){if(k.success){k.success()}}else{if(k.error){k.error()}}return m},_create:function(k){var l=k.toJSON(),m=sessionStorage.setItem(k.id,JSON.stringify(l));return(m===null)?(m):(l)},_read:function(k){return JSON.parse(sessionStorage.getItem(k.id))},_update:function(k){return k._create(k)},_delete:function(k){return sessionStorage.removeItem(k.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)},_log:function(){return JSON.stringify(this.toJSON(),null," ")},toString:function(){return"SessionStorageModel("+this.id+")"}});(function(){a.prototype=_.omit(a.prototype,"url","urlRoot")}());function j(n,m){var k=Array.prototype.slice.call(arguments,0),l=k.pop();k.unshift(l);return _.defaults.apply(_,k)}var g={searchAttributes:[],searchAliases:{},searchAttribute:function(m,k){var l=this.get(m);if(!k||(l===undefined||l===null)){return false}if(_.isArray(l)){return this._searchArrayAttribute(l,k)}return(l.toString().toLowerCase().indexOf(k.toLowerCase())!==-1)},_searchArrayAttribute:function(l,k){k=k.toLowerCase();return _.any(l,function(m){return(m.toString().toLowerCase().indexOf(k.toLowerCase())!==-1)})},search:function(k){var l=this;return _.filter(this.searchAttributes,function(m){return l.searchAttribute(m,k)})},matches:function(l){var n="=",k=l.split(n);if(k.length>=2){var m=k[0];m=this.searchAliases[m]||m;return this.searchAttribute(m,k[1])}return !!this.search(l).length},matchesAll:function(l){var k=this;l=l.match(/(".*"|\w*=".*"|\S*)/g).filter(function(m){return !!m});return _.all(l,function(m){m=m.replace(/"/g,"");return k.matches(m)})}};var c={hiddenUntilActivated:function(k,m){m=m||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,m||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");this.hidden=this.isHidden();if(k){var l=this;k.on("click",function(n){l.toggle(l.HUAVOptions.showSpeed)})}},isHidden:function(){return(this.HUAVOptions.$elementShown.is(":hidden"))},toggle:function(){if(this.hidden){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this);this.trigger("hiddenUntilActivated:shown",this)}this.hidden=false}else{if(_.isFunction(this.HUAVOptions.onhide)){this.HUAVOptions.onhide.call(this);this.trigger("hiddenUntilActivated:hidden",this)}this.hidden=true}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};var f={initialize:function(k){this.draggable=k.draggable||false},$dragHandle:function(){return this.$(".title-bar")},toggleDraggable:function(){if(this.draggable){this.draggableOff()}else{this.draggableOn()}},draggableOn:function(){this.draggable=true;this.dragStartHandler=_.bind(this._dragStartHandler,this);this.dragEndHandler=_.bind(this._dragEndHandler,this);var k=this.$dragHandle().attr("draggable",true).get(0);k.addEventListener("dragstart",this.dragStartHandler,false);k.addEventListener("dragend",this.dragEndHandler,false)},draggableOff:function(){this.draggable=false;var k=this.$dragHandle().attr("draggable",false).get(0);k.removeEventListener("dragstart",this.dragStartHandler,false);k.removeEventListener("dragend",this.dragEndHandler,false)},_dragStartHandler:function(k){k.dataTransfer.effectAllowed="move";k.dataTransfer.setData("text",JSON.stringify(this.model.toJSON()));this.trigger("draggable:dragstart",k,this);return false},_dragEndHandler:function(k){this.trigger("draggable:dragend",k,this);return false}};var d={initialize:function(k){this.selectable=k.selectable||false;this.selected=k.selected||false},$selector:function(){return this.$(".selector")},_renderSelected:function(){this.$selector().find("span").toggleClass("fa-check-square-o",this.selected).toggleClass("fa-square-o",!this.selected)},toggleSelector:function(){if(!this.$selector().is(":visible")){this.showSelector()}else{this.hideSelector()}},showSelector:function(k){k=k!==undefined?k:this.fxSpeed;this.selectable=true;this.trigger("selectable",true,this);this._renderSelected();this.$selector().show(k)},hideSelector:function(k){k=k!==undefined?k:this.fxSpeed;this.selectable=false;this.trigger("selectable",false,this);this.$selector().hide(k)},toggleSelect:function(k){if(this.selected){this.deselect(k)}else{this.select(k)}},select:function(k){if(!this.selected){this.trigger("selected",this,k);this.selected=true;this._renderSelected()}return false},deselect:function(k){if(this.selected){this.trigger("de-selected",this,k);this.selected=false;this._renderSelected()}return false}};function e(l,k){k=k||"model";var m=_.template(l.join(""));return function(o,n){var p={view:n||{},_l:b};p[k]=o||{};return m(p)}}return{LoggableMixin:i,SessionStorageModel:a,mixin:j,SearchableModelMixin:g,HiddenUntilActivatedViewMixin:c,DraggableViewMixin:f,SelectableViewMixin:d,wrapTemplate:e}}); \ No newline at end of file +define(["utils/add-logging","utils/localization"],function(h,b){var i={logger:null,_logNamespace:"?",log:function(){if(this.logger){var k=this.logger.log;if(typeof this.logger.log==="object"){k=Function.prototype.bind.call(this.logger.log,this.logger)}return k.apply(this.logger,arguments)}return undefined}};h(i);var a=Backbone.Model.extend({initialize:function(l){this._checkEnabledSessionStorage();if(!l.id){throw new Error("SessionStorageModel requires an id in the initial attributes")}this.id=l.id;var k=(!this.isNew())?(this._read(this)):({});this.clear({silent:true});this.save(_.extend({},this.defaults,k,l),{silent:true});this.on("change",function(){this.save()})},_checkEnabledSessionStorage:function(){try{return sessionStorage.length}catch(k){alert("Please enable cookies in your browser for this Galaxy site");return false}},sync:function(n,l,k){if(!k.silent){l.trigger("request",l,{},k)}var m={};switch(n){case"create":m=this._create(l);break;case"read":m=this._read(l);break;case"update":m=this._update(l);break;case"delete":m=this._delete(l);break}if(m!==undefined||m!==null){if(k.success){k.success()}}else{if(k.error){k.error()}}return m},_create:function(k){try{var l=k.toJSON(),n=sessionStorage.setItem(k.id,JSON.stringify(l));return(n===null)?(n):(l)}catch(m){if(!((m instanceof DOMException)&&(navigator.userAgent.indexOf("Safari")>-1))){throw m}}return null},_read:function(k){return JSON.parse(sessionStorage.getItem(k.id))},_update:function(k){return k._create(k)},_delete:function(k){return sessionStorage.removeItem(k.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)},_log:function(){return JSON.stringify(this.toJSON(),null," ")},toString:function(){return"SessionStorageModel("+this.id+")"}});(function(){a.prototype=_.omit(a.prototype,"url","urlRoot")}());function j(n,m){var k=Array.prototype.slice.call(arguments,0),l=k.pop();k.unshift(l);return _.defaults.apply(_,k)}var g={searchAttributes:[],searchAliases:{},searchAttribute:function(m,k){var l=this.get(m);if(!k||(l===undefined||l===null)){return false}if(_.isArray(l)){return this._searchArrayAttribute(l,k)}return(l.toString().toLowerCase().indexOf(k.toLowerCase())!==-1)},_searchArrayAttribute:function(l,k){k=k.toLowerCase();return _.any(l,function(m){return(m.toString().toLowerCase().indexOf(k.toLowerCase())!==-1)})},search:function(k){var l=this;return _.filter(this.searchAttributes,function(m){return l.searchAttribute(m,k)})},matches:function(l){var n="=",k=l.split(n);if(k.length>=2){var m=k[0];m=this.searchAliases[m]||m;return this.searchAttribute(m,k[1])}return !!this.search(l).length},matchesAll:function(l){var k=this;l=l.match(/(".*"|\w*=".*"|\S*)/g).filter(function(m){return !!m});return _.all(l,function(m){m=m.replace(/"/g,"");return k.matches(m)})}};var c={hiddenUntilActivated:function(k,m){m=m||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,m||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");this.hidden=this.isHidden();if(k){var l=this;k.on("click",function(n){l.toggle(l.HUAVOptions.showSpeed)})}},isHidden:function(){return(this.HUAVOptions.$elementShown.is(":hidden"))},toggle:function(){if(this.hidden){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this);this.trigger("hiddenUntilActivated:shown",this)}this.hidden=false}else{if(_.isFunction(this.HUAVOptions.onhide)){this.HUAVOptions.onhide.call(this);this.trigger("hiddenUntilActivated:hidden",this)}this.hidden=true}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};var f={initialize:function(k){this.draggable=k.draggable||false},$dragHandle:function(){return this.$(".title-bar")},toggleDraggable:function(){if(this.draggable){this.draggableOff()}else{this.draggableOn()}},draggableOn:function(){this.draggable=true;this.dragStartHandler=_.bind(this._dragStartHandler,this);this.dragEndHandler=_.bind(this._dragEndHandler,this);var k=this.$dragHandle().attr("draggable",true).get(0);k.addEventListener("dragstart",this.dragStartHandler,false);k.addEventListener("dragend",this.dragEndHandler,false)},draggableOff:function(){this.draggable=false;var k=this.$dragHandle().attr("draggable",false).get(0);k.removeEventListener("dragstart",this.dragStartHandler,false);k.removeEventListener("dragend",this.dragEndHandler,false)},_dragStartHandler:function(k){k.dataTransfer.effectAllowed="move";k.dataTransfer.setData("text",JSON.stringify(this.model.toJSON()));this.trigger("draggable:dragstart",k,this);return false},_dragEndHandler:function(k){this.trigger("draggable:dragend",k,this);return false}};var d={initialize:function(k){this.selectable=k.selectable||false;this.selected=k.selected||false},$selector:function(){return this.$(".selector")},_renderSelected:function(){this.$selector().find("span").toggleClass("fa-check-square-o",this.selected).toggleClass("fa-square-o",!this.selected)},toggleSelector:function(){if(!this.$selector().is(":visible")){this.showSelector()}else{this.hideSelector()}},showSelector:function(k){k=k!==undefined?k:this.fxSpeed;this.selectable=true;this.trigger("selectable",true,this);this._renderSelected();this.$selector().show(k)},hideSelector:function(k){k=k!==undefined?k:this.fxSpeed;this.selectable=false;this.trigger("selectable",false,this);this.$selector().hide(k)},toggleSelect:function(k){if(this.selected){this.deselect(k)}else{this.select(k)}},select:function(k){if(!this.selected){this.trigger("selected",this,k);this.selected=true;this._renderSelected()}return false},deselect:function(k){if(this.selected){this.trigger("de-selected",this,k);this.selected=false;this._renderSelected()}return false}};function e(l,k){k=k||"model";var m=_.template(l.join(""));return function(o,n){var p={view:n||{},_l:b};p[k]=o||{};return m(p)}}return{LoggableMixin:i,SessionStorageModel:a,mixin:j,SearchableModelMixin:g,HiddenUntilActivatedViewMixin:c,DraggableViewMixin:f,SelectableViewMixin:d,wrapTemplate:e}}); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/8612b5dfa37e/ Changeset: 8612b5dfa37e User: dan Date: 2015-03-02 16:34:55+00:00 Summary: Add a 10 second timeout to loading data URLs for Tool Data Tables. Affected #: 1 file diff -r 0a878e33a78666e7c36dd447a017307cb113a462 -r 8612b5dfa37e72b2cf093a0a517e6f1110b8372a lib/galaxy/tools/data/__init__.py --- a/lib/galaxy/tools/data/__init__.py +++ b/lib/galaxy/tools/data/__init__.py @@ -263,7 +263,7 @@ self.data = [] self.configure_and_load( config_element, tool_data_path, from_shed_config) - def configure_and_load( self, config_element, tool_data_path, from_shed_config=False): + def configure_and_load( self, config_element, tool_data_path, from_shed_config=False, url_timeout=10 ): """ Configure and load table from an XML element. """ @@ -289,7 +289,7 @@ if filename: tmp_file = NamedTemporaryFile( prefix='TTDT_URL_%s-' % self.name ) try: - tmp_file.write( urlopen( filename ).read() ) + tmp_file.write( urlopen( filename, timeout=url_timeout ).read() ) except Exception, e: log.error( 'Error loading Data Table URL "%s": %s', filename, e ) continue https://bitbucket.org/galaxy/galaxy-central/commits/4d2345e34c27/ Changeset: 4d2345e34c27 User: dannon Date: 2015-03-02 17:29:54+00:00 Summary: Fix for auth when user doesn't exist. Affected #: 1 file diff -r 8612b5dfa37e72b2cf093a0a517e6f1110b8372a -r 4d2345e34c27fa86812fb5b892bed1cf51e12ef6 lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -109,7 +109,7 @@ Checks the email/password using auth providers in order. If a match is found, returns the 'auto-register' option for that provider. """ - for provider, options in self.active_authenticators(email, password, debug): + for provider, options in self.active_authenticators(email, password): if provider is None: if debug: log.debug( "Unable to find module: %s" % options ) https://bitbucket.org/galaxy/galaxy-central/commits/e34af1e6e532/ Changeset: e34af1e6e532 User: jmchilton Date: 2015-03-02 18:45:12+00:00 Summary: Update basic.py to allow collection reduction with new tool form. Affected #: 1 file diff -r 4d2345e34c27fa86812fb5b892bed1cf51e12ef6 -r e34af1e6e532099d7b3a6f67f8c22502c7d2a189 lib/galaxy/tools/parameters/basic.py --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -1992,10 +1992,19 @@ value = [ int( value_part ) for value_part in value.split( "," ) ] if isinstance( value, list ): rval = [] + found_hdca = False for single_value in value: - if isinstance( single_value, dict ): - assert single_value['src'] == 'hda' - rval.append( trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.app.security.decode_id( single_value[ 'id' ] ) ) ) + if found_hdca: + raise ValueError("Only one collection may be supplied to parameter.") + if isinstance( single_value, dict ) and 'src' in single_value and 'id' in single_value: + if single_value['src'] == 'hda': + rval.append(trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.app.security.decode_id(single_value['id']) )) + elif single_value['src'] == 'hdca': + found_hdca = True + decoded_id = trans.app.security.decode_id( single_value[ 'id' ] ) + rval = trans.sa_session.query( trans.app.model.HistoryDatasetCollectionAssociation ).get( decoded_id ) + else: + raise ValueError("Unknown input source %s passed to job submission API." % single_value['src']) else: rval.append( trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( single_value ) ) elif isinstance( value, trans.app.model.HistoryDatasetAssociation ): https://bitbucket.org/galaxy/galaxy-central/commits/1e8f541217da/ Changeset: 1e8f541217da User: carlfeberhard Date: 2015-03-02 19:22:00+00:00 Summary: Fix to remove validation of genome builds since some data source tools will assign invalid genome builds and later validation makes these hdas un-updatable Affected #: 1 file diff -r e34af1e6e532099d7b3a6f67f8c22502c7d2a189 -r 1e8f541217daf3ddf77a648c912129c7247cc96e lib/galaxy/managers/base.py --- a/lib/galaxy/managers/base.py +++ b/lib/galaxy/managers/base.py @@ -789,10 +789,13 @@ # TODO: is this correct? if val is None: return '?' - for genome_build_shortname, longname in self.app.genome_builds.get_genome_build_names( trans=trans ): - if val == genome_build_shortname: - return val - raise exceptions.RequestParameterInvalidException( "invalid reference", key=key, val=val ) + # currently, data source sites like UCSC are able to set the genome build to non-local build names + # afterwards, attempting to validate the whole model will choke here + # for genome_build_shortname, longname in self.app.genome_builds.get_genome_build_names( trans=trans ): + # if val == genome_build_shortname: + # return val + # raise exceptions.RequestParameterInvalidException( "invalid reference", key=key, val=val ) + return val # def slug( self, trans, item, key, val ): # """validate slug""" https://bitbucket.org/galaxy/galaxy-central/commits/2a92468416e8/ Changeset: 2a92468416e8 User: dannon Date: 2015-03-02 19:54:29+00:00 Summary: Rearranging the layers of middleware to allow sentry and debug to coexist without exploding (but you probably don't want to use both at once anyway) Affected #: 1 file diff -r 1e8f541217daf3ddf77a648c912129c7247cc96e -r 2a92468416e81c70a15ecb3d3491fbbfa2679b64 lib/galaxy/webapps/tool_shed/buildapp.py --- a/lib/galaxy/webapps/tool_shed/buildapp.py +++ b/lib/galaxy/webapps/tool_shed/buildapp.py @@ -176,14 +176,6 @@ from paste import recursive app = recursive.RecursiveMiddleware( app, conf ) log.debug( "Enabling 'recursive' middleware" ) - # If sentry logging is enabled, log here before propogating up to - # the error middleware - # TODO sentry config is duplicated between tool_shed/galaxy, refactor this. - sentry_dsn = conf.get( 'sentry_dsn', None ) - if sentry_dsn: - from galaxy.web.framework.middleware.sentry import Sentry - log.debug( "Enabling 'sentry' middleware" ) - app = Sentry( app, sentry_dsn ) # Various debug middleware that can only be turned on if the debug # flag is set, either because they are insecure or greatly hurt # performance @@ -223,6 +215,14 @@ from paste.translogger import TransLogger app = TransLogger( app ) log.debug( "Enabling 'trans logger' middleware" ) + # If sentry logging is enabled, log here before propogating up to + # the error middleware + # TODO sentry config is duplicated between tool_shed/galaxy, refactor this. + sentry_dsn = conf.get( 'sentry_dsn', None ) + if sentry_dsn: + from galaxy.web.framework.middleware.sentry import Sentry + log.debug( "Enabling 'sentry' middleware" ) + app = Sentry( app, sentry_dsn ) # X-Forwarded-Host handling from galaxy.web.framework.middleware.xforwardedhost import XForwardedHostMiddleware app = XForwardedHostMiddleware( app ) https://bitbucket.org/galaxy/galaxy-central/commits/e9dcf9066aaa/ Changeset: e9dcf9066aaa User: natefoo Date: 2015-03-02 19:56:01+00:00 Summary: Make the UCSC Browser to pull new builds from (in the cron script) a command line argument. Default is UCSC Main, but for Galaxy Test and Main we use UCSC Test. Affected #: 1 file diff -r 2a92468416e81c70a15ecb3d3491fbbfa2679b64 -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 cron/parse_builds.py --- a/cron/parse_builds.py +++ b/cron/parse_builds.py @@ -2,7 +2,7 @@ """ Connects to the URL specified and outputs builds available at that -DSN in tabular format. USCS Test gateway is used as default. +DSN in tabular format. UCSC Main gateway is used as default. build description """ @@ -10,7 +10,10 @@ import urllib import xml.etree.ElementTree as ElementTree -URL = "http://genome.cse.ucsc.edu/cgi-bin/das/dsn" +try: + URL = sys.argv[1] +except IndexError: + URL = "http://genome.cse.ucsc.edu/cgi-bin/das/dsn" def getbuilds(url): try: @@ -28,7 +31,7 @@ print "?\tunspecified (?)" sys.exit(1) - print "#Harvested from http://genome.cse.ucsc.edu/cgi-bin/das/dsn" + print "#Harvested from " + URL print "?\tunspecified (?)" for dsn in tree: build = dsn.find("SOURCE").attrib['id'] https://bitbucket.org/galaxy/galaxy-central/commits/5cec4dd844b2/ Changeset: 5cec4dd844b2 User: martenson Date: 2015-03-02 21:33:43+00:00 Summary: tweak toolbox search to provide better (and more) results with the inclusion of toolhelp in index and with more versions of the same tools being massively installed the search results were inconsistent and inaccurate and incomplete. addresses https://trello.com/c/6Bvbduci/2486-toolbox-search-is-behaving-wrongly-differ... Affected #: 7 files diff -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 client/galaxy/scripts/galaxy.workflows.js --- a/client/galaxy/scripts/galaxy.workflows.js +++ b/client/galaxy/scripts/galaxy.workflows.js @@ -24,7 +24,7 @@ $(this).addClass("search_active"); // input.addClass(config.loadingClass); // Add '*' to facilitate partial matching. - var q = this.value + '*'; + var q = this.value; // Stop previous ajax-request if (this.timer) { clearTimeout(this.timer); diff -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 client/galaxy/scripts/mvc/tools.js --- a/client/galaxy/scripts/mvc/tools.js +++ b/client/galaxy/scripts/mvc/tools.js @@ -376,7 +376,7 @@ } // Do search via AJAX. - var q = query + '*'; + var q = query; // Stop previous ajax-request if (this.timer) { clearTimeout(this.timer); diff -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 lib/galaxy/tools/search/__init__.py --- a/lib/galaxy/tools/search/__init__.py +++ b/lib/galaxy/tools/search/__init__.py @@ -1,18 +1,27 @@ -from galaxy.eggs import require +""" +Module for building and searching the index of tools +installed within this Galaxy. +""" +from galaxy import eggs from galaxy.web.framework.helpers import to_unicode -require( "Whoosh" ) +eggs.require( "Whoosh" ) from whoosh.filedb.filestore import RamStorage from whoosh.fields import Schema, STORED, TEXT from whoosh.scoring import BM25F from whoosh.qparser import MultifieldParser -schema = Schema( id=STORED, title=TEXT, description=TEXT, help=TEXT ) - +schema = Schema( id=STORED, + title=TEXT, + description=TEXT, + section=TEXT, + help=TEXT ) +import logging +log = logging.getLogger( __name__ ) class ToolBoxSearch( object ): """ Support searching tools in a toolbox. This implementation uses - the "whoosh" search library. + the Whoosh search library. """ def __init__( self, toolbox, index_help=True ): @@ -26,13 +35,13 @@ self.storage = RamStorage() self.index = self.storage.create_index( schema ) writer = self.index.writer() - ## TODO: would also be nice to search section headers. for id, tool in self.toolbox.tools(): add_doc_kwds = { "id": id, - "title": to_unicode(tool.name), - "description": to_unicode(tool.description), - "help": to_unicode(""), + "title": to_unicode( tool.name ), + "description": to_unicode( tool.description ), + "section": to_unicode( tool.get_panel_section()[1] if len( tool.get_panel_section() ) == 2 else '' ), + "help": to_unicode( "" ), } if index_help and tool.help: try: @@ -45,13 +54,18 @@ writer.commit() def search( self, query, return_attribute='id' ): - # Change field boosts for searcher to place more weight on title, description than help. + # Change field boosts for searcher searcher = self.index.searcher( weighting=BM25F( - field_B={ 'title_B': 3, 'description_B': 2, 'help_B': 1 } + field_B={ 'title_B': 9, + 'section_B': 3, + 'description_B': 2, + 'help_B': 0.5 } ) ) - # Set query to search title, description, and help. - parser = MultifieldParser( [ 'title', 'description', 'help' ], schema=schema ) - results = searcher.search( parser.parse( query ) ) - return [ result[ return_attribute ] for result in results ] + # Set query to search title, description, section, and help. + parser = MultifieldParser( [ 'title', 'description', 'section', 'help' ], schema=schema ) + # Perform the search + hits = searcher.search( parser.parse( '*' + query + '*' ), limit=20 ) + + return [ hit[ return_attribute ] for hit in hits ] diff -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 static/scripts/galaxy.workflows.js --- a/static/scripts/galaxy.workflows.js +++ b/static/scripts/galaxy.workflows.js @@ -24,7 +24,7 @@ $(this).addClass("search_active"); // input.addClass(config.loadingClass); // Add '*' to facilitate partial matching. - var q = this.value + '*'; + var q = this.value; // Stop previous ajax-request if (this.timer) { clearTimeout(this.timer); diff -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 static/scripts/mvc/tools.js --- a/static/scripts/mvc/tools.js +++ b/static/scripts/mvc/tools.js @@ -376,7 +376,7 @@ } // Do search via AJAX. - var q = query + '*'; + var q = query; // Stop previous ajax-request if (this.timer) { clearTimeout(this.timer); diff -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 static/scripts/packed/galaxy.workflows.js --- a/static/scripts/packed/galaxy.workflows.js +++ b/static/scripts/packed/galaxy.workflows.js @@ -1,1 +1,1 @@ -$(function(){if(window.lt_ie_7){show_modal("Browser not supported","Sorry, the workflow editor is not supported for IE6 and below.");return}$("#tool-search-query").click(function(){$(this).focus();$(this).select()}).keyup(function(){$(this).css("font-style","normal");if(this.value.length<3){reset_tool_search(false)}else{if(this.value!=this.lastValue){$(this).addClass("search_active");var g=this.value+"*";if(this.timer){clearTimeout(this.timer)}$("#search-spinner").show();this.timer=setTimeout(function(){$.get(tool_search_url,{query:g},function(i){$("#search-no-results").hide();$(".toolSectionWrapper").hide();$(".toolSectionWrapper").find(".toolTitle").hide();if(i.length!=0){var h=$.map(i,function(k,j){return"link-"+k});$(h).each(function(j,k){$("[id='"+k+"']").parent().addClass("search_match");$("[id='"+k+"']").parent().show().parent().parent().show().parent().show()});$(".toolPanelLabel").each(function(){var l=$(this);var k=l.next();var j=true;while(k.length!==0&&k.hasClass("toolTitle")){if(k.is(":visible")){j=false;break}else{k=k.next()}}if(j){l.hide()}})}else{$("#search-no-results").show()}$("#search-spinner").hide()},"json")},200)}}this.lastValue=this.value});canvas_manager=new CanvasManager($("#canvas-viewport"),$("#overview"));reset();$.ajax({url:get_datatypes_url,dataType:"json",cache:false,success:function(g){populate_datatype_info(g);$.ajax({url:load_workflow_url,data:{id:workflow_id,_:"true"},dataType:"json",cache:false,success:function(h){reset();workflow.from_simple(h);workflow.has_changes=false;workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview();upgrade_message="";$.each(h.upgrade_messages,function(j,i){upgrade_message+=("<li>Step "+(parseInt(j,10)+1)+": "+workflow.nodes[j].name+"<ul>");$.each(i,function(k,l){upgrade_message+="<li>"+l+"</li>"});upgrade_message+="</ul></li>"});if(upgrade_message){show_modal("Workflow loaded with changes","Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>"+upgrade_message+"</ul>",{Continue:hide_modal})}else{hide_modal()}show_workflow_parameters()},beforeSubmit:function(h){show_message("Loading workflow","progress")}})}});$(document).ajaxStart(function(){active_ajax_call=true;$(document).bind("ajaxStop.global",function(){active_ajax_call=false})});$(document).ajaxError(function(i,g){var h=g.responseText||g.statusText||"Could not connect to server";show_modal("Server error",h,{"Ignore error":hide_modal});return false});make_popupmenu($("#workflow-options-button"),{Save:save_current_workflow,Run:function(){window.location=run_workflow_url},"Edit Attributes":c,"Auto Re-layout":f,Close:close_editor});function b(){workflow.clear_active_node();$(".right-content").hide();var j="";for(var h in workflow.nodes){var i=workflow.nodes[h];if(i.type=="tool"){j+="<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step "+i.id+" - "+i.name+"</div>";for(var k in i.output_terminals){var g=i.output_terminals[k];if($.inArray(g.name,i.workflow_outputs)!=-1){j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' checked /></p>"}else{j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' /></p>"}}j+="</div>"}}$("#output-fill-area").html(j);$("#output-fill-area input").bind("click",function(){var n=this.name.split("|")[0];var l=this.name.split("|")[1];if(this.checked){if($.inArray(l,workflow.nodes[n].workflow_outputs)==-1){workflow.nodes[n].workflow_outputs.push(l)}}else{while($.inArray(l,workflow.nodes[n].workflow_outputs)!=-1){var m=$.inArray(l,workflow.nodes[n].workflow_outputs);workflow.nodes[n].workflow_outputs=workflow.nodes[n].workflow_outputs.slice(0,m).concat(workflow.nodes[n].workflow_outputs.slice(m+1))}}workflow.has_changes=true});$("#workflow-output-area").show()}function f(){workflow.layout();workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview()}function c(){workflow.clear_active_node();$(".right-content").hide();$("#edit-attributes").show()}overview_size=$.jStorage.get("overview-size");if(overview_size!==undefined){$("#overview-border").css({width:overview_size,height:overview_size})}if($.jStorage.get("overview-off")){d()}else{e()}$("#overview-border").bind("dragend",function(h,j){var k=$(this).offsetParent();var i=k.offset();var g=Math.max(k.width()-(j.offsetX-i.left),k.height()-(j.offsetY-i.top));$.jStorage.set("overview-size",g+"px")});function e(){$.jStorage.set("overview-off",false);$("#overview-border").css("right","0px");$("#close-viewport").css("background-position","0px 0px")}function d(){$.jStorage.set("overview-off",true);$("#overview-border").css("right","20000px");$("#close-viewport").css("background-position","12px 0px")}$("#close-viewport").click(function(){if($("#overview-border").css("right")==="0px"){d()}else{e()}});window.onbeforeunload=function(){if(workflow&&workflow.has_changes){return"There are unsaved changes to your workflow which will be lost."}};$("div.toolSectionBody").hide();$("div.toolSectionTitle > span").wrap("<a href='#'></a>");var a=null;$("div.toolSectionTitle").each(function(){var g=$(this).next("div.toolSectionBody");$(this).click(function(){if(g.is(":hidden")){if(a){a.slideUp("fast")}a=g;g.slideDown("fast")}else{g.slideUp("fast");a=null}})});async_save_text("workflow-name","workflow-name",rename_async_url,"new_name");$("#workflow-tag").click(function(){$(".tag-area").click();return false});async_save_text("workflow-annotation","workflow-annotation",annotate_async_url,"new_annotation",25,true,4)});function reset(){if(workflow){workflow.remove_all()}workflow=new Workflow($("#canvas-container"))}function scroll_to_nodes(){var a=$("#canvas-viewport");var d=$("#canvas-container");var c,b;if(d.width()<a.width()){b=(a.width()-d.width())/2}else{b=0}if(d.height()<a.height()){c=(a.height()-d.height())/2}else{c=0}d.css({left:b,top:c})}function add_node_for_tool(b,a){node=add_node("tool",a,b);$.ajax({url:get_new_module_info_url,data:{type:"tool",tool_id:b,_:"true"},global:false,dataType:"json",success:function(c){node.init_field_data(c)},error:function(d,f){var c="error loading field data";if(d.status===0){c+=", server unavailable"}node.error(c)}})}function add_node_for_module(a,b){node=add_node(a,b);$.ajax({url:get_new_module_info_url,data:{type:a,_:"true"},dataType:"json",success:function(c){node.init_field_data(c)},error:function(d,f){var c="error loading field data";if(d.status==0){c+=", server unavailable"}node.error(c)}})}function display_pja(b,a){$("#pja_container").append(get_pja_form(b,a));$("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function(){action_to_rem=$(this).closest(".toolForm",".action_tag").children(".action_tag:first").text();$(this).closest(".toolForm").remove();delete workflow.active_node.post_job_actions[action_to_rem];workflow.active_form_has_changes=true})}function display_pja_list(){return pja_list}function display_file_list(b){addlist="<select id='node_data_list' name='node_data_list'>";for(var a in b.output_terminals){addlist+="<option value='"+a+"'>"+a+"</option>"}addlist+="</select>";return addlist}function new_pja(d,b,a){if(a.post_job_actions===undefined){a.post_job_actions={}}if(a.post_job_actions[d+b]===undefined){var c={};c.action_type=d;c.output_name=b;a.post_job_actions[d+b]=null;a.post_job_actions[d+b]=c;display_pja(c,a);workflow.active_form_has_changes=true;return true}else{return false}}function show_workflow_parameters(){var c=/\$\{.+?\}/g;var b=[];var f=$("#workflow-parameters-container");var e=$("#workflow-parameters-box");var a="";var d=[];$.each(workflow.nodes,function(g,h){var i=h.form_html.match(c);if(i){d=d.concat(i)}if(h.post_job_actions){$.each(h.post_job_actions,function(j,l){if(l.action_arguments){$.each(l.action_arguments,function(m,n){var o=n.match(c);if(o){d=d.concat(o)}})}});if(d){$.each(d,function(j,l){if($.inArray(l,b)===-1){b.push(l)}})}}});if(b&&b.length!==0){$.each(b,function(g,h){a+="<div>"+h.substring(2,h.length-1)+"</div>"});f.html(a);e.show()}else{f.html(a);e.hide()}}function show_form_for_tool(c,b){$(".right-content").hide();$("#right-content").show().html(c);if(b){$("#right-content").find(".toolForm:first").after("<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Attributes</div><div class='form-row'><label>Annotation / Notes:</label><div style='margin-right: 10px;'><textarea name='annotation' rows='3' style='width: 100%'>"+b.annotation+"</textarea><div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div></div></div></div>")}if(b&&b.type=="tool"){pjastr="<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> "+display_pja_list()+" <br/> "+display_file_list(b)+" <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div></div><div class='form-row'><div style='margin-right: 10px;'><span id='pja_container'></span>";pjastr+="<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";$("#right-content").find(".toolForm").after(pjastr);for(var a in b.post_job_actions){if(a!="undefined"){display_pja(b.post_job_actions[a],b)}}$("#add_pja").click(function(){new_pja($("#new_pja_list").val(),$("#node_data_list").val(),b)})}$("#right-content").find("form").ajaxForm({type:"POST",dataType:"json",success:function(d){workflow.active_form_has_changes=false;b.update_field_data(d);show_workflow_parameters()},beforeSubmit:function(d){d.push({name:"tool_state",value:b.tool_state});d.push({name:"_",value:"true"})}}).each(function(){var d=this;$(this).find("select[refresh_on_change='true']").change(function(){$(d).submit()});$(this).find("input[refresh_on_change='true']").change(function(){$(d).submit()});$(this).find(".popupmenu").each(function(){var g=$(this).parents("div.form-row").attr("id");var e=$('<a class="popup-arrow" id="popup-arrow-for-'+g+'">▼</a>');var f={};$(this).find("button").each(function(){var h=$(this).attr("name");var i=$(this).attr("value");f[$(this).text()]=function(){$(d).append("<input type='hidden' name='"+h+"' value='"+i+"' />").submit()}});e.insertAfter(this);$(this).remove();make_popupmenu(e,f)});$(this).find("input,textarea,select").each(function(){$(this).bind("focus click",function(){workflow.active_form_has_changes=true})})})}var close_editor=function(){workflow.check_changes_in_active_form();if(workflow&&workflow.has_changes){do_close=function(){window.onbeforeunload=undefined;window.document.location=workflow_index_url};show_modal("Close workflow editor","There are unsaved changes to your workflow which will be lost.",{Cancel:hide_modal,"Save Changes":function(){save_current_workflow(null,do_close)}},{"Don't Save":do_close})}else{window.document.location=workflow_index_url}};var save_current_workflow=function(b,c){show_message("Saving workflow","progress");workflow.check_changes_in_active_form();if(!workflow.has_changes){hide_modal();if(c){c()}return}workflow.rectify_workflow_outputs();var a=function(d){$.ajax({url:save_workflow_url,type:"POST",data:{id:workflow_id,workflow_data:function(){return JSON.stringify(workflow.to_simple())},_:"true"},dataType:"json",success:function(g){var e=$("<div></div>").text(g.message);if(g.errors){e.addClass("warningmark");var f=$("<ul/>");$.each(g.errors,function(j,h){$("<li></li>").text(h).appendTo(f)});e.append(f)}else{e.addClass("donemark")}workflow.name=g.name;workflow.has_changes=false;workflow.stored=true;show_workflow_parameters();if(g.errors){show_modal("Saving workflow",e,{Ok:hide_modal})}else{if(d){d()}hide_modal()}}})};if(active_ajax_call){$(document).bind("ajaxStop.save_workflow",function(){$(document).unbind("ajaxStop.save_workflow");a();$(document).unbind("ajaxStop.save_workflow");active_ajax_call=false})}else{a(c)}}; \ No newline at end of file +$(function(){if(window.lt_ie_7){show_modal("Browser not supported","Sorry, the workflow editor is not supported for IE6 and below.");return}$("#tool-search-query").click(function(){$(this).focus();$(this).select()}).keyup(function(){$(this).css("font-style","normal");if(this.value.length<3){reset_tool_search(false)}else{if(this.value!=this.lastValue){$(this).addClass("search_active");var g=this.value;if(this.timer){clearTimeout(this.timer)}$("#search-spinner").show();this.timer=setTimeout(function(){$.get(tool_search_url,{query:g},function(i){$("#search-no-results").hide();$(".toolSectionWrapper").hide();$(".toolSectionWrapper").find(".toolTitle").hide();if(i.length!=0){var h=$.map(i,function(k,j){return"link-"+k});$(h).each(function(j,k){$("[id='"+k+"']").parent().addClass("search_match");$("[id='"+k+"']").parent().show().parent().parent().show().parent().show()});$(".toolPanelLabel").each(function(){var l=$(this);var k=l.next();var j=true;while(k.length!==0&&k.hasClass("toolTitle")){if(k.is(":visible")){j=false;break}else{k=k.next()}}if(j){l.hide()}})}else{$("#search-no-results").show()}$("#search-spinner").hide()},"json")},200)}}this.lastValue=this.value});canvas_manager=new CanvasManager($("#canvas-viewport"),$("#overview"));reset();$.ajax({url:get_datatypes_url,dataType:"json",cache:false,success:function(g){populate_datatype_info(g);$.ajax({url:load_workflow_url,data:{id:workflow_id,_:"true"},dataType:"json",cache:false,success:function(h){reset();workflow.from_simple(h);workflow.has_changes=false;workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview();upgrade_message="";$.each(h.upgrade_messages,function(j,i){upgrade_message+=("<li>Step "+(parseInt(j,10)+1)+": "+workflow.nodes[j].name+"<ul>");$.each(i,function(k,l){upgrade_message+="<li>"+l+"</li>"});upgrade_message+="</ul></li>"});if(upgrade_message){show_modal("Workflow loaded with changes","Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>"+upgrade_message+"</ul>",{Continue:hide_modal})}else{hide_modal()}show_workflow_parameters()},beforeSubmit:function(h){show_message("Loading workflow","progress")}})}});$(document).ajaxStart(function(){active_ajax_call=true;$(document).bind("ajaxStop.global",function(){active_ajax_call=false})});$(document).ajaxError(function(i,g){var h=g.responseText||g.statusText||"Could not connect to server";show_modal("Server error",h,{"Ignore error":hide_modal});return false});make_popupmenu($("#workflow-options-button"),{Save:save_current_workflow,Run:function(){window.location=run_workflow_url},"Edit Attributes":c,"Auto Re-layout":f,Close:close_editor});function b(){workflow.clear_active_node();$(".right-content").hide();var j="";for(var h in workflow.nodes){var i=workflow.nodes[h];if(i.type=="tool"){j+="<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step "+i.id+" - "+i.name+"</div>";for(var k in i.output_terminals){var g=i.output_terminals[k];if($.inArray(g.name,i.workflow_outputs)!=-1){j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' checked /></p>"}else{j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' /></p>"}}j+="</div>"}}$("#output-fill-area").html(j);$("#output-fill-area input").bind("click",function(){var n=this.name.split("|")[0];var l=this.name.split("|")[1];if(this.checked){if($.inArray(l,workflow.nodes[n].workflow_outputs)==-1){workflow.nodes[n].workflow_outputs.push(l)}}else{while($.inArray(l,workflow.nodes[n].workflow_outputs)!=-1){var m=$.inArray(l,workflow.nodes[n].workflow_outputs);workflow.nodes[n].workflow_outputs=workflow.nodes[n].workflow_outputs.slice(0,m).concat(workflow.nodes[n].workflow_outputs.slice(m+1))}}workflow.has_changes=true});$("#workflow-output-area").show()}function f(){workflow.layout();workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview()}function c(){workflow.clear_active_node();$(".right-content").hide();$("#edit-attributes").show()}overview_size=$.jStorage.get("overview-size");if(overview_size!==undefined){$("#overview-border").css({width:overview_size,height:overview_size})}if($.jStorage.get("overview-off")){d()}else{e()}$("#overview-border").bind("dragend",function(h,j){var k=$(this).offsetParent();var i=k.offset();var g=Math.max(k.width()-(j.offsetX-i.left),k.height()-(j.offsetY-i.top));$.jStorage.set("overview-size",g+"px")});function e(){$.jStorage.set("overview-off",false);$("#overview-border").css("right","0px");$("#close-viewport").css("background-position","0px 0px")}function d(){$.jStorage.set("overview-off",true);$("#overview-border").css("right","20000px");$("#close-viewport").css("background-position","12px 0px")}$("#close-viewport").click(function(){if($("#overview-border").css("right")==="0px"){d()}else{e()}});window.onbeforeunload=function(){if(workflow&&workflow.has_changes){return"There are unsaved changes to your workflow which will be lost."}};$("div.toolSectionBody").hide();$("div.toolSectionTitle > span").wrap("<a href='#'></a>");var a=null;$("div.toolSectionTitle").each(function(){var g=$(this).next("div.toolSectionBody");$(this).click(function(){if(g.is(":hidden")){if(a){a.slideUp("fast")}a=g;g.slideDown("fast")}else{g.slideUp("fast");a=null}})});async_save_text("workflow-name","workflow-name",rename_async_url,"new_name");$("#workflow-tag").click(function(){$(".tag-area").click();return false});async_save_text("workflow-annotation","workflow-annotation",annotate_async_url,"new_annotation",25,true,4)});function reset(){if(workflow){workflow.remove_all()}workflow=new Workflow($("#canvas-container"))}function scroll_to_nodes(){var a=$("#canvas-viewport");var d=$("#canvas-container");var c,b;if(d.width()<a.width()){b=(a.width()-d.width())/2}else{b=0}if(d.height()<a.height()){c=(a.height()-d.height())/2}else{c=0}d.css({left:b,top:c})}function add_node_for_tool(b,a){node=add_node("tool",a,b);$.ajax({url:get_new_module_info_url,data:{type:"tool",tool_id:b,_:"true"},global:false,dataType:"json",success:function(c){node.init_field_data(c)},error:function(d,f){var c="error loading field data";if(d.status===0){c+=", server unavailable"}node.error(c)}})}function add_node_for_module(a,b){node=add_node(a,b);$.ajax({url:get_new_module_info_url,data:{type:a,_:"true"},dataType:"json",success:function(c){node.init_field_data(c)},error:function(d,f){var c="error loading field data";if(d.status==0){c+=", server unavailable"}node.error(c)}})}function display_pja(b,a){$("#pja_container").append(get_pja_form(b,a));$("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function(){action_to_rem=$(this).closest(".toolForm",".action_tag").children(".action_tag:first").text();$(this).closest(".toolForm").remove();delete workflow.active_node.post_job_actions[action_to_rem];workflow.active_form_has_changes=true})}function display_pja_list(){return pja_list}function display_file_list(b){addlist="<select id='node_data_list' name='node_data_list'>";for(var a in b.output_terminals){addlist+="<option value='"+a+"'>"+a+"</option>"}addlist+="</select>";return addlist}function new_pja(d,b,a){if(a.post_job_actions===undefined){a.post_job_actions={}}if(a.post_job_actions[d+b]===undefined){var c={};c.action_type=d;c.output_name=b;a.post_job_actions[d+b]=null;a.post_job_actions[d+b]=c;display_pja(c,a);workflow.active_form_has_changes=true;return true}else{return false}}function show_workflow_parameters(){var c=/\$\{.+?\}/g;var b=[];var f=$("#workflow-parameters-container");var e=$("#workflow-parameters-box");var a="";var d=[];$.each(workflow.nodes,function(g,h){var i=h.form_html.match(c);if(i){d=d.concat(i)}if(h.post_job_actions){$.each(h.post_job_actions,function(j,l){if(l.action_arguments){$.each(l.action_arguments,function(m,n){var o=n.match(c);if(o){d=d.concat(o)}})}});if(d){$.each(d,function(j,l){if($.inArray(l,b)===-1){b.push(l)}})}}});if(b&&b.length!==0){$.each(b,function(g,h){a+="<div>"+h.substring(2,h.length-1)+"</div>"});f.html(a);e.show()}else{f.html(a);e.hide()}}function show_form_for_tool(c,b){$(".right-content").hide();$("#right-content").show().html(c);if(b){$("#right-content").find(".toolForm:first").after("<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Attributes</div><div class='form-row'><label>Annotation / Notes:</label><div style='margin-right: 10px;'><textarea name='annotation' rows='3' style='width: 100%'>"+b.annotation+"</textarea><div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div></div></div></div>")}if(b&&b.type=="tool"){pjastr="<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> "+display_pja_list()+" <br/> "+display_file_list(b)+" <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div></div><div class='form-row'><div style='margin-right: 10px;'><span id='pja_container'></span>";pjastr+="<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";$("#right-content").find(".toolForm").after(pjastr);for(var a in b.post_job_actions){if(a!="undefined"){display_pja(b.post_job_actions[a],b)}}$("#add_pja").click(function(){new_pja($("#new_pja_list").val(),$("#node_data_list").val(),b)})}$("#right-content").find("form").ajaxForm({type:"POST",dataType:"json",success:function(d){workflow.active_form_has_changes=false;b.update_field_data(d);show_workflow_parameters()},beforeSubmit:function(d){d.push({name:"tool_state",value:b.tool_state});d.push({name:"_",value:"true"})}}).each(function(){var d=this;$(this).find("select[refresh_on_change='true']").change(function(){$(d).submit()});$(this).find("input[refresh_on_change='true']").change(function(){$(d).submit()});$(this).find(".popupmenu").each(function(){var g=$(this).parents("div.form-row").attr("id");var e=$('<a class="popup-arrow" id="popup-arrow-for-'+g+'">▼</a>');var f={};$(this).find("button").each(function(){var h=$(this).attr("name");var i=$(this).attr("value");f[$(this).text()]=function(){$(d).append("<input type='hidden' name='"+h+"' value='"+i+"' />").submit()}});e.insertAfter(this);$(this).remove();make_popupmenu(e,f)});$(this).find("input,textarea,select").each(function(){$(this).bind("focus click",function(){workflow.active_form_has_changes=true})})})}var close_editor=function(){workflow.check_changes_in_active_form();if(workflow&&workflow.has_changes){do_close=function(){window.onbeforeunload=undefined;window.document.location=workflow_index_url};show_modal("Close workflow editor","There are unsaved changes to your workflow which will be lost.",{Cancel:hide_modal,"Save Changes":function(){save_current_workflow(null,do_close)}},{"Don't Save":do_close})}else{window.document.location=workflow_index_url}};var save_current_workflow=function(b,c){show_message("Saving workflow","progress");workflow.check_changes_in_active_form();if(!workflow.has_changes){hide_modal();if(c){c()}return}workflow.rectify_workflow_outputs();var a=function(d){$.ajax({url:save_workflow_url,type:"POST",data:{id:workflow_id,workflow_data:function(){return JSON.stringify(workflow.to_simple())},_:"true"},dataType:"json",success:function(g){var e=$("<div></div>").text(g.message);if(g.errors){e.addClass("warningmark");var f=$("<ul/>");$.each(g.errors,function(j,h){$("<li></li>").text(h).appendTo(f)});e.append(f)}else{e.addClass("donemark")}workflow.name=g.name;workflow.has_changes=false;workflow.stored=true;show_workflow_parameters();if(g.errors){show_modal("Saving workflow",e,{Ok:hide_modal})}else{if(d){d()}hide_modal()}}})};if(active_ajax_call){$(document).bind("ajaxStop.save_workflow",function(){$(document).unbind("ajaxStop.save_workflow");a();$(document).unbind("ajaxStop.save_workflow");active_ajax_call=false})}else{a(c)}}; \ No newline at end of file diff -r e9dcf9066aaa7db5fcbf0ea5ec48d9428ff1f145 -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 static/scripts/packed/mvc/tools.js --- a/static/scripts/packed/mvc/tools.js +++ b/static/scripts/packed/mvc/tools.js @@ -1,1 +1,1 @@ -define(["libs/underscore","viz/trackster/util","mvc/data","libs/lunr"],function(y,a,z,s){var g={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},toggle:function(){this.set("hidden",!this.get("hidden"))},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.Model.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(A){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},set_value:function(A){this.set("value",A||"")}});var i=Backbone.Collection.extend({model:e});var k=e.extend({});var d=e.extend({set_value:function(A){this.set("value",parseInt(A,10))},get_samples:function(){return d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}});var f=d.extend({set_value:function(A){this.set("value",parseFloat(A))}});var u=e.extend({get_samples:function(){return y.map(this.get("options"),function(A){return A[0]})}});e.subModelTypes={integer:d,"float":f,data:k,select:u};var j=Backbone.Model.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[],outputs:[]},urlRoot:galaxy_config.root+"api/tools",initialize:function(A){this.set("inputs",new i(y.map(A.inputs,function(B){var C=e.subModelTypes[B.type]||e;return new C(B)})))},toJSON:function(){var A=Backbone.Model.prototype.toJSON.call(this);A.inputs=this.get("inputs").map(function(B){return B.toJSON()});return A},remove_inputs:function(B){var A=this,C=A.get("inputs").filter(function(D){return(B.indexOf(D.get("type"))!==-1)});A.get("inputs").remove(C)},copy:function(B){var C=new j(this.toJSON());if(B){var A=new Backbone.Collection();C.get("inputs").each(function(D){if(D.get_samples()){A.push(D)}});C.set("inputs",A)}return C},apply_search_results:function(A){(y.indexOf(A,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(A,B){this.get("inputs").find(function(C){return C.get("name")===A}).set("value",B)},set_input_values:function(B){var A=this;y.each(y.keys(B),function(C){A.set_input_value(C,B[C])})},run:function(){return this._run()},rerun:function(B,A){return this._run({action:"rerun",target_dataset_id:B.id,regions:A})},get_inputs_dict:function(){var A={};this.get("inputs").each(function(B){A[B.get("name")]=B.get("value")});return A},_run:function(C){var D=y.extend({tool_id:this.id,inputs:this.get_inputs_dict()},C);var B=$.Deferred(),A=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(D),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(E){return E!=="pending"}});$.when(A.go()).then(function(E){B.resolve(new z.DatasetCollection().reset(E))});return B}});y.extend(j.prototype,g);var q=Backbone.View.extend({});var n=Backbone.Collection.extend({model:j});var w=Backbone.Model.extend(g);var l=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){y.each(this.attributes.elems,function(A){A.show()});this.show();this.set("open",false)},apply_search_results:function(B){var C=true,A;y.each(this.attributes.elems,function(D){if(D instanceof w){A=D;A.hide()}else{if(D instanceof j){if(D.apply_search_results(B)){C=false;if(A){A.show()}}}}});if(C){this.hide()}else{this.show();this.set("open",true)}}});y.extend(l.prototype,g);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var C=this.attributes.query;if(C.length<this.attributes.min_chars_for_search){this.set("results",null);return}var B=C+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var A=this;this.timer=setTimeout(function(){$.get(A.attributes.search_url,{query:B},function(D){A.set("results",D);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});y.extend(c.prototype,g);var o=Backbone.Model.extend({initialize:function(A){this.attributes.tool_search=A.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=A.tools;this.attributes.layout=new Backbone.Collection(this.parse(A.layout))},parse:function(B){var A=this,C=function(F){var E=F.model_class;if(E.indexOf("Tool")===E.length-4){return A.attributes.tools.get(F.id)}else{if(E==="ToolSection"){var D=y.map(F.elems,C);F.elems=D;return new l(F)}else{if(E==="ToolSectionLabel"){return new w(F)}}}};return y.map(B,C)},clear_search_results:function(){this.get("layout").each(function(A){if(A instanceof l){A.clear_search_results()}else{A.show()}})},apply_search_results:function(){var B=this.get("tool_search").get("results");if(B===null){this.clear_search_results();return}var A=null;this.get("layout").each(function(C){if(C instanceof w){A=C;A.hide()}else{if(C instanceof j){if(C.apply_search_results(B)){if(A){A.show()}}}else{A=null;C.apply_search_results(B)}}})}});var t=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var m=t.extend({tagName:"div",render:function(){var A=$("<div/>");A.append(Handlebars.templates.tool_link(this.model.toJSON()));if(this.model.id==="upload1"){A.find("a").on("click",function(B){B.preventDefault();Galaxy.upload.show()})}this.$el.append(A);return this}});var b=t.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var r=t.extend({tagName:"div",className:"toolSectionWrapper",initialize:function(){t.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(Handlebars.templates.panel_section(this.model.toJSON()));var A=this.$el.find(".toolSectionBody");y.each(this.model.attributes.elems,function(B){if(B instanceof j){var C=new m({model:B,className:"toolTitle"});C.render();A.append(C.$el)}else{if(B instanceof w){var D=new b({model:B});D.render();A.append(D.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var p=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(Handlebars.templates.tool_search(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find("[title]").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(A){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===A.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var x=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var A=this;var B=new p({model:this.model.get("tool_search")});B.render();A.$el.append(B.$el);this.model.get("layout").each(function(D){if(D instanceof l){var C=new r({model:D});C.render();A.$el.append(C.$el)}else{if(D instanceof j){var E=new m({model:D,className:"toolTitleNoSection"});E.render();A.$el.append(E.$el)}else{if(D instanceof w){var F=new b({model:D});F.render();A.$el.append(F.$el)}}}});A.$el.find("a.tool-link").click(function(E){var D=$(this).attr("class").split(/\s+/)[0],C=A.model.get("tools").get(D);A.trigger("tool_link_click",E,C)});return this},handle_search_results:function(){var A=this.model.get("tool_search").get("results");if(A&&A.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var v=Backbone.View.extend({className:"toolForm",render:function(){this.$el.children().remove();this.$el.append(Handlebars.templates.tool_form(this.model.toJSON()))}});var h=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new x({collection:this.collection});this.tool_form_view=new v()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var A=this;this.tool_panel_view.on("tool_link_click",function(C,B){C.preventDefault();A.show_tool(B)})},show_tool:function(B){var A=this;B.fetch().done(function(){A.tool_form_view.model=B;A.tool_form_view.render();A.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,SelectToolParameter:u,Tool:j,ToolCollection:n,ToolSearch:c,ToolPanel:o,ToolPanelView:x,ToolFormView:v}}); \ No newline at end of file +define(["libs/underscore","viz/trackster/util","mvc/data","libs/lunr"],function(y,a,z,s){var g={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},toggle:function(){this.set("hidden",!this.get("hidden"))},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.Model.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(A){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},set_value:function(A){this.set("value",A||"")}});var i=Backbone.Collection.extend({model:e});var k=e.extend({});var d=e.extend({set_value:function(A){this.set("value",parseInt(A,10))},get_samples:function(){return d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}});var f=d.extend({set_value:function(A){this.set("value",parseFloat(A))}});var u=e.extend({get_samples:function(){return y.map(this.get("options"),function(A){return A[0]})}});e.subModelTypes={integer:d,"float":f,data:k,select:u};var j=Backbone.Model.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[],outputs:[]},urlRoot:galaxy_config.root+"api/tools",initialize:function(A){this.set("inputs",new i(y.map(A.inputs,function(B){var C=e.subModelTypes[B.type]||e;return new C(B)})))},toJSON:function(){var A=Backbone.Model.prototype.toJSON.call(this);A.inputs=this.get("inputs").map(function(B){return B.toJSON()});return A},remove_inputs:function(B){var A=this,C=A.get("inputs").filter(function(D){return(B.indexOf(D.get("type"))!==-1)});A.get("inputs").remove(C)},copy:function(B){var C=new j(this.toJSON());if(B){var A=new Backbone.Collection();C.get("inputs").each(function(D){if(D.get_samples()){A.push(D)}});C.set("inputs",A)}return C},apply_search_results:function(A){(y.indexOf(A,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(A,B){this.get("inputs").find(function(C){return C.get("name")===A}).set("value",B)},set_input_values:function(B){var A=this;y.each(y.keys(B),function(C){A.set_input_value(C,B[C])})},run:function(){return this._run()},rerun:function(B,A){return this._run({action:"rerun",target_dataset_id:B.id,regions:A})},get_inputs_dict:function(){var A={};this.get("inputs").each(function(B){A[B.get("name")]=B.get("value")});return A},_run:function(C){var D=y.extend({tool_id:this.id,inputs:this.get_inputs_dict()},C);var B=$.Deferred(),A=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(D),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(E){return E!=="pending"}});$.when(A.go()).then(function(E){B.resolve(new z.DatasetCollection().reset(E))});return B}});y.extend(j.prototype,g);var q=Backbone.View.extend({});var n=Backbone.Collection.extend({model:j});var w=Backbone.Model.extend(g);var l=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){y.each(this.attributes.elems,function(A){A.show()});this.show();this.set("open",false)},apply_search_results:function(B){var C=true,A;y.each(this.attributes.elems,function(D){if(D instanceof w){A=D;A.hide()}else{if(D instanceof j){if(D.apply_search_results(B)){C=false;if(A){A.show()}}}}});if(C){this.hide()}else{this.show();this.set("open",true)}}});y.extend(l.prototype,g);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var C=this.attributes.query;if(C.length<this.attributes.min_chars_for_search){this.set("results",null);return}var B=C;if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var A=this;this.timer=setTimeout(function(){$.get(A.attributes.search_url,{query:B},function(D){A.set("results",D);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});y.extend(c.prototype,g);var o=Backbone.Model.extend({initialize:function(A){this.attributes.tool_search=A.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=A.tools;this.attributes.layout=new Backbone.Collection(this.parse(A.layout))},parse:function(B){var A=this,C=function(F){var E=F.model_class;if(E.indexOf("Tool")===E.length-4){return A.attributes.tools.get(F.id)}else{if(E==="ToolSection"){var D=y.map(F.elems,C);F.elems=D;return new l(F)}else{if(E==="ToolSectionLabel"){return new w(F)}}}};return y.map(B,C)},clear_search_results:function(){this.get("layout").each(function(A){if(A instanceof l){A.clear_search_results()}else{A.show()}})},apply_search_results:function(){var B=this.get("tool_search").get("results");if(B===null){this.clear_search_results();return}var A=null;this.get("layout").each(function(C){if(C instanceof w){A=C;A.hide()}else{if(C instanceof j){if(C.apply_search_results(B)){if(A){A.show()}}}else{A=null;C.apply_search_results(B)}}})}});var t=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var m=t.extend({tagName:"div",render:function(){var A=$("<div/>");A.append(Handlebars.templates.tool_link(this.model.toJSON()));if(this.model.id==="upload1"){A.find("a").on("click",function(B){B.preventDefault();Galaxy.upload.show()})}this.$el.append(A);return this}});var b=t.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var r=t.extend({tagName:"div",className:"toolSectionWrapper",initialize:function(){t.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(Handlebars.templates.panel_section(this.model.toJSON()));var A=this.$el.find(".toolSectionBody");y.each(this.model.attributes.elems,function(B){if(B instanceof j){var C=new m({model:B,className:"toolTitle"});C.render();A.append(C.$el)}else{if(B instanceof w){var D=new b({model:B});D.render();A.append(D.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var p=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(Handlebars.templates.tool_search(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find("[title]").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(A){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===A.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var x=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var A=this;var B=new p({model:this.model.get("tool_search")});B.render();A.$el.append(B.$el);this.model.get("layout").each(function(D){if(D instanceof l){var C=new r({model:D});C.render();A.$el.append(C.$el)}else{if(D instanceof j){var E=new m({model:D,className:"toolTitleNoSection"});E.render();A.$el.append(E.$el)}else{if(D instanceof w){var F=new b({model:D});F.render();A.$el.append(F.$el)}}}});A.$el.find("a.tool-link").click(function(E){var D=$(this).attr("class").split(/\s+/)[0],C=A.model.get("tools").get(D);A.trigger("tool_link_click",E,C)});return this},handle_search_results:function(){var A=this.model.get("tool_search").get("results");if(A&&A.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var v=Backbone.View.extend({className:"toolForm",render:function(){this.$el.children().remove();this.$el.append(Handlebars.templates.tool_form(this.model.toJSON()))}});var h=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new x({collection:this.collection});this.tool_form_view=new v()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var A=this;this.tool_panel_view.on("tool_link_click",function(C,B){C.preventDefault();A.show_tool(B)})},show_tool:function(B){var A=this;B.fetch().done(function(){A.tool_form_view.model=B;A.tool_form_view.render();A.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,SelectToolParameter:u,Tool:j,ToolCollection:n,ToolSearch:c,ToolPanel:o,ToolPanelView:x,ToolFormView:v}}); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/14f402d4a683/ Changeset: 14f402d4a683 User: martenson Date: 2015-03-02 21:39:48+00:00 Summary: increase toolbox search delay log search terms Affected #: 3 files diff -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 -r 14f402d4a6830e984a58bf626be2f8c40ae91b5a client/galaxy/scripts/mvc/tools.js --- a/client/galaxy/scripts/mvc/tools.js +++ b/client/galaxy/scripts/mvc/tools.js @@ -385,13 +385,15 @@ $("#search-clear-btn").hide(); $("#search-spinner").show(); var self = this; + // log the search to analytics + ga( 'send', 'pageview', galaxy_config.root + '?q=' + q ); this.timer = setTimeout(function () { $.get(self.attributes.search_url, { query: q }, function (data) { self.set("results", data); $("#search-spinner").hide(); $("#search-clear-btn").show(); }, "json" ); - }, 200 ); + }, 400 ); }, clear_search: function() { diff -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 -r 14f402d4a6830e984a58bf626be2f8c40ae91b5a static/scripts/mvc/tools.js --- a/static/scripts/mvc/tools.js +++ b/static/scripts/mvc/tools.js @@ -385,13 +385,15 @@ $("#search-clear-btn").hide(); $("#search-spinner").show(); var self = this; + // log the search to analytics + ga( 'send', 'pageview', galaxy_config.root + '?q=' + q ); this.timer = setTimeout(function () { $.get(self.attributes.search_url, { query: q }, function (data) { self.set("results", data); $("#search-spinner").hide(); $("#search-clear-btn").show(); }, "json" ); - }, 200 ); + }, 400 ); }, clear_search: function() { diff -r 5cec4dd844b27d45bc1c31a6c6d0707a67473086 -r 14f402d4a6830e984a58bf626be2f8c40ae91b5a static/scripts/packed/mvc/tools.js --- a/static/scripts/packed/mvc/tools.js +++ b/static/scripts/packed/mvc/tools.js @@ -1,1 +1,1 @@ -define(["libs/underscore","viz/trackster/util","mvc/data","libs/lunr"],function(y,a,z,s){var g={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},toggle:function(){this.set("hidden",!this.get("hidden"))},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.Model.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(A){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},set_value:function(A){this.set("value",A||"")}});var i=Backbone.Collection.extend({model:e});var k=e.extend({});var d=e.extend({set_value:function(A){this.set("value",parseInt(A,10))},get_samples:function(){return d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}});var f=d.extend({set_value:function(A){this.set("value",parseFloat(A))}});var u=e.extend({get_samples:function(){return y.map(this.get("options"),function(A){return A[0]})}});e.subModelTypes={integer:d,"float":f,data:k,select:u};var j=Backbone.Model.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[],outputs:[]},urlRoot:galaxy_config.root+"api/tools",initialize:function(A){this.set("inputs",new i(y.map(A.inputs,function(B){var C=e.subModelTypes[B.type]||e;return new C(B)})))},toJSON:function(){var A=Backbone.Model.prototype.toJSON.call(this);A.inputs=this.get("inputs").map(function(B){return B.toJSON()});return A},remove_inputs:function(B){var A=this,C=A.get("inputs").filter(function(D){return(B.indexOf(D.get("type"))!==-1)});A.get("inputs").remove(C)},copy:function(B){var C=new j(this.toJSON());if(B){var A=new Backbone.Collection();C.get("inputs").each(function(D){if(D.get_samples()){A.push(D)}});C.set("inputs",A)}return C},apply_search_results:function(A){(y.indexOf(A,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(A,B){this.get("inputs").find(function(C){return C.get("name")===A}).set("value",B)},set_input_values:function(B){var A=this;y.each(y.keys(B),function(C){A.set_input_value(C,B[C])})},run:function(){return this._run()},rerun:function(B,A){return this._run({action:"rerun",target_dataset_id:B.id,regions:A})},get_inputs_dict:function(){var A={};this.get("inputs").each(function(B){A[B.get("name")]=B.get("value")});return A},_run:function(C){var D=y.extend({tool_id:this.id,inputs:this.get_inputs_dict()},C);var B=$.Deferred(),A=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(D),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(E){return E!=="pending"}});$.when(A.go()).then(function(E){B.resolve(new z.DatasetCollection().reset(E))});return B}});y.extend(j.prototype,g);var q=Backbone.View.extend({});var n=Backbone.Collection.extend({model:j});var w=Backbone.Model.extend(g);var l=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){y.each(this.attributes.elems,function(A){A.show()});this.show();this.set("open",false)},apply_search_results:function(B){var C=true,A;y.each(this.attributes.elems,function(D){if(D instanceof w){A=D;A.hide()}else{if(D instanceof j){if(D.apply_search_results(B)){C=false;if(A){A.show()}}}}});if(C){this.hide()}else{this.show();this.set("open",true)}}});y.extend(l.prototype,g);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var C=this.attributes.query;if(C.length<this.attributes.min_chars_for_search){this.set("results",null);return}var B=C;if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var A=this;this.timer=setTimeout(function(){$.get(A.attributes.search_url,{query:B},function(D){A.set("results",D);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});y.extend(c.prototype,g);var o=Backbone.Model.extend({initialize:function(A){this.attributes.tool_search=A.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=A.tools;this.attributes.layout=new Backbone.Collection(this.parse(A.layout))},parse:function(B){var A=this,C=function(F){var E=F.model_class;if(E.indexOf("Tool")===E.length-4){return A.attributes.tools.get(F.id)}else{if(E==="ToolSection"){var D=y.map(F.elems,C);F.elems=D;return new l(F)}else{if(E==="ToolSectionLabel"){return new w(F)}}}};return y.map(B,C)},clear_search_results:function(){this.get("layout").each(function(A){if(A instanceof l){A.clear_search_results()}else{A.show()}})},apply_search_results:function(){var B=this.get("tool_search").get("results");if(B===null){this.clear_search_results();return}var A=null;this.get("layout").each(function(C){if(C instanceof w){A=C;A.hide()}else{if(C instanceof j){if(C.apply_search_results(B)){if(A){A.show()}}}else{A=null;C.apply_search_results(B)}}})}});var t=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var m=t.extend({tagName:"div",render:function(){var A=$("<div/>");A.append(Handlebars.templates.tool_link(this.model.toJSON()));if(this.model.id==="upload1"){A.find("a").on("click",function(B){B.preventDefault();Galaxy.upload.show()})}this.$el.append(A);return this}});var b=t.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var r=t.extend({tagName:"div",className:"toolSectionWrapper",initialize:function(){t.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(Handlebars.templates.panel_section(this.model.toJSON()));var A=this.$el.find(".toolSectionBody");y.each(this.model.attributes.elems,function(B){if(B instanceof j){var C=new m({model:B,className:"toolTitle"});C.render();A.append(C.$el)}else{if(B instanceof w){var D=new b({model:B});D.render();A.append(D.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var p=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(Handlebars.templates.tool_search(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find("[title]").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(A){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===A.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var x=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var A=this;var B=new p({model:this.model.get("tool_search")});B.render();A.$el.append(B.$el);this.model.get("layout").each(function(D){if(D instanceof l){var C=new r({model:D});C.render();A.$el.append(C.$el)}else{if(D instanceof j){var E=new m({model:D,className:"toolTitleNoSection"});E.render();A.$el.append(E.$el)}else{if(D instanceof w){var F=new b({model:D});F.render();A.$el.append(F.$el)}}}});A.$el.find("a.tool-link").click(function(E){var D=$(this).attr("class").split(/\s+/)[0],C=A.model.get("tools").get(D);A.trigger("tool_link_click",E,C)});return this},handle_search_results:function(){var A=this.model.get("tool_search").get("results");if(A&&A.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var v=Backbone.View.extend({className:"toolForm",render:function(){this.$el.children().remove();this.$el.append(Handlebars.templates.tool_form(this.model.toJSON()))}});var h=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new x({collection:this.collection});this.tool_form_view=new v()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var A=this;this.tool_panel_view.on("tool_link_click",function(C,B){C.preventDefault();A.show_tool(B)})},show_tool:function(B){var A=this;B.fetch().done(function(){A.tool_form_view.model=B;A.tool_form_view.render();A.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,SelectToolParameter:u,Tool:j,ToolCollection:n,ToolSearch:c,ToolPanel:o,ToolPanelView:x,ToolFormView:v}}); \ No newline at end of file +define(["libs/underscore","viz/trackster/util","mvc/data","libs/lunr"],function(y,a,z,s){var g={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},toggle:function(){this.set("hidden",!this.get("hidden"))},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.Model.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(A){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},set_value:function(A){this.set("value",A||"")}});var i=Backbone.Collection.extend({model:e});var k=e.extend({});var d=e.extend({set_value:function(A){this.set("value",parseInt(A,10))},get_samples:function(){return d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}});var f=d.extend({set_value:function(A){this.set("value",parseFloat(A))}});var u=e.extend({get_samples:function(){return y.map(this.get("options"),function(A){return A[0]})}});e.subModelTypes={integer:d,"float":f,data:k,select:u};var j=Backbone.Model.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[],outputs:[]},urlRoot:galaxy_config.root+"api/tools",initialize:function(A){this.set("inputs",new i(y.map(A.inputs,function(B){var C=e.subModelTypes[B.type]||e;return new C(B)})))},toJSON:function(){var A=Backbone.Model.prototype.toJSON.call(this);A.inputs=this.get("inputs").map(function(B){return B.toJSON()});return A},remove_inputs:function(B){var A=this,C=A.get("inputs").filter(function(D){return(B.indexOf(D.get("type"))!==-1)});A.get("inputs").remove(C)},copy:function(B){var C=new j(this.toJSON());if(B){var A=new Backbone.Collection();C.get("inputs").each(function(D){if(D.get_samples()){A.push(D)}});C.set("inputs",A)}return C},apply_search_results:function(A){(y.indexOf(A,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(A,B){this.get("inputs").find(function(C){return C.get("name")===A}).set("value",B)},set_input_values:function(B){var A=this;y.each(y.keys(B),function(C){A.set_input_value(C,B[C])})},run:function(){return this._run()},rerun:function(B,A){return this._run({action:"rerun",target_dataset_id:B.id,regions:A})},get_inputs_dict:function(){var A={};this.get("inputs").each(function(B){A[B.get("name")]=B.get("value")});return A},_run:function(C){var D=y.extend({tool_id:this.id,inputs:this.get_inputs_dict()},C);var B=$.Deferred(),A=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(D),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(E){return E!=="pending"}});$.when(A.go()).then(function(E){B.resolve(new z.DatasetCollection().reset(E))});return B}});y.extend(j.prototype,g);var q=Backbone.View.extend({});var n=Backbone.Collection.extend({model:j});var w=Backbone.Model.extend(g);var l=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){y.each(this.attributes.elems,function(A){A.show()});this.show();this.set("open",false)},apply_search_results:function(B){var C=true,A;y.each(this.attributes.elems,function(D){if(D instanceof w){A=D;A.hide()}else{if(D instanceof j){if(D.apply_search_results(B)){C=false;if(A){A.show()}}}}});if(C){this.hide()}else{this.show();this.set("open",true)}}});y.extend(l.prototype,g);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var C=this.attributes.query;if(C.length<this.attributes.min_chars_for_search){this.set("results",null);return}var B=C;if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var A=this;ga("send","pageview",galaxy_config.root+"?q="+B);this.timer=setTimeout(function(){$.get(A.attributes.search_url,{query:B},function(D){A.set("results",D);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},400)},clear_search:function(){this.set("query","");this.set("results",null)}});y.extend(c.prototype,g);var o=Backbone.Model.extend({initialize:function(A){this.attributes.tool_search=A.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=A.tools;this.attributes.layout=new Backbone.Collection(this.parse(A.layout))},parse:function(B){var A=this,C=function(F){var E=F.model_class;if(E.indexOf("Tool")===E.length-4){return A.attributes.tools.get(F.id)}else{if(E==="ToolSection"){var D=y.map(F.elems,C);F.elems=D;return new l(F)}else{if(E==="ToolSectionLabel"){return new w(F)}}}};return y.map(B,C)},clear_search_results:function(){this.get("layout").each(function(A){if(A instanceof l){A.clear_search_results()}else{A.show()}})},apply_search_results:function(){var B=this.get("tool_search").get("results");if(B===null){this.clear_search_results();return}var A=null;this.get("layout").each(function(C){if(C instanceof w){A=C;A.hide()}else{if(C instanceof j){if(C.apply_search_results(B)){if(A){A.show()}}}else{A=null;C.apply_search_results(B)}}})}});var t=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var m=t.extend({tagName:"div",render:function(){var A=$("<div/>");A.append(Handlebars.templates.tool_link(this.model.toJSON()));if(this.model.id==="upload1"){A.find("a").on("click",function(B){B.preventDefault();Galaxy.upload.show()})}this.$el.append(A);return this}});var b=t.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var r=t.extend({tagName:"div",className:"toolSectionWrapper",initialize:function(){t.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(Handlebars.templates.panel_section(this.model.toJSON()));var A=this.$el.find(".toolSectionBody");y.each(this.model.attributes.elems,function(B){if(B instanceof j){var C=new m({model:B,className:"toolTitle"});C.render();A.append(C.$el)}else{if(B instanceof w){var D=new b({model:B});D.render();A.append(D.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var p=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(Handlebars.templates.tool_search(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find("[title]").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(A){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===A.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var x=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var A=this;var B=new p({model:this.model.get("tool_search")});B.render();A.$el.append(B.$el);this.model.get("layout").each(function(D){if(D instanceof l){var C=new r({model:D});C.render();A.$el.append(C.$el)}else{if(D instanceof j){var E=new m({model:D,className:"toolTitleNoSection"});E.render();A.$el.append(E.$el)}else{if(D instanceof w){var F=new b({model:D});F.render();A.$el.append(F.$el)}}}});A.$el.find("a.tool-link").click(function(E){var D=$(this).attr("class").split(/\s+/)[0],C=A.model.get("tools").get(D);A.trigger("tool_link_click",E,C)});return this},handle_search_results:function(){var A=this.model.get("tool_search").get("results");if(A&&A.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var v=Backbone.View.extend({className:"toolForm",render:function(){this.$el.children().remove();this.$el.append(Handlebars.templates.tool_form(this.model.toJSON()))}});var h=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new x({collection:this.collection});this.tool_form_view=new v()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var A=this;this.tool_panel_view.on("tool_link_click",function(C,B){C.preventDefault();A.show_tool(B)})},show_tool:function(B){var A=this;B.fetch().done(function(){A.tool_form_view.model=B;A.tool_form_view.render();A.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,SelectToolParameter:u,Tool:j,ToolCollection:n,ToolSearch:c,ToolPanel:o,ToolPanelView:x,ToolFormView:v}}); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/6f09ebd33874/ Changeset: 6f09ebd33874 User: martenson Date: 2015-03-02 22:19:11+00:00 Summary: compile handlebar templates I wanted only one but the compilation alg probably changed so am adding all Affected #: 4 files diff -r 14f402d4a6830e984a58bf626be2f8c40ae91b5a -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 static/scripts/templates/compiled/panel_section.js --- a/static/scripts/templates/compiled/panel_section.js +++ b/static/scripts/templates/compiled/panel_section.js @@ -1,13 +1,14 @@ (function() { var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; templates['panel_section'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression; + return "<div class=\"toolSectionTitle\" id=\"title_" - + escapeExpression(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"id","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"id","hash":{},"data":data}) : helper))) + "\">\n <a href=\"javascript:void(0)\"><span>" - + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper))) + "</span></a>\n</div>\n<div id=\"" - + escapeExpression(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"id","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"id","hash":{},"data":data}) : helper))) + "\" class=\"toolSectionBody\" style=\"display: none; \">\n <div class=\"toolSectionBg\"></div>\n<div>"; },"useData":true}); })(); \ No newline at end of file diff -r 14f402d4a6830e984a58bf626be2f8c40ae91b5a -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 static/scripts/templates/compiled/tool_form.js --- a/static/scripts/templates/compiled/tool_form.js +++ b/static/scripts/templates/compiled/tool_form.js @@ -1,26 +1,28 @@ (function() { var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; templates['tool_form'] = template({"1":function(depth0,helpers,partials,data) { - var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = " <div class=\"form-row\">\n <label for=\"" - + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper))) + var stack1, helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression; + + return " <div class=\"form-row\">\n <label for=\"" + + alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper))) + "\">" - + escapeExpression(((helper = (helper = helpers.label || (depth0 != null ? depth0.label : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"label","hash":{},"data":data}) : helper))) - + ":</label>\n <div class=\"form-row-input\">\n "; - stack1 = ((helper = (helper = helpers.html || (depth0 != null ? depth0.html : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"html","hash":{},"data":data}) : helper)); - if (stack1 != null) { buffer += stack1; } - return buffer + "\n </div>\n <div class=\"toolParamHelp\" style=\"clear: both;\">\n " - + escapeExpression(((helper = (helper = helpers.help || (depth0 != null ? depth0.help : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"help","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.label || (depth0 != null ? depth0.label : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"label","hash":{},"data":data}) : helper))) + + ":</label>\n <div class=\"form-row-input\">\n " + + ((stack1 = ((helper = (helper = helpers.html || (depth0 != null ? depth0.html : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"html","hash":{},"data":data}) : helper))) != null ? stack1 : "") + + "\n </div>\n <div class=\"toolParamHelp\" style=\"clear: both;\">\n " + + alias3(((helper = (helper = helpers.help || (depth0 != null ? depth0.help : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"help","hash":{},"data":data}) : helper))) + "\n </div>\n <div style=\"clear: both;\"></div>\n </div>\n"; },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "<div class=\"toolFormTitle\">" - + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper))) + var stack1, helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression; + + return "<div class=\"toolFormTitle\">" + + alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper))) + " (version " - + escapeExpression(((helper = (helper = helpers.version || (depth0 != null ? depth0.version : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"version","hash":{},"data":data}) : helper))) - + ")</div>\n <div class=\"toolFormBody\">\n"; - stack1 = helpers.each.call(depth0, (depth0 != null ? depth0.inputs : depth0), {"name":"each","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data}); - if (stack1 != null) { buffer += stack1; } - return buffer + " </div>\n <div class=\"form-row form-actions\">\n <input type=\"submit\" class=\"btn btn-primary\" name=\"runtool_btn\" value=\"Execute\">\n</div>\n<div class=\"toolHelp\">\n <div class=\"toolHelpBody\">" - + escapeExpression(((helper = (helper = helpers.help || (depth0 != null ? depth0.help : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"help","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.version || (depth0 != null ? depth0.version : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"version","hash":{},"data":data}) : helper))) + + ")</div>\n <div class=\"toolFormBody\">\n" + + ((stack1 = helpers.each.call(depth0,(depth0 != null ? depth0.inputs : depth0),{"name":"each","hash":{},"fn":this.program(1, data, 0),"inverse":this.noop,"data":data})) != null ? stack1 : "") + + " </div>\n <div class=\"form-row form-actions\">\n <input type=\"submit\" class=\"btn btn-primary\" name=\"runtool_btn\" value=\"Execute\">\n</div>\n<div class=\"toolHelp\">\n <div class=\"toolHelpBody\">" + + alias3(((helper = (helper = helpers.help || (depth0 != null ? depth0.help : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"help","hash":{},"data":data}) : helper))) + "</div>\n</div>"; },"useData":true}); })(); \ No newline at end of file diff -r 14f402d4a6830e984a58bf626be2f8c40ae91b5a -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 static/scripts/templates/compiled/tool_link.js --- a/static/scripts/templates/compiled/tool_link.js +++ b/static/scripts/templates/compiled/tool_link.js @@ -1,18 +1,19 @@ (function() { var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; templates['tool_link'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression; + return "<a class=\"" - + escapeExpression(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"id","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"id","hash":{},"data":data}) : helper))) + " tool-link\" href=\"" - + escapeExpression(((helper = (helper = helpers.link || (depth0 != null ? depth0.link : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"link","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.link || (depth0 != null ? depth0.link : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"link","hash":{},"data":data}) : helper))) + "\" target=\"" - + escapeExpression(((helper = (helper = helpers.target || (depth0 != null ? depth0.target : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"target","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.target || (depth0 != null ? depth0.target : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"target","hash":{},"data":data}) : helper))) + "\" minsizehint=\"" - + escapeExpression(((helper = (helper = helpers.min_width || (depth0 != null ? depth0.min_width : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"min_width","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.min_width || (depth0 != null ? depth0.min_width : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"min_width","hash":{},"data":data}) : helper))) + "\">" - + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper))) + + alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper))) + "</a> " - + escapeExpression(((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"description","hash":{},"data":data}) : helper))); + + alias3(((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"description","hash":{},"data":data}) : helper))); },"useData":true}); })(); \ No newline at end of file diff -r 14f402d4a6830e984a58bf626be2f8c40ae91b5a -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 static/scripts/templates/compiled/tool_search.js --- a/static/scripts/templates/compiled/tool_search.js +++ b/static/scripts/templates/compiled/tool_search.js @@ -1,11 +1,12 @@ (function() { var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; templates['tool_search'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "<input type=\"text\" name=\"query\" value=\"" - + escapeExpression(((helper = (helper = helpers.search_hint_string || (depth0 != null ? depth0.search_hint_string : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"search_hint_string","hash":{},"data":data}) : helper))) + var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression; + + return "<input type=\"text\" name=\"query\" placeholder=\"" + + alias3(((helper = (helper = helpers.search_hint_string || (depth0 != null ? depth0.search_hint_string : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"search_hint_string","hash":{},"data":data}) : helper))) + "\" id=\"tool-search-query\" autocomplete=\"off\" class=\"search-query parent-width\" />\n<a id=\"search-clear-btn\" title=\"clear search (esc)\"></a>\n<img src=\"" - + escapeExpression(((helper = (helper = helpers.spinner_url || (depth0 != null ? depth0.spinner_url : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"spinner_url","hash":{},"data":data}) : helper))) - + "\" id=\"search-spinner\" class=\"search-spinner\"/>"; + + alias3(((helper = (helper = helpers.spinner_url || (depth0 != null ? depth0.spinner_url : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"spinner_url","hash":{},"data":data}) : helper))) + + "\" id=\"search-spinner\" class=\"search-spinner\"/>\n"; },"useData":true}); })(); \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/commits/a4f9af6ab587/ Changeset: a4f9af6ab587 User: dannon Date: 2015-03-02 22:26:11+00:00 Summary: Change auth_debug behavior -- simply use an appropriate loglevel Affected #: 10 files diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc config/galaxy.ini.sample --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -848,8 +848,6 @@ # (e.g. Active Directory) instead or in addition to local authentication # (.sample is used if default does not exist). #auth_config_file = config/auth_conf.xml -# Print debugging info for auth -#auth_debug = False # Optional list of email addresses of API users who can make calls on behalf of # other users. diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -48,7 +48,6 @@ self.__plugins_dict = plugin_config.plugins_dict( galaxy.auth.providers, 'plugin_type' ) auth_config_file = app.config.auth_config_file self.__init_authenticators(auth_config_file) - self.debug = getattr(app.config, 'auth_debug', False) def __init_authenticators(self, auth_config_file): # parse XML @@ -104,17 +103,16 @@ break return message, status - def check_auto_registration(self, trans, email, password, debug=False): + def check_auto_registration(self, trans, email, password): """ Checks the email/password using auth providers in order. If a match is found, returns the 'auto-register' option for that provider. """ for provider, options in self.active_authenticators(email, password): if provider is None: - if debug: - log.debug( "Unable to find module: %s" % options ) + log.debug( "Unable to find module: %s" % options ) else: - auth_result, auto_username = provider.authenticate(email, password, options, debug) + auth_result, auto_username = provider.authenticate(email, password, options) auto_username = str(auto_username).lower() if auth_result is True: # make username unique @@ -127,8 +125,7 @@ i += 1 else: break # end for loop if we can't make a unique username - if debug: - log.debug( "Email: %s, auto-register with username: %s" % (email, auto_username) ) + log.debug( "Email: %s, auto-register with username: %s" % (email, auto_username) ) return (_get_bool(options, 'auto-register', False), auto_username) elif auth_result is None: log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) @@ -139,8 +136,7 @@ """Checks the email/password using auth providers.""" for provider, options in self.active_authenticators(user.email, password): if provider is None: - if self.debug: - log.debug( "Unable to find module: %s" % options ) + log.debug( "Unable to find module: %s" % options ) else: auth_result = provider.authenticate_user(user, password, options) if auth_result is True: @@ -155,8 +151,7 @@ """ for provider, options in self.active_authenticators(user.email, current_password): if provider is None: - if self.debug: - log.debug( "Unable to find module: %s" % options ) + log.debug( "Unable to find module: %s" % options ) else: if _get_bool(options, "allow-password-change", False): auth_result = provider.authenticate_user(user, current_password, options) @@ -182,8 +177,7 @@ continue # skip to next yield authenticator.plugin, authenticator.options except Exception: - if self.debug: - log.debug( ('Auth: Exception:\n%s' % (traceback.format_exc(),)) ) + log.debug( ('Auth: Exception:\n%s' % (traceback.format_exc(),)) ) raise Authenticator = namedtuple('Authenticator', ['plugin', 'filter_template', 'options']) diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/auth/providers/__init__.py --- a/lib/galaxy/auth/providers/__init__.py +++ b/lib/galaxy/auth/providers/__init__.py @@ -16,7 +16,7 @@ """ Short string providing labelling this plugin """ @abc.abstractmethod - def authenticate(self, username, password, options, debug=False): + def authenticate(self, username, password, options): """ Check that the username and password are correct. @@ -29,8 +29,6 @@ :type password: str :param options: options provided in auth_config_file :type options: dict - :param debug: whether to print debugging info (defaults to False) - :type debug: bool :returns: True: accept user, False: reject user and None: reject user and don't try any other providers. str is the username to register with if accepting @@ -38,7 +36,7 @@ """ @abc.abstractmethod - def authenticate_user(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options): """ Same as authenticate() method, except an User object is provided instead of a username. @@ -52,8 +50,6 @@ :type password: str :param options: options provided in auth_config_file :type options: dict - :param debug: whether to print debugging info (defaults to False) - :type debug: bool :returns: True: accept user, False: reject user and None: reject user and don't try any other providers :rtype: bool diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -27,13 +27,12 @@ """ plugin_type = 'activedirectory' - def authenticate(self, username, password, options, debug=False): + def authenticate(self, username, password, options): """ See abstract method documentation. """ - if debug: - log.debug("Username: %s" % username) - log.debug("Options: %s" % options) + log.debug("Username: %s" % username) + log.debug("Options: %s" % options) failure_mode = False # reject but continue if options.get('continue-on-failure', 'False') == 'False': @@ -42,8 +41,7 @@ try: import ldap except: - if debug: - log.debug("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) + log.debug("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) return (failure_mode, '') # do AD search (if required) @@ -64,8 +62,7 @@ # parse results _, suser = l.result(result, 60) _, attrs = suser[0] - if debug: - log.debug(("AD Search attributes: %s" % attrs)) + log.debug(("AD Search attributes: %s" % attrs)) if hasattr(attrs, 'has_key'): for attr in attributes: if attr in attrs: @@ -73,8 +70,7 @@ else: vars[attr] = "" except Exception: - if debug: - log.debug('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) + log.debug('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) return (failure_mode, '') # end search @@ -86,19 +82,17 @@ l.protocol_version = 3 l.simple_bind_s(_get_subs(options, 'bind-user', vars), _get_subs(options, 'bind-password', vars)) except Exception: - if debug: - log.debug('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) + log.debug('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) return (failure_mode, '') - if debug: - log.debug("User: %s, ACTIVEDIRECTORY: True" % (username)) + log.debug("User: %s, ACTIVEDIRECTORY: True" % (username)) return (True, _get_subs(options, 'auto-register-username', vars)) - def authenticate_user(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options): """ See abstract method documentation. """ - return self.authenticate(user.email, password, options, debug)[0] + return self.authenticate(user.email, password, options)[0] __all__ = ['ActiveDirectory'] diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/auth/providers/alwaysreject.py --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -16,18 +16,17 @@ """ plugin_type = 'alwaysreject' - def authenticate(self, username, password, options, debug=False): + def authenticate(self, username, password, options): """ See abstract method documentation. """ return (None, '') - def authenticate_user(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options): """ See abstract method documentation. """ - if debug: - log.debug("User: %s, ALWAYSREJECT: None" % (user.email)) + log.debug("User: %s, ALWAYSREJECT: None" % (user.email)) return None diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/auth/providers/localdb.py --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -13,19 +13,18 @@ """Authenticate users against the local Galaxy database (as per usual).""" plugin_type = 'localdb' - def authenticate(self, username, password, options, debug=False): + def authenticate(self, username, password, options): """ See abstract method documentation. """ return (False, '') # it can never auto-create based of localdb (chicken-egg) - def authenticate_user(self, user, password, options, debug=False): + def authenticate_user(self, user, password, options): """ See abstract method documentation. """ user_ok = user.check_password(password) - if debug: - log.debug("User: %s, LOCALDB: %s" % (user.email, user_ok)) + log.debug("User: %s, LOCALDB: %s" % (user.email, user_ok)) return user_ok diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -441,8 +441,6 @@ # Default chunk size for chunkable datatypes -- 64k self.display_chunk_size = int( kwargs.get( 'display_chunk_size', 65536) ) - # auth - self.auth_debug = string_as_bool( kwargs.get( 'auth_debug', False ) ) self.citation_cache_type = kwargs.get( "citation_cache_type", "file" ) self.citation_cache_data_dir = self.resolve_path( kwargs.get( "citation_cache_data_dir", "database/citations/data" ) ) diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/webapps/galaxy/controllers/mobile.py --- a/lib/galaxy/webapps/galaxy/controllers/mobile.py +++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py @@ -58,7 +58,7 @@ # error = password_error = None # user = trans.sa_session.query( model.User ).filter_by( email = email ).first() # if not user: - # autoreg = galaxy.auth.check_auto_registration(trans, email, password, trans.app.config.auth_config_file, trans.app.config.auth_debug) + # autoreg = galaxy.auth.check_auto_registration(trans, email, password, trans.app.config.auth_config_file) # if autoreg[0]: # kwd = {} # kwd['username'] = autoreg[1] @@ -82,7 +82,7 @@ # error = "This account has been marked deleted, contact your Galaxy administrator to restore the account." # elif user.external: # error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." - # elif not galaxy.auth.check_password(user, password, trans.app.config.auth_config_file, trans.app.config.auth_debug): + # elif not galaxy.auth.check_password(user, password, trans.app.config.auth_config_file): # error = "Invalid password" # else: # trans.handle_user_login( user ) diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -514,9 +514,7 @@ redirect = kwd.get( 'redirect', trans.request.referer ).strip() success = False user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first() - if trans.app.config.auth_debug: - print ("trans.app.config.auth_config_file: %s" % trans.app.config.auth_config_file) - print ("trans.app.config.auth_debug: %s WARNING: don't use in production" % trans.app.config.auth_debug) + log.debug("trans.app.config.auth_config_file: %s" % trans.app.config.auth_config_file) if not user: autoreg = trans.app.auth_manager.check_auto_registration(trans, email, password) if autoreg[0]: diff -r 6f09ebd33874856a2495fedeeb5e85e2c6203362 -r a4f9af6ab5870618d0318fca1d0af6b762f278bc lib/galaxy/webapps/tool_shed/config.py --- a/lib/galaxy/webapps/tool_shed/config.py +++ b/lib/galaxy/webapps/tool_shed/config.py @@ -132,7 +132,6 @@ if global_conf and "__file__" in global_conf: global_conf_parser.read(global_conf['__file__']) self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) ) - self.auth_debug = string_as_bool( kwargs.get( 'auth_debug', False ) ) self.citation_cache_type = kwargs.get( "citation_cache_type", "file" ) self.citation_cache_data_dir = resolve_path( kwargs.get( "citation_cache_data_dir", "database/tool_shed_citations/data" ), self.root ) self.citation_cache_lock_dir = resolve_path( kwargs.get( "citation_cache_lock_dir", "database/tool_shed_citations/locks" ), self.root ) https://bitbucket.org/galaxy/galaxy-central/commits/13ff916e7fc0/ Changeset: 13ff916e7fc0 User: dannon Date: 2015-03-02 22:35:14+00:00 Summary: Swap logging in auth exception handling to use log.exception Affected #: 2 files diff -r a4f9af6ab5870618d0318fca1d0af6b762f278bc -r 13ff916e7fc049900a1233e84e9a140c8491de36 lib/galaxy/auth/__init__.py --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -3,7 +3,6 @@ """ from collections import namedtuple -import traceback import xml.etree.ElementTree from galaxy.security.validate_user_input import validate_publicname @@ -177,7 +176,7 @@ continue # skip to next yield authenticator.plugin, authenticator.options except Exception: - log.debug( ('Auth: Exception:\n%s' % (traceback.format_exc(),)) ) + log.exception( "Active Authenticators Failure" ) raise Authenticator = namedtuple('Authenticator', ['plugin', 'filter_template', 'options']) diff -r a4f9af6ab5870618d0318fca1d0af6b762f278bc -r 13ff916e7fc049900a1233e84e9a140c8491de36 lib/galaxy/auth/providers/activedirectory.py --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/activedirectory.py @@ -4,7 +4,6 @@ @author: Andrew Robinson """ -import traceback from ..providers import AuthProvider import logging @@ -70,7 +69,7 @@ else: vars[attr] = "" except Exception: - log.debug('User: %s, ACTIVEDIRECTORY: Search Exception:\n%s' % (username, traceback.format_exc(),)) + log.exception('ACTIVEDIRECTORY Search Exception for User: %s' % username) return (failure_mode, '') # end search @@ -82,7 +81,7 @@ l.protocol_version = 3 l.simple_bind_s(_get_subs(options, 'bind-user', vars), _get_subs(options, 'bind-password', vars)) except Exception: - log.debug('User: %s, ACTIVEDIRECTORY: Authenticate Exception:\n%s' % (username, traceback.format_exc())) + log.exception('ACTIVEDIRECTORY Authenticate Exception for User %s' % username) return (failure_mode, '') log.debug("User: %s, ACTIVEDIRECTORY: True" % (username)) https://bitbucket.org/galaxy/galaxy-central/commits/614be0554e42/ Changeset: 614be0554e42 User: dannon Date: 2015-03-03 00:51:46+00:00 Summary: Fix bug in toolshed set_tool_versions during error case Affected #: 1 file diff -r 13ff916e7fc049900a1233e84e9a140c8491de36 -r 614be0554e42399b32dbfc5982bd72f9f98137a5 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -1763,9 +1763,9 @@ message = "Tool versions have been set for all included tools." status = 'done' else: - message = "Version information for the tools included in the <b>%s</b> repository is missing. " % escape( repository.name ) - message += "Reset all of this reppository's metadata in the tool shed, then set the installed tool versions " - message ++ "from the installed repository's <b>Repository Actions</b> menu. " + message = ("Version information for the tools included in the <b>%s</b> repository is missing. " + "Reset all of this reppository's metadata in the tool shed, then set the installed tool versions " + "from the installed repository's <b>Repository Actions</b> menu. " % escape( repository.name )) status = 'error' shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, repository ) repo_files_dir = os.path.abspath( os.path.join( relative_install_dir, repository.name ) ) https://bitbucket.org/galaxy/galaxy-central/commits/c0321a70f8f5/ Changeset: c0321a70f8f5 User: dannon Date: 2015-03-03 01:10:28+00:00 Summary: Fix another bug in admin_toolshed controller encountered if tool_dependency_dir not set but deps are defined Affected #: 1 file diff -r 614be0554e42399b32dbfc5982bd72f9f98137a5 -r c0321a70f8f58e06859453e834d273cac4509ef7 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -614,10 +614,10 @@ self.initiate_tool_dependency_installation( trans, tool_dependencies, message=message, status=status ) # Handle tool dependencies check box. if trans.app.config.tool_dependency_dir is None: - if includes_tool_dependencies: - message = "Tool dependencies defined in this repository can be automatically installed if you set " - message += "the value of your <b>tool_dependency_dir</b> setting in your Galaxy config file " - message += "(galaxy.ini) and restart your Galaxy server." + if tool_dependencies_dict: + message = ("Tool dependencies defined in this repository can be automatically installed if you set " + "the value of your <b>tool_dependency_dir</b> setting in your Galaxy config file " + "(galaxy.ini) and restart your Galaxy server.") status = "warning" install_tool_dependencies_check_box_checked = False else: https://bitbucket.org/galaxy/galaxy-central/commits/8af2b8d5c8cd/ Changeset: 8af2b8d5c8cd User: dannon Date: 2015-03-03 01:43:37+00:00 Summary: Remove cruft and unused vars, cleanup/pep8 in admin_toolshed controller. Affected #: 1 file diff -r c0321a70f8f58e06859453e834d273cac4509ef7 -r 8af2b8d5c8cd1ab84021a7e1197b7d38d946b62f lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -199,7 +199,6 @@ @web.require_admin def browse_tool_sheds( self, trans, **kwd ): message = escape( kwd.get( 'message', '' ) ) - status = kwd.get( 'status', 'done' ) return trans.fill_template( '/webapps/galaxy/admin/tool_sheds.mako', message=message, status='error' ) @@ -216,8 +215,7 @@ str( repository.name ), str( repository.owner ), str( repository.changeset_revision ) ) - url = common_util.url_join( tool_shed_url, - 'repository/check_for_updates%s' % params ) + url = common_util.url_join( tool_shed_url, 'repository/check_for_updates%s' % params ) return trans.response.send_redirect( url ) @web.expose @@ -331,7 +329,7 @@ image can be defined in either a README.rst file contained in the repository or the help section of a Galaxy tool config that is contained in the repository. The following image definitions are all supported. The former $PATH_TO_IMAGES is no longer required, and is now ignored. - .. image:: https://raw.github.com/galaxy/some_image.png + .. image:: https://raw.github.com/galaxy/some_image.png .. image:: $PATH_TO_IMAGES/some_image.png .. image:: /static/images/some_image.gif .. image:: some_image.jpg @@ -348,7 +346,7 @@ file_name = os.path.basename( relative_path_to_image_file ) try: extension = file_name.split( '.' )[ -1 ] - except Exception, e: + except Exception: extension = None if extension: mimetype = trans.app.datatypes_registry.get_mimetype_by_extension( extension ) @@ -497,7 +495,6 @@ text = util.unicodify( installed_tool_dependency.error_message ) if text is not None: err_msg += ' %s' % text - tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in tool_dependencies ] if err_msg: message += err_msg status = 'error' @@ -604,7 +601,7 @@ updated_metadata_dict=updated_metadata, updated_changeset_revision=updating_to_changeset_revision, updated_ctx_rev=updating_to_ctx_rev ) - if install_tool_dependencies: + if includes_tool_dependencies: tool_dependencies = tool_dependency_util.create_tool_dependency_objects( trans.app, repository, relative_install_dir, @@ -641,7 +638,6 @@ @web.require_admin def manage_repositories( self, trans, **kwd ): message = escape( kwd.get( 'message', '' ) ) - status = kwd.get( 'status', 'done' ) tsridslist = common_util.get_tool_shed_repository_ids( **kwd ) if 'operation' in kwd: operation = kwd[ 'operation' ].lower() @@ -857,7 +853,7 @@ # The user must be on the manage_repository_tool_dependencies page and clicked the button to either install or uninstall a # tool dependency, but they didn't check any of the available tool dependencies on which to perform the action. tool_shed_repository = suc.get_tool_shed_repository_by_id( trans.app, repository_id ) - self.tool_dependency_grid.title = "Tool shed repository '%s' tool dependencies" % escape( tool_shed_repository.name ) + self.tool_dependency_grid.title = "Tool shed repository '%s' tool dependencies" % escape( tool_shed_repository.name ) if 'operation' in kwd: operation = kwd[ 'operation' ].lower() if not tool_dependency_ids: @@ -1018,12 +1014,9 @@ repo_info_dicts = [ encoding_util.tool_shed_decode( encoded_repo_info_dict ) for encoded_repo_info_dict in encoded_repo_info_dicts ] dd = dependency_display.DependencyDisplayer( trans.app ) install_repository_manager = install_manager.InstallRepositoryManager( trans.app ) - if ( not includes_tools_for_display_in_tool_panel and kwd.get( 'select_shed_tool_panel_config_button', False ) ) or \ - ( includes_tools_for_display_in_tool_panel and kwd.get( 'select_tool_panel_section_button', False ) ): + if ( ( not includes_tools_for_display_in_tool_panel and kwd.get( 'select_shed_tool_panel_config_button', False ) ) or + ( includes_tools_for_display_in_tool_panel and kwd.get( 'select_tool_panel_section_button', False ) ) ): if updating: - encoded_updated_metadata_dict = kwd.get( 'encoded_updated_metadata_dict', None ) - updated_changeset_revision = kwd.get( 'updated_changeset_revision', None ) - updated_ctx_rev = kwd.get( 'updated_ctx_rev', None ) repository = suc.get_tool_shed_repository_by_id( trans.app, updating_repository_id ) decoded_updated_metadata = encoding_util.tool_shed_decode( encoded_updated_metadata ) # Now that the user has decided whether they will handle dependencies, we can update @@ -1090,7 +1083,6 @@ repo_info_dict, includes_tool_dependencies, updating=updating ) - changeset_revision = dependencies_for_repository_dict.get( 'changeset_revision', None ) if not has_repository_dependencies: has_repository_dependencies = dependencies_for_repository_dict.get( 'has_repository_dependencies', False ) if not includes_tool_dependencies: @@ -1104,8 +1096,6 @@ installed_tool_dependencies = dependencies_for_repository_dict.get( 'installed_tool_dependencies', None ) missing_repository_dependencies = dependencies_for_repository_dict.get( 'missing_repository_dependencies', None ) missing_tool_dependencies = dependencies_for_repository_dict.get( 'missing_tool_dependencies', None ) - name = dependencies_for_repository_dict.get( 'name', None ) - repository_owner = dependencies_for_repository_dict.get( 'repository_owner', None ) readme_files_dict = readme_util.get_readme_files_dict_for_display( trans.app, tool_shed_url, repo_info_dict ) # We're handling 1 of 3 scenarios here: (1) we're installing a tool shed repository for the first time, so we've # retrieved the list of installed and missing repository dependencies from the database (2) we're handling the @@ -1128,14 +1118,12 @@ else: # We're installing a list of repositories, each of which may have tool dependencies or repository dependencies. containers_dicts = [] - installed_repository_manager = trans.app.installed_repository_manager for repo_info_dict in repo_info_dicts: dependencies_for_repository_dict = \ trans.app.installed_repository_manager.get_dependencies_for_repository( tool_shed_url, repo_info_dict, includes_tool_dependencies, updating=updating ) - changeset_revision = dependencies_for_repository_dict.get( 'changeset_revision', None ) if not has_repository_dependencies: has_repository_dependencies = dependencies_for_repository_dict.get( 'has_repository_dependencies', False ) if not includes_tool_dependencies: @@ -1149,17 +1137,16 @@ installed_tool_dependencies = dependencies_for_repository_dict.get( 'installed_tool_dependencies', None ) missing_repository_dependencies = dependencies_for_repository_dict.get( 'missing_repository_dependencies', None ) missing_tool_dependencies = dependencies_for_repository_dict.get( 'missing_tool_dependencies', None ) - name = dependencies_for_repository_dict.get( 'name', None ) - repository_owner = dependencies_for_repository_dict.get( 'repository_owner', None ) - containers_dict = \ - dd.populate_containers_dict_for_new_install( tool_shed_url=tool_shed_url, - tool_path=tool_path, - readme_files_dict=None, - installed_repository_dependencies=installed_repository_dependencies, - missing_repository_dependencies=missing_repository_dependencies, - installed_tool_dependencies=installed_tool_dependencies, - missing_tool_dependencies=missing_tool_dependencies, - updating=updating ) + containers_dict = dd.populate_containers_dict_for_new_install( + tool_shed_url=tool_shed_url, + tool_path=tool_path, + readme_files_dict=None, + installed_repository_dependencies=installed_repository_dependencies, + missing_repository_dependencies=missing_repository_dependencies, + installed_tool_dependencies=installed_tool_dependencies, + missing_tool_dependencies=missing_tool_dependencies, + updating=updating + ) containers_dicts.append( containers_dict ) # Merge all containers into a single container. containers_dict = dd.merge_containers_dicts_for_new_install( containers_dicts ) @@ -1280,10 +1267,6 @@ shed_tool_conf, tool_path, relative_install_dir = \ suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository ) repository_clone_url = common_util.generate_clone_url_for_installed_repository( trans.app, tool_shed_repository ) - clone_dir = os.path.join( tool_path, - suc.generate_tool_shed_repository_install_dir( repository_clone_url, - tool_shed_repository.installed_changeset_revision ) ) - relative_install_dir = os.path.join( clone_dir, tool_shed_repository.name ) tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( trans.app, tool_shed_repository.tool_shed ) tool_section = None tool_panel_section_id = kwd.get( 'tool_panel_section_id', '' ) @@ -1381,7 +1364,7 @@ tool_shed_repository_ids=encoded_repository_ids, tool_shed_url=tool_shed_url ) encoded_kwd = encoding_util.tool_shed_encode( new_kwd ) - tsr_ids = [ r.id for r in created_or_updated_tool_shed_repositories ] + tsr_ids = [ r.id for r in created_or_updated_tool_shed_repositories ] tool_shed_repositories = [] for tsr_id in tsr_ids: tsr = trans.install_model.context.query( trans.install_model.ToolShedRepository ).get( tsr_id ) @@ -1452,8 +1435,8 @@ # The received lists of tool_shed_repositories and repo_info_dicts are ordered. for index, tool_shed_repository in enumerate( tool_shed_repositories ): repo_info_dict = repo_info_dicts[ index ] - repair_dict = repair_repository_manager.repair_tool_shed_repository( tool_shed_repository, - encoding_util.tool_shed_encode( repo_info_dict ) ) + repair_repository_manager.repair_tool_shed_repository( tool_shed_repository, + encoding_util.tool_shed_encode( repo_info_dict ) ) tsr_ids_for_monitoring = [ trans.security.encode_id( tsr.id ) for tsr in tool_shed_repositories ] return trans.response.send_redirect( web.url_for( controller='admin_toolshed', action='monitor_repository_installation', @@ -1477,7 +1460,7 @@ status=repository.status, html_status=unicode( trans.fill_template( "admin/tool_shed_repository/repository_installation_status.mako", repository=repository ), - 'utf-8' ) ) ) + 'utf-8' ) ) ) return rval @web.expose @@ -1568,7 +1551,6 @@ repo_info_dict, includes_tool_dependencies, updating=False ) - changeset_revision = dependencies_for_repository_dict.get( 'changeset_revision', None ) has_repository_dependencies = dependencies_for_repository_dict.get( 'has_repository_dependencies', False ) includes_tool_dependencies = dependencies_for_repository_dict.get( 'includes_tool_dependencies', False ) includes_tools = dependencies_for_repository_dict.get( 'includes_tools', False ) @@ -1577,8 +1559,6 @@ installed_tool_dependencies = dependencies_for_repository_dict.get( 'installed_tool_dependencies', None ) missing_repository_dependencies = dependencies_for_repository_dict.get( 'missing_repository_dependencies', None ) missing_tool_dependencies = dependencies_for_repository_dict.get( 'missing_tool_dependencies', None ) - repository_name = dependencies_for_repository_dict.get( 'name', None ) - repository_owner = dependencies_for_repository_dict.get( 'repository_owner', None ) if installed_repository_dependencies or missing_repository_dependencies: has_repository_dependencies = True else: @@ -1691,7 +1671,7 @@ repository=repository, changeset_revision=repository.changeset_revision, repository_clone_url=repository_clone_url, - shed_config_dict = repository.get_shed_config_dict( trans.app ), + shed_config_dict=repository.get_shed_config_dict( trans.app ), relative_install_dir=relative_install_dir, repository_files_dir=None, resetting_all_metadata_on_repository=False, @@ -1801,7 +1781,7 @@ status=tool_dependency.status, html_status=unicode( trans.fill_template( "admin/tool_shed_repository/tool_dependency_installation_status.mako", tool_dependency=tool_dependency ), - 'utf-8' ) ) ) + 'utf-8' ) ) ) return rval @web.expose @@ -1923,12 +1903,12 @@ # Add new Data Manager entries if 'data_manager' in irmm_metadata_dict: dmh = data_manager.DataManagerHandler( trans.app ) - new_data_managers = dmh.install_data_managers( trans.app.config.shed_data_manager_config_file, - irmm_metadata_dict, - repository.get_shed_config_dict( trans.app ), - os.path.join( relative_install_dir, name ), - repository, - repository_tools_tups ) + dmh.install_data_managers( trans.app.config.shed_data_manager_config_file, + irmm_metadata_dict, + repository.get_shed_config_dict( trans.app ), + os.path.join( relative_install_dir, name ), + repository, + repository_tools_tups ) if 'repository_dependencies' in irmm_metadata_dict or 'tool_dependencies' in irmm_metadata_dict: new_repository_dependencies_dict = irmm_metadata_dict.get( 'repository_dependencies', {} ) new_repository_dependencies = new_repository_dependencies_dict.get( 'repository_dependencies', [] ) @@ -2000,7 +1980,7 @@ encoded_relative_install_dir=encoded_relative_install_dir, encoded_tool_dependencies_dict=encoded_tool_dependencies_dict, message=message, - status = status ) + status=status ) return self.install_tool_dependencies_with_update( trans, **new_kwd ) # Updates received did not include any newly defined repository dependencies or newly defined # tool dependencies that need to be installed. https://bitbucket.org/galaxy/galaxy-central/commits/13cc751d07ed/ Changeset: 13cc751d07ed User: dannon Date: 2015-03-03 01:51:40+00:00 Summary: One more bugfix in admin_toolshed / undefined var. Affected #: 1 file diff -r 8af2b8d5c8cd1ab84021a7e1197b7d38d946b62f -r 13cc751d07ed98a6c0ebbd781a8c6319a7f8e1f9 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -589,7 +589,6 @@ encoded_updated_metadata = kwd.get( 'encoded_updated_metadata', None ) message = escape( kwd.get( 'message', '' ) ) status = kwd.get( 'status', 'done' ) - install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) ) if 'install_tool_dependencies_with_update_button' in kwd: # Now that the user has chosen whether to install tool dependencies or not, we can # update the repository record with the changes in the updated revision. @@ -601,7 +600,7 @@ updated_metadata_dict=updated_metadata, updated_changeset_revision=updating_to_changeset_revision, updated_ctx_rev=updating_to_ctx_rev ) - if includes_tool_dependencies: + if tool_dependencies_dict: tool_dependencies = tool_dependency_util.create_tool_dependency_objects( trans.app, repository, relative_install_dir, 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.
participants (1)
-
commits-noreply@bitbucket.org