3 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/09c5a80bac6f/ changeset: 09c5a80bac6f user: smcmanus date: 2012-10-15 23:29:29 summary: Added /api/folders. The api_folders configuration variable controls access to it (and is False by default). affected #: 6 files diff -r 399e97a26d027135493b9a8bc086d495af190abf -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -233,6 +233,11 @@ self.amqp[k] = v self.biostar = kwargs.get( 'biostar', None ) self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) ) + # Experimental: This will not be enabled by default and will hide + # nonproduction code. + # The api_folders refers to whether the API exposes + self.api_folders = string_as_bool( kwargs.get( 'api_folders', False ) ) + def __read_tool_job_config( self, global_conf_parser, section, key ): try: tool_runners_config = global_conf_parser.items( section ) diff -r 399e97a26d027135493b9a8bc086d495af190abf -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 lib/galaxy/webapps/galaxy/api/libraries.py --- a/lib/galaxy/webapps/galaxy/api/libraries.py +++ b/lib/galaxy/webapps/galaxy/api/libraries.py @@ -20,6 +20,7 @@ GET /api/libraries/deleted Displays a collection (list) of libraries. """ + log.debug( "LibrariesController.index: enter" ) query = trans.sa_session.query( trans.app.model.Library ) deleted = util.string_as_bool( deleted ) if deleted: @@ -53,6 +54,7 @@ GET /api/libraries/deleted/{encoded_library_id} Displays information about a library. """ + log.debug( "LibraryContentsController.show: enter" ) library_id = id deleted = util.string_as_bool( deleted ) params = util.Params( kwd ) diff -r 399e97a26d027135493b9a8bc086d495af190abf -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 lib/galaxy/webapps/galaxy/api/library_contents.py --- a/lib/galaxy/webapps/galaxy/api/library_contents.py +++ b/lib/galaxy/webapps/galaxy/api/library_contents.py @@ -13,6 +13,7 @@ class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems ): @web.expose_api + # TODO: Add parameter to only get top level of datasets/subfolders. def index( self, trans, library_id, **kwd ): """ GET /api/libraries/{encoded_library_id}/contents diff -r 399e97a26d027135493b9a8bc086d495af190abf -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 lib/galaxy/webapps/galaxy/buildapp.py --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -60,6 +60,10 @@ # Add the web API webapp.add_api_controllers( 'galaxy.webapps.galaxy.api', app ) + # The /folders section is experimental at this point: + log.debug( "app.config.api_folders: %s" % app.config.api_folders ) + if app.config.api_folders: + webapp.api_mapper.resource( 'folder', 'folders', path_prefix='/api' ) webapp.api_mapper.resource( 'content', 'contents', controller='library_contents', diff -r 399e97a26d027135493b9a8bc086d495af190abf -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 lib/galaxy/webapps/galaxy/controllers/library_common.py --- a/lib/galaxy/webapps/galaxy/controllers/library_common.py +++ b/lib/galaxy/webapps/galaxy/controllers/library_common.py @@ -317,6 +317,8 @@ status='done' ) # If not inheritable info_association, redirect to the library. message = "The new folder named '%s' has been added to the data library." % new_folder.name + # SM: This is the second place where the API controller would + # reference the library id: return trans.response.send_redirect( web.url_for( controller='library_common', action='browse_library', cntrller=cntrller, diff -r 399e97a26d027135493b9a8bc086d495af190abf -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 scripts/api/library_create_folder.py --- a/scripts/api/library_create_folder.py +++ b/scripts/api/library_create_folder.py @@ -15,6 +15,7 @@ try: data[ 'description' ] = sys.argv[5] except IndexError: + print "Unable to set description; using empty description in its place" data[ 'description' ] = '' submit( sys.argv[1], sys.argv[2], data ) https://bitbucket.org/galaxy/galaxy-central/changeset/3c7ad9558428/ changeset: 3c7ad9558428 user: smcmanus date: 2012-10-15 23:42:55 summary: Merge affected #: 42 files diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/datatypes/assembly.py --- a/lib/galaxy/datatypes/assembly.py +++ b/lib/galaxy/datatypes/assembly.py @@ -191,7 +191,7 @@ if long_reads: gen_msg = gen_msg + ' Long Reads' if len(gen_msg) > 0: - gen_msg = 'Uses: ' + gen_msg + gen_msg = 'Uses: ' + gen_msg except: log.debug( "Velveth could not read Log file in %s" % efp) log.debug( "Velveth log info %s" % gen_msg) diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/jobs/handler.py --- a/lib/galaxy/jobs/handler.py +++ b/lib/galaxy/jobs/handler.py @@ -430,7 +430,7 @@ if ( None != job.get_job_runner_name() ): runner_name = (job.get_job_runner_name().split(":",1))[0] if ( isinstance( job, model.Job ) ): - log.debug( "stopping job %d in %s runner" %( job.get_id(), runner_name ) ) + log.debug( "stopping job %d in %s runner" %( job.get_id(), runner_name ) ) elif ( isinstance( job, model.Task ) ): log.debug( "Stopping job %d, task %d in %s runner" % ( job.get_job().get_id(), job.get_id(), runner_name ) ) diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/model/migrate/versions/0033_published_cols_for_histories_and_workflows.py --- a/lib/galaxy/model/migrate/versions/0033_published_cols_for_histories_and_workflows.py +++ b/lib/galaxy/model/migrate/versions/0033_published_cols_for_histories_and_workflows.py @@ -15,87 +15,87 @@ db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) ) def upgrade(): - print __doc__ - metadata.reflect() + print __doc__ + metadata.reflect() - # Create published column in history table. - History_table = Table( "history", metadata, autoload=True ) - c = Column( "published", Boolean, index=True ) - try: - c.create( History_table ) - assert c is History_table.c.published - except Exception, e: - print "Adding published column to history table failed: %s" % str( e ) - log.debug( "Adding published column to history table failed: %s" % str( e ) ) + # Create published column in history table. + History_table = Table( "history", metadata, autoload=True ) + c = Column( "published", Boolean, index=True ) + try: + c.create( History_table ) + assert c is History_table.c.published + except Exception, e: + print "Adding published column to history table failed: %s" % str( e ) + log.debug( "Adding published column to history table failed: %s" % str( e ) ) - # Create index for published column in history table. - try: - i = Index( "ix_history_published", History_table.c.published ) - i.create() - except: - # Mysql doesn't have a named index, but alter should work - History_table.c.published.alter( unique=False ) + # Create index for published column in history table. + try: + i = Index( "ix_history_published", History_table.c.published ) + i.create() + except: + # Mysql doesn't have a named index, but alter should work + History_table.c.published.alter( unique=False ) - # Create published column in stored workflows table. - StoredWorkflow_table = Table( "stored_workflow", metadata, autoload=True ) - c = Column( "published", Boolean, index=True ) - try: - c.create( StoredWorkflow_table ) - assert c is StoredWorkflow_table.c.published - except Exception, e: - print "Adding published column to stored_workflow table failed: %s" % str( e ) - log.debug( "Adding published column to stored_workflow table failed: %s" % str( e ) ) + # Create published column in stored workflows table. + StoredWorkflow_table = Table( "stored_workflow", metadata, autoload=True ) + c = Column( "published", Boolean, index=True ) + try: + c.create( StoredWorkflow_table ) + assert c is StoredWorkflow_table.c.published + except Exception, e: + print "Adding published column to stored_workflow table failed: %s" % str( e ) + log.debug( "Adding published column to stored_workflow table failed: %s" % str( e ) ) - # Create index for published column in stored workflows table. - try: - i = Index( "ix_stored_workflow_published", StoredWorkflow_table.c.published ) - i.create() - except: - # Mysql doesn't have a named index, but alter should work - StoredWorkflow_table.c.published.alter( unique=False ) + # Create index for published column in stored workflows table. + try: + i = Index( "ix_stored_workflow_published", StoredWorkflow_table.c.published ) + i.create() + except: + # Mysql doesn't have a named index, but alter should work + StoredWorkflow_table.c.published.alter( unique=False ) - # Create importable column in page table. - Page_table = Table( "page", metadata, autoload=True ) - c = Column( "importable", Boolean, index=True ) - try: - c.create( Page_table ) - assert c is Page_table.c.importable - except Exception, e: - print "Adding importable column to page table failed: %s" % str( e ) - log.debug( "Adding importable column to page table failed: %s" % str( e ) ) - - # Create index for importable column in page table. - try: - i = Index( "ix_page_importable", Page_table.c.importable ) - i.create() - except: - # Mysql doesn't have a named index, but alter should work - Page_table.c.importable.alter( unique=False ) + # Create importable column in page table. + Page_table = Table( "page", metadata, autoload=True ) + c = Column( "importable", Boolean, index=True ) + try: + c.create( Page_table ) + assert c is Page_table.c.importable + except Exception, e: + print "Adding importable column to page table failed: %s" % str( e ) + log.debug( "Adding importable column to page table failed: %s" % str( e ) ) + + # Create index for importable column in page table. + try: + i = Index( "ix_page_importable", Page_table.c.importable ) + i.create() + except: + # Mysql doesn't have a named index, but alter should work + Page_table.c.importable.alter( unique=False ) def downgrade(): - metadata.reflect() + metadata.reflect() - # Drop published column from history table. - History_table = Table( "history", metadata, autoload=True ) - try: - History_table.c.published.drop() - except Exception, e: - print "Dropping column published from history table failed: %s" % str( e ) - log.debug( "Dropping column published from history table failed: %s" % str( e ) ) + # Drop published column from history table. + History_table = Table( "history", metadata, autoload=True ) + try: + History_table.c.published.drop() + except Exception, e: + print "Dropping column published from history table failed: %s" % str( e ) + log.debug( "Dropping column published from history table failed: %s" % str( e ) ) - # Drop published column from stored_workflow table. - StoredWorkflow_table = Table( "stored_workflow", metadata, autoload=True ) - try: - StoredWorkflow_table.c.published.drop() - except Exception, e: - print "Dropping column published from stored_workflow table failed: %s" % str( e ) - log.debug( "Dropping column published from stored_workflow table failed: %s" % str( e ) ) - + # Drop published column from stored_workflow table. + StoredWorkflow_table = Table( "stored_workflow", metadata, autoload=True ) + try: + StoredWorkflow_table.c.published.drop() + except Exception, e: + print "Dropping column published from stored_workflow table failed: %s" % str( e ) + log.debug( "Dropping column published from stored_workflow table failed: %s" % str( e ) ) + # Drop importable column from page table. - Page_table = Table( "page", metadata, autoload=True ) - try: - Page_table.c.importable.drop() - except Exception, e: - print "Dropping column importable from page table failed: %s" % str( e ) - log.debug( "Dropping column importable from page table failed: %s" % str( e ) ) \ No newline at end of file + Page_table = Table( "page", metadata, autoload=True ) + try: + Page_table.c.importable.drop() + except Exception, e: + print "Dropping column importable from page table failed: %s" % str( e ) + log.debug( "Dropping column importable from page table failed: %s" % str( e ) ) \ No newline at end of file diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py --- a/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py +++ b/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py @@ -69,7 +69,7 @@ # Add column. deleted_column.create( Visualiation_table ) assert deleted_column is Visualiation_table.c.deleted - + # Fill column with default value. cmd = "UPDATE visualization SET deleted = %s" % default_false db_session.execute( cmd ) @@ -83,7 +83,7 @@ except Exception, e: print "Adding index 'ix_visualization_deleted' failed: %s" % str( e ) log.debug( "Adding index 'ix_visualization_deleted' failed: %s" % str( e ) ) - + try: # Add column. importable_column.create( Visualiation_table ) @@ -102,10 +102,10 @@ except Exception, e: print "Adding index 'ix_visualization_importable' failed: %s" % str( e ) log.debug( "Adding index 'ix_visualization_importable' failed: %s" % str( e ) ) - + try: - slug_column.create( Visualiation_table ) - assert slug_column is Visualiation_table.c.slug + slug_column.create( Visualiation_table ) + assert slug_column is Visualiation_table.c.slug except Exception, e: print "Adding slug column to visualization table failed: %s" % str( e ) log.debug( "Adding slug column to visualization table failed: %s" % str( e ) ) @@ -121,7 +121,7 @@ except Exception, e: print "Adding index 'ix_visualization_slug' failed: %s" % str( e ) log.debug( "Adding index 'ix_visualization_slug' failed: %s" % str( e ) ) - + try: # Add column. published_column.create( Visualiation_table ) @@ -180,25 +180,25 @@ # Drop columns for supporting sharing from visualization table. try: - Visualiation_table.c.deleted.drop() + Visualiation_table.c.deleted.drop() except Exception, e: print "Dropping deleted column from visualization table failed: %s" % str( e ) log.debug( "Dropping deleted column from visualization table failed: %s" % str( e ) ) try: - Visualiation_table.c.importable.drop() + Visualiation_table.c.importable.drop() except Exception, e: print "Dropping importable column from visualization table failed: %s" % str( e ) log.debug( "Dropping importable column from visualization table failed: %s" % str( e ) ) try: - Visualiation_table.c.slug.drop() + Visualiation_table.c.slug.drop() except Exception, e: print "Dropping slug column from visualization table failed: %s" % str( e ) log.debug( "Dropping slug column from visualization table failed: %s" % str( e ) ) try: - Visualiation_table.c.published.drop() + Visualiation_table.c.published.drop() except Exception, e: print "Dropping published column from visualization table failed: %s" % str( e ) log.debug( "Dropping published column from visualization table failed: %s" % str( e ) ) diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/model/migrate/versions/0051_imported_col_for_jobs_table.py --- a/lib/galaxy/model/migrate/versions/0051_imported_col_for_jobs_table.py +++ b/lib/galaxy/model/migrate/versions/0051_imported_col_for_jobs_table.py @@ -14,35 +14,35 @@ db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) ) def upgrade(): - print __doc__ - metadata.reflect() + print __doc__ + metadata.reflect() - # Create and initialize imported column in job table. - Jobs_table = Table( "job", metadata, autoload=True ) - c = Column( "imported", Boolean, default=False, index=True ) - try: - # Create - c.create( Jobs_table ) - assert c is Jobs_table.c.imported - - # Initialize. - if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite': - default_false = "0" - elif migrate_engine.name == 'postgres': - default_false = "false" - db_session.execute( "UPDATE job SET imported=%s" % default_false ) - - except Exception, e: - print "Adding imported column to job table failed: %s" % str( e ) - log.debug( "Adding imported column to job table failed: %s" % str( e ) ) + # Create and initialize imported column in job table. + Jobs_table = Table( "job", metadata, autoload=True ) + c = Column( "imported", Boolean, default=False, index=True ) + try: + # Create + c.create( Jobs_table ) + assert c is Jobs_table.c.imported + + # Initialize. + if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite': + default_false = "0" + elif migrate_engine.name == 'postgres': + default_false = "false" + db_session.execute( "UPDATE job SET imported=%s" % default_false ) + + except Exception, e: + print "Adding imported column to job table failed: %s" % str( e ) + log.debug( "Adding imported column to job table failed: %s" % str( e ) ) def downgrade(): - metadata.reflect() + metadata.reflect() - # Drop imported column from job table. - Jobs_table = Table( "job", metadata, autoload=True ) - try: - Jobs_table.c.imported.drop() - except Exception, e: - print "Dropping column imported from job table failed: %s" % str( e ) - log.debug( "Dropping column imported from job table failed: %s" % str( e ) ) \ No newline at end of file + # Drop imported column from job table. + Jobs_table = Table( "job", metadata, autoload=True ) + try: + Jobs_table.c.imported.drop() + except Exception, e: + print "Dropping column imported from job table failed: %s" % str( e ) + log.debug( "Dropping column imported from job table failed: %s" % str( e ) ) \ No newline at end of file diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/tools/actions/index_genome.py --- a/lib/galaxy/tools/actions/index_genome.py +++ b/lib/galaxy/tools/actions/index_genome.py @@ -22,8 +22,8 @@ job.user_id = incoming['user'] start_job_state = job.state # should be job.states.NEW job.state = job.states.WAITING # we need to set job state to something other than NEW, - # or else when tracking jobs in db it will be picked up - # before we have added input / output parameters + # or else when tracking jobs in db it will be picked up + # before we have added input / output parameters trans.sa_session.add( job ) # Create dataset that will serve as archive. diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/visualization/data_providers/basic.py --- a/lib/galaxy/visualization/data_providers/basic.py +++ b/lib/galaxy/visualization/data_providers/basic.py @@ -125,6 +125,7 @@ except: return None return val + returning_data = False f = open( self.original_dataset.file_name ) #TODO: add f.seek if given fptr in kwargs for count, line in enumerate( f ): @@ -134,6 +135,8 @@ continue if ( count - start_val ) >= max_vals: break + + returning_data = True fields = line.split() fields_len = len( fields ) @@ -162,20 +165,24 @@ response[ 'endpoint' ] = dict( last_line=( count - 1 ), file_ptr=f.tell() ) f.close() + if not returning_data: return None + for index, meta in enumerate( response[ 'meta' ] ): column_type = column_types[ index ] + count = meta[ 'count' ] - if( column_type == 'float' or column_type == 'int' ): - count = meta[ 'count' ] + if( ( column_type == 'float' or column_type == 'int' ) + and count ): meta[ 'mean' ] = float( meta[ 'sum' ] ) / count sorted_data = sorted( response[ 'data' ][ index ] ) # even data count - - middle_index = count / 2 - 1 + middle_index = ( count / 2 ) - 1 if count % 2 == 0: meta[ 'median' ] = sum( sorted_data[ middle_index : ( middle_index + 1 ) ] ) / 2.0 else: meta[ 'median' ] = sorted_data[ middle_index ] + # ugh ... metadata_data_lines is not a reliable source; hafta have an EOF return response diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/webapps/galaxy/controllers/data_admin.py --- a/lib/galaxy/webapps/galaxy/controllers/data_admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/data_admin.py @@ -102,15 +102,15 @@ @web.expose @web.require_admin def index_build( self, trans, **kwd ): - """Index a previously downloaded genome.""" + """Index a previously downloaded genome.""" params = util.Params( kwd ) path = os.path.abspath( params.get( 'path', None ) ) indexes = [ params.get( 'indexes', None ) ] dbkey = params.get( 'dbkey', None ) intname = params.get( 'longname', None ) - indexjob = trans.app.job_manager.deferred_job_queue.plugins['GenomeIndexPlugin'].create_job( trans, path, indexes, dbkey, intname ) - return indexjob - + indexjob = trans.app.job_manager.deferred_job_queue.plugins['GenomeIndexPlugin'].create_job( trans, path, indexes, dbkey, intname ) + return indexjob + @web.expose @web.require_admin def download_build( self, trans, **kwd ): diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/webapps/galaxy/controllers/forms.py --- a/lib/galaxy/webapps/galaxy/controllers/forms.py +++ b/lib/galaxy/webapps/galaxy/controllers/forms.py @@ -596,7 +596,7 @@ index = 1 for row in reader: if len(row) < 7: # ignore bogus rows - continue + continue options = row[5].split(',') if len(row) >= 8: fields.append( { 'name': '%i_field_name' % index, diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc lib/galaxy/webapps/galaxy/controllers/ucsc_proxy.py --- a/lib/galaxy/webapps/galaxy/controllers/ucsc_proxy.py +++ b/lib/galaxy/webapps/galaxy/controllers/ucsc_proxy.py @@ -156,4 +156,4 @@ '<INPUT TYPE=RADIO NAME="hgta_regionType" VALUE="range" onClick="regionType=\'range\';">' : '<INPUT TYPE=RADIO NAME="hgta_regionType" VALUE="range" onClick="regionType=\'range\';" CHECKED>', "<OPTION VALUE=bed>" : "<OPTION VALUE=bed SELECTED>" , '<INPUT TYPE=SUBMIT NAME="hgta_doSchema" VALUE="describe table schema">' : '<INPUT TYPE=SUBMIT NAME="hgta_doSchema" VALUE="describe table schema" onClick="changeTarget(\'_blank\')" onMouseOut="changeTarget(\'_self\')">' - } + } diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/packed/templates/compiled/template-visualization-chartSettings.js --- a/static/scripts/packed/templates/compiled/template-visualization-chartSettings.js +++ b/static/scripts/packed/templates/compiled/template-visualization-chartSettings.js @@ -1,1 +1,3 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-chartSettings"]=b(function(f,m,e,l,k){e=e||f.helpers;var i="",c,h,g="function",j=this.escapeExpression,n=this;function d(p,o){return"checked"}i+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n </p>\n \n <div id="maxDataPoints" class="form-input numeric-slider-input">\n <label for="maxDataPoints">Maximum data points allowed on graph: </label>\n <div class="slider-output">';h=e.maxDataPoints;if(h){c=h.call(m,{hash:{}})}else{c=m.maxDataPoints;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div style="clear: both;"></div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Change the maximum number of data points displayable on this graph (higher values will\n load significantly slower)\n </p>\n </div>\n\n <div id="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">';h=e.datapointSize;if(h){c=h.call(m,{hash:{}})}else{c=m.datapointSize;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n </div>\n\n <div id="entryAnimDuration" class="form-input checkbox-input">\n <label for="animated">Animate graph transitions?: </label>\n <input type="checkbox" id="animated" class="checkbox control" value="';c=m.entryAnimDuration;c=e["if"].call(m,c,{hash:{},inverse:n.noop,fn:n.program(1,d,k)});if(c||c===0){i+=c}i+='" />\n <p class="form-help help-text-small">\n Uncheck this to disable the animations used on the graph\n </p>\n </div>\n\n <div id="width" class="form-input numeric-slider-input">\n <label for="width">Graph width: </label>\n <div class="slider-output">';h=e.width;if(h){c=h.call(m,{hash:{}})}else{c=m.width;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including graph margins and axes)\n </p>\n </div>\n\n <div id="height" class="form-input numeric-slider-input">\n <label for="height">Graph height: </label>\n <div class="slider-output">';h=e.height;if(h){c=h.call(m,{hash:{}})}else{c=m.height;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including graph margins and axes)\n </p>\n </div>\n\n <div id="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="';h=e.xLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.xLabel;c=typeof c===g?c():c}i+=j(c)+'" />\n <p class="form-help help-text-small"></p>\n </div>\n\n <div id="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="';h=e.yLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.yLabel;c=typeof c===g?c():c}i+=j(c)+'" />\n <p class="form-help help-text-small"></p>\n </div>\n\n <input id="render-button" type="button" value="Draw" />';return i})})(); \ No newline at end of file +<<<<<<< local +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-chartSettings"]=b(function(f,m,e,l,k){e=e||f.helpers;var i="",c,h,g="function",j=this.escapeExpression,n=this;function d(p,o){return' checked="true"'}i+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n </p>\n \n <div id="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">';h=e.datapointSize;if(h){c=h.call(m,{hash:{}})}else{c=m.datapointSize;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n </div>\n\n <div id="animDuration" class="form-input checkbox-input">\n <label for="animated">Animate graph transitions?: </label>\n <input type="checkbox" id="animated"\n class="checkbox control"';c=m.animDuration;c=e["if"].call(m,c,{hash:{},inverse:n.noop,fn:n.program(1,d,k)});if(c||c===0){i+=c}i+=' />\n <p class="form-help help-text-small">\n Uncheck this to disable the animations used on the graph\n </p>\n </div>\n\n <div id="width" class="form-input numeric-slider-input">\n <label for="width">Graph width: </label>\n <div class="slider-output">';h=e.width;if(h){c=h.call(m,{hash:{}})}else{c=m.width;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including graph margins and axes)\n </p>\n </div>\n\n <div id="height" class="form-input numeric-slider-input">\n <label for="height">Graph height: </label>\n <div class="slider-output">';h=e.height;if(h){c=h.call(m,{hash:{}})}else{c=m.height;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including graph margins and axes)\n </p>\n </div>\n\n <div id="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="';h=e.xLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.xLabel;c=typeof c===g?c():c}i+=j(c)+'" />\n <p class="form-help help-text-small"></p>\n </div>\n\n <div id="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="';h=e.yLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.yLabel;c=typeof c===g?c():c}i+=j(c)+'" />\n <p class="form-help help-text-small"></p>\n </div>\n\n <input id="render-button" type="button" value="Draw" />';return i})})();======= +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-chartSettings"]=b(function(f,m,e,l,k){e=e||f.helpers;var i="",c,h,g="function",j=this.escapeExpression,n=this;function d(p,o){return"checked"}i+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n </p>\n \n <div id="maxDataPoints" class="form-input numeric-slider-input">\n <label for="maxDataPoints">Maximum data points allowed on graph: </label>\n <div class="slider-output">';h=e.maxDataPoints;if(h){c=h.call(m,{hash:{}})}else{c=m.maxDataPoints;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div style="clear: both;"></div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Change the maximum number of data points displayable on this graph (higher values will\n load significantly slower)\n </p>\n </div>\n\n <div id="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">';h=e.datapointSize;if(h){c=h.call(m,{hash:{}})}else{c=m.datapointSize;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n </div>\n\n <div id="entryAnimDuration" class="form-input checkbox-input">\n <label for="animated">Animate graph transitions?: </label>\n <input type="checkbox" id="animated" class="checkbox control" value="';c=m.entryAnimDuration;c=e["if"].call(m,c,{hash:{},inverse:n.noop,fn:n.program(1,d,k)});if(c||c===0){i+=c}i+='" />\n <p class="form-help help-text-small">\n Uncheck this to disable the animations used on the graph\n </p>\n </div>\n\n <div id="width" class="form-input numeric-slider-input">\n <label for="width">Graph width: </label>\n <div class="slider-output">';h=e.width;if(h){c=h.call(m,{hash:{}})}else{c=m.width;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including graph margins and axes)\n </p>\n </div>\n\n <div id="height" class="form-input numeric-slider-input">\n <label for="height">Graph height: </label>\n <div class="slider-output">';h=e.height;if(h){c=h.call(m,{hash:{}})}else{c=m.height;c=typeof c===g?c():c}i+=j(c)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including graph margins and axes)\n </p>\n </div>\n\n <div id="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="';h=e.xLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.xLabel;c=typeof c===g?c():c}i+=j(c)+'" />\n <p class="form-help help-text-small"></p>\n </div>\n\n <div id="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="';h=e.yLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.yLabel;c=typeof c===g?c():c}i+=j(c)+'" />\n <p class="form-help help-text-small"></p>\n </div>\n\n <input id="render-button" type="button" value="Draw" />';return i})})();>>>>>>> other diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/packed/utils/LazyDataLoader.js --- a/static/scripts/packed/utils/LazyDataLoader.js +++ b/static/scripts/packed/utils/LazyDataLoader.js @@ -1,1 +1,3 @@ -function LazyDataLoader(b){var a=this;jQuery.extend(a,LoggableMixin);jQuery.extend(a,{total:undefined,url:undefined,currentIntervalId:undefined,loadedPartialEvent:undefined,loadedAllEvent:undefined,data:[],delay:500,start:0,size:1000,initialize:function(c){jQuery.extend(a,c);if(c.hasOwnProperty("initialize")){c.initialize.call(a,c)}if(!a.total){throw (a+" requires a total (total size of the data)")}if(!a.url){throw (a+" requires a url")}this.log(this+" initialized:",a)},buildUrl:function(d,c){return a.url+"&"+jQuery.param({start_val:d,max_vals:c})},ajaxErrorFn:function(e,c,d){alert(a+" ERROR:"+c+"\n"+d)},load:function(d){function c(g,f){a.log(a+".loadHelper, start:",g,"size:",f);var e=a.buildUrl(g,f);a.log("\t url:",e);jQuery.ajax({url:a.buildUrl(g,f),dataType:"json",error:function(j,h,i){a.log("\t ajax error, status:",h,"error:",i);if(a.currentIntervalId){clearInterval(a.currentIntervalId)}a.ajaxErrorFn(j,h,i)},success:function(h){var i=g+f,j=Math.min(a.total-i,a.size);a.log("\t ajax success, next:",i,"remainder:",j);a.data.push(h);if(a.loadedPartialEvent){a.log("\t firing:",a.loadedPartialEvent);$(a).trigger(a.loadedPartialEvent,h,g,f)}if(j>0){a.currentIntervalId=setTimeout(function(){c(i,j)},a.delay);a.log("\t currentIntervalId:",a.currentIntervalId)}else{a.log(a+".loadHelper, has finished:",a.data);if(a.loadedAllEvent){a.log("\t firing:",a.loadedAllEvent);$(a).trigger(a.loadedAllEvent,a.data,a.total)}if(d){d(a.data)}}}})}c(a.start,Math.min(a.total,a.size))},toString:function(){return"LazyDataLoader"}});a.initialize(b);return a}; \ No newline at end of file +<<<<<<< local +function LazyDataLoader(c){var a=this,d="loaded.new",b="complete";ERROR_EVENT="error";jQuery.extend(a,LoggableMixin);jQuery.extend(a,{total:undefined,url:undefined,currentIntervalId:undefined,data:[],delay:500,start:0,size:1000,initialize:function(e){jQuery.extend(a,e);if(e.hasOwnProperty("initialize")){e.initialize.call(a,e)}this.log(this+" initialized:",a)},buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})},ajaxErrorFn:function(g,e,f){},load:function(h){this.log(this+".load");if(!a.url){throw (a+" requires a url")}if(this.total===null){this.log("\t total is null (will load all)")}else{this.log("\t total:",this.total)}var g=a.size;if((a.total!==null)&&(a.total<a.size)){g=a.total}a.log(a+"\t beginning recursion");f(a.start,g);function f(k,j){a.log(a+".loadHelper, start:",k,"size:",j);var i=a.buildUrl(k,j);a.log("\t url:",i);jQuery.ajax({url:a.buildUrl(k,j),dataType:"json",error:function(n,l,m){a.log("\t ajax error, status:",l,"error:",m);if(a.currentIntervalId){clearInterval(a.currentIntervalId)}$(a).trigger(ERROR_EVENT,[l,m]);a.ajaxErrorFn(n,l,m)},success:function(l){a.log("\t ajax success, response:",l,"next:",m,"remainder:",n);if(l!==null){a.data.push(l);$(a).trigger(d,[l,k,j]);var m=k+j,n=a.size;if(a.total!==null){n=Math.min(a.total-m,a.size)}a.log("\t next recursion, start:",m,"size:",n);if(a.total===null||n>0){a.currentIntervalId=setTimeout(function(){f(m,n)},a.delay);a.log("\t currentIntervalId:",a.currentIntervalId)}else{e()}}else{e()}}})}function e(){a.log(a+".loadHelper, has finished:",a.data);$(a).trigger(b,[a.data,a.total]);if(h){h(a.data)}}},toString:function(){return"LazyDataLoader"}});a.initialize(c);return a};======= +function LazyDataLoader(b){var a=this;jQuery.extend(a,LoggableMixin);jQuery.extend(a,{total:undefined,url:undefined,currentIntervalId:undefined,loadedPartialEvent:undefined,loadedAllEvent:undefined,data:[],delay:500,start:0,size:1000,initialize:function(c){jQuery.extend(a,c);if(c.hasOwnProperty("initialize")){c.initialize.call(a,c)}if(!a.total){throw (a+" requires a total (total size of the data)")}if(!a.url){throw (a+" requires a url")}this.log(this+" initialized:",a)},buildUrl:function(d,c){return a.url+"&"+jQuery.param({start_val:d,max_vals:c})},ajaxErrorFn:function(e,c,d){alert(a+" ERROR:"+c+"\n"+d)},load:function(d){function c(g,f){a.log(a+".loadHelper, start:",g,"size:",f);var e=a.buildUrl(g,f);a.log("\t url:",e);jQuery.ajax({url:a.buildUrl(g,f),dataType:"json",error:function(j,h,i){a.log("\t ajax error, status:",h,"error:",i);if(a.currentIntervalId){clearInterval(a.currentIntervalId)}a.ajaxErrorFn(j,h,i)},success:function(h){var i=g+f,j=Math.min(a.total-i,a.size);a.log("\t ajax success, next:",i,"remainder:",j);a.data.push(h);if(a.loadedPartialEvent){a.log("\t firing:",a.loadedPartialEvent);$(a).trigger(a.loadedPartialEvent,h,g,f)}if(j>0){a.currentIntervalId=setTimeout(function(){c(i,j)},a.delay);a.log("\t currentIntervalId:",a.currentIntervalId)}else{a.log(a+".loadHelper, has finished:",a.data);if(a.loadedAllEvent){a.log("\t firing:",a.loadedAllEvent);$(a).trigger(a.loadedAllEvent,a.data,a.total)}if(d){d(a.data)}}}})}c(a.start,Math.min(a.total,a.size))},toString:function(){return"LazyDataLoader"}});a.initialize(b);return a};>>>>>>> other diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/packed/viz/scatterplot.js --- a/static/scripts/packed/viz/scatterplot.js +++ b/static/scripts/packed/viz/scatterplot.js @@ -1,1 +1,3 @@ -define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui-1.8.23.custom.min"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.debugging=true;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:10000,datapointSize:4,entryAnimDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.entryAnimDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.entryAnimDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(){var r=d3.select(this);r.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",0).attr("y2",r.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",r.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}this.apiDatasetsURL=c.apiDatasetsURL;this.chartConfig=c.chartConfig||{};this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types.split(", "),function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:f,name:e})}d.allColumns.push({index:f,name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");return this},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={maxDataPoints:{min:1000,max:30000,step:100},datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");c.log("slider set up","this:",h,"slider:",i,"id",j);function f(){var l=$(this),k=l.slider("value");g.text(k);c.chartConfig[j]=k}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"click #render-button":"renderPlot","click #include-id-checkbox":"toggleThirdColumnSelector"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},getColumnVals:function(){var c={};this.$el.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},fetchData:function(f,d){var c=this,e=this.apiDatasetsURL+"/"+this.dataset.id+"?data_type=raw_data&"+jQuery.param(f);this.log("url:",e);this.showLoadingIndicator("Fetching data...",function(){jQuery.ajax({url:e,dataType:"json",success:d,error:function(i,g,h){c.hideLoadingIndicator();alert("ERROR:"+g+"\n"+h)}})})},renderPlot:function(){var e=this,g=this.getColumnVals(),f=[];this.log("columnSelections:",g);this.log(g.X.val,g.Y.val);this.xColIndex=g.X.colIndex;this.yColIndex=g.Y.colIndex;f=[this.xColIndex,this.yColIndex];if($("#include-id-checkbox").attr("checked")){f.push(g.ID.colIndex)}var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();this.chartConfig.xLabel=(d==="X")?(g.X.colName):(d);this.chartConfig.yLabel=(c==="Y")?(g.Y.colName):(c);e.plot.updateConfig(this.chartConfig,false);var h={columns:"["+f+"]"};this.fetchData(h,function(i){e.dataFetch=i;e.showLoadingIndicator("Rendering...",function(){e.plot.render(i.data,i.meta);e.renderStats(i.data,i.meta);e.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");e.hideLoadingIndicator()})})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.dataFetch.meta[0].count,yval:this.dataFetch.meta[1].count},{name:"Min",xval:this.dataFetch.meta[0].min,yval:this.dataFetch.meta[1].min},{name:"Max",xval:this.dataFetch.meta[0].max,yval:this.dataFetch.meta[1].max},{name:"Mean",xval:this.dataFetch.meta[0].mean,yval:this.dataFetch.meta[1].mean},{name:"Median",xval:this.dataFetch.meta[0].median,yval:this.dataFetch.meta[1].median}]}))},toString:function(){return"ScatterplotControlForm("+attributes.dataset.id+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}}); \ No newline at end of file +<<<<<<< local +define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui-1.8.23.custom.min"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.animDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(){var r=d3.select(this);r.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",0).attr("y2",r.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",r.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){if(this.logger){window.form=this}this.dataset=null;this.chartConfig=null;this.plot=null;this.loader=null;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null;this.initializeFromAttributes(c);this.initializeChart(c);this.initializeDataLoader(c)},initializeFromAttributes:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ")}this.log("dataset:",this.dataset);if(!c.apiDatasetsURL){throw ("ScatterplotView requires a apiDatasetsURL")}else{this.dataURL=c.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("this.dataURL:",this.dataURL)},initializeChart:function(c){this.chartConfig=c.chartConfig||{};if(this.logger){this.chartConfig.debugging=true}this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config},initializeDataLoader:function(d){var c=this;this.loader=new LazyDataLoader({logger:(this.logger)?(this.logger):(null),url:null,start:d.start||0,total:d.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})}});$(this.loader).bind("error",function(g,e,f){c.log("ERROR:",e,f);alert("ERROR fetching data:\n"+e+"\n"+f);c.hideLoadingIndicator()})},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types,function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:f,name:e})}d.allColumns.push({index:f,name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");return this},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");function f(){var l=$(this),k=l.slider("value");g.text(k)}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"click #include-id-checkbox":"toggleThirdColumnSelector","click #data-settings #render-button":"renderPlot","click #chart-settings #render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},renderPlot:function(){var c=this;c.data=null;c.meta=null;_.extend(this.chartConfig,this.getGraphSettings());this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("this.loader, url:",this.loader.url,"total:",this.loader.total);$(this.loader).bind("loaded.new",function(e,d){c.log(c+" loaded.new",d);c.postProcessDataFetchResponse(d);c.log("postprocessed data:",c.data,"meta:",c.meta);c.showLoadingIndicator("Rendering...",function(){c.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");c.plot.render(c.data,c.meta);c.renderStats(c.data,c.meta);c.hideLoadingIndicator()})});$(this.loader).bind("complete",function(d,e){c.log("complete",e);$(c.loader).unbind()});c.showLoadingIndicator("Fetching data...",function(){c.loader.load()})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var c=this;newGraphSettings=this.getGraphSettings();this.log("newGraphSettings:",newGraphSettings);_.extend(this.chartConfig,newGraphSettings);this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);if(c.data&&c.meta){c.showLoadingIndicator("Rendering...",function(){c.plot.render(c.data,c.meta);c.hideLoadingIndicator()})}else{this.renderPlot()}},postProcessDataFetchResponse:function(c){this.postProcessData(c.data);this.postProcessMeta(c.meta)},postProcessData:function(d){var c=this;if(c.data){_.each(d,function(f,e){c.data[e]=c.data[e].concat(f)})}else{c.data=d}},postProcessMeta:function(e){var c=this,d=this.dataset.metadata_column_types;if(c.meta){_.each(e,function(g,f){var k=c.meta[f],i=d[f];c.log(f+" postprocessing meta:",g);k.count+=(g.count)?(g.count):(0);c.log(f,"count:",k.count);if((i==="int")||(i==="float")){k.min=Math.min(g.min,k.min);k.max=Math.max(g.max,k.max);k.sum=g.sum+k.sum;k.mean=(k.count)?(k.sum/k.count):(null);var h=c.data[f].slice().sort(),j=Math.floor(h.length/2);if(h.length%2===0){k.median=((h[j]+h[(j+1)])/2)}else{k.median=h[j]}}})}else{c.meta=e;c.log("initial meta:",c.meta)}},getDataSettings:function(){var d=this.getColumnSelections(),c=[];this.log("columnSelections:",d);c=[d.X.colIndex,d.Y.colIndex];if(this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked")){c.push(d.ID.colIndex)}var e={data_type:"raw_data",columns:"["+c+"]"};this.log("params:",e);return e},getColumnSelections:function(){var c={};this.$dataSettingsPanel.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},getGraphSettings:function(){var e={},f=this.getColumnSelections();e.datapointSize=this.$chartSettingsPanel.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");e.width=this.$chartSettingsPanel.find("#width.numeric-slider-input").find(".slider").slider("value");e.height=this.$chartSettingsPanel.find("#height.numeric-slider-input").find(".slider").slider("value");var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();e.xLabel=(d==="X")?(f.X.colName):(d);e.yLabel=(c==="Y")?(f.Y.colName):(c);e.animDuration=10;if(this.$chartSettingsPanel.find("#animDuration.checkbox-input").is(":checked")){e.animDuration=500}this.log("graphSettings:",e);return e},toString:function(){return"ScatterplotControlForm("+this.dataset.id+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}});======= +define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui-1.8.23.custom.min"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.debugging=true;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:10000,datapointSize:4,entryAnimDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.entryAnimDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.entryAnimDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(){var r=d3.select(this);r.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",0).attr("y2",r.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",r.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}this.apiDatasetsURL=c.apiDatasetsURL;this.chartConfig=c.chartConfig||{};this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types.split(", "),function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:f,name:e})}d.allColumns.push({index:f,name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");return this},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={maxDataPoints:{min:1000,max:30000,step:100},datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");c.log("slider set up","this:",h,"slider:",i,"id",j);function f(){var l=$(this),k=l.slider("value");g.text(k);c.chartConfig[j]=k}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"click #render-button":"renderPlot","click #include-id-checkbox":"toggleThirdColumnSelector"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},getColumnVals:function(){var c={};this.$el.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},fetchData:function(f,d){var c=this,e=this.apiDatasetsURL+"/"+this.dataset.id+"?data_type=raw_data&"+jQuery.param(f);this.log("url:",e);this.showLoadingIndicator("Fetching data...",function(){jQuery.ajax({url:e,dataType:"json",success:d,error:function(i,g,h){c.hideLoadingIndicator();alert("ERROR:"+g+"\n"+h)}})})},renderPlot:function(){var e=this,g=this.getColumnVals(),f=[];this.log("columnSelections:",g);this.log(g.X.val,g.Y.val);this.xColIndex=g.X.colIndex;this.yColIndex=g.Y.colIndex;f=[this.xColIndex,this.yColIndex];if($("#include-id-checkbox").attr("checked")){f.push(g.ID.colIndex)}var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();this.chartConfig.xLabel=(d==="X")?(g.X.colName):(d);this.chartConfig.yLabel=(c==="Y")?(g.Y.colName):(c);e.plot.updateConfig(this.chartConfig,false);var h={columns:"["+f+"]"};this.fetchData(h,function(i){e.dataFetch=i;e.showLoadingIndicator("Rendering...",function(){e.plot.render(i.data,i.meta);e.renderStats(i.data,i.meta);e.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");e.hideLoadingIndicator()})})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.dataFetch.meta[0].count,yval:this.dataFetch.meta[1].count},{name:"Min",xval:this.dataFetch.meta[0].min,yval:this.dataFetch.meta[1].min},{name:"Max",xval:this.dataFetch.meta[0].max,yval:this.dataFetch.meta[1].max},{name:"Mean",xval:this.dataFetch.meta[0].mean,yval:this.dataFetch.meta[1].mean},{name:"Median",xval:this.dataFetch.meta[0].median,yval:this.dataFetch.meta[1].median}]}))},toString:function(){return"ScatterplotControlForm("+attributes.dataset.id+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}});>>>>>>> other diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/packed/viz/trackster/tracks.js --- a/static/scripts/packed/viz/trackster/tracks.js +++ b/static/scripts/packed/viz/trackster/tracks.js @@ -1,1 +1,1 @@ -define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ac,x,l,u,L,aa,i){var q=ac.extend;var Q=l.get_random_color;var ad=function(ae,ag,af){$.ajax({url:ae,data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(ah){show_modal("Select datasets for new tracks",ah,{Cancel:function(){hide_modal()},Add:function(){var ai=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var aj={data_type:"track_config",hda_ldda:"hda"},ak=$(this).val();if($(this).attr("name")!=="id"){aj.hda_ldda="ldda"}ai[ai.length]=$.ajax({url:ag+"/"+ak,data:aj,dataType:"json"})});$.when.apply($,ai).then(function(){var aj=(arguments[0] instanceof Array?$.map(arguments,function(ak){return ak[0]}):[arguments[0]]);af(aj)});hide_modal()}})}})};var W=function(ae){return("isResolved" in ae)};var n={};var k=function(ae,af){n[ae.attr("id")]=af};var m=function(ae,ag,ai,ah){ai=".group";var af={};n[ae.attr("id")]=ah;ae.bind("drag",{handle:"."+ag,relative:true},function(aq,ar){var ap=$(this),av=$(this).parent(),am=av.children(),ao=n[$(this).attr("id")],al,ak,at,aj,an;ak=$(this).parents(ai);if(ak.length!==0){at=ak.position().top;aj=at+ak.outerHeight();if(ar.offsetY<at){$(this).insertBefore(ak);var au=n[ak.attr("id")];au.remove_drawable(ao);au.container.add_drawable_before(ao,au);return}else{if(ar.offsetY>aj){$(this).insertAfter(ak);var au=n[ak.attr("id")];au.remove_drawable(ao);au.container.add_drawable(ao);return}}}ak=null;for(an=0;an<am.length;an++){al=$(am.get(an));at=al.position().top;aj=at+al.outerHeight();if(al.is(ai)&&this!==al.get(0)&&ar.offsetY>=at&&ar.offsetY<=aj){if(ar.offsetY-at<aj-ar.offsetY){al.find(".content-div").prepend(this)}else{al.find(".content-div").append(this)}if(ao.container){ao.container.remove_drawable(ao)}n[al.attr("id")].add_drawable(ao);return}}for(an=0;an<am.length;an++){al=$(am.get(an));if(ar.offsetY<al.position().top&&!(al.hasClass("reference-track")||al.hasClass("intro"))){break}}if(an===am.length){if(this!==am.get(an-1)){av.append(this);n[av.attr("id")].move_drawable(ao,an)}}else{if(this!==am.get(an)){$(this).insertBefore(am.get(an));n[av.attr("id")].move_drawable(ao,(ar.deltaY>0?an-1:an))}}}).bind("dragstart",function(){af["border-top"]=ae.css("border-top");af["border-bottom"]=ae.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(af)})};exports.moveable=m;var ab=16,G=9,D=20,A=100,I=12000,T=400,K=5000,w=100,o="There was an error in indexing this dataset. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",V="Ready for display",R=10,H=20;function X(af,ae){if(!ae){ae=0}var ag=Math.pow(10,ae);return Math.round(af*ag)/ag}var r=function(af,ae,ah){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=ah.name;this.view=af;this.container=ae;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ah.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ah.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ai){ai.stopPropagation()});var ag=this;this.container_div.hover(function(){ag.icons_div.show()},function(){ag.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ae){if(ae.content_visible){ae.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ae.hide_contents();ae.content_visible=false}else{ae.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ae.content_visible=true;ae.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(af){var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(){af.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ae()}}};$(window).bind("keypress.check_enter_esc",ag);show_modal("Configure",af.config.build_form(),{Cancel:ah,OK:ae})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ae){$(".bs-tooltip").remove();ae.remove()}}];q(r.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(){},to_dict:function(){},set_name:function(ae){this.old_name=this.name;this.name=ae;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ae=this.view;this.container_div.hide(0,function(){$(this).remove();ae.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(af,ak,aj,ai,ae,ah){var ag=this;this.action_icons[af]=$("<a/>").attr("href","javascript:void(0);").attr("title",ak).addClass("icon-button").addClass(aj).tooltip().click(function(){ai(ag)}).appendTo(this.icons_div);if(ah){this.action_icons[af].hide()}},build_action_icons:function(ae){var ag;for(var af=0;af<ae.length;af++){ag=ae[af];this.add_action_icon(ag.name,ag.title,ag.css_class,ag.on_click_fn,ag.prepend,ag.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(af,ae,ag){r.call(this,af,ae,ag);this.obj_type=ag.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ag){this.drawables=[];var af;for(var ae=0;ae<ag.length;ae++){af=p(ag[ae],this.view,this);this.add_drawable(af)}},init:function(){for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae].init()}},_draw:function(){for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae]._draw()}},to_dict:function(){var af=[];for(var ae=0;ae<this.drawables.length;ae++){af.push(this.drawables[ae].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:af}},add_drawable:function(ae){this.drawables.push(ae);ae.container=this;this.changed()},add_drawable_before:function(ag,ae){this.changed();var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables.splice(af,0,ag);return true}return false},replace_drawable:function(ag,ae,af){var ah=this.drawables.indexOf(ag);if(ah!==-1){this.drawables[ah]=ae;if(af){ag.container_div.replaceWith(ae.container_div)}this.changed()}return ah},remove_drawable:function(af){var ae=this.drawables.indexOf(af);if(ae!==-1){this.drawables.splice(ae,1);af.container=null;this.changed();return true}return false},move_drawable:function(af,ag){var ae=this.drawables.indexOf(af);if(ae!==-1){this.drawables.splice(ae,1);this.drawables.splice(ag,0,af);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(af,ae,ah){q(ah,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,af,ae,ah);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ah){this.unpack_drawables(ah.drawables)}if("filters" in ah){var ag=this.filters_manager;this.filters_manager=new i.FiltersManager(this,ah.filters);ag.parent_div.replaceWith(this.filters_manager.parent_div);if(ah.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ae){$(".bs-tooltip").remove();ae.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ae){if(ae.filters_manager.visible()){ae.filters_manager.clear_filters();ae._restore_filter_managers()}else{ae.setup_multitrack_filtering();ae.request_draw(true)}ae.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ae=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ae)}return ae},build_header_div:function(){var ae=$("<div/>").addClass("track-header");ae.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ae);return ae},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ag=this.drawables.length;if(ag===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ag===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var an,am,ak,aq=true,ai=this.drawables[0].get_type(),ae=0;for(an=0;an<ag;an++){ak=this.drawables[an];if(ak.get_type()!==ai){can_composite=false;break}if(ak instanceof c){ae++}}if(aq||ae===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ae>1&&ae===this.drawables.length){var ar={},af;ak=this.drawables[0];for(am=0;am<ak.filters_manager.filters.length;am++){af=ak.filters_manager.filters[am];ar[af.name]=[af]}for(an=1;an<this.drawables.length;an++){ak=this.drawables[an];for(am=0;am<ak.filters_manager.filters.length;am++){af=ak.filters_manager.filters[am];if(af.name in ar){ar[af.name].push(af)}}}this.filters_manager.remove_all();var ah,aj,al,ao;for(var ap in ar){ah=ar[ap];if(ah.length===ae){aj=new i.NumberFilter({name:ah[0].name,index:ah[0].index});this.filters_manager.add_filter(aj)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae].filters_manager=this.saved_filters_managers[ae]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ae=0;ae<this.drawables.length;ae++){drawable=this.drawables[ae];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ai=[];for(var af=0;af<this.drawables.length;af++){ai.push(this.drawables[af].name)}var ag="Composite Track of "+this.drawables.length+" tracks ("+ai.join(", ")+")";var ah=new f(this.view,this.view,{name:ag,drawables:this.drawables});var ae=this.container.replace_drawable(this,ah,true);ah.request_draw()},add_drawable:function(ae){z.prototype.add_drawable.call(this,ae);this.update_icons()},remove_drawable:function(ae){z.prototype.remove_drawable.call(this,ae);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ae=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ae},request_draw:function(ae,ag){for(var af=0;af<this.drawables.length;af++){this.drawables[af].request_draw(ae,ag)}}});var Z=function(ae){q(ae,{obj_type:"View"});z.call(this,"View",ae.container,ae);this.chrom=null;this.vis_id=ae.vis_id;this.dbkey=ae.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.init();this.canvas_manager=new x.CanvasManager(this.container.get(0).ownerDocument);this.reset()};ac.extend(Z.prototype,Backbone.Events);q(Z.prototype,z.prototype,{init:function(){this.requested_redraw=false;var ag=this.container,ae=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ag);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ag);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ag);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,ae);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ah=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){ad(select_datasets_url,add_track_async_url,function(ai){ac.each(ai,function(aj){ae.add_drawable(p(aj,ae,ae))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var af=function(ai){if(ai.type==="focusout"||(ai.keyCode||ai.which)===13||(ai.keyCode||ai.which)===27){if((ai.keyCode||ai.which)!==27){ae.go_to($(this).val())}$(this).hide();$(this).val("");ae.location_span.show();ae.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",af).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ae.location_span.hide();ae.chrom_select.hide();ae.nav_input.val(ae.chrom+":"+ae.low+"-"+ae.high);ae.nav_input.css("display","inline-block");ae.nav_input.select();ae.nav_input.focus();ae.nav_input.autocomplete({source:function(ak,ai){var al=[],aj=$.map(ae.get_drawables(),function(am){return am.data_manager.search_features(ak.term).success(function(an){al=al.concat(an)})});$.when.apply($,aj).done(function(){ai($.map(al,function(am){return{label:am[0],value:am[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ae.zoom_out();ae.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ae.zoom_in();ae.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ae.change_chrom(ae.chrom_select.val())});this.browser_content_div.click(function(ai){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ai){ae.zoom_in(ai.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ai,aj){this.current_x=aj.offsetX}).bind("drag",function(ai,ak){var al=ak.offsetX-this.current_x;this.current_x=ak.offsetX;var aj=Math.round(al/ae.viewport_container.width()*(ae.max_high-ae.max_low));ae.move_delta(-aj)});this.overview_close.click(function(){ae.reset_overview()});this.viewport_container.bind("draginit",function(ai,aj){if(ai.clientX>ae.viewport_container.width()-16){return false}}).bind("dragstart",function(ai,aj){aj.original_low=ae.low;aj.current_height=ai.clientY;aj.current_x=aj.offsetX}).bind("drag",function(ak,am){var ai=$(this);var an=am.offsetX-am.current_x;var aj=ai.scrollTop()-(ak.clientY-am.current_height);ai.scrollTop(aj);am.current_height=ak.clientY;am.current_x=am.offsetX;var al=Math.round(an/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(al)}).bind("mousewheel",function(ak,am,aj,ai){if(aj){aj*=50;var al=Math.round(-aj/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(al)}});this.top_labeltrack.bind("dragstart",function(ai,aj){return $("<div />").css({height:ae.browser_content_div.height()+ae.top_labeltrack.height()+ae.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(am,an){$(an.proxy).css({left:Math.min(am.pageX,an.startX)-ae.container.offset().left,width:Math.abs(am.pageX-an.startX)});var aj=Math.min(am.pageX,an.startX)-ae.container.offset().left,ai=Math.max(am.pageX,an.startX)-ae.container.offset().left,al=(ae.high-ae.low),ak=ae.viewport_container.width();ae.update_location(Math.round(aj/ak*al)+ae.low,Math.round(ai/ak*al)+ae.low)}).bind("dragend",function(an,ao){var aj=Math.min(an.pageX,ao.startX),ai=Math.max(an.pageX,ao.startX),al=(ae.high-ae.low),ak=ae.viewport_container.width(),am=ae.low;ae.low=Math.round(aj/ak*al)+am;ae.high=Math.round(ai/ak*al)+am;$(ao.proxy).remove();ae.request_redraw()});this.add_label_track(new Y(this,{content_div:this.top_labeltrack}));this.add_label_track(new Y(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ae.resize_window()},500)});$(document).bind("redraw",function(){ae.redraw()});this.reset();$(window).trigger("resize")},changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(af,ah,ae,ai){if(this.timer){clearTimeout(this.timer)}if(ai){var ag=this;this.timer=setTimeout(function(){ag.trigger("navigate",af+":"+ah+"-"+ae)},500)}else{view.trigger("navigate",af+":"+ah+"-"+ae)}},update_location:function(ae,ag){this.location_span.text(commatize(ae)+" - "+commatize(ag));this.nav_input.val(this.chrom+":"+commatize(ae)+"-"+commatize(ag));var af=view.chrom_select.val();if(af!==""){this.trigger_navigate(af,view.low,view.high,true)}},load_chroms:function(ag){ag.num=w;var ae=this,af=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ag,dataType:"json",success:function(ai){if(ai.chrom_info.length===0){return}if(ai.reference){ae.add_label_track(new B(ae))}ae.chrom_data=ai.chrom_info;var al='<option value="">Select Chrom/Contig</option>';for(var ak=0,ah=ae.chrom_data.length;ak<ah;ak++){var aj=ae.chrom_data[ak].chrom;al+='<option value="'+aj+'">'+aj+"</option>"}if(ai.prev_chroms){al+='<option value="previous">Previous '+w+"</option>"}if(ai.next_chroms){al+='<option value="next">Next '+w+"</option>"}ae.chrom_select.html(al);ae.chrom_start_index=ai.start_index;af.resolve(ai)},error:function(){alert("Could not load chroms for this dbkey:",ae.dbkey)}});return af},change_chrom:function(aj,af,al){var ag=this;if(!ag.chrom_data){ag.load_chroms_deferred.then(function(){ag.change_chrom(aj,af,al)});return}if(!aj||aj==="None"){return}if(aj==="previous"){ag.load_chroms({low:this.chrom_start_index-w});return}if(aj==="next"){ag.load_chroms({low:this.chrom_start_index+w});return}var ak=$.grep(ag.chrom_data,function(am,an){return am.chrom===aj})[0];if(ak===undefined){ag.load_chroms({chrom:aj},function(){ag.change_chrom(aj,af,al)});return}else{if(aj!==ag.chrom){ag.chrom=aj;ag.chrom_select.val(ag.chrom);ag.max_high=ak.len-1;ag.reset();ag.request_redraw(true);for(var ai=0,ae=ag.drawables.length;ai<ae;ai++){var ah=ag.drawables[ai];if(ah.init){ah.init()}}if(ag.reference_track){ag.reference_track.init()}}if(af!==undefined&&al!==undefined){ag.low=Math.max(af,0);ag.high=Math.min(al,ag.max_high)}else{ag.low=0;ag.high=ag.max_high}ag.reset_overview();ag.request_redraw()}},go_to:function(ai){ai=ai.replace(/ |,/g,"");var am=this,ae,ah,af=ai.split(":"),ak=af[0],al=af[1];if(al!==undefined){try{var aj=al.split("-");ae=parseInt(aj[0],10);ah=parseInt(aj[1],10)}catch(ag){return false}}am.change_chrom(ak,ae,ah)},move_fraction:function(ag){var ae=this;var af=ae.high-ae.low;this.move_delta(ag*af)},move_delta:function(ah){var ae=this;var ag=ae.high-ae.low;if(ae.low-ah<ae.max_low){ae.low=ae.max_low;ae.high=ae.max_low+ag}else{if(ae.high-ah>ae.max_high){ae.high=ae.max_high;ae.low=ae.max_high-ag}else{ae.high-=ah;ae.low-=ah}}ae.request_redraw();var af=ae.chrom_select.val();this.trigger_navigate(af,ae.low,ae.high,true)},add_drawable:function(ae){z.prototype.add_drawable.call(this,ae);ae.init();this.changed();this.update_intro_div()},add_label_track:function(ae){ae.view=this;ae.init();this.label_tracks.push(ae)},remove_drawable:function(ag,af){z.prototype.remove_drawable.call(this,ag);if(af){var ae=this;ag.container_div.hide(0,function(){$(this).remove();ae.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(am,ae,al,an){var ak=this,aj=(an?[an]:ak.drawables),ag;var af;for(var ai=0;ai<aj.length;ai++){af=aj[ai];ag=-1;for(var ah=0;ah<ak.tracks_to_be_redrawn.length;ah++){if(ak.tracks_to_be_redrawn[ah][0]===af){ag=ah;break}}if(ag<0){ak.tracks_to_be_redrawn.push([af,ae,al])}else{ak.tracks_to_be_redrawn[ai][1]=ae;ak.tracks_to_be_redrawn[ai][2]=al}}if(!this.requested_redraw){requestAnimationFrame(function(){ak._redraw(am)});this.requested_redraw=true}},_redraw:function(ao){this.requested_redraw=false;var al=this.low,ah=this.high;if(al<this.max_low){al=this.max_low}if(ah>this.max_high){ah=this.max_high}var an=this.high-this.low;if(this.high!==0&&an<this.min_separation){ah=al+this.min_separation}this.low=Math.floor(al);this.high=Math.ceil(ah);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=this.viewport_container.width()/(this.high-this.low);var ae=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ak=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ap=13;this.overview_box.css({left:ae,width:Math.max(ap,ak)}).show();if(ak<ap){this.overview_box.css("left",ae-(ap-ak)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ae,width:ak})}if(!ao){var ag,af,am;for(var ai=0,aj=this.tracks_to_be_redrawn.length;ai<aj;ai++){ag=this.tracks_to_be_redrawn[ai][0];af=this.tracks_to_be_redrawn[ai][1];am=this.tracks_to_be_redrawn[ai][2];if(ag){ag._draw(af,am)}}this.tracks_to_be_redrawn=[];for(ai=0,aj=this.label_tracks.length;ai<aj;ai++){this.label_tracks[ai]._draw()}}},zoom_in:function(af,ag){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ah=this.high-this.low,ai=ah/2+this.low,ae=(ah/this.zoom_factor)/2;if(af){ai=af/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ai-ae);this.high=Math.round(ai+ae);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var af=this.high-this.low,ag=af/2+this.low,ae=(af*this.zoom_factor)/2;this.low=Math.round(ag-ae);this.high=Math.round(ag+ae);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ag){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ag.dataset_id){return}this.overview_viewport.find(".track").remove()}var af=ag.copy({content_div:this.overview_viewport}),ae=this;af.header_div.hide();af.is_overview=true;ae.overview_drawable=af;this.overview_drawable.postdraw_actions=function(){ae.overview_highlight.show().height(ae.overview_drawable.content_div.height());ae.overview_viewport.height(ae.overview_drawable.content_div.height()+ae.overview_box.outerHeight());ae.overview_close.show();ae.resize_window()};ae.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();view.overview_drawable=null}});var s=function(ag,al,ah){this.track=ag;this.name=al.name;this.params=[];var at=al.params;for(var ai=0;ai<at.length;ai++){var an=at[ai],af=an.name,ar=an.label,aj=unescape(an.html),au=an.value,ap=an.type;if(ap==="number"){this.params.push(new e(af,ar,aj,(af in ah?ah[af]:au),an.min,an.max))}else{if(ap==="select"){this.params.push(new N(af,ar,aj,(af in ah?ah[af]:au)))}else{console.log("WARNING: unrecognized tool parameter type:",af,ap)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(aw){aw.stopPropagation()}).click(function(aw){aw.stopPropagation()}).bind("dblclick",function(aw){aw.stopPropagation()});var aq=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ao=this.params;var am=this;$.each(this.params,function(ax,aA){var az=$("<div>").addClass("param-row").appendTo(am.parent_div);var aw=$("<div>").addClass("param-label").text(aA.label).appendTo(az);var ay=$("<div/>").addClass("param-input").html(aA.html).appendTo(az);ay.find(":input").val(aA.value);$("<div style='clear: both;'/>").appendTo(az)});this.parent_div.find("input").click(function(){$(this).select()});var av=$("<div>").addClass("param-row").appendTo(this.parent_div);var ak=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(av);var ae=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(av);ae.click(function(){am.run_on_region()});ak.click(function(){am.run_on_dataset()});if("visible" in ah&&ah.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ae=0;ae<this.params.length;ae++){this.params[ae].update_value()}},state_dict:function(){var af={};for(var ae=0;ae<this.params.length;ae++){af[this.params[ae].name]=this.params[ae].value}af.visible=this.parent_div.is(":visible");return af},get_param_values_dict:function(){var ae={};this.parent_div.find(":input").each(function(){var af=$(this).attr("name"),ag=$(this).val();ae[af]=ag});return ae},get_param_values:function(){var ae=[];this.parent_div.find(":input").each(function(){var af=$(this).attr("name"),ag=$(this).val();if(af){ae[ae.length]=ag}});return ae},run_on_dataset:function(){var ae=this;ae.run({target_dataset_id:this.track.original_dataset_id,tool_id:ae.name},null,function(af){show_modal(ae.name+" is Running",ae.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var af={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.name,regions:[{chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}]},aj=this.track,ag=af.tool_id+aj.tool_region_and_parameters_str(af.chrom,af.low,af.high),ae;if(aj.container===view){var ai=new P(view,view,{name:this.name});var ah=aj.container.replace_drawable(aj,ai,false);ai.container_div.insertBefore(aj.view.content_div.children()[ah]);ai.add_drawable(aj);aj.container_div.appendTo(ai.content_div);ae=ai}else{ae=aj.container}var ak=new aj.constructor(view,ae,{name:ag,hda_ldda:"hda"});ak.init_for_tool_data();ak.change_mode(aj.mode);ak.set_filters_manager(aj.filters_manager.copy(ak));ak.update_icons();ae.add_drawable(ak);ak.tiles_div.text("Starting job.");this.update_params();this.run(af,ak,function(al){ak.set_dataset(new aa.Dataset(al));ak.tiles_div.text("Running job.");ak.init()})},run:function(ae,ag,ah){ae.inputs=this.get_param_values_dict();var af=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ae),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ai){return ai!=="pending"}});$.when(af.go()).then(function(ai){if(ai==="no converter"){ag.container_div.addClass("error");ag.content_div.text(J)}else{if(ai.error){ag.container_div.addClass("error");ag.content_div.text(y+ai.message)}else{ah(ai)}}})}});var N=function(af,ae,ag,ah){this.name=af;this.label=ae;this.html=$(ag);this.value=ah};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ag,af,ai,aj,ah,ae){N.call(this,ag,af,ai,aj);this.min=ah;this.max=ae};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ae,af){L.Scaler.call(this,af);this.filter=ae};C.prototype.gen_val=function(ae){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ae[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ae){this.track=ae.track;this.params=ae.params;this.values={};this.restore_values((ae.saved_values?ae.saved_values:{}));this.onchange=ae.onchange};q(F.prototype,{restore_values:function(ae){var af=this;$.each(this.params,function(ag,ah){if(ae[ah.key]!==undefined){af.values[ah.key]=ae[ah.key]}else{af.values[ah.key]=ah.default_value}})},build_form:function(){var ah=this;var ae=$("<div />");var ag;function af(am,ai){for(var aq=0;aq<am.length;aq++){ag=am[aq];if(ag.hidden){continue}var ak="param_"+aq;var av=ah.values[ag.key];var ax=$("<div class='form-row' />").appendTo(ai);ax.append($("<label />").attr("for",ak).text(ag.label+":"));if(ag.type==="bool"){ax.append($('<input type="checkbox" />').attr("id",ak).attr("name",ak).attr("checked",av))}else{if(ag.type==="text"){ax.append($('<input type="text"/>').attr("id",ak).val(av).click(function(){$(this).select()}))}else{if(ag.type==="select"){var at=$("<select />").attr("id",ak);for(var ao=0;ao<ag.options.length;ao++){$("<option/>").text(ag.options[ao].label).attr("value",ag.options[ao].value).appendTo(at)}at.val(av);ax.append(at)}else{if(ag.type==="color"){var aw=$("<div/>").appendTo(ax),ar=$("<input />").attr("id",ak).attr("name",ak).val(av).css("float","left").appendTo(aw).click(function(az){$(".bs-tooltip").removeClass("in");var ay=$(this).siblings(".bs-tooltip").addClass("in");ay.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ay).height()/2)+($(this).height()/2)}).show();ay.click(function(aA){aA.stopPropagation()});$(document).bind("click.color-picker",function(){ay.hide();$(document).unbind("click.color-picker")});az.stopPropagation()}),ap=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(aw).attr("title","Set new random color").tooltip(),au=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(aw).hide(),al=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(au),aj=$("<div class='tooltip-arrow'></div>").appendTo(au),an=$.farbtastic(al,{width:100,height:100,callback:ar,color:av});aw.append($("<div/>").css("clear","both"));(function(ay){ap.click(function(){ay.setColor(Q())})})(an)}else{ax.append($("<input />").attr("id",ak).attr("name",ak).val(av))}}}}if(ag.help){ax.append($("<div class='help'/>").text(ag.help))}}}af(this.params,ae);return ae},update_from_form:function(ae){var ag=this;var af=false;$.each(this.params,function(ah,aj){if(!aj.hidden){var ak="param_"+ah;var ai=ae.find("#"+ak).val();if(aj.type==="float"){ai=parseFloat(ai)}else{if(aj.type==="int"){ai=parseInt(ai)}else{if(aj.type==="bool"){ai=ae.find("#"+ak).is(":checked")}}}if(ai!==ag.values[aj.key]){ag.values[aj.key]=ai;af=true}}});if(af){this.onchange();this.track.changed()}}});var b=function(ae,ai,ag,af,ah){this.track=ae;this.region=ai;this.low=ai.get("start");this.high=ai.get("end");this.resolution=ag;this.html_elt=$("<div class='track-tile'/>").append(af).height($(af).attr("height"));this.data=ah;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ae,aj,ag,af,ah,ai){b.call(this,ae,aj,ag,af,ah);this.max_val=ai};q(j.prototype,b.prototype);var O=function(ah,ap,ai,ag,ak,ar,al,at,af,ao){b.call(this,ah,ap,ai,ag,ak);this.mode=al;this.all_slotted=af;this.feature_mapper=ao;this.has_icons=false;if(at){this.has_icons=true;var am=this;ag=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ag.width}).prependTo(this.html_elt);var an=new x.GenomeRegion({chrom:ah.view.chrom,start:this.low,end:this.high}),aq=ak.length,aj=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+aq+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ae=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+aq+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);aj.click(function(){am.stale=true;ah.data_manager.get_more_data(an,ah.mode,am.resolution,{},ah.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();ah.request_draw(true)}).dblclick(function(au){au.stopPropagation()});ae.click(function(){am.stale=true;ah.data_manager.get_more_data(an,ah.mode,am.resolution,{},ah.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();ah.request_draw(true)}).dblclick(function(au){au.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var af=this,ae={};if(af.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(aq){if(!this.hovered){return}var al=$(this).offset(),ap=aq.pageX-al.left,ao=aq.pageY-al.top,av=af.feature_mapper.get_feature_data(ap,ao),am=(av?av[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!am||$(this).attr("id")!==am.toString()){$(this).remove()}});if(av){var ah=ae[am];if(!ah){var am=av[0],ar={name:av[3],start:av[1],end:av[2],strand:av[4]},ak=af.track.filters_manager.filters,aj;for(var an=0;an<ak.length;an++){aj=ak[an];ar[aj.name]=av[aj.index]}var ah=$("<div/>").attr("id",am).addClass("feature-popup"),aw=$("<table/>"),au,at,ax;for(au in ar){at=ar[au];ax=$("<tr/>").appendTo(aw);$("<th/>").appendTo(ax).text(au);$("<td/>").attr("align","left").appendTo(ax).text(typeof(at)==="number"?X(at,2):at)}ah.append($("<div class='feature-popup-inner'>").append(aw));ae[am]=ah}ah.appendTo($(this).parents(".track-content").children(".overlay"));var ai=ap+parseInt(af.html_elt.css("left"))-ah.width()/2,ag=ao+parseInt(af.html_elt.css("top"))+7;ah.css("left",ai+"px").css("top",ag+"px")}else{if(!aq.isPropagationStopped()){aq.stopPropagation();$(this).siblings().each(function(){$(this).trigger(aq)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(af,ae,ag){q(ag,{drag_handle_class:"draghandle"});r.call(this,af,ae,ag);this.dataset=new aa.Dataset({id:ag.dataset_id,hda_ldda:ag.hda_ldda});this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ag?ag.data_query_wait:K);this.data_manager=("data_manager" in ag?ag.data_manager:new x.GenomeDataManager({dataset:this.dataset,data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ag)||ag.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ae){ae.view.set_overview(ae)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ae){if(ae.filters_manager.visible()){ae.filters_manager.clear_filters()}else{ae.filters_manager.init_filters()}ae.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ae){ae.dynamic_tool_div.toggle();if(ae.dynamic_tool_div.is(":visible")){ae.set_name(ae.name+ae.tool_region_and_parameters_str())}else{ae.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ae){var ah='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ag=ac.template(ah,{track:ae});var aj=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},af=function(){var al=$('select[name="regions"] option:selected').val(),an,ak=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),am=ac.map($(".bookmark"),function(ao){return new x.GenomeRegion({from_str:$(ao).children(".position").text()})});if(al==="cur"){an=[ak]}else{if(al==="bookmarks"){an=am}else{an=[ak].concat(am)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ae.dataset_id,hda_ldda:ae.hda_ldda,regions:JSON.stringify(new Backbone.Collection(an).toJSON())})},ai=function(ak){if((ak.keyCode||ak.which)===27){aj()}else{if((ak.keyCode||ak.which)===13){af()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ag,{No:aj,Yes:af})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ae=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ae)}this.name_div=$("<div/>").addClass("track-name").appendTo(ae).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ae},on_resize:function(){},add_resize_handle:function(){var ae=this;var ah=false;var ag=false;var af=$("<div class='track-resize'>");$(ae.container_div).hover(function(){if(ae.content_visible){ah=true;af.show()}},function(){ah=false;if(!ag){af.hide()}});af.hide().bind("dragstart",function(ai,aj){ag=true;aj.original_height=$(ae.content_div).height()}).bind("drag",function(aj,ak){var ai=Math.min(Math.max(ak.original_height+ak.deltaY,ae.min_height_px),ae.max_height_px);$(ae.tiles_div).css("height",ai);ae.visible_height_px=(ae.max_height_px===ai?0:ai);ae.on_resize()}).bind("dragend",function(ai,aj){ae.tile_cache.clear();ag=false;if(!ah){af.hide()}ae.config.values.height=ae.visible_height_px;ae.changed()}).appendTo(ae.container_div)},set_display_modes:function(ah,ak){this.display_modes=ah;this.mode=(ak?ak:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var af=this,ai={};for(var ag=0,ae=af.display_modes.length;ag<ae;ag++){var aj=af.display_modes[ag];ai[aj]=function(al){return function(){af.change_mode(al);af.icons_div.show();af.container_div.mouseleave(function(){af.icons_div.hide()})}}(aj)}make_popupmenu(this.action_icons.mode_icon,ai)},build_action_icons:function(){r.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof Y){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof U){return"ReadTrack"}else{if(this instanceof S){return"VcfTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(){var af=this;af.enabled=false;af.tile_cache.clear();af.data_manager.clear();af.content_div.css("height","auto");af.tiles_div.children().remove();af.container_div.removeClass("nodata error pending");if(!af.dataset_id){return}var ae=$.Deferred(),ag={hda_ldda:af.hda_ldda,data_type:this.dataset_check_type,chrom:af.view.chrom};$.getJSON(this.dataset.url(),ag,function(ah){if(!ah||ah==="error"||ah.kind==="error"){af.container_div.addClass("error");af.tiles_div.text(o);if(ah.message){var ai=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ah.message+"</pre>",{Close:hide_modal})});af.tiles_div.append(ai)}}else{if(ah==="no converter"){af.container_div.addClass("error");af.tiles_div.text(J)}else{if(ah==="no data"||(ah.data!==undefined&&(ah.data===null||ah.data.length===0))){af.container_div.addClass("nodata");af.tiles_div.text(E)}else{if(ah==="pending"){af.container_div.addClass("pending");af.tiles_div.html(v);setTimeout(function(){af.init()},af.data_query_wait)}else{if(ah==="data"||ah.status==="data"){if(ah.valid_chroms){af.valid_chroms=ah.valid_chroms;af.update_icons()}af.tiles_div.text(V);if(af.view.chrom){af.tiles_div.text("");af.tiles_div.css("height",af.visible_height_px+"px");af.enabled=true;$.when(af.predraw_init()).done(function(){ae.resolve();af.container_div.removeClass("nodata error pending");af.request_draw()})}else{ae.resolve()}}}}}}});this.update_icons();return ae},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ag,af,ah){g.call(this,ag,af,ah);var ae=this;m(ae.container_div,ae.drag_handle_class,".group",ae);this.filters_manager=new i.FiltersManager(this,("filters" in ah?ah.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in ah&&ah.tool?new s(this,ah.tool,ah.tool_state):null);this.tile_cache=new x.Cache(R);if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(ah.mode){this.change_mode(ah.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ae){$(".bs-tooltip").remove();ae.slotters[ae.view.resolution_px_b].max_rows*=2;ae.request_draw(true)},hide:true}]),copy:function(ae){var af=this.to_dict();q(af,{data_manager:this.data_manager});var ag=new this.constructor(this.view,ae,af);ag.change_mode(this.mode);ag.enabled=this.enabled;return ag},set_filters_manager:function(ae){this.filters_manager=ae;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(af){var ae=this;ae.mode=af;ae.config.values.mode=af;ae.tile_cache.clear();ae.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ae.mode+")");return ae},update_icons:function(){var ae=this;if(ae.filters_available){ae.action_icons.filters_icon.show()}else{ae.action_icons.filters_icon.hide()}if(ae.tool){ae.action_icons.tools_icon.show();ae.action_icons.param_space_viz_icon.show()}else{ae.action_icons.tools_icon.hide();ae.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(af,ag,ae){return af+"_"+ag+"_"+ae},request_draw:function(af,ae){this.view.request_redraw(false,af,ae,this)},before_draw:function(){},_draw:function(af,ap){if(!this.can_draw()){return}var an=this.view.low,aj=this.view.high,al=aj-an,ag=this.view.container.width(),ar=this.view.resolution_px_b,ai=this.view.resolution_b_px;if(this.is_overview){an=this.view.max_low;aj=this.view.max_high;ai=(view.max_high-view.max_low)/ag;ar=1/ai}this.before_draw();this.tiles_div.children().addClass("remove");var ae=Math.floor(an/(ai*T)),am=true,aq=[],ak=function(at){return(at&&"track" in at)};while((ae*T*ai)<aj){var ao=this.draw_helper(af,ag,ae,ai,this.tiles_div,ar);if(ak(ao)){aq.push(ao)}else{am=false}ae+=1}if(!ap){this.tiles_div.children(".remove").removeClass("remove").remove()}var ah=this;if(am){this.tiles_div.children(".remove").remove();ah.postdraw_actions(aq,ag,ar,ap)}},postdraw_actions:function(ag,ah,aj,ae){var ai=false;for(var af=0;af<ag.length;af++){if(ag[af].has_icons){ai=true;break}}if(ai){for(var af=0;af<ag.length;af++){tile=ag[af];if(!tile.has_icons){tile.html_elt.css("padding-top",D)}}}},draw_helper:function(ae,aq,aw,au,aj,ak,ar){var ap=this,az=this._gen_tile_cache_key(aq,ak,aw),ah=this._get_tile_bounds(aw,au);if(!ar){ar={}}var ay=(ae?undefined:ap.tile_cache.get_elt(az));if(ay){ap.show_tile(ay,aj,ak);return ay}var an=true;var av=ap.data_manager.get_data(ah,ap.mode,au,ap.data_url_extra_params);if(W(av)){an=false}var al;if(view.reference_track&&ak>view.canvas_manager.char_width_px){al=view.reference_track.data_manager.get_data(ah,ap.mode,au,view.reference_track.data_url_extra_params);if(W(al)){an=false}}if(an){q(av,ar.more_tile_data);var am=ap.mode;if(am==="Auto"){am=ap.get_mode(av);ap.update_auto_mode(am)}var ag=ap.view.canvas_manager.new_canvas(),ax=ah.get("start"),af=ah.get("end"),aq=Math.ceil((af-ax)*ak)+ap.left_offset,ao=ap.get_canvas_height(av,am,ak,aq);ag.width=aq;ag.height=ao;var at=ag.getContext("2d");at.translate(this.left_offset,0);var ay=ap.draw_tile(av,at,am,au,ah,ak,al);if(ay!==undefined){ap.tile_cache.set_elt(az,ay);ap.show_tile(ay,aj,ak)}return ay}var ai=$.Deferred();$.when(av,al).then(function(){view.request_redraw(false,false,false,ap);ai.resolve()});return ai},get_canvas_height:function(ae,ag,ah,af){return this.visible_height_px},draw_tile:function(ae,af,aj,ah,ai,ak,ag){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ag,aj,ak){var af=this,ae=ag.html_elt;ag.predisplay_actions();var ai=(ag.low-(this.is_overview?this.view.max_low:this.view.low))*ak;if(this.left_offset){ai-=this.left_offset}ae.css({position:"absolute",top:0,left:ai});if(ae.hasClass("remove")){ae.removeClass("remove")}else{aj.append(ae)}ag.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ag.html_elt.height());ag.html_elt.parent().children().css("height",this.max_height_px+"px");var ah=this.max_height_px;if(this.visible_height_px!==0){ah=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",ah+"px")},_get_tile_bounds:function(ae,af){var ah=Math.floor(ae*T*af),ai=Math.ceil(T*af),ag=(ah+ai<=this.view.max_high?ah+ai:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:ah,end:ag})},tool_region_and_parameters_str:function(ag,ae,ah){var af=this,ai=(ag!==undefined&&ae!==undefined&&ah!==undefined?ag+":"+ae+"-"+ah:"all");return" - region=["+ai+"], parameters=["+af.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ae,af){return true},can_subset:function(ae){return false},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ag,ah,aj,ae){var af=this;af.normal_postdraw_actions(ag,ah,aj,ae);af.dataset_check_type="converted_datasets_state";af.data_query_wait=K;var ai=new l.ServerStateDeferred({url:af.dataset_state_url,url_params:{dataset_id:af.dataset_id,hda_ldda:af.hda_ldda},interval:af.data_query_wait,success_fn:function(ak){return ak!=="pending"}});$.when(ai.go()).then(function(){af.data_manager.set("data_type","data")});af.postdraw_actions=af.normal_postdraw_actions}}});var Y=function(af,ae){var ag={resize:false};g.call(this,af,ae,ag);this.container_div.addClass("label-track")};q(Y.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ag=this.view,ah=ag.high-ag.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ah)/Math.log(10)))),ae=Math.floor(ag.low/ak)*ak,ai=this.view.container.width(),af=$("<div style='position: relative; height: 1.3em;'></div>");while(ae<ag.high){var aj=(ae-ag.low)/ah*ai;af.append($("<div class='label'>"+commatize(ae)+"</div>").css({position:"absolute",left:aj-1}));ae+=ak}this.content_div.children(":first").remove();this.content_div.append(af)}});var f=function(af,ae,ai){M.call(this,af,ae,ai);this.drawables=[];this.left_offset=0;if("drawables" in ai){var ah;for(var ag=0;ag<ai.drawables.length;ag++){ah=ai.drawables[ag];this.drawables[ag]=p(ah,af,null);if(ah.left_offset>this.left_offset){this.left_offset=ah.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ae){$(".bs-tooltip").remove();ae.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ae){M.prototype.change_mode.call(this,ae);for(var af=0;af<this.drawables.length;af++){this.drawables[af].change_mode(ae)}},init:function(){var ag=[];for(var af=0;af<this.drawables.length;af++){ag.push(this.drawables[af].init())}var ae=this;$.when.apply($,ag).then(function(){ae.enabled=true;ae.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:r.prototype.can_draw,draw_helper:function(af,av,aB,ay,am,ao,aw){var au=this,aF=this._gen_tile_cache_key(av,ao,aB),aj=this._get_tile_bounds(aB,ay);if(!aw){aw={}}var aE=(af?undefined:au.tile_cache.get_elt(aF));if(aE){au.show_tile(aE,am,ao);return aE}var an=[],au,ar=true,az,ap;for(var aA=0;aA<this.drawables.length;aA++){au=this.drawables[aA];az=au.data_manager.get_data(aj,au.mode,ay,au.data_url_extra_params);if(W(az)){ar=false}an.push(az);ap=null;if(view.reference_track&&ao>view.canvas_manager.char_width_px){ap=view.reference_track.data_manager.get_data(aj,au.mode,ay,view.reference_track.data_url_extra_params);if(W(ap)){ar=false}}an.push(ap)}if(ar){q(az,aw.more_tile_data);this.tile_predraw_init();var ai=au.view.canvas_manager.new_canvas(),ak=au._get_tile_bounds(aB,ay),aC=aj.get("start"),ag=aj.get("end"),aD=0,av=Math.ceil((ag-aC)*ao)+this.left_offset,at=0,ah=[],aA;var ae=0;for(aA=0;aA<this.drawables.length;aA++,aD+=2){au=this.drawables[aA];az=an[aD];var aq=au.mode;if(aq==="Auto"){aq=au.get_mode(az);au.update_auto_mode(aq)}ah.push(aq);ae=au.get_canvas_height(az,aq,ao,av);if(ae>at){at=ae}}ai.width=av;ai.height=(aw.height?aw.height:at);aD=0;var ax=ai.getContext("2d");ax.translate(this.left_offset,0);ax.globalAlpha=0.5;ax.globalCompositeOperation="source-over";for(aA=0;aA<this.drawables.length;aA++,aD+=2){au=this.drawables[aA];az=an[aD];ap=an[aD+1];aE=au.draw_tile(az,ax,ah[aA],ay,aj,ao,ap)}this.tile_cache.set_elt(aF,aE);this.show_tile(aE,am,ao);return aE}var al=$.Deferred(),au=this;$.when.apply($,an).then(function(){view.request_redraw(false,false,false,au);al.resolve()});return al},show_group:function(){var ah=new P(this.view,this.container,{name:this.name}),ae;for(var ag=0;ag<this.drawables.length;ag++){ae=this.drawables[ag];ae.update_icons();ah.add_drawable(ae);ae.container=ah;ah.content_div.append(ae.container_div)}var af=this.container.replace_drawable(this,ah,true);ah.request_draw()},tile_predraw_init:function(){var ah=Number.MAX_VALUE,ae=-ah,af;for(var ag=0;ag<this.drawables.length;ag++){af=this.drawables[ag];if(af instanceof h){if(af.prefs.min_value<ah){ah=af.prefs.min_value}if(af.prefs.max_value>ae){ae=af.prefs.max_value}}}for(var ag=0;ag<this.drawables.length;ag++){af=this.drawables[ag];af.prefs.min_value=ah;af.prefs.max_value=ae}},postdraw_actions:function(ag,aj,al,af){M.prototype.postdraw_actions.call(this,ag,aj,al,af);var ai=-1;for(var ah=0;ah<ag.length;ah++){var ae=ag[ah].html_elt.find("canvas").height();if(ae>ai){ai=ae}}for(var ah=0;ah<ag.length;ah++){var ak=ag[ah];if(ak.html_elt.find("canvas").height()!==ai){this.draw_helper(true,aj,ak.index,ak.resolution,ak.html_elt.parent(),al,{height:ai});ak.html_elt.remove()}}}});var B=function(ae){M.call(this,ae,{content_div:ae.top_labeltrack},{resize:false});ae.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.ReferenceTrackDataManager({data_url:this.data_url});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ai,ag,ae,af,aj,ak,ah){if(ak>this.view.canvas_manager.char_width_px){return M.prototype.draw_helper.call(this,ai,ag,ae,af,aj,ak,ah)}else{this.hide_contents();return null}},draw_tile:function(am,an,ai,ah,ak,ao){var ag=this;if(ao>this.view.canvas_manager.char_width_px){if(am.data===null){this.hide_contents();return}var af=an.canvas;an.font=an.canvas.manager.default_font;an.textAlign="center";am=am.data;for(var aj=0,al=am.length;aj<al;aj++){var ae=Math.floor(aj*ao);an.fillText(am[aj],ae,10)}this.show_contents();return new b(ag,ak,ah,af,am)}this.hide_contents()}});var h=function(ag,af,ah){var ae=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ag,af,ah);this.hda_ldda=ah.hda_ldda;this.dataset_id=ah.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:Q()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:ah.prefs,onchange:function(){ae.set_name(ae.prefs.name);ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.set_min_value(ae.prefs.min_value);ae.set_max_value(ae.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ae){this.prefs.min_value=ae;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ae){this.prefs.max_value=ae;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ae=this;ae.vertical_range=undefined;return $.getJSON(ae.dataset.url(),{data_type:"data",stats:true,chrom:ae.view.chrom,low:0,high:ae.view.max_high,hda_ldda:ae.hda_ldda},function(af){ae.container_div.addClass("line-track");var ai=af.data;if(isNaN(parseFloat(ae.prefs.min_value))||isNaN(parseFloat(ae.prefs.max_value))){var ag=ai.min,ak=ai.max;ag=Math.floor(Math.min(0,Math.max(ag,ai.mean-2*ai.sd)));ak=Math.ceil(Math.max(0,Math.min(ak,ai.mean+2*ai.sd)));ae.prefs.min_value=ag;ae.prefs.max_value=ak;$("#track_"+ae.dataset_id+"_minval").val(ae.prefs.min_value);$("#track_"+ae.dataset_id+"_maxval").val(ae.prefs.max_value)}ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.total_frequency=ai.total_frequency;ae.container_div.find(".yaxislabel").remove();var aj=$("<div/>").text(X(ae.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(al){$(".bs-tooltip").remove();var al=parseFloat(al);if(!isNaN(al)){ae.set_min_value(al)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ae.dataset_id+"_minval").prependTo(ae.container_div),ah=$("<div/>").text(X(ae.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(al){$(".bs-tooltip").remove();var al=parseFloat(al);if(!isNaN(al)){ae.set_max_value(al)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ae.dataset_id+"_maxval").prependTo(ae.container_div)})},draw_tile:function(an,al,ag,af,ai,am){var ae=al.canvas,ah=ai.get("start"),ak=ai.get("end"),aj=new L.LinePainter(an.data,ah,ak,this.prefs,ag);aj.draw(al,ae.width,ae.height,am);return new b(this,ai,af,ae,an.data)},can_subset:function(ae){return false}});var t=function(ag,af,ah){var ae=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ag,af,ah);this.hda_ldda=ah.hda_ldda;this.dataset_id=ah.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"4169E1"},{key:"negative_color",label:"Negative Color",type:"color",default_value:"FF8C00"},{key:"min_value",label:"Min Value",type:"float",default_value:0},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:ah.prefs,onchange:function(){ae.set_name(ae.prefs.name);ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.set_min_value(ae.prefs.min_value);ae.set_max_value(ae.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ae){this.prefs.min_value=ae;this.tile_cache.clear();this.request_draw()},set_max_value:function(ae){this.prefs.max_value=ae;this.tile_cache.clear();this.request_draw()},draw_tile:function(ao,am,aj,ah,af,an){var ag=am.canvas,ae=this._get_tile_bounds(af,ah),ai=ae[0],al=ae[1],ak=new L.DiagonalHeatmapPainter(ao.data,ai,al,this.prefs,aj);ak.draw(am,ag.width,ag.height,an);return new b(this,af,ah,ag,ao.data)}});var c=function(ah,ag,aj){var af=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,ah,ag,aj);var ai=Q(),ae=Q([ai,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ai},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ae},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:aj.prefs,onchange:function(){af.set_name(af.prefs.name);af.tile_cache.clear();af.set_painter_from_config();af.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=aj.hda_ldda;this.dataset_id=aj.dataset_id;this.original_dataset_id=aj.dataset_id;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};q(c.prototype,r.prototype,M.prototype,{set_dataset:function(ae){this.dataset_id=ae.get("id");this.hda_ldda=ae.get("hda_ldda");this.dataset=ae;this.data_manager.set("dataset",ae)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(au,ao,aj,ai){M.prototype.postdraw_actions.call(this,au,ai);var an=this,aq;if(an.mode==="Coverage"){var af=-1;for(aq=0;aq<au.length;aq++){var ap=au[aq].max_val;if(ap>af){af=ap}}for(aq=0;aq<au.length;aq++){var aw=au[aq];if(aw.max_val!==af){aw.html_elt.remove();an.draw_helper(true,ao,aw.index,aw.resolution,aw.html_elt.parent(),aj,{more_tile_data:{max:af}})}}}if(an.filters_manager){var ak=an.filters_manager.filters;for(var at=0;at<ak.length;at++){ak[at].update_ui_elt()}var av=false,ae,al;for(aq=0;aq<au.length;aq++){if(au[aq].data.length){ae=au[aq].data[0];for(var at=0;at<ak.length;at++){al=ak[at];if(al.applies_to(ae)&&al.min!==al.max){av=true;break}}}}if(an.filters_available!==av){an.filters_available=av;if(!an.filters_available){an.filters_manager.hide()}an.update_icons()}}this.container_div.find(".yaxislabel").remove();var ah=au[0];if(ah instanceof j){var am=(this.prefs.histogram_max?this.prefs.histogram_max:ah.max_val),ag=$("<div/>").text(am).make_text_editable({num_cols:12,on_finish:function(ax){$(".bs-tooltip").remove();var ax=parseFloat(ax);an.prefs.histogram_max=(!isNaN(ax)?ax:null);an.tile_cache.clear();an.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ag)}if(ah instanceof O){var ar=true;for(aq=0;aq<au.length;aq++){if(!au[aq].all_slotted){ar=false;break}}if(!ar){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ae){var ae;if(this.mode==="Auto"){if(ae==="no_detail"){ae="feature spans"}else{if(ae==="summary_tree"){ae="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ae+")")}},incremental_slots:function(ai,ae,ah){var af=this.view.canvas_manager.dummy_context,ag=this.slotters[ai];if(!ag||(ag.mode!==ah)){ag=new (u.FeatureSlotter)(ai,ah,A,function(aj){return af.measureText(aj)});this.slotters[ai]=ag}return ag.slot_features(ae)},get_mode:function(ae){if(ae.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ae.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(ae,ai,aj,af){if(ai==="summary_tree"||ai==="Coverage"){return this.summary_draw_height}else{var ah=this.incremental_slots(aj,ae.data,ai);var ag=new (this.painter)(null,null,null,this.prefs,ai);return Math.max(ab,ag.get_required_height(ah,af))}},draw_tile:function(ao,at,aq,au,ah,al,ag){var ar=this,af=at.canvas,aA=ah.get("start"),ae=ah.get("end"),ai=this.left_offset;if(aq==="summary_tree"||aq==="Coverage"){var aC=new L.SummaryTreePainter(ao,aA,ae,this.prefs);aC.draw(at,af.width,af.height,al);return new j(ar,ah,au,af,ao.data,ao.max)}var ak=[],ap=this.slotters[al].slots;all_slotted=true;if(ao.data){var am=this.filters_manager.filters;for(var av=0,ax=ao.data.length;av<ax;av++){var aj=ao.data[av];var aw=false;var an;for(var az=0,aE=am.length;az<aE;az++){an=am[az];an.update_attrs(aj);if(!an.keep(aj)){aw=true;break}}if(!aw){ak.push(aj);if(!(aj[0] in ap)){all_slotted=false}}}}var aD=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null);var aB=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null);var aC=new (this.painter)(ak,aA,ae,this.prefs,aq,aD,aB,ag);var ay=null;at.fillStyle=this.prefs.block_color;at.font=at.canvas.manager.default_font;at.textAlign="right";if(ao.data){ay=aC.draw(at,af.width,af.height,al,ap);ay.translation=-ai}return new O(ar,ah,au,af,ao.data,al,aq,ao.message,all_slotted,ay)},data_and_mode_compatible:function(ae,af){if(af==="Auto"){return true}else{if(af==="Coverage"){return ae.dataset_type==="summary_tree"}else{if(ae.extra_info==="no_detail"||ae.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ae){if(ae.dataset_type==="summary_tree"||ae.message||ae.extra_info==="no_detail"){return false}return true}});var S=function(af,ae,ag){c.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:Q()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter};q(S.prototype,r.prototype,M.prototype,c.prototype);var U=function(ag,af,ai){c.call(this,ag,af,ai);var ah=Q(),ae=Q([ah,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:ah},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ae},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ai.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter;this.update_icons()};q(U.prototype,r.prototype,M.prototype,c.prototype);var d={LineTrack:h,FeatureTrack:c,VcfTrack:S,ReadTrack:U,CompositeTrack:f,DrawableGroup:P};var p=function(ag,af,ae){if("copy" in ag){return ag.copy(ae)}else{var ah=ag.obj_type;if(!ah){ah=ag.track_type}return new d[ah](af,ae,ag)}};return{View:Z,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:U,VcfTrack:S,CompositeTrack:f,object_from_template:p,select_datasets:ad}}); \ No newline at end of file +define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,x,l,u,L,Z,i){var q=ab.extend;var V=function(ac){return("isResolved" in ac)};var n={};var k=function(ac,ad){n[ac.attr("id")]=ad};var m=function(ac,ae,ag,af){ag=".group";var ad={};n[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=n[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}n[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);n[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));n[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};exports.moveable=m;var aa=16,G=9,D=20,A=100,I=12000,S=400,K=5000,w=100,o="There was an error in indexing this dataset. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20;function W(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var r=function(ad,ac,af){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];q(r.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(ad,ac,ae){r.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=p(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac]._draw()}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(ad,ac,af){q(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw(true)}ac.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ag=[];for(var ad=0;ad<this.drawables.length;ad++){ag.push(this.drawables[ad].name)}var ae="Composite Track of "+this.drawables.length+" tracks ("+ag.join(", ")+")";var af=new f(this.view,this.view,{name:ae,drawables:this.drawables});var ac=this.container.replace_drawable(this,af,true);af.request_draw()},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){z.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac,ae){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].request_draw(ac,ae)}}});var Y=function(ac){q(ac,{obj_type:"View"});z.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.init();this.canvas_manager=new x.CanvasManager(this.container.get(0).ownerDocument);this.reset()};ab.extend(Y.prototype,Backbone.Events);q(Y.prototype,z.prototype,{init:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){x.select_datasets(select_datasets_url,add_track_async_url,function(ag){ab.each(ag,function(ah){ac.add_drawable(p(ah,ac,ac))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_drawables(),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new X(this,{content_div:this.top_labeltrack}));this.add_label_track(new X(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=w;var ac=this,ad=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+w+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+w+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-w});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+w});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();ae.request_redraw(true);for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad!==undefined&&aj!==undefined){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/ |,/g,"");var ak=this,ac,af,ad=ag.split(":"),ai=ad[0],aj=ad[1];if(aj!==undefined){try{var ah=aj.split("-");ac=parseInt(ah[0],10);af=parseInt(ah[1],10)}catch(ae){return false}}ak.change_chrom(ai,ac,af)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw();var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){z.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ak,ac,aj,al){var ai=this,ah=(al?[al]:ai.drawables),ae;var ad;for(var ag=0;ag<ah.length;ag++){ad=ah[ag];ae=-1;for(var af=0;af<ai.tracks_to_be_redrawn.length;af++){if(ai.tracks_to_be_redrawn[af][0]===ad){ae=af;break}}if(ae<0){ai.tracks_to_be_redrawn.push([ad,ac,aj])}else{ai.tracks_to_be_redrawn[ag][1]=ac;ai.tracks_to_be_redrawn[ag][2]=aj}}if(!this.requested_redraw){requestAnimationFrame(function(){ai._redraw(ak)});this.requested_redraw=true}},_redraw:function(am){this.requested_redraw=false;var aj=this.low,af=this.high;if(aj<this.max_low){aj=this.max_low}if(af>this.max_high){af=this.max_high}var al=this.high-this.low;if(this.high!==0&&al<this.min_separation){af=aj+this.min_separation}this.low=Math.floor(aj);this.high=Math.ceil(af);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=this.viewport_container.width()/(this.high-this.low);var ac=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=13;this.overview_box.css({left:ac,width:Math.max(an,ai)}).show();if(ai<an){this.overview_box.css("left",ac-(an-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ac,width:ai})}if(!am){var ae,ad,ak;for(var ag=0,ah=this.tracks_to_be_redrawn.length;ag<ah;ag++){ae=this.tracks_to_be_redrawn[ag][0];ad=this.tracks_to_be_redrawn[ag][1];ak=this.tracks_to_be_redrawn[ag][2];if(ae){ae._draw(ad,ak)}}this.tracks_to_be_redrawn=[];for(ag=0,ah=this.label_tracks.length;ag<ah;ag++){this.label_tracks[ag]._draw()}}},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ae){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ae.dataset_id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();view.overview_drawable=null}});var s=function(ae,aj,af){this.track=ae;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new N(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.original_dataset_id,tool_id:ac.name},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ad={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.name,regions:[{chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ad.chrom,ad.low,ad.high),ac;if(ah.container===view){var ag=new P(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var ai=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});ai.init_for_tool_data();ai.change_mode(ah.mode);ai.set_filters_manager(ah.filters_manager.copy(ai));ai.update_icons();ac.add_drawable(ai);ai.tiles_div.text("Starting job.");this.update_params();this.run(ad,ai,function(aj){ai.set_dataset(new Z.Dataset(aj));ai.tiles_div.text("Running job.");ai.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(y+ag.message)}else{af(ag)}}})}});var N=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){N.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};q(F.prototype,{restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(l.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="float"){ag=parseFloat(ag)}else{if(ah.type==="int"){ag=parseInt(ag)}else{if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}}}if(ag!==ae.values[ah.key]){ae.values[ah.key]=ag;ad=true}}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ac,ah,ae,ad,af,ag){b.call(this,ac,ah,ae,ad,af);this.max_val=ag};q(j.prototype,b.prototype);var O=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new x.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?W(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){q(ae,{drag_handle_class:"draghandle"});r.call(this,ad,ac,ae);this.dataset=new Z.Dataset({id:ae.dataset_id,hda_ldda:ae.hda_ldda});this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new x.GenomeDataManager({dataset:this.dataset,data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ae)||ae.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new x.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ac.dataset_id,hda_ldda:ac.hda_ldda,regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},on_resize:function(){},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){r.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof X){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof R){return"VcfTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.content_div.css("height","auto");ad.tiles_div.children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset_id){return}var ac=$.Deferred(),ae={hda_ldda:ad.hda_ldda,data_type:this.dataset_check_type,chrom:ad.view.chrom};$.getJSON(this.dataset.url(),ae,function(af){if(!af||af==="error"||af.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(o);if(af.message){var ag=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+af.message+"</pre>",{Close:hide_modal})});ad.tiles_div.append(ag)}}else{if(af==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(af==="no data"||(af.data!==undefined&&(af.data===null||af.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(af==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(v);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(af==="data"||af.status==="data"){if(af.valid_chroms){ad.valid_chroms=af.valid_chroms;ad.update_icons()}ad.tiles_div.text(U);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when(ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;m(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new s(this,af.tool,af.tool_state):null);this.tile_cache=new x.Cache(Q);if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(af.mode){this.change_mode(af.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw(true)},hide:true}]),copy:function(ac){var ad=this.to_dict();q(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;ac.tile_cache.clear();ac.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ae,ac){return ad+"_"+ae+"_"+ac},request_draw:function(ad,ac){this.view.request_redraw(false,ad,ac,this)},before_draw:function(){},_draw:function(ad,an){if(!this.can_draw()){return}var al=this.view.low,ah=this.view.high,aj=ah-al,ae=this.view.container.width(),ap=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;ap=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(al/(ag*S)),ak=true,ao=[],ai=function(aq){return(aq&&"track" in aq)};while((ac*S*ag)<ah){var am=this.draw_helper(ad,ae,ac,ag,this.tiles_div,ap);if(ai(am)){ao.push(am)}else{ak=false}ac+=1}if(!an){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;if(ak){this.tiles_div.children(".remove").remove();af.postdraw_actions(ao,ae,ap,an)}},postdraw_actions:function(ae,af,ah,ac){var ag=false;for(var ad=0;ad<ae.length;ad++){if(ae[ad].has_icons){ag=true;break}}if(ag){for(var ad=0;ad<ae.length;ad++){tile=ae[ad];if(!tile.has_icons){tile.html_elt.css("padding-top",D)}}}},draw_helper:function(ac,ao,au,ar,ah,ai,ap){var an=this,ax=this._gen_tile_cache_key(ao,ai,au),af=this._get_tile_bounds(au,ar);if(!ap){ap={}}var aw=(ac?undefined:an.tile_cache.get_elt(ax));if(aw){an.show_tile(aw,ah,ai);return aw}var al=true;var at=an.data_manager.get_data(af,an.mode,ar,an.data_url_extra_params);if(V(at)){al=false}var aj;if(view.reference_track&&ai>view.canvas_manager.char_width_px){aj=view.reference_track.data_manager.get_data(af,an.mode,ar,view.reference_track.data_url_extra_params);if(V(aj)){al=false}}if(al){q(at,ap.more_tile_data);var ak=an.mode;if(ak==="Auto"){ak=an.get_mode(at);an.update_auto_mode(ak)}var ae=an.view.canvas_manager.new_canvas(),av=af.get("start"),ad=af.get("end"),ao=Math.ceil((ad-av)*ai)+an.left_offset,am=an.get_canvas_height(at,ak,ai,ao);ae.width=ao;ae.height=am;var aq=ae.getContext("2d");aq.translate(this.left_offset,0);var aw=an.draw_tile(at,aq,ak,ar,af,ai,aj);if(aw!==undefined){an.tile_cache.set_elt(ax,aw);an.show_tile(aw,ah,ai)}return aw}var ag=$.Deferred();$.when(at,aj).then(function(){view.request_redraw(false,false,false,an);ag.resolve()});return ag},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah,ai){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{ah.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*S*ad),ag=Math.ceil(S*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae,ac,af){var ad=this,ag=(ae!==undefined&&ac!==undefined&&af!==undefined?ae+":"+ac+"-"+af:"all");return" - region=["+ag+"], parameters=["+ad.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){return true},can_subset:function(ac){return false},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new l.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset_id,hda_ldda:ad.hda_ldda},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var X=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};q(X.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ae=this.view,af=ae.high-ae.low,ai=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/ai)*ai,ag=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ah=(ac-ae.low)/af*ag;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ah-1}));ac+=ai}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){M.call(this,ad,ac,ag);this.drawables=[];this.left_offset=0;if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=p(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ac){M.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:r.prototype.can_draw,draw_helper:function(ad,at,az,aw,ak,am,au){var ar=this,aD=this._gen_tile_cache_key(at,am,az),ah=this._get_tile_bounds(az,aw);if(!au){au={}}var aC=(ad?undefined:ar.tile_cache.get_elt(aD));if(aC){ar.show_tile(aC,ak,am);return aC}var al=[],ar,ap=true,ax,an;for(var ay=0;ay<this.drawables.length;ay++){ar=this.drawables[ay];ax=ar.data_manager.get_data(ah,ar.mode,aw,ar.data_url_extra_params);if(V(ax)){ap=false}al.push(ax);an=null;if(view.reference_track&&am>view.canvas_manager.char_width_px){an=view.reference_track.data_manager.get_data(ah,ar.mode,aw,view.reference_track.data_url_extra_params);if(V(an)){ap=false}}al.push(an)}if(ap){q(ax,au.more_tile_data);this.tile_predraw_init();var ag=ar.view.canvas_manager.new_canvas(),ai=ar._get_tile_bounds(az,aw),aA=ah.get("start"),ae=ah.get("end"),aB=0,at=Math.ceil((ae-aA)*am)+this.left_offset,aq=0,af=[],ay;var ac=0;for(ay=0;ay<this.drawables.length;ay++,aB+=2){ar=this.drawables[ay];ax=al[aB];var ao=ar.mode;if(ao==="Auto"){ao=ar.get_mode(ax);ar.update_auto_mode(ao)}af.push(ao);ac=ar.get_canvas_height(ax,ao,am,at);if(ac>aq){aq=ac}}ag.width=at;ag.height=(au.height?au.height:aq);aB=0;var av=ag.getContext("2d");av.translate(this.left_offset,0);av.globalAlpha=0.5;av.globalCompositeOperation="source-over";for(ay=0;ay<this.drawables.length;ay++,aB+=2){ar=this.drawables[ay];ax=al[aB];an=al[aB+1];aC=ar.draw_tile(ax,av,af[ay],aw,ah,am,an)}this.tile_cache.set_elt(aD,aC);this.show_tile(aC,ak,am);return aC}var aj=$.Deferred(),ar=this;$.when.apply($,al).then(function(){view.request_redraw(false,false,false,ar);aj.resolve()});return aj},show_group:function(){var af=new P(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw()},tile_predraw_init:function(){var af=Number.MAX_VALUE,ac=-af,ad;for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];if(ad instanceof h){if(ad.prefs.min_value<af){af=ad.prefs.min_value}if(ad.prefs.max_value>ac){ac=ad.prefs.max_value}}}for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];ad.prefs.min_value=af;ad.prefs.max_value=ac}},postdraw_actions:function(ae,ah,aj,ad){M.prototype.postdraw_actions.call(this,ae,ah,aj,ad);var ag=-1;for(var af=0;af<ae.length;af++){var ac=ae[af].html_elt.find("canvas").height();if(ac>ag){ag=ac}}for(var af=0;af<ae.length;af++){var ai=ae[af];if(ai.html_elt.find("canvas").height()!==ag){this.draw_helper(true,ah,ai.index,ai.resolution,ai.html_elt.parent(),aj,{height:ag});ai.html_elt.remove()}}}});var B=function(ac){M.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.ReferenceTrackDataManager({data_url:this.data_url});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ag,ae,ac,ad,ah,ai,af){if(ai>this.view.canvas_manager.char_width_px){return M.prototype.draw_helper.call(this,ag,ae,ac,ad,ah,ai,af)}else{this.hide_contents();return null}},draw_tile:function(ak,al,ag,af,ai,am){var ae=this;if(am>this.view.canvas_manager.char_width_px){if(ak.data===null){this.hide_contents();return}var ad=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";ak=ak.data;for(var ah=0,aj=ak.length;ah<aj;ah++){var ac=Math.floor(ah*am);al.fillText(ak[ah],ac,10)}this.show_contents();return new b(ae,ai,af,ad,ak)}this.hide_contents()}});var h=function(ae,ad,af){var ac=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:l.get_random_color()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ac=this;ac.vertical_range=undefined;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.hda_ldda},function(ad){ac.container_div.addClass("line-track");var ag=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=ag.min,ai=ag.max;ae=Math.floor(Math.min(0,Math.max(ae,ag.mean-2*ag.sd)));ai=Math.ceil(Math.max(0,Math.min(ai,ag.mean+2*ag.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ai;$("#track_"+ac.dataset_id+"_minval").val(ac.prefs.min_value);$("#track_"+ac.dataset_id+"_maxval").val(ac.prefs.max_value)}ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.total_frequency=ag.total_frequency;ac.container_div.find(".yaxislabel").remove();var ah=$("<div/>").text(W(ac.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_min_value(aj)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ac.dataset_id+"_minval").prependTo(ac.container_div),af=$("<div/>").text(W(ac.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_max_value(aj)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ac.dataset_id+"_maxval").prependTo(ac.container_div)})},draw_tile:function(al,aj,ae,ad,ag,ak){var ac=aj.canvas,af=ag.get("start"),ai=ag.get("end"),ah=new L.LinePainter(al.data,af,ai,this.prefs,ae);ah.draw(aj,ac.width,ac.height,ak);return new b(this,ag,ad,ac,al.data)},can_subset:function(ac){return false}});var t=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"4169E1"},{key:"negative_color",label:"Negative Color",type:"color",default_value:"FF8C00"},{key:"min_value",label:"Min Value",type:"float",default_value:0},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;this.tile_cache.clear();this.request_draw()},draw_tile:function(am,ak,ah,af,ad,al){var ae=ak.canvas,ac=this._get_tile_bounds(ad,af),ag=ac[0],aj=ac[1],ai=new L.DiagonalHeatmapPainter(am.data,ag,aj,this.prefs,ah);ai.draw(ak,ae.width,ae.height,al);return new b(this,ad,af,ae,am.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,af,ae,ah);var ag=l.get_random_color(),ac=l.get_random_color([ag,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.tile_cache.clear();ad.set_painter_from_config();ad.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ah.hda_ldda;this.dataset_id=ah.dataset_id;this.original_dataset_id=ah.dataset_id;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};q(c.prototype,r.prototype,M.prototype,{set_dataset:function(ac){this.dataset_id=ac.get("id");this.hda_ldda=ac.get("hda_ldda");this.dataset=ac;this.data_manager.set("dataset",ac)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ar,am,ah,ag){M.prototype.postdraw_actions.call(this,ar,ag);var al=this,ao;if(al.mode==="Coverage"){var ad=-1;for(ao=0;ao<ar.length;ao++){var an=ar[ao].max_val;if(an>ad){ad=an}}for(ao=0;ao<ar.length;ao++){var au=ar[ao];if(au.max_val!==ad){au.html_elt.remove();al.draw_helper(true,am,au.index,au.resolution,au.html_elt.parent(),ah,{more_tile_data:{max:ad}})}}}if(al.filters_manager){var ai=al.filters_manager.filters;for(var aq=0;aq<ai.length;aq++){ai[aq].update_ui_elt()}var at=false,ac,aj;for(ao=0;ao<ar.length;ao++){if(ar[ao].data.length){ac=ar[ao].data[0];for(var aq=0;aq<ai.length;aq++){aj=ai[aq];if(aj.applies_to(ac)&&aj.min!==aj.max){at=true;break}}}}if(al.filters_available!==at){al.filters_available=at;if(!al.filters_available){al.filters_manager.hide()}al.update_icons()}}this.container_div.find(".yaxislabel").remove();var af=ar[0];if(af instanceof j){var ak=(this.prefs.histogram_max?this.prefs.histogram_max:af.max_val),ae=$("<div/>").text(ak).make_text_editable({num_cols:12,on_finish:function(av){$(".bs-tooltip").remove();var av=parseFloat(av);al.prefs.histogram_max=(!isNaN(av)?av:null);al.tile_cache.clear();al.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ae)}if(af instanceof O){var ap=true;for(ao=0;ao<ar.length;ao++){if(!ar[ao].all_slotted){ap=false;break}}if(!ap){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}else{if(ac==="summary_tree"){ac="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (u.FeatureSlotter)(ag,af,A,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ac.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(ac,ag,ah,ad){if(ag==="summary_tree"||ag==="Coverage"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(ao==="summary_tree"||ao==="Coverage"){var aA=new L.SummaryTreePainter(am,ay,ac,this.prefs);aA.draw(aq,ad.width,ad.height,aj);return new j(ap,af,ar,ad,am.data,am.max)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null);var az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null);var aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae);var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new O(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="summary_tree"}else{if(ac.extra_info==="no_detail"||ac.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="summary_tree"||ac.message||ac.extra_info==="no_detail"){return false}return true}});var R=function(ad,ac,ae){c.call(this,ad,ac,ae);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:l.get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter};q(R.prototype,r.prototype,M.prototype,c.prototype);var T=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=l.get_random_color(),ac=l.get_random_color([af,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter;this.update_icons()};q(T.prototype,r.prototype,M.prototype,c.prototype);var d={LineTrack:h,FeatureTrack:c,VcfTrack:R,ReadTrack:T,CompositeTrack:f,DrawableGroup:P};var p=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{View:Y,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:T,VcfTrack:R,CompositeTrack:f,object_from_template:p}}); \ No newline at end of file diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/templates/compiled/template-visualization-chartSettings.js --- a/static/scripts/templates/compiled/template-visualization-chartSettings.js +++ b/static/scripts/templates/compiled/template-visualization-chartSettings.js @@ -7,21 +7,17 @@ function program1(depth0,data) { - return "checked";} + return " checked=\"true\"";} - buffer += "<p class=\"help-text\">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the 'handle' is in focus, your keyboard's arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the 'Draw' button to render (or re-render) the chart with the current settings.\n </p>\n \n <div id=\"maxDataPoints\" class=\"form-input numeric-slider-input\">\n <label for=\"maxDataPoints\">Maximum data points allowed on graph: </label>\n <div class=\"slider-output\">"; - foundHelper = helpers.maxDataPoints; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.maxDataPoints; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "</div>\n <div style=\"clear: both;\"></div>\n <div class=\"slider\"></div>\n <p class=\"form-help help-text-small\">\n Change the maximum number of data points displayable on this graph (higher values will\n load significantly slower)\n </p>\n </div>\n\n <div id=\"datapointSize\" class=\"form-input numeric-slider-input\">\n <label for=\"datapointSize\">Size of data point: </label>\n <div class=\"slider-output\">"; + buffer += "<p class=\"help-text\">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the 'handle' is in focus, your keyboard's arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the 'Draw' button to render (or re-render) the chart with the current settings.\n </p>\n \n <div id=\"datapointSize\" class=\"form-input numeric-slider-input\">\n <label for=\"datapointSize\">Size of data point: </label>\n <div class=\"slider-output\">"; foundHelper = helpers.datapointSize; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } else { stack1 = depth0.datapointSize; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "</div>\n <div class=\"slider\"></div>\n <p class=\"form-help help-text-small\">\n Size of the graphic representation of each data point\n </p>\n </div>\n\n <div id=\"entryAnimDuration\" class=\"form-input checkbox-input\">\n <label for=\"animated\">Animate graph transitions?: </label>\n <input type=\"checkbox\" id=\"animated\" class=\"checkbox control\" value=\""; - stack1 = depth0.entryAnimDuration; + buffer += escapeExpression(stack1) + "</div>\n <div class=\"slider\"></div>\n <p class=\"form-help help-text-small\">\n Size of the graphic representation of each data point\n </p>\n </div>\n\n <div id=\"animDuration\" class=\"form-input checkbox-input\">\n <label for=\"animated\">Animate graph transitions?: </label>\n <input type=\"checkbox\" id=\"animated\"\n class=\"checkbox control\""; + stack1 = depth0.animDuration; stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(1, program1, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\" />\n <p class=\"form-help help-text-small\">\n Uncheck this to disable the animations used on the graph\n </p>\n </div>\n\n <div id=\"width\" class=\"form-input numeric-slider-input\">\n <label for=\"width\">Graph width: </label>\n <div class=\"slider-output\">"; + buffer += " />\n <p class=\"form-help help-text-small\">\n Uncheck this to disable the animations used on the graph\n </p>\n </div>\n\n <div id=\"width\" class=\"form-input numeric-slider-input\">\n <label for=\"width\">Graph width: </label>\n <div class=\"slider-output\">"; foundHelper = helpers.width; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } else { stack1 = depth0.width; stack1 = typeof stack1 === functionType ? stack1() : stack1; } diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/templates/visualization-templates.html --- a/static/scripts/templates/visualization-templates.html +++ b/static/scripts/templates/visualization-templates.html @@ -94,17 +94,6 @@ Use the 'Draw' button to render (or re-render) the chart with the current settings. </p> - <div id="maxDataPoints" class="form-input numeric-slider-input"> - <label for="maxDataPoints">Maximum data points allowed on graph: </label> - <div class="slider-output">{{maxDataPoints}}</div> - <div style="clear: both;"></div> - <div class="slider"></div> - <p class="form-help help-text-small"> - Change the maximum number of data points displayable on this graph (higher values will - load significantly slower) - </p> - </div> - <div id="datapointSize" class="form-input numeric-slider-input"><label for="datapointSize">Size of data point: </label><div class="slider-output">{{datapointSize}}</div> @@ -114,9 +103,10 @@ </p></div> - <div id="entryAnimDuration" class="form-input checkbox-input"> + <div id="animDuration" class="form-input checkbox-input"><label for="animated">Animate graph transitions?: </label> - <input type="checkbox" id="animated" class="checkbox control" value="{{#if entryAnimDuration}}checked{{/if}}" /> + <input type="checkbox" id="animated" + class="checkbox control"{{#if animDuration}} checked="true"{{/if}} /><p class="form-help help-text-small"> Uncheck this to disable the animations used on the graph </p> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/utils/LazyDataLoader.js --- a/static/scripts/utils/LazyDataLoader.js +++ b/static/scripts/utils/LazyDataLoader.js @@ -7,8 +7,10 @@ /** * Object to progressively load JSON data from a REST url, delaying some time between loading chunks * - * Data from ajax loading is aggregated in a list, with one element for each ajax response. - * It's up to the calling code to combine the results in a meaningful, correct way + * Will load size amount of data every delay ms, starting at start and ending at total. + * + * NOTE: Data from ajax loading is aggregated in a list, with one element for each ajax response. + * It's up to the calling code to combine the results in a meaningful, correct way. * * example: * var loader = new scatterplot.LazyDataLoader({ @@ -29,19 +31,23 @@ * max_vals: size * }); * }, - * - * loadedPartialEvent : 'loader.partial', - * loadedAllEvent : 'loader.all', * }); - * $( loader ).bind( 'loader.partial', function( event, data ){ - * console.info( 'partial load complete:', event, data ); + * + * // you can use events + * $( loader ).bind( 'error', function( event, xhr, status, error ){ + * alert( loader + ' ERROR:' + status + '\n' + error ); + * // bail out... + * }); + * $( loader ).bind( 'loaded.new', function( event, response ){ + * console.info( 'new data available:', event, response ); * // ... do stuff with new data * }); - * $( loader ).bind( 'loader.all', function( event, data ){ - * console.info( 'final load complete:', event, data ); + * $( loader ).bind( 'complete', function( event, allDataArray, total ){ + * console.info( 'final load complete:', event, allDataArray, total ); * // ... do stuff with all data * }); - * + * + * // ...or use a callback called when all data is loaded * loader.load( function( dataArray ){ console.debug( 'FINISHED!', x, y, z ); } ); */ function LazyDataLoader( config ){ @@ -49,7 +55,14 @@ // get, async, and params sent via url query string // we want json // we know the size of the data on the server beforehand - var loader = this; + var loader = this, + // events to trigger when new or all data has been loaded + // new batches of data (including last). Will be sent: the ajax response data, start value, and size + LOADED_NEW_EVENT = 'loaded.new', + // all data has been loaded: the final loader's data array and the total + LOADED_ALL_EVENT = 'complete'; + // error from ajax + ERROR_EVENT = 'error'; jQuery.extend( loader, LoggableMixin ); jQuery.extend( loader, { @@ -63,12 +76,6 @@ // holds the interval id for the current load delay currentIntervalId : undefined, - // optional events to trigger when partial, last data are loaded - // loadedPartialEvent will be sent: the ajax response data, start value, and size - loadedPartialEvent : undefined, - // loadedAllEvent will be sent: the final loader's data array and the total - loadedAllEvent : undefined, - // each load call will add an element to this array // it's the responsibility of the code using this to combine them properly data : [], @@ -90,10 +97,6 @@ config.initialize.call( loader, config ); } - // ensure necessary stuff - if( !loader.total ){ throw( loader + ' requires a total (total size of the data)' ); } - if( !loader.url ){ throw( loader + ' requires a url' ); } - this.log( this + ' initialized:', loader ); }, @@ -103,7 +106,7 @@ //@param {int} size : the number of lines/rows/data to get on the next load buildUrl : function( start, size ){ // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params - return loader.url + '&' + jQuery.param({ + return this.url + '&' + jQuery.param({ start_val: start, max_vals: size }); @@ -111,14 +114,33 @@ //OVERRIDE: to handle ajax errors differently ajaxErrorFn : function( xhr, status, error ){ - alert( loader + ' ERROR:' + status + '\n' + error ); }, // interface to begin load (and first recursive call) //@param {Function} callback : function to execute when all data is loaded. callback is passed loader.data load : function( callback ){ + this.log( this + '.load' ); + + // ensure necessary stuff + if( !loader.url ){ throw( loader + ' requires a url' ); } + + if( this.total === null ){ + this.log( '\t total is null (will load all)' ); + } else { + this.log( '\t total:', this.total ); + } + //if( !loader.total ){ throw( loader + ' requires a total (total size of the data)' ); } - // subsequent recursive calls + //FIRST RECURSION: start + var startingSize = loader.size; + if( ( loader.total !== null ) + && ( loader.total < loader.size ) ){ + startingSize = loader.total; + } + loader.log( loader + '\t beginning recursion' ); + loadHelper( loader.start, startingSize ); + + //FIRST, SUBSEQUENT RECURSION function function loadHelper( start, size ){ loader.log( loader + '.loadHelper, start:', start, 'size:', size ); var url = loader.buildUrl( start, size ); @@ -132,46 +154,57 @@ if( loader.currentIntervalId ){ clearInterval( loader.currentIntervalId ); } + $( loader ).trigger( ERROR_EVENT, [ status, error ] ); loader.ajaxErrorFn( xhr, status, error ); }, success : function( response ){ - var next = start + size, - remainder = Math.min( loader.total - next, loader.size ); - loader.log( '\t ajax success, next:', next, 'remainder:', remainder ); + loader.log( '\t ajax success, response:', response, 'next:', next, 'remainder:', remainder ); - // store the response as is in a new element - //TODO:?? store start, size as well? - loader.data.push( response ); + if( response !== null ){ + // store the response as is in a new element + //TODO:?? store start, size as well? + loader.data.push( response ); + + //TODO: these might not be the best way to split this up + // fire the first load event (if this is the first batch) AND partial + $( loader ).trigger( LOADED_NEW_EVENT, [ response, start, size ] ); + + //RECURSION: + var next = start + size, + remainder = loader.size; + + if( loader.total !== null ){ + remainder = Math.min( loader.total - next, loader.size ); + } + loader.log( '\t next recursion, start:', next, 'size:', remainder ); + + // if we haven't gotten everything yet, so set up for next recursive call and set the timer + if( loader.total === null || remainder > 0 ){ + loader.currentIntervalId = setTimeout( + function(){ loadHelper( next, remainder ); }, + loader.delay + ); + loader.log( '\t currentIntervalId:', loader.currentIntervalId ); + + // otherwise (base-case), don't do anything + } else { + loadFinished(); + } - // fire the partial load event - if( loader.loadedPartialEvent ){ - loader.log( '\t firing:', loader.loadedPartialEvent ); - $( loader ).trigger( loader.loadedPartialEvent, response, start, size ); - } - - // if we haven't gotten everything yet, - // set up for next recursive call and set the timer - if( remainder > 0 ){ - loader.currentIntervalId = setTimeout( - function(){ loadHelper( next, remainder ); }, - loader.delay - ); - loader.log( '\t currentIntervalId:', loader.currentIntervalId ); - - // otherwise (base-case), don't do anything - } else { - loader.log( loader + '.loadHelper, has finished:', loader.data ); - if( loader.loadedAllEvent ){ - loader.log( '\t firing:', loader.loadedAllEvent ); - $( loader ).trigger( loader.loadedAllEvent, loader.data, loader.total ); - } - if( callback ){ callback( loader.data ); } + } else { //response === null --> base-case, server sez nuthin left + loadFinished(); } } }); } - loadHelper( loader.start, Math.min( loader.total, loader.size ) ); + + //HANDLE BASE-CASE, LAST RECURSION + function loadFinished(){ + loader.log( loader + '.loadHelper, has finished:', loader.data ); + $( loader ).trigger( LOADED_ALL_EVENT, [ loader.data, loader.total ] ); + if( callback ){ callback( loader.data ); } + } }, toString : function(){ return 'LazyDataLoader'; } @@ -180,4 +213,3 @@ loader.initialize( config ); return loader; } - diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc static/scripts/viz/scatterplot.js --- a/static/scripts/viz/scatterplot.js +++ b/static/scripts/viz/scatterplot.js @@ -80,7 +80,8 @@ PADDING = 8, X_LABEL_TOO_LONG_AT = 5; - this.debugging = true; + // set up logging + //this.debugging = true; this.log = function(){ if( this.debugging && console && console.debug ){ var args = Array.prototype.slice.call( arguments ); @@ -96,9 +97,10 @@ this.defaults = { id : 'TwoVarScatterplot', containerSelector : 'body', - maxDataPoints : 10000, + //TODO??: needed? + maxDataPoints : 30000, datapointSize : 4, - entryAnimDuration : 500, + animDuration : 500, //TODO: variable effect (not always exactly # of ticks set to) xNumTicks : 10, yNumTicks : 10, @@ -123,6 +125,8 @@ this.config = _.extend( {}, this.defaults, config ); this.updateConfig = function( newConfig, rerender ){ + // setter for chart config + //TODO: validate here _.extend( this.config, newConfig ); }; @@ -130,6 +134,7 @@ this.toString = function(){ return this.config.id; }; + // conv. methods for svg transforms this.translateStr = function( x, y ){ return 'translate(' + x + ',' + y + ')'; }; @@ -346,7 +351,7 @@ // glyphs that need to be removed: transition to from normal state to 'exit' state, remove from DOM this.datapoints.exit() .each( function(){ count += 1; } ) - .transition().duration( this.config.entryAnimDuration ) + .transition().duration( this.config.animDuration ) .attr( "cy", this.config.height ) .attr( "r", 0 ) .remove(); @@ -394,7 +399,7 @@ count = 0; newDatapoints // ...animate to final position - .transition().duration( this.config.entryAnimDuration ) + .transition().duration( this.config.animDuration ) .each( function(){ count += 1; } ) .attr( "cx", xPosFn ) .attr( "cy", yPosFn ) @@ -480,38 +485,99 @@ * handles: * getting the desired data * configuring the plot display + * showing (general) statistics + * + * initialize attributes REQUIRES a dataset and an apiDatasetsURL */ var ScatterplotControlForm = BaseView.extend( LoggableMixin ).extend({ //logger : console, className : 'scatterplot-settings-form', + dataLoadDelay : 500, + dataLoadSize : 3001, + loadingIndicatorImage : 'loading_large_white_bg.gif', initialize : function( attributes ){ + if( this.logger ){ window.form = this; } + + this.dataset = null; + this.chartConfig = null; + this.plot = null; + this.loader = null; + this.$statsPanel = null; + this.$chartSettingsPanel = null; + this.$dataSettingsPanel = null; + this.dataFetch = null; + + this.initializeFromAttributes( attributes ); + this.initializeChart( attributes ); + this.initializeDataLoader( attributes ); + }, + + initializeFromAttributes : function( attributes ){ + // ensure certain vars we need are passed in attributes if( !attributes || !attributes.dataset ){ throw( "ScatterplotView requires a dataset" ); } else { this.dataset = attributes.dataset; } - + if( jQuery.type( this.dataset.metadata_column_types ) === 'string' ){ + this.dataset.metadata_column_types = this.dataset.metadata_column_types.split( ', ' ); + } + this.log( 'dataset:', this.dataset ); + // passed from mako helper //TODO: integrate to galaxyPaths - this.apiDatasetsURL = attributes.apiDatasetsURL; - - // set up the basic chart infrastructure with config (if any) + if( !attributes.apiDatasetsURL ){ + throw( "ScatterplotView requires a apiDatasetsURL" ); + } else { + this.dataURL = attributes.apiDatasetsURL + '/' + this.dataset.id + '?'; + } + this.log( 'this.dataURL:', this.dataURL ); + }, + + initializeChart : function( attributes ){ + // set up the basic chart infrastructure and config (if any) this.chartConfig = attributes.chartConfig || {}; + if( this.logger ){ this.chartConfig.debugging = true; } this.log( 'initial chartConfig:', this.chartConfig ); this.plot = new TwoVarScatterplot( this.chartConfig ); this.chartConfig = this.plot.config; - - this.$statsPanel = null; - this.$chartSettingsPanel = null; - this.$dataSettingsPanel = null; - this.dataFetch = null; + }, + + initializeDataLoader : function( attributes ){ + // set up data loader + var view = this; + this.loader = new LazyDataLoader({ + logger : ( this.logger )?( this.logger ):( null ), + // we'll generate this when columns are chosen + url : null, + start : attributes.start || 0, + //NOTE: metadata_data_lines can be null (so we won't know the total) + total : attributes.total || this.dataset.metadata_data_lines, + delay : this.dataLoadDelay, + size : this.dataLoadSize, + + buildUrl : function( start, size ){ + // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params + return this.url + '&' + jQuery.param({ + start_val: start, + max_vals: size + }); + } + }); + $( this.loader ).bind( 'error', function( event, status, error ){ + view.log( 'ERROR:', status, error ); + alert( 'ERROR fetching data:\n' + status + '\n' + error ); + view.hideLoadingIndicator(); + }); }, + // ------------------------------------------------------------------------- CONTROLS RENDERING render : function(){ + // render the data/chart control forms (but not the chart) var view = this, formData = { config : this.chartConfig, @@ -521,7 +587,7 @@ }; // gather column indeces (from metadata_column_types) and names (from metadata_columnnames) - _.each( this.dataset.metadata_column_types.split( ', ' ), function( type, index ){ + _.each( this.dataset.metadata_column_types, function( type, index ){ //TODO: using 0-based indeces // label with the name if available (fall back on 'column <index>') var name = 'column ' + ( index + 1 ); @@ -538,6 +604,7 @@ //TODO: other vals: max_vals, start_val, pagination (plot-settings) + // render template and set up panels, store refs this.$el.append( ScatterplotControlForm.templates.form( formData ) ); this.$dataSettingsPanel = this.$el.find( '.tab-pane#data-settings' ); this.$chartSettingsPanel = this._render_chartSettings(); @@ -548,12 +615,12 @@ }, _render_chartSettings : function(){ + // chart settings panel var chartControl = this, $chartSettingsPanel = this.$el.find( '.tab-pane#chart-settings' ), // limits for controls (by control/chartConfig id) //TODO: move into TwoVarScatterplot controlRanges = { - 'maxDataPoints' : { min: 1000, max: 30000, step: 100 }, 'datapointSize' : { min: 2, max: 10, step: 1 }, 'width' : { min: 200, max: 800, step: 20 }, 'height' : { min: 200, max: 800, step: 20 } @@ -562,14 +629,13 @@ // render the html $chartSettingsPanel.append( ScatterplotControlForm.templates.chartSettings( this.chartConfig ) ); - // set up js on controls - // sliders + // set up js on sliders $chartSettingsPanel.find( '.numeric-slider-input' ).each( function(){ var $this = $( this ), $output = $this.find( '.slider-output' ), $slider = $this.find( '.slider' ), id = $this.attr( 'id' ); - chartControl.log( 'slider set up', 'this:', $this, 'slider:', $slider, 'id', id ); + //chartControl.log( 'slider set up', 'this:', $this, 'slider:', $slider, 'id', id ); // what to do when the slider changes: update display and update chartConfig function onSliderChange(){ @@ -577,7 +643,7 @@ newValue = $this.slider( 'value' ); //chartControl.log( 'slider change', 'this:', $this, 'output:', $output, 'value', newValue ); $output.text( newValue ); - chartControl.chartConfig[ id ] = newValue; + //chartControl.chartConfig[ id ] = newValue; } $slider.slider( _.extend( controlRanges[ id ], { @@ -587,21 +653,23 @@ })); }); - //TODO: anim checkbox - return $chartSettingsPanel; }, + // ------------------------------------------------------------------------- EVENTS events : { - 'click #render-button' : 'renderPlot', - 'click #include-id-checkbox' : 'toggleThirdColumnSelector' + 'click #include-id-checkbox' : 'toggleThirdColumnSelector', + 'click #data-settings #render-button' : 'renderPlot', + 'click #chart-settings #render-button' : 'changeChartSettings' }, toggleThirdColumnSelector : function(){ + // show/hide the id selector on the data settings panel this.$el.find( 'select[name="ID"]' ).parent().toggle(); }, showLoadingIndicator : function( message, callback ){ + // display the loading indicator over the tab panels if hidden, update message (if passed) message = message || ''; var indicator = this.$el.find( 'div#loading-indicator' ); messageBox = indicator.find( '.loading-message' ); @@ -626,11 +694,217 @@ this.$el.find( 'div#loading-indicator' ).fadeOut( 'fast', callback ); }, - getColumnVals : function(){ + // ------------------------------------------------------------------------- GRAPH/STATS RENDERING + renderPlot : function(){ + // fetch the data, (re-)render the chart + //TODO: separate data fetch + var view = this; + + // this is a complete re-render, so clear the prev. data + view.data = null; + view.meta = null; + + // update the chartConfig (here and plot) using graph settings + //TODO: separate and improve (used in changeChartSettings too) + _.extend( this.chartConfig, this.getGraphSettings() ); + this.log( 'this.chartConfig:', this.chartConfig ); + this.plot.updateConfig( this.chartConfig, false ); + + // build the url with the current data settings + this.loader.url = this.dataURL + '&' + jQuery.param( this.getDataSettings() ); + this.log( 'this.loader, url:', this.loader.url, 'total:', this.loader.total ); + + // bind the new data event to: aggregate data, update the chart and stats with new data + $( this.loader ).bind( 'loaded.new', function( event, response ){ + view.log( view + ' loaded.new', response ); + + // aggregate data and meta + view.postProcessDataFetchResponse( response ); + view.log( 'postprocessed data:', view.data, 'meta:', view.meta ); + + // update the graph and stats + view.showLoadingIndicator( 'Rendering...', function(){ + view.$el.find( 'ul.nav' ).find( 'a[href="#chart-stats"]' ).tab( 'show' ); + + view.plot.render( view.data, view.meta ); + view.renderStats( view.data, view.meta ); + view.hideLoadingIndicator(); + }); + }); + // when all data loaded - unbind (or we'll start doubling event handlers) + $( this.loader ).bind( 'complete', function( event, data ){ + view.log( 'complete', data ); + $( view.loader ).unbind(); + }); + + // begin loading the data + view.showLoadingIndicator( 'Fetching data...', function(){ view.loader.load(); }); + }, + + renderStats : function(){ + // render the stats table in the stats panel + //TODO: there's a better way + this.$statsPanel.html( ScatterplotControlForm.templates.statsTable({ + stats: [ + { name: 'Count', xval: this.meta[0].count, yval: this.meta[1].count }, + { name: 'Min', xval: this.meta[0].min, yval: this.meta[1].min }, + { name: 'Max', xval: this.meta[0].max, yval: this.meta[1].max }, + { name: 'Sum', xval: this.meta[0].sum, yval: this.meta[1].sum }, + { name: 'Mean', xval: this.meta[0].mean, yval: this.meta[1].mean }, + { name: 'Median', xval: this.meta[0].median, yval: this.meta[1].median } + ] + })); + }, + + changeChartSettings : function(){ + // re-render the chart with new chart settings and OLD data + var view = this; + newGraphSettings = this.getGraphSettings(); + + // update the chart config from the chartSettings panel controls + this.log( 'newGraphSettings:', newGraphSettings ); + _.extend( this.chartConfig, newGraphSettings ); + this.log( 'this.chartConfig:', this.chartConfig ); + this.plot.updateConfig( this.chartConfig, false ); + + // if there's current data, call plot.render with it (no data fetch) + if( view.data && view.meta ){ + view.showLoadingIndicator( 'Rendering...', function(){ + view.plot.render( view.data, view.meta ); + view.hideLoadingIndicator(); + }); + + // no current data, call renderPlot instead (which will fetch data) + } else { + this.renderPlot(); + } + }, + + // ------------------------------------------------------------------------- DATA AGGREGATION + postProcessDataFetchResponse : function( response ){ + // the loader only returns new data - it's up to this to munge the fetches together properly + //TODO: we're now storing data in two places: loader and here + // can't we reduce incoming data into loader.data[0]? are there concurrency problems? + this.postProcessData( response.data ); + this.postProcessMeta( response.meta ); + }, + + postProcessData : function( newData ){ + // stack the column data on top of each other into this.data + var view = this; + + // if we already have data: aggregate + if( view.data ){ + _.each( newData, function( newColData, colIndex ){ + //view.log( colIndex + ' data:', newColData ); + //TODO??: time, space efficiency of this? + view.data[ colIndex ] = view.data[ colIndex ].concat( newColData ); + }); + + // otherwise: assign (first load) + } else { + view.data = newData; + } + }, + + postProcessMeta : function( newMeta ){ + // munge the meta data (stats) from the server fetches together + //pre: this.data must be preprocessed (needed for medians) + var view = this, + colTypes = this.dataset.metadata_column_types; + + // if we already have meta: aggregate + if( view.meta ){ + _.each( newMeta, function( newColMeta, colIndex ){ + var colMeta = view.meta[ colIndex ], + colType = colTypes[ colIndex ]; + view.log( colIndex + ' postprocessing meta:', newColMeta ); + //view.log( colIndex + ' old meta:', + // 'min:', colMeta.min, + // 'max:', colMeta.max, + // 'sum:', colMeta.sum, + // 'mean:', colMeta.mean, + // 'median:', colMeta.median + //); + + //!TODO: at what point are we getting int/float overflow on these?! + //??: need to be null safe? + colMeta.count += ( newColMeta.count )?( newColMeta.count ):( 0 ); + view.log( colIndex, 'count:', colMeta.count ); + + if( ( colType === 'int' ) || ( colType === 'float' ) ){ + //view.log( colIndex + ' incoming meta:', + // 'min:', newColMeta.min, + // 'max:', newColMeta.max, + // 'sum:', newColMeta.sum, + // 'mean:', newColMeta.mean, + // 'median:', newColMeta.median + //); + + colMeta.min = Math.min( newColMeta.min, colMeta.min ); + colMeta.max = Math.max( newColMeta.max, colMeta.max ); + colMeta.sum = newColMeta.sum + colMeta.sum; + colMeta.mean = ( colMeta.count )?( colMeta.sum / colMeta.count ):( null ); + + // median's a pain bc of sorting (requires the data as well) + var sortedCol = view.data[ colIndex ].slice().sort(), + middleIndex = Math.floor( sortedCol.length / 2 ); + + if( sortedCol.length % 2 === 0 ){ + colMeta.median = ( ( sortedCol[ middleIndex ] + sortedCol[( middleIndex + 1 )] ) / 2 ); + + } else { + colMeta.median = sortedCol[ middleIndex ]; + } + + //view.log( colIndex + ' new meta:', + // 'min:', colMeta.min, + // 'max:', colMeta.max, + // 'sum:', colMeta.sum, + // 'mean:', colMeta.mean, + // 'median:', colMeta.median + //); + } + }); + + // otherwise: assign (first load) + } else { + view.meta = newMeta; + view.log( 'initial meta:', view.meta ); + } + }, + + // ------------------------------------------------------------------------- GET DATA/GRAPH SETTINGS + getDataSettings : function(){ + // parse the column values for both indeces (for the data fetch) and names (for the graph) + var columnSelections = this.getColumnSelections(), + columns = []; + this.log( 'columnSelections:', columnSelections ); + + //TODO: validate columns - minimally: we can assume either set by selectors or via a good query string + + // get column indices for params, include the desired ID column (if any) + columns = [ columnSelections.X.colIndex, columnSelections.Y.colIndex ]; + if( this.$dataSettingsPanel.find( '#include-id-checkbox' ).attr( 'checked' ) ){ + columns.push( columnSelections.ID.colIndex ); + } + + //TODO: other vals: max, start, page + + var params = { + data_type : 'raw_data', + columns : '[' + columns + ']' + }; + this.log( 'params:', params ); + return params; + }, + + getColumnSelections : function(){ + // gets the current user-selected values for which columns to fetch from the data settings panel // returns a map: { column-select name (eg. X) : { colIndex : column-selector val, // colName : selected option text }, ... } var selections = {}; - this.$el.find( 'div.column-select select' ).each( function(){ + this.$dataSettingsPanel.find( 'div.column-select select' ).each( function(){ var $this = $( this ), val = $this.val(); selections[ $this.attr( 'name' ) ] = { @@ -640,94 +914,44 @@ }); return selections; }, - - fetchData : function( params, callbackFn ){ - var view = this, - url = this.apiDatasetsURL + '/' + this.dataset.id + '?data_type=raw_data&' + jQuery.param( params ); - this.log( 'url:', url ); - this.showLoadingIndicator( 'Fetching data...', function(){ - jQuery.ajax({ - url : url, - dataType : 'json', - success : callbackFn, - error : function( xhr, status, error ){ - view.hideLoadingIndicator(); - alert( 'ERROR:' + status + '\n' + error ); - } - }); - }); - }, - - renderPlot : function(){ - // parse the column values for both - // indeces (for the data fetch) and names (for the graph) - var view = this, - columnSelections = this.getColumnVals(), - columns = []; - this.log( 'columnSelections:', columnSelections ); - - //TODO: move this data/chart settings form crap out - this.log( columnSelections.X.val, columnSelections.Y.val ); - this.xColIndex = columnSelections.X.colIndex; - this.yColIndex = columnSelections.Y.colIndex; - columns = [ this.xColIndex, this.yColIndex ]; - - // include the desired ID column - if( $( '#include-id-checkbox' ).attr( 'checked' ) ){ - columns.push( columnSelections.ID.colIndex ); - } - - // update labels using chartSettings inputs (if not at defaults), otherwise the selects' colName + getGraphSettings : function(){ + // gets the user-selected chartConfig from the chart settings panel + var settings = {}, + colSelections = this.getColumnSelections(); + //this.log( 'colSelections:', colSelections ); + + //TODO: simplify with keys and loop + settings.datapointSize = this.$chartSettingsPanel.find( '#datapointSize.numeric-slider-input' ) + .find( '.slider' ).slider( 'value' ); + settings.width = this.$chartSettingsPanel.find( '#width.numeric-slider-input' ) + .find( '.slider' ).slider( 'value' ); + settings.height = this.$chartSettingsPanel.find( '#height.numeric-slider-input' ) + .find( '.slider' ).slider( 'value' ); + + // update axes labels using chartSettings inputs (if not at defaults), otherwise the selects' colName + //TODO: a little confusing var chartSettingsXLabel = this.$chartSettingsPanel.find( 'input#X-axis-label' ).val(), chartSettingsYLabel = this.$chartSettingsPanel.find( 'input#Y-axis-label' ).val(); - this.chartConfig.xLabel = ( chartSettingsXLabel === 'X' )? - ( columnSelections.X.colName ):( chartSettingsXLabel ); - this.chartConfig.yLabel = ( chartSettingsYLabel === 'Y' )? - ( columnSelections.Y.colName ):( chartSettingsYLabel ); - //this.log( 'this.chartConfig:', this.chartConfig ); - view.plot.updateConfig( this.chartConfig, false ); - - //TODO: validate columns - minimally: we can assume either set by selectors or via a good query string - //TODO: other vals: max, start, page - - // fetch the data, sending chosen columns to the server - var params = { - columns : '[' + columns + ']' - }; - - //TODO: prob. better to use events rather than callback chains like this - this.fetchData( params, function( response ){ - // save the endpoint (number of next line, fileptr) for this object - //TODO: server sends back an endpoint, cache for next pagination request - view.dataFetch = response; - view.showLoadingIndicator( 'Rendering...', function(){ - view.plot.render( response.data, response.meta ); - - view.renderStats( response.data, response.meta ); - view.$el.find( 'ul.nav' ).find( 'a[href="#chart-stats"]' ).tab( 'show' ); - - view.hideLoadingIndicator(); - }); - }); + settings.xLabel = ( chartSettingsXLabel === 'X' )? + ( colSelections.X.colName ):( chartSettingsXLabel ); + settings.yLabel = ( chartSettingsYLabel === 'Y' )? + ( colSelections.Y.colName ):( chartSettingsYLabel ); + + settings.animDuration = 10; + if( this.$chartSettingsPanel.find( '#animDuration.checkbox-input' ).is( ':checked' ) ){ + settings.animDuration = 500; + } + + this.log( 'graphSettings:', settings ); + return settings; }, - - renderStats : function(){ - this.$statsPanel.html( ScatterplotControlForm.templates.statsTable({ - stats: [ - { name: 'Count', xval: this.dataFetch.meta[0].count, yval: this.dataFetch.meta[1].count }, - { name: 'Min', xval: this.dataFetch.meta[0].min, yval: this.dataFetch.meta[1].min }, - { name: 'Max', xval: this.dataFetch.meta[0].max, yval: this.dataFetch.meta[1].max }, - { name: 'Mean', xval: this.dataFetch.meta[0].mean, yval: this.dataFetch.meta[1].mean }, - { name: 'Median', xval: this.dataFetch.meta[0].median, yval: this.dataFetch.meta[1].median } - ] - })); - }, - + toString : function(){ - return 'ScatterplotControlForm(' + attributes.dataset.id + ')'; + return 'ScatterplotControlForm(' + this.dataset.id + ')'; } }); + ScatterplotControlForm.templates = { form : Handlebars.templates[ 'template-visualization-scatterplotControlForm' ], statsTable : Handlebars.templates[ 'template-visualization-statsTable' ], diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/admin/external_service/common.mako --- a/templates/admin/external_service/common.mako +++ b/templates/admin/external_service/common.mako @@ -7,16 +7,16 @@ ##<a href="${h.url_for( controller='external_service', action='view_external_service', id=trans.security.encode_id( external_service.id ) )}">${external_service.name}</a><div style="clear: both"></div></div> - <div class="form-row"> - <label>Description:</label> - ${external_service.description} - <div style="clear: both"></div> - </div> - <div class="form-row"> - <label>Version:</label> - ${external_service.version} - <div style="clear: both"></div> - </div> + <div class="form-row"> + <label>Description:</label> + ${external_service.description} + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Version:</label> + ${external_service.version} + <div style="clear: both"></div> + </div><div class="form-row"><label>External service type:</label> %if trans.app.external_service_types.all_external_service_types.has_key( external_service.external_service_type_id ): diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/admin/external_service/create_external_service.mako --- a/templates/admin/external_service/create_external_service.mako +++ b/templates/admin/external_service/create_external_service.mako @@ -10,16 +10,16 @@ <div class="toolForm"><div class="toolFormTitle">New external service</div> %if widgets: - %for i, field in enumerate( widgets ): - <div class="form-row"> - <label>${field['label']}:</label> - ${field['widget'].get_html()} - <div class="toolParamHelp" style="clear: both;"> - ${field['helptext']} - </div> - <div style="clear: both"></div> - </div> - %endfor + %for i, field in enumerate( widgets ): + <div class="form-row"> + <label>${field['label']}:</label> + ${field['widget'].get_html()} + <div class="toolParamHelp" style="clear: both;"> + ${field['helptext']} + </div> + <div style="clear: both"></div> + </div> + %endfor %endif </div><div class="form-row"> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/admin/external_service/reload_external_service_types.mako --- a/templates/admin/external_service/reload_external_service_types.mako +++ b/templates/admin/external_service/reload_external_service_types.mako @@ -8,15 +8,15 @@ ${render_msg( message, status )} %endif <form name="reload_external_service_types" action="${h.url_for( controller='external_service', action='reload_external_service_types' )}" method="post"> - <div class="toolForm"> - <div class="toolFormTitle">Reload external service types</div> - <div class="form-row"> - <label>Select external service type to reload:</label> - ${external_service_type_select_field.get_html()} - <div style="clear: both"></div> - </div> - <div class="form-row"> - <input type="submit" name="reload_external_service_type_button" value="Reload"/> - </div> - </div> + <div class="toolForm"> + <div class="toolFormTitle">Reload external service types</div> + <div class="form-row"> + <label>Select external service type to reload:</label> + ${external_service_type_select_field.get_html()} + <div style="clear: both"></div> + </div> + <div class="form-row"> + <input type="submit" name="reload_external_service_type_button" value="Reload"/> + </div> + </div></form> \ No newline at end of file diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/admin/forms/edit_form_definition.mako --- a/templates/admin/forms/edit_form_definition.mako +++ b/templates/admin/forms/edit_form_definition.mako @@ -55,23 +55,23 @@ </h4><div class="msg_body2"> %endif - <div class="repeat-group-item"> - %for field_attr in field: - <div class="form-row"> - <label>${field_attr[0]}</label> - ${field_attr[1].get_html()} - ${render_selectbox_options( index, field_attr )} + <div class="repeat-group-item"> + %for field_attr in field: + <div class="form-row"> + <label>${field_attr[0]}</label> + ${field_attr[1].get_html()} + ${render_selectbox_options( index, field_attr )} %if len(field_attr) == 3: - <div class="toolParamHelp" style="clear: both;"> - ${field_attr[2]} - </div> + <div class="toolParamHelp" style="clear: both;"> + ${field_attr[2]} + </div> %endif - </div> - %endfor - <div class="form-row"> - <input type="submit" name="remove_button" value="Remove field ${index+1}"/> - </div> - </div> + </div> + %endfor + <div class="form-row"> + <input type="submit" name="remove_button" value="Remove field ${index+1}"/> + </div> + </div></div></%def> @@ -96,7 +96,7 @@ <form id="edit_form_definition" name="edit_form_definition" action="${h.url_for( controller='forms', action='edit_form_definition', id=trans.security.encode_id( form_definition.current.id ) )}" method="post" ><div class="toolForm"> - <div class="toolFormTitle">Edit form definition "${form_definition.name}" (${form_definition.type})</div> + <div class="toolFormTitle">Edit form definition "${form_definition.name}" (${form_definition.type})</div> %if response_redirect: <input type="hidden" name="response_redirect" value="${response_redirect}" size="40" /> %endif @@ -112,20 +112,20 @@ </div> %endfor </div> - %if current_form_type == trans.app.model.FormDefinition.types.SAMPLE: - <p/> - <div class="toolForm"> - <div class="toolFormTitle">Form Layout</div> - <div class="form-row"> - <label>Layout grid names</label> - </div> - %for index, lg in enumerate( layout_grids ): - ${render_layout( index, lg )} - %endfor - <div class="form-row"> - <input type="submit" name="add_layout_grid_button" value="Add layout grid"/> - </div> - </div> + %if current_form_type == trans.app.model.FormDefinition.types.SAMPLE: + <p/> + <div class="toolForm"> + <div class="toolFormTitle">Form Layout</div> + <div class="form-row"> + <label>Layout grid names</label> + </div> + %for index, lg in enumerate( layout_grids ): + ${render_layout( index, lg )} + %endfor + <div class="form-row"> + <input type="submit" name="add_layout_grid_button" value="Add layout grid"/> + </div> + </div> %endif <p/><div class="toolForm"> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/admin/request_type/edit_request_type.mako --- a/templates/admin/request_type/edit_request_type.mako +++ b/templates/admin/request_type/edit_request_type.mako @@ -60,20 +60,20 @@ <div class="toolForm"><div class="toolFormTitle">Sample states defined for this request type</div> %for element_count, state in enumerate( request_type.states ): - <div class="repeat-group-item"> - <div class="form-row"> - <label>${1+element_count}. State name:</label> - <input type="text" name="state_name_${trans.security.encode_id( state.id )}" value="${state.name}" size="40"/> - </div> - <div class="form-row"> - <label>Description:</label> - <input type="text" name="state_desc_${trans.security.encode_id( state.id )}" value="${state.desc}" size="40"/> - <div class="toolParamHelp" style="clear: both;"> - optional - </div> - </div> - <div style="clear: both"></div> - </div> + <div class="repeat-group-item"> + <div class="form-row"> + <label>${1+element_count}. State name:</label> + <input type="text" name="state_name_${trans.security.encode_id( state.id )}" value="${state.name}" size="40"/> + </div> + <div class="form-row"> + <label>Description:</label> + <input type="text" name="state_desc_${trans.security.encode_id( state.id )}" value="${state.desc}" size="40"/> + <div class="toolParamHelp" style="clear: both;"> + optional + </div> + </div> + <div style="clear: both"></div> + </div> %endfor </div><p/> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/admin/requests/rename_datasets.mako --- a/templates/admin/requests/rename_datasets.mako +++ b/templates/admin/requests/rename_datasets.mako @@ -15,45 +15,45 @@ %endif <div class="toolForm"> - <form name="rename_datasets" id="rename_datasets" action="${h.url_for( controller='requests_admin', action='rename_datasets', id_list=id_list, sample_id=trans.security.encode_id( sample.id ) )}" method="post" > + <form name="rename_datasets" id="rename_datasets" action="${h.url_for( controller='requests_admin', action='rename_datasets', id_list=id_list, sample_id=trans.security.encode_id( sample.id ) )}" method="post" > - <table class="grid"> - <thead> - <tr> - <th>Prepend directory name</th> - <th>Name</th> - <th>Path on external service</th> - </tr> - <thead> - <tbody> - %for id in id_list: - <% sample_dataset = trans.sa_session.query( trans.model.SampleDataset ).get( trans.security.decode_id( id ) ) %> - %if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.NOT_STARTED: - <tr> - <td> - <% rename_datasets_for_sample_select_field = build_rename_datasets_for_sample_select_field( trans, sample_dataset ) %> - ${rename_datasets_for_sample_select_field.get_html()} - </td> - <td> - <input type="text" name="new_name_${trans.security.encode_id( sample_dataset.id ) }" value="${sample_dataset.name}" size="100"/> - </td> - <td>${sample_dataset.file_path}</td> - </tr> - %endif - %endfor - </tbody> - </table> - <br/> + <table class="grid"> + <thead> + <tr> + <th>Prepend directory name</th> + <th>Name</th> + <th>Path on external service</th> + </tr> + <thead> + <tbody> + %for id in id_list: + <% sample_dataset = trans.sa_session.query( trans.model.SampleDataset ).get( trans.security.decode_id( id ) ) %> + %if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.NOT_STARTED: + <tr> + <td> + <% rename_datasets_for_sample_select_field = build_rename_datasets_for_sample_select_field( trans, sample_dataset ) %> + ${rename_datasets_for_sample_select_field.get_html()} + </td> + <td> + <input type="text" name="new_name_${trans.security.encode_id( sample_dataset.id ) }" value="${sample_dataset.name}" size="100"/> + </td> + <td>${sample_dataset.file_path}</td> + </tr> + %endif + %endfor + </tbody> + </table> + <br/><div class="form-row"> - <div class="toolParamHelp" style="clear: both;"> - A dataset name should only contain the alphanumeric characters or underscore(_). - If a dataset name contains any other character, it would be replaced by an underscore(_). - </div> + <div class="toolParamHelp" style="clear: both;"> + A dataset name should only contain the alphanumeric characters or underscore(_). + If a dataset name contains any other character, it would be replaced by an underscore(_). + </div></div> - <div class="form-row"> - <input type="submit" name="rename_datasets_button" value="Save"/> - <input type="submit" name="cancel_rename_datasets_button" value="Close"/> - </div> - </form> + <div class="form-row"> + <input type="submit" name="rename_datasets_button" value="Save"/> + <input type="submit" name="cancel_rename_datasets_button" value="Close"/> + </div> + </form></div> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/admin/requests/select_datasets_to_transfer.mako --- a/templates/admin/requests/select_datasets_to_transfer.mako +++ b/templates/admin/requests/select_datasets_to_transfer.mako @@ -13,16 +13,16 @@ <script type="text/javascript"> $(function(){ - $("#tree").ajaxComplete(function(event, XMLHttpRequest, ajaxOptions) { - _log("debug", "ajaxComplete: %o", this); // dom element listening - }); + $("#tree").ajaxComplete(function(event, XMLHttpRequest, ajaxOptions) { + _log("debug", "ajaxComplete: %o", this); // dom element listening + }); // --- Initialize sample trees $("#tree").dynatree({ title: "${scp_configs['data_location']}", - rootVisible: true, - minExpandLevel: 0, // 1: root node is not collapsible - persist: false, - checkbox: true, + rootVisible: true, + minExpandLevel: 0, // 1: root node is not collapsible + persist: false, + checkbox: true, selectMode: 3, onPostInit: function(isReloading, isError) { //alert("reloading: "+isReloading+", error:"+isError); @@ -43,38 +43,38 @@ data: { request_id: "${trans.security.encode_id( request.id )}", external_service_id: "${trans.security.encode_id( external_service.id )}", key: dtnode.data.key }, }); }, - onSelect: function(select, dtnode) { + onSelect: function(select, dtnode) { // Display list of selected nodes - var selNodes = dtnode.tree.getSelectedNodes(); - // convert to title/key array - var selKeys = $.map(selNodes, function(node){ - return node.data.key; - }); - document.select_datasets_to_transfer.selected_datasets_to_transfer.value = selKeys.join(",") + var selNodes = dtnode.tree.getSelectedNodes(); + // convert to title/key array + var selKeys = $.map(selNodes, function(node){ + return node.data.key; + }); + document.select_datasets_to_transfer.selected_datasets_to_transfer.value = selKeys.join(",") }, - onActivate: function(dtnode) { - var cell = $("#file_details"); - var selected_value; - if (dtnode.data.key == 'root') { - selected_value = "${scp_configs['data_location']}/"; - } else { - selected_value = dtnode.data.key; - }; - if (selected_value.charAt(selected_value.length-1) != '/') { - // Make ajax call - $.ajax( { - type: "POST", - url: "${h.url_for( controller='requests_admin', action='get_file_details' )}", - dataType: "json", - data: { request_id: "${trans.security.encode_id(request.id)}", external_service_id: "${trans.security.encode_id(external_service.id)}", folder_path: selected_value }, - success : function ( data ) { - cell.html( '<label>'+data+'</label>' ) - } + onActivate: function(dtnode) { + var cell = $("#file_details"); + var selected_value; + if (dtnode.data.key == 'root') { + selected_value = "${scp_configs['data_location']}/"; + } else { + selected_value = dtnode.data.key; + }; + if (selected_value.charAt(selected_value.length-1) != '/') { + // Make ajax call + $.ajax( { + type: "POST", + url: "${h.url_for( controller='requests_admin', action='get_file_details' )}", + dataType: "json", + data: { request_id: "${trans.security.encode_id(request.id)}", external_service_id: "${trans.security.encode_id(external_service.id)}", folder_path: selected_value }, + success : function ( data ) { + cell.html( '<label>'+data+'</label>' ) + } }); } else { cell.html( '' ); }; - }, + }, }); }); </script> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/dataset/embed.mako --- a/templates/dataset/embed.mako +++ b/templates/dataset/embed.mako @@ -1,6 +1,6 @@ <%inherit file="/embed_base.mako"/><%! - from galaxy.web.framework.helpers import iff + from galaxy.web.framework.helpers import iff %><%def name="render_item_links( dataset )"> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/display_base.mako --- a/templates/display_base.mako +++ b/templates/display_base.mako @@ -1,12 +1,12 @@ <%! - def inherit( context ): - if context.get('no_panels'): - return '/base.mako' - else: - return '/webapps/galaxy/base_panels.mako' - - from galaxy.model import History, StoredWorkflow, Page - from galaxy.web.framework.helpers import iff + def inherit( context ): + if context.get('no_panels'): + return '/base.mako' + else: + return '/webapps/galaxy/base_panels.mako' + + from galaxy.model import History, StoredWorkflow, Page + from galaxy.web.framework.helpers import iff %><%inherit file="${inherit( context )}"/><%namespace file="/tagging_common.mako" import="render_individual_tagging_element, render_community_tagging_element" /> @@ -23,11 +23,11 @@ <%def name="init()"><% - self.has_left_panel=False - self.has_right_panel=True - self.message_box_visible=False - self.active_view="shared" - self.overlay_visible=False + self.has_left_panel=False + self.has_right_panel=True + self.message_box_visible=False + self.active_view="shared" + self.overlay_visible=False %></%def> @@ -171,12 +171,12 @@ ## For base.mako <%def name="body()"> - ${self.render_content()} + ${self.render_content()} </%def> ## For base_panels.mako <%def name="center_panel()"> - ${self.render_content()} + ${self.render_content()} </%def> @@ -196,23 +196,23 @@ %><div class="unified-panel-header" unselectable="on"> - <div class="unified-panel-header-inner"> - %if item.published: - <a href="${href_to_all_items}">Published ${item_plural}</a> | - <a href="${href_to_user_items}">${item.user.username}</a> - %elif item.importable: - Accessible ${get_class_display_name( item.__class__ )} - %elif item.users_shared_with: - Shared ${get_class_display_name( item.__class__ )} - %else: - Private ${get_class_display_name( item.__class__ )} - %endif - | ${get_item_name( item )} - + <div class="unified-panel-header-inner"> + %if item.published: + <a href="${href_to_all_items}">Published ${item_plural}</a> | + <a href="${href_to_user_items}">${item.user.username}</a> + %elif item.importable: + Accessible ${get_class_display_name( item.__class__ )} + %elif item.users_shared_with: + Shared ${get_class_display_name( item.__class__ )} + %else: + Private ${get_class_display_name( item.__class__ )} + %endif + | ${get_item_name( item )} + <div style="float: right"> ${self.render_item_links( item )} </div> - </div> + </div></div><div class="unified-panel-body"> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/display_common.mako --- a/templates/display_common.mako +++ b/templates/display_common.mako @@ -29,12 +29,12 @@ item_name = item.get_display_name() else: item_name = item.name - + # Encode in unicode. if type( item_name ) is str: item_name = unicode( item_name, 'utf-8' ) - return item_name - %> + return item_name + %></%def> ## Get plural display name for a class. @@ -65,7 +65,7 @@ ## Get plural term for item. <%def name="get_item_plural( item )"> - <% return get_class_plural( item.__class__ ) %> + <% return get_class_plural( item.__class__ ) %></%def> ## Get plural term for class. diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/history/display.mako --- a/templates/history/display.mako +++ b/templates/history/display.mako @@ -20,11 +20,11 @@ } .column { float: left; - padding: 10px; - margin: 20px; - background: #666; - border: 5px solid #ccc; - width: 300px; + padding: 10px; + margin: 20px; + background: #666; + border: 5px solid #ccc; + width: 300px; } </style> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/history/embed.mako --- a/templates/history/embed.mako +++ b/templates/history/embed.mako @@ -1,6 +1,6 @@ <%inherit file="/embed_base.mako"/><%! - from galaxy.web.framework.helpers import iff + from galaxy.web.framework.helpers import iff %><%def name="render_summary_content( history, datasets )"> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/mobile/dataset/detail.mako --- a/templates/mobile/dataset/detail.mako +++ b/templates/mobile/dataset/detail.mako @@ -5,25 +5,25 @@ </div><div class="pad"> - <fieldset> - <div class="row"> - <label>State</label><span>${dataset.state}</span> - </div> - <div class="row"> - <label>Content</label><span>${dataset.blurb}</span> - </div> - <div class="row"> - <label>Format</label><span>${dataset.ext}</span> - </div> - <div class="row"> - <label>Info</label><span>${dataset.display_info()}</span> - </div> - %if dataset.state == "ok": - <div class="row"> - <a href="${h.url_for( action='dataset_peek', id=dataset.id )}">Peek</a> - </div> - %endif - </fieldset> + <fieldset> + <div class="row"> + <label>State</label><span>${dataset.state}</span> + </div> + <div class="row"> + <label>Content</label><span>${dataset.blurb}</span> + </div> + <div class="row"> + <label>Format</label><span>${dataset.ext}</span> + </div> + <div class="row"> + <label>Info</label><span>${dataset.display_info()}</span> + </div> + %if dataset.state == "ok": + <div class="row"> + <a href="${h.url_for( action='dataset_peek', id=dataset.id )}">Peek</a> + </div> + %endif + </fieldset></div></body> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/mobile/history/detail.mako --- a/templates/mobile/history/detail.mako +++ b/templates/mobile/history/detail.mako @@ -6,73 +6,73 @@ <ul class="edgetoedge"> %for data in history.active_datasets: - %if data.visible: + %if data.visible: - <% - if data.state in ['no state','',None]: - data_state = "queued" - else: - data_state = data.state - %> + <% + if data.state in ['no state','',None]: + data_state = "queued" + else: + data_state = data.state + %> - <li id="historyItemContainer-${data.id}"> + <li id="historyItemContainer-${data.id}"> + + <div style="float: left; padding-right: 8px;"> + <div style='display: none;' id="progress-${data.id}"> + <img src="${h.url_for('/static/style/data_running.gif')}" border="0"> + </div> + %if data_state == 'running': + <div><img src="${h.url_for('/static/style/data_running.gif')}" border="0"></div> + %elif data_state == 'upload': + <div><img src="${h.url_for('/static/style/data_upload.gif')}" border="0"></div> + %else: + <div><img src="${h.url_for( "/static/style/data_%s.png" % data_state )}" border="0"></div> + %endif + </div> + + <a href="${h.url_for( action="dataset_detail", id=data.id )}"> + + <div>${data.hid}: ${data.display_name()}</div> + + <div class="secondary"> + ## Body for history items, extra info and actions, data "peek" + <% current_user_roles = trans.get_current_user_roles() %> + %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): + <div>You do not have permission to view this dataset.</div> + %elif data_state == "queued": + <div>Job is waiting to run</div> + %elif data_state == "running": + <div>Job is currently running</div> + %elif data_state == "error": + <div> + An error occurred running this job. + </div> + %elif data_state == "discarded": + <div> + The job creating this dataset was cancelled before completion. + </div> + %elif data_state == 'setting_metadata': + <div>Metadata is being Auto-Detected.</div> + %elif data_state == "empty": + <div>No data: <i>${data.display_info()}</i></div> + %elif data_state in [ "ok", "failed_metadata" ]: + <div> + %if data_state == "failed_metadata": + Warning: setting metadata failed, + %endif + ${data.blurb}, + format: <span class="${data.ext}">${data.ext}</span>, + database: <span class="${data.dbkey}">${data.dbkey}</span> + </div> + %else: + <div>Error: unknown dataset state "${data_state}".</div> + %endif + </div> + + </a> - <div style="float: left; padding-right: 8px;"> - <div style='display: none;' id="progress-${data.id}"> - <img src="${h.url_for('/static/style/data_running.gif')}" border="0"> - </div> - %if data_state == 'running': - <div><img src="${h.url_for('/static/style/data_running.gif')}" border="0"></div> - %elif data_state == 'upload': - <div><img src="${h.url_for('/static/style/data_upload.gif')}" border="0"></div> - %else: - <div><img src="${h.url_for( "/static/style/data_%s.png" % data_state )}" border="0"></div> - %endif - </div> - - <a href="${h.url_for( action="dataset_detail", id=data.id )}"> - - <div>${data.hid}: ${data.display_name()}</div> - - <div class="secondary"> - ## Body for history items, extra info and actions, data "peek" - <% current_user_roles = trans.get_current_user_roles() %> - %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): - <div>You do not have permission to view this dataset.</div> - %elif data_state == "queued": - <div>Job is waiting to run</div> - %elif data_state == "running": - <div>Job is currently running</div> - %elif data_state == "error": - <div> - An error occurred running this job. - </div> - %elif data_state == "discarded": - <div> - The job creating this dataset was cancelled before completion. - </div> - %elif data_state == 'setting_metadata': - <div>Metadata is being Auto-Detected.</div> - %elif data_state == "empty": - <div>No data: <i>${data.display_info()}</i></div> - %elif data_state in [ "ok", "failed_metadata" ]: - <div> - %if data_state == "failed_metadata": - Warning: setting metadata failed, - %endif - ${data.blurb}, - format: <span class="${data.ext}">${data.ext}</span>, - database: <span class="${data.dbkey}">${data.dbkey}</span> - </div> - %else: - <div>Error: unknown dataset state "${data_state}".</div> - %endif - </div> - - </a> - - </li> - %endif + </li> + %endif %endfor diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/page/history_annotation_table.mako --- a/templates/page/history_annotation_table.mako +++ b/templates/page/history_annotation_table.mako @@ -2,60 +2,60 @@ <%namespace file="../root/history_common.mako" import="render_dataset" /><div class="annotated_item"> - <table> - ## Table header. - <tr> - <th colspan='2'>History '${history.get_display_name()}'</th> - </tr> - <tr> - ## Status messages and tags. - <td colspan='2'> - %if history.deleted: - <div class="warningmessagesmall"> - ${_('This is a deleted history.')} - </div> - %endif - ## Tags come for free with community tagging, so not sure if this is necessary. - ##%if trans.get_user() is not None: - ## Tags: ${render_tagging_element_html( tags=history.tags, editable=False, use_toggle_link=False )} - ##%endif - </td> - </tr> - <tr> - <td colspan="2" class="annotation" item_class="History" item_id="${trans.security.encode_id( history.id )}">Description of History: - <ol> - <li>What was the motivation for this history? - <li>What is the outcome of this history? - <li>What are unresolved questions from this history? - <li>What new questions arise from this history? - </ol> - </td> - </tr> + <table> + ## Table header. + <tr> + <th colspan='2'>History '${history.get_display_name()}'</th> + </tr> + <tr> + ## Status messages and tags. + <td colspan='2'> + %if history.deleted: + <div class="warningmessagesmall"> + ${_('This is a deleted history.')} + </div> + %endif + ## Tags come for free with community tagging, so not sure if this is necessary. + ##%if trans.get_user() is not None: + ## Tags: ${render_tagging_element_html( tags=history.tags, editable=False, use_toggle_link=False )} + ##%endif + </td> + </tr> + <tr> + <td colspan="2" class="annotation" item_class="History" item_id="${trans.security.encode_id( history.id )}">Description of History: + <ol> + <li>What was the motivation for this history? + <li>What is the outcome of this history? + <li>What are unresolved questions from this history? + <li>What new questions arise from this history? + </ol> + </td> + </tr> - ## Table body. For each dataset, there is an area to annotate the dataset. - %if not datasets: - <tr> - <td> - <div class="infomessagesmall" id="emptyHistoryMessage"> - ${_("Your history is empty. Click 'Get Data' on the left pane to start")} - </div> - </td> - </tr> - %else: - ## Render requested datasets. - %for data in datasets: - %if data.visible: - <tr> - <td valign="top" class="annotation" item_class="HistoryDatasetAssociation" item_id="${trans.security.encode_id( data.id )}">Describe this step: why was it done? what data did it produce?</td> - ##<td valign="top" class="annotation">Describe this step: why was it done? what data does it produce?</td> - <td> - <div class="historyItemContainer" id="historyItemContainer-${data.id}"> - ${render_dataset( data, data.hid, show_deleted_on_refresh = show_deleted, for_editing = False )} - </div> - </td> - </tr> - %endif - %endfor - %endif - </table> + ## Table body. For each dataset, there is an area to annotate the dataset. + %if not datasets: + <tr> + <td> + <div class="infomessagesmall" id="emptyHistoryMessage"> + ${_("Your history is empty. Click 'Get Data' on the left pane to start")} + </div> + </td> + </tr> + %else: + ## Render requested datasets. + %for data in datasets: + %if data.visible: + <tr> + <td valign="top" class="annotation" item_class="HistoryDatasetAssociation" item_id="${trans.security.encode_id( data.id )}">Describe this step: why was it done? what data did it produce?</td> + ##<td valign="top" class="annotation">Describe this step: why was it done? what data does it produce?</td> + <td> + <div class="historyItemContainer" id="historyItemContainer-${data.id}"> + ${render_dataset( data, data.hid, show_deleted_on_refresh = show_deleted, for_editing = False )} + </div> + </td> + </tr> + %endif + %endfor + %endif + </table></div> \ No newline at end of file diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/page/index.mako --- a/templates/page/index.mako +++ b/templates/page/index.mako @@ -15,36 +15,36 @@ <div class="page-container" style="padding: 10px;"> ${h.to_unicode( grid )} - <br><br> - <h2>Pages shared with you by others</h2> + <br><br> + <h2>Pages shared with you by others</h2> - %if shared_by_others: - <table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%"> - <tr class="header"> - <th>Title</th> - <th>Owner</th> - <th></th> - </tr> - %for i, association in enumerate( shared_by_others ): - <% page = association.page %> - <tr> - <td> - <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='display_by_username_and_slug', username=page.user.username, slug=page.slug)}">${page.title}</a> - </td> - <td>${page.user.username}</td> - <td> - <div popupmenu="shared-${i}-popup"> - <a class="action-button" href="${h.url_for( action='display_by_username_and_slug', username=page.user.username, slug=page.slug)}" target="_top">View</a> - </div> - </td> - </tr> - %endfor - </table> - %else: + %if shared_by_others: + <table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%"> + <tr class="header"> + <th>Title</th> + <th>Owner</th> + <th></th> + </tr> + %for i, association in enumerate( shared_by_others ): + <% page = association.page %> + <tr> + <td> + <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='display_by_username_and_slug', username=page.user.username, slug=page.slug)}">${page.title}</a> + </td> + <td>${page.user.username}</td> + <td> + <div popupmenu="shared-${i}-popup"> + <a class="action-button" href="${h.url_for( action='display_by_username_and_slug', username=page.user.username, slug=page.slug)}" target="_top">View</a> + </div> + </td> + </tr> + %endfor + </table> + %else: - No pages have been shared with you. + No pages have been shared with you. - %endif + %endif </div></div> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/requests/common/create_request.mako --- a/templates/requests/common/create_request.mako +++ b/templates/requests/common/create_request.mako @@ -32,10 +32,10 @@ ## The request_type_select_field is a SelectField named request_type_id ${request_type_select_field.get_html()} %if cntrller != 'requests_admin': - <div class="toolParamHelp" style="clear: both;"> - Contact the lab manager if you are not sure about the request type configuration. - </div> - %endif + <div class="toolParamHelp" style="clear: both;"> + Contact the lab manager if you are not sure about the request type configuration. + </div> + %endif </div> %if request_type_select_field_selected != 'none': ## If a request_type has been selected, display the associated form using received widgets. @@ -54,7 +54,7 @@ <input type="submit" name="add_sample_button" value="Add samples"/></div> %endif - </form> - </div> + </form> + </div> %endif </div> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/requests/common/edit_samples.mako --- a/templates/requests/common/edit_samples.mako +++ b/templates/requests/common/edit_samples.mako @@ -18,15 +18,15 @@ <%def name="local_javascripts()"><script type="text/javascript"> - // This function stops the form from getting submitted when return key is pressed - // This is needed in this form as the barcode scanner (when in keyboard emulation mode) - // may send a return key appended to the scanned barcode string. - function stopRKey(evt) { - var evt = (evt) ? evt : ((event) ? event : null); - var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null); - if ((evt.keyCode == 13) && (node.type=="text")) {return false;} - } - document.onkeypress = stopRKey + // This function stops the form from getting submitted when return key is pressed + // This is needed in this form as the barcode scanner (when in keyboard emulation mode) + // may send a return key appended to the scanned barcode string. + function stopRKey(evt) { + var evt = (evt) ? evt : ((event) ? event : null); + var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null); + if ((evt.keyCode == 13) && (node.type=="text")) {return false;} + } + document.onkeypress = stopRKey </script></%def> @@ -100,14 +100,14 @@ %elif sample_operation_selected_value == trans.app.model.Sample.bulk_operations.SELECT_LIBRARY: <% libraries_selected_value = libraries_select_field.get_selected( return_value=True ) %><div class="form-row"> - <label>Select data library:</label> - ${libraries_select_field.get_html()} + <label>Select data library:</label> + ${libraries_select_field.get_html()} </div> %if libraries_selected_value != 'none': <div class="form-row"> - <label>Select folder:</label> - ${folders_select_field.get_html()} - </div> + <label>Select folder:</label> + ${folders_select_field.get_html()} + </div> %endif %endif </div> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/requests/common/find_samples.mako --- a/templates/requests/common/find_samples.mako +++ b/templates/requests/common/find_samples.mako @@ -59,19 +59,19 @@ </div></div> %if results: - <div class="form-row"> + <div class="form-row"><label><i>${results}</i></label> %if samples: - <div class="toolParamHelp" style="clear: both;"> - The search results are sorted by the date the samples where created. - </div> - %endif - </div> - %endif + <div class="toolParamHelp" style="clear: both;"> + The search results are sorted by the date the samples where created. + </div> + %endif + </div> + %endif <div class="form-row"> - %if samples: - %for sample in samples: - <div class="form-row"> + %if samples: + %for sample in samples: + <div class="form-row"> Sample: <b>${sample.name}</b> | Barcode: ${sample.bar_code}<br/> %if sample.request.is_new or not sample.state: State: Unsubmitted<br/> @@ -90,10 +90,10 @@ <div class="toolParamHelp" style="clear: both;"><a href="${h.url_for( controller='requests_common', action='view_request', cntrller=cntrller, id=trans.security.encode_id( sample.request.id ) )}">Sequencing request: ${sample.request.name} | Type: ${sample.request.type.name} | State: ${sample.request.state}</a></div> - </div> - <br/> - %endfor - %endif + </div> + <br/> + %endfor + %endif </div></form></div> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/root/alternate_history.mako --- a/templates/root/alternate_history.mako +++ b/templates/root/alternate_history.mako @@ -298,10 +298,10 @@ 'name' : history.name, 'status' : status, - 'showDeleted' : show_deleted, - 'showHidden' : show_hidden, - 'quotaMsg' : over_quota, - 'message' : message, ##'go outside' + 'showDeleted' : show_deleted, + 'showHidden' : show_hidden, + 'quotaMsg' : over_quota, + 'message' : message, ##'go outside' 'deleted' : history.deleted, 'diskSize' : history.get_disk_size( nice_size=True ), @@ -336,7 +336,7 @@ 'hdas' : [ prep_hda( hda, for_editing ) for hda in datasets ], # some of these may be unneeded when all is said and done... - 'hdaId' : hda_id, + 'hdaId' : hda_id, 'forEditing' : for_editing, } %> @@ -418,43 +418,43 @@ <%def name="stylesheets()"> ${parent.stylesheets()} ${h.css("base", "history", "autocomplete_tagging" )} - <style> + <style> ## TODO: move to base.less - .historyItemBody { - display: none; - } - div.form-row { - padding: 5px 5px 5px 0px; - } - #top-links { - margin-bottom: 15px; - } - #history-name-container { - color: gray; - font-weight: bold; - } - #history-name { - word-wrap: break-word; - } - .editable-text { - border: solid transparent 1px; - padding: 3px; - margin: -4px; - } - </style> - - <noscript> - ## js disabled: degrade gracefully - <style> - .historyItemBody { - display: block; - } - </style> - </noscript> + .historyItemBody { + display: none; + } + div.form-row { + padding: 5px 5px 5px 0px; + } + #top-links { + margin-bottom: 15px; + } + #history-name-container { + color: gray; + font-weight: bold; + } + #history-name { + word-wrap: break-word; + } + .editable-text { + border: solid transparent 1px; + padding: 3px; + margin: -4px; + } + </style> + + <noscript> + ## js disabled: degrade gracefully + <style> + .historyItemBody { + display: block; + } + </style> + </noscript></%def><%def name="title()"> - ${_('Galaxy History')} + ${_('Galaxy History')} </%def><body class="historyPage"></body> diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/root/tool_menu.mako --- a/templates/root/tool_menu.mako +++ b/templates/root/tool_menu.mako @@ -44,7 +44,7 @@ search_url: "${h.url_for( controller='root', action='tool_search' )}", hidden: false }); - + // Set up tool panel. tool_panel = new tools.ToolPanel( { tool_search: tool_search } ); tool_panel.reset( tool_panel.parse( ${h.to_json_string( dictified_panel )} ) ); @@ -73,8 +73,8 @@ JSON.stringify({"search_active" : search_active})); }); */ - - $( '.tooltip' ).tooltip(); + + $( '.tooltip' ).tooltip(); // TODO: is this necessary? $( "a[minsizehint]" ).click( function() { diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/visualization/scatterplot.mako --- a/templates/visualization/scatterplot.mako +++ b/templates/visualization/scatterplot.mako @@ -14,12 +14,12 @@ /* -------------------------------------------- layout */ .column { - position:relative; + position:relative; overflow: auto; } .left-column { - float: left; + float: left; width: 40%; } @@ -207,19 +207,19 @@ require([ "viz/scatterplot" ], function( scatterplot ){ var hda = ${h.to_json_string( hda )}, - historyID = '${historyID}' - apiDatasetsURL = "${h.url_for( controller='/api/datasets' )}"; + historyID = '${historyID}'; - var settingsForm = new scatterplot.ScatterplotControlForm({ + settingsForm = new scatterplot.ScatterplotControlForm({ dataset : hda, el : $( '#chart-settings-form' ), - apiDatasetsURL : apiDatasetsURL, - + apiDatasetsURL : "${h.url_for( controller='/api/datasets' )}", + chartConfig : { containerSelector : '#chart-holder', marginTop : 20, } }).render(); + }); </script> @@ -243,4 +243,3 @@ <div id="test"></div></%def> - diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/visualization/trackster_common.mako --- a/templates/visualization/trackster_common.mako +++ b/templates/visualization/trackster_common.mako @@ -4,14 +4,14 @@ ## Render needed CSS files. <%def name="render_trackster_css_files()"> - ${h.css( "history", "autocomplete_tagging", "trackster", "library", - "jquery-ui/smoothness/jquery-ui-1.8.23.custom" )} + ${h.css( "history", "autocomplete_tagging", "trackster", "library", + "jquery-ui/smoothness/jquery-ui-1.8.23.custom" )} </%def> ## Render needed JavaScript files. <%def name="render_trackster_js_files()"> - ${h.js( "galaxy.panels", "libs/jquery/jstorage", "libs/jquery/jquery.event.drag", "libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel", "libs/jquery/jquery-ui-1.8.23.custom.min", "libs/require", "libs/farbtastic" )} + ${h.js( "galaxy.panels", "libs/jquery/jstorage", "libs/jquery/jquery.event.drag", "libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel", "libs/jquery/jquery-ui-1.8.23.custom.min", "libs/require", "libs/farbtastic" )} </%def> ## Render a block of JavaScript that contains all necessary variables for Trackster. diff -r 09c5a80bac6f7d157ac371fc61d3f3ebd5b25c77 -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc templates/workflow/embed.mako --- a/templates/workflow/embed.mako +++ b/templates/workflow/embed.mako @@ -1,6 +1,6 @@ <%inherit file="/embed_base.mako"/><%! - from galaxy.web.framework.helpers import iff + from galaxy.web.framework.helpers import iff %><%def name="render_summary_content( workflow, steps )"> https://bitbucket.org/galaxy/galaxy-central/changeset/55fa61760848/ changeset: 55fa61760848 user: smcmanus date: 2012-10-15 23:43:22 summary: Merge affected #: 2 files diff -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc -r 55fa61760848ffd1026dc897260955a195a388c2 lib/galaxy/webapps/galaxy/controllers/dataset.py --- a/lib/galaxy/webapps/galaxy/controllers/dataset.py +++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py @@ -160,13 +160,16 @@ dataset is either nonexistent or inaccessible to the user. ''' hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) ) - assert hda and trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ) + assert hda and self._can_access_dataset( trans, hda ) return hda.creating_job - + + def _can_access_dataset( self, trans, dataset, allow_admin=True ): + return ( allow_admin and trans.user_is_admin() ) or trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), dataset ) + @web.expose def errors( self, trans, id ): hda = trans.sa_session.query( model.HistoryDatasetAssociation ).get( id ) - if not hda or not trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ): + if not hda or not self._can_access_dataset( trans, hda ): return trans.show_error_message( "Either this dataset does not exist or you do not have permission to access it." ) return trans.fill_template( "dataset/errors.mako", hda=hda ) @web.expose @@ -174,7 +177,7 @@ trans.response.set_content_type( 'text/plain' ) try: hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) ) - assert hda and trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ) + assert hda and self._can_access_dataset( trans, hda ) job = hda.creating_job_associations[0].job except: return "Invalid dataset ID or you are not allowed to access this dataset" @@ -248,7 +251,7 @@ # Check email a bit email = email.strip() parts = email.split() - if len( parts ) == 1 and len( email ) > 0 and trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ): + if len( parts ) == 1 and len( email ) > 0 and self._can_access_dataset( trans, hda ): to = to_address + ", " + email else: to = to_address @@ -268,7 +271,7 @@ def get_metadata_file(self, trans, hda_id, metadata_name): """ Allows the downloading of metadata files associated with datasets (eg. bai index for bam files) """ data = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( hda_id ) ) - if not data or not trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), data.dataset ): + if not data or not self._can_access_dataset( trans, data ): return trans.show_error_message( "You are not allowed to access this dataset" ) valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' @@ -292,7 +295,7 @@ data = None if not data: raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( hda_id ) ) - if not trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), data.dataset ): + if not self._can_access_dataset( trans, data ): return trans.show_error_message( "You are not allowed to access this dataset" ) if data.state == trans.model.Dataset.states.UPLOAD: return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." ) @@ -367,7 +370,7 @@ manage_permissions_action = trans.app.security_agent.get_action( trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) permissions = { manage_permissions_action : [ trans.app.security_agent.get_private_user_role( data.history.user ) ] } trans.app.security_agent.set_dataset_permission( data.dataset, permissions ) - if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): + if self._can_access_dataset( trans, data ): if data.state == trans.model.Dataset.states.UPLOAD: return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to edit its metadata." ) params = util.Params( kwd, sanitize=False ) @@ -700,7 +703,7 @@ current_user_roles = trans.get_current_user_roles() if trans.app.security_agent.dataset_is_public( data.dataset ): return trans.response.send_redirect( redirect_url ) # anon access already permitted by rbac - if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): + if self._can_access_dataset( trans, data ): trans.app.host_security_agent.set_dataset_permissions( data, trans.user, site ) return trans.response.send_redirect( redirect_url ) else: @@ -726,7 +729,7 @@ link_name = urllib.unquote_plus( link_name ) if None in [ app_name, link_name ]: return trans.show_error_message( "A display application name and link name must be provided." ) - if trans.app.security_agent.can_access_dataset( user_roles, data.dataset ): + if self._can_access_dataset( trans, data ): msg = [] refresh = False display_app = trans.app.datatypes_registry.display_applications.get( app_name ) @@ -979,7 +982,7 @@ hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( dataset_id ) ) if not hda: raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) ) - if not trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ): + if not self._can_access_dataset( trans, hda ): return trans.show_error_message( "You are not allowed to access this dataset" ) # Get the associated job, if any. If this hda was copied from another, diff -r 3c7ad9558428f99bec322c8a14cfc7a0aab8e7dc -r 55fa61760848ffd1026dc897260955a195a388c2 lib/galaxy/webapps/galaxy/controllers/tool_runner.py --- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py +++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py @@ -121,7 +121,7 @@ # Get the dataset object data = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id ) #only allow rerunning if user is allowed access to the dataset. - if not trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), data.dataset ): + if not ( trans.user_is_admin() or trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), data.dataset ) ): error( "You are not allowed to access this dataset" ) # Get the associated job, if any. job = data.creating_job 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.